github.com/erriapo/terraform@v0.6.12-0.20160203182612-0340ea72354f/builtin/providers/azurerm/resource_arm_route_table.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/Azure/azure-sdk-for-go/arm/network"
    12  	"github.com/hashicorp/terraform/helper/hashcode"
    13  	"github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/helper/schema"
    15  )
    16  
    17  func resourceArmRouteTable() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceArmRouteTableCreate,
    20  		Read:   resourceArmRouteTableRead,
    21  		Update: resourceArmRouteTableCreate,
    22  		Delete: resourceArmRouteTableDelete,
    23  
    24  		Schema: map[string]*schema.Schema{
    25  			"name": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Required: true,
    28  				ForceNew: true,
    29  			},
    30  
    31  			"location": &schema.Schema{
    32  				Type:      schema.TypeString,
    33  				Required:  true,
    34  				ForceNew:  true,
    35  				StateFunc: azureRMNormalizeLocation,
    36  			},
    37  
    38  			"resource_group_name": &schema.Schema{
    39  				Type:     schema.TypeString,
    40  				Required: true,
    41  				ForceNew: true,
    42  			},
    43  
    44  			"route": &schema.Schema{
    45  				Type:     schema.TypeSet,
    46  				Optional: true,
    47  				Computed: true,
    48  				Elem: &schema.Resource{
    49  					Schema: map[string]*schema.Schema{
    50  						"name": &schema.Schema{
    51  							Type:     schema.TypeString,
    52  							Required: true,
    53  						},
    54  
    55  						"address_prefix": &schema.Schema{
    56  							Type:     schema.TypeString,
    57  							Required: true,
    58  						},
    59  
    60  						"next_hop_type": &schema.Schema{
    61  							Type:         schema.TypeString,
    62  							Required:     true,
    63  							ValidateFunc: validateRouteTableNextHopType,
    64  						},
    65  
    66  						"next_hop_in_ip_address": &schema.Schema{
    67  							Type:     schema.TypeString,
    68  							Optional: true,
    69  							Computed: true,
    70  						},
    71  					},
    72  				},
    73  				Set: resourceArmRouteTableRouteHash,
    74  			},
    75  
    76  			"subnets": &schema.Schema{
    77  				Type:     schema.TypeSet,
    78  				Optional: true,
    79  				Computed: true,
    80  				Elem:     &schema.Schema{Type: schema.TypeString},
    81  				Set:      schema.HashString,
    82  			},
    83  
    84  			"tags": tagsSchema(),
    85  		},
    86  	}
    87  }
    88  
    89  func resourceArmRouteTableCreate(d *schema.ResourceData, meta interface{}) error {
    90  	client := meta.(*ArmClient)
    91  	routeTablesClient := client.routeTablesClient
    92  
    93  	log.Printf("[INFO] preparing arguments for Azure ARM Route Table creation.")
    94  
    95  	name := d.Get("name").(string)
    96  	location := d.Get("location").(string)
    97  	resGroup := d.Get("resource_group_name").(string)
    98  	tags := d.Get("tags").(map[string]interface{})
    99  
   100  	routeSet := network.RouteTable{
   101  		Name:     &name,
   102  		Location: &location,
   103  		Tags:     expandTags(tags),
   104  	}
   105  
   106  	if _, ok := d.GetOk("route"); ok {
   107  		properties := network.RouteTablePropertiesFormat{}
   108  		routes, routeErr := expandAzureRmRouteTableRoutes(d)
   109  		if routeErr != nil {
   110  			return fmt.Errorf("Error Building list of Route Table Routes: %s", routeErr)
   111  		}
   112  		if len(routes) > 0 {
   113  			routeSet.Properties = &properties
   114  		}
   115  
   116  	}
   117  
   118  	resp, err := routeTablesClient.CreateOrUpdate(resGroup, name, routeSet)
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	d.SetId(*resp.ID)
   124  
   125  	log.Printf("[DEBUG] Waiting for Route Table (%s) to become available", name)
   126  	stateConf := &resource.StateChangeConf{
   127  		Pending: []string{"Accepted", "Updating"},
   128  		Target:  []string{"Succeeded"},
   129  		Refresh: routeTableStateRefreshFunc(client, resGroup, name),
   130  		Timeout: 10 * time.Minute,
   131  	}
   132  	if _, err := stateConf.WaitForState(); err != nil {
   133  		return fmt.Errorf("Error waiting forRoute Table (%s) to become available: %s", name, err)
   134  	}
   135  
   136  	return resourceArmRouteTableRead(d, meta)
   137  }
   138  
   139  func resourceArmRouteTableRead(d *schema.ResourceData, meta interface{}) error {
   140  	routeTablesClient := meta.(*ArmClient).routeTablesClient
   141  
   142  	id, err := parseAzureResourceID(d.Id())
   143  	if err != nil {
   144  		return err
   145  	}
   146  	resGroup := id.ResourceGroup
   147  	name := id.Path["routeTables"]
   148  
   149  	resp, err := routeTablesClient.Get(resGroup, name, "")
   150  	if resp.StatusCode == http.StatusNotFound {
   151  		d.SetId("")
   152  		return nil
   153  	}
   154  	if err != nil {
   155  		return fmt.Errorf("Error making Read request on Azure Route Table %s: %s", name, err)
   156  	}
   157  
   158  	if resp.Properties.Subnets != nil {
   159  		if len(*resp.Properties.Subnets) > 0 {
   160  			subnets := make([]string, 0, len(*resp.Properties.Subnets))
   161  			for _, subnet := range *resp.Properties.Subnets {
   162  				id := subnet.ID
   163  				subnets = append(subnets, *id)
   164  			}
   165  
   166  			if err := d.Set("subnets", subnets); err != nil {
   167  				return err
   168  			}
   169  		}
   170  	}
   171  
   172  	flattenAndSetTags(d, resp.Tags)
   173  
   174  	return nil
   175  }
   176  
   177  func resourceArmRouteTableDelete(d *schema.ResourceData, meta interface{}) error {
   178  	routeTablesClient := meta.(*ArmClient).routeTablesClient
   179  
   180  	id, err := parseAzureResourceID(d.Id())
   181  	if err != nil {
   182  		return err
   183  	}
   184  	resGroup := id.ResourceGroup
   185  	name := id.Path["routeTables"]
   186  
   187  	_, err = routeTablesClient.Delete(resGroup, name)
   188  
   189  	return err
   190  }
   191  
   192  func expandAzureRmRouteTableRoutes(d *schema.ResourceData) ([]network.Route, error) {
   193  	configs := d.Get("route").(*schema.Set).List()
   194  	routes := make([]network.Route, 0, len(configs))
   195  
   196  	for _, configRaw := range configs {
   197  		data := configRaw.(map[string]interface{})
   198  
   199  		address_prefix := data["address_prefix"].(string)
   200  		next_hop_type := data["next_hop_type"].(string)
   201  
   202  		properties := network.RoutePropertiesFormat{
   203  			AddressPrefix: &address_prefix,
   204  			NextHopType:   network.RouteNextHopType(next_hop_type),
   205  		}
   206  
   207  		if v := data["next_hop_in_ip_address"].(string); v != "" {
   208  			properties.NextHopIPAddress = &v
   209  		}
   210  
   211  		name := data["name"].(string)
   212  		route := network.Route{
   213  			Name:       &name,
   214  			Properties: &properties,
   215  		}
   216  
   217  		routes = append(routes, route)
   218  	}
   219  
   220  	return routes, nil
   221  }
   222  
   223  func routeTableStateRefreshFunc(client *ArmClient, resourceGroupName string, routeTableName string) resource.StateRefreshFunc {
   224  	return func() (interface{}, string, error) {
   225  		res, err := client.routeTablesClient.Get(resourceGroupName, routeTableName, "")
   226  		if err != nil {
   227  			return nil, "", fmt.Errorf("Error issuing read request in routeTableStateRefreshFunc to Azure ARM for route table '%s' (RG: '%s'): %s", routeTableName, resourceGroupName, err)
   228  		}
   229  
   230  		return res, *res.Properties.ProvisioningState, nil
   231  	}
   232  }
   233  
   234  func resourceArmRouteTableRouteHash(v interface{}) int {
   235  	var buf bytes.Buffer
   236  	m := v.(map[string]interface{})
   237  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   238  	buf.WriteString(fmt.Sprintf("%s-", m["address_prefix"].(string)))
   239  	buf.WriteString(fmt.Sprintf("%s-", m["next_hop_type"].(string)))
   240  
   241  	return hashcode.String(buf.String())
   242  }
   243  
   244  func validateRouteTableNextHopType(v interface{}, k string) (ws []string, errors []error) {
   245  	value := strings.ToLower(v.(string))
   246  	hopTypes := map[string]bool{
   247  		"virtualnetworkgateway": true,
   248  		"vnetlocal":             true,
   249  		"internet":              true,
   250  		"virtualappliance":      true,
   251  		"none":                  true,
   252  	}
   253  
   254  	if !hopTypes[value] {
   255  		errors = append(errors, fmt.Errorf("Route Table NextHopType Protocol can only be VirtualNetworkGateway, VnetLocal, Internet or VirtualAppliance"))
   256  	}
   257  	return
   258  }