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 }