github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_default_route_table.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/schema"
    10  )
    11  
    12  func resourceAwsDefaultRouteTable() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceAwsDefaultRouteTableCreate,
    15  		Read:   resourceAwsDefaultRouteTableRead,
    16  		Update: resourceAwsRouteTableUpdate,
    17  		Delete: resourceAwsDefaultRouteTableDelete,
    18  
    19  		Schema: map[string]*schema.Schema{
    20  			"default_route_table_id": {
    21  				Type:     schema.TypeString,
    22  				Required: true,
    23  				ForceNew: true,
    24  			},
    25  
    26  			"vpc_id": {
    27  				Type:     schema.TypeString,
    28  				Computed: true,
    29  			},
    30  
    31  			"propagating_vgws": {
    32  				Type:     schema.TypeSet,
    33  				Optional: true,
    34  				Elem:     &schema.Schema{Type: schema.TypeString},
    35  				Set:      schema.HashString,
    36  			},
    37  
    38  			"route": {
    39  				Type:     schema.TypeSet,
    40  				Computed: true,
    41  				Optional: true,
    42  				Elem: &schema.Resource{
    43  					Schema: map[string]*schema.Schema{
    44  						"cidr_block": {
    45  							Type:     schema.TypeString,
    46  							Optional: true,
    47  						},
    48  
    49  						"ipv6_cidr_block": {
    50  							Type:     schema.TypeString,
    51  							Optional: true,
    52  						},
    53  
    54  						"egress_only_gateway_id": {
    55  							Type:     schema.TypeString,
    56  							Optional: true,
    57  						},
    58  
    59  						"gateway_id": {
    60  							Type:     schema.TypeString,
    61  							Optional: true,
    62  						},
    63  
    64  						"instance_id": {
    65  							Type:     schema.TypeString,
    66  							Optional: true,
    67  						},
    68  
    69  						"nat_gateway_id": {
    70  							Type:     schema.TypeString,
    71  							Optional: true,
    72  						},
    73  
    74  						"vpc_peering_connection_id": {
    75  							Type:     schema.TypeString,
    76  							Optional: true,
    77  						},
    78  
    79  						"network_interface_id": {
    80  							Type:     schema.TypeString,
    81  							Optional: true,
    82  						},
    83  					},
    84  				},
    85  				Set: resourceAwsRouteTableHash,
    86  			},
    87  
    88  			"tags": tagsSchema(),
    89  		},
    90  	}
    91  }
    92  
    93  func resourceAwsDefaultRouteTableCreate(d *schema.ResourceData, meta interface{}) error {
    94  	d.SetId(d.Get("default_route_table_id").(string))
    95  
    96  	conn := meta.(*AWSClient).ec2conn
    97  	rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, d.Id())()
    98  	if err != nil {
    99  		return err
   100  	}
   101  	if rtRaw == nil {
   102  		log.Printf("[WARN] Default Route Table not found")
   103  		d.SetId("")
   104  		return nil
   105  	}
   106  
   107  	rt := rtRaw.(*ec2.RouteTable)
   108  
   109  	d.Set("vpc_id", rt.VpcId)
   110  
   111  	// revoke all default and pre-existing routes on the default route table.
   112  	// In the UPDATE method, we'll apply only the rules in the configuration.
   113  	log.Printf("[DEBUG] Revoking default routes for Default Route Table for %s", d.Id())
   114  	if err := revokeAllRouteTableRules(d.Id(), meta); err != nil {
   115  		return err
   116  	}
   117  
   118  	return resourceAwsRouteTableUpdate(d, meta)
   119  }
   120  
   121  func resourceAwsDefaultRouteTableRead(d *schema.ResourceData, meta interface{}) error {
   122  	conn := meta.(*AWSClient).ec2conn
   123  	// look up default route table for VPC
   124  	filter1 := &ec2.Filter{
   125  		Name:   aws.String("association.main"),
   126  		Values: []*string{aws.String("true")},
   127  	}
   128  	filter2 := &ec2.Filter{
   129  		Name:   aws.String("vpc-id"),
   130  		Values: []*string{aws.String(d.Get("vpc_id").(string))},
   131  	}
   132  
   133  	findOpts := &ec2.DescribeRouteTablesInput{
   134  		Filters: []*ec2.Filter{filter1, filter2},
   135  	}
   136  
   137  	resp, err := conn.DescribeRouteTables(findOpts)
   138  	if err != nil {
   139  		return err
   140  	}
   141  
   142  	if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil {
   143  		return fmt.Errorf("Default Route table not found")
   144  	}
   145  
   146  	rt := resp.RouteTables[0]
   147  
   148  	d.Set("default_route_table_id", rt.RouteTableId)
   149  	d.SetId(*rt.RouteTableId)
   150  
   151  	// re-use regular AWS Route Table READ. This is an extra API call but saves us
   152  	// from trying to manually keep parity
   153  	return resourceAwsRouteTableRead(d, meta)
   154  }
   155  
   156  func resourceAwsDefaultRouteTableDelete(d *schema.ResourceData, meta interface{}) error {
   157  	log.Printf("[WARN] Cannot destroy Default Route Table. Terraform will remove this resource from the state file, however resources may remain.")
   158  	d.SetId("")
   159  	return nil
   160  }
   161  
   162  // revokeAllRouteTableRules revoke all routes on the Default Route Table
   163  // This should only be ran once at creation time of this resource
   164  func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) error {
   165  	conn := meta.(*AWSClient).ec2conn
   166  	log.Printf("\n***\nrevokeAllRouteTableRules\n***\n")
   167  
   168  	resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesInput{
   169  		RouteTableIds: []*string{aws.String(defaultRouteTableId)},
   170  	})
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil {
   176  		return fmt.Errorf("Default Route table not found")
   177  	}
   178  
   179  	rt := resp.RouteTables[0]
   180  
   181  	// Remove all Gateway association
   182  	for _, r := range rt.PropagatingVgws {
   183  		log.Printf(
   184  			"[INFO] Deleting VGW propagation from %s: %s",
   185  			defaultRouteTableId, *r.GatewayId)
   186  		_, err := conn.DisableVgwRoutePropagation(&ec2.DisableVgwRoutePropagationInput{
   187  			RouteTableId: aws.String(defaultRouteTableId),
   188  			GatewayId:    r.GatewayId,
   189  		})
   190  		if err != nil {
   191  			return err
   192  		}
   193  	}
   194  
   195  	// Delete all routes
   196  	for _, r := range rt.Routes {
   197  		// you cannot delete the local route
   198  		if r.GatewayId != nil && *r.GatewayId == "local" {
   199  			continue
   200  		}
   201  		if r.DestinationPrefixListId != nil {
   202  			// Skipping because VPC endpoint routes are handled separately
   203  			// See aws_vpc_endpoint
   204  			continue
   205  		}
   206  
   207  		if r.DestinationCidrBlock != nil {
   208  			log.Printf(
   209  				"[INFO] Deleting route from %s: %s",
   210  				defaultRouteTableId, *r.DestinationCidrBlock)
   211  			_, err := conn.DeleteRoute(&ec2.DeleteRouteInput{
   212  				RouteTableId:         aws.String(defaultRouteTableId),
   213  				DestinationCidrBlock: r.DestinationCidrBlock,
   214  			})
   215  			if err != nil {
   216  				return err
   217  			}
   218  		}
   219  
   220  		if r.DestinationIpv6CidrBlock != nil {
   221  			log.Printf(
   222  				"[INFO] Deleting route from %s: %s",
   223  				defaultRouteTableId, *r.DestinationIpv6CidrBlock)
   224  			_, err := conn.DeleteRoute(&ec2.DeleteRouteInput{
   225  				RouteTableId:             aws.String(defaultRouteTableId),
   226  				DestinationIpv6CidrBlock: r.DestinationIpv6CidrBlock,
   227  			})
   228  			if err != nil {
   229  				return err
   230  			}
   231  		}
   232  
   233  	}
   234  
   235  	return nil
   236  }