github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/builtin/providers/google/resource_compute_firewall.go (about) 1 package google 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "sort" 8 9 "github.com/hashicorp/terraform/helper/hashcode" 10 "github.com/hashicorp/terraform/helper/schema" 11 "google.golang.org/api/compute/v1" 12 "google.golang.org/api/googleapi" 13 ) 14 15 func resourceComputeFirewall() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceComputeFirewallCreate, 18 Read: resourceComputeFirewallRead, 19 Update: resourceComputeFirewallUpdate, 20 Delete: resourceComputeFirewallDelete, 21 22 Schema: map[string]*schema.Schema{ 23 "name": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 }, 28 29 "network": &schema.Schema{ 30 Type: schema.TypeString, 31 Required: true, 32 ForceNew: true, 33 }, 34 35 "allow": &schema.Schema{ 36 Type: schema.TypeSet, 37 Required: true, 38 Elem: &schema.Resource{ 39 Schema: map[string]*schema.Schema{ 40 "protocol": &schema.Schema{ 41 Type: schema.TypeString, 42 Required: true, 43 }, 44 45 "ports": &schema.Schema{ 46 Type: schema.TypeSet, 47 Optional: true, 48 Elem: &schema.Schema{Type: schema.TypeString}, 49 Set: schema.HashString, 50 }, 51 }, 52 }, 53 Set: resourceComputeFirewallAllowHash, 54 }, 55 56 "description": &schema.Schema{ 57 Type: schema.TypeString, 58 Optional: true, 59 }, 60 61 "project": &schema.Schema{ 62 Type: schema.TypeString, 63 Optional: true, 64 ForceNew: true, 65 }, 66 67 "self_link": &schema.Schema{ 68 Type: schema.TypeString, 69 Computed: true, 70 }, 71 72 "source_ranges": &schema.Schema{ 73 Type: schema.TypeSet, 74 Optional: true, 75 Elem: &schema.Schema{Type: schema.TypeString}, 76 Set: schema.HashString, 77 }, 78 79 "source_tags": &schema.Schema{ 80 Type: schema.TypeSet, 81 Optional: true, 82 Elem: &schema.Schema{Type: schema.TypeString}, 83 Set: schema.HashString, 84 }, 85 86 "target_tags": &schema.Schema{ 87 Type: schema.TypeSet, 88 Optional: true, 89 Elem: &schema.Schema{Type: schema.TypeString}, 90 Set: schema.HashString, 91 }, 92 }, 93 } 94 } 95 96 func resourceComputeFirewallAllowHash(v interface{}) int { 97 var buf bytes.Buffer 98 m := v.(map[string]interface{}) 99 buf.WriteString(fmt.Sprintf("%s-", m["protocol"].(string))) 100 101 // We need to make sure to sort the strings below so that we always 102 // generate the same hash code no matter what is in the set. 103 if v, ok := m["ports"]; ok { 104 vs := v.(*schema.Set).List() 105 s := make([]string, len(vs)) 106 for i, raw := range vs { 107 s[i] = raw.(string) 108 } 109 sort.Strings(s) 110 111 for _, v := range s { 112 buf.WriteString(fmt.Sprintf("%s-", v)) 113 } 114 } 115 116 return hashcode.String(buf.String()) 117 } 118 119 func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) error { 120 config := meta.(*Config) 121 122 project, err := getProject(d, config) 123 if err != nil { 124 return err 125 } 126 127 firewall, err := resourceFirewall(d, meta) 128 if err != nil { 129 return err 130 } 131 132 op, err := config.clientCompute.Firewalls.Insert( 133 project, firewall).Do() 134 if err != nil { 135 return fmt.Errorf("Error creating firewall: %s", err) 136 } 137 138 // It probably maybe worked, so store the ID now 139 d.SetId(firewall.Name) 140 141 err = computeOperationWaitGlobal(config, op, "Creating Firewall") 142 if err != nil { 143 return err 144 } 145 146 return resourceComputeFirewallRead(d, meta) 147 } 148 149 func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error { 150 config := meta.(*Config) 151 152 project, err := getProject(d, config) 153 if err != nil { 154 return err 155 } 156 157 firewall, err := config.clientCompute.Firewalls.Get( 158 project, d.Id()).Do() 159 if err != nil { 160 if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { 161 // The resource doesn't exist anymore 162 log.Printf("[WARN] Removing Firewall %q because it's gone", d.Get("name").(string)) 163 d.SetId("") 164 165 return nil 166 } 167 168 return fmt.Errorf("Error reading firewall: %s", err) 169 } 170 171 d.Set("self_link", firewall.SelfLink) 172 173 return nil 174 } 175 176 func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) error { 177 config := meta.(*Config) 178 179 project, err := getProject(d, config) 180 if err != nil { 181 return err 182 } 183 184 d.Partial(true) 185 186 firewall, err := resourceFirewall(d, meta) 187 if err != nil { 188 return err 189 } 190 191 op, err := config.clientCompute.Firewalls.Update( 192 project, d.Id(), firewall).Do() 193 if err != nil { 194 return fmt.Errorf("Error updating firewall: %s", err) 195 } 196 197 err = computeOperationWaitGlobal(config, op, "Updating Firewall") 198 if err != nil { 199 return err 200 } 201 202 d.Partial(false) 203 204 return resourceComputeFirewallRead(d, meta) 205 } 206 207 func resourceComputeFirewallDelete(d *schema.ResourceData, meta interface{}) error { 208 config := meta.(*Config) 209 210 project, err := getProject(d, config) 211 if err != nil { 212 return err 213 } 214 215 // Delete the firewall 216 op, err := config.clientCompute.Firewalls.Delete( 217 project, d.Id()).Do() 218 if err != nil { 219 return fmt.Errorf("Error deleting firewall: %s", err) 220 } 221 222 err = computeOperationWaitGlobal(config, op, "Deleting Firewall") 223 if err != nil { 224 return err 225 } 226 227 d.SetId("") 228 return nil 229 } 230 231 func resourceFirewall( 232 d *schema.ResourceData, 233 meta interface{}) (*compute.Firewall, error) { 234 config := meta.(*Config) 235 236 project, _ := getProject(d, config) 237 238 // Look up the network to attach the firewall to 239 network, err := config.clientCompute.Networks.Get( 240 project, d.Get("network").(string)).Do() 241 if err != nil { 242 return nil, fmt.Errorf("Error reading network: %s", err) 243 } 244 245 // Build up the list of allowed entries 246 var allowed []*compute.FirewallAllowed 247 if v := d.Get("allow").(*schema.Set); v.Len() > 0 { 248 allowed = make([]*compute.FirewallAllowed, 0, v.Len()) 249 for _, v := range v.List() { 250 m := v.(map[string]interface{}) 251 252 var ports []string 253 if v := m["ports"].(*schema.Set); v.Len() > 0 { 254 ports = make([]string, v.Len()) 255 for i, v := range v.List() { 256 ports[i] = v.(string) 257 } 258 } 259 260 allowed = append(allowed, &compute.FirewallAllowed{ 261 IPProtocol: m["protocol"].(string), 262 Ports: ports, 263 }) 264 } 265 } 266 267 // Build up the list of sources 268 var sourceRanges, sourceTags []string 269 if v := d.Get("source_ranges").(*schema.Set); v.Len() > 0 { 270 sourceRanges = make([]string, v.Len()) 271 for i, v := range v.List() { 272 sourceRanges[i] = v.(string) 273 } 274 } 275 if v := d.Get("source_tags").(*schema.Set); v.Len() > 0 { 276 sourceTags = make([]string, v.Len()) 277 for i, v := range v.List() { 278 sourceTags[i] = v.(string) 279 } 280 } 281 282 // Build up the list of targets 283 var targetTags []string 284 if v := d.Get("target_tags").(*schema.Set); v.Len() > 0 { 285 targetTags = make([]string, v.Len()) 286 for i, v := range v.List() { 287 targetTags[i] = v.(string) 288 } 289 } 290 291 // Build the firewall parameter 292 return &compute.Firewall{ 293 Name: d.Get("name").(string), 294 Description: d.Get("description").(string), 295 Network: network.SelfLink, 296 Allowed: allowed, 297 SourceRanges: sourceRanges, 298 SourceTags: sourceTags, 299 TargetTags: targetTags, 300 }, nil 301 }