Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow vpc_peering_connection #963

Merged
merged 3 commits into from
Feb 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func Provider() terraform.ResourceProvider {
"aws_security_group": resourceAwsSecurityGroup(),
"aws_subnet": resourceAwsSubnet(),
"aws_vpc": resourceAwsVpc(),
"aws_vpc_peering_connection": resourceAwsVpcPeeringConnection(),
},

ConfigureFunc: providerConfigure,
Expand Down
19 changes: 15 additions & 4 deletions builtin/providers/aws/resource_aws_route_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ func resourceAwsRouteTable() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},

"vpc_peering_connection_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
},
Set: resourceAwsRouteTableHash,
Expand Down Expand Up @@ -125,6 +130,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error {

m["gateway_id"] = r.GatewayId
m["instance_id"] = r.InstanceId
m["vpc_peering_connection_id"] = r.VpcPeeringConnectionId

route.Add(m)
}
Expand Down Expand Up @@ -166,10 +172,11 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error
m := route.(map[string]interface{})

opts := ec2.CreateRoute{
RouteTableId: d.Id(),
DestinationCidrBlock: m["cidr_block"].(string),
GatewayId: m["gateway_id"].(string),
InstanceId: m["instance_id"].(string),
RouteTableId: d.Id(),
DestinationCidrBlock: m["cidr_block"].(string),
GatewayId: m["gateway_id"].(string),
InstanceId: m["instance_id"].(string),
VpcPeeringConnectionId: m["vpc_peering_connection_id"].(string),
}

_, err := ec2conn.CreateRoute(&opts)
Expand Down Expand Up @@ -257,6 +264,10 @@ func resourceAwsRouteTableHash(v interface{}) int {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

if v, ok := m["vpc_peering_connection_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

return hashcode.String(buf.String())
}

Expand Down
93 changes: 75 additions & 18 deletions builtin/providers/aws/resource_aws_route_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,27 +129,26 @@ func TestAccAWSRouteTable_tags(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckRouteTableDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRouteTableConfigTags,
Check: resource.ComposeTestCheckFunc(
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
testAccCheckTags(&route_table.Tags, "foo", "bar"),
),
},

resource.TestStep{
Config: testAccRouteTableConfigTagsUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
testAccCheckTags(&route_table.Tags, "foo", ""),
testAccCheckTags(&route_table.Tags, "bar", "baz"),
),
},
},
resource.TestStep{
Config: testAccRouteTableConfigTags,
Check: resource.ComposeTestCheckFunc(
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
testAccCheckTags(&route_table.Tags, "foo", "bar"),
),
},

resource.TestStep{
Config: testAccRouteTableConfigTagsUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
testAccCheckTags(&route_table.Tags, "foo", ""),
testAccCheckTags(&route_table.Tags, "bar", "baz"),
),
},
},
})
}


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

Expand Down Expand Up @@ -209,6 +208,45 @@ func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestChec
}
}

func TestAccAWSRouteTable_vpcPeering(t *testing.T) {
var v ec2.RouteTable

testCheck := func(*terraform.State) error {
if len(v.Routes) != 2 {
return fmt.Errorf("bad routes: %#v", v.Routes)
}

routes := make(map[string]ec2.Route)
for _, r := range v.Routes {
routes[r.DestinationCidrBlock] = r
}

if _, ok := routes["10.1.0.0/16"]; !ok {
return fmt.Errorf("bad routes: %#v", v.Routes)
}
if _, ok := routes["10.2.0.0/16"]; !ok {
return fmt.Errorf("bad routes: %#v", v.Routes)
}

return nil
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRouteTableDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRouteTableVpcPeeringConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckRouteTableExists(
"aws_route_table.foo", &v),
testCheck,
),
},
},
})
}

const testAccRouteTableConfig = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
Expand Down Expand Up @@ -306,3 +344,22 @@ resource "aws_route_table" "foo" {
}
}
`

const testAccRouteTableVpcPeeringConfig = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
}

resource "aws_internet_gateway" "foo" {
vpc_id = "${aws_vpc.foo.id}"
}

resource "aws_route_table" "foo" {
vpc_id = "${aws_vpc.foo.id}"

route {
cidr_block = "10.2.0.0/16"
vpc_peering_connection_id = "vpc-12345"
}
}
`
145 changes: 145 additions & 0 deletions builtin/providers/aws/resource_aws_vpc_peering_connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package aws

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/mitchellh/goamz/ec2"
)

func resourceAwsVpcPeeringConnection() *schema.Resource {
return &schema.Resource{
Create: resourceAwsVpcPeeringCreate,
Read: resourceAwsVpcPeeringRead,
Update: resourceAwsVpcPeeringUpdate,
Delete: resourceAwsVpcPeeringDelete,

Schema: map[string]*schema.Schema{
"peer_owner_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"peer_vpc_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vpc_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tagsSchema(),
},
}
}

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

// Create the vpc peering connection
createOpts := &ec2.CreateVpcPeeringConnection{
PeerOwnerId: d.Get("peer_owner_id").(string),
PeerVpcId: d.Get("peer_vpc_id").(string),
VpcId: d.Get("vpc_id").(string),
}
log.Printf("[DEBUG] VpcPeeringCreate create config: %#v", createOpts)
resp, err := ec2conn.CreateVpcPeeringConnection(createOpts)
if err != nil {
return fmt.Errorf("Error creating vpc peering connection: %s", err)
}

// Get the ID and store it
rt := &resp.VpcPeeringConnection
d.SetId(rt.VpcPeeringConnectionId)
log.Printf("[INFO] Vpc Peering Connection ID: %s", d.Id())

// Wait for the vpc peering connection to become available
log.Printf(
"[DEBUG] Waiting for vpc peering connection (%s) to become available",
d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{"pending"},
Target: "ready",
Refresh: resourceAwsVpcPeeringConnectionStateRefreshFunc(ec2conn, d.Id()),
Timeout: 1 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf(
"Error waiting for vpc peering (%s) to become available: %s",
d.Id(), err)
}

return nil
}

func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error {
ec2conn := meta.(*AWSClient).ec2conn
pcRaw, _, err := resourceAwsVpcPeeringConnectionStateRefreshFunc(ec2conn, d.Id())()
if err != nil {
return err
}
if pcRaw == nil {
d.SetId("")
return nil
}

pc := pcRaw.(*ec2.VpcPeeringConnection)

d.Set("peer_owner_id", pc.AccepterVpcInfo.OwnerId)
d.Set("peer_vpc_id", pc.AccepterVpcInfo.VpcId)
d.Set("vpc_id", pc.RequesterVpcInfo.VpcId)
d.Set("tags", tagsToMap(pc.Tags))

return nil
}

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

if err := setTags(ec2conn, d); err != nil {
return err
} else {
d.SetPartial("tags")
}

return resourceAwsRouteTableRead(d, meta)
}

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

_, err := ec2conn.DeleteVpcPeeringConnection(d.Id())
return err
}

// resourceAwsVpcPeeringConnectionStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a VpcPeeringConnection.
func resourceAwsVpcPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {

resp, err := conn.DescribeVpcPeeringConnection([]string{id}, ec2.NewFilter())
if err != nil {
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcPeeringConnectionID.NotFound" {
resp = nil
} else {
log.Printf("Error on VpcPeeringConnectionStateRefresh: %s", err)
return nil, "", err
}
}

if resp == nil {
// Sometimes AWS just has consistency issues and doesn't see
// our instance yet. Return an empty state.
return nil, "", nil
}

pc := &resp.VpcPeeringConnections[0]

return pc, "ready", nil
}
}
79 changes: 79 additions & 0 deletions builtin/providers/aws/resource_aws_vpc_peering_connection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/goamz/ec2"
)

func TestAccAWSVPCPeeringConnection_normal(t *testing.T) {
var conf ec2.Address

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSVpcPeeringConnectionDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccVpcPeeringConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &conf),
),
},
},
})
}

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

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

describe, err := conn.DescribeVpcPeeringConnection([]string{rs.Primary.ID}, ec2.NewFilter())

if err == nil {
if len(describe.VpcPeeringConnections) != 0 {
return fmt.Errorf("vpc peering connection still exists")
}
}
}

return nil
}

func testAccCheckAWSVpcPeeringConnectionExists(n string, res *ec2.Address) 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 peering connection id is set")
}

return nil
}
}

const testAccVpcPeeringConfig = `
resource "aws_vpc" "foo" {
cidr_block = "10.0.0.0/16"
}

resource "aws_vpc" "bar" {
cidr_block = "10.0.1.0/16"
}

resource "aws_vpc_peering_connection" "foo" {
peer_owner_id = "12345"
vpc_id = "${aws_vpc.foo.id}"
peer_vpc_id = "${aws_vpc.bar.id}"
}
`
Loading