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