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