Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add delegation support to virtual network subnet blocks #24972

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions internal/services/network/subnet_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ var subnetDelegationServiceNames = []string{
"Qumulo.Storage/fileSystems",
}

var subnetDelegationActions = []string{
"Microsoft.Network/networkinterfaces/*",
"Microsoft.Network/publicIPAddresses/join/action",
"Microsoft.Network/publicIPAddresses/read",
"Microsoft.Network/virtualNetworks/read",
"Microsoft.Network/virtualNetworks/subnets/action",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action",
"Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action",
}

func resourceSubnet() *pluginsdk.Resource {
resource := &pluginsdk.Resource{
Create: resourceSubnetCreate,
Expand Down
52 changes: 51 additions & 1 deletion internal/services/network/virtual_network_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func resourceVirtualNetworkSchema() map[string]*pluginsdk.Schema {
Type: pluginsdk.TypeSet,
Optional: true,
Computed: true,
ConfigMode: pluginsdk.SchemaConfigModeAttr,
ConfigMode: pluginsdk.SchemaConfigModeAuto,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Expand All @@ -164,6 +164,42 @@ func resourceVirtualNetworkSchema() map[string]*pluginsdk.Schema {
ValidateFunc: validation.StringIsNotEmpty,
},

"delegation": {
Type: pluginsdk.TypeList,
Optional: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
},
"service_delegation": {
Type: pluginsdk.TypeList,
Required: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(subnetDelegationServiceNames, false),
},

"actions": {
Type: pluginsdk.TypeList,
Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validation.StringInSlice(subnetDelegationActions, false),
},
},
},
},
},
},
},
},

"security_group": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -395,6 +431,13 @@ func expandVirtualNetworkProperties(ctx context.Context, d *pluginsdk.ResourceDa
subnetObj.SubnetPropertiesFormat.NetworkSecurityGroup = nil
}

if v, ok := subnet["delegation"]; ok {
delegationsRaw := v.([]interface{})
subnetObj.SubnetPropertiesFormat.Delegations = expandSubnetDelegation(delegationsRaw)
} else {
subnetObj.SubnetPropertiesFormat.Delegations = nil
}

subnets = append(subnets, *subnetObj)
}
}
Expand Down Expand Up @@ -503,6 +546,13 @@ func flattenVirtualNetworkSubnets(input *[]network.Subnet) *pluginsdk.Set {
output["security_group"] = *nsg.ID
}
}
if delegations := props.Delegations; delegations != nil {
flattenedDelegations := flattenSubnetDelegation(delegations)
if len(flattenedDelegations) > 0 {
output["delegation"] = flattenedDelegations
}
}

}

results.Add(output)
Expand Down
54 changes: 54 additions & 0 deletions internal/services/network/virtual_network_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,27 @@ func TestAccVirtualNetwork_ddosProtectionPlan(t *testing.T) {
})
}

func TestAccVirtualNetwork_subnetDelegation(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_virtual_network", "test")
r := VirtualNetworkResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.subnetDelegation(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
// Validate the delegation properties
check.That(data.ResourceName).Key("subnet.0.delegation.#").HasValue("1"),
check.That(data.ResourceName).Key("subnet.0.delegation.0.name").HasValue("acctestDelegation"),
check.That(data.ResourceName).Key("subnet.0.delegation.0.service_delegation.0.name").HasValue("Microsoft.ContainerInstance/containerGroups"),
check.That(data.ResourceName).Key("subnet.0.delegation.0.service_delegation.0.actions.#").HasValue("1"),
check.That(data.ResourceName).Key("subnet.0.delegation.0.service_delegation.0.actions.0").HasValue("Microsoft.Network/virtualNetworks/subnets/action"),
),
},
data.ImportStep(),
})
}

func TestAccVirtualNetwork_disappears(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_virtual_network", "test")
r := VirtualNetworkResource{}
Expand Down Expand Up @@ -623,3 +644,36 @@ resource "azurerm_virtual_network" "test" {
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (VirtualNetworkResource) subnetDelegation(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_virtual_network" "test" {
name = "acctestVNet-%d"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name

subnet {
name = "acctestSubnet-%d"
address_prefix = "10.0.1.0/24"

delegation {
name = "acctestDelegation"
service_delegation {
name = "Microsoft.ContainerInstance/containerGroups"
actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
}
}
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
}
19 changes: 17 additions & 2 deletions website/docs/r/virtual_network.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ resource "azurerm_virtual_network" "example" {

The following arguments are supported:

* `name` - (Required) The name of the virtual network. Changing this forces a new resource to be created.
* `name` - (Required) The name of the virtual network. Changing this forces a new resource to be created.

* `resource_group_name` - (Required) The name of the resource group in which to create the virtual network. Changing this forces a new resource to be created.

* `address_space` - (Required) The address space that is used the virtual network. You can supply more than one address space.

* `location` - (Required) The location/region where the virtual network is created. Changing this forces a new resource to be created.
* `location` - (Required) The location/region where the virtual network is created. Changing this forces a new resource to be created.

---

Expand Down Expand Up @@ -113,6 +113,20 @@ The `subnet` block supports:

* `address_prefix` - (Required) The address prefix to use for the subnet.

* `delegation` - (Optional) Can be specified multiple times to define multiple delegations. Each delegation block supports fields documented below.

A delegation block supports the following:

`name` - (Required) The name of the delegation.

`service_delegation` - (Required) A `service_delegation` block as documented below.

A service_delegation block supports the following:

`name` - (Required) The name of the service to which the subnet is delegated (e.g., `Microsoft.ContainerInstance/containerGroups`).

`actions` - (Optional) A list of actions that are delegated. Can include `Microsoft.Network/virtualNetworks/subnets/action` and others depending on the service.

* `security_group` - (Optional) The Network Security Group to associate with the subnet. (Referenced by `id`, ie. `azurerm_network_security_group.example.id`)

## Attributes Reference
Expand All @@ -138,6 +152,7 @@ In addition to the Arguments listed above - the following Attributes are exporte
The `subnet` block exports:

* `id` - The ID of this subnet.
* `delegation` - One or more delegation blocks as configured, including the name and details of the service delegation.

## Timeouts

Expand Down
Loading