Skip to content

Commit

Permalink
Add support for CIDR in port forwarding source
Browse files Browse the repository at this point in the history
Fixes #40
  • Loading branch information
paultyng committed Sep 21, 2020
1 parent 4620d29 commit 6495dca
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/resources/port_forward.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ description: |-
- **name** (String, Optional) The name of the port forwarding rule.
- **port_forward_interface** (String, Optional) The port forwarding interface. Can be `wan`, `wan2`, or `both`.
- **protocol** (String, Optional) The protocol for the port forwarding rule. Can be `tcp`, `udp`, or `tcp_udp`. Defaults to `tcp_udp`.
- **src_ip** (String, Optional) The source IPv4 address of the port forwarding rule. For all traffic, specify `any`. Defaults to `any`.
- **src_ip** (String, Optional) The source IPv4 address (or CIDR) of the port forwarding rule. For all traffic, specify `any`. Defaults to `any`.


15 changes: 15 additions & 0 deletions internal/provider/cidr.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
package provider

import (
"fmt"
"net"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func cidrValidate(raw interface{}, key string) ([]string, []error) {
v, ok := raw.(string)
if !ok {
return nil, []error{fmt.Errorf("expected string, got %T", raw)}
}

_, _, err := net.ParseCIDR(v)
if err != nil {
return nil, []error{err}
}

return nil, nil
}

func cidrDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
_, oldNet, err := net.ParseCIDR(old)
if err != nil {
Expand Down
37 changes: 37 additions & 0 deletions internal/provider/cidr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package provider

import (
"testing"
)

func TestCIDRValidate(t *testing.T) {
for _, c := range []struct {
expectedError string
cidr string
}{
{"invalid CIDR address: ", ""},
{"invalid CIDR address: abc", "abc"},
{"invalid CIDR address: 192.1.2.3", "192.1.2.3"},
{"invalid CIDR address: 500.1.2.3/20", "500.1.2.3/20"},
{"invalid CIDR address: 192.1.2.3/500", "192.1.2.3/500"},

{"", "192.1.2.1/20"},
} {
t.Run(c.cidr, func(t *testing.T) {
_, actualErrs := cidrValidate(c.cidr, "key")
switch len(actualErrs) {
case 0:
if c.expectedError != "" {
t.Fatalf("expected no error, got %d: %#v", len(actualErrs), actualErrs)
}
case 1:
actualErr := actualErrs[0].Error()
if actualErr != c.expectedError {
t.Fatalf("expected %q, got %q", c.expectedError, actualErr)
}
default:
t.Fatalf("expected 0 or 1 errors, got %d: %#v", len(actualErrs), actualErrs)
}
})
}
}
1 change: 1 addition & 0 deletions internal/provider/resource_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func resourceNetwork() *schema.Resource {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: cidrDiffSuppress,
ValidateFunc: cidrValidate,
},
"network_group": {
Description: "The group of the network.",
Expand Down
3 changes: 2 additions & 1 deletion internal/provider/resource_port_forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,14 @@ func resourcePortForward() *schema.Resource {
ValidateFunc: validation.StringInSlice([]string{"tcp_udp", "tcp", "udp"}, false),
},
"src_ip": {
Description: "The source IPv4 address of the port forwarding rule. For all traffic, specify `any`.",
Description: "The source IPv4 address (or CIDR) of the port forwarding rule. For all traffic, specify `any`.",
Type: schema.TypeString,
Optional: true,
Default: "any",
ValidateFunc: validation.Any(
validation.StringInSlice([]string{"any"}, false),
validation.IsIPv4Address,
cidrValidate,
),
},
},
Expand Down
52 changes: 52 additions & 0 deletions internal/provider/resource_port_forward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,58 @@ func TestAccPortForward_basic(t *testing.T) {
resource.TestCheckResourceAttr("unifi_port_forward.test", "dst_port", "22"),
),
},
importStep("unifi_port_forward.test"),
{
Config: testAccPortForwardConfig("22", false, "10.1.1.2", "8022", "fwd name"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("unifi_port_forward.test", "fwd_port", "8022"),
resource.TestCheckResourceAttr("unifi_port_forward.test", "fwd_ip", "10.1.1.2"),
),
},
importStep("unifi_port_forward.test"),
{
Config: testAccPortForwardConfig("22", false, "10.1.1.1", "22", "fwd name 2"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("unifi_port_forward.test", "name", "fwd name 2"),
),
},
importStep("unifi_port_forward.test"),
},
})
}

func TestAccPortForward_src_ip(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
ProviderFactories: providerFactories,
// TODO: CheckDestroy: ,
Steps: []resource.TestStep{
{
Config: testAccPortForwardConfigSrc("22", false, "10.1.1.1", "22", "fwd name", "192.168.1.0"),
Check: resource.ComposeTestCheckFunc(
// testCheckNetworkExists(t, "name"),
resource.TestCheckResourceAttr("unifi_port_forward.test", "dst_port", "22"),
),
},
importStep("unifi_port_forward.test"),
},
})
}

func TestAccPortForward_src_cidr(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
ProviderFactories: providerFactories,
// TODO: CheckDestroy: ,
Steps: []resource.TestStep{
{
Config: testAccPortForwardConfigSrc("22", false, "10.1.1.1", "22", "fwd name", "192.168.1.0/20"),
Check: resource.ComposeTestCheckFunc(
// testCheckNetworkExists(t, "name"),
resource.TestCheckResourceAttr("unifi_port_forward.test", "dst_port", "22"),
),
},
importStep("unifi_port_forward.test"),
},
})
}
Expand All @@ -48,3 +87,16 @@ resource "unifi_port_forward" "test" {
}
`, dstPort, enabled, fwdIP, fwdPort, name)
}

func testAccPortForwardConfigSrc(dstPort string, enabled bool, fwdIP, fwdPort, name, src string) string {
return fmt.Sprintf(`
resource "unifi_port_forward" "test" {
dst_port = %q
enabled = %t
fwd_ip = %q
fwd_port = %q
name = %q
src_ip = %q
}
`, dstPort, enabled, fwdIP, fwdPort, name, src)
}

0 comments on commit 6495dca

Please sign in to comment.