Merge with changes from master

This commit is contained in:
Chris Bednarski 2015-06-09 12:12:47 -07:00
commit f01154366a
242 changed files with 8878 additions and 980 deletions

View File

@ -1,4 +1,43 @@
## 0.5.3 (Unreleased)
## 0.6.0 (Unreleased)
FEATURES:
* **New provider: `azure`** [GH-2053]
* **New resource: `aws_autoscaling_notification`** [GH-2197]
* **New resource: `aws_ecs_cluster`** [GH-1803]
* **New resource: `aws_ecs_service`** [GH-1803]
* **New resource: `aws_ecs_task_definition`** [GH-1803]
* **New resource: `aws_iam_group_association`** [GH-2273]
* **New resource: `aws_spot_instance_request`** [GH-2263]
* **New remote state backend: `swift`**: You can now store remote state in
a OpenStack Swift. [GH-2254]
* command/output: support display of module outputs [GH-2102]
* core: keys() and values() funcs for map variables [GH-2198]
IMPROVEMENTS:
* core: HTTP remote state now accepts `skip_cert_verification`
option to ignore TLS cert verification. [GH-2214]
* provider/aws: ElastiCache Subnet Groups can be updated
without destroying first [GH-2191]
* provider/docker: `docker_container` has the `privileged`
option. [GH-2227]
* provider/openstack: allow `OS_AUTH_TOKEN` environment variable
to set the openstack `api_key` field [GH-2234]
* provider/openstack: Can now configure endpoint type (public, admin,
internal) [GH-2262]
BUG FIXES:
* command/apply: prevent output duplication when reporting errors [GH-2267]
* provider/aws: fix panic when route has no cidr_block [GH-2215]
* provider/aws: fix issue preventing destruction of IAM Roles [GH-2177]
* provider/aws: fix issue causing perpetual diff on ELB listeners
when non-lowercase protocol strings were used [GH-2246]
* provider/aws: corrected frankfurt S3 website region [GH-2259]
* provider/aws: `aws_elasticache_cluster` port is required [GH-2160]
## 0.5.3 (June 1, 2015)
IMPROVEMENTS:
@ -7,11 +46,16 @@ IMPROVEMENTS:
* **New resource: `aws_sqs_queue`** [GH-1939]
* **New resource: `aws_sns_topic`** [GH-1974]
* **New resource: `aws_sns_topic_subscription`** [GH-1974]
* **New resource: `aws_volume_attachment`** [GH-2050]
* **New resource: `google_storage_bucket`** [GH-2060]
* provider/aws: support ec2 termination protection [GH-1988]
* provider/aws: support for RDS Read Replicas [GH-1946]
* provider/aws: `aws_s3_bucket` add support for `policy` [GH-1992]
* provider/aws: `aws_ebs_volume` add support for `tags` [GH-2135]
* provider/aws: New `force_destroy` parameter for S3 buckets, to destroy
* provider/aws: `aws_elasticache_cluster` Confirm node status before reporting
available
* provider/aws: `aws_network_acl` Add support for ICMP Protocol [GH-2148]
* provider/aws: New `force_destroy` parameter for S3 buckets, to destroy
Buckets that contain objects [GH-2007]
* provider/aws: switching `health_check_type` on ASGs no longer requires
resource refresh [GH-2147]
@ -19,6 +63,9 @@ IMPROVEMENTS:
BUG FIXES:
* provider/aws: Correctly handle AWS keypairs which no longer exist [GH-2032]
* provider/aws: Fix issue with restoring an Instance from snapshot ID
[GH-2120]
* provider/template: store relative path in the state [GH-2038]
* provisioner/chef: fix interpolation in the Chef provisioner [GH-2168]
* provisioner/remote-exec: Don't prepend shebang on scripts that already
have one [GH-2041]
@ -130,7 +177,7 @@ IMPROVEMENTS:
* **New resource: `google_dns_record_set`**
* **Migrate to upstream AWS SDK:** Migrate the AWS provider to
[awslabs/aws-sdk-go](https://github.com/awslabs/aws-sdk-go),
the offical `awslabs` library. Previously we had forked the library for
the official `awslabs` library. Previously we had forked the library for
stability while `awslabs` refactored. Now that work has completed, and we've
migrated back to the upstream version.
* core: Improve error message on diff mismatch [GH-1501]
@ -158,7 +205,7 @@ IMPROVEMENTS:
* provider/aws: `aws_network_acl` improved validation for network ACL ports
and protocols [GH-1798] [GH-1808]
* provider/aws: `aws_route_table` can target network interfaces [GH-968]
* provider/aws: `aws_route_table` can specify propogating VGWs [GH-1516]
* provider/aws: `aws_route_table` can specify propagating VGWs [GH-1516]
* provider/aws: `aws_route53_record` supports weighted sets [GH-1578]
* provider/aws: `aws_route53_zone` exports nameservers [GH-1525]
* provider/aws: `aws_s3_bucket` website support [GH-1738]
@ -315,7 +362,7 @@ FEATURES:
* **Math operations** in interpolations. You can now do things like
`${count.index+1}`. [GH-1068]
* **New AWS SDK:** Move to `aws-sdk-go` (hashicorp/aws-sdk-go),
a fork of the offical `awslabs` repo. We forked for stability while
a fork of the official `awslabs` repo. We forked for stability while
`awslabs` refactored the library, and will move back to the officially
supported version in the next release.
@ -344,7 +391,7 @@ IMPROVEMENTS:
* providers/aws: Improve dependency violation error handling, when deleting
Internet Gateways or Auto Scaling groups [GH-1325].
* provider/aws: Add non-destructive updates to AWS RDS. You can now upgrade
`egine_version`, `parameter_group_name`, and `multi_az` without forcing
`engine_version`, `parameter_group_name`, and `multi_az` without forcing
a new database to be created.[GH-1341]
* providers/aws: Full support for block device mappings on instances and
launch configurations [GH-1045, GH-1364]

View File

@ -0,0 +1,12 @@
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

@ -0,0 +1 @@
package main

View File

@ -5,8 +5,8 @@ import (
"fmt"
"log"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -5,7 +5,7 @@ import (
"reflect"
"testing"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -7,20 +7,21 @@ import (
"github.com/hashicorp/terraform/helper/multierror"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/credentials"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/awslabs/aws-sdk-go/service/kinesis"
"github.com/awslabs/aws-sdk-go/service/lambda"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/awslabs/aws-sdk-go/service/s3"
"github.com/awslabs/aws-sdk-go/service/sns"
"github.com/awslabs/aws-sdk-go/service/sqs"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/kinesis"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/sns"
"github.com/aws/aws-sdk-go/service/sqs"
)
type Config struct {
@ -36,6 +37,7 @@ type Config struct {
type AWSClient struct {
ec2conn *ec2.EC2
ecsconn *ecs.ECS
elbconn *elb.ELB
autoscalingconn *autoscaling.AutoScaling
s3conn *s3.S3
@ -118,6 +120,9 @@ func (c *Config) Client() (interface{}, error) {
log.Println("[INFO] Initializing EC2 Connection")
client.ec2conn = ec2.New(awsConfig)
log.Println("[INFO] Initializing ECS Connection")
client.ecsconn = ecs.New(awsConfig)
// aws-sdk-go uses v4 for signing requests, which requires all global
// endpoints to use 'us-east-1'.
// See http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html

View File

@ -5,8 +5,8 @@ import (
"net"
"strconv"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
)
func expandNetworkAclEntries(configured []interface{}, entryType string) ([]*ec2.NetworkACLEntry, error) {

View File

@ -4,8 +4,8 @@ import (
"reflect"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
)
func Test_expandNetworkACLEntry(t *testing.T) {

View File

@ -85,12 +85,16 @@ func Provider() terraform.ResourceProvider {
ResourcesMap: map[string]*schema.Resource{
"aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(),
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
"aws_autoscaling_notification": resourceAwsAutoscalingNotification(),
"aws_customer_gateway": resourceAwsCustomerGateway(),
"aws_db_instance": resourceAwsDbInstance(),
"aws_db_parameter_group": resourceAwsDbParameterGroup(),
"aws_db_security_group": resourceAwsDbSecurityGroup(),
"aws_db_subnet_group": resourceAwsDbSubnetGroup(),
"aws_ebs_volume": resourceAwsEbsVolume(),
"aws_ecs_cluster": resourceAwsEcsCluster(),
"aws_ecs_service": resourceAwsEcsService(),
"aws_ecs_task_definition": resourceAwsEcsTaskDefinition(),
"aws_eip": resourceAwsEip(),
"aws_elasticache_cluster": resourceAwsElasticacheCluster(),
"aws_elasticache_security_group": resourceAwsElasticacheSecurityGroup(),
@ -99,6 +103,7 @@ func Provider() terraform.ResourceProvider {
"aws_iam_access_key": resourceAwsIamAccessKey(),
"aws_iam_group_policy": resourceAwsIamGroupPolicy(),
"aws_iam_group": resourceAwsIamGroup(),
"aws_iam_group_membership": resourceAwsIamGroupMembership(),
"aws_iam_instance_profile": resourceAwsIamInstanceProfile(),
"aws_iam_policy": resourceAwsIamPolicy(),
"aws_iam_role_policy": resourceAwsIamRolePolicy(),
@ -125,6 +130,7 @@ func Provider() terraform.ResourceProvider {
"aws_s3_bucket": resourceAwsS3Bucket(),
"aws_security_group": resourceAwsSecurityGroup(),
"aws_security_group_rule": resourceAwsSecurityGroupRule(),
"aws_spot_instance_request": resourceAwsSpotInstanceRequest(),
"aws_sqs_queue": resourceAwsSqsQueue(),
"aws_sns_topic": resourceAwsSnsTopic(),
"aws_sns_topic_subscription": resourceAwsSnsTopicSubscription(),

View File

@ -4,9 +4,9 @@ import (
"fmt"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSAppCookieStickinessPolicy(t *testing.T) {
func TestAccAWSAppCookieStickinessPolicy_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -9,10 +9,10 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/elb"
)
func resourceAwsAutoscalingGroup() *schema.Resource {
@ -462,7 +462,7 @@ func waitForASGCapacity(d *schema.ResourceData, meta interface{}) error {
return nil
}
return fmt.Errorf("Still need to wait for more healthy instances.")
return fmt.Errorf("Still need to wait for more healthy instances. This could mean instances failed to launch. See Scaling History for more information.")
})
}

View File

@ -6,9 +6,9 @@ import (
"strings"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
@ -343,9 +343,42 @@ resource "aws_autoscaling_group" "bar" {
`
const testAccAWSAutoScalingGroupConfigWithLoadBalancer = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
tags { Name = "tf-asg-test" }
}
resource "aws_internet_gateway" "gw" {
vpc_id = "${aws_vpc.foo.id}"
}
resource "aws_subnet" "foo" {
cidr_block = "10.1.1.0/24"
vpc_id = "${aws_vpc.foo.id}"
}
resource "aws_security_group" "foo" {
vpc_id="${aws_vpc.foo.id}"
ingress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_elb" "bar" {
name = "foobar-terraform-test"
availability_zones = ["us-west-2a"]
subnets = ["${aws_subnet.foo.id}"]
security_groups = ["${aws_security_group.foo.id}"]
listener {
instance_port = 80
@ -361,6 +394,8 @@ resource "aws_elb" "bar" {
interval = 5
timeout = 2
}
depends_on = ["aws_internet_gateway.gw"]
}
resource "aws_launch_configuration" "foobar" {
@ -368,16 +403,18 @@ resource "aws_launch_configuration" "foobar" {
// bitnami-nginxstack-1.6.1-0-linux-ubuntu-14.04.1-x86_64-hvm-ebs-ami-99f5b1a9-3
image_id = "ami-b5b3fc85"
instance_type = "t2.micro"
security_groups = ["${aws_security_group.foo.id}"]
}
resource "aws_autoscaling_group" "bar" {
availability_zones = ["us-west-2a"]
availability_zones = ["${aws_subnet.foo.availability_zone}"]
vpc_zone_identifier = ["${aws_subnet.foo.id}"]
name = "foobar3-terraform-test"
max_size = 2
min_size = 2
health_check_grace_period = 300
health_check_type = "ELB"
min_elb_capacity = 1
min_elb_capacity = 2
force_delete = true
launch_configuration = "${aws_launch_configuration.foobar.name}"

View File

@ -0,0 +1,200 @@
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsAutoscalingNotification() *schema.Resource {
return &schema.Resource{
Create: resourceAwsAutoscalingNotificationCreate,
Read: resourceAwsAutoscalingNotificationRead,
Update: resourceAwsAutoscalingNotificationUpdate,
Delete: resourceAwsAutoscalingNotificationDelete,
Schema: map[string]*schema.Schema{
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"group_names": &schema.Schema{
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"notifications": &schema.Schema{
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}
func resourceAwsAutoscalingNotificationCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
gl := convertSetToList(d.Get("group_names").(*schema.Set))
nl := convertSetToList(d.Get("notifications").(*schema.Set))
topic := d.Get("topic_arn").(string)
if err := addNotificationConfigToGroupsWithTopic(conn, gl, nl, topic); err != nil {
return err
}
// ARNs are unique, and these notifications are per ARN, so we re-use the ARN
// here as the ID
d.SetId(topic)
return resourceAwsAutoscalingNotificationRead(d, meta)
}
func resourceAwsAutoscalingNotificationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
gl := convertSetToList(d.Get("group_names").(*schema.Set))
opts := &autoscaling.DescribeNotificationConfigurationsInput{
AutoScalingGroupNames: gl,
}
resp, err := conn.DescribeNotificationConfigurations(opts)
if err != nil {
return fmt.Errorf("Error describing notifications")
}
topic := d.Get("topic_arn").(string)
// Grab all applicable notifcation configurations for this Topic.
// Each NotificationType will have a record, so 1 Group with 3 Types results
// in 3 records, all with the same Group name
gRaw := make(map[string]bool)
nRaw := make(map[string]bool)
for _, n := range resp.NotificationConfigurations {
if *n.TopicARN == topic {
gRaw[*n.AutoScalingGroupName] = true
nRaw[*n.NotificationType] = true
}
}
// Grab the keys here as the list of Groups
var gList []string
for k, _ := range gRaw {
gList = append(gList, k)
}
// Grab the keys here as the list of Types
var nList []string
for k, _ := range nRaw {
nList = append(nList, k)
}
if err := d.Set("group_names", gList); err != nil {
return err
}
if err := d.Set("notifications", nList); err != nil {
return err
}
return nil
}
func resourceAwsAutoscalingNotificationUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
// Notifications API call is a PUT, so we don't need to diff the list, just
// push whatever it is and AWS sorts it out
nl := convertSetToList(d.Get("notifications").(*schema.Set))
o, n := d.GetChange("group_names")
if o == nil {
o = new(schema.Set)
}
if n == nil {
n = new(schema.Set)
}
os := o.(*schema.Set)
ns := n.(*schema.Set)
remove := convertSetToList(os.Difference(ns))
add := convertSetToList(ns.Difference(os))
topic := d.Get("topic_arn").(string)
if err := removeNotificationConfigToGroupsWithTopic(conn, remove, topic); err != nil {
return err
}
var update []*string
if d.HasChange("notifications") {
update = convertSetToList(d.Get("group_names").(*schema.Set))
} else {
update = add
}
if err := addNotificationConfigToGroupsWithTopic(conn, update, nl, topic); err != nil {
return err
}
return resourceAwsAutoscalingNotificationRead(d, meta)
}
func addNotificationConfigToGroupsWithTopic(conn *autoscaling.AutoScaling, groups []*string, nl []*string, topic string) error {
for _, a := range groups {
opts := &autoscaling.PutNotificationConfigurationInput{
AutoScalingGroupName: a,
NotificationTypes: nl,
TopicARN: aws.String(topic),
}
_, err := conn.PutNotificationConfiguration(opts)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
return fmt.Errorf("[WARN] Error creating Autoscaling Group Notification for Group %s, error: \"%s\", code: \"%s\"", *a, awsErr.Message(), awsErr.Code())
}
return err
}
}
return nil
}
func removeNotificationConfigToGroupsWithTopic(conn *autoscaling.AutoScaling, groups []*string, topic string) error {
for _, r := range groups {
opts := &autoscaling.DeleteNotificationConfigurationInput{
AutoScalingGroupName: r,
TopicARN: aws.String(topic),
}
_, err := conn.DeleteNotificationConfiguration(opts)
if err != nil {
return fmt.Errorf("[WARN] Error deleting notification configuration for ASG \"%s\", Topic ARN \"%s\"", *r, topic)
}
}
return nil
}
func resourceAwsAutoscalingNotificationDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
gl := convertSetToList(d.Get("group_names").(*schema.Set))
topic := d.Get("topic_arn").(string)
if err := removeNotificationConfigToGroupsWithTopic(conn, gl, topic); err != nil {
return err
}
return nil
}
func convertSetToList(s *schema.Set) (nl []*string) {
l := s.List()
for _, n := range l {
nl = append(nl, aws.String(n.(string)))
}
return nl
}

View File

@ -0,0 +1,252 @@
package aws
import (
"fmt"
"strconv"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccASGNotification_basic(t *testing.T) {
var asgn autoscaling.DescribeNotificationConfigurationsOutput
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckASGNDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccASGNotificationConfig_basic,
Check: resource.ComposeTestCheckFunc(
testAccCheckASGNotificationExists("aws_autoscaling_notification.example", []string{"foobar1-terraform-test"}, &asgn),
testAccCheckAWSASGNotificationAttributes("aws_autoscaling_notification.example", &asgn),
),
},
},
})
}
func TestAccASGNotification_update(t *testing.T) {
var asgn autoscaling.DescribeNotificationConfigurationsOutput
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckASGNDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccASGNotificationConfig_basic,
Check: resource.ComposeTestCheckFunc(
testAccCheckASGNotificationExists("aws_autoscaling_notification.example", []string{"foobar1-terraform-test"}, &asgn),
testAccCheckAWSASGNotificationAttributes("aws_autoscaling_notification.example", &asgn),
),
},
resource.TestStep{
Config: testAccASGNotificationConfig_update,
Check: resource.ComposeTestCheckFunc(
testAccCheckASGNotificationExists("aws_autoscaling_notification.example", []string{"foobar1-terraform-test", "barfoo-terraform-test"}, &asgn),
testAccCheckAWSASGNotificationAttributes("aws_autoscaling_notification.example", &asgn),
),
},
},
})
}
func testAccCheckASGNotificationExists(n string, groups []string, asgn *autoscaling.DescribeNotificationConfigurationsOutput) 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 ASG Notification ID is set")
}
var gl []*string
for _, g := range groups {
gl = append(gl, aws.String(g))
}
conn := testAccProvider.Meta().(*AWSClient).autoscalingconn
opts := &autoscaling.DescribeNotificationConfigurationsInput{
AutoScalingGroupNames: gl,
}
resp, err := conn.DescribeNotificationConfigurations(opts)
if err != nil {
return fmt.Errorf("Error describing notifications")
}
*asgn = *resp
return nil
}
}
func testAccCheckASGNDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_autoscaling_notification" {
continue
}
groups := []*string{aws.String("foobar1-terraform-test")}
conn := testAccProvider.Meta().(*AWSClient).autoscalingconn
opts := &autoscaling.DescribeNotificationConfigurationsInput{
AutoScalingGroupNames: groups,
}
resp, err := conn.DescribeNotificationConfigurations(opts)
if err != nil {
return fmt.Errorf("Error describing notifications")
}
if len(resp.NotificationConfigurations) != 0 {
fmt.Errorf("Error finding notification descriptions")
}
}
return nil
}
func testAccCheckAWSASGNotificationAttributes(n string, asgn *autoscaling.DescribeNotificationConfigurationsOutput) 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 ASG Notification ID is set")
}
if len(asgn.NotificationConfigurations) == 0 {
return fmt.Errorf("Error: no ASG Notifications found")
}
// build a unique list of groups, notification types
gRaw := make(map[string]bool)
nRaw := make(map[string]bool)
for _, n := range asgn.NotificationConfigurations {
if *n.TopicARN == rs.Primary.Attributes["topic_arn"] {
gRaw[*n.AutoScalingGroupName] = true
nRaw[*n.NotificationType] = true
}
}
// Grab the keys here as the list of Groups
var gList []string
for k, _ := range gRaw {
gList = append(gList, k)
}
// Grab the keys here as the list of Types
var nList []string
for k, _ := range nRaw {
nList = append(nList, k)
}
typeCount, _ := strconv.Atoi(rs.Primary.Attributes["notifications.#"])
if len(nList) != typeCount {
return fmt.Errorf("Error: Bad ASG Notification count, expected (%d), got (%d)", typeCount, len(nList))
}
groupCount, _ := strconv.Atoi(rs.Primary.Attributes["group_names.#"])
if len(gList) != groupCount {
return fmt.Errorf("Error: Bad ASG Group count, expected (%d), got (%d)", typeCount, len(gList))
}
return nil
}
}
const testAccASGNotificationConfig_basic = `
resource "aws_sns_topic" "topic_example" {
name = "user-updates-topic"
}
resource "aws_launch_configuration" "foobar" {
name = "foobarautoscaling-terraform-test"
image_id = "ami-21f78e11"
instance_type = "t1.micro"
}
resource "aws_autoscaling_group" "bar" {
availability_zones = ["us-west-2a"]
name = "foobar1-terraform-test"
max_size = 1
min_size = 1
health_check_grace_period = 100
health_check_type = "ELB"
desired_capacity = 1
force_delete = true
termination_policies = ["OldestInstance"]
launch_configuration = "${aws_launch_configuration.foobar.name}"
}
resource "aws_autoscaling_notification" "example" {
group_names = ["${aws_autoscaling_group.bar.name}"]
notifications = [
"autoscaling:EC2_INSTANCE_LAUNCH",
"autoscaling:EC2_INSTANCE_TERMINATE",
]
topic_arn = "${aws_sns_topic.topic_example.arn}"
}
`
const testAccASGNotificationConfig_update = `
resource "aws_sns_topic" "user_updates" {
name = "user-updates-topic"
}
resource "aws_launch_configuration" "foobar" {
name = "foobarautoscaling-terraform-test"
image_id = "ami-21f78e11"
instance_type = "t1.micro"
}
resource "aws_autoscaling_group" "bar" {
availability_zones = ["us-west-2a"]
name = "foobar1-terraform-test"
max_size = 1
min_size = 1
health_check_grace_period = 100
health_check_type = "ELB"
desired_capacity = 1
force_delete = true
termination_policies = ["OldestInstance"]
launch_configuration = "${aws_launch_configuration.foobar.name}"
}
resource "aws_autoscaling_group" "foo" {
availability_zones = ["us-west-2b"]
name = "barfoo-terraform-test"
max_size = 1
min_size = 1
health_check_grace_period = 200
health_check_type = "ELB"
desired_capacity = 1
force_delete = true
termination_policies = ["OldestInstance"]
launch_configuration = "${aws_launch_configuration.foobar.name}"
}
resource "aws_autoscaling_notification" "example" {
group_names = [
"${aws_autoscaling_group.bar.name}",
"${aws_autoscaling_group.foo.name}",
]
notifications = [
"autoscaling:EC2_INSTANCE_LAUNCH",
"autoscaling:EC2_INSTANCE_TERMINATE",
"autoscaling:EC2_INSTANCE_LAUNCH_ERROR"
]
topic_arn = "${aws_sns_topic.user_updates.arn}"
}`

View File

@ -5,9 +5,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccCustomerGateway(t *testing.T) {
func TestAccCustomerGateway_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -6,10 +6,10 @@ import (
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -9,12 +9,12 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
)
func TestAccAWSDBInstance(t *testing.T) {
func TestAccAWSDBInstance_basic(t *testing.T) {
var v rds.DBInstance
resource.Test(t, resource.TestCase{

View File

@ -11,9 +11,9 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
)
func resourceAwsDbParameterGroup() *schema.Resource {

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSDBParameterGroup(t *testing.T) {
func TestAccAWSDBParameterGroup_basic(t *testing.T) {
var v rds.DBParameterGroup
resource.Test(t, resource.TestCase{

View File

@ -6,9 +6,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/multierror"
"github.com/hashicorp/terraform/helper/resource"

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSDBSecurityGroup(t *testing.T) {
func TestAccAWSDBSecurityGroup_basic(t *testing.T) {
var v rds.DBSecurityGroup
resource.Test(t, resource.TestCase{

View File

@ -6,9 +6,9 @@ import (
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -7,12 +7,12 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
)
func TestAccAWSDBSubnetGroup(t *testing.T) {
func TestAccAWSDBSubnetGroup_basic(t *testing.T) {
var v rds.DBSubnetGroup
testCheck := func(*terraform.State) error {

View File

@ -5,9 +5,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEBSVolume(t *testing.T) {
func TestAccAWSEBSVolume_basic(t *testing.T) {
var v ec2.Volume
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },

View File

@ -0,0 +1,80 @@
package aws
import (
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsEcsCluster() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEcsClusterCreate,
Read: resourceAwsEcsClusterRead,
Delete: resourceAwsEcsClusterDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceAwsEcsClusterCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
clusterName := d.Get("name").(string)
log.Printf("[DEBUG] Creating ECS cluster %s", clusterName)
out, err := conn.CreateCluster(&ecs.CreateClusterInput{
ClusterName: aws.String(clusterName),
})
if err != nil {
return err
}
log.Printf("[DEBUG] ECS cluster %s created", *out.Cluster.ClusterARN)
d.SetId(*out.Cluster.ClusterARN)
d.Set("name", *out.Cluster.ClusterName)
return nil
}
func resourceAwsEcsClusterRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
clusterName := d.Get("name").(string)
log.Printf("[DEBUG] Reading ECS cluster %s", clusterName)
out, err := conn.DescribeClusters(&ecs.DescribeClustersInput{
Clusters: []*string{aws.String(clusterName)},
})
if err != nil {
return err
}
log.Printf("[DEBUG] Received ECS clusters: %#v", out.Clusters)
d.SetId(*out.Clusters[0].ClusterARN)
d.Set("name", *out.Clusters[0].ClusterName)
return nil
}
func resourceAwsEcsClusterDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
log.Printf("[DEBUG] Deleting ECS cluster %s", d.Id())
// TODO: Handle ClientException: The Cluster cannot be deleted while Container Instances are active.
// TODO: Handle ClientException: The Cluster cannot be deleted while Services are active.
out, err := conn.DeleteCluster(&ecs.DeleteClusterInput{
Cluster: aws.String(d.Id()),
})
log.Printf("[DEBUG] ECS cluster %s deleted: %#v", d.Id(), out)
return err
}

View File

@ -0,0 +1,68 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEcsCluster_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSEcsCluster,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsClusterExists("aws_ecs_cluster.foo"),
),
},
},
})
}
func testAccCheckAWSEcsClusterDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ecsconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_ecs_cluster" {
continue
}
out, err := conn.DescribeClusters(&ecs.DescribeClustersInput{
Clusters: []*string{aws.String(rs.Primary.ID)},
})
if err == nil {
if len(out.Clusters) != 0 {
return fmt.Errorf("ECS cluster still exists:\n%#v", out.Clusters)
}
}
return err
}
return nil
}
func testAccCheckAWSEcsClusterExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
return nil
}
}
var testAccAWSEcsCluster = `
resource "aws_ecs_cluster" "foo" {
name = "red-grapes"
}
`

View File

@ -0,0 +1,316 @@
package aws
import (
"bytes"
"fmt"
"log"
"regexp"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
var taskDefinitionRE = regexp.MustCompile("^([a-zA-Z0-9_-]+):([0-9]+)$")
func resourceAwsEcsService() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEcsServiceCreate,
Read: resourceAwsEcsServiceRead,
Update: resourceAwsEcsServiceUpdate,
Delete: resourceAwsEcsServiceDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"cluster": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"task_definition": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"desired_count": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"iam_role": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"load_balancer": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"elb_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"container_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"container_port": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: resourceAwsEcsLoadBalancerHash,
},
},
}
}
func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
input := ecs.CreateServiceInput{
ServiceName: aws.String(d.Get("name").(string)),
TaskDefinition: aws.String(d.Get("task_definition").(string)),
DesiredCount: aws.Long(int64(d.Get("desired_count").(int))),
}
if v, ok := d.GetOk("cluster"); ok {
input.Cluster = aws.String(v.(string))
}
loadBalancers := expandEcsLoadBalancers(d.Get("load_balancer").(*schema.Set).List())
if len(loadBalancers) > 0 {
log.Printf("[DEBUG] Adding ECS load balancers: %#v", loadBalancers)
input.LoadBalancers = loadBalancers
}
if v, ok := d.GetOk("iam_role"); ok {
input.Role = aws.String(v.(string))
}
log.Printf("[DEBUG] Creating ECS service: %#v", input)
out, err := conn.CreateService(&input)
if err != nil {
return err
}
service := *out.Service
log.Printf("[DEBUG] ECS service created: %s", *service.ServiceARN)
d.SetId(*service.ServiceARN)
d.Set("cluster", *service.ClusterARN)
return resourceAwsEcsServiceUpdate(d, meta)
}
func resourceAwsEcsServiceRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
log.Printf("[DEBUG] Reading ECS service %s", d.Id())
input := ecs.DescribeServicesInput{
Services: []*string{aws.String(d.Id())},
Cluster: aws.String(d.Get("cluster").(string)),
}
out, err := conn.DescribeServices(&input)
if err != nil {
return err
}
service := out.Services[0]
log.Printf("[DEBUG] Received ECS service %#v", service)
d.SetId(*service.ServiceARN)
d.Set("name", *service.ServiceName)
// Save task definition in the same format
if strings.HasPrefix(d.Get("task_definition").(string), "arn:aws:ecs:") {
d.Set("task_definition", *service.TaskDefinition)
} else {
taskDefinition := buildFamilyAndRevisionFromARN(*service.TaskDefinition)
d.Set("task_definition", taskDefinition)
}
d.Set("desired_count", *service.DesiredCount)
d.Set("cluster", *service.ClusterARN)
if service.RoleARN != nil {
d.Set("iam_role", *service.RoleARN)
}
if service.LoadBalancers != nil {
d.Set("load_balancers", flattenEcsLoadBalancers(service.LoadBalancers))
}
return nil
}
func resourceAwsEcsServiceUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
log.Printf("[DEBUG] Updating ECS service %s", d.Id())
input := ecs.UpdateServiceInput{
Service: aws.String(d.Id()),
Cluster: aws.String(d.Get("cluster").(string)),
}
if d.HasChange("desired_count") {
_, n := d.GetChange("desired_count")
input.DesiredCount = aws.Long(int64(n.(int)))
}
if d.HasChange("task_definition") {
_, n := d.GetChange("task_definition")
input.TaskDefinition = aws.String(n.(string))
}
out, err := conn.UpdateService(&input)
if err != nil {
return err
}
service := out.Service
log.Printf("[DEBUG] Updated ECS service %#v", service)
return resourceAwsEcsServiceRead(d, meta)
}
func resourceAwsEcsServiceDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
// Check if it's not already gone
resp, err := conn.DescribeServices(&ecs.DescribeServicesInput{
Services: []*string{aws.String(d.Id())},
Cluster: aws.String(d.Get("cluster").(string)),
})
if err != nil {
return err
}
log.Printf("[DEBUG] ECS service %s is currently %s", d.Id(), *resp.Services[0].Status)
if *resp.Services[0].Status == "INACTIVE" {
return nil
}
// Drain the ECS service
if *resp.Services[0].Status != "DRAINING" {
log.Printf("[DEBUG] Draining ECS service %s", d.Id())
_, err = conn.UpdateService(&ecs.UpdateServiceInput{
Service: aws.String(d.Id()),
Cluster: aws.String(d.Get("cluster").(string)),
DesiredCount: aws.Long(int64(0)),
})
if err != nil {
return err
}
}
input := ecs.DeleteServiceInput{
Service: aws.String(d.Id()),
Cluster: aws.String(d.Get("cluster").(string)),
}
log.Printf("[DEBUG] Deleting ECS service %#v", input)
out, err := conn.DeleteService(&input)
if err != nil {
return err
}
// Wait until it's deleted
wait := resource.StateChangeConf{
Pending: []string{"DRAINING"},
Target: "INACTIVE",
Timeout: 5 * time.Minute,
MinTimeout: 1 * time.Second,
Refresh: func() (interface{}, string, error) {
log.Printf("[DEBUG] Checking if ECS service %s is INACTIVE", d.Id())
resp, err := conn.DescribeServices(&ecs.DescribeServicesInput{
Services: []*string{aws.String(d.Id())},
Cluster: aws.String(d.Get("cluster").(string)),
})
if err != nil {
return resp, "FAILED", err
}
return resp, *resp.Services[0].Status, nil
},
}
_, err = wait.WaitForState()
if err != nil {
return err
}
log.Printf("[DEBUG] ECS service %s deleted.", *out.Service.ServiceARN)
return nil
}
func resourceAwsEcsLoadBalancerHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["elb_name"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["container_name"].(string)))
buf.WriteString(fmt.Sprintf("%d-", m["container_port"].(int)))
return hashcode.String(buf.String())
}
func buildFamilyAndRevisionFromARN(arn string) string {
return strings.Split(arn, "/")[1]
}
func buildTaskDefinitionARN(taskDefinition string, meta interface{}) (string, error) {
// If it's already an ARN, just return it
if strings.HasPrefix(taskDefinition, "arn:aws:ecs:") {
return taskDefinition, nil
}
// Parse out family & revision
family, revision, err := parseTaskDefinition(taskDefinition)
if err != nil {
return "", err
}
iamconn := meta.(*AWSClient).iamconn
region := meta.(*AWSClient).region
// An zero value GetUserInput{} defers to the currently logged in user
resp, err := iamconn.GetUser(&iam.GetUserInput{})
if err != nil {
return "", fmt.Errorf("GetUser ERROR: %#v", err)
}
// arn:aws:iam::0123456789:user/username
userARN := *resp.User.ARN
accountID := strings.Split(userARN, ":")[4]
// arn:aws:ecs:us-west-2:01234567890:task-definition/mongodb:3
arn := fmt.Sprintf("arn:aws:ecs:%s:%s:task-definition/%s:%s",
region, accountID, family, revision)
log.Printf("[DEBUG] Built task definition ARN: %s", arn)
return arn, nil
}
func parseTaskDefinition(taskDefinition string) (string, string, error) {
matches := taskDefinitionRE.FindAllStringSubmatch(taskDefinition, 2)
if len(matches) == 0 || len(matches[0]) != 3 {
return "", "", fmt.Errorf(
"Invalid task definition format, family:rev or ARN expected (%#v)",
taskDefinition)
}
return matches[0][1], matches[0][2], nil
}

View File

@ -0,0 +1,276 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestParseTaskDefinition(t *testing.T) {
cases := map[string]map[string]interface{}{
"invalid": map[string]interface{}{
"family": "",
"revision": "",
"isValid": false,
},
"invalidWithColon:": map[string]interface{}{
"family": "",
"revision": "",
"isValid": false,
},
"1234": map[string]interface{}{
"family": "",
"revision": "",
"isValid": false,
},
"invalid:aaa": map[string]interface{}{
"family": "",
"revision": "",
"isValid": false,
},
"invalid=family:1": map[string]interface{}{
"family": "",
"revision": "",
"isValid": false,
},
"invalid:name:1": map[string]interface{}{
"family": "",
"revision": "",
"isValid": false,
},
"valid:1": map[string]interface{}{
"family": "valid",
"revision": "1",
"isValid": true,
},
"abc12-def:54": map[string]interface{}{
"family": "abc12-def",
"revision": "54",
"isValid": true,
},
"lorem_ip-sum:123": map[string]interface{}{
"family": "lorem_ip-sum",
"revision": "123",
"isValid": true,
},
"lorem-ipsum:1": map[string]interface{}{
"family": "lorem-ipsum",
"revision": "1",
"isValid": true,
},
}
for input, expectedOutput := range cases {
family, revision, err := parseTaskDefinition(input)
isValid := expectedOutput["isValid"].(bool)
if !isValid && err == nil {
t.Fatalf("Task definition %s should fail", input)
}
expectedFamily := expectedOutput["family"].(string)
if family != expectedFamily {
t.Fatalf("Unexpected family (%#v) for task definition %s\n%#v", family, input, err)
}
expectedRevision := expectedOutput["revision"].(string)
if revision != expectedRevision {
t.Fatalf("Unexpected revision (%#v) for task definition %s\n%#v", revision, input, err)
}
}
}
func TestAccAWSEcsServiceWithARN(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSEcsService,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
),
},
resource.TestStep{
Config: testAccAWSEcsServiceModified,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
),
},
},
})
}
func TestAccAWSEcsServiceWithFamilyAndRevision(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSEcsServiceWithFamilyAndRevision,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
),
},
resource.TestStep{
Config: testAccAWSEcsServiceWithFamilyAndRevisionModified,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
),
},
},
})
}
func testAccCheckAWSEcsServiceDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ecsconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_ecs_service" {
continue
}
out, err := conn.DescribeServices(&ecs.DescribeServicesInput{
Services: []*string{aws.String(rs.Primary.ID)},
})
if err == nil {
if len(out.Services) > 0 {
return fmt.Errorf("ECS service still exists:\n%#v", out.Services)
}
}
return err
}
return nil
}
func testAccCheckAWSEcsServiceExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
return nil
}
}
var testAccAWSEcsService = `
resource "aws_ecs_cluster" "default" {
name = "terraformecstest1"
}
resource "aws_ecs_task_definition" "mongo" {
family = "mongodb"
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "mongo:latest",
"memory": 128,
"name": "mongodb"
}
]
DEFINITION
}
resource "aws_ecs_service" "mongo" {
name = "mongodb"
cluster = "${aws_ecs_cluster.default.id}"
task_definition = "${aws_ecs_task_definition.mongo.arn}"
desired_count = 1
}
`
var testAccAWSEcsServiceModified = `
resource "aws_ecs_cluster" "default" {
name = "terraformecstest1"
}
resource "aws_ecs_task_definition" "mongo" {
family = "mongodb"
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "mongo:latest",
"memory": 128,
"name": "mongodb"
}
]
DEFINITION
}
resource "aws_ecs_service" "mongo" {
name = "mongodb"
cluster = "${aws_ecs_cluster.default.id}"
task_definition = "${aws_ecs_task_definition.mongo.arn}"
desired_count = 2
}
`
var testAccAWSEcsServiceWithFamilyAndRevision = `
resource "aws_ecs_cluster" "default" {
name = "terraformecstest2"
}
resource "aws_ecs_task_definition" "jenkins" {
family = "jenkins"
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "jenkins:latest",
"memory": 128,
"name": "jenkins"
}
]
DEFINITION
}
resource "aws_ecs_service" "jenkins" {
name = "jenkins"
cluster = "${aws_ecs_cluster.default.id}"
task_definition = "${aws_ecs_task_definition.jenkins.family}:${aws_ecs_task_definition.jenkins.revision}"
desired_count = 1
}
`
var testAccAWSEcsServiceWithFamilyAndRevisionModified = `
resource "aws_ecs_cluster" "default" {
name = "terraformecstest2"
}
resource "aws_ecs_task_definition" "jenkins" {
family = "jenkins"
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "jenkins:latest",
"memory": 128,
"name": "jenkins"
}
]
DEFINITION
}
resource "aws_ecs_service" "jenkins" {
name = "jenkins"
cluster = "${aws_ecs_cluster.default.id}"
task_definition = "${aws_ecs_task_definition.jenkins.family}:${aws_ecs_task_definition.jenkins.revision}"
desired_count = 1
}
`

View File

@ -0,0 +1,158 @@
package aws
import (
"bytes"
"crypto/sha1"
"encoding/hex"
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsEcsTaskDefinition() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEcsTaskDefinitionCreate,
Read: resourceAwsEcsTaskDefinitionRead,
Update: resourceAwsEcsTaskDefinitionUpdate,
Delete: resourceAwsEcsTaskDefinitionDelete,
Schema: map[string]*schema.Schema{
"arn": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"family": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"revision": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
},
"container_definitions": &schema.Schema{
Type: schema.TypeString,
Required: true,
StateFunc: func(v interface{}) string {
hash := sha1.Sum([]byte(v.(string)))
return hex.EncodeToString(hash[:])
},
},
"volume": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"host_path": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
},
Set: resourceAwsEcsTaskDefinitionVolumeHash,
},
},
}
}
func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
rawDefinitions := d.Get("container_definitions").(string)
definitions, err := expandEcsContainerDefinitions(rawDefinitions)
if err != nil {
return err
}
input := ecs.RegisterTaskDefinitionInput{
ContainerDefinitions: definitions,
Family: aws.String(d.Get("family").(string)),
}
if v, ok := d.GetOk("volume"); ok {
volumes, err := expandEcsVolumes(v.(*schema.Set).List())
if err != nil {
return err
}
input.Volumes = volumes
}
log.Printf("[DEBUG] Registering ECS task definition: %#v", input)
out, err := conn.RegisterTaskDefinition(&input)
if err != nil {
return err
}
taskDefinition := *out.TaskDefinition
log.Printf("[DEBUG] ECS task definition registered: %#v (rev. %d)",
*taskDefinition.TaskDefinitionARN, *taskDefinition.Revision)
d.SetId(*taskDefinition.Family)
d.Set("arn", *taskDefinition.TaskDefinitionARN)
return resourceAwsEcsTaskDefinitionRead(d, meta)
}
func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
log.Printf("[DEBUG] Reading task definition %s", d.Id())
out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
TaskDefinition: aws.String(d.Get("arn").(string)),
})
if err != nil {
return err
}
log.Printf("[DEBUG] Received task definition %#v", out)
taskDefinition := out.TaskDefinition
d.SetId(*taskDefinition.Family)
d.Set("arn", *taskDefinition.TaskDefinitionARN)
d.Set("family", *taskDefinition.Family)
d.Set("revision", *taskDefinition.Revision)
d.Set("container_definitions", taskDefinition.ContainerDefinitions)
d.Set("volumes", flattenEcsVolumes(taskDefinition.Volumes))
return nil
}
func resourceAwsEcsTaskDefinitionUpdate(d *schema.ResourceData, meta interface{}) error {
return resourceAwsEcsTaskDefinitionCreate(d, meta)
}
func resourceAwsEcsTaskDefinitionDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn
// NOT YET IMPLEMENTED o_O
_, err := conn.DeregisterTaskDefinition(&ecs.DeregisterTaskDefinitionInput{
TaskDefinition: aws.String(d.Id()),
})
log.Printf("[DEBUG] Deregistering task definition %s returned %#v", d.Id(), err)
return nil
}
func resourceAwsEcsTaskDefinitionVolumeHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["host_path"].(string)))
return hashcode.String(buf.String())
}

View File

@ -0,0 +1,111 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEcsTaskDefinition_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSEcsTaskDefinition,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins"),
),
},
},
})
}
func testAccCheckAWSEcsTaskDefinitionDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ecsconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_ecs_task_definition" {
continue
}
out, err := conn.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
TaskDefinition: aws.String(rs.Primary.ID),
})
if err == nil {
if out.TaskDefinition != nil {
return fmt.Errorf("ECS task definition still exists:\n%#v", *out.TaskDefinition)
}
}
return err
}
return nil
}
func testAccCheckAWSEcsTaskDefinitionExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
return nil
}
}
var testAccAWSEcsTaskDefinition = `
resource "aws_ecs_task_definition" "jenkins" {
family = "jenkins"
container_definitions = <<TASK_DEFINITION
[
{
"cpu": 10,
"command": ["sleep", "10"],
"entryPoint": ["/"],
"environment": [
{"name": "VARNAME", "value": "VARVAL"}
],
"essential": true,
"image": "jenkins",
"links": ["mongodb"],
"memory": 128,
"name": "jenkins",
"portMappings": [
{
"containerPort": 80,
"hostPort": 8080
}
]
},
{
"cpu": 10,
"command": ["sleep", "10"],
"entryPoint": ["/"],
"essential": true,
"image": "mongodb",
"memory": 128,
"name": "mongodb",
"portMappings": [
{
"containerPort": 28017,
"hostPort": 28017
}
]
}
]
TASK_DEFINITION
volume {
name = "jenkins-home"
host_path = "/ecs/jenkins-home"
}
}
`

View File

@ -6,9 +6,9 @@ import (
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -5,14 +5,14 @@ import (
"strings"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEIP_normal(t *testing.T) {
func TestAccAWSEIP_basic(t *testing.T) {
var conf ec2.Address
resource.Test(t, resource.TestCase{

View File

@ -7,10 +7,10 @@ import (
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
@ -52,8 +52,7 @@ func resourceAwsElasticacheCluster() *schema.Resource {
},
"port": &schema.Schema{
Type: schema.TypeInt,
Default: 11211,
Optional: true,
Required: true,
ForceNew: true,
},
"engine_version": &schema.Schema{
@ -123,7 +122,7 @@ func resourceAwsElasticacheClusterCreate(d *schema.ResourceData, meta interface{
numNodes := int64(d.Get("num_cache_nodes").(int)) // 2
engine := d.Get("engine").(string) // memcached
engineVersion := d.Get("engine_version").(string) // 1.4.14
port := int64(d.Get("port").(int)) // 11211
port := int64(d.Get("port").(int)) // e.g) 11211
subnetGroupName := d.Get("subnet_group_name").(string)
securityNameSet := d.Get("security_group_names").(*schema.Set)
securityIdSet := d.Get("security_group_ids").(*schema.Set)

View File

@ -6,8 +6,8 @@ import (
"testing"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
@ -32,6 +32,7 @@ func TestAccAWSElasticacheCluster_basic(t *testing.T) {
}
func TestAccAWSElasticacheCluster_vpc(t *testing.T) {
var csg elasticache.CacheSubnetGroup
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
@ -40,7 +41,7 @@ func TestAccAWSElasticacheCluster_vpc(t *testing.T) {
resource.TestStep{
Config: testAccAWSElasticacheClusterInVPCConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar"),
testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar", &csg),
testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar"),
),
},
@ -95,7 +96,7 @@ func genRandInt() int {
}
var testAccAWSElasticacheClusterConfig = fmt.Sprintf(`
provider "aws" {
provider "aws" {
region = "us-east-1"
}
resource "aws_security_group" "bar" {
@ -120,6 +121,7 @@ resource "aws_elasticache_cluster" "bar" {
engine = "memcached"
node_type = "cache.m1.small"
num_cache_nodes = 1
port = 11211
parameter_group_name = "default.memcached1.4"
security_group_names = ["${aws_elasticache_security_group.bar.name}"]
}

View File

@ -5,9 +5,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSElasticacheSecurityGroup(t *testing.T) {
func TestAccAWSElasticacheSecurityGroup_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -5,9 +5,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
@ -17,13 +17,13 @@ func resourceAwsElasticacheSubnetGroup() *schema.Resource {
return &schema.Resource{
Create: resourceAwsElasticacheSubnetGroupCreate,
Read: resourceAwsElasticacheSubnetGroupRead,
Update: resourceAwsElasticacheSubnetGroupUpdate,
Delete: resourceAwsElasticacheSubnetGroupDelete,
Schema: map[string]*schema.Schema{
"description": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
@ -34,7 +34,6 @@ func resourceAwsElasticacheSubnetGroup() *schema.Resource {
Type: schema.TypeSet,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: func(v interface{}) int {
return hashcode.String(v.(string))
@ -110,6 +109,29 @@ func resourceAwsElasticacheSubnetGroupRead(d *schema.ResourceData, meta interfac
return nil
}
func resourceAwsElasticacheSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).elasticacheconn
if d.HasChange("subnet_ids") || d.HasChange("description") {
var subnets []*string
if v := d.Get("subnet_ids"); v != nil {
for _, v := range v.(*schema.Set).List() {
subnets = append(subnets, aws.String(v.(string)))
}
}
log.Printf("[DEBUG] Updating ElastiCache Subnet Group")
_, err := conn.ModifyCacheSubnetGroup(&elasticache.ModifyCacheSubnetGroupInput{
CacheSubnetGroupName: aws.String(d.Get("name").(string)),
CacheSubnetGroupDescription: aws.String(d.Get("description").(string)),
SubnetIDs: subnets,
})
if err != nil {
return err
}
}
return resourceAwsElasticacheSubnetGroupRead(d, meta)
}
func resourceAwsElasticacheSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).elasticacheconn

View File

@ -4,22 +4,56 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSElasticacheSubnetGroup(t *testing.T) {
func TestAccAWSElasticacheSubnetGroup_basic(t *testing.T) {
var csg elasticache.CacheSubnetGroup
config := fmt.Sprintf(testAccAWSElasticacheSubnetGroupConfig, genRandInt())
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSElasticacheSubnetGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSElasticacheSubnetGroupConfig,
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar"),
testAccCheckAWSElasticacheSubnetGroupExists("aws_elasticache_subnet_group.bar", &csg),
),
},
},
})
}
func TestAccAWSElasticacheSubnetGroup_update(t *testing.T) {
var csg elasticache.CacheSubnetGroup
rn := "aws_elasticache_subnet_group.bar"
ri := genRandInt()
preConfig := fmt.Sprintf(testAccAWSElasticacheSubnetGroupUpdateConfigPre, ri)
postConfig := fmt.Sprintf(testAccAWSElasticacheSubnetGroupUpdateConfigPost, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSElasticacheSubnetGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists(rn, &csg),
testAccCheckAWSElastiCacheSubnetGroupAttrs(&csg, rn, 1),
),
},
resource.TestStep{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists(rn, &csg),
testAccCheckAWSElastiCacheSubnetGroupAttrs(&csg, rn, 2),
),
},
},
@ -46,7 +80,7 @@ func testAccCheckAWSElasticacheSubnetGroupDestroy(s *terraform.State) error {
return nil
}
func testAccCheckAWSElasticacheSubnetGroupExists(n string) resource.TestCheckFunc {
func testAccCheckAWSElasticacheSubnetGroupExists(n string, csg *elasticache.CacheSubnetGroup) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
@ -58,17 +92,47 @@ func testAccCheckAWSElasticacheSubnetGroupExists(n string) resource.TestCheckFun
}
conn := testAccProvider.Meta().(*AWSClient).elasticacheconn
_, err := conn.DescribeCacheSubnetGroups(&elasticache.DescribeCacheSubnetGroupsInput{
resp, err := conn.DescribeCacheSubnetGroups(&elasticache.DescribeCacheSubnetGroupsInput{
CacheSubnetGroupName: aws.String(rs.Primary.ID),
})
if err != nil {
return fmt.Errorf("CacheSubnetGroup error: %v", err)
}
for _, c := range resp.CacheSubnetGroups {
if rs.Primary.ID == *c.CacheSubnetGroupName {
*csg = *c
}
}
if csg == nil {
return fmt.Errorf("cache subnet group not found")
}
return nil
}
}
var testAccAWSElasticacheSubnetGroupConfig = fmt.Sprintf(`
func testAccCheckAWSElastiCacheSubnetGroupAttrs(csg *elasticache.CacheSubnetGroup, n string, count int) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if len(csg.Subnets) != count {
return fmt.Errorf("Bad cache subnet count, expected: %d, got: %d", count, len(csg.Subnets))
}
if rs.Primary.Attributes["description"] != *csg.CacheSubnetGroupDescription {
return fmt.Errorf("Bad cache subnet description, expected: %s, got: %s", rs.Primary.Attributes["description"], *csg.CacheSubnetGroupDescription)
}
return nil
}
}
var testAccAWSElasticacheSubnetGroupConfig = `
resource "aws_vpc" "foo" {
cidr_block = "192.168.0.0/16"
tags {
@ -90,4 +154,63 @@ resource "aws_elasticache_subnet_group" "bar" {
description = "tf-test-cache-subnet-group-descr"
subnet_ids = ["${aws_subnet.foo.id}"]
}
`, genRandInt())
`
var testAccAWSElasticacheSubnetGroupUpdateConfigPre = `
resource "aws_vpc" "foo" {
cidr_block = "10.0.0.0/16"
tags {
Name = "tf-elc-sub-test"
}
}
resource "aws_subnet" "foo" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
tags {
Name = "tf-test"
}
}
resource "aws_elasticache_subnet_group" "bar" {
name = "tf-test-cache-subnet-%03d"
description = "tf-test-cache-subnet-group-descr"
subnet_ids = ["${aws_subnet.foo.id}"]
}
`
var testAccAWSElasticacheSubnetGroupUpdateConfigPost = `
resource "aws_vpc" "foo" {
cidr_block = "10.0.0.0/16"
tags {
Name = "tf-elc-sub-test"
}
}
resource "aws_subnet" "foo" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
tags {
Name = "tf-test"
}
}
resource "aws_subnet" "bar" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "10.0.2.0/24"
availability_zone = "us-west-2a"
tags {
Name = "tf-test-foo-update"
}
}
resource "aws_elasticache_subnet_group" "bar" {
name = "tf-test-cache-subnet-%03d"
description = "tf-test-cache-subnet-group-descr-edited"
subnet_ids = [
"${aws_subnet.foo.id}",
"${aws_subnet.bar.id}",
]
}
`

View File

@ -4,10 +4,11 @@ import (
"bytes"
"fmt"
"log"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
@ -541,9 +542,11 @@ func resourceAwsElbListenerHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%d-", m["instance_port"].(int)))
buf.WriteString(fmt.Sprintf("%s-", m["instance_protocol"].(string)))
buf.WriteString(fmt.Sprintf("%s-",
strings.ToLower(m["instance_protocol"].(string))))
buf.WriteString(fmt.Sprintf("%d-", m["lb_port"].(int)))
buf.WriteString(fmt.Sprintf("%s-", m["lb_protocol"].(string)))
buf.WriteString(fmt.Sprintf("%s-",
strings.ToLower(m["lb_protocol"].(string))))
if v, ok := m["ssl_certificate_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))

View File

@ -7,9 +7,9 @@ import (
"sort"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
@ -362,6 +362,39 @@ func TestAccAWSELB_SecurityGroups(t *testing.T) {
})
}
// Unit test for listeners hash
func TestResourceAwsElbListenerHash(t *testing.T) {
cases := map[string]struct {
Left map[string]interface{}
Right map[string]interface{}
Match bool
}{
"protocols are case insensitive": {
map[string]interface{}{
"instance_port": 80,
"instance_protocol": "TCP",
"lb_port": 80,
"lb_protocol": "TCP",
},
map[string]interface{}{
"instance_port": 80,
"instance_protocol": "Tcp",
"lb_port": 80,
"lb_protocol": "tcP",
},
true,
},
}
for tn, tc := range cases {
leftHash := resourceAwsElbListenerHash(tc.Left)
rightHash := resourceAwsElbListenerHash(tc.Right)
if (leftHash == rightHash) != tc.Match {
t.Fatalf("%s: expected match: %t, but did not get it", tn, tc.Match)
}
}
}
func testAccCheckAWSELBDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).elbconn
@ -513,7 +546,8 @@ resource "aws_elb" "bar" {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
// Protocol should be case insensitive
lb_protocol = "HttP"
}
tags {

View File

@ -3,9 +3,9 @@ package aws
import (
"fmt"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSAccessKey_normal(t *testing.T) {
func TestAccAWSAccessKey_basic(t *testing.T) {
var conf iam.AccessKeyMetadata
resource.Test(t, resource.TestCase{

View File

@ -3,9 +3,9 @@ package aws
import (
"fmt"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -0,0 +1,156 @@
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsIamGroupMembership() *schema.Resource {
return &schema.Resource{
Create: resourceAwsIamGroupMembershipCreate,
Read: resourceAwsIamGroupMembershipRead,
Update: resourceAwsIamGroupMembershipUpdate,
Delete: resourceAwsIamGroupMembershipDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"users": &schema.Schema{
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"group": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceAwsIamGroupMembershipCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).iamconn
group := d.Get("group").(string)
userList := expandStringList(d.Get("users").(*schema.Set).List())
if err := addUsersToGroup(conn, userList, group); err != nil {
return err
}
d.SetId(d.Get("name").(string))
return resourceAwsIamGroupMembershipRead(d, meta)
}
func resourceAwsIamGroupMembershipRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).iamconn
group := d.Get("group").(string)
resp, err := conn.GetGroup(&iam.GetGroupInput{
GroupName: aws.String(group),
})
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
// aws specific error
if awsErr.Code() == "NoSuchEntity" {
// group not found
d.SetId("")
return nil
}
}
return err
}
ul := make([]string, 0, len(resp.Users))
for _, u := range resp.Users {
ul = append(ul, *u.UserName)
}
if err := d.Set("users", ul); err != nil {
return fmt.Errorf("[WARN] Error setting user list from IAM Group Membership (%s), error: %s", group, err)
}
return nil
}
func resourceAwsIamGroupMembershipUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).iamconn
if d.HasChange("users") {
group := d.Get("group").(string)
o, n := d.GetChange("users")
if o == nil {
o = new(schema.Set)
}
if n == nil {
n = new(schema.Set)
}
os := o.(*schema.Set)
ns := n.(*schema.Set)
remove := expandStringList(os.Difference(ns).List())
add := expandStringList(ns.Difference(os).List())
if err := removeUsersFromGroup(conn, remove, group); err != nil {
return err
}
if err := addUsersToGroup(conn, add, group); err != nil {
return err
}
}
return resourceAwsIamGroupMembershipRead(d, meta)
}
func resourceAwsIamGroupMembershipDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).iamconn
userList := expandStringList(d.Get("users").(*schema.Set).List())
group := d.Get("group").(string)
if err := removeUsersFromGroup(conn, userList, group); err != nil {
return err
}
return nil
}
func removeUsersFromGroup(conn *iam.IAM, users []*string, group string) error {
for _, u := range users {
_, err := conn.RemoveUserFromGroup(&iam.RemoveUserFromGroupInput{
UserName: u,
GroupName: aws.String(group),
})
if err != nil {
return err
}
}
return nil
}
func addUsersToGroup(conn *iam.IAM, users []*string, group string) error {
for _, u := range users {
_, err := conn.AddUserToGroup(&iam.AddUserToGroupInput{
UserName: u,
GroupName: aws.String(group),
})
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,169 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSGroupMembership_basic(t *testing.T) {
var group iam.GetGroupOutput
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSGroupMembershipDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSGroupMemberConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSGroupMembershipExists("aws_iam_group_membership.team", &group),
testAccCheckAWSGroupMembershipAttributes(&group, []string{"test-user"}),
),
},
resource.TestStep{
Config: testAccAWSGroupMemberConfigUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSGroupMembershipExists("aws_iam_group_membership.team", &group),
testAccCheckAWSGroupMembershipAttributes(&group, []string{"test-user-two", "test-user-three"}),
),
},
},
})
}
func testAccCheckAWSGroupMembershipDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).iamconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_iam_group_membership" {
continue
}
group := rs.Primary.Attributes["group"]
resp, err := conn.GetGroup(&iam.GetGroupInput{
GroupName: aws.String(group),
})
if err != nil {
// might error here
return err
}
users := []string{"test-user", "test-user-two", "test-user-three"}
for _, u := range resp.Users {
for _, i := range users {
if i == *u.UserName {
return fmt.Errorf("Error: User (s) still a member of Group (%s)", i, *resp.Group.GroupName)
}
}
}
}
return nil
}
func testAccCheckAWSGroupMembershipExists(n string, g *iam.GetGroupOutput) 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 User name is set")
}
conn := testAccProvider.Meta().(*AWSClient).iamconn
gn := rs.Primary.Attributes["group"]
resp, err := conn.GetGroup(&iam.GetGroupInput{
GroupName: aws.String(gn),
})
if err != nil {
return fmt.Errorf("Error: Group (%s) not found", gn)
}
*g = *resp
return nil
}
}
func testAccCheckAWSGroupMembershipAttributes(group *iam.GetGroupOutput, users []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if *group.Group.GroupName != "test-group" {
return fmt.Errorf("Bad group membership: expected %s, got %s", "test-group", *group.Group.GroupName)
}
uc := len(users)
for _, u := range users {
for _, gu := range group.Users {
if u == *gu.UserName {
uc--
}
}
}
if uc > 0 {
return fmt.Errorf("Bad group membership count, expected (%d), but only (%d) found", len(users), uc)
}
return nil
}
}
const testAccAWSGroupMemberConfig = `
resource "aws_iam_group" "group" {
name = "test-group"
path = "/"
}
resource "aws_iam_user" "user" {
name = "test-user"
path = "/"
}
resource "aws_iam_group_membership" "team" {
name = "tf-testing-group-membership"
users = ["${aws_iam_user.user.name}"]
group = "${aws_iam_group.group.name}"
}
`
const testAccAWSGroupMemberConfigUpdate = `
resource "aws_iam_group" "group" {
name = "test-group"
path = "/"
}
resource "aws_iam_user" "user" {
name = "test-user"
path = "/"
}
resource "aws_iam_user" "user_two" {
name = "test-user-two"
path = "/"
}
resource "aws_iam_user" "user_three" {
name = "test-user-three"
path = "/"
}
resource "aws_iam_group_membership" "team" {
name = "tf-testing-group-membership"
users = [
"${aws_iam_user.user_two.name}",
"${aws_iam_user.user_three.name}",
]
group = "${aws_iam_group.group.name}"
}
`

View File

@ -5,9 +5,9 @@ import (
"net/url"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSIAMGroupPolicy(t *testing.T) {
func TestAccAWSIAMGroupPolicy_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSIAMGroup_normal(t *testing.T) {
func TestAccAWSIAMGroup_basic(t *testing.T) {
var conf iam.GetGroupOutput
resource.Test(t, resource.TestCase{

View File

@ -3,9 +3,9 @@ package aws
import (
"fmt"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -6,7 +6,7 @@ import (
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccAWSIAMInstanceProfile(t *testing.T) {
func TestAccAWSIAMInstanceProfile_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -3,9 +3,9 @@ package aws
import (
"fmt"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)
@ -59,7 +59,7 @@ func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error
response, err := iamconn.CreatePolicy(request)
if err != nil {
return fmt.Errorf("Error creating IAM policy %s: %#v", name, err)
return fmt.Errorf("Error creating IAM policy %s: %s", name, err)
}
return readIamPolicy(d, response.Policy)
@ -78,7 +78,7 @@ func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IAM policy %s: %#v", d.Id(), err)
return fmt.Errorf("Error reading IAM policy %s: %s", d.Id(), err)
}
return readIamPolicy(d, response.Policy)
@ -101,7 +101,7 @@ func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error
}
if _, err := iamconn.CreatePolicyVersion(request); err != nil {
return fmt.Errorf("Error updating IAM policy %s: %#v", d.Id(), err)
return fmt.Errorf("Error updating IAM policy %s: %s", d.Id(), err)
}
return nil
}
@ -187,7 +187,7 @@ func iamPolicyDeleteVersion(arn, versionID string, iamconn *iam.IAM) error {
_, err := iamconn.DeletePolicyVersion(request)
if err != nil {
return fmt.Errorf("Error deleting version %s from IAM policy %s: %#v", versionID, arn, err)
return fmt.Errorf("Error deleting version %s from IAM policy %s: %s", versionID, arn, err)
}
return nil
}
@ -199,7 +199,7 @@ func iamPolicyListVersions(arn string, iamconn *iam.IAM) ([]*iam.PolicyVersion,
response, err := iamconn.ListPolicyVersions(request)
if err != nil {
return nil, fmt.Errorf("Error listing versions for IAM policy %s: %#v", arn, err)
return nil, fmt.Errorf("Error listing versions for IAM policy %s: %s", arn, err)
}
return response.Versions, nil
}

View File

@ -3,9 +3,9 @@ package aws
import (
"fmt"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)
@ -102,6 +102,27 @@ func resourceAwsIamRoleReadResult(d *schema.ResourceData, role *iam.Role) error
func resourceAwsIamRoleDelete(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
// Roles cannot be destroyed when attached to an existing Instance Profile
resp, err := iamconn.ListInstanceProfilesForRole(&iam.ListInstanceProfilesForRoleInput{
RoleName: aws.String(d.Id()),
})
if err != nil {
return fmt.Errorf("Error listing Profiles for IAM Role (%s) when trying to delete: %s", d.Id(), err)
}
// Loop and remove this Role from any Profiles
if len(resp.InstanceProfiles) > 0 {
for _, i := range resp.InstanceProfiles {
_, err := iamconn.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
InstanceProfileName: i.InstanceProfileName,
RoleName: aws.String(d.Id()),
})
if err != nil {
return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
}
}
}
request := &iam.DeleteRoleInput{
RoleName: aws.String(d.Id()),
}

View File

@ -5,9 +5,9 @@ import (
"net/url"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSIAMRolePolicy(t *testing.T) {
func TestAccAWSIAMRolePolicy_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSRole_normal(t *testing.T) {
func TestAccAWSRole_basic(t *testing.T) {
var conf iam.GetRoleOutput
resource.Test(t, resource.TestCase{
@ -30,6 +30,31 @@ func TestAccAWSRole_normal(t *testing.T) {
})
}
func TestAccAWSRole_testNameChange(t *testing.T) {
var conf iam.GetRoleOutput
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRoleDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSRolePre,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRoleExists("aws_iam_role.role_update_test", &conf),
),
},
resource.TestStep{
Config: testAccAWSRolePost,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRoleExists("aws_iam_role.role_update_test", &conf),
),
},
},
})
}
func testAccCheckAWSRoleDestroy(s *terraform.State) error {
iamconn := testAccProvider.Meta().(*AWSClient).iamconn
@ -105,3 +130,101 @@ resource "aws_iam_role" "role" {
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"ec2.amazonaws.com\"]},\"Action\":[\"sts:AssumeRole\"]}]}"
}
`
const testAccAWSRolePre = `
resource "aws_iam_role" "role_update_test" {
name = "tf_old_name"
path = "/test/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "role_update_test" {
name = "role_update_test"
role = "${aws_iam_role.role_update_test.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
}
]
}
EOF
}
resource "aws_iam_instance_profile" "role_update_test" {
name = "role_update_test"
path = "/test/"
roles = ["${aws_iam_role.role_update_test.name}"]
}
`
const testAccAWSRolePost = `
resource "aws_iam_role" "role_update_test" {
name = "tf_new_name"
path = "/test/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "role_update_test" {
name = "role_update_test"
role = "${aws_iam_role.role_update_test.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
}
]
}
EOF
}
resource "aws_iam_instance_profile" "role_update_test" {
name = "role_update_test"
path = "/test/"
roles = ["${aws_iam_role.role_update_test.name}"]
}
`

View File

@ -6,9 +6,9 @@ import (
"fmt"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -7,8 +7,8 @@ import (
"testing"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -3,9 +3,9 @@ package aws
import (
"fmt"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -5,9 +5,9 @@ import (
"net/url"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSIAMUserPolicy(t *testing.T) {
func TestAccAWSIAMUserPolicy_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSUser_normal(t *testing.T) {
func TestAccAWSUser_basic(t *testing.T) {
var conf iam.GetUserOutput
resource.Test(t, resource.TestCase{

View File

@ -10,9 +10,10 @@ import (
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
@ -37,8 +38,8 @@ func resourceAwsInstance() *schema.Resource {
"associate_public_ip_address": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Optional: true,
},
"availability_zone": &schema.Schema{
@ -85,6 +86,7 @@ func resourceAwsInstance() *schema.Resource {
"source_dest_check": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"user_data": &schema.Schema{
@ -312,214 +314,32 @@ func resourceAwsInstance() *schema.Resource {
func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
// Figure out user data
userData := ""
if v := d.Get("user_data"); v != nil {
userData = base64.StdEncoding.EncodeToString([]byte(v.(string)))
}
// check for non-default Subnet, and cast it to a String
var hasSubnet bool
subnet, hasSubnet := d.GetOk("subnet_id")
subnetID := subnet.(string)
placement := &ec2.Placement{
AvailabilityZone: aws.String(d.Get("availability_zone").(string)),
GroupName: aws.String(d.Get("placement_group").(string)),
}
if hasSubnet {
// Tenancy is only valid inside a VPC
// See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Placement.html
if v := d.Get("tenancy").(string); v != "" {
placement.Tenancy = aws.String(v)
}
}
iam := &ec2.IAMInstanceProfileSpecification{
Name: aws.String(d.Get("iam_instance_profile").(string)),
instanceOpts, err := buildAwsInstanceOpts(d, meta)
if err != nil {
return err
}
// Build the creation struct
runOpts := &ec2.RunInstancesInput{
ImageID: aws.String(d.Get("ami").(string)),
Placement: placement,
InstanceType: aws.String(d.Get("instance_type").(string)),
BlockDeviceMappings: instanceOpts.BlockDeviceMappings,
DisableAPITermination: instanceOpts.DisableAPITermination,
EBSOptimized: instanceOpts.EBSOptimized,
IAMInstanceProfile: instanceOpts.IAMInstanceProfile,
ImageID: instanceOpts.ImageID,
InstanceType: instanceOpts.InstanceType,
MaxCount: aws.Long(int64(1)),
MinCount: aws.Long(int64(1)),
UserData: aws.String(userData),
EBSOptimized: aws.Boolean(d.Get("ebs_optimized").(bool)),
DisableAPITermination: aws.Boolean(d.Get("disable_api_termination").(bool)),
IAMInstanceProfile: iam,
}
associatePublicIPAddress := false
if v := d.Get("associate_public_ip_address"); v != nil {
associatePublicIPAddress = v.(bool)
}
var groups []*string
if v := d.Get("security_groups"); v != nil {
// Security group names.
// For a nondefault VPC, you must use security group IDs instead.
// See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html
sgs := v.(*schema.Set).List()
if len(sgs) > 0 && hasSubnet {
log.Printf("[WARN] Deprecated. Attempting to use 'security_groups' within a VPC instance. Use 'vpc_security_group_ids' instead.")
}
for _, v := range sgs {
str := v.(string)
groups = append(groups, aws.String(str))
}
}
if hasSubnet && associatePublicIPAddress {
// If we have a non-default VPC / Subnet specified, we can flag
// AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided.
// You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise
// you get: Network interfaces and an instance-level subnet ID may not be specified on the same request
// You also need to attach Security Groups to the NetworkInterface instead of the instance,
// to avoid: Network interfaces and an instance-level security groups may not be specified on
// the same request
ni := &ec2.InstanceNetworkInterfaceSpecification{
AssociatePublicIPAddress: aws.Boolean(associatePublicIPAddress),
DeviceIndex: aws.Long(int64(0)),
SubnetID: aws.String(subnetID),
Groups: groups,
}
if v, ok := d.GetOk("private_ip"); ok {
ni.PrivateIPAddress = aws.String(v.(string))
}
if v := d.Get("vpc_security_group_ids"); v != nil {
for _, v := range v.(*schema.Set).List() {
ni.Groups = append(ni.Groups, aws.String(v.(string)))
}
}
runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ni}
} else {
if subnetID != "" {
runOpts.SubnetID = aws.String(subnetID)
}
if v, ok := d.GetOk("private_ip"); ok {
runOpts.PrivateIPAddress = aws.String(v.(string))
}
if runOpts.SubnetID != nil &&
*runOpts.SubnetID != "" {
runOpts.SecurityGroupIDs = groups
} else {
runOpts.SecurityGroups = groups
}
if v := d.Get("vpc_security_group_ids"); v != nil {
for _, v := range v.(*schema.Set).List() {
runOpts.SecurityGroupIDs = append(runOpts.SecurityGroupIDs, aws.String(v.(string)))
}
}
}
if v, ok := d.GetOk("key_name"); ok {
runOpts.KeyName = aws.String(v.(string))
}
blockDevices := make([]*ec2.BlockDeviceMapping, 0)
if v, ok := d.GetOk("ebs_block_device"); ok {
vL := v.(*schema.Set).List()
for _, v := range vL {
bd := v.(map[string]interface{})
ebs := &ec2.EBSBlockDevice{
DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)),
}
if v, ok := bd["snapshot_id"].(string); ok && v != "" {
ebs.SnapshotID = aws.String(v)
}
if v, ok := bd["encrypted"].(bool); ok && v {
ebs.Encrypted = aws.Boolean(v)
}
if v, ok := bd["volume_size"].(int); ok && v != 0 {
ebs.VolumeSize = aws.Long(int64(v))
}
if v, ok := bd["volume_type"].(string); ok && v != "" {
ebs.VolumeType = aws.String(v)
}
if v, ok := bd["iops"].(int); ok && v > 0 {
ebs.IOPS = aws.Long(int64(v))
}
blockDevices = append(blockDevices, &ec2.BlockDeviceMapping{
DeviceName: aws.String(bd["device_name"].(string)),
EBS: ebs,
})
}
}
if v, ok := d.GetOk("ephemeral_block_device"); ok {
vL := v.(*schema.Set).List()
for _, v := range vL {
bd := v.(map[string]interface{})
blockDevices = append(blockDevices, &ec2.BlockDeviceMapping{
DeviceName: aws.String(bd["device_name"].(string)),
VirtualName: aws.String(bd["virtual_name"].(string)),
})
}
}
if v, ok := d.GetOk("root_block_device"); ok {
vL := v.(*schema.Set).List()
if len(vL) > 1 {
return fmt.Errorf("Cannot specify more than one root_block_device.")
}
for _, v := range vL {
bd := v.(map[string]interface{})
ebs := &ec2.EBSBlockDevice{
DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)),
}
if v, ok := bd["volume_size"].(int); ok && v != 0 {
ebs.VolumeSize = aws.Long(int64(v))
}
if v, ok := bd["volume_type"].(string); ok && v != "" {
ebs.VolumeType = aws.String(v)
}
if v, ok := bd["iops"].(int); ok && v > 0 {
ebs.IOPS = aws.Long(int64(v))
}
if dn, err := fetchRootDeviceName(d.Get("ami").(string), conn); err == nil {
if dn == nil {
return fmt.Errorf(
"Expected 1 AMI for ID: %s, got none",
d.Get("ami").(string))
}
blockDevices = append(blockDevices, &ec2.BlockDeviceMapping{
DeviceName: dn,
EBS: ebs,
})
} else {
return err
}
}
}
if len(blockDevices) > 0 {
runOpts.BlockDeviceMappings = blockDevices
NetworkInterfaces: instanceOpts.NetworkInterfaces,
Placement: instanceOpts.Placement,
PrivateIPAddress: instanceOpts.PrivateIPAddress,
SecurityGroupIDs: instanceOpts.SecurityGroupIDs,
SecurityGroups: instanceOpts.SecurityGroups,
SubnetID: instanceOpts.SubnetID,
UserData: instanceOpts.UserData64,
}
// Create the instance
log.Printf("[DEBUG] Run configuration: %#v", runOpts)
var err error
log.Printf("[DEBUG] Run configuration: %s", awsutil.StringValue(runOpts))
var runResp *ec2.Reservation
for i := 0; i < 5; i++ {
@ -755,32 +575,8 @@ func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceAwsInstanceDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
log.Printf("[INFO] Terminating instance: %s", d.Id())
req := &ec2.TerminateInstancesInput{
InstanceIDs: []*string{aws.String(d.Id())},
}
if _, err := conn.TerminateInstances(req); err != nil {
return fmt.Errorf("Error terminating instance: %s", err)
}
log.Printf(
"[DEBUG] Waiting for instance (%s) to become terminated",
d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{"pending", "running", "shutting-down", "stopped", "stopping"},
Target: "terminated",
Refresh: InstanceStateRefreshFunc(conn, d.Id()),
Timeout: 10 * time.Minute,
Delay: 10 * time.Second,
MinTimeout: 3 * time.Second,
}
_, err := stateConf.WaitForState()
if err != nil {
return fmt.Errorf(
"Error waiting for instance (%s) to terminate: %s",
d.Id(), err)
if err := awsTerminateInstance(conn, d.Id()); err != nil {
return err
}
d.SetId("")
@ -925,3 +721,261 @@ func fetchRootDeviceName(ami string, conn *ec2.EC2) (*string, error) {
return nil, err
}
}
func readBlockDeviceMappingsFromConfig(
d *schema.ResourceData, conn *ec2.EC2) ([]*ec2.BlockDeviceMapping, error) {
blockDevices := make([]*ec2.BlockDeviceMapping, 0)
if v, ok := d.GetOk("ebs_block_device"); ok {
vL := v.(*schema.Set).List()
for _, v := range vL {
bd := v.(map[string]interface{})
ebs := &ec2.EBSBlockDevice{
DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)),
}
if v, ok := bd["snapshot_id"].(string); ok && v != "" {
ebs.SnapshotID = aws.String(v)
}
if v, ok := bd["encrypted"].(bool); ok && v {
ebs.Encrypted = aws.Boolean(v)
}
if v, ok := bd["volume_size"].(int); ok && v != 0 {
ebs.VolumeSize = aws.Long(int64(v))
}
if v, ok := bd["volume_type"].(string); ok && v != "" {
ebs.VolumeType = aws.String(v)
}
if v, ok := bd["iops"].(int); ok && v > 0 {
ebs.IOPS = aws.Long(int64(v))
}
blockDevices = append(blockDevices, &ec2.BlockDeviceMapping{
DeviceName: aws.String(bd["device_name"].(string)),
EBS: ebs,
})
}
}
if v, ok := d.GetOk("ephemeral_block_device"); ok {
vL := v.(*schema.Set).List()
for _, v := range vL {
bd := v.(map[string]interface{})
blockDevices = append(blockDevices, &ec2.BlockDeviceMapping{
DeviceName: aws.String(bd["device_name"].(string)),
VirtualName: aws.String(bd["virtual_name"].(string)),
})
}
}
if v, ok := d.GetOk("root_block_device"); ok {
vL := v.(*schema.Set).List()
if len(vL) > 1 {
return nil, fmt.Errorf("Cannot specify more than one root_block_device.")
}
for _, v := range vL {
bd := v.(map[string]interface{})
ebs := &ec2.EBSBlockDevice{
DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)),
}
if v, ok := bd["volume_size"].(int); ok && v != 0 {
ebs.VolumeSize = aws.Long(int64(v))
}
if v, ok := bd["volume_type"].(string); ok && v != "" {
ebs.VolumeType = aws.String(v)
}
if v, ok := bd["iops"].(int); ok && v > 0 {
ebs.IOPS = aws.Long(int64(v))
}
if dn, err := fetchRootDeviceName(d.Get("ami").(string), conn); err == nil {
if dn == nil {
return nil, fmt.Errorf(
"Expected 1 AMI for ID: %s, got none",
d.Get("ami").(string))
}
blockDevices = append(blockDevices, &ec2.BlockDeviceMapping{
DeviceName: dn,
EBS: ebs,
})
} else {
return nil, err
}
}
}
return blockDevices, nil
}
type awsInstanceOpts struct {
BlockDeviceMappings []*ec2.BlockDeviceMapping
DisableAPITermination *bool
EBSOptimized *bool
IAMInstanceProfile *ec2.IAMInstanceProfileSpecification
ImageID *string
InstanceType *string
KeyName *string
NetworkInterfaces []*ec2.InstanceNetworkInterfaceSpecification
Placement *ec2.Placement
PrivateIPAddress *string
SecurityGroupIDs []*string
SecurityGroups []*string
SpotPlacement *ec2.SpotPlacement
SubnetID *string
UserData64 *string
}
func buildAwsInstanceOpts(
d *schema.ResourceData, meta interface{}) (*awsInstanceOpts, error) {
conn := meta.(*AWSClient).ec2conn
opts := &awsInstanceOpts{
DisableAPITermination: aws.Boolean(d.Get("disable_api_termination").(bool)),
EBSOptimized: aws.Boolean(d.Get("ebs_optimized").(bool)),
ImageID: aws.String(d.Get("ami").(string)),
InstanceType: aws.String(d.Get("instance_type").(string)),
}
opts.IAMInstanceProfile = &ec2.IAMInstanceProfileSpecification{
Name: aws.String(d.Get("iam_instance_profile").(string)),
}
opts.UserData64 = aws.String(
base64.StdEncoding.EncodeToString([]byte(d.Get("user_data").(string))))
// check for non-default Subnet, and cast it to a String
subnet, hasSubnet := d.GetOk("subnet_id")
subnetID := subnet.(string)
// Placement is used for aws_instance; SpotPlacement is used for
// aws_spot_instance_request. They represent the same data. :-|
opts.Placement = &ec2.Placement{
AvailabilityZone: aws.String(d.Get("availability_zone").(string)),
GroupName: aws.String(d.Get("placement_group").(string)),
}
opts.SpotPlacement = &ec2.SpotPlacement{
AvailabilityZone: aws.String(d.Get("availability_zone").(string)),
GroupName: aws.String(d.Get("placement_group").(string)),
}
if v := d.Get("tenancy").(string); v != "" {
opts.Placement.Tenancy = aws.String(v)
}
associatePublicIPAddress := d.Get("associate_public_ip_address").(bool)
var groups []*string
if v := d.Get("security_groups"); v != nil {
// Security group names.
// For a nondefault VPC, you must use security group IDs instead.
// See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html
sgs := v.(*schema.Set).List()
if len(sgs) > 0 && hasSubnet {
log.Printf("[WARN] Deprecated. Attempting to use 'security_groups' within a VPC instance. Use 'vpc_security_group_ids' instead.")
}
for _, v := range sgs {
str := v.(string)
groups = append(groups, aws.String(str))
}
}
if hasSubnet && associatePublicIPAddress {
// If we have a non-default VPC / Subnet specified, we can flag
// AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided.
// You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise
// you get: Network interfaces and an instance-level subnet ID may not be specified on the same request
// You also need to attach Security Groups to the NetworkInterface instead of the instance,
// to avoid: Network interfaces and an instance-level security groups may not be specified on
// the same request
ni := &ec2.InstanceNetworkInterfaceSpecification{
AssociatePublicIPAddress: aws.Boolean(associatePublicIPAddress),
DeviceIndex: aws.Long(int64(0)),
SubnetID: aws.String(subnetID),
Groups: groups,
}
if v, ok := d.GetOk("private_ip"); ok {
ni.PrivateIPAddress = aws.String(v.(string))
}
if v := d.Get("vpc_security_group_ids"); v != nil {
for _, v := range v.(*schema.Set).List() {
ni.Groups = append(ni.Groups, aws.String(v.(string)))
}
}
opts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ni}
} else {
if subnetID != "" {
opts.SubnetID = aws.String(subnetID)
}
if v, ok := d.GetOk("private_ip"); ok {
opts.PrivateIPAddress = aws.String(v.(string))
}
if opts.SubnetID != nil &&
*opts.SubnetID != "" {
opts.SecurityGroupIDs = groups
} else {
opts.SecurityGroups = groups
}
if v := d.Get("vpc_security_group_ids"); v != nil {
for _, v := range v.(*schema.Set).List() {
opts.SecurityGroupIDs = append(opts.SecurityGroupIDs, aws.String(v.(string)))
}
}
}
if v, ok := d.GetOk("key_name"); ok {
opts.KeyName = aws.String(v.(string))
}
blockDevices, err := readBlockDeviceMappingsFromConfig(d, conn)
if err != nil {
return nil, err
}
if len(blockDevices) > 0 {
opts.BlockDeviceMappings = blockDevices
}
return opts, nil
}
func awsTerminateInstance(conn *ec2.EC2, id string) error {
log.Printf("[INFO] Terminating instance: %s", id)
req := &ec2.TerminateInstancesInput{
InstanceIDs: []*string{aws.String(id)},
}
if _, err := conn.TerminateInstances(req); err != nil {
return fmt.Errorf("Error terminating instance: %s", err)
}
log.Printf("[DEBUG] Waiting for instance (%s) to become terminated", id)
stateConf := &resource.StateChangeConf{
Pending: []string{"pending", "running", "shutting-down", "stopped", "stopping"},
Target: "terminated",
Refresh: InstanceStateRefreshFunc(conn, id),
Timeout: 10 * time.Minute,
Delay: 10 * time.Second,
MinTimeout: 3 * time.Second,
}
_, err := stateConf.WaitForState()
if err != nil {
return fmt.Errorf(
"Error waiting for instance (%s) to terminate: %s", id, err)
}
return nil
}

View File

@ -5,15 +5,15 @@ import (
"reflect"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSInstance_normal(t *testing.T) {
func TestAccAWSInstance_basic(t *testing.T) {
var v ec2.Instance
var vol *ec2.Volume
@ -653,7 +653,6 @@ resource "aws_instance" "foo" {
ami = "ami-4fccb37f"
instance_type = "m1.small"
subnet_id = "${aws_subnet.foo.id}"
source_dest_check = true
}
`

View File

@ -5,9 +5,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,9 +4,9 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -6,9 +6,9 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
)
func resourceAwsKeyPair() *schema.Resource {

View File

@ -5,14 +5,14 @@ import (
"strings"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSKeyPair_normal(t *testing.T) {
func TestAccAWSKeyPair_basic(t *testing.T) {
var conf ec2.KeyPairInfo
resource.Test(t, resource.TestCase{

View File

@ -4,9 +4,9 @@ import (
"fmt"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/kinesis"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/kinesis"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -7,8 +7,8 @@ import (
"testing"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/kinesis"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/kinesis"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -8,9 +8,9 @@ import (
"strings"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/hashicorp/terraform/helper/schema"
)
@ -131,7 +131,6 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
if err != nil {
return fmt.Errorf("Error creating Lambda function: %s", err)
}
// Add retry wrapper around this
d.SetId(d.Get("function_name").(string))

View File

@ -5,8 +5,8 @@ import (
"testing"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -9,10 +9,10 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -7,13 +7,33 @@ import (
"testing"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSLaunchConfiguration_basic(t *testing.T) {
var conf autoscaling.LaunchConfiguration
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSLaunchConfigurationNoNameConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
"aws_launch_configuration.bar", "terraform-"),
),
},
},
})
}
func TestAccAWSLaunchConfiguration_withBlockDevices(t *testing.T) {
var conf autoscaling.LaunchConfiguration
@ -61,26 +81,6 @@ func TestAccAWSLaunchConfiguration_withSpotPrice(t *testing.T) {
})
}
func TestAccAWSLaunchConfiguration_withGeneratedName(t *testing.T) {
var conf autoscaling.LaunchConfiguration
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSLaunchConfigurationNoNameConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf),
testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
"aws_launch_configuration.bar", "terraform-"),
),
},
},
})
}
func testAccCheckAWSLaunchConfigurationGeneratedNamePrefix(
resource, prefix string) resource.TestCheckFunc {
return func(s *terraform.State) error {

View File

@ -4,9 +4,9 @@ import (
"fmt"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAwsLBCookieStickinessPolicy(t *testing.T) {
func TestAccAwsLBCookieStickinessPolicy_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -4,8 +4,8 @@ import (
"fmt"
"log"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -8,7 +8,7 @@ import (
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSMainRouteTableAssociation(t *testing.T) {
func TestAccAWSMainRouteTableAssociation_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -8,9 +8,9 @@ import (
"strconv"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -4,9 +4,9 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -7,9 +7,9 @@ import (
"strconv"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
@ -78,9 +78,17 @@ func resourceAwsNetworkInterfaceCreate(d *schema.ResourceData, meta interface{})
conn := meta.(*AWSClient).ec2conn
request := &ec2.CreateNetworkInterfaceInput{
Groups: expandStringList(d.Get("security_groups").(*schema.Set).List()),
SubnetID: aws.String(d.Get("subnet_id").(string)),
PrivateIPAddresses: expandPrivateIPAddesses(d.Get("private_ips").(*schema.Set).List()),
SubnetID: aws.String(d.Get("subnet_id").(string)),
}
security_groups := d.Get("security_groups").(*schema.Set).List()
if len(security_groups) != 0 {
request.Groups = expandStringList(security_groups)
}
private_ips := d.Get("private_ips").(*schema.Set).List()
if len(private_ips) != 0 {
request.PrivateIPAddresses = expandPrivateIPAddesses(private_ips)
}
log.Printf("[DEBUG] Creating network interface")

View File

@ -4,9 +4,9 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

View File

@ -6,8 +6,8 @@ import (
"strconv"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -8,7 +8,7 @@ import (
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSProxyProtocolPolicy(t *testing.T) {
func TestAccAWSProxyProtocolPolicy_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,

View File

@ -11,9 +11,9 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/route53"
)
func resourceAwsRoute53Record() *schema.Resource {

View File

@ -8,8 +8,8 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
)
func TestCleanRecordName(t *testing.T) {

View File

@ -10,9 +10,9 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/route53"
)
func resourceAwsRoute53Zone() *schema.Resource {

View File

@ -9,9 +9,9 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/route53"
)
func resourceAwsRoute53ZoneAssociation() *schema.Resource {

View File

@ -8,8 +8,8 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
)
func TestAccRoute53ZoneAssociation_basic(t *testing.T) {

View File

@ -9,8 +9,8 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/route53"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
)
func TestCleanPrefix(t *testing.T) {

View File

@ -6,9 +6,9 @@ import (
"log"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
@ -361,7 +361,10 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error
func resourceAwsRouteTableHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["cidr_block"].(string)))
if v, ok := m["cidr_block"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
if v, ok := m["gateway_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))

View File

@ -4,9 +4,9 @@ import (
"fmt"
"log"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/schema"
)

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSRouteTableAssociation(t *testing.T) {
func TestAccAWSRouteTableAssociation_basic(t *testing.T) {
var v, v2 ec2.RouteTable
resource.Test(t, resource.TestCase{

View File

@ -4,14 +4,14 @@ import (
"fmt"
"testing"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSRouteTable_normal(t *testing.T) {
func TestAccAWSRouteTable_basic(t *testing.T) {
var v ec2.RouteTable
testCheck := func(*terraform.State) error {

View File

@ -7,9 +7,9 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
)
func resourceAwsS3Bucket() *schema.Resource {
@ -433,6 +433,13 @@ func websiteEndpoint(s3conn *s3.S3, d *schema.ResourceData) (string, error) {
func WebsiteEndpointUrl(bucket string, region string) string {
region = normalizeRegion(region)
// Frankfurt(and probably future) regions uses different syntax for website endpoints
// http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html
if region == "eu-central-1" {
return fmt.Sprintf("%s.s3-website.%s.amazonaws.com", bucket, region)
}
return fmt.Sprintf("%s.s3-website-%s.amazonaws.com", bucket, region)
}

View File

@ -12,8 +12,8 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
)
func TestAccAWSS3Bucket_basic(t *testing.T) {

View File

@ -7,9 +7,9 @@ import (
"sort"
"time"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

View File

@ -7,9 +7,9 @@ import (
"sort"
"strings"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/aws/awserr"
"github.com/awslabs/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)

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