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

Support address_prefixes for multiple prefixes in subnet and virtualnetwork (ipv6) #6148

Closed
wants to merge 1 commit into from
Closed

Support address_prefixes for multiple prefixes in subnet and virtualnetwork (ipv6) #6148

wants to merge 1 commit into from

Conversation

fabianofranz
Copy link
Contributor

@fabianofranz fabianofranz commented Mar 17, 2020

The azure subnet resource supports addressPrefix when one prefix is available and addressPrefixes when two or or more are set (for instance, when configuring an ipv4 and ipv6 dual stack configuration for a network). Update azurerm_subnet to allow either address_prefix or address_prefixes as input, where the latter is a list of string. Check that at least one is set, and mark the older address_prefix as deprecated.

The virtual network resource allows inline subnets, but does not currently support this argument. When the address_prefixes argument is used, address_prefix will be null when terraform refreshes its state causing terraform to panic. This code updates also the virtual network resource to allow
address_prefixes to be used and for address_prefix to be null.

Fixes #5140
Takes over #5139

@ghost ghost added the size/M label Mar 17, 2020
@abhinavdahiya
Copy link
Contributor

maybe commits from #6142 belong with this PR since they are addressing the same subnets with multiple address prefixes

@ghost ghost added size/L and removed size/M labels Mar 18, 2020
@fabianofranz fabianofranz changed the title subnet: Support address_prefixes for multiple prefixes (ipv6) Support address_prefixes for multiple prefixes in subnet and virtualnetwork (ipv6) Mar 18, 2020
@fabianofranz
Copy link
Contributor Author

@abhinavdahiya makes sense, I added commit #6142 to this PR and closed the other one.

@fabianofranz
Copy link
Contributor Author

@katbyte PTAL

Copy link
Collaborator

@katbyte katbyte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @fabianofranz, looks like we're missing doc updates, could we update them? thanks!

@@ -94,7 +100,18 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error {
d.Set("virtual_network_name", virtualNetworkName)

if props := resp.SubnetPropertiesFormat; props != nil {
d.Set("address_prefix", props.AddressPrefix)
if props.AddressPrefix != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need a nil check here as d.Set will do it for us

"address_prefixes": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we validate this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do the same validation I mentioned above here

Copy link
Member

@mbfrahry mbfrahry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @fabianofranz, this is off to a good start. I've left some comments on what we can do differently but the bulk of my issues are around testing. I've left some notes on one of the tests but it'd also be great to get a more comprehensive suite of tests since we're deprecating and we should ensure that the old functionality works with the new way of doing things. We'll also want to update the attributes by adding and removing address prefixes. Lastly, we'll need to update the documentation by deprecating the old field there and adding the new ones.

properties.AddressPrefixes = nil
}
if !prefixSet {
return fmt.Errorf("[ERROR] either address_prefix or address_prefixes is required")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this check and prefixSet if we swap the ConflictsWith tag in the schema for address_prefix and address_prefixes with ExactlyOneOf: []string{"address_prefix", "address_prefixes"},

@@ -306,7 +330,18 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error {
d.Set("virtual_network_name", networkName)

if props := resp.SubnetPropertiesFormat; props != nil {
d.Set("address_prefix", props.AddressPrefix)
if props.AddressPrefix != nil {
d.Set("address_prefix", props.AddressPrefix)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to Katie's comment above, we don't need to nil check this before setting it

@@ -30,6 +30,28 @@ func TestAccDataSourceSubnet_basic(t *testing.T) {
})
}

func TestAccDataSourceAzureRMSubnet_basic_addressPrefixes(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we're missing a similar test for the actual resource

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test also fails with:

Subnet is not valid because its IP address range is outside the IP address range of virtual network.

It looks like it's due to the ipv6 address that was specified.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test now passes!

d.Set("address_prefix", props.AddressPrefix)
}
if props.AddressPrefixes == nil {
if props.AddressPrefix != nil && len(*props.AddressPrefix) > 0 {

This comment was marked as resolved.

func testAccAzureRMVirtualNetwork_basic_addressPrefixes(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should append the package initial to the resource group name like so:

Suggested change
name = "acctestRG-%d"
name = "acctestRG-n-%d"

so we can better track the resource groups that are getting hung up on what tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since most already existing tests already use that, I'd suggest to handle this for all tests in a separate PR. ;-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we should do it for the rest but we should do the best practice now for any new features and we can fix up the rest when we can

properties.AddressPrefix = &(*properties.AddressPrefixes)[0]
properties.AddressPrefixes = nil
}
if prefixSet == 0 {

This comment was marked as resolved.

@ghost ghost added size/XL documentation and removed size/L labels Apr 2, 2020
@fabianofranz
Copy link
Contributor Author

@katbyte @mbfrahry I'm having a test failure with ExactlyOneOf, do you have any clue? Tks!

--- FAIL: TestProvider (0.13s)
    provider_test.go:12: err: 1 error occurred:
        	* resource azurerm_virtual_network: ExactlyOneOf: address_prefix references unknown attribute (address_prefix) at part (address_prefix)

@ghost ghost removed the waiting-response label Apr 4, 2020
@mbfrahry
Copy link
Member

mbfrahry commented Apr 7, 2020

Hey @fabianofranz, unfortunately ExactlyOneOf, ConflictsWith, and the others have a limitation in that they don't work quite the way you want them to for Lists and Sets. The error you're seeing is because the ExactlyOneOf logic is looking for address_prefix but it should really be looking for subnet.x.address_prefix where x is the index of the set you want to compare. The tricky bit is that we don't know how many subnets there could be so we can't effectively check that ExactlyOneOf works. Unfortunately, we'll need to do some of this logic manually for now with a note to remove it when we release 3.0 of the provider in the future.

You can use it with List/Set that has a MaxItems: 1 because we know that subnet.0.address_prefix will exist. But we can't use that Validation for any List/Set that we don't know the size of.

Also, I want to apologize for sending you down this rabbit hole. The files changed tab made it tricky to see that those values were in a Set. But the validation should be able to stay with the subnet resource

@fabianofranz
Copy link
Contributor Author

Hey @fabianofranz, unfortunately ExactlyOneOf, ConflictsWith, and the others have a limitation in that they don't work quite the way you want them to for Lists and Sets. The error you're seeing is because the ExactlyOneOf logic is looking for address_prefix but it should really be looking for subnet.x.address_prefix where x is the index of the set you want to compare. The tricky bit is that we don't know how many subnets there could be so we can't effectively check that ExactlyOneOf works. Unfortunately, we'll need to do some of this logic manually for now with a note to remove it when we release 3.0 of the provider in the future.

You can use it with List/Set that has a MaxItems: 1 because we know that subnet.0.address_prefix will exist. But we can't use that Validation for any List/Set that we don't know the size of.

Also, I want to apologize for sending you down this rabbit hole. The files changed tab made it tricky to see that those values were in a Set. But the validation should be able to stay with the subnet resource

Ok @mbfrahry, thanks for the explanation. I updated this PR back to validations in the subnet resource and addressed most comments from you and @katbyte. I think it must be good for another round of reviews, thanks!

Copy link
Member

@mbfrahry mbfrahry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @fabianofranz, thanks for making my requested changes. The tests for the subnet resource/datasource side of things looks good. I just have some minor comments/fixes to address

I am having issues getting the AllowMultipleAddressPrefixesOnSubnet feature for virtual networks registered and so I can't move forward on reviewing that because I can't test it. I've opened a support ticket to see why that's the case but I'm not sure how long that'll take.

We can either wait some unknown amount of time to see what they come back with or we split this PR into two PRs. One for subnets and one for virtual networks and we get the subnets one in quickly. Apologies for the added work while we wait on the Azure side

@@ -241,6 +263,11 @@ func resourceArmSubnetUpdate(d *schema.ResourceData, meta interface{}) error {
props.AddressPrefix = utils.String(d.Get("address_prefix").(string))
}

if d.HasChange("address_prefixes") {
addressPrefixesRaw := d.Get("address_prefixes").([]interface{})
props.AddressPrefixes = utils.ExpandStringSlice(addressPrefixesRaw)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do logic in the Create method for when address prefixes length is 1. Do we want to mirror that here?

Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you have an empty address prefix? If not we should definitely enforce that we pass something to the API through

Suggested change
Elem: &schema.Schema{Type: schema.TypeString},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringIsNotEmpty,
},

Type: schema.TypeString,
Optional: true,
Computed: true,
Deprecated: "Use the `address_prefixes` property instead.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a TODO comment here to remove these deprecations in the next major version. This will help us quickly find and remove all the deprecations when the time comes for the next major version

Suggested change
Deprecated: "Use the `address_prefixes` property instead.",
// TODO Remove this in the next major version release
Deprecated: "Use the `address_prefixes` property instead.",

"address_prefixes": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do the same validation I mentioned above here

properties.AddressPrefixes = nil
}
if prefixSet == 0 {
return nil, fmt.Errorf("[ERROR] either address_prefix or address_prefixes is required")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return nil, fmt.Errorf("[ERROR] either address_prefix or address_prefixes is required")
return nil, fmt.Errorf("one of `address_prefix` or `address_prefixes` must be set")

just cleaning up the language here to be more consistent with similar error messages.

@@ -101,7 +105,8 @@ The following attributes are exported:
* `name` - The name of the subnet.
* `resource_group_name` - The name of the resource group in which the subnet is created in.
* `virtual_network_name` - The name of the virtual network in which the subnet is created in
* `address_prefix` - The address prefix for the subnet
* `address_prefix` - (Deprecated) The address prefix for the subnet
* `address_prefixes` - The address prefixes for the subnet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to add something similar over on the datasource docs as well

func testAccAzureRMVirtualNetwork_basic_addressPrefixes(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we should do it for the rest but we should do the best practice now for any new features and we can fix up the rest when we can

func testAccAzureRMSubnet_basic_addressPrefixes(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = "acctestRG-%d"
name = "acctestRG-n-%d"

Updating for best practices

func testAccDataSourceArmVirtualNetwork_basic_addressPrefixes(data acceptance.TestData) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctest%d-rg"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = "acctest%d-rg"
name = "acctest%d-n-rg"

Updating for best practices

@@ -30,6 +30,28 @@ func TestAccDataSourceSubnet_basic(t *testing.T) {
})
}

func TestAccDataSourceAzureRMSubnet_basic_addressPrefixes(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test now passes!

@fabianofranz
Copy link
Contributor Author

@mbfrahry thanks for the review, all latest comments were addressed.

I am having issues getting the AllowMultipleAddressPrefixesOnSubnet feature for virtual networks registered

I'm facing exactly the same issue when trying to test it since yesterday, and I'm pretty sure it wasn't happening until a few days ago. Let's wait and see how your ticket goes. ;-)

So here goes another PR that splits this one. If we're good to go with the subnets part of this, let's have the other PR going and once it lands, I'll rebase this one to focus on the VNet and wait for a solution about the test issue. Tks!

@mbfrahry
Copy link
Member

Thanks for splitting this out @fabianofranz, I just heard back from support and they said that this feature isn't available for the public use yet and they aren't approving people to use it. I'll move this PR to our Blocked milestone until they release this feature to the public.

@mbfrahry mbfrahry added this to the Blocked milestone Apr 17, 2020
The azure subnet resource allows for multiple address prefixes using the
address_prefixes argument. The virtual network resource allows inline subnets,
but does not currently support this argument. When the address_prefixes argument
is used, address_prefix will be null when terraform refreshes its state causing
terraform to panic. This code updates the virtual network resource to allow
address_prefixes to be used and for address_prefix to be null.

Tests have been added to test the multiple prefixes. The magic number in the
new tests is the same magic number used in the other VNet tests. I'm not 100%
clear on this number, but it appears to be a known ID. It's origin is
documented (not very well) here:

#1913

This fix addresses several IPv6 related bugs.
@abhinavdahiya
Copy link
Contributor

Any updates on this @fabianofranz @mbfrahry

@mbfrahry
Copy link
Member

Closing this for now as it's not yet available for public use

@mbfrahry mbfrahry closed this Jul 10, 2020
@ghost
Copy link

ghost commented Aug 10, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks!

@hashicorp hashicorp locked and limited conversation to collaborators Aug 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Subnets with multiple addressPrefixes cannot be used as a source or created
4 participants