Skip to content

Commit

Permalink
Merge upstream 1.26 to master
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Duchesne committed Jul 4, 2018
2 parents 0e760d6 + 7b7d817 commit 6e0f9c1
Show file tree
Hide file tree
Showing 93 changed files with 5,399 additions and 1,025 deletions.
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
## 1.26.0 (July 04, 2018)

FEATURES:

* **New Data Source:** `aws_launch_configuration` ([#3624](https://github.com/terraform-providers/terraform-provider-aws/issues/3624))
* **New Data Source:** `aws_pricing_product` ([#5057](https://github.com/terraform-providers/terraform-provider-aws/issues/5057))
* **New Resource:** `aws_s3_bucket_inventory` ([#5019](https://github.com/terraform-providers/terraform-provider-aws/issues/5019))
* **New Resource:** `aws_vpc_ipv4_cidr_block_association` ([#3723](https://github.com/terraform-providers/terraform-provider-aws/issues/3723))

ENHANCEMENTS:

* data-source/aws_elasticache_replication_group: Add `member_clusters` attribute ([#5056](https://github.com/terraform-providers/terraform-provider-aws/issues/5056))
* data-source/aws_instances: Add `instance_state_names` argument (support non-`running` instances) ([#4950](https://github.com/terraform-providers/terraform-provider-aws/issues/4950))
* data-source/aws_route_tables: Add `filter` argument ([#5035](https://github.com/terraform-providers/terraform-provider-aws/issues/5035))
* data-source/aws_subnet_ids: Add `filter` argument ([#5038](https://github.com/terraform-providers/terraform-provider-aws/issues/5038))
* resource/aws_eip_association: Support resource import ([#5006](https://github.com/terraform-providers/terraform-provider-aws/issues/5006))
* resource/aws_elasticache_replication_group: Add `member_clusters` attribute ([#5056](https://github.com/terraform-providers/terraform-provider-aws/issues/5056))
* resource/aws_lambda_alias: Add `routing_config` argument (support traffic shifting) ([#3316](https://github.com/terraform-providers/terraform-provider-aws/issues/3316))
* resource/aws_lambda_event_source_mapping: Make `starting_position` optional and allow `batch_size` to support default of 10 for SQS ([#5024](https://github.com/terraform-providers/terraform-provider-aws/issues/5024))
* resource/aws_network_acl_rule: Add plan time conflict validation with `cidr_block` and `ipv6_cidr_block` ([#3951](https://github.com/terraform-providers/terraform-provider-aws/issues/3951))
* resource/aws_spot_fleet_request: Add `fleet_type` argument ([#5032](https://github.com/terraform-providers/terraform-provider-aws/issues/5032))
* resource/aws_ssm_document: Add `tags` argument (support tagging) ([#5020](https://github.com/terraform-providers/terraform-provider-aws/issues/5020))

BUG FIXES:

* resource/aws_codebuild_project: Prevent panic with missing environment variable type ([#5052](https://github.com/terraform-providers/terraform-provider-aws/issues/5052))
* resource/aws_kms_alias: Fix perpetual plan when `target_key_id` is ARN ([#4010](https://github.com/terraform-providers/terraform-provider-aws/issues/4010))

## 1.25.0 (June 27, 2018)

NOTES:
Expand Down
144 changes: 144 additions & 0 deletions aws/aws_vpc_ipv4_cidr_block_association.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package aws

import (
"fmt"
"log"
"time"

"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/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

const (
VpcCidrBlockStateCodeDeleted = "deleted"
)

func resourceAwsVpcIpv4CidrBlockAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceAwsVpcIpv4CidrBlockAssociationCreate,
Read: resourceAwsVpcIpv4CidrBlockAssociationRead,
Delete: resourceAwsVpcIpv4CidrBlockAssociationDelete,

Schema: map[string]*schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"cidr_block": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.CIDRNetwork(16, 28), // The allowed block size is between a /28 netmask and /16 netmask.
},
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},
}
}

func resourceAwsVpcIpv4CidrBlockAssociationCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

req := &ec2.AssociateVpcCidrBlockInput{
VpcId: aws.String(d.Get("vpc_id").(string)),
CidrBlock: aws.String(d.Get("cidr_block").(string)),
}
log.Printf("[DEBUG] Creating VPC IPv4 CIDR block association: %#v", req)
resp, err := conn.AssociateVpcCidrBlock(req)
if err != nil {
return fmt.Errorf("Error creating VPC IPv4 CIDR block association: %s", err)
}

d.SetId(aws.StringValue(resp.CidrBlockAssociation.AssociationId))

stateConf := &resource.StateChangeConf{
Pending: []string{ec2.VpcCidrBlockStateCodeAssociating},
Target: []string{ec2.VpcCidrBlockStateCodeAssociated},
Refresh: vpcIpv4CidrBlockAssociationStateRefresh(conn, d.Get("vpc_id").(string), d.Id()),
Timeout: d.Timeout(schema.TimeoutCreate),
Delay: 10 * time.Second,
MinTimeout: 5 * time.Second,
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for IPv4 CIDR block association (%s) to become available: %s", d.Id(), err)
}

return resourceAwsVpcIpv4CidrBlockAssociationRead(d, meta)
}

func resourceAwsVpcIpv4CidrBlockAssociationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

assocRaw, state, err := vpcIpv4CidrBlockAssociationStateRefresh(conn, d.Get("vpc_id").(string), d.Id())()
if err != nil {
return fmt.Errorf("Error reading IPv4 CIDR block association: %s", err)
}
if state == VpcCidrBlockStateCodeDeleted {
log.Printf("[WARN] IPv4 CIDR block association (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

assoc := assocRaw.(*ec2.VpcCidrBlockAssociation)
d.Set("cidr_block", assoc.CidrBlock)

return nil
}

func resourceAwsVpcIpv4CidrBlockAssociationDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

log.Printf("[DEBUG] Deleting VPC IPv4 CIDR block association: %s", d.Id())
_, err := conn.DisassociateVpcCidrBlock(&ec2.DisassociateVpcCidrBlockInput{
AssociationId: aws.String(d.Id()),
})
if err != nil {
if isAWSErr(err, "InvalidVpcID.NotFound", "") {
return nil
}
return fmt.Errorf("Error deleting VPC IPv4 CIDR block association: %s", err)
}

stateConf := &resource.StateChangeConf{
Pending: []string{ec2.VpcCidrBlockStateCodeDisassociating},
Target: []string{ec2.VpcCidrBlockStateCodeDisassociated, VpcCidrBlockStateCodeDeleted},
Refresh: vpcIpv4CidrBlockAssociationStateRefresh(conn, d.Get("vpc_id").(string), d.Id()),
Timeout: d.Timeout(schema.TimeoutDelete),
Delay: 10 * time.Second,
MinTimeout: 5 * time.Second,
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for VPC IPv4 CIDR block association (%s) to be deleted: %s", d.Id(), err.Error())
}

return nil
}

func vpcIpv4CidrBlockAssociationStateRefresh(conn *ec2.EC2, vpcId, assocId string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
vpc, err := vpcDescribe(conn, vpcId)
if err != nil {
return nil, "", err
}

if vpc != nil {
for _, cidrAssociation := range vpc.CidrBlockAssociationSet {
if aws.StringValue(cidrAssociation.AssociationId) == assocId {
return cidrAssociation, aws.StringValue(cidrAssociation.CidrBlockState.State), nil
}
}
}

return "", VpcCidrBlockStateCodeDeleted, nil
}
}
141 changes: 141 additions & 0 deletions aws/aws_vpc_ipv4_cidr_block_association_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package aws

import (
"fmt"
"testing"

"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 TestAccAwsVpcIpv4CidrBlockAssociation_basic(t *testing.T) {
var associationSecondary, associationTertiary ec2.VpcCidrBlockAssociation

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsVpcIpv4CidrBlockAssociationDestroy,
Steps: []resource.TestStep{
{
Config: testAccAwsVpcIpv4CidrBlockAssociationConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsVpcIpv4CidrBlockAssociationExists("aws_vpc_ipv4_cidr_block_association.secondary_cidr", &associationSecondary),
testAccCheckAdditionalAwsVpcIpv4CidrBlock(&associationSecondary, "172.2.0.0/16"),
testAccCheckAwsVpcIpv4CidrBlockAssociationExists("aws_vpc_ipv4_cidr_block_association.tertiary_cidr", &associationTertiary),
testAccCheckAdditionalAwsVpcIpv4CidrBlock(&associationTertiary, "170.2.0.0/16"),
),
},
},
})
}

func testAccCheckAdditionalAwsVpcIpv4CidrBlock(association *ec2.VpcCidrBlockAssociation, expected string) resource.TestCheckFunc {
return func(s *terraform.State) error {
CIDRBlock := association.CidrBlock
if *CIDRBlock != expected {
return fmt.Errorf("Bad CIDR: %s", *association.CidrBlock)
}

return nil
}
}

func testAccCheckAwsVpcIpv4CidrBlockAssociationDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_vpc_ipv4_cidr_block_association" {
continue
}

// Try to find the VPC
DescribeVpcOpts := &ec2.DescribeVpcsInput{
VpcIds: []*string{aws.String(rs.Primary.Attributes["vpc_id"])},
}
resp, err := conn.DescribeVpcs(DescribeVpcOpts)
if err == nil {
vpc := resp.Vpcs[0]

for _, ipv4Association := range vpc.CidrBlockAssociationSet {
if *ipv4Association.AssociationId == rs.Primary.ID {
return fmt.Errorf("VPC CIDR block association still exists")
}
}

return nil
}

// Verify the error is what we want
ec2err, ok := err.(awserr.Error)
if !ok {
return err
}
if ec2err.Code() != "InvalidVpcID.NotFound" {
return err
}
}

return nil
}

func testAccCheckAwsVpcIpv4CidrBlockAssociationExists(n string, association *ec2.VpcCidrBlockAssociation) 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 VPC ID is set")
}

conn := testAccProvider.Meta().(*AWSClient).ec2conn
DescribeVpcOpts := &ec2.DescribeVpcsInput{
VpcIds: []*string{aws.String(rs.Primary.Attributes["vpc_id"])},
}
resp, err := conn.DescribeVpcs(DescribeVpcOpts)
if err != nil {
return err
}
if len(resp.Vpcs) == 0 {
return fmt.Errorf("VPC not found")
}

vpc := resp.Vpcs[0]
found := false
for _, cidrAssociation := range vpc.CidrBlockAssociationSet {
if *cidrAssociation.AssociationId == rs.Primary.ID {
*association = *cidrAssociation
found = true
}
}

if !found {
return fmt.Errorf("VPC CIDR block association not found")
}

return nil
}
}

const testAccAwsVpcIpv4CidrBlockAssociationConfig = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
tags {
Name = "terraform-testacc-vpc-ipv4-cidr-block-association"
}
}
resource "aws_vpc_ipv4_cidr_block_association" "secondary_cidr" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "172.2.0.0/16"
}
resource "aws_vpc_ipv4_cidr_block_association" "tertiary_cidr" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "170.2.0.0/16"
}
`
3 changes: 3 additions & 0 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import (
"github.com/aws/aws-sdk-go/service/neptune"
"github.com/aws/aws-sdk-go/service/opsworks"
"github.com/aws/aws-sdk-go/service/organizations"
"github.com/aws/aws-sdk-go/service/pricing"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/aws/aws-sdk-go/service/route53"
Expand Down Expand Up @@ -232,6 +233,7 @@ type AWSClient struct {
lexmodelconn *lexmodelbuildingservice.LexModelBuildingService
budgetconn *budgets.Budgets
neptuneconn *neptune.Neptune
pricingconn *pricing.Pricing
}

func (c *AWSClient) S3() *s3.S3 {
Expand Down Expand Up @@ -528,6 +530,7 @@ func (c *Config) Client() (interface{}, error) {
client.mediastoreconn = mediastore.New(sess)
client.appsyncconn = appsync.New(sess)
client.neptuneconn = neptune.New(sess)
client.pricingconn = pricing.New(sess)

// Workaround for https://github.com/aws/aws-sdk-go/issues/1376
client.kinesisconn.Handlers.Retry.PushBack(func(r *request.Request) {
Expand Down
4 changes: 2 additions & 2 deletions aws/data_source_aws_ecs_container_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ func dataSourceAwsEcsContainerDefinition() *schema.Resource {
"docker_labels": {
Type: schema.TypeMap,
Computed: true,
Elem: schema.TypeString,
Elem: &schema.Schema{Type: schema.TypeString},
},
"environment": {
Type: schema.TypeMap,
Computed: true,
Elem: schema.TypeString,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
Expand Down
9 changes: 9 additions & 0 deletions aws/data_source_aws_elasticache_replication_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ func dataSourceAwsElasticacheReplicationGroup() *schema.Resource {
Type: schema.TypeInt,
Computed: true,
},
"member_clusters": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"node_type": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -106,6 +112,9 @@ func dataSourceAwsElasticacheReplicationGroupRead(d *schema.ResourceData, meta i
d.Set("primary_endpoint_address", rg.NodeGroups[0].PrimaryEndpoint.Address)
}
d.Set("number_cache_clusters", len(rg.MemberClusters))
if err := d.Set("member_clusters", flattenStringList(rg.MemberClusters)); err != nil {
return fmt.Errorf("error setting member_clusters: %s", err)
}
d.Set("node_type", rg.CacheNodeType)
d.Set("snapshot_window", rg.SnapshotWindow)
d.Set("snapshot_retention_limit", rg.SnapshotRetentionLimit)
Expand Down
Loading

0 comments on commit 6e0f9c1

Please sign in to comment.