github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2.go (about)

     1  package openstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  
    12  	"github.com/gophercloud/gophercloud"
    13  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
    14  )
    15  
    16  func resourceNetworkingSecGroupRuleV2() *schema.Resource {
    17  	return &schema.Resource{
    18  		Create: resourceNetworkingSecGroupRuleV2Create,
    19  		Read:   resourceNetworkingSecGroupRuleV2Read,
    20  		Delete: resourceNetworkingSecGroupRuleV2Delete,
    21  		Importer: &schema.ResourceImporter{
    22  			State: schema.ImportStatePassthrough,
    23  		},
    24  
    25  		Timeouts: &schema.ResourceTimeout{
    26  			Delete: schema.DefaultTimeout(10 * time.Minute),
    27  		},
    28  
    29  		Schema: map[string]*schema.Schema{
    30  			"region": &schema.Schema{
    31  				Type:        schema.TypeString,
    32  				Required:    true,
    33  				ForceNew:    true,
    34  				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
    35  			},
    36  			"direction": &schema.Schema{
    37  				Type:     schema.TypeString,
    38  				Required: true,
    39  				ForceNew: true,
    40  			},
    41  			"ethertype": &schema.Schema{
    42  				Type:     schema.TypeString,
    43  				Required: true,
    44  				ForceNew: true,
    45  			},
    46  			"port_range_min": &schema.Schema{
    47  				Type:     schema.TypeInt,
    48  				Optional: true,
    49  				ForceNew: true,
    50  				Computed: true,
    51  			},
    52  			"port_range_max": &schema.Schema{
    53  				Type:     schema.TypeInt,
    54  				Optional: true,
    55  				ForceNew: true,
    56  				Computed: true,
    57  			},
    58  			"protocol": &schema.Schema{
    59  				Type:     schema.TypeString,
    60  				Optional: true,
    61  				ForceNew: true,
    62  				Computed: true,
    63  			},
    64  			"remote_group_id": &schema.Schema{
    65  				Type:     schema.TypeString,
    66  				Optional: true,
    67  				ForceNew: true,
    68  				Computed: true,
    69  			},
    70  			"remote_ip_prefix": &schema.Schema{
    71  				Type:     schema.TypeString,
    72  				Optional: true,
    73  				ForceNew: true,
    74  				Computed: true,
    75  				StateFunc: func(v interface{}) string {
    76  					return strings.ToLower(v.(string))
    77  				},
    78  			},
    79  			"security_group_id": &schema.Schema{
    80  				Type:     schema.TypeString,
    81  				Required: true,
    82  				ForceNew: true,
    83  			},
    84  			"tenant_id": &schema.Schema{
    85  				Type:     schema.TypeString,
    86  				Optional: true,
    87  				ForceNew: true,
    88  				Computed: true,
    89  			},
    90  		},
    91  	}
    92  }
    93  
    94  func resourceNetworkingSecGroupRuleV2Create(d *schema.ResourceData, meta interface{}) error {
    95  
    96  	config := meta.(*Config)
    97  	networkingClient, err := config.networkingV2Client(GetRegion(d))
    98  	if err != nil {
    99  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   100  	}
   101  
   102  	portRangeMin := d.Get("port_range_min").(int)
   103  	portRangeMax := d.Get("port_range_max").(int)
   104  	protocol := d.Get("protocol").(string)
   105  
   106  	if protocol == "" {
   107  		if portRangeMin != 0 || portRangeMax != 0 {
   108  			return fmt.Errorf("A protocol must be specified when using port_range_min and port_range_max")
   109  		}
   110  	}
   111  
   112  	opts := rules.CreateOpts{
   113  		SecGroupID:     d.Get("security_group_id").(string),
   114  		PortRangeMin:   d.Get("port_range_min").(int),
   115  		PortRangeMax:   d.Get("port_range_max").(int),
   116  		RemoteGroupID:  d.Get("remote_group_id").(string),
   117  		RemoteIPPrefix: d.Get("remote_ip_prefix").(string),
   118  		TenantID:       d.Get("tenant_id").(string),
   119  	}
   120  
   121  	if v, ok := d.GetOk("direction"); ok {
   122  		direction := resourceNetworkingSecGroupRuleV2DetermineDirection(v.(string))
   123  		opts.Direction = direction
   124  	}
   125  
   126  	if v, ok := d.GetOk("ethertype"); ok {
   127  		ethertype := resourceNetworkingSecGroupRuleV2DetermineEtherType(v.(string))
   128  		opts.EtherType = ethertype
   129  	}
   130  
   131  	if v, ok := d.GetOk("protocol"); ok {
   132  		protocol := resourceNetworkingSecGroupRuleV2DetermineProtocol(v.(string))
   133  		opts.Protocol = protocol
   134  	}
   135  
   136  	log.Printf("[DEBUG] Create OpenStack Neutron security group: %#v", opts)
   137  
   138  	security_group_rule, err := rules.Create(networkingClient, opts).Extract()
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	log.Printf("[DEBUG] OpenStack Neutron Security Group Rule created: %#v", security_group_rule)
   144  
   145  	d.SetId(security_group_rule.ID)
   146  
   147  	return resourceNetworkingSecGroupRuleV2Read(d, meta)
   148  }
   149  
   150  func resourceNetworkingSecGroupRuleV2Read(d *schema.ResourceData, meta interface{}) error {
   151  	log.Printf("[DEBUG] Retrieve information about security group rule: %s", d.Id())
   152  
   153  	config := meta.(*Config)
   154  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   155  	if err != nil {
   156  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   157  	}
   158  
   159  	security_group_rule, err := rules.Get(networkingClient, d.Id()).Extract()
   160  
   161  	if err != nil {
   162  		return CheckDeleted(d, err, "OpenStack Security Group Rule")
   163  	}
   164  
   165  	d.Set("direction", security_group_rule.Direction)
   166  	d.Set("ethertype", security_group_rule.EtherType)
   167  	d.Set("protocol", security_group_rule.Protocol)
   168  	d.Set("port_range_min", security_group_rule.PortRangeMin)
   169  	d.Set("port_range_max", security_group_rule.PortRangeMax)
   170  	d.Set("remote_group_id", security_group_rule.RemoteGroupID)
   171  	d.Set("remote_ip_prefix", security_group_rule.RemoteIPPrefix)
   172  	d.Set("security_group_id", security_group_rule.SecGroupID)
   173  	d.Set("tenant_id", security_group_rule.TenantID)
   174  	d.Set("region", GetRegion(d))
   175  
   176  	return nil
   177  }
   178  
   179  func resourceNetworkingSecGroupRuleV2Delete(d *schema.ResourceData, meta interface{}) error {
   180  	log.Printf("[DEBUG] Destroy security group rule: %s", d.Id())
   181  
   182  	config := meta.(*Config)
   183  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   184  	if err != nil {
   185  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   186  	}
   187  
   188  	stateConf := &resource.StateChangeConf{
   189  		Pending:    []string{"ACTIVE"},
   190  		Target:     []string{"DELETED"},
   191  		Refresh:    waitForSecGroupRuleDelete(networkingClient, d.Id()),
   192  		Timeout:    d.Timeout(schema.TimeoutDelete),
   193  		Delay:      5 * time.Second,
   194  		MinTimeout: 3 * time.Second,
   195  	}
   196  
   197  	_, err = stateConf.WaitForState()
   198  	if err != nil {
   199  		return fmt.Errorf("Error deleting OpenStack Neutron Security Group Rule: %s", err)
   200  	}
   201  
   202  	d.SetId("")
   203  	return err
   204  }
   205  
   206  func resourceNetworkingSecGroupRuleV2DetermineDirection(v string) rules.RuleDirection {
   207  	var direction rules.RuleDirection
   208  	switch v {
   209  	case "ingress":
   210  		direction = rules.DirIngress
   211  	case "egress":
   212  		direction = rules.DirEgress
   213  	}
   214  
   215  	return direction
   216  }
   217  
   218  func resourceNetworkingSecGroupRuleV2DetermineEtherType(v string) rules.RuleEtherType {
   219  	var etherType rules.RuleEtherType
   220  	switch v {
   221  	case "IPv4":
   222  		etherType = rules.EtherType4
   223  	case "IPv6":
   224  		etherType = rules.EtherType6
   225  	}
   226  
   227  	return etherType
   228  }
   229  
   230  func resourceNetworkingSecGroupRuleV2DetermineProtocol(v string) rules.RuleProtocol {
   231  	var protocol rules.RuleProtocol
   232  	switch v {
   233  	case "tcp":
   234  		protocol = rules.ProtocolTCP
   235  	case "udp":
   236  		protocol = rules.ProtocolUDP
   237  	case "icmp":
   238  		protocol = rules.ProtocolICMP
   239  	}
   240  
   241  	return protocol
   242  }
   243  
   244  func waitForSecGroupRuleDelete(networkingClient *gophercloud.ServiceClient, secGroupRuleId string) resource.StateRefreshFunc {
   245  	return func() (interface{}, string, error) {
   246  		log.Printf("[DEBUG] Attempting to delete OpenStack Security Group Rule %s.\n", secGroupRuleId)
   247  
   248  		r, err := rules.Get(networkingClient, secGroupRuleId).Extract()
   249  		if err != nil {
   250  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   251  				log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId)
   252  				return r, "DELETED", nil
   253  			}
   254  			return r, "ACTIVE", err
   255  		}
   256  
   257  		err = rules.Delete(networkingClient, secGroupRuleId).ExtractErr()
   258  		if err != nil {
   259  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   260  				log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId)
   261  				return r, "DELETED", nil
   262  			}
   263  			return r, "ACTIVE", err
   264  		}
   265  
   266  		log.Printf("[DEBUG] OpenStack Neutron Security Group Rule %s still active.\n", secGroupRuleId)
   267  		return r, "ACTIVE", nil
   268  	}
   269  }