github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/aws/resource_aws_route.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/service/ec2" 9 "github.com/hashicorp/terraform/helper/hashcode" 10 "github.com/hashicorp/terraform/helper/schema" 11 ) 12 13 // AWS Route resource Schema declaration 14 func resourceAwsRoute() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceAwsRouteCreate, 17 Read: resourceAwsRouteRead, 18 Update: resourceAwsRouteUpdate, 19 Delete: resourceAwsRouteDelete, 20 Exists: resourceAwsRouteExists, 21 22 Schema: map[string]*schema.Schema{ 23 "destination_cidr_block": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 }, 28 29 "destination_prefix_list_id": &schema.Schema{ 30 Type: schema.TypeString, 31 Computed: true, 32 }, 33 34 "gateway_id": &schema.Schema{ 35 Type: schema.TypeString, 36 Optional: true, 37 }, 38 39 "instance_id": &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 }, 43 44 "instance_owner_id": &schema.Schema{ 45 Type: schema.TypeString, 46 Computed: true, 47 }, 48 49 "network_interface_id": &schema.Schema{ 50 Type: schema.TypeString, 51 Optional: true, 52 }, 53 54 "origin": &schema.Schema{ 55 Type: schema.TypeString, 56 Computed: true, 57 }, 58 59 "state": &schema.Schema{ 60 Type: schema.TypeString, 61 Computed: true, 62 }, 63 64 "route_table_id": &schema.Schema{ 65 Type: schema.TypeString, 66 Required: true, 67 }, 68 69 "vpc_peering_connection_id": &schema.Schema{ 70 Type: schema.TypeString, 71 Optional: true, 72 }, 73 }, 74 } 75 } 76 77 func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { 78 conn := meta.(*AWSClient).ec2conn 79 var numTargets int 80 var setTarget string 81 allowedTargets := []string{ 82 "gateway_id", 83 "instance_id", 84 "network_interface_id", 85 "vpc_peering_connection_id", 86 } 87 88 // Check if more than 1 target is specified 89 for _, target := range allowedTargets { 90 if len(d.Get(target).(string)) > 0 { 91 numTargets++ 92 setTarget = target 93 } 94 } 95 96 if numTargets > 1 { 97 fmt.Errorf("Error: more than 1 target specified. Only 1 of gateway_id" + 98 "instance_id, network_interface_id, route_table_id or" + 99 "vpc_peering_connection_id is allowed.") 100 } 101 102 createOpts := &ec2.CreateRouteInput{} 103 // Formulate CreateRouteInput based on the target type 104 switch setTarget { 105 case "gateway_id": 106 createOpts = &ec2.CreateRouteInput{ 107 RouteTableId: aws.String(d.Get("route_table_id").(string)), 108 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 109 GatewayId: aws.String(d.Get("gateway_id").(string)), 110 } 111 case "instance_id": 112 createOpts = &ec2.CreateRouteInput{ 113 RouteTableId: aws.String(d.Get("route_table_id").(string)), 114 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 115 InstanceId: aws.String(d.Get("instance_id").(string)), 116 } 117 case "network_interface_id": 118 createOpts = &ec2.CreateRouteInput{ 119 RouteTableId: aws.String(d.Get("route_table_id").(string)), 120 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 121 NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)), 122 } 123 case "vpc_peering_connection_id": 124 createOpts = &ec2.CreateRouteInput{ 125 RouteTableId: aws.String(d.Get("route_table_id").(string)), 126 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 127 VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)), 128 } 129 default: 130 fmt.Errorf("Error: invalid target type specified.") 131 } 132 log.Printf("[DEBUG] Route create config: %s", createOpts) 133 134 // Create the route 135 _, err := conn.CreateRoute(createOpts) 136 if err != nil { 137 return fmt.Errorf("Error creating route: %s", err) 138 } 139 140 route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string)) 141 if err != nil { 142 fmt.Errorf("Error: %s", err) 143 } 144 145 d.SetId(routeIDHash(d, route)) 146 147 return resourceAwsRouteRead(d, meta) 148 } 149 150 func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { 151 conn := meta.(*AWSClient).ec2conn 152 route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string)) 153 if err != nil { 154 return err 155 } 156 157 d.Set("destination_prefix_list_id", route.DestinationPrefixListId) 158 d.Set("gateway_id", route.GatewayId) 159 d.Set("instance_id", route.InstanceId) 160 d.Set("instance_owner_id", route.InstanceOwnerId) 161 d.Set("network_interface_id", route.NetworkInterfaceId) 162 d.Set("origin", route.Origin) 163 d.Set("state", route.State) 164 d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId) 165 166 return nil 167 } 168 169 func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error { 170 conn := meta.(*AWSClient).ec2conn 171 var numTargets int 172 var setTarget string 173 allowedTargets := []string{ 174 "gateway_id", 175 "instance_id", 176 "network_interface_id", 177 "vpc_peering_connection_id", 178 } 179 replaceOpts := &ec2.ReplaceRouteInput{} 180 181 // Check if more than 1 target is specified 182 for _, target := range allowedTargets { 183 if len(d.Get(target).(string)) > 0 { 184 numTargets++ 185 setTarget = target 186 } 187 } 188 189 if numTargets > 1 { 190 fmt.Errorf("Error: more than 1 target specified. Only 1 of gateway_id" + 191 "instance_id, network_interface_id, route_table_id or" + 192 "vpc_peering_connection_id is allowed.") 193 } 194 195 // Formulate ReplaceRouteInput based on the target type 196 switch setTarget { 197 case "gateway_id": 198 replaceOpts = &ec2.ReplaceRouteInput{ 199 RouteTableId: aws.String(d.Get("route_table_id").(string)), 200 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 201 GatewayId: aws.String(d.Get("gateway_id").(string)), 202 } 203 case "instance_id": 204 replaceOpts = &ec2.ReplaceRouteInput{ 205 RouteTableId: aws.String(d.Get("route_table_id").(string)), 206 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 207 InstanceId: aws.String(d.Get("instance_id").(string)), 208 //NOOP: Ensure we don't blow away network interface id that is set after instance is launched 209 NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)), 210 } 211 case "network_interface_id": 212 replaceOpts = &ec2.ReplaceRouteInput{ 213 RouteTableId: aws.String(d.Get("route_table_id").(string)), 214 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 215 NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)), 216 } 217 case "vpc_peering_connection_id": 218 replaceOpts = &ec2.ReplaceRouteInput{ 219 RouteTableId: aws.String(d.Get("route_table_id").(string)), 220 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 221 VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)), 222 } 223 default: 224 fmt.Errorf("Error: invalid target type specified.") 225 } 226 log.Printf("[DEBUG] Route replace config: %s", replaceOpts) 227 228 // Replace the route 229 _, err := conn.ReplaceRoute(replaceOpts) 230 if err != nil { 231 return err 232 } 233 234 return nil 235 } 236 237 func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { 238 conn := meta.(*AWSClient).ec2conn 239 240 deleteOpts := &ec2.DeleteRouteInput{ 241 RouteTableId: aws.String(d.Get("route_table_id").(string)), 242 DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), 243 } 244 log.Printf("[DEBUG] Route delete opts: %s", deleteOpts) 245 246 resp, err := conn.DeleteRoute(deleteOpts) 247 log.Printf("[DEBUG] Route delete result: %s", resp) 248 if err != nil { 249 return err 250 } 251 252 d.SetId("") 253 return nil 254 } 255 256 func resourceAwsRouteExists(d *schema.ResourceData, meta interface{}) (bool, error) { 257 conn := meta.(*AWSClient).ec2conn 258 routeTableId := d.Get("route_table_id").(string) 259 260 findOpts := &ec2.DescribeRouteTablesInput{ 261 RouteTableIds: []*string{&routeTableId}, 262 } 263 264 res, err := conn.DescribeRouteTables(findOpts) 265 if err != nil { 266 return false, err 267 } 268 269 cidr := d.Get("destination_cidr_block").(string) 270 for _, route := range (*res.RouteTables[0]).Routes { 271 if *route.DestinationCidrBlock == cidr { 272 return true, nil 273 } 274 } 275 276 return false, nil 277 } 278 279 // Create an ID for a route 280 func routeIDHash(d *schema.ResourceData, r *ec2.Route) string { 281 return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock)) 282 } 283 284 // Helper: retrieve a route 285 func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string) (*ec2.Route, error) { 286 routeTableID := rtbid 287 288 findOpts := &ec2.DescribeRouteTablesInput{ 289 RouteTableIds: []*string{&routeTableID}, 290 } 291 292 resp, err := conn.DescribeRouteTables(findOpts) 293 if err != nil { 294 return nil, err 295 } 296 297 for _, route := range (*resp.RouteTables[0]).Routes { 298 if *route.DestinationCidrBlock == cidr { 299 return route, nil 300 } 301 } 302 303 return nil, nil 304 }