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