From 513fd298655517f9ac651de447934bd82b68df5b Mon Sep 17 00:00:00 2001 From: Wojciech Dubiel Date: Sun, 21 Mar 2021 16:37:58 -0400 Subject: [PATCH] Implement static WAN configuration in unifi_network --- docs/resources/network.md | 5 +- internal/provider/resource_network.go | 79 +++++++++++++++++----- internal/provider/resource_network_test.go | 22 ++++-- 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/docs/resources/network.md b/docs/resources/network.md index ce706b1..c3cceff 100644 --- a/docs/resources/network.md +++ b/docs/resources/network.md @@ -67,10 +67,11 @@ resource "unifi_network" "wan" { - **site** (String) The name of the site to associate the network with. - **subnet** (String) The subnet of the network. Must be a valid CIDR address. - **vlan_id** (Number) The VLAN ID of the network. -- **wan_dns1** (String) Primary DNS server for the WAN. -- **wan_dns2** (String) Secondary DNS server for the WAN. +- **wan_dns** (List of String) DNS servers IPs of the WAN. - **wan_egress_qos** (Number) Specifies the WAN egress quality of service. Defaults to `0`. +- **wan_gateway** (String) The IPv4 gateway of the WAN. - **wan_ip** (String) The IPv4 address of the WAN. +- **wan_netmask** (String) The IPv4 netmask of the WAN. - **wan_networkgroup** (String) Specifies the WAN network group. Must be one of either `WAN`, `WAN2` or `WAN_LTE_FAILOVER`. - **wan_type** (String) Specifies the IPV4 WAN connection type. Must be one of either `disabled`, `static`, `dhcp`, or `pppoe`. - **wan_username** (String) Specifies the IPV4 WAN username. diff --git a/internal/provider/resource_network.go b/internal/provider/resource_network.go index 55ed680..496011e 100644 --- a/internal/provider/resource_network.go +++ b/internal/provider/resource_network.go @@ -160,6 +160,28 @@ func resourceNetwork() *schema.Resource { Optional: true, ValidateFunc: validation.IsIPv4Address, }, + "wan_netmask": { + Description: "The IPv4 netmask of the WAN.", + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.IsIPv4Address, + }, + "wan_gateway": { + Description: "The IPv4 gateway of the WAN.", + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.IsIPv4Address, + }, + "wan_dns": { + Description: "DNS servers IPs of the WAN.", + Type: schema.TypeList, + Optional: true, + MaxItems: 4, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.IsIPv4Address, + }, + }, "wan_type": { Description: "Specifies the IPV4 WAN connection type. Must be one of either `disabled`, `static`, `dhcp`, or `pppoe`.", Type: schema.TypeString, @@ -190,18 +212,6 @@ func resourceNetwork() *schema.Resource { Optional: true, ValidateFunc: validateWANPassword, }, - "wan_dns1": { - Description: "Primary DNS server for the WAN.", - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsIPv4Address, - }, - "wan_dns2": { - Description: "Secondary DNS server for the WAN.", - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.IsIPv4Address, - }, }, } } @@ -235,6 +245,10 @@ func resourceNetworkGetResourceData(d *schema.ResourceData) (*unifi.Network, err if err != nil { return nil, fmt.Errorf("unable to convert dhcp_dns to string slice: %w", err) } + wanDNS, err := listToStringSlice(d.Get("wan_dns").([]interface{})) + if err != nil { + return nil, fmt.Errorf("unable to convert wan_dns to string slice: %w", err) + } return &unifi.Network{ Name: d.Get("name").(string), @@ -268,19 +282,49 @@ func resourceNetworkGetResourceData(d *schema.ResourceData) (*unifi.Network, err WANIP: d.Get("wan_ip").(string), WANType: d.Get("wan_type").(string), + WANNetmask: d.Get("wan_netmask").(string), + WANGateway: d.Get("wan_gateway").(string), WANNetworkGroup: d.Get("wan_networkgroup").(string), WANEgressQOS: d.Get("wan_egress_qos").(int), WANUsername: d.Get("wan_username").(string), XWANPassword: d.Get("x_wan_password").(string), - WANDNS1: d.Get("wan_dns1").(string), - WANDNS2: d.Get("wan_dns2").(string), + + // this is kinda hacky but ¯\_(ツ)_/¯ + WANDNS1: append(wanDNS, "")[0], + WANDNS2: append(wanDNS, "", "")[1], + WANDNS3: append(wanDNS, "", "", "")[2], + WANDNS4: append(wanDNS, "", "", "", "")[3], }, nil } func resourceNetworkSetResourceData(resp *unifi.Network, d *schema.ResourceData, site string) error { wanType := "" + wanDNS := []string{} + wanIP := "" + wanNetmask := "" + wanGateway := "" + if resp.Purpose == "wan" { wanType = resp.WANType + + for _, dns := range []string{ + resp.WANDNS1, + resp.WANDNS2, + resp.WANDNS3, + resp.WANDNS4, + } { + if dns == "" { + continue + } + wanDNS = append(wanDNS, dns) + } + + if wanType != "dhcp" { + wanIP = resp.WANIP + wanNetmask = resp.WANNetmask + wanGateway = resp.WANGateway + } + // TODO: set other wan only fields here? } @@ -327,14 +371,15 @@ func resourceNetworkSetResourceData(resp *unifi.Network, d *schema.ResourceData, d.Set("ipv6_pd_interface", resp.IPV6PDInterface) d.Set("ipv6_pd_prefixid", resp.IPV6PDPrefixid) d.Set("ipv6_ra_enable", resp.IPV6RaEnabled) - d.Set("wan_ip", resp.WANIP) + d.Set("wan_ip", wanIP) + d.Set("wan_netmask", wanNetmask) + d.Set("wan_gateway", wanGateway) d.Set("wan_type", wanType) + d.Set("wan_dns", wanDNS) d.Set("wan_networkgroup", resp.WANNetworkGroup) d.Set("wan_egress_qos", resp.WANEgressQOS) d.Set("wan_username", resp.WANUsername) d.Set("x_wan_password", resp.XWANPassword) - d.Set("wan_dns1", resp.WANDNS1) - d.Set("wan_dns2", resp.WANDNS2) return nil } diff --git a/internal/provider/resource_network_test.go b/internal/provider/resource_network_test.go index 7de7ae2..ba04444 100644 --- a/internal/provider/resource_network_test.go +++ b/internal/provider/resource_network_test.go @@ -149,8 +149,9 @@ func TestAccNetwork_wan(t *testing.T) { resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_egress_qos", "1"), resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_username", "username"), resource.TestCheckResourceAttr("unifi_network.wan_test", "x_wan_password", "password"), - resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_dns1", "8.8.8.8"), - resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_dns2", "4.4.4.4"), + + resource.TestCheckOutput("wan_dns1", "8.8.8.8"), + resource.TestCheckOutput("wan_dns2", "4.4.4.4"), ), }, importStep("unifi_network.wan_test"), @@ -163,8 +164,9 @@ func TestAccNetwork_wan(t *testing.T) { resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_egress_qos", "1"), resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_username", "username"), resource.TestCheckResourceAttr("unifi_network.wan_test", "x_wan_password", "password"), - resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_dns1", "8.8.8.8"), - resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_dns2", "4.4.4.4"), + + resource.TestCheckOutput("wan_dns1", "8.8.8.8"), + resource.TestCheckOutput("wan_dns2", "4.4.4.4"), ), }, importStep("unifi_network.wan_test"), @@ -323,8 +325,16 @@ resource "unifi_network" "wan_test" { wan_egress_qos = %d wan_username = "%s" x_wan_password = "%s" - wan_dns1 = "%s" - wan_dns2 = "%s" + + wan_dns = ["%s", "%s"] +} + +output "wan_dns1" { + value = unifi_network.wan_test.wan_dns[0] +} + +output "wan_dns2" { + value = unifi_network.wan_test.wan_dns[1] } `, networkGroup, wanType, wanIP, wanEgressQOS, wanUsername, wanPassword, wanDNS1, wanDNS2) }