github.com/adrian-bl/terraform@v0.7.0-rc2.0.20160705220747-de0a34fc3517/builtin/providers/aws/resource_aws_vpc_peering_connection.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/aws/awserr" 10 "github.com/aws/aws-sdk-go/service/ec2" 11 "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 func resourceAwsVpcPeeringConnection() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceAwsVPCPeeringCreate, 18 Read: resourceAwsVPCPeeringRead, 19 Update: resourceAwsVPCPeeringUpdate, 20 Delete: resourceAwsVPCPeeringDelete, 21 Importer: &schema.ResourceImporter{ 22 State: schema.ImportStatePassthrough, 23 }, 24 25 Schema: map[string]*schema.Schema{ 26 "peer_owner_id": &schema.Schema{ 27 Type: schema.TypeString, 28 Required: true, 29 ForceNew: true, 30 DefaultFunc: schema.EnvDefaultFunc("AWS_ACCOUNT_ID", nil), 31 }, 32 "peer_vpc_id": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 ForceNew: true, 36 }, 37 "vpc_id": &schema.Schema{ 38 Type: schema.TypeString, 39 Required: true, 40 ForceNew: true, 41 }, 42 "auto_accept": &schema.Schema{ 43 Type: schema.TypeBool, 44 Optional: true, 45 }, 46 "accept_status": &schema.Schema{ 47 Type: schema.TypeString, 48 Computed: true, 49 }, 50 "tags": tagsSchema(), 51 }, 52 } 53 } 54 55 func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error { 56 conn := meta.(*AWSClient).ec2conn 57 58 // Create the vpc peering connection 59 createOpts := &ec2.CreateVpcPeeringConnectionInput{ 60 PeerOwnerId: aws.String(d.Get("peer_owner_id").(string)), 61 PeerVpcId: aws.String(d.Get("peer_vpc_id").(string)), 62 VpcId: aws.String(d.Get("vpc_id").(string)), 63 } 64 log.Printf("[DEBUG] VPCPeeringCreate create config: %#v", createOpts) 65 resp, err := conn.CreateVpcPeeringConnection(createOpts) 66 if err != nil { 67 return fmt.Errorf("Error creating vpc peering connection: %s", err) 68 } 69 70 // Get the ID and store it 71 rt := resp.VpcPeeringConnection 72 d.SetId(*rt.VpcPeeringConnectionId) 73 log.Printf("[INFO] VPC Peering Connection ID: %s", d.Id()) 74 75 // Wait for the vpc peering connection to become available 76 log.Printf( 77 "[DEBUG] Waiting for vpc peering connection (%s) to become available", 78 d.Id()) 79 stateConf := &resource.StateChangeConf{ 80 Pending: []string{"pending"}, 81 Target: []string{"pending-acceptance"}, 82 Refresh: resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id()), 83 Timeout: 1 * time.Minute, 84 } 85 if _, err := stateConf.WaitForState(); err != nil { 86 return fmt.Errorf( 87 "Error waiting for vpc peering (%s) to become available: %s", 88 d.Id(), err) 89 } 90 91 return resourceAwsVPCPeeringUpdate(d, meta) 92 } 93 94 func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error { 95 conn := meta.(*AWSClient).ec2conn 96 pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())() 97 if err != nil { 98 return err 99 } 100 if pcRaw == nil { 101 d.SetId("") 102 return nil 103 } 104 105 pc := pcRaw.(*ec2.VpcPeeringConnection) 106 107 // The failed status is a status that we can assume just means the 108 // connection is gone. Destruction isn't allowed, and it eventually 109 // just "falls off" the console. See GH-2322 110 if pc.Status != nil { 111 if *pc.Status.Code == "failed" || *pc.Status.Code == "deleted" || *pc.Status.Code == "rejected" || *pc.Status.Code == "deleting" || *pc.Status.Code == "expired" { 112 log.Printf("[DEBUG] VPC Peering Connect (%s) in state (%s), removing", d.Id(), *pc.Status.Code) 113 d.SetId("") 114 return nil 115 } 116 } 117 118 d.Set("accept_status", *pc.Status.Code) 119 d.Set("peer_owner_id", pc.AccepterVpcInfo.OwnerId) 120 d.Set("peer_vpc_id", pc.AccepterVpcInfo.VpcId) 121 d.Set("vpc_id", pc.RequesterVpcInfo.VpcId) 122 d.Set("tags", tagsToMap(pc.Tags)) 123 124 return nil 125 } 126 127 func resourceVPCPeeringConnectionAccept(conn *ec2.EC2, id string) (string, error) { 128 129 log.Printf("[INFO] Accept VPC Peering Connection with id: %s", id) 130 131 req := &ec2.AcceptVpcPeeringConnectionInput{ 132 VpcPeeringConnectionId: aws.String(id), 133 } 134 135 resp, err := conn.AcceptVpcPeeringConnection(req) 136 if err != nil { 137 return "", err 138 } 139 pc := resp.VpcPeeringConnection 140 return *pc.Status.Code, err 141 } 142 143 func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error { 144 conn := meta.(*AWSClient).ec2conn 145 146 if err := setTags(conn, d); err != nil { 147 return err 148 } else { 149 d.SetPartial("tags") 150 } 151 152 if _, ok := d.GetOk("auto_accept"); ok { 153 pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())() 154 155 if err != nil { 156 return err 157 } 158 if pcRaw == nil { 159 d.SetId("") 160 return nil 161 } 162 pc := pcRaw.(*ec2.VpcPeeringConnection) 163 164 if pc.Status != nil && *pc.Status.Code == "pending-acceptance" { 165 status, err := resourceVPCPeeringConnectionAccept(conn, d.Id()) 166 if err != nil { 167 return err 168 } 169 log.Printf( 170 "[DEBUG] VPC Peering connection accept status: %s", 171 status) 172 } 173 } 174 175 return resourceAwsVPCPeeringRead(d, meta) 176 } 177 178 func resourceAwsVPCPeeringDelete(d *schema.ResourceData, meta interface{}) error { 179 conn := meta.(*AWSClient).ec2conn 180 181 _, err := conn.DeleteVpcPeeringConnection( 182 &ec2.DeleteVpcPeeringConnectionInput{ 183 VpcPeeringConnectionId: aws.String(d.Id()), 184 }) 185 return err 186 } 187 188 // resourceAwsVPCPeeringConnectionStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch 189 // a VPCPeeringConnection. 190 func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { 191 return func() (interface{}, string, error) { 192 193 resp, err := conn.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ 194 VpcPeeringConnectionIds: []*string{aws.String(id)}, 195 }) 196 if err != nil { 197 if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcPeeringConnectionID.NotFound" { 198 resp = nil 199 } else { 200 log.Printf("Error on VPCPeeringConnectionStateRefresh: %s", err) 201 return nil, "", err 202 } 203 } 204 205 if resp == nil { 206 // Sometimes AWS just has consistency issues and doesn't see 207 // our instance yet. Return an empty state. 208 return nil, "", nil 209 } 210 211 pc := resp.VpcPeeringConnections[0] 212 213 return pc, *pc.Status.Code, nil 214 } 215 }