Skip to content

Commit

Permalink
Feature: Add 'ip_version' to Public IP Address
Browse files Browse the repository at this point in the history
  • Loading branch information
Krueladin committed Oct 4, 2018
1 parent 040b71f commit b2fbe78
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 1 deletion.
26 changes: 25 additions & 1 deletion azurerm/helpers/validate/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ import (
"net"
)

func IPv6Address(i interface{}, k string) (_ []string, errors []error) {
return validateIpv6Address(i, k, false)
}

func validateIpv6Address(i interface{}, k string, allowEmpty bool) (_ []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

if v == "" && allowEmpty {
return
}

ip := net.ParseIP(v)
if six := ip.To16(); six == nil {
errors = append(errors, fmt.Errorf("%q is not a valid IPv6 address: %q", k, v))
}

return

}

func IPv4Address(i interface{}, k string) (_ []string, errors []error) {
return validateIpv4Address(i, k, false)
}
Expand All @@ -26,7 +50,7 @@ func validateIpv4Address(i interface{}, k string, allowEmpty bool) (_ []string,

ip := net.ParseIP(v)
if four := ip.To4(); four == nil {
errors = append(errors, fmt.Errorf("%q is not a valid IP4 address: %q", k, v))
errors = append(errors, fmt.Errorf("%q is not a valid IPv4 address: %q", k, v))
}

return
Expand Down
51 changes: 51 additions & 0 deletions azurerm/helpers/validate/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,57 @@ import (
"testing"
)

func TestIPv6Address(t *testing.T) {
cases := []struct {
IP string
Errors int
}{
{
IP: "",
Errors: 1,
},
{
IP: "0.0.0.0",
Errors: 0,
},
{
IP: "not:a:real:address:1:2:3:4",
Errors: 1,
},
{
IP: "text",
Errors: 1,
},
{
IP: "::",
Errors: 0,
},
{
IP: "0:0:0:0:0:0:0:0",
Errors: 0,
},
{
IP: "2001:0db8:85a3:0:0:8a2e:0370:7334",
Errors: 0,
},
{
IP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
Errors: 0,
},
}

for _, tc := range cases {
t.Run(tc.IP, func(t *testing.T) {
_, errors := IPv6Address(tc.IP, "test")

if len(errors) != tc.Errors {
t.Fatalf("Expected IPv6Address to return %d error(s) not %d", tc.Errors, len(errors))
}
})
}

}

func TestIPv4Address(t *testing.T) {
cases := []struct {
IP string
Expand Down
23 changes: 23 additions & 0 deletions azurerm/resource_arm_public_ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ func resourceArmPublicIp() *schema.Resource {
}, true),
},

"ip_version": {
Type: schema.TypeString,
Optional: true,
Default: string(network.IPv4),
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
string(network.IPv4),
string(network.IPv6),
}, true),
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
StateFunc: ignoreCaseStateFunc,
},

"sku": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -122,6 +135,13 @@ func resourceArmPublicIpCreate(d *schema.ResourceData, meta interface{}) error {

idleTimeout := d.Get("idle_timeout_in_minutes").(int)
ipAllocationMethod := network.IPAllocationMethod(d.Get("public_ip_address_allocation").(string))
ipVersion := network.IPVersion(d.Get("ip_version").(string))

if strings.ToLower(string(ipVersion)) == "ipv6" {
if strings.ToLower(string(ipAllocationMethod)) == "static" {
return fmt.Errorf("Cannot specify publicIpAllocationMethod as Static for IPv6 PublicIp")
}
}

if strings.ToLower(string(sku.Name)) == "standard" {
if strings.ToLower(string(ipAllocationMethod)) != "static" {
Expand All @@ -135,6 +155,7 @@ func resourceArmPublicIpCreate(d *schema.ResourceData, meta interface{}) error {
Sku: &sku,
PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
PublicIPAllocationMethod: ipAllocationMethod,
PublicIPAddressVersion: ipVersion,
IdleTimeoutInMinutes: utils.Int32(int32(idleTimeout)),
},
Tags: expandTags(tags),
Expand Down Expand Up @@ -209,6 +230,7 @@ func resourceArmPublicIpRead(d *schema.ResourceData, meta interface{}) error {
if location := resp.Location; location != nil {
d.Set("location", azureRMNormalizeLocation(*location))
}
d.Set("ip_version", strings.ToLower(string(resp.PublicIPAddressPropertiesFormat.PublicIPAddressVersion)))

d.Set("public_ip_address_allocation", strings.ToLower(string(resp.PublicIPAddressPropertiesFormat.PublicIPAllocationMethod)))

Expand All @@ -218,6 +240,7 @@ func resourceArmPublicIpRead(d *schema.ResourceData, meta interface{}) error {

if props := resp.PublicIPAddressPropertiesFormat; props != nil {
d.Set("public_ip_address_allocation", strings.ToLower(string(props.PublicIPAllocationMethod)))
d.Set("ip_version", strings.ToLower(string(props.PublicIPAddressVersion)))

if settings := props.DNSSettings; settings != nil {
d.Set("fqdn", settings.Fqdn)
Expand Down
152 changes: 152 additions & 0 deletions azurerm/resource_arm_public_ip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,104 @@ func TestAccAzureRMPublicIpStatic_basic_withDNSLabel(t *testing.T) {
})
}

func TestAccAzureRMPublicIpStatic_standard_withIPv6_fails(t *testing.T) {
ri := acctest.RandInt()
ipVersion := "IPV6"
config := testAccAzureRMPublicIPStatic_standard_withIPVersion(ri, testLocation(), ipVersion)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPublicIpDestroy,
Steps: []resource.TestStep{
{
Config: config,
ExpectError: regexp.MustCompile("Cannot specify publicIpAllocationMethod as Static for IPv6 PublicIp"),
},
},
})
}

func TestAccAzureRMPublicIpDynamic_basic_withIPv6(t *testing.T) {
resourceName := "azurerm_public_ip.test"
ri := acctest.RandInt()
ipVersion := "Ipv6"
config := testAccAzureRMPublicIPDynamic_basic_withIPVersion(ri, testLocation(), ipVersion)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPublicIpDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMPublicIpExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "ip_version", "ipv6"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})

}

func TestAccAzureRMPublicIpStatic_basic_defaultsToIPv4(t *testing.T) {
resourceName := "azurerm_public_ip.test"
ri := acctest.RandInt()
config := testAccAzureRMPublicIPStatic_basic(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPublicIpDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMPublicIpExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "ip_version", "ipv4"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccAzureRMPublicIpStatic_basic_withIPv4(t *testing.T) {
resourceName := "azurerm_public_ip.test"
ri := acctest.RandInt()
ipVersion := "IPv4"
config := testAccAzureRMPublicIPStatic_basic_withIPVersion(ri, testLocation(), ipVersion)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPublicIpDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMPublicIpExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "ip_version", "ipv4"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMPublicIpStatic_standard(t *testing.T) {
resourceName := "azurerm_public_ip.test"
ri := acctest.RandInt()
Expand Down Expand Up @@ -428,6 +526,24 @@ resource "azurerm_public_ip" "test" {
`, rInt, location, rInt, dnsNameLabel)
}

func testAccAzureRMPublicIPStatic_basic_withIPVersion(rInt int, location string, ipVersion string) string {
return fmt.Sprintf(`
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}"
public_ip_address_allocation = "static"
ip_version = "%s"
}
`, rInt, location, rInt, ipVersion)
}

func testAccAzureRMPublicIPStatic_standard(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand All @@ -445,6 +561,24 @@ resource "azurerm_public_ip" "test" {
`, rInt, location, rInt)
}

func testAccAzureRMPublicIPStatic_standard_withIPVersion(rInt int, location string, ipVersion string) string {
return fmt.Sprintf(`
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}"
public_ip_address_allocation = "static"
ip_version = "%s"
sku = "standard"
}
`, rInt, location, rInt, ipVersion)
}

func testAccAzureRMPublicIPStatic_update(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down Expand Up @@ -495,6 +629,24 @@ resource "azurerm_public_ip" "test" {
`, rInt, location, rInt)
}

func testAccAzureRMPublicIPDynamic_basic_withIPVersion(rInt int, location string, ipVersion string) string {
return fmt.Sprintf(`
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}"
public_ip_address_allocation = "dynamic"
ip_version = "%s"
}
`, rInt, location, rInt, ipVersion)
}

func testAccAzureRMPublicIPStatic_withTags(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down

0 comments on commit b2fbe78

Please sign in to comment.