diff --git a/builtin/providers/azurerm/resource_arm_network_interface_card.go b/builtin/providers/azurerm/resource_arm_network_interface_card.go index 7450519b1..3c74bc3e0 100644 --- a/builtin/providers/azurerm/resource_arm_network_interface_card.go +++ b/builtin/providers/azurerm/resource_arm_network_interface_card.go @@ -172,6 +172,14 @@ func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) properties.NetworkSecurityGroup = &network.SecurityGroup{ ID: &nsgId, } + + networkSecurityGroupName, err := parseNetworkSecurityGroupName(nsgId) + if err != nil { + return err + } + + armMutexKV.Lock(networkSecurityGroupName) + defer armMutexKV.Unlock(networkSecurityGroupName) } dns, hasDns := d.GetOk("dns_servers") @@ -308,6 +316,17 @@ func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) resGroup := id.ResourceGroup name := id.Path["networkInterfaces"] + if v, ok := d.GetOk("network_security_group_id"); ok { + networkSecurityGroupId := v.(string) + networkSecurityGroupName, err := parseNetworkSecurityGroupName(networkSecurityGroupId) + if err != nil { + return err + } + + armMutexKV.Lock(networkSecurityGroupName) + defer armMutexKV.Unlock(networkSecurityGroupName) + } + _, err = ifaceClient.Delete(resGroup, name, make(chan struct{})) return err diff --git a/builtin/providers/azurerm/resource_arm_subnet.go b/builtin/providers/azurerm/resource_arm_subnet.go index c5329b9f8..65df4f447 100644 --- a/builtin/providers/azurerm/resource_arm_subnet.go +++ b/builtin/providers/azurerm/resource_arm_subnet.go @@ -89,6 +89,14 @@ func resourceArmSubnetCreate(d *schema.ResourceData, meta interface{}) error { properties.NetworkSecurityGroup = &network.SecurityGroup{ ID: &nsgId, } + + networkSecurityGroupName, err := parseNetworkSecurityGroupName(nsgId) + if err != nil { + return err + } + + armMutexKV.Lock(networkSecurityGroupName) + defer armMutexKV.Unlock(networkSecurityGroupName) } if v, ok := d.GetOk("route_table_id"); ok { @@ -182,6 +190,17 @@ func resourceArmSubnetDelete(d *schema.ResourceData, meta interface{}) error { name := id.Path["subnets"] vnetName := id.Path["virtualNetworks"] + if v, ok := d.GetOk("network_security_group_id"); ok { + networkSecurityGroupId := v.(string) + networkSecurityGroupName, err := parseNetworkSecurityGroupName(networkSecurityGroupId) + if err != nil { + return err + } + + armMutexKV.Lock(networkSecurityGroupName) + defer armMutexKV.Unlock(networkSecurityGroupName) + } + armMutexKV.Lock(vnetName) defer armMutexKV.Unlock(vnetName) diff --git a/builtin/providers/azurerm/resource_arm_virtual_network.go b/builtin/providers/azurerm/resource_arm_virtual_network.go index 5d4ba9a29..217323a6f 100644 --- a/builtin/providers/azurerm/resource_arm_virtual_network.go +++ b/builtin/providers/azurerm/resource_arm_virtual_network.go @@ -97,6 +97,21 @@ func resourceArmVirtualNetworkCreate(d *schema.ResourceData, meta interface{}) e Tags: expandTags(tags), } + networkSecurityGroupNames := make([]string, 0) + for _, subnet := range *vnet.VirtualNetworkPropertiesFormat.Subnets { + if subnet.NetworkSecurityGroup != nil { + nsgName, err := parseNetworkSecurityGroupName(*subnet.NetworkSecurityGroup.ID) + if err != nil { + return err + } + + networkSecurityGroupNames = append(networkSecurityGroupNames, nsgName) + } + } + + azureRMVirtualNetworkLockNetworkSecurityGroups(&networkSecurityGroupNames) + defer azureRMVirtualNetworkUnlockNetworkSecurityGroups(&networkSecurityGroupNames) + _, err := vnetClient.CreateOrUpdate(resGroup, name, vnet, make(chan struct{})) if err != nil { return err @@ -182,6 +197,14 @@ func resourceArmVirtualNetworkDelete(d *schema.ResourceData, meta interface{}) e resGroup := id.ResourceGroup name := id.Path["virtualNetworks"] + nsgNames, err := expandAzureRmVirtualNetworkVirtualNetworkSecurityGroupNames(d) + if err != nil { + return fmt.Errorf("[ERROR] Error parsing Network Security Group ID's: %+v", err) + } + + azureRMVirtualNetworkLockNetworkSecurityGroups(&nsgNames) + defer azureRMVirtualNetworkUnlockNetworkSecurityGroups(&nsgNames) + _, err = vnetClient.Delete(resGroup, name, make(chan struct{})) return err @@ -245,3 +268,40 @@ func resourceAzureSubnetHash(v interface{}) int { } return hashcode.String(subnet) } + +func expandAzureRmVirtualNetworkVirtualNetworkSecurityGroupNames(d *schema.ResourceData) ([]string, error) { + nsgNames := make([]string, 0) + + if v, ok := d.GetOk("subnet"); ok { + subnets := v.(*schema.Set).List() + for _, subnet := range subnets { + subnet, ok := subnet.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("[ERROR] Subnet should be a Hash - was '%+v'", subnet) + } + + networkSecurityGroupId := subnet["security_group"].(string) + if networkSecurityGroupId != "" { + nsgName, err := parseNetworkSecurityGroupName(networkSecurityGroupId) + if err != nil { + return nil, err + } + + nsgNames = append(nsgNames, nsgName) + } + } + } + + return nsgNames, nil +} + +func azureRMVirtualNetworkUnlockNetworkSecurityGroups(networkSecurityGroupNames *[]string) { + for _, networkSecurityGroupName := range *networkSecurityGroupNames { + armMutexKV.Unlock(networkSecurityGroupName) + } +} +func azureRMVirtualNetworkLockNetworkSecurityGroups(networkSecurityGroupNames *[]string) { + for _, networkSecurityGroupName := range *networkSecurityGroupNames { + armMutexKV.Lock(networkSecurityGroupName) + } +} diff --git a/builtin/providers/azurerm/resourceid.go b/builtin/providers/azurerm/resourceid.go index b05f4d75f..f981b410b 100644 --- a/builtin/providers/azurerm/resourceid.go +++ b/builtin/providers/azurerm/resourceid.go @@ -95,3 +95,12 @@ func parseAzureResourceID(id string) (*ResourceID, error) { return idObj, nil } + +func parseNetworkSecurityGroupName(networkSecurityGroupId string) (string, error) { + id, err := parseAzureResourceID(networkSecurityGroupId) + if err != nil { + return "", fmt.Errorf("[ERROR] Unable to Parse Network Security Group ID '%s': %+v", networkSecurityGroupId, err) + } + + return id.Path["networkSecurityGroups"], nil +}