github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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  	azureClient.secGroupMutex.Lock()
    90  	defer azureClient.secGroupMutex.Unlock()
    91  
    92  	// create and configure the RuleResponse:
    93  	name := d.Get("name").(string)
    94  	rule := netsecgroup.RuleRequest{
    95  		Name:                     name,
    96  		Type:                     netsecgroup.RuleType(d.Get("type").(string)),
    97  		Priority:                 d.Get("priority").(int),
    98  		Action:                   netsecgroup.RuleAction(d.Get("action").(string)),
    99  		SourceAddressPrefix:      d.Get("source_address_prefix").(string),
   100  		SourcePortRange:          d.Get("source_port_range").(string),
   101  		DestinationAddressPrefix: d.Get("destination_address_prefix").(string),
   102  		DestinationPortRange:     d.Get("destination_port_range").(string),
   103  		Protocol:                 netsecgroup.RuleProtocol(d.Get("protocol").(string)),
   104  	}
   105  
   106  	// apply the rule to all the necessary network security groups:
   107  	secGroups := d.Get("security_group_names").(*schema.Set).List()
   108  	for _, sg := range secGroups {
   109  		secGroup := sg.(string)
   110  
   111  		// send the create request to Azure:
   112  		log.Printf("[INFO] Sending Azure security group rule addition request for security group %q.", secGroup)
   113  		reqID, err := secGroupClient.SetNetworkSecurityGroupRule(
   114  			secGroup,
   115  			rule,
   116  		)
   117  		if err != nil {
   118  			return fmt.Errorf("Error sending Azure network security group rule creation request for security group %q: %s", secGroup, err)
   119  		}
   120  		err = mgmtClient.WaitForOperation(reqID, nil)
   121  		if err != nil {
   122  			return fmt.Errorf("Error creating Azure network security group rule for security group %q: %s", secGroup, err)
   123  		}
   124  	}
   125  
   126  	d.SetId(name)
   127  	return nil
   128  }
   129  
   130  // resourceAzureSecurityGroupRuleRead does all the necessary API calls to
   131  // read the state of a network security group ruke off Azure.
   132  func resourceAzureSecurityGroupRuleRead(d *schema.ResourceData, meta interface{}) error {
   133  	azureClient := meta.(*Client)
   134  	secGroupClient := azureClient.secGroupClient
   135  
   136  	var found bool
   137  	name := d.Get("name").(string)
   138  
   139  	secGroups := d.Get("security_group_names").(*schema.Set).List()
   140  	remaining := schema.NewSet(schema.HashString, nil)
   141  
   142  	// for each of our security groups; check for our rule:
   143  	for _, sg := range secGroups {
   144  		secGroupName := sg.(string)
   145  
   146  		// get info on the network security group and check its rules for this one:
   147  		log.Printf("[INFO] Sending Azure network security group rule query for security group %s.", secGroupName)
   148  		secgroup, err := secGroupClient.GetNetworkSecurityGroup(secGroupName)
   149  		if err != nil {
   150  			if !management.IsResourceNotFoundError(err) {
   151  				return fmt.Errorf("Error issuing network security group rules query for security group %q: %s", secGroupName, err)
   152  			} else {
   153  				// it meants that the network security group this rule belonged to has
   154  				// been deleted; so we skip this iteration:
   155  				continue
   156  			}
   157  		}
   158  
   159  		// find our security rule:
   160  		for _, rule := range secgroup.Rules {
   161  			if rule.Name == name {
   162  				// note the fact that this rule still apllies to this security group:
   163  				found = true
   164  				remaining.Add(secGroupName)
   165  
   166  				break
   167  			}
   168  		}
   169  	}
   170  
   171  	// check to see if there is any security group still having this rule:
   172  	if !found {
   173  		d.SetId("")
   174  		return nil
   175  	}
   176  
   177  	// now; we must update the set of security groups still having this rule:
   178  	d.Set("security_group_names", remaining)
   179  	return nil
   180  }
   181  
   182  // resourceAzureSecurityGroupRuleUpdate does all the necessary API calls to
   183  // update the state of a network security group rule off Azure.
   184  func resourceAzureSecurityGroupRuleUpdate(d *schema.ResourceData, meta interface{}) error {
   185  	azureClient := meta.(*Client)
   186  	mgmtClient := azureClient.mgmtClient
   187  	secGroupClient := azureClient.secGroupClient
   188  
   189  	azureClient.secGroupMutex.Lock()
   190  	defer azureClient.secGroupMutex.Unlock()
   191  
   192  	var found bool
   193  	name := d.Get("name").(string)
   194  	newRule := netsecgroup.RuleRequest{
   195  		Name:                     d.Get("name").(string),
   196  		Type:                     netsecgroup.RuleType(d.Get("type").(string)),
   197  		Priority:                 d.Get("priority").(int),
   198  		Action:                   netsecgroup.RuleAction(d.Get("action").(string)),
   199  		SourceAddressPrefix:      d.Get("source_address_prefix").(string),
   200  		SourcePortRange:          d.Get("source_port_range").(string),
   201  		DestinationAddressPrefix: d.Get("destination_address_prefix").(string),
   202  		DestinationPortRange:     d.Get("destination_port_range").(string),
   203  		Protocol:                 netsecgroup.RuleProtocol(d.Get("protocol").(string)),
   204  	}
   205  
   206  	// iterate over all the security groups that should have this rule and
   207  	// update it per security group:
   208  	remaining := schema.NewSet(schema.HashString, nil)
   209  	secGroupNames := d.Get("security_group_names").(*schema.Set).List()
   210  	for _, sg := range secGroupNames {
   211  		secGroupName := sg.(string)
   212  
   213  		// get info on the network security group and check its rules for this one:
   214  		log.Printf("[INFO] Sending Azure network security group rule query for security group %q.", secGroupName)
   215  		secgroup, err := secGroupClient.GetNetworkSecurityGroup(secGroupName)
   216  		if err != nil {
   217  			if !management.IsResourceNotFoundError(err) {
   218  				return fmt.Errorf("Error issuing network security group rules query: %s", err)
   219  			} else {
   220  				// it meants that the network security group this rule belonged to has
   221  				// been deleted; so we skip this iteration:
   222  				continue
   223  			}
   224  		}
   225  
   226  		// try and find our security group rule:
   227  		for _, rule := range secgroup.Rules {
   228  			if rule.Name == name {
   229  				// note the fact that this rule still applies to this security group:
   230  				found = true
   231  				remaining.Add(secGroupName)
   232  
   233  				// and go ahead and update it:
   234  				log.Printf("[INFO] Sending Azure network security group rule update request for security group %q.", secGroupName)
   235  				reqID, err := secGroupClient.SetNetworkSecurityGroupRule(
   236  					secGroupName,
   237  					newRule,
   238  				)
   239  				if err != nil {
   240  					return fmt.Errorf("Error sending Azure network security group rule update request for security group %q: %s", secGroupName, err)
   241  				}
   242  				err = mgmtClient.WaitForOperation(reqID, nil)
   243  				if err != nil {
   244  					return fmt.Errorf("Error updating Azure network security group rule for security group %q: %s", secGroupName, err)
   245  				}
   246  
   247  				break
   248  			}
   249  		}
   250  	}
   251  
   252  	// check to see if there is any security group still having this rule:
   253  	if !found {
   254  		d.SetId("")
   255  		return nil
   256  	}
   257  
   258  	// here; we must update the set of security groups still having this rule:
   259  	d.Set("security_group_names", remaining)
   260  
   261  	return nil
   262  }
   263  
   264  // resourceAzureSecurityGroupRuleDelete does all the necessary API calls to
   265  // delete a network security group rule off Azure.
   266  func resourceAzureSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
   267  	azureClient := meta.(*Client)
   268  	mgmtClient := azureClient.mgmtClient
   269  	secGroupClient := azureClient.secGroupClient
   270  
   271  	azureClient.secGroupMutex.Lock()
   272  	defer azureClient.secGroupMutex.Unlock()
   273  
   274  	name := d.Get("name").(string)
   275  	secGroupNames := d.Get("security_group_names").(*schema.Set).List()
   276  	for _, sg := range secGroupNames {
   277  		secGroupName := sg.(string)
   278  
   279  		// get info on the network security group and search for our rule:
   280  		log.Printf("[INFO] Sending network security group rule query for security group %q.", secGroupName)
   281  		secgroup, err := secGroupClient.GetNetworkSecurityGroup(secGroupName)
   282  		if err != nil {
   283  			if management.IsResourceNotFoundError(err) {
   284  				// it means that this network security group this rule belonged to has
   285  				// been deleted; so we need not do anything more here:
   286  				continue
   287  			} else {
   288  				return fmt.Errorf("Error issuing Azure network security group rules query for security group %q: %s", secGroupName, err)
   289  			}
   290  		}
   291  
   292  		// check if the rule has been deleted in the meantime:
   293  		for _, rule := range secgroup.Rules {
   294  			if rule.Name == name {
   295  				// if not; we shall issue the delete:
   296  				reqID, err := secGroupClient.DeleteNetworkSecurityGroupRule(secGroupName, name)
   297  				if err != nil {
   298  					return fmt.Errorf("Error sending network security group rule delete request to Azure: %s", err)
   299  				}
   300  				err = mgmtClient.WaitForOperation(reqID, nil)
   301  				if err != nil {
   302  					return fmt.Errorf("Error deleting network security group rule off Azure: %s", err)
   303  				}
   304  			}
   305  			break
   306  		}
   307  	}
   308  
   309  	return nil
   310  }