Merge branch 'master' into aws-go-instance
* master: Code cleanup Update CHANGELOG.md fix nit-pick from go vet remove duplicated function provider/aws: Convert AWS Route Table Association to aws-sdk-go Cleansup: Restore expandIPPerms, remove flattenIPPerms clean up debug output to make go vet happy providers/aws: Convert AWS VPC Peering to aws-sdk-go provider/aws: Add env default for AWS_ACCOUNT_ID in VPC Peering connection convert route table tests to aws-sdk-go provider/aws: Convert AWS Route Table to aws-sdk-go providers/aws: iops in root device skipped when output state Give route table assoc it's own copy of this method for now provider/aws: Convert Main Route Table assoc. to aws-sdk-go aws/Route53 record creation timeout 10->30 mins provider/aws: Convert AWS Security Group to aws-sdk-go Fixing up the tests to make them pass correctly Fixing a corner case while retrieving a template UUID Adding tests and docs for the new VPN resources Adding a few new resources
This commit is contained in:
commit
f8c22c1e2d
|
@ -49,7 +49,8 @@ BUG FIXES:
|
||||||
"resource.0" would ignore the latter completely. [GH-1086]
|
"resource.0" would ignore the latter completely. [GH-1086]
|
||||||
* providers/aws: manually deleted VPC removes it from the state
|
* providers/aws: manually deleted VPC removes it from the state
|
||||||
* providers/aws: `source_dest_check` regression fixed (now works). [GH-1020]
|
* providers/aws: `source_dest_check` regression fixed (now works). [GH-1020]
|
||||||
* providers/aws: Longer wait times for DB instances
|
* providers/aws: Longer wait times for DB instances.
|
||||||
|
* providers/aws: Longer wait times for route53 records (30 mins). [GH-1164]
|
||||||
* providers/digitalocean: Waits until droplet is ready to be destroyed [GH-1057]
|
* providers/digitalocean: Waits until droplet is ready to be destroyed [GH-1057]
|
||||||
* providers/digitalocean: More lenient about 404's while waiting [GH-1062]
|
* providers/digitalocean: More lenient about 404's while waiting [GH-1062]
|
||||||
* providers/google: Network data in state was not being stored. [GH-1095]
|
* providers/google: Network data in state was not being stored. [GH-1095]
|
||||||
|
|
|
@ -4,8 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceAwsMainRouteTableAssociation() *schema.Resource {
|
func resourceAwsMainRouteTableAssociation() *schema.Resource {
|
||||||
|
@ -39,7 +40,7 @@ func resourceAwsMainRouteTableAssociation() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
vpcId := d.Get("vpc_id").(string)
|
vpcId := d.Get("vpc_id").(string)
|
||||||
routeTableId := d.Get("route_table_id").(string)
|
routeTableId := d.Get("route_table_id").(string)
|
||||||
|
|
||||||
|
@ -50,23 +51,23 @@ func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta int
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := ec2conn.ReassociateRouteTable(
|
resp, err := ec2conn.ReplaceRouteTableAssociation(&ec2.ReplaceRouteTableAssociationRequest{
|
||||||
mainAssociation.AssociationId,
|
AssociationID: mainAssociation.RouteTableAssociationID,
|
||||||
routeTableId,
|
RouteTableID: aws.String(routeTableId),
|
||||||
)
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("original_route_table_id", mainAssociation.RouteTableId)
|
d.Set("original_route_table_id", mainAssociation.RouteTableID)
|
||||||
d.SetId(resp.AssociationId)
|
d.SetId(*resp.NewAssociationID)
|
||||||
log.Printf("[INFO] New main route table association ID: %s", d.Id())
|
log.Printf("[INFO] New main route table association ID: %s", d.Id())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
mainAssociation, err := findMainRouteTableAssociation(
|
mainAssociation, err := findMainRouteTableAssociation(
|
||||||
ec2conn,
|
ec2conn,
|
||||||
|
@ -75,7 +76,7 @@ func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta inter
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if mainAssociation.AssociationId != d.Id() {
|
if *mainAssociation.RouteTableAssociationID != d.Id() {
|
||||||
// It seems it doesn't exist anymore, so clear the ID
|
// It seems it doesn't exist anymore, so clear the ID
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
}
|
}
|
||||||
|
@ -87,25 +88,28 @@ func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta inter
|
||||||
// original_route_table_id - this needs to stay recorded as the AWS-created
|
// original_route_table_id - this needs to stay recorded as the AWS-created
|
||||||
// table from VPC creation.
|
// table from VPC creation.
|
||||||
func resourceAwsMainRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsMainRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
vpcId := d.Get("vpc_id").(string)
|
vpcId := d.Get("vpc_id").(string)
|
||||||
routeTableId := d.Get("route_table_id").(string)
|
routeTableId := d.Get("route_table_id").(string)
|
||||||
|
|
||||||
log.Printf("[INFO] Updating main route table association: %s => %s", vpcId, routeTableId)
|
log.Printf("[INFO] Updating main route table association: %s => %s", vpcId, routeTableId)
|
||||||
|
|
||||||
resp, err := ec2conn.ReassociateRouteTable(d.Id(), routeTableId)
|
resp, err := ec2conn.ReplaceRouteTableAssociation(&ec2.ReplaceRouteTableAssociationRequest{
|
||||||
|
AssociationID: aws.String(d.Id()),
|
||||||
|
RouteTableID: aws.String(routeTableId),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId(resp.AssociationId)
|
d.SetId(*resp.NewAssociationID)
|
||||||
log.Printf("[INFO] New main route table association ID: %s", d.Id())
|
log.Printf("[INFO] New main route table association ID: %s", d.Id())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsMainRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsMainRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
vpcId := d.Get("vpc_id").(string)
|
vpcId := d.Get("vpc_id").(string)
|
||||||
originalRouteTableId := d.Get("original_route_table_id").(string)
|
originalRouteTableId := d.Get("original_route_table_id").(string)
|
||||||
|
|
||||||
|
@ -113,12 +117,15 @@ func resourceAwsMainRouteTableAssociationDelete(d *schema.ResourceData, meta int
|
||||||
vpcId,
|
vpcId,
|
||||||
originalRouteTableId)
|
originalRouteTableId)
|
||||||
|
|
||||||
resp, err := ec2conn.ReassociateRouteTable(d.Id(), originalRouteTableId)
|
resp, err := ec2conn.ReplaceRouteTableAssociation(&ec2.ReplaceRouteTableAssociationRequest{
|
||||||
|
AssociationID: aws.String(d.Id()),
|
||||||
|
RouteTableID: aws.String(originalRouteTableId),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[INFO] Resulting Association ID: %s", resp.AssociationId)
|
log.Printf("[INFO] Resulting Association ID: %s", *resp.NewAssociationID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -130,7 +137,7 @@ func findMainRouteTableAssociation(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTa
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range mainRouteTable.Associations {
|
for _, a := range mainRouteTable.Associations {
|
||||||
if a.Main {
|
if *a.Main {
|
||||||
return &a, nil
|
return &a, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,10 +145,17 @@ func findMainRouteTableAssociation(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTa
|
||||||
}
|
}
|
||||||
|
|
||||||
func findMainRouteTable(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTable, error) {
|
func findMainRouteTable(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTable, error) {
|
||||||
filter := ec2.NewFilter()
|
mainFilter := ec2.Filter{
|
||||||
filter.Add("association.main", "true")
|
aws.String("association.main"),
|
||||||
filter.Add("vpc-id", vpcId)
|
[]string{"true"},
|
||||||
routeResp, err := ec2conn.DescribeRouteTables(nil, filter)
|
}
|
||||||
|
vpcFilter := ec2.Filter{
|
||||||
|
aws.String("vpc-id"),
|
||||||
|
[]string{vpcId},
|
||||||
|
}
|
||||||
|
routeResp, err := ec2conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
|
||||||
|
Filters: []ec2.Filter{mainFilter, vpcFilter},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if len(routeResp.RouteTables) != 1 {
|
} else if len(routeResp.RouteTables) != 1 {
|
||||||
|
|
|
@ -65,15 +65,15 @@ func testAccCheckMainRouteTableAssociation(
|
||||||
return fmt.Errorf("Not found: %s", vpcResource)
|
return fmt.Errorf("Not found: %s", vpcResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
mainAssociation, err := findMainRouteTableAssociation(conn, vpc.Primary.ID)
|
mainAssociation, err := findMainRouteTableAssociation(conn, vpc.Primary.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if mainAssociation.AssociationId != rs.Primary.ID {
|
if *mainAssociation.RouteTableAssociationID != rs.Primary.ID {
|
||||||
return fmt.Errorf("Found wrong main association: %s",
|
return fmt.Errorf("Found wrong main association: %s",
|
||||||
mainAssociation.AssociationId)
|
*mainAssociation.RouteTableAssociationID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -138,7 +138,7 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
Delay: 30 * time.Second,
|
Delay: 30 * time.Second,
|
||||||
Pending: []string{"PENDING"},
|
Pending: []string{"PENDING"},
|
||||||
Target: "INSYNC",
|
Target: "INSYNC",
|
||||||
Timeout: 10 * time.Minute,
|
Timeout: 30 * time.Minute,
|
||||||
MinTimeout: 5 * time.Second,
|
MinTimeout: 5 * time.Second,
|
||||||
Refresh: func() (result interface{}, state string, err error) {
|
Refresh: func() (result interface{}, state string, err error) {
|
||||||
changeRequest := &route53.GetChangeRequest{
|
changeRequest := &route53.GetChangeRequest{
|
||||||
|
|
|
@ -6,10 +6,11 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceAwsRouteTable() *schema.Resource {
|
func resourceAwsRouteTable() *schema.Resource {
|
||||||
|
@ -61,11 +62,11 @@ func resourceAwsRouteTable() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
// Create the routing table
|
// Create the routing table
|
||||||
createOpts := &ec2.CreateRouteTable{
|
createOpts := &ec2.CreateRouteTableRequest{
|
||||||
VpcId: d.Get("vpc_id").(string),
|
VPCID: aws.String(d.Get("vpc_id").(string)),
|
||||||
}
|
}
|
||||||
log.Printf("[DEBUG] RouteTable create config: %#v", createOpts)
|
log.Printf("[DEBUG] RouteTable create config: %#v", createOpts)
|
||||||
|
|
||||||
|
@ -75,8 +76,8 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the ID and store it
|
// Get the ID and store it
|
||||||
rt := &resp.RouteTable
|
rt := resp.RouteTable
|
||||||
d.SetId(rt.RouteTableId)
|
d.SetId(*rt.RouteTableID)
|
||||||
log.Printf("[INFO] Route Table ID: %s", d.Id())
|
log.Printf("[INFO] Route Table ID: %s", d.Id())
|
||||||
|
|
||||||
// Wait for the route table to become available
|
// Wait for the route table to become available
|
||||||
|
@ -99,7 +100,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())()
|
rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -110,40 +111,48 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
rt := rtRaw.(*ec2.RouteTable)
|
rt := rtRaw.(*ec2.RouteTable)
|
||||||
d.Set("vpc_id", rt.VpcId)
|
d.Set("vpc_id", rt.VPCID)
|
||||||
|
|
||||||
// Create an empty schema.Set to hold all routes
|
// Create an empty schema.Set to hold all routes
|
||||||
route := &schema.Set{F: resourceAwsRouteTableHash}
|
route := &schema.Set{F: resourceAwsRouteTableHash}
|
||||||
|
|
||||||
// Loop through the routes and add them to the set
|
// Loop through the routes and add them to the set
|
||||||
for _, r := range rt.Routes {
|
for _, r := range rt.Routes {
|
||||||
if r.GatewayId == "local" {
|
if r.GatewayID != nil && *r.GatewayID == "local" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Origin == "EnableVgwRoutePropagation" {
|
if r.Origin != nil && *r.Origin == "EnableVgwRoutePropagation" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
m := make(map[string]interface{})
|
m := make(map[string]interface{})
|
||||||
m["cidr_block"] = r.DestinationCidrBlock
|
|
||||||
|
|
||||||
m["gateway_id"] = r.GatewayId
|
if r.DestinationCIDRBlock != nil {
|
||||||
m["instance_id"] = r.InstanceId
|
m["cidr_block"] = *r.DestinationCIDRBlock
|
||||||
m["vpc_peering_connection_id"] = r.VpcPeeringConnectionId
|
}
|
||||||
|
if r.GatewayID != nil {
|
||||||
|
m["gateway_id"] = *r.GatewayID
|
||||||
|
}
|
||||||
|
if r.InstanceID != nil {
|
||||||
|
m["instance_id"] = *r.InstanceID
|
||||||
|
}
|
||||||
|
if r.VPCPeeringConnectionID != nil {
|
||||||
|
m["vpc_peering_connection_id"] = *r.VPCPeeringConnectionID
|
||||||
|
}
|
||||||
|
|
||||||
route.Add(m)
|
route.Add(m)
|
||||||
}
|
}
|
||||||
d.Set("route", route)
|
d.Set("route", route)
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
d.Set("tags", tagsToMap(rt.Tags))
|
d.Set("tags", tagsToMapSDK(rt.Tags))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
// Check if the route set as a whole has changed
|
// Check if the route set as a whole has changed
|
||||||
if d.HasChange("route") {
|
if d.HasChange("route") {
|
||||||
|
@ -159,8 +168,10 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"[INFO] Deleting route from %s: %s",
|
"[INFO] Deleting route from %s: %s",
|
||||||
d.Id(), m["cidr_block"].(string))
|
d.Id(), m["cidr_block"].(string))
|
||||||
_, err := ec2conn.DeleteRoute(
|
err := ec2conn.DeleteRoute(&ec2.DeleteRouteRequest{
|
||||||
d.Id(), m["cidr_block"].(string))
|
RouteTableID: aws.String(d.Id()),
|
||||||
|
DestinationCIDRBlock: aws.String(m["cidr_block"].(string)),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -174,17 +185,16 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
for _, route := range nrs.List() {
|
for _, route := range nrs.List() {
|
||||||
m := route.(map[string]interface{})
|
m := route.(map[string]interface{})
|
||||||
|
|
||||||
opts := ec2.CreateRoute{
|
opts := ec2.CreateRouteRequest{
|
||||||
RouteTableId: d.Id(),
|
RouteTableID: aws.String(d.Id()),
|
||||||
DestinationCidrBlock: m["cidr_block"].(string),
|
DestinationCIDRBlock: aws.String(m["cidr_block"].(string)),
|
||||||
GatewayId: m["gateway_id"].(string),
|
GatewayID: aws.String(m["gateway_id"].(string)),
|
||||||
InstanceId: m["instance_id"].(string),
|
InstanceID: aws.String(m["instance_id"].(string)),
|
||||||
VpcPeeringConnectionId: m["vpc_peering_connection_id"].(string),
|
VPCPeeringConnectionID: aws.String(m["vpc_peering_connection_id"].(string)),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[INFO] Creating route for %s: %#v", d.Id(), opts)
|
log.Printf("[INFO] Creating route for %s: %#v", d.Id(), opts)
|
||||||
_, err := ec2conn.CreateRoute(&opts)
|
if err := ec2conn.CreateRoute(&opts); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +203,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setTags(ec2conn, d); err != nil {
|
if err := setTagsSDK(ec2conn, d); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
d.SetPartial("tags")
|
d.SetPartial("tags")
|
||||||
|
@ -203,7 +213,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
// First request the routing table since we'll have to disassociate
|
// First request the routing table since we'll have to disassociate
|
||||||
// all the subnets first.
|
// all the subnets first.
|
||||||
|
@ -218,16 +228,22 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error
|
||||||
|
|
||||||
// Do all the disassociations
|
// Do all the disassociations
|
||||||
for _, a := range rt.Associations {
|
for _, a := range rt.Associations {
|
||||||
log.Printf("[INFO] Disassociating association: %s", a.AssociationId)
|
log.Printf("[INFO] Disassociating association: %s", *a.RouteTableAssociationID)
|
||||||
if _, err := ec2conn.DisassociateRouteTable(a.AssociationId); err != nil {
|
err := ec2conn.DisassociateRouteTable(&ec2.DisassociateRouteTableRequest{
|
||||||
|
AssociationID: a.RouteTableAssociationID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the route table
|
// Delete the route table
|
||||||
log.Printf("[INFO] Deleting Route Table: %s", d.Id())
|
log.Printf("[INFO] Deleting Route Table: %s", d.Id())
|
||||||
if _, err := ec2conn.DeleteRouteTable(d.Id()); err != nil {
|
err = ec2conn.DeleteRouteTable(&ec2.DeleteRouteTableRequest{
|
||||||
ec2err, ok := err.(*ec2.Error)
|
RouteTableID: aws.String(d.Id()),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec2err, ok := err.(aws.APIError)
|
||||||
if ok && ec2err.Code == "InvalidRouteTableID.NotFound" {
|
if ok && ec2err.Code == "InvalidRouteTableID.NotFound" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -279,9 +295,11 @@ func resourceAwsRouteTableHash(v interface{}) int {
|
||||||
// a RouteTable.
|
// a RouteTable.
|
||||||
func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
return func() (interface{}, string, error) {
|
||||||
resp, err := conn.DescribeRouteTables([]string{id}, ec2.NewFilter())
|
resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
|
||||||
|
RouteTableIDs: []string{id},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidRouteTableID.NotFound" {
|
if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidRouteTableID.NotFound" {
|
||||||
resp = nil
|
resp = nil
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Error on RouteTableStateRefresh: %s", err)
|
log.Printf("Error on RouteTableStateRefresh: %s", err)
|
||||||
|
|
|
@ -4,8 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceAwsRouteTableAssociation() *schema.Resource {
|
func resourceAwsRouteTableAssociation() *schema.Resource {
|
||||||
|
@ -31,30 +32,31 @@ func resourceAwsRouteTableAssociation() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"[INFO] Creating route table association: %s => %s",
|
"[INFO] Creating route table association: %s => %s",
|
||||||
d.Get("subnet_id").(string),
|
d.Get("subnet_id").(string),
|
||||||
d.Get("route_table_id").(string))
|
d.Get("route_table_id").(string))
|
||||||
|
|
||||||
resp, err := ec2conn.AssociateRouteTable(
|
resp, err := ec2conn.AssociateRouteTable(&ec2.AssociateRouteTableRequest{
|
||||||
d.Get("route_table_id").(string),
|
RouteTableID: aws.String(d.Get("route_table_id").(string)),
|
||||||
d.Get("subnet_id").(string))
|
SubnetID: aws.String(d.Get("subnet_id").(string)),
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the ID and return
|
// Set the ID and return
|
||||||
d.SetId(resp.AssociationId)
|
d.SetId(*resp.AssociationID)
|
||||||
log.Printf("[INFO] Association ID: %s", d.Id())
|
log.Printf("[INFO] Association ID: %s", d.Id())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
// Get the routing table that this association belongs to
|
// Get the routing table that this association belongs to
|
||||||
rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(
|
rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(
|
||||||
|
@ -70,9 +72,9 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface
|
||||||
// Inspect that the association exists
|
// Inspect that the association exists
|
||||||
found := false
|
found := false
|
||||||
for _, a := range rt.Associations {
|
for _, a := range rt.Associations {
|
||||||
if a.AssociationId == d.Id() {
|
if *a.RouteTableAssociationID == d.Id() {
|
||||||
found = true
|
found = true
|
||||||
d.Set("subnet_id", a.SubnetId)
|
d.Set("subnet_id", *a.SubnetID)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,19 +88,21 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"[INFO] Creating route table association: %s => %s",
|
"[INFO] Creating route table association: %s => %s",
|
||||||
d.Get("subnet_id").(string),
|
d.Get("subnet_id").(string),
|
||||||
d.Get("route_table_id").(string))
|
d.Get("route_table_id").(string))
|
||||||
|
|
||||||
resp, err := ec2conn.ReassociateRouteTable(
|
req := &ec2.ReplaceRouteTableAssociationRequest{
|
||||||
d.Id(),
|
AssociationID: aws.String(d.Id()),
|
||||||
d.Get("route_table_id").(string))
|
RouteTableID: aws.String(d.Get("route_table_id").(string)),
|
||||||
|
}
|
||||||
|
resp, err := ec2conn.ReplaceRouteTableAssociation(req)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec2err, ok := err.(*ec2.Error)
|
ec2err, ok := err.(aws.APIError)
|
||||||
if ok && ec2err.Code == "InvalidAssociationID.NotFound" {
|
if ok && ec2err.Code == "InvalidAssociationID.NotFound" {
|
||||||
// Not found, so just create a new one
|
// Not found, so just create a new one
|
||||||
return resourceAwsRouteTableAssociationCreate(d, meta)
|
return resourceAwsRouteTableAssociationCreate(d, meta)
|
||||||
|
@ -108,18 +112,21 @@ func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interfa
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the ID
|
// Update the ID
|
||||||
d.SetId(resp.AssociationId)
|
d.SetId(*resp.NewAssociationID)
|
||||||
log.Printf("[INFO] Association ID: %s", d.Id())
|
log.Printf("[INFO] Association ID: %s", d.Id())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
log.Printf("[INFO] Deleting route table association: %s", d.Id())
|
log.Printf("[INFO] Deleting route table association: %s", d.Id())
|
||||||
if _, err := ec2conn.DisassociateRouteTable(d.Id()); err != nil {
|
err := ec2conn.DisassociateRouteTable(&ec2.DisassociateRouteTableRequest{
|
||||||
ec2err, ok := err.(*ec2.Error)
|
AssociationID: aws.String(d.Id()),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec2err, ok := err.(aws.APIError)
|
||||||
if ok && ec2err.Code == "InvalidAssociationID.NotFound" {
|
if ok && ec2err.Code == "InvalidAssociationID.NotFound" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccAWSRouteTableAssociation(t *testing.T) {
|
func TestAccAWSRouteTableAssociation(t *testing.T) {
|
||||||
|
@ -37,7 +38,7 @@ func TestAccAWSRouteTableAssociation(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error {
|
func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error {
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
for _, rs := range s.RootModule().Resources {
|
for _, rs := range s.RootModule().Resources {
|
||||||
if rs.Type != "aws_route_table_association" {
|
if rs.Type != "aws_route_table_association" {
|
||||||
|
@ -45,11 +46,12 @@ func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find the resource
|
// Try to find the resource
|
||||||
resp, err := conn.DescribeRouteTables(
|
resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
|
||||||
[]string{rs.Primary.Attributes["route_table_Id"]}, ec2.NewFilter())
|
RouteTableIDs: []string{rs.Primary.Attributes["route_table_id"]},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Verify the error is what we want
|
// Verify the error is what we want
|
||||||
ec2err, ok := err.(*ec2.Error)
|
ec2err, ok := err.(aws.APIError)
|
||||||
if !ok {
|
if !ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -62,7 +64,7 @@ func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error {
|
||||||
rt := resp.RouteTables[0]
|
rt := resp.RouteTables[0]
|
||||||
if len(rt.Associations) > 0 {
|
if len(rt.Associations) > 0 {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"route table %s has associations", rt.RouteTableId)
|
"route table %s has associations", *rt.RouteTableID)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,9 +83,10 @@ func testAccCheckRouteTableAssociationExists(n string, v *ec2.RouteTable) resour
|
||||||
return fmt.Errorf("No ID is set")
|
return fmt.Errorf("No ID is set")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
resp, err := conn.DescribeRouteTables(
|
resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
|
||||||
[]string{rs.Primary.Attributes["route_table_id"]}, ec2.NewFilter())
|
RouteTableIDs: []string{rs.Primary.Attributes["route_table_id"]},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccAWSRouteTable_normal(t *testing.T) {
|
func TestAccAWSRouteTable_normal(t *testing.T) {
|
||||||
|
@ -19,7 +20,7 @@ func TestAccAWSRouteTable_normal(t *testing.T) {
|
||||||
|
|
||||||
routes := make(map[string]ec2.Route)
|
routes := make(map[string]ec2.Route)
|
||||||
for _, r := range v.Routes {
|
for _, r := range v.Routes {
|
||||||
routes[r.DestinationCidrBlock] = r
|
routes[*r.DestinationCIDRBlock] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := routes["10.1.0.0/16"]; !ok {
|
if _, ok := routes["10.1.0.0/16"]; !ok {
|
||||||
|
@ -39,7 +40,7 @@ func TestAccAWSRouteTable_normal(t *testing.T) {
|
||||||
|
|
||||||
routes := make(map[string]ec2.Route)
|
routes := make(map[string]ec2.Route)
|
||||||
for _, r := range v.Routes {
|
for _, r := range v.Routes {
|
||||||
routes[r.DestinationCidrBlock] = r
|
routes[*r.DestinationCIDRBlock] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := routes["10.1.0.0/16"]; !ok {
|
if _, ok := routes["10.1.0.0/16"]; !ok {
|
||||||
|
@ -91,7 +92,7 @@ func TestAccAWSRouteTable_instance(t *testing.T) {
|
||||||
|
|
||||||
routes := make(map[string]ec2.Route)
|
routes := make(map[string]ec2.Route)
|
||||||
for _, r := range v.Routes {
|
for _, r := range v.Routes {
|
||||||
routes[r.DestinationCidrBlock] = r
|
routes[*r.DestinationCIDRBlock] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := routes["10.1.0.0/16"]; !ok {
|
if _, ok := routes["10.1.0.0/16"]; !ok {
|
||||||
|
@ -133,7 +134,7 @@ func TestAccAWSRouteTable_tags(t *testing.T) {
|
||||||
Config: testAccRouteTableConfigTags,
|
Config: testAccRouteTableConfigTags,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
|
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
|
||||||
testAccCheckTags(&route_table.Tags, "foo", "bar"),
|
testAccCheckTagsSDK(&route_table.Tags, "foo", "bar"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -141,8 +142,8 @@ func TestAccAWSRouteTable_tags(t *testing.T) {
|
||||||
Config: testAccRouteTableConfigTagsUpdate,
|
Config: testAccRouteTableConfigTagsUpdate,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
|
testAccCheckRouteTableExists("aws_route_table.foo", &route_table),
|
||||||
testAccCheckTags(&route_table.Tags, "foo", ""),
|
testAccCheckTagsSDK(&route_table.Tags, "foo", ""),
|
||||||
testAccCheckTags(&route_table.Tags, "bar", "baz"),
|
testAccCheckTagsSDK(&route_table.Tags, "bar", "baz"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -150,7 +151,7 @@ func TestAccAWSRouteTable_tags(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckRouteTableDestroy(s *terraform.State) error {
|
func testAccCheckRouteTableDestroy(s *terraform.State) error {
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
for _, rs := range s.RootModule().Resources {
|
for _, rs := range s.RootModule().Resources {
|
||||||
if rs.Type != "aws_route_table" {
|
if rs.Type != "aws_route_table" {
|
||||||
|
@ -158,8 +159,9 @@ func testAccCheckRouteTableDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find the resource
|
// Try to find the resource
|
||||||
resp, err := conn.DescribeRouteTables(
|
resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
|
||||||
[]string{rs.Primary.ID}, ec2.NewFilter())
|
RouteTableIDs: []string{rs.Primary.ID},
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if len(resp.RouteTables) > 0 {
|
if len(resp.RouteTables) > 0 {
|
||||||
return fmt.Errorf("still exist.")
|
return fmt.Errorf("still exist.")
|
||||||
|
@ -169,7 +171,7 @@ func testAccCheckRouteTableDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the error is what we want
|
// Verify the error is what we want
|
||||||
ec2err, ok := err.(*ec2.Error)
|
ec2err, ok := err.(aws.APIError)
|
||||||
if !ok {
|
if !ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -192,9 +194,10 @@ func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestChec
|
||||||
return fmt.Errorf("No ID is set")
|
return fmt.Errorf("No ID is set")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
resp, err := conn.DescribeRouteTables(
|
resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
|
||||||
[]string{rs.Primary.ID}, ec2.NewFilter())
|
RouteTableIDs: []string{rs.Primary.ID},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -208,7 +211,10 @@ func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestChec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSRouteTable_vpcPeering(t *testing.T) {
|
// TODO: re-enable this test.
|
||||||
|
// VPC Peering connections are prefixed with pcx
|
||||||
|
// Right now there is no VPC Peering resource
|
||||||
|
func _TestAccAWSRouteTable_vpcPeering(t *testing.T) {
|
||||||
var v ec2.RouteTable
|
var v ec2.RouteTable
|
||||||
|
|
||||||
testCheck := func(*terraform.State) error {
|
testCheck := func(*terraform.State) error {
|
||||||
|
@ -218,7 +224,7 @@ func TestAccAWSRouteTable_vpcPeering(t *testing.T) {
|
||||||
|
|
||||||
routes := make(map[string]ec2.Route)
|
routes := make(map[string]ec2.Route)
|
||||||
for _, r := range v.Routes {
|
for _, r := range v.Routes {
|
||||||
routes[r.DestinationCidrBlock] = r
|
routes[*r.DestinationCIDRBlock] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := routes["10.1.0.0/16"]; !ok {
|
if _, ok := routes["10.1.0.0/16"]; !ok {
|
||||||
|
@ -345,6 +351,9 @@ resource "aws_route_table" "foo" {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// TODO: re-enable this test.
|
||||||
|
// VPC Peering connections are prefixed with pcx
|
||||||
|
// Right now there is no VPC Peering resource
|
||||||
const testAccRouteTableVpcPeeringConfig = `
|
const testAccRouteTableVpcPeeringConfig = `
|
||||||
resource "aws_vpc" "foo" {
|
resource "aws_vpc" "foo" {
|
||||||
cidr_block = "10.1.0.0/16"
|
cidr_block = "10.1.0.0/16"
|
||||||
|
@ -359,7 +368,7 @@ resource "aws_route_table" "foo" {
|
||||||
|
|
||||||
route {
|
route {
|
||||||
cidr_block = "10.2.0.0/16"
|
cidr_block = "10.2.0.0/16"
|
||||||
vpc_peering_connection_id = "vpc-12345"
|
vpc_peering_connection_id = "pcx-12345"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -7,10 +7,11 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceAwsSecurityGroup() *schema.Resource {
|
func resourceAwsSecurityGroup() *schema.Resource {
|
||||||
|
@ -141,18 +142,18 @@ func resourceAwsSecurityGroup() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
securityGroupOpts := ec2.SecurityGroup{
|
securityGroupOpts := &ec2.CreateSecurityGroupRequest{
|
||||||
Name: d.Get("name").(string),
|
GroupName: aws.String(d.Get("name").(string)),
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := d.Get("vpc_id"); v != nil {
|
if v := d.Get("vpc_id"); v != nil {
|
||||||
securityGroupOpts.VpcId = v.(string)
|
securityGroupOpts.VPCID = aws.String(v.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := d.Get("description"); v != nil {
|
if v := d.Get("description"); v != nil {
|
||||||
securityGroupOpts.Description = v.(string)
|
securityGroupOpts.Description = aws.String(v.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf(
|
log.Printf(
|
||||||
|
@ -162,7 +163,7 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
return fmt.Errorf("Error creating Security Group: %s", err)
|
return fmt.Errorf("Error creating Security Group: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId(createResp.Id)
|
d.SetId(*createResp.GroupID)
|
||||||
|
|
||||||
log.Printf("[INFO] Security Group ID: %s", d.Id())
|
log.Printf("[INFO] Security Group ID: %s", d.Id())
|
||||||
|
|
||||||
|
@ -186,7 +187,7 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
|
sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -197,24 +198,23 @@ func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sg := sgRaw.(*ec2.SecurityGroupInfo)
|
sg := sgRaw.(ec2.SecurityGroup)
|
||||||
|
|
||||||
ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPerms)
|
ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermissions)
|
||||||
egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermsEgress)
|
egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermissionsEgress)
|
||||||
|
|
||||||
d.Set("description", sg.Description)
|
d.Set("description", sg.Description)
|
||||||
d.Set("name", sg.Name)
|
d.Set("name", sg.GroupName)
|
||||||
d.Set("vpc_id", sg.VpcId)
|
d.Set("vpc_id", sg.VPCID)
|
||||||
d.Set("owner_id", sg.OwnerId)
|
d.Set("owner_id", sg.OwnerID)
|
||||||
d.Set("ingress", ingressRules)
|
d.Set("ingress", ingressRules)
|
||||||
d.Set("egress", egressRules)
|
d.Set("egress", egressRules)
|
||||||
d.Set("tags", tagsToMap(sg.Tags))
|
d.Set("tags", tagsToMapSDK(sg.Tags))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
|
sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -224,7 +224,8 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
group := sgRaw.(*ec2.SecurityGroupInfo).SecurityGroup
|
|
||||||
|
group := sgRaw.(ec2.SecurityGroup)
|
||||||
|
|
||||||
err = resourceAwsSecurityGroupUpdateRules(d, "ingress", meta, group)
|
err = resourceAwsSecurityGroupUpdateRules(d, "ingress", meta, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -238,7 +239,7 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setTags(ec2conn, d); err != nil {
|
if err := setTagsSDK(ec2conn, d); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,14 +249,16 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
log.Printf("[DEBUG] Security Group destroy: %v", d.Id())
|
log.Printf("[DEBUG] Security Group destroy: %v", d.Id())
|
||||||
|
|
||||||
return resource.Retry(5*time.Minute, func() error {
|
return resource.Retry(5*time.Minute, func() error {
|
||||||
_, err := ec2conn.DeleteSecurityGroup(ec2.SecurityGroup{Id: d.Id()})
|
err := ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupRequest{
|
||||||
|
GroupID: aws.String(d.Id()),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec2err, ok := err.(*ec2.Error)
|
ec2err, ok := err.(aws.APIError)
|
||||||
if !ok {
|
if !ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -313,34 +316,45 @@ func resourceAwsSecurityGroupRuleHash(v interface{}) int {
|
||||||
return hashcode.String(buf.String())
|
return hashcode.String(buf.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPerm) []map[string]interface{} {
|
func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPermission) []map[string]interface{} {
|
||||||
ruleMap := make(map[string]map[string]interface{})
|
ruleMap := make(map[string]map[string]interface{})
|
||||||
for _, perm := range permissions {
|
for _, perm := range permissions {
|
||||||
k := fmt.Sprintf("%s-%d-%d", perm.Protocol, perm.FromPort, perm.ToPort)
|
var fromPort, toPort int
|
||||||
|
if v := perm.FromPort; v != nil {
|
||||||
|
fromPort = *v
|
||||||
|
}
|
||||||
|
if v := perm.ToPort; v != nil {
|
||||||
|
toPort = *v
|
||||||
|
}
|
||||||
|
|
||||||
|
k := fmt.Sprintf("%s-%d-%d", *perm.IPProtocol, fromPort, toPort)
|
||||||
m, ok := ruleMap[k]
|
m, ok := ruleMap[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
m = make(map[string]interface{})
|
m = make(map[string]interface{})
|
||||||
ruleMap[k] = m
|
ruleMap[k] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
m["from_port"] = perm.FromPort
|
m["from_port"] = fromPort
|
||||||
m["to_port"] = perm.ToPort
|
m["to_port"] = toPort
|
||||||
m["protocol"] = perm.Protocol
|
m["protocol"] = *perm.IPProtocol
|
||||||
|
|
||||||
if len(perm.SourceIPs) > 0 {
|
if len(perm.IPRanges) > 0 {
|
||||||
raw, ok := m["cidr_blocks"]
|
raw, ok := m["cidr_blocks"]
|
||||||
if !ok {
|
if !ok {
|
||||||
raw = make([]string, 0, len(perm.SourceIPs))
|
raw = make([]string, 0, len(perm.IPRanges))
|
||||||
}
|
}
|
||||||
list := raw.([]string)
|
list := raw.([]string)
|
||||||
|
|
||||||
list = append(list, perm.SourceIPs...)
|
for _, ip := range perm.IPRanges {
|
||||||
|
list = append(list, *ip.CIDRIP)
|
||||||
|
}
|
||||||
|
|
||||||
m["cidr_blocks"] = list
|
m["cidr_blocks"] = list
|
||||||
}
|
}
|
||||||
|
|
||||||
var groups []string
|
var groups []string
|
||||||
if len(perm.SourceGroups) > 0 {
|
if len(perm.UserIDGroupPairs) > 0 {
|
||||||
groups = flattenSecurityGroups(perm.SourceGroups)
|
groups = flattenSecurityGroupsSDK(perm.UserIDGroupPairs)
|
||||||
}
|
}
|
||||||
for i, id := range groups {
|
for i, id := range groups {
|
||||||
if id == d.Id() {
|
if id == d.Id() {
|
||||||
|
@ -364,7 +378,6 @@ func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []
|
||||||
for _, m := range ruleMap {
|
for _, m := range ruleMap {
|
||||||
rules = append(rules, m)
|
rules = append(rules, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +396,7 @@ func resourceAwsSecurityGroupUpdateRules(
|
||||||
os := o.(*schema.Set)
|
os := o.(*schema.Set)
|
||||||
ns := n.(*schema.Set)
|
ns := n.(*schema.Set)
|
||||||
|
|
||||||
|
// TODO: re-munge this when test is updated
|
||||||
remove := expandIPPerms(d.Id(), os.Difference(ns).List())
|
remove := expandIPPerms(d.Id(), os.Difference(ns).List())
|
||||||
add := expandIPPerms(d.Id(), ns.Difference(os).List())
|
add := expandIPPerms(d.Id(), ns.Difference(os).List())
|
||||||
|
|
||||||
|
@ -396,34 +410,53 @@ func resourceAwsSecurityGroupUpdateRules(
|
||||||
// not have service issues.
|
// not have service issues.
|
||||||
|
|
||||||
if len(remove) > 0 || len(add) > 0 {
|
if len(remove) > 0 || len(add) > 0 {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
|
var err error
|
||||||
if len(remove) > 0 {
|
if len(remove) > 0 {
|
||||||
// Revoke the old rules
|
log.Printf("[DEBUG] Revoking security group %#v %s rule: %#v",
|
||||||
revoke := ec2conn.RevokeSecurityGroup
|
group, ruleset, remove)
|
||||||
|
|
||||||
if ruleset == "egress" {
|
if ruleset == "egress" {
|
||||||
revoke = ec2conn.RevokeSecurityGroupEgress
|
req := &ec2.RevokeSecurityGroupEgressRequest{
|
||||||
|
GroupID: group.GroupID,
|
||||||
|
IPPermissions: remove,
|
||||||
|
}
|
||||||
|
err = ec2conn.RevokeSecurityGroupEgress(req)
|
||||||
|
} else {
|
||||||
|
req := &ec2.RevokeSecurityGroupIngressRequest{
|
||||||
|
GroupID: group.GroupID,
|
||||||
|
IPPermissions: remove,
|
||||||
|
}
|
||||||
|
err = ec2conn.RevokeSecurityGroupIngress(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Revoking security group %s %s rule: %#v",
|
if err != nil {
|
||||||
group, ruleset, remove)
|
|
||||||
if _, err := revoke(group, remove); err != nil {
|
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"Error revoking security group %s rules: %s",
|
"Error authorizing security group %s rules: %s",
|
||||||
ruleset, err)
|
ruleset, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(add) > 0 {
|
if len(add) > 0 {
|
||||||
|
log.Printf("[DEBUG] Authorizing security group %#v %s rule: %#v",
|
||||||
|
group, ruleset, add)
|
||||||
// Authorize the new rules
|
// Authorize the new rules
|
||||||
authorize := ec2conn.AuthorizeSecurityGroup
|
|
||||||
if ruleset == "egress" {
|
if ruleset == "egress" {
|
||||||
authorize = ec2conn.AuthorizeSecurityGroupEgress
|
req := &ec2.AuthorizeSecurityGroupEgressRequest{
|
||||||
|
GroupID: group.GroupID,
|
||||||
|
IPPermissions: add,
|
||||||
|
}
|
||||||
|
err = ec2conn.AuthorizeSecurityGroupEgress(req)
|
||||||
|
} else {
|
||||||
|
req := &ec2.AuthorizeSecurityGroupIngressRequest{
|
||||||
|
GroupID: group.GroupID,
|
||||||
|
IPPermissions: add,
|
||||||
|
}
|
||||||
|
err = ec2conn.AuthorizeSecurityGroupIngress(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Authorizing security group %s %s rule: %#v",
|
if err != nil {
|
||||||
group, ruleset, add)
|
|
||||||
if _, err := authorize(group, add); err != nil {
|
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"Error authorizing security group %s rules: %s",
|
"Error authorizing security group %s rules: %s",
|
||||||
ruleset, err)
|
ruleset, err)
|
||||||
|
@ -431,7 +464,6 @@ func resourceAwsSecurityGroupUpdateRules(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,10 +471,12 @@ func resourceAwsSecurityGroupUpdateRules(
|
||||||
// a security group.
|
// a security group.
|
||||||
func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
return func() (interface{}, string, error) {
|
||||||
sgs := []ec2.SecurityGroup{ec2.SecurityGroup{Id: id}}
|
req := &ec2.DescribeSecurityGroupsRequest{
|
||||||
resp, err := conn.SecurityGroups(sgs, nil)
|
GroupIDs: []string{id},
|
||||||
|
}
|
||||||
|
resp, err := conn.DescribeSecurityGroups(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ec2err, ok := err.(*ec2.Error); ok {
|
if ec2err, ok := err.(aws.APIError); ok {
|
||||||
if ec2err.Code == "InvalidSecurityGroupID.NotFound" ||
|
if ec2err.Code == "InvalidSecurityGroupID.NotFound" ||
|
||||||
ec2err.Code == "InvalidGroup.NotFound" {
|
ec2err.Code == "InvalidGroup.NotFound" {
|
||||||
resp = nil
|
resp = nil
|
||||||
|
@ -460,7 +494,7 @@ func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
||||||
return nil, "", nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
group := &resp.Groups[0]
|
group := resp.SecurityGroups[0]
|
||||||
return group, "exists", nil
|
return group, "exists", nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,18 @@ package aws
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccAWSSecurityGroup_normal(t *testing.T) {
|
func TestAccAWSSecurityGroup_normal(t *testing.T) {
|
||||||
var group ec2.SecurityGroupInfo
|
var group ec2.SecurityGroup
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -44,7 +46,7 @@ func TestAccAWSSecurityGroup_normal(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSSecurityGroup_self(t *testing.T) {
|
func TestAccAWSSecurityGroup_self(t *testing.T) {
|
||||||
var group ec2.SecurityGroupInfo
|
var group ec2.SecurityGroup
|
||||||
|
|
||||||
checkSelf := func(s *terraform.State) (err error) {
|
checkSelf := func(s *terraform.State) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -53,7 +55,7 @@ func TestAccAWSSecurityGroup_self(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if group.IPPerms[0].SourceGroups[0].Id != group.Id {
|
if *group.IPPermissions[0].UserIDGroupPairs[0].GroupID != *group.GroupID {
|
||||||
return fmt.Errorf("bad: %#v", group)
|
return fmt.Errorf("bad: %#v", group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +91,10 @@ func TestAccAWSSecurityGroup_self(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSSecurityGroup_vpc(t *testing.T) {
|
func TestAccAWSSecurityGroup_vpc(t *testing.T) {
|
||||||
var group ec2.SecurityGroupInfo
|
var group ec2.SecurityGroup
|
||||||
|
|
||||||
testCheck := func(*terraform.State) error {
|
testCheck := func(*terraform.State) error {
|
||||||
if group.VpcId == "" {
|
if *group.VPCID == "" {
|
||||||
return fmt.Errorf("should have vpc ID")
|
return fmt.Errorf("should have vpc ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +143,7 @@ func TestAccAWSSecurityGroup_vpc(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSSecurityGroup_MultiIngress(t *testing.T) {
|
func TestAccAWSSecurityGroup_MultiIngress(t *testing.T) {
|
||||||
var group ec2.SecurityGroupInfo
|
var group ec2.SecurityGroup
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -159,7 +161,7 @@ func TestAccAWSSecurityGroup_MultiIngress(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSSecurityGroup_Change(t *testing.T) {
|
func TestAccAWSSecurityGroup_Change(t *testing.T) {
|
||||||
var group ec2.SecurityGroupInfo
|
var group ec2.SecurityGroup
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -184,30 +186,27 @@ func TestAccAWSSecurityGroup_Change(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error {
|
func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error {
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
for _, rs := range s.RootModule().Resources {
|
for _, rs := range s.RootModule().Resources {
|
||||||
if rs.Type != "aws_security_group" {
|
if rs.Type != "aws_security_group" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sgs := []ec2.SecurityGroup{
|
|
||||||
ec2.SecurityGroup{
|
|
||||||
Id: rs.Primary.ID,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve our group
|
// Retrieve our group
|
||||||
resp, err := conn.SecurityGroups(sgs, nil)
|
req := &ec2.DescribeSecurityGroupsRequest{
|
||||||
|
GroupIDs: []string{rs.Primary.ID},
|
||||||
|
}
|
||||||
|
resp, err := conn.DescribeSecurityGroups(req)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if len(resp.Groups) > 0 && resp.Groups[0].Id == rs.Primary.ID {
|
if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupID == rs.Primary.ID {
|
||||||
return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
|
return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ec2err, ok := err.(*ec2.Error)
|
ec2err, ok := err.(aws.APIError)
|
||||||
if !ok {
|
if !ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -220,7 +219,7 @@ func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroupInfo) resource.TestCheckFunc {
|
func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -231,20 +230,19 @@ func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroupInfo)
|
||||||
return fmt.Errorf("No Security Group is set")
|
return fmt.Errorf("No Security Group is set")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
sgs := []ec2.SecurityGroup{
|
req := &ec2.DescribeSecurityGroupsRequest{
|
||||||
ec2.SecurityGroup{
|
GroupIDs: []string{rs.Primary.ID},
|
||||||
Id: rs.Primary.ID,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
resp, err := conn.SecurityGroups(sgs, nil)
|
resp, err := conn.DescribeSecurityGroups(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(resp.Groups) > 0 && resp.Groups[0].Id == rs.Primary.ID {
|
if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupID == rs.Primary.ID {
|
||||||
|
|
||||||
*group = resp.Groups[0]
|
log.Printf("\n==\n===\nfound group\n===\n==\n")
|
||||||
|
*group = resp.SecurityGroups[0]
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -253,32 +251,32 @@ func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroupInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroupInfo) resource.TestCheckFunc {
|
func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroup) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
p := ec2.IPPerm{
|
p := ec2.IPPermission{
|
||||||
FromPort: 80,
|
FromPort: aws.Integer(80),
|
||||||
ToPort: 8000,
|
ToPort: aws.Integer(8000),
|
||||||
Protocol: "tcp",
|
IPProtocol: aws.String("tcp"),
|
||||||
SourceIPs: []string{"10.0.0.0/8"},
|
IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("10.0.0.0/8")}},
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.Name != "terraform_acceptance_test_example" {
|
if *group.GroupName != "terraform_acceptance_test_example" {
|
||||||
return fmt.Errorf("Bad name: %s", group.Name)
|
return fmt.Errorf("Bad name: %s", *group.GroupName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.Description != "Used in the terraform acceptance tests" {
|
if *group.Description != "Used in the terraform acceptance tests" {
|
||||||
return fmt.Errorf("Bad description: %s", group.Description)
|
return fmt.Errorf("Bad description: %s", *group.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(group.IPPerms) == 0 {
|
if len(group.IPPermissions) == 0 {
|
||||||
return fmt.Errorf("No IPPerms")
|
return fmt.Errorf("No IPPerms")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare our ingress
|
// Compare our ingress
|
||||||
if !reflect.DeepEqual(group.IPPerms[0], p) {
|
if !reflect.DeepEqual(group.IPPermissions[0], p) {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
||||||
group.IPPerms[0],
|
group.IPPermissions[0],
|
||||||
p)
|
p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +285,7 @@ func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroupInfo) resour
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSSecurityGroup_tags(t *testing.T) {
|
func TestAccAWSSecurityGroup_tags(t *testing.T) {
|
||||||
var group ec2.SecurityGroupInfo
|
var group ec2.SecurityGroup
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -298,7 +296,7 @@ func TestAccAWSSecurityGroup_tags(t *testing.T) {
|
||||||
Config: testAccAWSSecurityGroupConfigTags,
|
Config: testAccAWSSecurityGroupConfigTags,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group),
|
testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group),
|
||||||
testAccCheckTags(&group.Tags, "foo", "bar"),
|
testAccCheckTagsSDK(&group.Tags, "foo", "bar"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -306,56 +304,56 @@ func TestAccAWSSecurityGroup_tags(t *testing.T) {
|
||||||
Config: testAccAWSSecurityGroupConfigTagsUpdate,
|
Config: testAccAWSSecurityGroupConfigTagsUpdate,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group),
|
testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group),
|
||||||
testAccCheckTags(&group.Tags, "foo", ""),
|
testAccCheckTagsSDK(&group.Tags, "foo", ""),
|
||||||
testAccCheckTags(&group.Tags, "bar", "baz"),
|
testAccCheckTagsSDK(&group.Tags, "bar", "baz"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckAWSSecurityGroupAttributesChanged(group *ec2.SecurityGroupInfo) resource.TestCheckFunc {
|
func testAccCheckAWSSecurityGroupAttributesChanged(group *ec2.SecurityGroup) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
p := []ec2.IPPerm{
|
p := []ec2.IPPermission{
|
||||||
ec2.IPPerm{
|
ec2.IPPermission{
|
||||||
FromPort: 80,
|
FromPort: aws.Integer(80),
|
||||||
ToPort: 9000,
|
ToPort: aws.Integer(9000),
|
||||||
Protocol: "tcp",
|
IPProtocol: aws.String("tcp"),
|
||||||
SourceIPs: []string{"10.0.0.0/8"},
|
IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("10.0.0.0/8")}},
|
||||||
},
|
},
|
||||||
ec2.IPPerm{
|
ec2.IPPermission{
|
||||||
FromPort: 80,
|
FromPort: aws.Integer(80),
|
||||||
ToPort: 8000,
|
ToPort: aws.Integer(8000),
|
||||||
Protocol: "tcp",
|
IPProtocol: aws.String("tcp"),
|
||||||
SourceIPs: []string{"0.0.0.0/0", "10.0.0.0/8"},
|
IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("0.0.0.0/0")}, ec2.IPRange{aws.String("10.0.0.0/8")}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.Name != "terraform_acceptance_test_example" {
|
if *group.GroupName != "terraform_acceptance_test_example" {
|
||||||
return fmt.Errorf("Bad name: %s", group.Name)
|
return fmt.Errorf("Bad name: %s", *group.GroupName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.Description != "Used in the terraform acceptance tests" {
|
if *group.Description != "Used in the terraform acceptance tests" {
|
||||||
return fmt.Errorf("Bad description: %s", group.Description)
|
return fmt.Errorf("Bad description: %s", *group.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare our ingress
|
// Compare our ingress
|
||||||
if len(group.IPPerms) != 2 {
|
if len(group.IPPermissions) != 2 {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
||||||
group.IPPerms,
|
group.IPPermissions,
|
||||||
p)
|
p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.IPPerms[0].ToPort == 8000 {
|
if *group.IPPermissions[0].ToPort == 8000 {
|
||||||
group.IPPerms[1], group.IPPerms[0] =
|
group.IPPermissions[1], group.IPPermissions[0] =
|
||||||
group.IPPerms[0], group.IPPerms[1]
|
group.IPPermissions[0], group.IPPermissions[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(group.IPPerms, p) {
|
if !reflect.DeepEqual(group.IPPermissions, p) {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
||||||
group.IPPerms,
|
group.IPPermissions,
|
||||||
p)
|
p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,10 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceAwsVpcPeeringConnection() *schema.Resource {
|
func resourceAwsVpcPeeringConnection() *schema.Resource {
|
||||||
|
@ -19,9 +20,10 @@ func resourceAwsVpcPeeringConnection() *schema.Resource {
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"peer_owner_id": &schema.Schema{
|
"peer_owner_id": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("AWS_ACCOUNT_ID", nil),
|
||||||
},
|
},
|
||||||
"peer_vpc_id": &schema.Schema{
|
"peer_vpc_id": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
@ -39,23 +41,23 @@ func resourceAwsVpcPeeringConnection() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
// Create the vpc peering connection
|
// Create the vpc peering connection
|
||||||
createOpts := &ec2.CreateVpcPeeringConnection{
|
createOpts := &ec2.CreateVPCPeeringConnectionRequest{
|
||||||
PeerOwnerId: d.Get("peer_owner_id").(string),
|
PeerOwnerID: aws.String(d.Get("peer_owner_id").(string)),
|
||||||
PeerVpcId: d.Get("peer_vpc_id").(string),
|
PeerVPCID: aws.String(d.Get("peer_vpc_id").(string)),
|
||||||
VpcId: d.Get("vpc_id").(string),
|
VPCID: aws.String(d.Get("vpc_id").(string)),
|
||||||
}
|
}
|
||||||
log.Printf("[DEBUG] VpcPeeringCreate create config: %#v", createOpts)
|
log.Printf("[DEBUG] VpcPeeringCreate create config: %#v", createOpts)
|
||||||
resp, err := ec2conn.CreateVpcPeeringConnection(createOpts)
|
resp, err := ec2conn.CreateVPCPeeringConnection(createOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating vpc peering connection: %s", err)
|
return fmt.Errorf("Error creating vpc peering connection: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the ID and store it
|
// Get the ID and store it
|
||||||
rt := &resp.VpcPeeringConnection
|
rt := resp.VPCPeeringConnection
|
||||||
d.SetId(rt.VpcPeeringConnectionId)
|
d.SetId(*rt.VPCPeeringConnectionID)
|
||||||
log.Printf("[INFO] Vpc Peering Connection ID: %s", d.Id())
|
log.Printf("[INFO] Vpc Peering Connection ID: %s", d.Id())
|
||||||
|
|
||||||
// Wait for the vpc peering connection to become available
|
// Wait for the vpc peering connection to become available
|
||||||
|
@ -78,7 +80,7 @@ func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
pcRaw, _, err := resourceAwsVpcPeeringConnectionStateRefreshFunc(ec2conn, d.Id())()
|
pcRaw, _, err := resourceAwsVpcPeeringConnectionStateRefreshFunc(ec2conn, d.Id())()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -88,20 +90,20 @@ func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pc := pcRaw.(*ec2.VpcPeeringConnection)
|
pc := pcRaw.(*ec2.VPCPeeringConnection)
|
||||||
|
|
||||||
d.Set("peer_owner_id", pc.AccepterVpcInfo.OwnerId)
|
d.Set("peer_owner_id", pc.AccepterVPCInfo.OwnerID)
|
||||||
d.Set("peer_vpc_id", pc.AccepterVpcInfo.VpcId)
|
d.Set("peer_vpc_id", pc.AccepterVPCInfo.VPCID)
|
||||||
d.Set("vpc_id", pc.RequesterVpcInfo.VpcId)
|
d.Set("vpc_id", pc.RequesterVPCInfo.VPCID)
|
||||||
d.Set("tags", tagsToMap(pc.Tags))
|
d.Set("tags", tagsToMapSDK(pc.Tags))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
if err := setTags(ec2conn, d); err != nil {
|
if err := setTagsSDK(ec2conn, d); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
d.SetPartial("tags")
|
d.SetPartial("tags")
|
||||||
|
@ -111,9 +113,12 @@ func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsVpcPeeringDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsVpcPeeringDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
ec2conn := meta.(*AWSClient).ec2conn
|
ec2conn := meta.(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
_, err := ec2conn.DeleteVpcPeeringConnection(d.Id())
|
_, err := ec2conn.DeleteVPCPeeringConnection(
|
||||||
|
&ec2.DeleteVPCPeeringConnectionRequest{
|
||||||
|
VPCPeeringConnectionID: aws.String(d.Id()),
|
||||||
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,9 +127,11 @@ func resourceAwsVpcPeeringDelete(d *schema.ResourceData, meta interface{}) error
|
||||||
func resourceAwsVpcPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
func resourceAwsVpcPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
return func() (interface{}, string, error) {
|
||||||
|
|
||||||
resp, err := conn.DescribeVpcPeeringConnection([]string{id}, ec2.NewFilter())
|
resp, err := conn.DescribeVPCPeeringConnections(&ec2.DescribeVPCPeeringConnectionsRequest{
|
||||||
|
VPCPeeringConnectionIDs: []string{id},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcPeeringConnectionID.NotFound" {
|
if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpcPeeringConnectionID.NotFound" {
|
||||||
resp = nil
|
resp = nil
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Error on VpcPeeringConnectionStateRefresh: %s", err)
|
log.Printf("Error on VpcPeeringConnectionStateRefresh: %s", err)
|
||||||
|
@ -138,7 +145,7 @@ func resourceAwsVpcPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) r
|
||||||
return nil, "", nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pc := &resp.VpcPeeringConnections[0]
|
pc := &resp.VPCPeeringConnections[0]
|
||||||
|
|
||||||
return pc, "ready", nil
|
return pc, "ready", nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccAWSVPCPeeringConnection_normal(t *testing.T) {
|
func TestAccAWSVPCPeeringConnection_normal(t *testing.T) {
|
||||||
|
@ -28,17 +28,20 @@ func TestAccAWSVPCPeeringConnection_normal(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error {
|
func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error {
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
conn := testAccProvider.Meta().(*AWSClient).awsEC2conn
|
||||||
|
|
||||||
for _, rs := range s.RootModule().Resources {
|
for _, rs := range s.RootModule().Resources {
|
||||||
if rs.Type != "aws_vpc_peering_connection" {
|
if rs.Type != "aws_vpc_peering_connection" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
describe, err := conn.DescribeVpcPeeringConnection([]string{rs.Primary.ID}, ec2.NewFilter())
|
describe, err := conn.DescribeVPCPeeringConnections(
|
||||||
|
&ec2.DescribeVPCPeeringConnectionsRequest{
|
||||||
|
VPCPeeringConnectionIDs: []string{rs.Primary.ID},
|
||||||
|
})
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if len(describe.VpcPeeringConnections) != 0 {
|
if len(describe.VPCPeeringConnections) != 0 {
|
||||||
return fmt.Errorf("vpc peering connection still exists")
|
return fmt.Errorf("vpc peering connection still exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,11 +71,10 @@ resource "aws_vpc" "foo" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_vpc" "bar" {
|
resource "aws_vpc" "bar" {
|
||||||
cidr_block = "10.0.1.0/16"
|
cidr_block = "10.1.0.0/16"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_vpc_peering_connection" "foo" {
|
resource "aws_vpc_peering_connection" "foo" {
|
||||||
peer_owner_id = "12345"
|
|
||||||
vpc_id = "${aws_vpc.foo.id}"
|
vpc_id = "${aws_vpc.foo.id}"
|
||||||
peer_vpc_id = "${aws_vpc.bar.id}"
|
peer_vpc_id = "${aws_vpc.bar.id}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/aws-sdk-go/aws"
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/aws-sdk-go/gen/elb"
|
"github.com/hashicorp/aws-sdk-go/gen/elb"
|
||||||
"github.com/hashicorp/aws-sdk-go/gen/rds"
|
"github.com/hashicorp/aws-sdk-go/gen/rds"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
@ -39,15 +40,15 @@ func expandListeners(configured []interface{}) ([]elb.Listener, error) {
|
||||||
|
|
||||||
// Takes the result of flatmap.Expand for an array of ingress/egress
|
// Takes the result of flatmap.Expand for an array of ingress/egress
|
||||||
// security group rules and returns EC2 API compatible objects
|
// security group rules and returns EC2 API compatible objects
|
||||||
func expandIPPerms(id string, configured []interface{}) []ec2.IPPerm {
|
func expandIPPerms(id string, configured []interface{}) []awsEC2.IPPermission {
|
||||||
perms := make([]ec2.IPPerm, len(configured))
|
perms := make([]awsEC2.IPPermission, len(configured))
|
||||||
for i, mRaw := range configured {
|
for i, mRaw := range configured {
|
||||||
var perm ec2.IPPerm
|
var perm awsEC2.IPPermission
|
||||||
m := mRaw.(map[string]interface{})
|
m := mRaw.(map[string]interface{})
|
||||||
|
|
||||||
perm.FromPort = m["from_port"].(int)
|
perm.FromPort = aws.Integer(m["from_port"].(int))
|
||||||
perm.ToPort = m["to_port"].(int)
|
perm.ToPort = aws.Integer(m["to_port"].(int))
|
||||||
perm.Protocol = m["protocol"].(string)
|
perm.IPProtocol = aws.String(m["protocol"].(string))
|
||||||
|
|
||||||
var groups []string
|
var groups []string
|
||||||
if raw, ok := m["security_groups"]; ok {
|
if raw, ok := m["security_groups"]; ok {
|
||||||
|
@ -61,25 +62,25 @@ func expandIPPerms(id string, configured []interface{}) []ec2.IPPerm {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(groups) > 0 {
|
if len(groups) > 0 {
|
||||||
perm.SourceGroups = make([]ec2.UserSecurityGroup, len(groups))
|
perm.UserIDGroupPairs = make([]awsEC2.UserIDGroupPair, len(groups))
|
||||||
for i, name := range groups {
|
for i, name := range groups {
|
||||||
ownerId, id := "", name
|
ownerId, id := "", name
|
||||||
if items := strings.Split(id, "/"); len(items) > 1 {
|
if items := strings.Split(id, "/"); len(items) > 1 {
|
||||||
ownerId, id = items[0], items[1]
|
ownerId, id = items[0], items[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
perm.SourceGroups[i] = ec2.UserSecurityGroup{
|
perm.UserIDGroupPairs[i] = awsEC2.UserIDGroupPair{
|
||||||
Id: id,
|
GroupID: aws.String(id),
|
||||||
OwnerId: ownerId,
|
UserID: aws.String(ownerId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if raw, ok := m["cidr_blocks"]; ok {
|
if raw, ok := m["cidr_blocks"]; ok {
|
||||||
list := raw.([]interface{})
|
list := raw.([]interface{})
|
||||||
perm.SourceIPs = make([]string, len(list))
|
perm.IPRanges = make([]awsEC2.IPRange, len(list))
|
||||||
for i, v := range list {
|
for i, v := range list {
|
||||||
perm.SourceIPs[i] = v.(string)
|
perm.IPRanges[i] = awsEC2.IPRange{aws.String(v.(string))}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,31 +112,6 @@ func expandParameters(configured []interface{}) ([]rds.Parameter, error) {
|
||||||
return parameters, nil
|
return parameters, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flattens an array of ipPerms into a list of primitives that
|
|
||||||
// flatmap.Flatten() can handle
|
|
||||||
func flattenIPPerms(list []ec2.IPPerm) []map[string]interface{} {
|
|
||||||
result := make([]map[string]interface{}, 0, len(list))
|
|
||||||
|
|
||||||
for _, perm := range list {
|
|
||||||
n := make(map[string]interface{})
|
|
||||||
n["from_port"] = perm.FromPort
|
|
||||||
n["protocol"] = perm.Protocol
|
|
||||||
n["to_port"] = perm.ToPort
|
|
||||||
|
|
||||||
if len(perm.SourceIPs) > 0 {
|
|
||||||
n["cidr_blocks"] = perm.SourceIPs
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := flattenSecurityGroups(perm.SourceGroups); len(v) > 0 {
|
|
||||||
n["security_groups"] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flattens a health check into something that flatmap.Flatten()
|
// Flattens a health check into something that flatmap.Flatten()
|
||||||
// can handle
|
// can handle
|
||||||
func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} {
|
func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} {
|
||||||
|
@ -162,6 +138,15 @@ func flattenSecurityGroups(list []ec2.UserSecurityGroup) []string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flattens an array of UserSecurityGroups into a []string
|
||||||
|
func flattenSecurityGroupsSDK(list []awsEC2.UserIDGroupPair) []string {
|
||||||
|
result := make([]string, 0, len(list))
|
||||||
|
for _, g := range list {
|
||||||
|
result = append(result, *g.GroupID)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// Flattens an array of Instances into a []string
|
// Flattens an array of Instances into a []string
|
||||||
func flattenInstances(list []elb.Instance) []string {
|
func flattenInstances(list []elb.Instance) []string {
|
||||||
result := make([]string, 0, len(list))
|
result := make([]string, 0, len(list))
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package aws
|
package aws
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/aws-sdk-go/aws"
|
"github.com/hashicorp/aws-sdk-go/aws"
|
||||||
|
awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2"
|
||||||
"github.com/hashicorp/aws-sdk-go/gen/elb"
|
"github.com/hashicorp/aws-sdk-go/gen/elb"
|
||||||
"github.com/hashicorp/aws-sdk-go/gen/rds"
|
"github.com/hashicorp/aws-sdk-go/gen/rds"
|
||||||
"github.com/hashicorp/terraform/flatmap"
|
"github.com/hashicorp/terraform/flatmap"
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Returns test configuration
|
// Returns test configuration
|
||||||
|
@ -61,120 +62,60 @@ func TestExpandIPPerms(t *testing.T) {
|
||||||
}
|
}
|
||||||
perms := expandIPPerms("foo", expanded)
|
perms := expandIPPerms("foo", expanded)
|
||||||
|
|
||||||
expected := []ec2.IPPerm{
|
log.Printf("wtf is perms:\n%#v", perms)
|
||||||
ec2.IPPerm{
|
|
||||||
Protocol: "icmp",
|
expected := []awsEC2.IPPermission{
|
||||||
FromPort: 1,
|
awsEC2.IPPermission{
|
||||||
ToPort: -1,
|
IPProtocol: aws.String("icmp"),
|
||||||
SourceIPs: []string{"0.0.0.0/0"},
|
FromPort: aws.Integer(1),
|
||||||
SourceGroups: []ec2.UserSecurityGroup{
|
ToPort: aws.Integer(-1),
|
||||||
ec2.UserSecurityGroup{
|
IPRanges: []awsEC2.IPRange{awsEC2.IPRange{aws.String("0.0.0.0/0")}},
|
||||||
OwnerId: "foo",
|
UserIDGroupPairs: []awsEC2.UserIDGroupPair{
|
||||||
Id: "sg-22222",
|
awsEC2.UserIDGroupPair{
|
||||||
|
UserID: aws.String("foo"),
|
||||||
|
GroupID: aws.String("sg-22222"),
|
||||||
},
|
},
|
||||||
ec2.UserSecurityGroup{
|
awsEC2.UserIDGroupPair{
|
||||||
Id: "sg-11111",
|
GroupID: aws.String("sg-22222"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ec2.IPPerm{
|
awsEC2.IPPermission{
|
||||||
Protocol: "icmp",
|
IPProtocol: aws.String("icmp"),
|
||||||
FromPort: 1,
|
FromPort: aws.Integer(1),
|
||||||
ToPort: -1,
|
ToPort: aws.Integer(-1),
|
||||||
SourceGroups: []ec2.UserSecurityGroup{
|
UserIDGroupPairs: []awsEC2.UserIDGroupPair{
|
||||||
ec2.UserSecurityGroup{
|
awsEC2.UserIDGroupPair{
|
||||||
Id: "foo",
|
UserID: aws.String("foo"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(perms, expected) {
|
exp := expected[0]
|
||||||
|
perm := perms[0]
|
||||||
|
|
||||||
|
if *exp.FromPort != *perm.FromPort {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
||||||
perms[0],
|
*perm.FromPort,
|
||||||
expected)
|
*exp.FromPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if *exp.IPRanges[0].CIDRIP != *perm.IPRanges[0].CIDRIP {
|
||||||
|
t.Fatalf(
|
||||||
func TestFlattenIPPerms(t *testing.T) {
|
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
||||||
cases := []struct {
|
*perm.IPRanges[0].CIDRIP,
|
||||||
Input []ec2.IPPerm
|
*exp.IPRanges[0].CIDRIP)
|
||||||
Output []map[string]interface{}
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Input: []ec2.IPPerm{
|
|
||||||
ec2.IPPerm{
|
|
||||||
Protocol: "icmp",
|
|
||||||
FromPort: 1,
|
|
||||||
ToPort: -1,
|
|
||||||
SourceIPs: []string{"0.0.0.0/0"},
|
|
||||||
SourceGroups: []ec2.UserSecurityGroup{
|
|
||||||
ec2.UserSecurityGroup{
|
|
||||||
Id: "sg-11111",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
Output: []map[string]interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"protocol": "icmp",
|
|
||||||
"from_port": 1,
|
|
||||||
"to_port": -1,
|
|
||||||
"cidr_blocks": []string{"0.0.0.0/0"},
|
|
||||||
"security_groups": []string{"sg-11111"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
Input: []ec2.IPPerm{
|
|
||||||
ec2.IPPerm{
|
|
||||||
Protocol: "icmp",
|
|
||||||
FromPort: 1,
|
|
||||||
ToPort: -1,
|
|
||||||
SourceIPs: []string{"0.0.0.0/0"},
|
|
||||||
SourceGroups: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
Output: []map[string]interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"protocol": "icmp",
|
|
||||||
"from_port": 1,
|
|
||||||
"to_port": -1,
|
|
||||||
"cidr_blocks": []string{"0.0.0.0/0"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: []ec2.IPPerm{
|
|
||||||
ec2.IPPerm{
|
|
||||||
Protocol: "icmp",
|
|
||||||
FromPort: 1,
|
|
||||||
ToPort: -1,
|
|
||||||
SourceIPs: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
Output: []map[string]interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"protocol": "icmp",
|
|
||||||
"from_port": 1,
|
|
||||||
"to_port": -1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
if *exp.UserIDGroupPairs[0].UserID != *perm.UserIDGroupPairs[0].UserID {
|
||||||
output := flattenIPPerms(tc.Input)
|
t.Fatalf(
|
||||||
if !reflect.DeepEqual(output, tc.Output) {
|
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
|
||||||
t.Fatalf("Input:\n\n%#v\n\nOutput:\n\n%#v", tc.Input, output)
|
*perm.UserIDGroupPairs[0].UserID,
|
||||||
}
|
*exp.UserIDGroupPairs[0].UserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpandListeners(t *testing.T) {
|
func TestExpandListeners(t *testing.T) {
|
||||||
|
|
|
@ -30,22 +30,25 @@ func Provider() terraform.ResourceProvider {
|
||||||
"timeout": &schema.Schema{
|
"timeout": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Required: true,
|
Required: true,
|
||||||
DefaultFunc: schema.EnvDefaultFunc("CLOUDSTACK_TIMEOUT", 180),
|
DefaultFunc: schema.EnvDefaultFunc("CLOUDSTACK_TIMEOUT", 300),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
"cloudstack_disk": resourceCloudStackDisk(),
|
"cloudstack_disk": resourceCloudStackDisk(),
|
||||||
"cloudstack_egress_firewall": resourceCloudStackEgressFirewall(),
|
"cloudstack_egress_firewall": resourceCloudStackEgressFirewall(),
|
||||||
"cloudstack_firewall": resourceCloudStackFirewall(),
|
"cloudstack_firewall": resourceCloudStackFirewall(),
|
||||||
"cloudstack_instance": resourceCloudStackInstance(),
|
"cloudstack_instance": resourceCloudStackInstance(),
|
||||||
"cloudstack_ipaddress": resourceCloudStackIPAddress(),
|
"cloudstack_ipaddress": resourceCloudStackIPAddress(),
|
||||||
"cloudstack_network": resourceCloudStackNetwork(),
|
"cloudstack_network": resourceCloudStackNetwork(),
|
||||||
"cloudstack_network_acl": resourceCloudStackNetworkACL(),
|
"cloudstack_network_acl": resourceCloudStackNetworkACL(),
|
||||||
"cloudstack_network_acl_rule": resourceCloudStackNetworkACLRule(),
|
"cloudstack_network_acl_rule": resourceCloudStackNetworkACLRule(),
|
||||||
"cloudstack_nic": resourceCloudStackNIC(),
|
"cloudstack_nic": resourceCloudStackNIC(),
|
||||||
"cloudstack_port_forward": resourceCloudStackPortForward(),
|
"cloudstack_port_forward": resourceCloudStackPortForward(),
|
||||||
"cloudstack_vpc": resourceCloudStackVPC(),
|
"cloudstack_vpc": resourceCloudStackVPC(),
|
||||||
|
"cloudstack_vpn_connection": resourceCloudStackVPNConnection(),
|
||||||
|
"cloudstack_vpn_customer_gateway": resourceCloudStackVPNCustomerGateway(),
|
||||||
|
"cloudstack_vpn_gateway": resourceCloudStackVPNGateway(),
|
||||||
},
|
},
|
||||||
|
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
|
|
|
@ -51,7 +51,8 @@ var CLOUDSTACK_NETWORK_1_OFFERING = ""
|
||||||
var CLOUDSTACK_NETWORK_1_IPADDRESS = ""
|
var CLOUDSTACK_NETWORK_1_IPADDRESS = ""
|
||||||
var CLOUDSTACK_NETWORK_2 = ""
|
var CLOUDSTACK_NETWORK_2 = ""
|
||||||
var CLOUDSTACK_NETWORK_2_IPADDRESS = ""
|
var CLOUDSTACK_NETWORK_2_IPADDRESS = ""
|
||||||
var CLOUDSTACK_VPC_CIDR = ""
|
var CLOUDSTACK_VPC_CIDR_1 = ""
|
||||||
|
var CLOUDSTACK_VPC_CIDR_2 = ""
|
||||||
var CLOUDSTACK_VPC_OFFERING = ""
|
var CLOUDSTACK_VPC_OFFERING = ""
|
||||||
var CLOUDSTACK_VPC_NETWORK_CIDR = ""
|
var CLOUDSTACK_VPC_NETWORK_CIDR = ""
|
||||||
var CLOUDSTACK_VPC_NETWORK_OFFERING = ""
|
var CLOUDSTACK_VPC_NETWORK_OFFERING = ""
|
||||||
|
|
|
@ -95,18 +95,18 @@ func resourceCloudStackInstanceCreate(d *schema.ResourceData, meta interface{})
|
||||||
return e.Error()
|
return e.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the template UUID
|
|
||||||
templateid, e := retrieveUUID(cs, "template", d.Get("template").(string))
|
|
||||||
if e != nil {
|
|
||||||
return e.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the zone object
|
// Retrieve the zone object
|
||||||
zone, _, err := cs.Zone.GetZoneByName(d.Get("zone").(string))
|
zone, _, err := cs.Zone.GetZoneByName(d.Get("zone").(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve the template UUID
|
||||||
|
templateid, e := retrieveTemplateUUID(cs, zone.Id, d.Get("template").(string))
|
||||||
|
if e != nil {
|
||||||
|
return e.Error()
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new parameter struct
|
// Create a new parameter struct
|
||||||
p := cs.VirtualMachine.NewDeployVirtualMachineParams(serviceofferingid, templateid, zone.Id)
|
p := cs.VirtualMachine.NewDeployVirtualMachineParams(serviceofferingid, templateid, zone.Id)
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,6 @@ resource "cloudstack_vpc" "foobar" {
|
||||||
resource "cloudstack_ipaddress" "foo" {
|
resource "cloudstack_ipaddress" "foo" {
|
||||||
vpc = "${cloudstack_vpc.foobar.name}"
|
vpc = "${cloudstack_vpc.foobar.name}"
|
||||||
}`,
|
}`,
|
||||||
CLOUDSTACK_VPC_CIDR,
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
CLOUDSTACK_VPC_OFFERING,
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
CLOUDSTACK_ZONE)
|
CLOUDSTACK_ZONE)
|
||||||
|
|
|
@ -196,7 +196,7 @@ resource "cloudstack_network_acl_rule" "foo" {
|
||||||
traffic_type = "ingress"
|
traffic_type = "ingress"
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
CLOUDSTACK_VPC_CIDR,
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
CLOUDSTACK_VPC_OFFERING,
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
CLOUDSTACK_ZONE)
|
CLOUDSTACK_ZONE)
|
||||||
|
|
||||||
|
@ -233,6 +233,6 @@ resource "cloudstack_network_acl_rule" "foo" {
|
||||||
traffic_type = "egress"
|
traffic_type = "egress"
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
CLOUDSTACK_VPC_CIDR,
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
CLOUDSTACK_VPC_OFFERING,
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
CLOUDSTACK_ZONE)
|
CLOUDSTACK_ZONE)
|
||||||
|
|
|
@ -112,6 +112,6 @@ resource "cloudstack_network_acl" "foo" {
|
||||||
description = "terraform-acl-text"
|
description = "terraform-acl-text"
|
||||||
vpc = "${cloudstack_vpc.foobar.name}"
|
vpc = "${cloudstack_vpc.foobar.name}"
|
||||||
}`,
|
}`,
|
||||||
CLOUDSTACK_VPC_CIDR,
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
CLOUDSTACK_VPC_OFFERING,
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
CLOUDSTACK_ZONE)
|
CLOUDSTACK_ZONE)
|
||||||
|
|
|
@ -186,7 +186,7 @@ resource "cloudstack_network" "foo" {
|
||||||
aclid = "${cloudstack_network_acl.foo.id}"
|
aclid = "${cloudstack_network_acl.foo.id}"
|
||||||
zone = "${cloudstack_vpc.foobar.zone}"
|
zone = "${cloudstack_vpc.foobar.zone}"
|
||||||
}`,
|
}`,
|
||||||
CLOUDSTACK_VPC_CIDR,
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
CLOUDSTACK_VPC_OFFERING,
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
CLOUDSTACK_ZONE,
|
CLOUDSTACK_ZONE,
|
||||||
CLOUDSTACK_VPC_NETWORK_CIDR,
|
CLOUDSTACK_VPC_NETWORK_CIDR,
|
||||||
|
|
|
@ -72,8 +72,8 @@ func testAccCheckCloudStackVPCAttributes(
|
||||||
return fmt.Errorf("Bad display text: %s", vpc.Displaytext)
|
return fmt.Errorf("Bad display text: %s", vpc.Displaytext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vpc.Cidr != CLOUDSTACK_VPC_CIDR {
|
if vpc.Cidr != CLOUDSTACK_VPC_CIDR_1 {
|
||||||
return fmt.Errorf("Bad VPC offering: %s", vpc.Cidr)
|
return fmt.Errorf("Bad VPC CIDR: %s", vpc.Cidr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -113,6 +113,6 @@ resource "cloudstack_vpc" "foo" {
|
||||||
vpc_offering = "%s"
|
vpc_offering = "%s"
|
||||||
zone = "%s"
|
zone = "%s"
|
||||||
}`,
|
}`,
|
||||||
CLOUDSTACK_VPC_CIDR,
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
CLOUDSTACK_VPC_OFFERING,
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
CLOUDSTACK_ZONE)
|
CLOUDSTACK_ZONE)
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package cloudstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceCloudStackVPNConnection() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceCloudStackVPNConnectionCreate,
|
||||||
|
Read: resourceCloudStackVPNConnectionRead,
|
||||||
|
Delete: resourceCloudStackVPNConnectionDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"customergatewayid": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"vpngatewayid": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNConnectionCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewCreateVpnConnectionParams(
|
||||||
|
d.Get("customergatewayid").(string),
|
||||||
|
d.Get("vpngatewayid").(string),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create the new VPN Connection
|
||||||
|
v, err := cs.VPN.CreateVpnConnection(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating VPN Connection: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(v.Id)
|
||||||
|
|
||||||
|
return resourceCloudStackVPNConnectionRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNConnectionRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Get the VPN Connection details
|
||||||
|
v, count, err := cs.VPN.GetVpnConnectionByID(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if count == 0 {
|
||||||
|
log.Printf("[DEBUG] VPN Connection does no longer exist")
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("customergatewayid", v.S2scustomergatewayid)
|
||||||
|
d.Set("vpngatewayid", v.S2svpngatewayid)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNConnectionDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewDeleteVpnConnectionParams(d.Id())
|
||||||
|
|
||||||
|
// Delete the VPN Connection
|
||||||
|
_, err := cs.VPN.DeleteVpnConnection(p)
|
||||||
|
if err != nil {
|
||||||
|
// This is a very poor way to be told the UUID does no longer exist :(
|
||||||
|
if strings.Contains(err.Error(), fmt.Sprintf(
|
||||||
|
"Invalid parameter id value=%s due to incorrect long value format, "+
|
||||||
|
"or entity does not exist", d.Id())) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error deleting VPN Connection: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package cloudstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccCloudStackVPNConnection_basic(t *testing.T) {
|
||||||
|
var vpnConnection cloudstack.VpnConnection
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckCloudStackVPNConnectionDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCloudStackVPNConnection_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudStackVPNConnectionExists(
|
||||||
|
"cloudstack_vpn_connection.foo-bar", &vpnConnection),
|
||||||
|
testAccCheckCloudStackVPNConnectionExists(
|
||||||
|
"cloudstack_vpn_connection.bar-foo", &vpnConnection),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNConnectionExists(
|
||||||
|
n string, vpnConnection *cloudstack.VpnConnection) 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 VPN Connection ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
|
||||||
|
v, _, err := cs.VPN.GetVpnConnectionByID(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("VPN Connection not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
*vpnConnection = *v
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNConnectionDestroy(s *terraform.State) error {
|
||||||
|
cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "cloudstack_vpn_connection" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No VPN Connection ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := cs.VPN.NewDeleteVpnConnectionParams(rs.Primary.ID)
|
||||||
|
_, err := cs.VPN.DeleteVpnConnection(p)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error deleting VPN Connection (%s): %s",
|
||||||
|
rs.Primary.ID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testAccCloudStackVPNConnection_basic = fmt.Sprintf(`
|
||||||
|
resource "cloudstack_vpc" "foo" {
|
||||||
|
name = "terraform-vpc-foo"
|
||||||
|
cidr = "%s"
|
||||||
|
vpc_offering = "%s"
|
||||||
|
zone = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpc" "bar" {
|
||||||
|
name = "terraform-vpc-bar"
|
||||||
|
cidr = "%s"
|
||||||
|
vpc_offering = "%s"
|
||||||
|
zone = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_gateway" "foo" {
|
||||||
|
vpc = "${cloudstack_vpc.foo.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_gateway" "bar" {
|
||||||
|
vpc = "${cloudstack_vpc.bar.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "foo" {
|
||||||
|
name = "terraform-foo"
|
||||||
|
cidr = "${cloudstack_vpc.foo.cidr}"
|
||||||
|
esp_policy = "aes256-sha1"
|
||||||
|
gateway = "${cloudstack_vpn_gateway.foo.public_ip}"
|
||||||
|
ike_policy = "aes256-sha1"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "bar" {
|
||||||
|
name = "terraform-bar"
|
||||||
|
cidr = "${cloudstack_vpc.bar.cidr}"
|
||||||
|
esp_policy = "aes256-sha1"
|
||||||
|
gateway = "${cloudstack_vpn_gateway.bar.public_ip}"
|
||||||
|
ike_policy = "aes256-sha1"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_connection" "foo-bar" {
|
||||||
|
customergatewayid = "${cloudstack_vpn_customer_gateway.foo.id}"
|
||||||
|
vpngatewayid = "${cloudstack_vpn_gateway.bar.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_connection" "bar-foo" {
|
||||||
|
customergatewayid = "${cloudstack_vpn_customer_gateway.bar.id}"
|
||||||
|
vpngatewayid = "${cloudstack_vpn_gateway.foo.id}"
|
||||||
|
}`,
|
||||||
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
|
CLOUDSTACK_ZONE,
|
||||||
|
CLOUDSTACK_VPC_CIDR_2,
|
||||||
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
|
CLOUDSTACK_ZONE)
|
|
@ -0,0 +1,193 @@
|
||||||
|
package cloudstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceCloudStackVPNCustomerGateway() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceCloudStackVPNCustomerGatewayCreate,
|
||||||
|
Read: resourceCloudStackVPNCustomerGatewayRead,
|
||||||
|
Update: resourceCloudStackVPNCustomerGatewayUpdate,
|
||||||
|
Delete: resourceCloudStackVPNCustomerGatewayDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cidr": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"esp_policy": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"gateway": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ike_policy": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ipsec_psk": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"dpd": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"esp_lifetime": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ike_lifetime": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNCustomerGatewayCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewCreateVpnCustomerGatewayParams(
|
||||||
|
d.Get("cidr").(string),
|
||||||
|
d.Get("esp_policy").(string),
|
||||||
|
d.Get("gateway").(string),
|
||||||
|
d.Get("ike_policy").(string),
|
||||||
|
d.Get("ipsec_psk").(string),
|
||||||
|
)
|
||||||
|
|
||||||
|
p.SetName(d.Get("name").(string))
|
||||||
|
|
||||||
|
if dpd, ok := d.GetOk("dpd"); ok {
|
||||||
|
p.SetDpd(dpd.(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
if esplifetime, ok := d.GetOk("esp_lifetime"); ok {
|
||||||
|
p.SetEsplifetime(esplifetime.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ikelifetime, ok := d.GetOk("ike_lifetime"); ok {
|
||||||
|
p.SetIkelifetime(ikelifetime.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the new VPN Customer Gateway
|
||||||
|
v, err := cs.VPN.CreateVpnCustomerGateway(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating VPN Customer Gateway %s: %s", d.Get("name").(string), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(v.Id)
|
||||||
|
|
||||||
|
return resourceCloudStackVPNCustomerGatewayRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNCustomerGatewayRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Get the VPN Customer Gateway details
|
||||||
|
v, count, err := cs.VPN.GetVpnCustomerGatewayByID(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if count == 0 {
|
||||||
|
log.Printf(
|
||||||
|
"[DEBUG] VPN Customer Gateway %s does no longer exist", d.Get("name").(string))
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", v.Name)
|
||||||
|
d.Set("cidr", v.Cidrlist)
|
||||||
|
d.Set("esp_policy", v.Esppolicy)
|
||||||
|
d.Set("gateway", v.Gateway)
|
||||||
|
d.Set("ike_policy", v.Ikepolicy)
|
||||||
|
d.Set("ipsec_psk", v.Ipsecpsk)
|
||||||
|
d.Set("dpd", v.Dpd)
|
||||||
|
d.Set("esp_lifetime", v.Esplifetime)
|
||||||
|
d.Set("ike_lifetime", v.Ikelifetime)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNCustomerGatewayUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewUpdateVpnCustomerGatewayParams(
|
||||||
|
d.Get("cidr").(string),
|
||||||
|
d.Get("esp_policy").(string),
|
||||||
|
d.Get("gateway").(string),
|
||||||
|
d.Id(),
|
||||||
|
d.Get("ike_policy").(string),
|
||||||
|
d.Get("ipsec_psk").(string),
|
||||||
|
)
|
||||||
|
|
||||||
|
p.SetName(d.Get("name").(string))
|
||||||
|
|
||||||
|
if dpd, ok := d.GetOk("dpd"); ok {
|
||||||
|
p.SetDpd(dpd.(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
if esplifetime, ok := d.GetOk("esp_lifetime"); ok {
|
||||||
|
p.SetEsplifetime(esplifetime.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ikelifetime, ok := d.GetOk("ike_lifetime"); ok {
|
||||||
|
p.SetIkelifetime(ikelifetime.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the VPN Customer Gateway
|
||||||
|
_, err := cs.VPN.UpdateVpnCustomerGateway(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating VPN Customer Gateway %s: %s", d.Get("name").(string), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceCloudStackVPNCustomerGatewayRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNCustomerGatewayDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewDeleteVpnCustomerGatewayParams(d.Id())
|
||||||
|
|
||||||
|
// Delete the VPN Customer Gateway
|
||||||
|
_, err := cs.VPN.DeleteVpnCustomerGateway(p)
|
||||||
|
if err != nil {
|
||||||
|
// This is a very poor way to be told the UUID does no longer exist :(
|
||||||
|
if strings.Contains(err.Error(), fmt.Sprintf(
|
||||||
|
"Invalid parameter id value=%s due to incorrect long value format, "+
|
||||||
|
"or entity does not exist", d.Id())) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error deleting VPN Customer Gateway %s: %s", d.Get("name").(string), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,223 @@
|
||||||
|
package cloudstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccCloudStackVPNCustomerGateway_basic(t *testing.T) {
|
||||||
|
var vpnCustomerGateway cloudstack.VpnCustomerGateway
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckCloudStackVPNCustomerGatewayDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCloudStackVPNCustomerGateway_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudStackVPNCustomerGatewayExists(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", &vpnCustomerGateway),
|
||||||
|
testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", "name", "terraform-foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.bar", "name", "terraform-bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", "ike_policy", "aes256-sha1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.bar", "esp_policy", "aes256-sha1"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccCloudStackVPNCustomerGateway_update(t *testing.T) {
|
||||||
|
var vpnCustomerGateway cloudstack.VpnCustomerGateway
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckCloudStackVPNCustomerGatewayDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCloudStackVPNCustomerGateway_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudStackVPNCustomerGatewayExists(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", &vpnCustomerGateway),
|
||||||
|
testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", "name", "terraform-foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.bar", "name", "terraform-bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", "ike_policy", "aes256-sha1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.bar", "esp_policy", "aes256-sha1"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCloudStackVPNCustomerGateway_update,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudStackVPNCustomerGatewayExists(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", &vpnCustomerGateway),
|
||||||
|
testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", "name", "terraform-foo-bar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.bar", "name", "terraform-bar-foo"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.foo", "ike_policy", "3des-md5"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_customer_gateway.bar", "esp_policy", "3des-md5"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNCustomerGatewayExists(
|
||||||
|
n string, vpnCustomerGateway *cloudstack.VpnCustomerGateway) 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 VPN CustomerGateway ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
|
||||||
|
v, _, err := cs.VPN.GetVpnCustomerGatewayByID(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("VPN CustomerGateway not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
*vpnCustomerGateway = *v
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNCustomerGatewayAttributes(
|
||||||
|
vpnCustomerGateway *cloudstack.VpnCustomerGateway) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
|
||||||
|
if vpnCustomerGateway.Esppolicy != "aes256-sha1" {
|
||||||
|
return fmt.Errorf("Bad ESP policy: %s", vpnCustomerGateway.Esppolicy)
|
||||||
|
}
|
||||||
|
|
||||||
|
if vpnCustomerGateway.Ikepolicy != "aes256-sha1" {
|
||||||
|
return fmt.Errorf("Bad IKE policy: %s", vpnCustomerGateway.Ikepolicy)
|
||||||
|
}
|
||||||
|
|
||||||
|
if vpnCustomerGateway.Ipsecpsk != "terraform" {
|
||||||
|
return fmt.Errorf("Bad IPSEC pre-shared key: %s", vpnCustomerGateway.Ipsecpsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNCustomerGatewayDestroy(s *terraform.State) error {
|
||||||
|
cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "cloudstack_vpn_customer_gateway" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No VPN Customer Gateway ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := cs.VPN.NewDeleteVpnCustomerGatewayParams(rs.Primary.ID)
|
||||||
|
_, err := cs.VPN.DeleteVpnCustomerGateway(p)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error deleting VPN Customer Gateway (%s): %s",
|
||||||
|
rs.Primary.ID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testAccCloudStackVPNCustomerGateway_basic = fmt.Sprintf(`
|
||||||
|
resource "cloudstack_vpc" "foo" {
|
||||||
|
name = "terraform-vpc-foo"
|
||||||
|
cidr = "%s"
|
||||||
|
vpc_offering = "%s"
|
||||||
|
zone = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpc" "bar" {
|
||||||
|
name = "terraform-vpc-bar"
|
||||||
|
cidr = "%s"
|
||||||
|
vpc_offering = "%s"
|
||||||
|
zone = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_gateway" "foo" {
|
||||||
|
vpc = "${cloudstack_vpc.foo.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_gateway" "bar" {
|
||||||
|
vpc = "${cloudstack_vpc.bar.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "foo" {
|
||||||
|
name = "terraform-foo"
|
||||||
|
cidr = "${cloudstack_vpc.foo.cidr}"
|
||||||
|
esp_policy = "aes256-sha1"
|
||||||
|
gateway = "${cloudstack_vpn_gateway.foo.public_ip}"
|
||||||
|
ike_policy = "aes256-sha1"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "bar" {
|
||||||
|
name = "terraform-bar"
|
||||||
|
cidr = "${cloudstack_vpc.bar.cidr}"
|
||||||
|
esp_policy = "aes256-sha1"
|
||||||
|
gateway = "${cloudstack_vpn_gateway.bar.public_ip}"
|
||||||
|
ike_policy = "aes256-sha1"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}`,
|
||||||
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
|
CLOUDSTACK_ZONE,
|
||||||
|
CLOUDSTACK_VPC_CIDR_2,
|
||||||
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
|
CLOUDSTACK_ZONE)
|
||||||
|
|
||||||
|
var testAccCloudStackVPNCustomerGateway_update = fmt.Sprintf(`
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "foo" {
|
||||||
|
name = "terraform-foo-bar"
|
||||||
|
cidr = "${cloudstack_vpc.foo.cidr}"
|
||||||
|
esp_policy = "3des-md5"
|
||||||
|
gateway = "${cloudstack_vpn_gateway.foo.public_ip}"
|
||||||
|
ike_policy = "3des-md5"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "bar" {
|
||||||
|
name = "terraform-bar-foo"
|
||||||
|
cidr = "${cloudstack_vpc.bar.cidr}"
|
||||||
|
esp_policy = "3des-md5"
|
||||||
|
gateway = "${cloudstack_vpn_gateway.bar.public_ip}"
|
||||||
|
ike_policy = "3des-md5"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}`)
|
|
@ -0,0 +1,97 @@
|
||||||
|
package cloudstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceCloudStackVPNGateway() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceCloudStackVPNGatewayCreate,
|
||||||
|
Read: resourceCloudStackVPNGatewayRead,
|
||||||
|
Delete: resourceCloudStackVPNGatewayDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"vpc": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"public_ip": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNGatewayCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Retrieve the VPC UUID
|
||||||
|
vpcid, e := retrieveUUID(cs, "vpc", d.Get("vpc").(string))
|
||||||
|
if e != nil {
|
||||||
|
return e.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewCreateVpnGatewayParams(vpcid)
|
||||||
|
|
||||||
|
// Create the new VPN Gateway
|
||||||
|
v, err := cs.VPN.CreateVpnGateway(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating VPN Gateway for VPC %s: %s", d.Get("vpc").(string), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(v.Id)
|
||||||
|
|
||||||
|
return resourceCloudStackVPNGatewayRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNGatewayRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Get the VPN Gateway details
|
||||||
|
v, count, err := cs.VPN.GetVpnGatewayByID(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if count == 0 {
|
||||||
|
log.Printf(
|
||||||
|
"[DEBUG] VPN Gateway for VPC %s does no longer exist", d.Get("vpc").(string))
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("public_ip", v.Publicip)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCloudStackVPNGatewayDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
cs := meta.(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
// Create a new parameter struct
|
||||||
|
p := cs.VPN.NewDeleteVpnGatewayParams(d.Id())
|
||||||
|
|
||||||
|
// Delete the VPN Gateway
|
||||||
|
_, err := cs.VPN.DeleteVpnGateway(p)
|
||||||
|
if err != nil {
|
||||||
|
// This is a very poor way to be told the UUID does no longer exist :(
|
||||||
|
if strings.Contains(err.Error(), fmt.Sprintf(
|
||||||
|
"Invalid parameter id value=%s due to incorrect long value format, "+
|
||||||
|
"or entity does not exist", d.Id())) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error deleting VPN Gateway for VPC %s: %s", d.Get("vpc").(string), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package cloudstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccCloudStackVPNGateway_basic(t *testing.T) {
|
||||||
|
var vpnGateway cloudstack.VpnGateway
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckCloudStackVPNGatewayDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCloudStackVPNGateway_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudStackVPNGatewayExists(
|
||||||
|
"cloudstack_vpn_gateway.foo", &vpnGateway),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"cloudstack_vpn_gateway.foo", "vpc", "terraform-vpc"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNGatewayExists(
|
||||||
|
n string, vpnGateway *cloudstack.VpnGateway) 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 VPN Gateway ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
|
||||||
|
v, _, err := cs.VPN.GetVpnGatewayByID(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("VPN Gateway not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
*vpnGateway = *v
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCloudStackVPNGatewayDestroy(s *terraform.State) error {
|
||||||
|
cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "cloudstack_vpn_gateway" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No VPN Gateway ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := cs.VPN.NewDeleteVpnGatewayParams(rs.Primary.ID)
|
||||||
|
_, err := cs.VPN.DeleteVpnGateway(p)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error deleting VPN Gateway (%s): %s",
|
||||||
|
rs.Primary.ID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testAccCloudStackVPNGateway_basic = fmt.Sprintf(`
|
||||||
|
resource "cloudstack_vpc" "foo" {
|
||||||
|
name = "terraform-vpc"
|
||||||
|
display_text = "terraform-vpc-text"
|
||||||
|
cidr = "%s"
|
||||||
|
vpc_offering = "%s"
|
||||||
|
zone = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "cloudstack_vpn_gateway" "foo" {
|
||||||
|
vpc = "${cloudstack_vpc.foo.name}"
|
||||||
|
}`,
|
||||||
|
CLOUDSTACK_VPC_CIDR_1,
|
||||||
|
CLOUDSTACK_VPC_OFFERING,
|
||||||
|
CLOUDSTACK_ZONE)
|
|
@ -40,8 +40,6 @@ func retrieveUUID(cs *cloudstack.CloudStackClient, name, value string) (uuid str
|
||||||
uuid, err = cs.VPC.GetVPCOfferingID(value)
|
uuid, err = cs.VPC.GetVPCOfferingID(value)
|
||||||
case "vpc":
|
case "vpc":
|
||||||
uuid, err = cs.VPC.GetVPCID(value)
|
uuid, err = cs.VPC.GetVPCID(value)
|
||||||
case "template":
|
|
||||||
uuid, err = cs.Template.GetTemplateID(value, "executable")
|
|
||||||
case "network":
|
case "network":
|
||||||
uuid, err = cs.Network.GetNetworkID(value)
|
uuid, err = cs.Network.GetNetworkID(value)
|
||||||
case "zone":
|
case "zone":
|
||||||
|
@ -71,6 +69,22 @@ func retrieveUUID(cs *cloudstack.CloudStackClient, name, value string) (uuid str
|
||||||
return uuid, nil
|
return uuid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func retrieveTemplateUUID(cs *cloudstack.CloudStackClient, zoneid, value string) (uuid string, e *retrieveError) {
|
||||||
|
// If the supplied value isn't a UUID, try to retrieve the UUID ourselves
|
||||||
|
if isUUID(value) {
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Retrieving UUID of template: %s", value)
|
||||||
|
|
||||||
|
uuid, err := cs.Template.GetTemplateID(value, "executable", zoneid)
|
||||||
|
if err != nil {
|
||||||
|
return uuid, &retrieveError{name: "template", value: value, err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid, nil
|
||||||
|
}
|
||||||
|
|
||||||
func isUUID(s string) bool {
|
func isUUID(s string) bool {
|
||||||
re := regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
|
re := regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
|
||||||
return re.MatchString(s)
|
return re.MatchString(s)
|
||||||
|
|
|
@ -58,4 +58,4 @@ The `rule` block supports:
|
||||||
|
|
||||||
The following attributes are exported:
|
The following attributes are exported:
|
||||||
|
|
||||||
* `ID` - The network ID for which the egress firewall rules are created.
|
* `id` - The network ID for which the egress firewall rules are created.
|
||||||
|
|
|
@ -58,4 +58,4 @@ The `rule` block supports:
|
||||||
|
|
||||||
The following attributes are exported:
|
The following attributes are exported:
|
||||||
|
|
||||||
* `ID` - The IP address ID for which the firewall rules are created.
|
* `id` - The IP address ID for which the firewall rules are created.
|
||||||
|
|
|
@ -66,4 +66,4 @@ The `rule` block supports:
|
||||||
|
|
||||||
The following attributes are exported:
|
The following attributes are exported:
|
||||||
|
|
||||||
* `ID` - The ACL ID for which the rules are created.
|
* `id` - The ACL ID for which the rules are created.
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
layout: "cloudstack"
|
||||||
|
page_title: "CloudStack: cloudstack_vpn_connection"
|
||||||
|
sidebar_current: "docs-cloudstack-resource-vpn-connection"
|
||||||
|
description: |-
|
||||||
|
Creates a site to site VPN connection.
|
||||||
|
---
|
||||||
|
|
||||||
|
# cloudstack\_vpn\_connection
|
||||||
|
|
||||||
|
Creates a site to site VPN connection.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
Basic usage:
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "cloudstack_vpn_connection" "default" {
|
||||||
|
customergatewayid = "xxx"
|
||||||
|
vpngatewayid = "xxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `customergatewayid` - (Required) The Customer Gateway ID to connect.
|
||||||
|
Changing this forces a new resource to be created.
|
||||||
|
|
||||||
|
* `vpngatewayid` - (Required) The VPN Gateway ID to connect.
|
||||||
|
Changing this forces a new resource to be created.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The ID of the VPN Connection.
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
layout: "cloudstack"
|
||||||
|
page_title: "CloudStack: cloudstack_vpn_customer_gateway"
|
||||||
|
sidebar_current: "docs-cloudstack-resource-vpn-customer-gateway"
|
||||||
|
description: |-
|
||||||
|
Creates a site to site VPN local customer gateway.
|
||||||
|
---
|
||||||
|
|
||||||
|
# cloudstack\_vpn\_customer\_gateway
|
||||||
|
|
||||||
|
Creates a site to site VPN local customer gateway.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
Basic usage:
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "cloudstack_vpn_customer_gateway" "default" {
|
||||||
|
name = "test-vpc"
|
||||||
|
cidr = "10.0.0.0/8"
|
||||||
|
esp_policy = "aes256-sha1"
|
||||||
|
gateway = "192.168.0.1"
|
||||||
|
ike_policy = "aes256-sha1"
|
||||||
|
ipsec_psk = "terraform"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the VPN Customer Gateway.
|
||||||
|
|
||||||
|
* `cidr` - (Required) The CIDR block that needs to be routed through this gateway.
|
||||||
|
|
||||||
|
* `esp_policy` - (Required) The ESP policy to use for this VPN Customer Gateway.
|
||||||
|
|
||||||
|
* `gateway` - (Required) The public IP address of the related VPN Gateway.
|
||||||
|
|
||||||
|
* `ike_policy` - (Required) The IKE policy to use for this VPN Customer Gateway.
|
||||||
|
|
||||||
|
* `ipsec_psk` - (Required) The IPSEC pre-shared key used for this gateway.
|
||||||
|
|
||||||
|
* `dpd` - (Optional) If DPD is enabled for the related VPN connection (defaults false)
|
||||||
|
|
||||||
|
* `esp_lifetime` - (Optional) The ESP lifetime of phase 2 VPN connection to this
|
||||||
|
VPN Customer Gateway in seconds (defaults 86400)
|
||||||
|
|
||||||
|
* `ike_lifetime` - (Optional) The IKE lifetime of phase 2 VPN connection to this
|
||||||
|
VPN Customer Gateway in seconds (defaults 86400)
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The ID of the VPN Customer Gateway.
|
||||||
|
* `dpd` - Enable or disable DPD is enabled for the related VPN connection.
|
||||||
|
* `esp_lifetime` - The ESP lifetime of phase 2 VPN connection to this VPN Customer Gateway.
|
||||||
|
* `ike_lifetime` - The IKE lifetime of phase 2 VPN connection to this VPN Customer Gateway.
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
layout: "cloudstack"
|
||||||
|
page_title: "CloudStack: cloudstack_vpn_gateway"
|
||||||
|
sidebar_current: "docs-cloudstack-resource-vpn-gateway"
|
||||||
|
description: |-
|
||||||
|
Creates a site to site VPN local gateway.
|
||||||
|
---
|
||||||
|
|
||||||
|
# cloudstack\_vpn\_gateway
|
||||||
|
|
||||||
|
Creates a site to site VPN local gateway.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
Basic usage:
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "cloudstack_vpn_gateway" "default" {
|
||||||
|
vpc = "test-vpc"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `vpc` - (Required) The name of the VPC for which to create the VPN Gateway.
|
||||||
|
Changing this forces a new resource to be created.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The ID of the VPN Gateway.
|
||||||
|
* `public_ip` - The public IP address associated with the VPN Gateway.
|
|
@ -1,66 +1,78 @@
|
||||||
<% wrap_layout :inner do %>
|
<% wrap_layout :inner do %>
|
||||||
<% content_for :sidebar do %>
|
<% content_for :sidebar do %>
|
||||||
<div class="docs-sidebar hidden-print affix-top" role="complementary">
|
<div class="docs-sidebar hidden-print affix-top" role="complementary">
|
||||||
<ul class="nav docs-sidenav">
|
<ul class="nav docs-sidenav">
|
||||||
<li<%= sidebar_current("docs-home") %>>
|
<li<%= sidebar_current("docs-home") %>>
|
||||||
<a href="/docs/index.html">« Documentation Home</a>
|
<a href="/docs/index.html">« Documentation Home</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-index") %>>
|
<li<%= sidebar_current("docs-cloudstack-index") %>>
|
||||||
<a href="/docs/providers/cloudstack/index.html">CloudStack Provider</a>
|
<a href="/docs/providers/cloudstack/index.html">CloudStack Provider</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource") %>>
|
||||||
<a href="#">Resources</a>
|
<a href="#">Resources</a>
|
||||||
<ul class="nav nav-visible">
|
<ul class="nav nav-visible">
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-disk") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-disk") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/disk.html">cloudstack_disk</a>
|
<a href="/docs/providers/cloudstack/r/disk.html">cloudstack_disk</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-egress-firewall") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-egress-firewall") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/egress_firewall.html">cloudstack_egress_firewall</a>
|
<a href="/docs/providers/cloudstack/r/egress_firewall.html">cloudstack_egress_firewall</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-firewall") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-firewall") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/firewall.html">cloudstack_firewall</a>
|
<a href="/docs/providers/cloudstack/r/firewall.html">cloudstack_firewall</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-instance") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-instance") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/instance.html">cloudstack_instance</a>
|
<a href="/docs/providers/cloudstack/r/instance.html">cloudstack_instance</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-ipaddress") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-ipaddress") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/ipaddress.html">cloudstack_ipaddress</a>
|
<a href="/docs/providers/cloudstack/r/ipaddress.html">cloudstack_ipaddress</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-network") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-network") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/network.html">cloudstack_network</a>
|
<a href="/docs/providers/cloudstack/r/network.html">cloudstack_network</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-network-acl") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-network-acl") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/network_acl.html">cloudstack_network_acl</a>
|
<a href="/docs/providers/cloudstack/r/network_acl.html">cloudstack_network_acl</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-network-acl-rule") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-network-acl-rule") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/network_acl_rule.html">cloudstack_network_acl_rule</a>
|
<a href="/docs/providers/cloudstack/r/network_acl_rule.html">cloudstack_network_acl_rule</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-nic") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-nic") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/nic.html">cloudstack_nic</a>
|
<a href="/docs/providers/cloudstack/r/nic.html">cloudstack_nic</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-port-forward") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-port-forward") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/port_forward.html">cloudstack_port_forward</a>
|
<a href="/docs/providers/cloudstack/r/port_forward.html">cloudstack_port_forward</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-cloudstack-resource-vpc") %>>
|
<li<%= sidebar_current("docs-cloudstack-resource-vpc") %>>
|
||||||
<a href="/docs/providers/cloudstack/r/vpc.html">cloudstack_vpc</a>
|
<a href="/docs/providers/cloudstack/r/vpc.html">cloudstack_vpc</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= yield %>
|
<li<%= sidebar_current("docs-cloudstack-resource-vpn-gateway") %>>
|
||||||
<% end %>
|
<a href="/docs/providers/cloudstack/r/vpn_gateway.html">cloudstack_vpn_gateway</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-cloudstack-resource-vpn-customer-gateway") %>>
|
||||||
|
<a href="/docs/providers/cloudstack/r/vpn_customer_gateway.html">cloudstack_vpn_customer_gateway</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-cloudstack-resource-vpn-connection") %>>
|
||||||
|
<a href="/docs/providers/cloudstack/r/vpn_connection.html">cloudstack_vpn_connection</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= yield %>
|
||||||
|
<% end %>
|
||||||
|
|
Loading…
Reference in New Issue