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