github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/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: "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 }