github.com/jsoriano/terraform@v0.6.7-0.20151026070445-8b70867fdd95/builtin/providers/azure/resource_azure_security_group_rule.go (about)

     1  package azure
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/Azure/azure-sdk-for-go/management"
     8  	netsecgroup "github.com/Azure/azure-sdk-for-go/management/networksecuritygroup"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  )
    11  
    12  // resourceAzureSecurityGroupRule returns the *schema.Resource for
    13  // a network security group rule on Azure.
    14  func resourceAzureSecurityGroupRule() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAzureSecurityGroupRuleCreate,
    17  		Read:   resourceAzureSecurityGroupRuleRead,
    18  		Update: resourceAzureSecurityGroupRuleUpdate,
    19  		Delete: resourceAzureSecurityGroupRuleDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": &schema.Schema{
    23  				Type:        schema.TypeString,
    24  				Required:    true,
    25  				ForceNew:    true,
    26  				Description: parameterDescriptions["name"],
    27  			},
    28  			"security_group_names": &schema.Schema{
    29  				Type:        schema.TypeSet,
    30  				Required:    true,
    31  				ForceNew:    true,
    32  				Description: parameterDescriptions["netsecgroup_secgroup_names"],
    33  				Elem: &schema.Schema{
    34  					Type: schema.TypeString,
    35  				},
    36  				Set: schema.HashString,
    37  			},
    38  			"type": &schema.Schema{
    39  				Type:        schema.TypeString,
    40  				Required:    true,
    41  				Description: parameterDescriptions["netsecgroup_type"],
    42  			},
    43  			"priority": &schema.Schema{
    44  				Type:        schema.TypeInt,
    45  				Required:    true,
    46  				Description: parameterDescriptions["netsecgroup_priority"],
    47  			},
    48  			"action": &schema.Schema{
    49  				Type:        schema.TypeString,
    50  				Required:    true,
    51  				Description: parameterDescriptions["netsecgroup_action"],
    52  			},
    53  			"source_address_prefix": &schema.Schema{
    54  				Type:        schema.TypeString,
    55  				Required:    true,
    56  				Description: parameterDescriptions["netsecgroup_src_addr_prefix"],
    57  			},
    58  			"source_port_range": &schema.Schema{
    59  				Type:        schema.TypeString,
    60  				Required:    true,
    61  				Description: parameterDescriptions["netsecgroup_src_port_range"],
    62  			},
    63  			"destination_address_prefix": &schema.Schema{
    64  				Type:        schema.TypeString,
    65  				Required:    true,
    66  				Description: parameterDescriptions["netsecgroup_dest_addr_prefix"],
    67  			},
    68  			"destination_port_range": &schema.Schema{
    69  				Type:        schema.TypeString,
    70  				Required:    true,
    71  				Description: parameterDescriptions["netsecgroup_dest_port_range"],
    72  			},
    73  			"protocol": &schema.Schema{
    74  				Type:        schema.TypeString,
    75  				Required:    true,
    76  				Description: parameterDescriptions["netsecgroup_protocol"],
    77  			},
    78  		},
    79  	}
    80  }
    81  
    82  // resourceAzureSecurityGroupRuleCreate does all the necessary API calls to
    83  // create a new network security group rule on Azure.
    84  func resourceAzureSecurityGroupRuleCreate(d *schema.ResourceData, meta interface{}) error {
    85  	azureClient := meta.(*Client)
    86  	mgmtClient := azureClient.mgmtClient
    87  	secGroupClient := azureClient.secGroupClient
    88  
    89  	// create and configure the RuleResponse:
    90  	name := d.Get("name").(string)
    91  	rule := netsecgroup.RuleRequest{
    92  		Name:                     name,
    93  		Type:                     netsecgroup.RuleType(d.Get("type").(string)),
    94  		Priority:                 d.Get("priority").(int),
    95  		Action:                   netsecgroup.RuleAction(d.Get("action").(string)),
    96  		SourceAddressPrefix:      d.Get("source_address_prefix").(string),
    97  		SourcePortRange:          d.Get("source_port_range").(string),
    98  		DestinationAddressPrefix: d.Get("destination_address_prefix").(string),
    99  		DestinationPortRange:     d.Get("destination_port_range").(string),
   100  		Protocol:                 netsecgroup.RuleProtocol(d.Get("protocol").(string)),
   101  	}
   102  
   103  	// apply the rule to all the necessary network security groups:
   104  	secGroups := d.Get("security_group_names").(*schema.Set).List()
   105  	for _, sg := range secGroups {
   106  		secGroup := sg.(string)
   107  
   108  		// send the create request to Azure:
   109  		log.Printf("[INFO] Sending Azure security group rule addition request for security group %q.", secGroup)
   110  		reqID, err := secGroupClient.SetNetworkSecurityGroupRule(
   111  			secGroup,
   112  			rule,
   113  		)
   114  		if err != nil {
   115  			return fmt.Errorf("Error sending Azure network security group rule creation request for security group %q: %s", secGroup, err)
   116  		}
   117  		err = mgmtClient.WaitForOperation(reqID, nil)
   118  		if err != nil {
   119  			return fmt.Errorf("Error creating Azure network security group rule for security group %q: %s", secGroup, err)
   120  		}
   121  	}
   122  
   123  	d.SetId(name)
   124  	return nil
   125  }
   126  
   127  // resourceAzureSecurityGroupRuleRead does all the necessary API calls to
   128  // read the state of a network security group ruke off Azure.
   129  func resourceAzureSecurityGroupRuleRead(d *schema.ResourceData, meta interface{}) error {
   130  	azureClient := meta.(*Client)
   131  	secGroupClient := azureClient.secGroupClient
   132  
   133  	var found bool
   134  	name := d.Get("name").(string)
   135  
   136  	secGroups := d.Get("security_group_names").(*schema.Set).List()
   137  	remaining := schema.NewSet(schema.HashString, nil)
   138  
   139  	// for each of our security groups; check for our rule:
   140  	for _, sg := range secGroups {
   141  		secGroupName := sg.(string)
   142  
   143  		// get info on the network security group and check its rules for this one:
   144  		log.Printf("[INFO] Sending Azure network security group rule query for security group %s.", secGroupName)
   145  		secgroup, err := secGroupClient.GetNetworkSecurityGroup(secGroupName)
   146  		if err != nil {
   147  			if !management.IsResourceNotFoundError(err) {
   148  				return fmt.Errorf("Error issuing network security group rules query for security group %q: %s", secGroupName, err)
   149  			} else {
   150  				// it meants that the network security group this rule belonged to has
   151  				// been deleted; so we skip this iteration:
   152  				continue
   153  			}
   154  		}
   155  
   156  		// find our security rule:
   157  		for _, rule := range secgroup.Rules {
   158  			if rule.Name == name {
   159  				// note the fact that this rule still apllies to this security group:
   160  				found = true
   161  				remaining.Add(secGroupName)
   162  
   163  				break
   164  			}
   165  		}
   166  	}
   167  
   168  	// check to see if there is any security group still having this rule:
   169  	if !found {
   170  		d.SetId("")
   171  		return nil
   172  	}
   173  
   174  	// now; we must update the set of security groups still having this rule:
   175  	d.Set("security_group_names", remaining)
   176  	return nil
   177  }
   178  
   179  // resourceAzureSecurityGroupRuleUpdate does all the necessary API calls to
   180  // update the state of a network security group rule off Azure.
   181  func resourceAzureSecurityGroupRuleUpdate(d *schema.ResourceData, meta interface{}) error {
   182  	azureClient := meta.(*Client)
   183  	mgmtClient := azureClient.mgmtClient
   184  	secGroupClient := azureClient.secGroupClient
   185  
   186  	var found bool
   187  	name := d.Get("name").(string)
   188  	newRule := netsecgroup.RuleRequest{
   189  		Name:                     d.Get("name").(string),
   190  		Type:                     netsecgroup.RuleType(d.Get("type").(string)),
   191  		Priority:                 d.Get("priority").(int),
   192  		Action:                   netsecgroup.RuleAction(d.Get("action").(string)),
   193  		SourceAddressPrefix:      d.Get("source_address_prefix").(string),
   194  		SourcePortRange:          d.Get("source_port_range").(string),
   195  		DestinationAddressPrefix: d.Get("destination_address_prefix").(string),
   196  		DestinationPortRange:     d.Get("destination_port_range").(string),
   197  		Protocol:                 netsecgroup.RuleProtocol(d.Get("protocol").(string)),
   198  	}
   199  
   200  	// iterate over all the security groups that should have this rule and
   201  	// update it per security group:
   202  	remaining := schema.NewSet(schema.HashString, nil)
   203  	secGroupNames := d.Get("security_group_names").(*schema.Set).List()
   204  	for _, sg := range secGroupNames {
   205  		secGroupName := sg.(string)
   206  
   207  		// get info on the network security group and check its rules for this one:
   208  		log.Printf("[INFO] Sending Azure network security group rule query for security group %q.", secGroupName)
   209  		secgroup, err := secGroupClient.GetNetworkSecurityGroup(secGroupName)
   210  		if err != nil {
   211  			if !management.IsResourceNotFoundError(err) {
   212  				return fmt.Errorf("Error issuing network security group rules query: %s", err)
   213  			} else {
   214  				// it meants that the network security group this rule belonged to has
   215  				// been deleted; so we skip this iteration:
   216  				continue
   217  			}
   218  		}
   219  
   220  		// try and find our security group rule:
   221  		for _, rule := range secgroup.Rules {
   222  			if rule.Name == name {
   223  				// note the fact that this rule still applies to this security group:
   224  				found = true
   225  				remaining.Add(secGroupName)
   226  
   227  				// and go ahead and update it:
   228  				log.Printf("[INFO] Sending Azure network security group rule update request for security group %q.", secGroupName)
   229  				reqID, err := secGroupClient.SetNetworkSecurityGroupRule(
   230  					secGroupName,
   231  					newRule,
   232  				)
   233  				if err != nil {
   234  					return fmt.Errorf("Error sending Azure network security group rule update request for security group %q: %s", secGroupName, err)
   235  				}
   236  				err = mgmtClient.WaitForOperation(reqID, nil)
   237  				if err != nil {
   238  					return fmt.Errorf("Error updating Azure network security group rule for security group %q: %s", secGroupName, err)
   239  				}
   240  
   241  				break
   242  			}
   243  		}
   244  	}
   245  
   246  	// check to see if there is any security group still having this rule:
   247  	if !found {
   248  		d.SetId("")
   249  		return nil
   250  	}
   251  
   252  	// here; we must update the set of security groups still having this rule:
   253  	d.Set("security_group_names", remaining)
   254  
   255  	return nil
   256  }
   257  
   258  // resourceAzureSecurityGroupRuleDelete does all the necessary API calls to
   259  // delete a network security group rule off Azure.
   260  func resourceAzureSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
   261  	azureClient := meta.(*Client)
   262  	mgmtClient := azureClient.mgmtClient
   263  	secGroupClient := azureClient.secGroupClient
   264  
   265  	name := d.Get("name").(string)
   266  	secGroupNames := d.Get("security_group_names").(*schema.Set).List()
   267  	for _, sg := range secGroupNames {
   268  		secGroupName := sg.(string)
   269  
   270  		// get info on the network security group and search for our rule:
   271  		log.Printf("[INFO] Sending network security group rule query for security group %q.", secGroupName)
   272  		secgroup, err := secGroupClient.GetNetworkSecurityGroup(secGroupName)
   273  		if err != nil {
   274  			if management.IsResourceNotFoundError(err) {
   275  				// it means that this network security group this rule belonged to has
   276  				// been deleted; so we need not do anything more here:
   277  				continue
   278  			} else {
   279  				return fmt.Errorf("Error issuing Azure network security group rules query for security group %q: %s", secGroupName, err)
   280  			}
   281  		}
   282  
   283  		// check if the rule has been deleted in the meantime:
   284  		for _, rule := range secgroup.Rules {
   285  			if rule.Name == name {
   286  				// if not; we shall issue the delete:
   287  				reqID, err := secGroupClient.DeleteNetworkSecurityGroupRule(secGroupName, name)
   288  				if err != nil {
   289  					return fmt.Errorf("Error sending network security group rule delete request to Azure: %s", err)
   290  				}
   291  				err = mgmtClient.WaitForOperation(reqID, nil)
   292  				if err != nil {
   293  					return fmt.Errorf("Error deleting network security group rule off Azure: %s", err)
   294  				}
   295  			}
   296  			break
   297  		}
   298  	}
   299  
   300  	return nil
   301  }