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  }