Skip to content

Commit

Permalink
Merge pull request #2042 from terraform-providers/subnet_delegation
Browse files Browse the repository at this point in the history
Add delegation support for Subnet
  • Loading branch information
katbyte authored Jan 8, 2019
2 parents e65a6d7 + 70c4108 commit 357fe46
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 13 deletions.
129 changes: 121 additions & 8 deletions azurerm/resource_arm_subnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

Expand Down Expand Up @@ -66,6 +67,45 @@ func resourceArmSubnet() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"delegation": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"service_delegation": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"Microsoft.ContainerInstance/containerGroups",
}, false),
},
"actions": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"Microsoft.Network/virtualNetworks/subnets/action",
}, false),
},
},
},
},
},
},
},
},
},
}
}
Expand Down Expand Up @@ -122,13 +162,12 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err
properties.RouteTable = nil
}

serviceEndpoints, serviceEndpointsErr := expandAzureRmServiceEndpoints(d)
if serviceEndpointsErr != nil {
return fmt.Errorf("Error Building list of Service Endpoints: %+v", serviceEndpointsErr)
}

serviceEndpoints := expandSubnetServiceEndpoints(d)
properties.ServiceEndpoints = &serviceEndpoints

delegations := expandSubnetDelegation(d)
properties.Delegations = &delegations

subnet := network.Subnet{
Name: &name,
SubnetPropertiesFormat: &properties,
Expand Down Expand Up @@ -185,9 +224,11 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error {
if props := resp.SubnetPropertiesFormat; props != nil {
d.Set("address_prefix", props.AddressPrefix)

var securityGroupId *string
if props.NetworkSecurityGroup != nil {
d.Set("network_security_group_id", props.NetworkSecurityGroup.ID)
securityGroupId = props.NetworkSecurityGroup.ID
}
d.Set("network_security_group_id", securityGroupId)

var routeTableId string
if props.RouteTable != nil && props.RouteTable.ID != nil {
Expand All @@ -204,6 +245,11 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("service_endpoints", serviceEndpoints); err != nil {
return err
}

delegation := flattenSubnetDelegation(props.Delegations)
if err := d.Set("delegation", delegation); err != nil {
return fmt.Errorf("Error flattening `delegation`: %+v", err)
}
}

return nil
Expand Down Expand Up @@ -261,7 +307,7 @@ func resourceArmSubnetDelete(d *schema.ResourceData, meta interface{}) error {
return nil
}

func expandAzureRmServiceEndpoints(d *schema.ResourceData) ([]network.ServiceEndpointPropertiesFormat, error) {
func expandSubnetServiceEndpoints(d *schema.ResourceData) []network.ServiceEndpointPropertiesFormat {
serviceEndpoints := d.Get("service_endpoints").([]interface{})
enpoints := make([]network.ServiceEndpointPropertiesFormat, 0)

Expand All @@ -275,7 +321,7 @@ func expandAzureRmServiceEndpoints(d *schema.ResourceData) ([]network.ServiceEnd
enpoints = append(enpoints, endpoint)
}

return enpoints, nil
return enpoints
}

func flattenSubnetServiceEndpoints(serviceEndpoints *[]network.ServiceEndpointPropertiesFormat) []string {
Expand All @@ -301,3 +347,70 @@ func flattenSubnetIPConfigurations(ipConfigurations *[]network.IPConfiguration)

return ips
}

func expandSubnetDelegation(d *schema.ResourceData) []network.Delegation {
delegations := d.Get("delegation").([]interface{})
retDelegations := make([]network.Delegation, 0)

for _, deleValue := range delegations {
deleData := deleValue.(map[string]interface{})
deleName := deleData["name"].(string)
srvDelegations := deleData["service_delegation"].([]interface{})
srvDelegation := srvDelegations[0].(map[string]interface{})
srvName := srvDelegation["name"].(string)
srvActions := srvDelegation["actions"].([]interface{})

retSrvActions := make([]string, 0)
for _, srvAction := range srvActions {
srvActionData := srvAction.(string)
retSrvActions = append(retSrvActions, srvActionData)
}

retDelegation := network.Delegation{
Name: &deleName,
ServiceDelegationPropertiesFormat: &network.ServiceDelegationPropertiesFormat{
ServiceName: &srvName,
Actions: &retSrvActions,
},
}

retDelegations = append(retDelegations, retDelegation)
}

return retDelegations
}

func flattenSubnetDelegation(delegations *[]network.Delegation) []interface{} {
if delegations == nil {
return []interface{}{}
}

retDeles := make([]interface{}, 0)

for _, dele := range *delegations {
retDele := make(map[string]interface{})
if v := dele.Name; v != nil {
retDele["name"] = *v
}

svcDeles := make([]interface{}, 0)
svcDele := make(map[string]interface{})
if props := dele.ServiceDelegationPropertiesFormat; props != nil {
if v := props.ServiceName; v != nil {
svcDele["name"] = *v
}

if v := props.Actions; v != nil {
svcDele["actions"] = *v
}
}

svcDeles = append(svcDeles, svcDele)

retDele["service_delegation"] = svcDeles

retDeles = append(retDeles, retDele)
}

return retDeles
}
64 changes: 59 additions & 5 deletions azurerm/resource_arm_subnet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,29 @@ func TestAccAzureRMSubnet_basic(t *testing.T) {
})
}

func TestAccAzureRMSubnet_delegation(t *testing.T) {
resourceName := "azurerm_subnet.test"
ri := acctest.RandInt()
config := testAccAzureRMSubnet_delegation(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMSubnetDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSubnetExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "delegation.#", "1"),
),
},
},
})
}

func TestAccAzureRMSubnet_routeTableUpdate(t *testing.T) {
resourceName := "azurerm_subnet.test"
ri := acctest.RandInt()
location := testLocation()
initConfig := testAccAzureRMSubnet_routeTable(ri, location)
Expand All @@ -52,14 +74,14 @@ func TestAccAzureRMSubnet_routeTableUpdate(t *testing.T) {
{
Config: initConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSubnetExists("azurerm_subnet.test"),
testCheckAzureRMSubnetExists(resourceName),
),
},

{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSubnetRouteTableExists("azurerm_subnet.test", fmt.Sprintf("acctest-%d", ri)),
testCheckAzureRMSubnetRouteTableExists(resourceName, fmt.Sprintf("acctest-%d", ri)),
),
},
},
Expand Down Expand Up @@ -157,6 +179,7 @@ func TestAccAzureRMSubnet_bug7986(t *testing.T) {
}

func TestAccAzureRMSubnet_bug15204(t *testing.T) {
resourceName := "azurerm_subnet.test"
ri := acctest.RandInt()
initConfig := testAccAzureRMSubnet_bug15204(ri, testLocation())

Expand All @@ -168,14 +191,15 @@ func TestAccAzureRMSubnet_bug15204(t *testing.T) {
{
Config: initConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSubnetExists("azurerm_subnet.test"),
testCheckAzureRMSubnetExists(resourceName),
),
},
},
})
}

func TestAccAzureRMSubnet_disappears(t *testing.T) {
resourceName := "azurerm_subnet.test"
ri := acctest.RandInt()
config := testAccAzureRMSubnet_basic(ri, testLocation())

Expand All @@ -187,8 +211,8 @@ func TestAccAzureRMSubnet_disappears(t *testing.T) {
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSubnetExists("azurerm_subnet.test"),
testCheckAzureRMSubnetDisappears("azurerm_subnet.test"),
testCheckAzureRMSubnetExists(resourceName),
testCheckAzureRMSubnetDisappears(resourceName),
),
ExpectNonEmptyPlan: true,
},
Expand Down Expand Up @@ -380,6 +404,36 @@ resource "azurerm_subnet" "test" {
`, rInt, location, rInt, rInt)
}

func testAccAzureRMSubnet_delegation(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%d"
address_space = ["10.0.0.0/16"]
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_subnet" "test" {
name = "acctestsubnet%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.2.0/24"
delegation {
name = "acctestdelegation"
service_delegation {
name = "Microsoft.ContainerInstance/containerGroups"
actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
}
}
}
`, rInt, location, rInt, rInt)
}

func testAccAzureRMSubnet_routeTable(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down
23 changes: 23 additions & 0 deletions website/docs/r/subnet.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ resource "azurerm_subnet" "test" {
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.1.0/24"
delegation {
name = "acctestdelegation"
service_delegation {
name = "Microsoft.ContainerInstance/containerGroups"
actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
}
}
}
```

Expand All @@ -60,6 +67,22 @@ The following arguments are supported:

* `service_endpoints` - (Optional) The list of Service endpoints to associate with the subnet. Possible values include: `Microsoft.AzureActiveDirectory`, `Microsoft.AzureCosmosDB`, `Microsoft.EventHub`, `Microsoft.KeyVault`, `Microsoft.ServiceBus`, `Microsoft.Sql` and `Microsoft.Storage`.

* `delegation` - (Optional) One or more `delegation` blocks as defined below.

---

A `delegation` block supports the following:
* `name` (Required) A name for this delegation.
* `service_delegation` (Required) A `service_delegation` block as defined below.

---

A `service_delegation` block supports the following:
* `name` - (Required) The name of service to delegate to. Possible values include: `Microsoft.ContainerInstance/containerGroups`.
* `actions` - (Optional) A list of Actions which should be delegated. Possible values include: `Microsoft.Network/virtualNetworks/subnets/action`.

[More information on Subnet Delegation can be found in the Azure CLI documentation](https://docs.microsoft.com/en-us/cli/azure/network/vnet/subnet?view=azure-cli-latest#az-network-vnet-subnet-list-available-delegations)

## Attributes Reference

The following attributes are exported:
Expand Down

0 comments on commit 357fe46

Please sign in to comment.