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