Skip to content

Commit

Permalink
azurerm_public_ip - support for the ddos_protection_mode and `ddo…
Browse files Browse the repository at this point in the history
…s_protection_plan_id` properties (#19206)
  • Loading branch information
teowa authored Nov 10, 2022
1 parent 819cda5 commit e00a4b0
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 2 deletions.
18 changes: 18 additions & 0 deletions internal/services/network/public_ip_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ func dataSourcePublicIP() *pluginsdk.Resource {
Computed: true,
},

"ddos_protection_mode": {
Type: pluginsdk.TypeString,
Computed: true,
},

"ddos_protection_plan_id": {
Type: pluginsdk.TypeString,
Computed: true,
},

"ip_version": {
Type: pluginsdk.TypeString,
Computed: true,
Expand Down Expand Up @@ -137,6 +147,14 @@ func dataSourcePublicIPRead(d *pluginsdk.ResourceData, meta interface{}) error {
reverseFqdn = *dnsSettings.ReverseFqdn
}
}

if ddosSetting := props.DdosSettings; ddosSetting != nil {
d.Set("ddos_protection_mode", string(ddosSetting.ProtectionMode))
if subResource := ddosSetting.DdosProtectionPlan; subResource != nil {
d.Set("ddos_protection_plan_id", subResource.ID)
}
}

d.Set("domain_name_label", domainNameLabel)
d.Set("fqdn", fqdn)
d.Set("reverse_fqdn", reverseFqdn)
Expand Down
42 changes: 40 additions & 2 deletions internal/services/network/public_ip_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ func resourcePublicIp() *pluginsdk.Resource {
},

// Optional
"ddos_protection_mode": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
string(network.DdosSettingsProtectionModeDisabled),
string(network.DdosSettingsProtectionModeEnabled),
string(network.DdosSettingsProtectionModeVirtualNetworkInherited),
}, false),
Default: string(network.DdosSettingsProtectionModeVirtualNetworkInherited),
},

"ddos_protection_plan_id": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validate.DdosProtectionPlanID,
},

"edge_zone": commonschema.EdgeZoneOptionalForceNew(),

"ip_version": {
Expand Down Expand Up @@ -174,7 +191,7 @@ func resourcePublicIpCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) e

location := azure.NormalizeLocation(d.Get("location").(string))
sku := d.Get("sku").(string)
sku_tier := d.Get("sku_tier").(string)
skuTier := d.Get("sku_tier").(string)
t := d.Get("tags").(map[string]interface{})

idleTimeout := d.Get("idle_timeout_in_minutes").(int)
Expand All @@ -187,21 +204,35 @@ func resourcePublicIpCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) e
}
}

ddosProtectionMode := d.Get("ddos_protection_mode").(string)

publicIp := network.PublicIPAddress{
Name: utils.String(id.Name),
ExtendedLocation: expandEdgeZone(d.Get("edge_zone").(string)),
Location: &location,
Sku: &network.PublicIPAddressSku{
Name: network.PublicIPAddressSkuName(sku),
Tier: network.PublicIPAddressSkuTier(sku_tier),
Tier: network.PublicIPAddressSkuTier(skuTier),
},
PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
PublicIPAllocationMethod: network.IPAllocationMethod(ipAllocationMethod),
PublicIPAddressVersion: ipVersion,
IdleTimeoutInMinutes: utils.Int32(int32(idleTimeout)),
DdosSettings: &network.DdosSettings{
ProtectionMode: network.DdosSettingsProtectionMode(ddosProtectionMode),
},
},
Tags: tags.Expand(t),
}
ddosProtectionPlanId, planOk := d.GetOk("ddos_protection_plan_id")
if planOk {
if !strings.EqualFold(ddosProtectionMode, "enabled") {
return fmt.Errorf("ddos protection plan id can only be set when ddos protection is enabled")
}
publicIp.PublicIPAddressPropertiesFormat.DdosSettings.DdosProtectionPlan = &network.SubResource{
ID: utils.String(ddosProtectionPlanId.(string)),
}
}

zones := zones.ExpandUntyped(d.Get("zones").(*schema.Set).List())
if len(zones) > 0 {
Expand Down Expand Up @@ -306,6 +337,13 @@ func resourcePublicIpRead(d *pluginsdk.ResourceData, meta interface{}) error {
d.Set("domain_name_label", settings.DomainNameLabel)
}

if ddosSetting := props.DdosSettings; ddosSetting != nil {
d.Set("ddos_protection_mode", string(ddosSetting.ProtectionMode))
if subResource := ddosSetting.DdosProtectionPlan; subResource != nil {
d.Set("ddos_protection_plan_id", subResource.ID)
}
}

d.Set("ip_tags", flattenPublicIpPropsIpTags(props.IPTags))

d.Set("ip_address", props.IPAddress)
Expand Down
77 changes: 77 additions & 0 deletions internal/services/network/public_ip_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestAccPublicIpStatic_basic(t *testing.T) {
check.That(data.ResourceName).Key("ip_address").Exists(),
check.That(data.ResourceName).Key("allocation_method").HasValue("Static"),
check.That(data.ResourceName).Key("ip_version").HasValue("IPv4"),
check.That(data.ResourceName).Key("ddos_protection_mode").HasValue("VirtualNetworkInherited"),
),
},
data.ImportStep(),
Expand Down Expand Up @@ -191,6 +192,31 @@ func TestAccPublicIpStatic_standard(t *testing.T) {
})
}

func TestAccPublicIpStatic_standard_withDDoS(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_public_ip", "test")
r := PublicIPResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.standardDDoSDisabled(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("ddos_protection_mode").HasValue("Disabled"),
),
},
data.ImportStep(),
{
Config: r.standardDDoSEnabled(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("ddos_protection_mode").HasValue("Enabled"),
check.That(data.ResourceName).Key("ddos_protection_plan_id").Exists(),
),
},
data.ImportStep(),
})
}

func TestAccPublicIpStatic_disappears(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_public_ip", "test")
r := PublicIPResource{}
Expand Down Expand Up @@ -550,6 +576,57 @@ resource "azurerm_public_ip" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (PublicIPResource) standardDDoSDisabled(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_public_ip" "test" {
name = "acctestpublicip-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
allocation_method = "Static"
sku = "Standard"
ddos_protection_mode = "Disabled"
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (PublicIPResource) standardDDoSEnabled(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_network_ddos_protection_plan" "test" {
name = "acctestddospplan-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}
resource "azurerm_public_ip" "test" {
name = "acctestpublicip-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
allocation_method = "Static"
sku = "Standard"
ddos_protection_mode = "Enabled"
ddos_protection_plan_id = azurerm_network_ddos_protection_plan.test.id
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
}

func (PublicIPResource) standardPrefix(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/d/public_ip.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ output "public_ip_address" {
* `id` - The ID of the Public IP address.
* `domain_name_label` - The label for the Domain Name.
* `idle_timeout_in_minutes` - Specifies the timeout for the TCP idle connection.
* `ddos_protection_mode` - The DDoS protection mode of the public IP.
* `ddos_protection_plan_id` - The ID of DDoS protection plan associated with the public IP.
* `fqdn` - Fully qualified domain name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone.
* `ip_address` - The IP address value that was allocated.
* `ip_version` - The IP version being used, for example `IPv4` or `IPv6`.
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/public_ip.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ The following arguments are supported:

-> **Note:** Availability Zones are only supported with a [Standard SKU](https://docs.microsoft.com/azure/virtual-network/virtual-network-ip-addresses-overview-arm#standard) and [in select regions](https://docs.microsoft.com/azure/availability-zones/az-overview) at this time. Standard SKU Public IP Addresses that do not specify a zone are **not** zone-redundant by default.

* `ddos_protection_mode` - (Optional) The DDoS protection mode of the public IP. Possible values are `Disabled`, `Enabled`, and `VirtualNetworkInherited`. Defaults to `VirtualNetworkInherited`.

* `ddos_protection_plan_id` - (Optional) The ID of DDoS protection plan associated with the public IP.

-> **Note:** `ddos_protection_plan_id` can only be set when `ddos_protection_mode` is `Enabled`.

* `domain_name_label` - (Optional) Label for the Domain Name. Will be used to make up the FQDN. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system.

* `edge_zone` - (Optional) Specifies the Edge Zone within the Azure Region where this Public IP should exist. Changing this forces a new Public IP to be created.
Expand Down

0 comments on commit e00a4b0

Please sign in to comment.