github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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 _, err := routeTablesClient.CreateOrUpdate(resGroup, name, routeSet, make(chan struct{})) 115 if err != nil { 116 return err 117 } 118 119 read, err := routeTablesClient.Get(resGroup, name, "") 120 if err != nil { 121 return err 122 } 123 if read.ID == nil { 124 return fmt.Errorf("Cannot read Route Table %s (resource group %s) ID", name, resGroup) 125 } 126 127 d.SetId(*read.ID) 128 129 return resourceArmRouteTableRead(d, meta) 130 } 131 132 func resourceArmRouteTableRead(d *schema.ResourceData, meta interface{}) error { 133 routeTablesClient := meta.(*ArmClient).routeTablesClient 134 135 id, err := parseAzureResourceID(d.Id()) 136 if err != nil { 137 return err 138 } 139 resGroup := id.ResourceGroup 140 name := id.Path["routeTables"] 141 142 resp, err := routeTablesClient.Get(resGroup, name, "") 143 if err != nil { 144 if resp.StatusCode == http.StatusNotFound { 145 d.SetId("") 146 return nil 147 } 148 return fmt.Errorf("Error making Read request on Azure Route Table %s: %s", name, err) 149 } 150 151 d.Set("name", name) 152 d.Set("resource_group_name", resGroup) 153 d.Set("location", resp.Location) 154 155 if resp.RouteTablePropertiesFormat.Routes != nil { 156 d.Set("route", schema.NewSet(resourceArmRouteTableRouteHash, flattenAzureRmRouteTableRoutes(resp.RouteTablePropertiesFormat.Routes))) 157 } 158 159 subnets := []string{} 160 if resp.RouteTablePropertiesFormat.Subnets != nil { 161 for _, subnet := range *resp.RouteTablePropertiesFormat.Subnets { 162 id := subnet.ID 163 subnets = append(subnets, *id) 164 } 165 } 166 d.Set("subnets", subnets) 167 168 flattenAndSetTags(d, resp.Tags) 169 170 return nil 171 } 172 173 func resourceArmRouteTableDelete(d *schema.ResourceData, meta interface{}) error { 174 routeTablesClient := meta.(*ArmClient).routeTablesClient 175 176 id, err := parseAzureResourceID(d.Id()) 177 if err != nil { 178 return err 179 } 180 resGroup := id.ResourceGroup 181 name := id.Path["routeTables"] 182 183 _, err = routeTablesClient.Delete(resGroup, name, make(chan struct{})) 184 185 return err 186 } 187 188 func expandAzureRmRouteTableRoutes(d *schema.ResourceData) ([]network.Route, error) { 189 configs := d.Get("route").(*schema.Set).List() 190 routes := make([]network.Route, 0, len(configs)) 191 192 for _, configRaw := range configs { 193 data := configRaw.(map[string]interface{}) 194 195 address_prefix := data["address_prefix"].(string) 196 next_hop_type := data["next_hop_type"].(string) 197 198 properties := network.RoutePropertiesFormat{ 199 AddressPrefix: &address_prefix, 200 NextHopType: network.RouteNextHopType(next_hop_type), 201 } 202 203 if v := data["next_hop_in_ip_address"].(string); v != "" { 204 properties.NextHopIPAddress = &v 205 } 206 207 name := data["name"].(string) 208 route := network.Route{ 209 Name: &name, 210 RoutePropertiesFormat: &properties, 211 } 212 213 routes = append(routes, route) 214 } 215 216 return routes, nil 217 } 218 219 func flattenAzureRmRouteTableRoutes(routes *[]network.Route) []interface{} { 220 results := make([]interface{}, 0, len(*routes)) 221 222 for _, route := range *routes { 223 r := make(map[string]interface{}) 224 r["name"] = *route.Name 225 r["address_prefix"] = *route.RoutePropertiesFormat.AddressPrefix 226 r["next_hop_type"] = string(route.RoutePropertiesFormat.NextHopType) 227 if route.RoutePropertiesFormat.NextHopIPAddress != nil { 228 r["next_hop_in_ip_address"] = *route.RoutePropertiesFormat.NextHopIPAddress 229 } 230 results = append(results, r) 231 } 232 233 return results 234 } 235 236 func resourceArmRouteTableRouteHash(v interface{}) int { 237 var buf bytes.Buffer 238 m := v.(map[string]interface{}) 239 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 240 buf.WriteString(fmt.Sprintf("%s-", m["address_prefix"].(string))) 241 buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["next_hop_type"].(string)))) 242 243 return hashcode.String(buf.String()) 244 } 245 246 func validateRouteTableNextHopType(v interface{}, k string) (ws []string, errors []error) { 247 value := strings.ToLower(v.(string)) 248 hopTypes := map[string]bool{ 249 "virtualnetworkgateway": true, 250 "vnetlocal": true, 251 "internet": true, 252 "virtualappliance": true, 253 "none": true, 254 } 255 256 if !hopTypes[value] { 257 errors = append(errors, fmt.Errorf("Route Table NextHopType Protocol can only be VirtualNetworkGateway, VnetLocal, Internet or VirtualAppliance")) 258 } 259 return 260 }