Add missing IPv6 properties (#261)

* Add missing WAN IPv6 properties to network resource

* Rename 'ipv6_static_subnet' to 'ipv6_subnet'

According to the go-unifi lib, the name was incorrect

* Improve description and validation of IPv6 properties

* Add missing IPv6 props to network

* Add IPv6 support to firewall rules

* Adjust naming

* ensure unique vlan

* Add vlan ID validation

* fix assertion

* Update docs

* rename attribute

* cleanup imports

* test protocol_v6

* test dhcp_v6_lease

* spelling

* switch protocol back

Co-authored-by: Paul Tyng <paul@paultyng.net>
This commit is contained in:
Andreas Harter
2022-10-22 18:56:56 +02:00
committed by GitHub
parent 7238aa36e5
commit 0604e1deaf
22 changed files with 551 additions and 73 deletions

View File

@@ -43,27 +43,43 @@ data "unifi_network" "my_network" {
- `dhcp_lease` (Number) lease time for DHCP addresses.
- `dhcp_start` (String) The IPv4 address where the DHCP range of addresses starts.
- `dhcp_stop` (String) The IPv4 address where the DHCP range of addresses stops.
- `dhcp_v6_dns` (List of String) Specifies the IPv6 addresses for the DNS server to be returned from the DHCP server. Used if `dhcp_v6_dns_auto` is set to `false`.
- `dhcp_v6_dns_auto` (Boolean) Specifies DNS source to propagate. If set `false` the entries in `dhcp_v6_dns` are used, the upstream entries otherwise
- `dhcp_v6_enabled` (Boolean) Enable stateful DHCPv6 for static configuration.
- `dhcp_v6_lease` (Number) Specifies the lease time for DHCPv6 addresses.
- `dhcp_v6_start` (String) Start address of the DHCPv6 range. Used in static DHCPv6 configuration.
- `dhcp_v6_stop` (String) End address of the DHCPv6 range. Used in static DHCPv6 configuration.
- `dhcpd_boot_enabled` (Boolean) Toggles on the DHCP boot options. will be set to true if you have dhcpd_boot_filename, and dhcpd_boot_server set.
- `dhcpd_boot_filename` (String) the file to PXE boot from on the dhcpd_boot_server.
- `dhcpd_boot_server` (String) IPv4 address of a TFTP server to network boot from.
- `domain_name` (String) The domain name of this network.
- `igmp_snooping` (Boolean) Specifies whether IGMP snooping is enabled or not.
- `ipv6_interface_type` (String) Specifies which type of IPv6 connection to use.
- `ipv6_pd_interface` (String) Specifies which WAN interface is used for IPv6 Prefix Delegation.
- `ipv6_interface_type` (String) Specifies which type of IPv6 connection to use. Must be one of either `static`, `pd`, or `none`.
- `ipv6_pd_interface` (String) Specifies which WAN interface to use for IPv6 PD. Must be one of either `wan` or `wan2`.
- `ipv6_pd_prefixid` (String) Specifies the IPv6 Prefix ID.
- `ipv6_pd_start` (String) Start address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.
- `ipv6_pd_stop` (String) End address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.
- `ipv6_ra_enable` (Boolean) Specifies whether to enable router advertisements or not.
- `ipv6_ra_preferred_lifetime` (Number) Lifetime in which the address can be used. Address becomes deprecated afterwards. Must be lower than or equal to `ipv6_ra_valid_lifetime`
- `ipv6_ra_priority` (String) IPv6 router advertisement priority. Must be one of either `high`, `medium`, or `low`
- `ipv6_ra_valid_lifetime` (Number) Total lifetime in which the address can be used. Must be equal to or greater than `ipv6_ra_preferred_lifetime`.
- `ipv6_static_subnet` (String) Specifies the static IPv6 subnet (when ipv6_interface_type is 'static').
- `network_group` (String) The group of the network.
- `purpose` (String) The purpose of the network. One of `corporate`, `guest`, `wan`, or `vlan-only`.
- `subnet` (String) The subnet of the network (CIDR address).
- `vlan_id` (Number) The VLAN ID of the network.
- `wan_dhcp_v6_pd_size` (Number) Specifies the IPv6 prefix size to request from ISP. Must be a number between 48 and 64.
- `wan_dns` (List of String) DNS servers IPs of the WAN.
- `wan_egress_qos` (Number) Specifies the WAN egress quality of service.
- `wan_gateway` (String) The IPv4 gateway of the WAN.
- `wan_gateway_v6` (String) The IPv6 gateway of the WAN.
- `wan_ip` (String) The IPv4 address of the WAN.
- `wan_ipv6` (String) The IPv6 address of the WAN.
- `wan_netmask` (String) The IPv4 netmask of the WAN.
- `wan_networkgroup` (String) Specifies the WAN network group. One of either `WAN`, `WAN2` or `WAN_LTE_FAILOVER`.
- `wan_prefixlen` (Number) The IPv6 prefix length of the WAN. Must be between 1 and 128.
- `wan_type` (String) Specifies the IPV4 WAN connection type. One of either `disabled`, `static`, `dhcp`, or `pppoe`.
- `wan_type_v6` (String) Specifies the IPV6 WAN connection type. Must be one of either `disabled`, `static`, or `dhcpv6`.
- `wan_username` (String) Specifies the IPV4 WAN username.
- `x_wan_password` (String) Specifies the IPV4 WAN password.

View File

@@ -37,22 +37,26 @@ resource "unifi_firewall_rule" "drop_all" {
- `action` (String) The action of the firewall rule. Must be one of `drop`, `accept`, or `reject`.
- `name` (String) The name of the firewall rule.
- `protocol` (String) The protocol of the rule.
- `rule_index` (Number) The index of the rule. Must be >= 2000 < 3000 or >= 4000 < 5000.
- `ruleset` (String) The ruleset for the rule. This is from the perspective of the security gateway. Must be one of `WAN_IN`, `WAN_OUT`, `WAN_LOCAL`, `LAN_IN`, `LAN_OUT`, `LAN_LOCAL`, `GUEST_IN`, `GUEST_OUT`, `GUEST_LOCAL`, `WANv6_IN`, `WANv6_OUT`, `WANv6_LOCAL`, `LANv6_IN`, `LANv6_OUT`, `LANv6_LOCAL`, `GUESTv6_IN`, `GUESTv6_OUT`, or `GUESTv6_LOCAL`.
### Optional
- `dst_address` (String) The destination address of the firewall rule.
- `dst_address_ipv6` (String) The IPv6 destination address of the firewall rule.
- `dst_firewall_group_ids` (Set of String) The destination firewall group IDs of the firewall rule.
- `dst_network_id` (String) The destination network ID of the firewall rule.
- `dst_network_type` (String) The destination network type of the firewall rule. Can be one of `ADDRv4` or `NETv4`. Defaults to `NETv4`.
- `dst_port` (String) The destination port of the firewall rule.
- `icmp_typename` (String) ICMP type name.
- `icmp_v6_typename` (String) ICMPv6 type name.
- `ip_sec` (String) Specify whether the rule matches on IPsec packets. Can be one of `match-ipset` or `match-none`.
- `logging` (Boolean) Enable logging for the firewall rule.
- `protocol` (String) The protocol of the rule.
- `protocol_v6` (String) The IPv6 protocol of the rule.
- `site` (String) The name of the site to associate the firewall rule with.
- `src_address` (String) The source address for the firewall rule.
- `src_address_ipv6` (String) The IPv6 source address for the firewall rule.
- `src_firewall_group_ids` (Set of String) The source firewall group IDs for the firewall rule.
- `src_mac` (String) The source MAC address of the firewall rule.
- `src_network_id` (String) The source network ID for the firewall rule.

View File

@@ -57,6 +57,12 @@ resource "unifi_network" "wan" {
- `dhcp_relay_enabled` (Boolean) Specifies whether DHCP relay is enabled or not on this network.
- `dhcp_start` (String) The IPv4 address where the DHCP range of addresses starts.
- `dhcp_stop` (String) The IPv4 address where the DHCP range of addresses stops.
- `dhcp_v6_dns` (List of String) Specifies the IPv6 addresses for the DNS server to be returned from the DHCP server. Used if `dhcp_v6_dns_auto` is set to `false`.
- `dhcp_v6_dns_auto` (Boolean) Specifies DNS source to propagate. If set `false` the entries in `dhcp_v6_dns` are used, the upstream entries otherwise Defaults to `true`.
- `dhcp_v6_enabled` (Boolean) Enable stateful DHCPv6 for static configuration.
- `dhcp_v6_lease` (Number) Specifies the lease time for DHCPv6 addresses. Defaults to `86400`.
- `dhcp_v6_start` (String) Start address of the DHCPv6 range. Used in static DHCPv6 configuration.
- `dhcp_v6_stop` (String) End address of the DHCPv6 range. Used in static DHCPv6 configuration.
- `dhcpd_boot_enabled` (Boolean) Toggles on the DHCP boot options. Should be set to true when you want to have dhcpd_boot_filename, and dhcpd_boot_server to take effect.
- `dhcpd_boot_filename` (String) Specifies the file to PXE boot from on the dhcpd_boot_server.
- `dhcpd_boot_server` (String) Specifies the IPv4 address of a TFTP server to network boot from.
@@ -64,22 +70,32 @@ resource "unifi_network" "wan" {
- `igmp_snooping` (Boolean) Specifies whether IGMP snooping is enabled or not.
- `internet_access_enabled` (Boolean) Specifies whether this network should be allowed to access the internet or not. Defaults to `true`.
- `intra_network_access_enabled` (Boolean) Specifies whether this network should be allowed to access other local networks or not. Defaults to `true`.
- `ipv6_interface_type` (String) Specifies which type of IPv6 connection to use. Defaults to `none`.
- `ipv6_pd_interface` (String) Specifies which WAN interface to use for IPv6 PD.
- `ipv6_interface_type` (String) Specifies which type of IPv6 connection to use. Must be one of either `static`, `pd`, or `none`. Defaults to `none`.
- `ipv6_pd_interface` (String) Specifies which WAN interface to use for IPv6 PD. Must be one of either `wan` or `wan2`.
- `ipv6_pd_prefixid` (String) Specifies the IPv6 Prefix ID.
- `ipv6_pd_start` (String) Start address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.
- `ipv6_pd_stop` (String) End address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.
- `ipv6_ra_enable` (Boolean) Specifies whether to enable router advertisements or not.
- `ipv6_static_subnet` (String) Specifies the static IPv6 subnet when ipv6_interface_type is 'static'.
- `ipv6_ra_preferred_lifetime` (Number) Lifetime in which the address can be used. Address becomes deprecated afterwards. Must be lower than or equal to `ipv6_ra_valid_lifetime` Defaults to `14400`.
- `ipv6_ra_priority` (String) IPv6 router advertisement priority. Must be one of either `high`, `medium`, or `low`
- `ipv6_ra_valid_lifetime` (Number) Total lifetime in which the adress can be used. Must be equal to or greater than `ipv6_ra_preferred_lifetime`. Defaults to `86400`.
- `ipv6_static_subnet` (String) Specifies the static IPv6 subnet when `ipv6_interface_type` is 'static'.
- `network_group` (String) The group of the network. Defaults to `LAN`.
- `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_dhcp_v6_pd_size` (Number) Specifies the IPv6 prefix size to request from ISP. Must be between 48 and 64.
- `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_gateway_v6` (String) The IPv6 gateway of the WAN.
- `wan_ip` (String) The IPv4 address of the WAN.
- `wan_ipv6` (String) The IPv6 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_prefixlen` (Number) The IPv6 prefix length of the WAN. Must be between 1 and 128.
- `wan_type` (String) Specifies the IPV4 WAN connection type. Must be one of either `disabled`, `static`, `dhcp`, or `pppoe`.
- `wan_type_v6` (String) Specifies the IPV6 WAN connection type. Must be one of either `disabled`, `static`, or `dhcpv6`.
- `wan_username` (String) Specifies the IPV4 WAN username.
- `x_wan_password` (String) Specifies the IPV4 WAN password.

View File

@@ -102,6 +102,40 @@ func dataNetwork() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"dhcp_v6_dns": {
Description: "Specifies the IPv6 addresses for the DNS server to be returned from the DHCP " +
"server. Used if `dhcp_v6_dns_auto` is set to `false`.",
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"dhcp_v6_dns_auto": {
Description: "Specifies DNS source to propagate. If set `false` the entries in `dhcp_v6_dns` are used, the upstream entries otherwise",
Type: schema.TypeBool,
Computed: true,
},
"dhcp_v6_enabled": {
Description: "Enable stateful DHCPv6 for static configuration.",
Type: schema.TypeBool,
Computed: true,
},
"dhcp_v6_lease": {
Description: "Specifies the lease time for DHCPv6 addresses.",
Type: schema.TypeInt,
Computed: true,
},
"dhcp_v6_start": {
Description: "Start address of the DHCPv6 range. Used in static DHCPv6 configuration.",
Type: schema.TypeString,
Computed: true,
},
"dhcp_v6_stop": {
Description: "End address of the DHCPv6 range. Used in static DHCPv6 configuration.",
Type: schema.TypeString,
Computed: true,
},
"domain_name": {
Description: "The domain name of this network.",
Type: schema.TypeString,
@@ -113,7 +147,7 @@ func dataNetwork() *schema.Resource {
Computed: true,
},
"ipv6_interface_type": {
Description: "Specifies which type of IPv6 connection to use.",
Description: "Specifies which type of IPv6 connection to use. Must be one of either `static`, `pd`, or `none`.",
Type: schema.TypeString,
Computed: true,
},
@@ -123,7 +157,7 @@ func dataNetwork() *schema.Resource {
Computed: true,
},
"ipv6_pd_interface": {
Description: "Specifies which WAN interface is used for IPv6 Prefix Delegation.",
Description: "Specifies which WAN interface to use for IPv6 PD. Must be one of either `wan` or `wan2`.",
Type: schema.TypeString,
Computed: true,
},
@@ -132,11 +166,36 @@ func dataNetwork() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"ipv6_pd_start": {
Description: "Start address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.",
Type: schema.TypeString,
Computed: true,
},
"ipv6_pd_stop": {
Description: "End address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.",
Type: schema.TypeString,
Computed: true,
},
"ipv6_ra_enable": {
Description: "Specifies whether to enable router advertisements or not.",
Type: schema.TypeBool,
Computed: true,
},
"ipv6_ra_preferred_lifetime": {
Description: "Lifetime in which the address can be used. Address becomes deprecated afterwards. Must be lower than or equal to `ipv6_ra_valid_lifetime`",
Type: schema.TypeInt,
Computed: true,
},
"ipv6_ra_priority": {
Description: "IPv6 router advertisement priority. Must be one of either `high`, `medium`, or `low`",
Type: schema.TypeString,
Computed: true,
},
"ipv6_ra_valid_lifetime": {
Description: "Total lifetime in which the address can be used. Must be equal to or greater than `ipv6_ra_preferred_lifetime`.",
Type: schema.TypeInt,
Computed: true,
},
"wan_ip": {
Description: "The IPv4 address of the WAN.",
Type: schema.TypeString,
@@ -185,6 +244,31 @@ func dataNetwork() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"wan_type_v6": {
Description: "Specifies the IPV6 WAN connection type. Must be one of either `disabled`, `static`, or `dhcpv6`.",
Type: schema.TypeString,
Computed: true,
},
"wan_dhcp_v6_pd_size": {
Description: "Specifies the IPv6 prefix size to request from ISP. Must be a number between 48 and 64.",
Type: schema.TypeInt,
Computed: true,
},
"wan_ipv6": {
Description: "The IPv6 address of the WAN.",
Type: schema.TypeString,
Computed: true,
},
"wan_gateway_v6": {
Description: "The IPv6 gateway of the WAN.",
Type: schema.TypeString,
Computed: true,
},
"wan_prefixlen": {
Description: "The IPv6 prefix length of the WAN. Must be between 1 and 128.",
Type: schema.TypeInt,
Computed: true,
},
},
}
}
@@ -264,6 +348,11 @@ func dataNetworkRead(ctx context.Context, d *schema.ResourceData, meta interface
d.Set("wan_egress_qos", n.WANEgressQOS)
d.Set("wan_username", n.WANUsername)
d.Set("x_wan_password", n.XWANPassword)
d.Set("wan_type_v6", n.WANTypeV6)
d.Set("wan_dhcp_v6_pd_size", n.WANDHCPv6PDSize)
d.Set("wan_ipv6", n.WANIPV6)
d.Set("wan_gateway_v6", n.WANGatewayV6)
d.Set("wan_prefixlen", n.WANPrefixlen)
return nil
}

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

View File

@@ -3,10 +3,10 @@ package provider
import (
"context"
"fmt"
"github.com/paultyng/go-unifi/unifi"
"testing"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/paultyng/go-unifi/unifi"
)
func TestAccDataUser_default(t *testing.T) {

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/paultyng/go-unifi/unifi"
)

View File

@@ -3,8 +3,8 @@ package provider
import (
"context"
"errors"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"

View File

@@ -3,15 +3,17 @@ package provider
import (
"context"
"errors"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"regexp"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"
)
var firewallRuleProtocolRegexp = regexp.MustCompile("^$|all|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|tcp_udp|ah|ax.25|dccp|ddp|egp|eigrp|encap|esp|etherip|fc|ggp|gre|hip|hmp|icmp|idpr-cmtp|idrp|igmp|igp|ip|ipcomp|ipencap|ipip|ipv6|ipv6-frag|ipv6-icmp|ipv6-nonxt|ipv6-opts|ipv6-route|isis|iso-tp4|l2tp|manet|mobility-header|mpls-in-ip|ospf|pim|pup|rdp|rohc|rspf|rsvp|sctp|shim6|skip|st|tcp|udp|udplite|vmtp|vrrp|wesp|xns-idp|xtp")
var firewallRuleProtocolV6Regexp = regexp.MustCompile("^$|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|ah|all|dccp|eigrp|esp|gre|icmpv6|ipcomp|ipv6|ipv6-frag|ipv6-icmp|ipv6-nonxt|ipv6-opts|ipv6-route|isis|l2tp|manet|mobility-header|mpls-in-ip|ospf|pim|rsvp|sctp|shim6|tcp|tcp_udp|udp|vrrp")
var firewallRuleICMPv6TypenameRegexp = regexp.MustCompile("^$|address-unreachable|bad-header|beyond-scope|communication-prohibited|destination-unreachable|echo-reply|echo-request|failed-policy|neighbor-advertisement|neighbor-solicitation|no-route|packet-too-big|parameter-problem|port-unreachable|redirect|reject-route|router-advertisement|router-solicitation|time-exceeded|ttl-zero-during-reassembly|ttl-zero-during-transit|unknown-header-type|unknown-option")
func resourceFirewallRule() *schema.Resource {
return &schema.Resource{
@@ -67,14 +69,26 @@ func resourceFirewallRule() *schema.Resource {
"protocol": {
Description: "The protocol of the rule.",
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringMatch(firewallRuleProtocolRegexp, "must be a valid protocol"),
Optional: true,
ValidateFunc: validation.StringMatch(firewallRuleProtocolRegexp, "must be a valid IPv4 protocol"),
},
"protocol_v6": {
Description: "The IPv6 protocol of the rule.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringMatch(firewallRuleProtocolV6Regexp, "must be a valid IPv6 protocol"),
},
"icmp_typename": {
Description: "ICMP type name.",
Type: schema.TypeString,
Optional: true,
},
"icmp_v6_typename": {
Description: "ICMPv6 type name.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringMatch(firewallRuleICMPv6TypenameRegexp, "must be a ICMPv6 type"),
},
// sources
"src_network_id": {
@@ -100,6 +114,11 @@ func resourceFirewallRule() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"src_address_ipv6": {
Description: "The IPv6 source address for the firewall rule.",
Type: schema.TypeString,
Optional: true,
},
"src_mac": {
Description: "The source MAC address of the firewall rule.",
Type: schema.TypeString,
@@ -130,6 +149,11 @@ func resourceFirewallRule() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"dst_address_ipv6": {
Description: "The IPv6 destination address of the firewall rule.",
Type: schema.TypeString,
Optional: true,
},
"dst_port": {
Description: "The destination port of the firewall rule.",
Type: schema.TypeString,
@@ -219,7 +243,9 @@ func resourceFirewallRuleGetResourceData(d *schema.ResourceData) (*unifi.Firewal
Ruleset: d.Get("ruleset").(string),
RuleIndex: d.Get("rule_index").(int),
Protocol: d.Get("protocol").(string),
ProtocolV6: d.Get("protocol_v6").(string),
ICMPTypename: d.Get("icmp_typename").(string),
ICMPv6Typename: d.Get("icmp_v6_typename").(string),
Logging: d.Get("logging").(bool),
IPSec: d.Get("ip_sec").(string),
StateEstablished: d.Get("state_established").(bool),
@@ -230,11 +256,13 @@ func resourceFirewallRuleGetResourceData(d *schema.ResourceData) (*unifi.Firewal
SrcNetworkType: d.Get("src_network_type").(string),
SrcMACAddress: d.Get("src_mac").(string),
SrcAddress: d.Get("src_address").(string),
SrcAddressIPV6: d.Get("src_address_ipv6").(string),
SrcNetworkID: d.Get("src_network_id").(string),
SrcFirewallGroupIDs: srcFirewallGroupIDs,
DstNetworkType: d.Get("dst_network_type").(string),
DstAddress: d.Get("dst_address").(string),
DstAddressIPV6: d.Get("dst_address_ipv6").(string),
DstPort: d.Get("dst_port").(string),
DstNetworkID: d.Get("dst_network_id").(string),
DstFirewallGroupIDs: dstFirewallGroupIDs,
@@ -248,7 +276,9 @@ func resourceFirewallRuleSetResourceData(resp *unifi.FirewallRule, d *schema.Res
d.Set("ruleset", resp.Ruleset)
d.Set("rule_index", resp.RuleIndex)
d.Set("protocol", resp.Protocol)
d.Set("protocol_v6", resp.ProtocolV6)
d.Set("icmp_typename", resp.ICMPTypename)
d.Set("icmp_v6_typename", resp.ICMPv6Typename)
d.Set("logging", resp.Logging)
d.Set("ip_sec", resp.IPSec)
d.Set("state_established", resp.StateEstablished)
@@ -256,17 +286,17 @@ func resourceFirewallRuleSetResourceData(resp *unifi.FirewallRule, d *schema.Res
d.Set("state_new", resp.StateNew)
d.Set("state_related", resp.StateRelated)
// TODO: handle IPv6
d.Set("src_network_type", resp.SrcNetworkType)
d.Set("src_firewall_group_ids", stringSliceToSet(resp.SrcFirewallGroupIDs))
d.Set("src_mac", resp.SrcMACAddress)
d.Set("src_address", resp.SrcAddress)
d.Set("src_address_ipv6", resp.SrcAddressIPV6)
d.Set("src_network_id", resp.SrcNetworkID)
// TODO: handle IPv6
d.Set("dst_network_type", resp.DstNetworkType)
d.Set("dst_firewall_group_ids", stringSliceToSet(resp.DstFirewallGroupIDs))
d.Set("dst_address", resp.DstAddress)
d.Set("dst_address_ipv6", resp.DstAddressIPV6)
d.Set("dst_network_id", resp.DstNetworkID)
d.Set("dst_port", resp.DstPort)

View File

@@ -95,6 +95,33 @@ func TestAccFirewallRule_address_and_port_group(t *testing.T) {
})
}
func TestAccFirewallRule_IPv6_basic(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
ProviderFactories: providerFactories,
// TODO: CheckDestroy: ,
Steps: []resource.TestStep{
{
Config: testAccFirewallRuleConfigIPv6,
},
importStep("unifi_firewall_rule.test"),
},
})
}
func TestAccFirewallRule_IPv6_dst_port(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccFirewallRuleConfigIPv6WithPort,
},
importStep("unifi_firewall_rule.test"),
},
})
}
// func TestAccFirewallRule_firewall_group(t *testing.T) {
// func TestAccFirewallRule_network(t *testing.T) {
@@ -249,15 +276,48 @@ resource "unifi_firewall_rule" "test" {
}
`
// resource "unifi_firewall_rule" "can_print_drop" {
// name = "[tf] can-print (drop all)"
// action = "drop"
// ruleset = "LAN_IN"
const testAccFirewallRuleConfigIPv6 = `
resource "unifi_firewall_group" "test_a" {
name = "tf acc rule IPv6 group a"
type = "ipv6-address-group"
// rule_index = 2011
members = ["fd6a:37be:e364::/64", "fd6a:37be:e365::/64",]
}
// protocol = "all"
resource "unifi_firewall_group" "test_b" {
name = "tf acc rule IPv6 group b"
type = "ipv6-address-group"
// dst_address = "192.168.1.1"
// }
// `
members = ["2001:4860:4860::8888", "2001:4860:4860::8844"]
}
resource "unifi_firewall_rule" "test" {
name = "tf acc"
action = "drop"
ruleset = "LANv6_IN"
rule_index = 2510
protocol_v6 = "all"
src_firewall_group_ids = [unifi_firewall_group.test_a.id]
dst_firewall_group_ids = [unifi_firewall_group.test_b.id]
}
`
const testAccFirewallRuleConfigIPv6WithPort = `
resource "unifi_firewall_rule" "test" {
name = "tf acc"
action = "accept"
ruleset = "LANv6_IN"
rule_index = 2511
protocol = "tcp"
src_address_ipv6 = "fd6a:37be:e364::1/64"
dst_address_ipv6 = "fd6a:37be:e364::2/64"
dst_port = 53
}
`

View File

@@ -19,11 +19,23 @@ var (
wanTypeRegexp = regexp.MustCompile("disabled|dhcp|static|pppoe")
validateWANType = validation.StringMatch(wanTypeRegexp, "invalid WAN connection type")
wanTypeV6Regexp = regexp.MustCompile("disabled|dhcpv6|static")
validateWANTypeV6 = validation.StringMatch(wanTypeV6Regexp, "invalid WANv6 connection type")
wanPasswordRegexp = regexp.MustCompile("[^\"' ]+")
validateWANPassword = validation.StringMatch(wanPasswordRegexp, "invalid WAN password")
wanNetworkGroupRegexp = regexp.MustCompile("WAN[2]?|WAN_LTE_FAILOVER")
validateWANNetworkGroup = validation.StringMatch(wanNetworkGroupRegexp, "invalid WAN network group")
wanV6NetworkGroupRegexp = regexp.MustCompile("wan[2]?")
validateWANV6NetworkGroup = validation.StringMatch(wanV6NetworkGroupRegexp, "invalid WANv6 network group")
ipV6InterfaceTypeRegexp = regexp.MustCompile("none|pd|static")
validateIpV6InterfaceType = validation.StringMatch(ipV6InterfaceTypeRegexp, "invalid IPv6 interface type")
// This is a slightly larger range than the UI, it includes some reserved ones, so could be tightened up.
validateVLANID = validation.IntBetween(0, 4096)
)
func resourceNetwork() *schema.Resource {
@@ -64,9 +76,10 @@ func resourceNetwork() *schema.Resource {
ValidateFunc: validation.StringInSlice([]string{"corporate", "guest", "wan", "vlan-only"}, false),
},
"vlan_id": {
Description: "The VLAN ID of the network.",
Type: schema.TypeInt,
Optional: true,
Description: "The VLAN ID of the network.",
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validateVLANID,
},
"subnet": {
Description: "The subnet of the network. Must be a valid CIDR address.",
@@ -99,7 +112,7 @@ func resourceNetwork() *schema.Resource {
Optional: true,
},
"dhcp_lease": {
Description: "Specifies the lease time for DHCP addresses.",
Description: "Specifies the lease time for DHCP addresses in seconds.",
Type: schema.TypeInt,
Optional: true,
Default: 86400,
@@ -140,6 +153,47 @@ func resourceNetwork() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
},
"dhcp_v6_dns": {
Description: "Specifies the IPv6 addresses for the DNS server to be returned from the DHCP " +
"server. Used if `dhcp_v6_dns_auto` is set to `false`.",
Type: schema.TypeList,
Optional: true,
MaxItems: 4,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.IsIPv6Address,
// TODO: should this ensure blank can't get through?
},
},
"dhcp_v6_dns_auto": {
Description: "Specifies DNS source to propagate. If set `false` the entries in `dhcp_v6_dns` are used, the upstream entries otherwise",
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"dhcp_v6_enabled": {
Description: "Enable stateful DHCPv6 for static configuration.",
Type: schema.TypeBool,
Optional: true,
},
"dhcp_v6_lease": {
Description: "Specifies the lease time for DHCPv6 addresses in seconds.",
Type: schema.TypeInt,
Optional: true,
Default: 86400,
},
"dhcp_v6_start": {
Description: "Start address of the DHCPv6 range. Used in static DHCPv6 configuration.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv6Address,
},
"dhcp_v6_stop": {
Description: "End address of the DHCPv6 range. Used in static DHCPv6 configuration.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv6Address,
},
"domain_name": {
Description: "The domain name of this network.",
Type: schema.TypeString,
@@ -151,26 +205,40 @@ func resourceNetwork() *schema.Resource {
Optional: true,
},
"ipv6_interface_type": {
Description: "Specifies which type of IPv6 connection to use.",
Type: schema.TypeString,
Optional: true,
Default: "none",
Description: "Specifies which type of IPv6 connection to use. Must be one of either `static`, `pd`, or `none`.",
Type: schema.TypeString,
Optional: true,
Default: "none",
ValidateFunc: validateIpV6InterfaceType,
},
"ipv6_static_subnet": {
Description: "Specifies the static IPv6 subnet when ipv6_interface_type is 'static'.",
Description: "Specifies the static IPv6 subnet when `ipv6_interface_type` is 'static'.",
Type: schema.TypeString,
Optional: true,
},
"ipv6_pd_interface": {
Description: "Specifies which WAN interface to use for IPv6 PD.",
Type: schema.TypeString,
Optional: true,
Description: "Specifies which WAN interface to use for IPv6 PD. Must be one of either `wan` or `wan2`.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateWANV6NetworkGroup,
},
"ipv6_pd_prefixid": {
Description: "Specifies the IPv6 Prefix ID.",
Type: schema.TypeString,
Optional: true,
},
"ipv6_pd_start": {
Description: "Start address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv6Address,
},
"ipv6_pd_stop": {
Description: "End address of the DHCPv6 range. Used if `ipv6_interface_type` is set to `pd`.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv6Address,
},
"ipv6_ra_enable": {
Description: "Specifies whether to enable router advertisements or not.",
Type: schema.TypeBool,
@@ -188,6 +256,24 @@ func resourceNetwork() *schema.Resource {
Optional: true,
Default: true,
},
"ipv6_ra_preferred_lifetime": {
Description: "Lifetime in which the address can be used. Address becomes deprecated afterwards. Must be lower than or equal to `ipv6_ra_valid_lifetime`",
Type: schema.TypeInt,
Optional: true,
Default: 14400,
},
"ipv6_ra_priority": {
Description: "IPv6 router advertisement priority. Must be one of either `high`, `medium`, or `low`",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv4Address,
},
"ipv6_ra_valid_lifetime": {
Description: "Total lifetime in which the address can be used. Must be equal to or greater than `ipv6_ra_preferred_lifetime`.",
Type: schema.TypeInt,
Optional: true,
Default: 86400,
},
"wan_ip": {
Description: "The IPv4 address of the WAN.",
Type: schema.TypeString,
@@ -246,6 +332,36 @@ func resourceNetwork() *schema.Resource {
Optional: true,
ValidateFunc: validateWANPassword,
},
"wan_type_v6": {
Description: "Specifies the IPV6 WAN connection type. Must be one of either `disabled`, `static`, or `dhcpv6`.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateWANTypeV6,
},
"wan_dhcp_v6_pd_size": {
Description: "Specifies the IPv6 prefix size to request from ISP. Must be between 48 and 64.",
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(48, 64),
},
"wan_ipv6": {
Description: "The IPv6 address of the WAN.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv6Address,
},
"wan_gateway_v6": {
Description: "The IPv6 gateway of the WAN.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsIPv6Address,
},
"wan_prefixlen": {
Description: "The IPv6 prefix length of the WAN. Must be between 1 and 128.",
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(1, 128),
},
},
}
}
@@ -281,6 +397,10 @@ func resourceNetworkGetResourceData(d *schema.ResourceData, meta interface{}) (*
if err != nil {
return nil, fmt.Errorf("unable to convert dhcp_dns to string slice: %w", err)
}
dhcpV6DNS, err := listToStringSlice(d.Get("dhcp_v6_dns").([]interface{}))
if err != nil {
return nil, fmt.Errorf("unable to convert dhcp_v6_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)
@@ -314,11 +434,28 @@ func resourceNetworkGetResourceData(d *schema.ResourceData, meta interface{}) (*
Enabled: true,
IPV6InterfaceType: d.Get("ipv6_interface_type").(string),
IPV6Subnet: d.Get("ipv6_static_subnet").(string),
IPV6PDInterface: d.Get("ipv6_pd_interface").(string),
IPV6PDPrefixid: d.Get("ipv6_pd_prefixid").(string),
IPV6RaEnabled: d.Get("ipv6_ra_enable").(bool),
// Same hackish code as for DHCPv4 ¯\_(ツ)_/¯
DHCPDV6DNS1: append(dhcpV6DNS, "")[0],
DHCPDV6DNS2: append(dhcpV6DNS, "", "")[1],
DHCPDV6DNS3: append(dhcpV6DNS, "", "", "")[2],
DHCPDV6DNS4: append(dhcpV6DNS, "", "", "", "")[3],
DHCPDV6DNSAuto: d.Get("dhcp_v6_dns_auto").(bool),
DHCPDV6Enabled: d.Get("dhcp_v6_enabled").(bool),
DHCPDV6LeaseTime: d.Get("dhcp_v6_lease").(int),
DHCPDV6Start: d.Get("dhcp_v6_start").(string),
DHCPDV6Stop: d.Get("dhcp_v6_stop").(string),
IPV6InterfaceType: d.Get("ipv6_interface_type").(string),
IPV6Subnet: d.Get("ipv6_static_subnet").(string),
IPV6PDInterface: d.Get("ipv6_pd_interface").(string),
IPV6PDPrefixid: d.Get("ipv6_pd_prefixid").(string),
IPV6PDStart: d.Get("ipv6_pd_start").(string),
IPV6PDStop: d.Get("ipv6_pd_stop").(string),
IPV6RaEnabled: d.Get("ipv6_ra_enable").(bool),
IPV6RaPreferredLifetime: d.Get("ipv6_ra_preferred_lifetime").(int),
IPV6RaPriority: d.Get("ipv6_ra_priority").(string),
IPV6RaValidLifetime: d.Get("ipv6_ra_valid_lifetime").(int),
InternetAccessEnabled: d.Get("internet_access_enabled").(bool),
IntraNetworkAccessEnabled: d.Get("intra_network_access_enabled").(bool),
@@ -332,6 +469,12 @@ func resourceNetworkGetResourceData(d *schema.ResourceData, meta interface{}) (*
WANUsername: d.Get("wan_username").(string),
XWANPassword: d.Get("x_wan_password").(string),
WANTypeV6: d.Get("wan_type_v6").(string),
WANDHCPv6PDSize: d.Get("wan_dhcp_v6_pd_size").(int),
WANIPV6: d.Get("wan_ipv6").(string),
WANGatewayV6: d.Get("wan_gateway_v6").(string),
WANPrefixlen: d.Get("wan_prefixlen").(int),
// this is kinda hacky but ¯\_(ツ)_/¯
WANDNS1: append(wanDNS, "")[0],
WANDNS2: append(wanDNS, "", "")[1],
@@ -396,37 +539,67 @@ func resourceNetworkSetResourceData(resp *unifi.Network, d *schema.ResourceData,
}
}
dhcpV6DNS := []string{}
for _, dns := range []string{
resp.DHCPDV6DNS1,
resp.DHCPDV6DNS2,
resp.DHCPDV6DNS3,
resp.DHCPDV6DNS4,
} {
if dns == "" {
continue
}
dhcpV6DNS = append(dhcpV6DNS, dns)
}
d.Set("site", site)
d.Set("name", resp.Name)
d.Set("purpose", resp.Purpose)
d.Set("vlan_id", vlan)
d.Set("subnet", cidrZeroBased(resp.IPSubnet))
d.Set("network_group", resp.NetworkGroup)
d.Set("dhcp_start", resp.DHCPDStart)
d.Set("dhcp_stop", resp.DHCPDStop)
d.Set("dhcp_dns", dhcpDNS)
d.Set("dhcp_enabled", resp.DHCPDEnabled)
d.Set("dhcp_lease", dhcpLease)
d.Set("dhcpd_boot_enabled", resp.DHCPDBootEnabled)
d.Set("dhcpd_boot_server", resp.DHCPDBootServer)
d.Set("dhcpd_boot_filename", resp.DHCPDBootFilename)
d.Set("dhcp_relay_enabled", resp.DHCPRelayEnabled)
d.Set("dhcp_start", resp.DHCPDStart)
d.Set("dhcp_stop", resp.DHCPDStop)
d.Set("dhcp_v6_dns_auto", resp.DHCPDV6DNSAuto)
d.Set("dhcp_v6_dns", dhcpV6DNS)
d.Set("dhcp_v6_enabled", resp.DHCPDV6Enabled)
d.Set("dhcp_v6_lease", resp.DHCPDV6LeaseTime)
d.Set("dhcp_v6_start", resp.DHCPDV6Start)
d.Set("dhcp_v6_stop", resp.DHCPDV6Stop)
d.Set("dhcpd_boot_enabled", resp.DHCPDBootEnabled)
d.Set("dhcpd_boot_filename", resp.DHCPDBootFilename)
d.Set("dhcpd_boot_server", resp.DHCPDBootServer)
d.Set("domain_name", resp.DomainName)
d.Set("igmp_snooping", resp.IGMPSnooping)
d.Set("dhcp_dns", dhcpDNS)
d.Set("ipv6_interface_type", resp.IPV6InterfaceType)
d.Set("ipv6_static_subnet", resp.IPV6Subnet)
d.Set("ipv6_pd_interface", resp.IPV6PDInterface)
d.Set("ipv6_pd_prefixid", resp.IPV6PDPrefixid)
d.Set("ipv6_ra_enable", resp.IPV6RaEnabled)
d.Set("internet_access_enabled", resp.InternetAccessEnabled)
d.Set("intra_network_access_enabled", resp.IntraNetworkAccessEnabled)
d.Set("wan_ip", wanIP)
d.Set("wan_netmask", wanNetmask)
d.Set("wan_gateway", wanGateway)
d.Set("wan_type", wanType)
d.Set("ipv6_interface_type", resp.IPV6InterfaceType)
d.Set("ipv6_pd_interface", resp.IPV6PDInterface)
d.Set("ipv6_pd_prefixid", resp.IPV6PDPrefixid)
d.Set("ipv6_pd_start", resp.IPV6PDStart)
d.Set("ipv6_pd_stop", resp.IPV6PDStop)
d.Set("ipv6_ra_enable", resp.IPV6RaEnabled)
d.Set("ipv6_ra_preferred_lifetime", resp.IPV6RaPreferredLifetime)
d.Set("ipv6_ra_priority", resp.IPV6RaPriority)
d.Set("ipv6_ra_valid_lifetime", resp.IPV6RaValidLifetime)
d.Set("ipv6_static_subnet", resp.IPV6Subnet)
d.Set("wan_dhcp_v6_pd_size", resp.WANDHCPv6PDSize)
d.Set("wan_dns", wanDNS)
d.Set("wan_networkgroup", resp.WANNetworkGroup)
d.Set("wan_egress_qos", resp.WANEgressQOS)
d.Set("wan_gateway_v6", resp.WANGatewayV6)
d.Set("wan_gateway", wanGateway)
d.Set("wan_ip", wanIP)
d.Set("wan_ipv6", resp.WANIPV6)
d.Set("wan_netmask", wanNetmask)
d.Set("wan_networkgroup", resp.WANNetworkGroup)
d.Set("wan_prefixlen", resp.WANPrefixlen)
d.Set("wan_type_v6", resp.WANTypeV6)
d.Set("wan_type", wanType)
d.Set("wan_username", resp.WANUsername)
d.Set("x_wan_password", resp.XWANPassword)

View File

@@ -133,6 +133,7 @@ func TestAccNetwork_v6(t *testing.T) {
name := acctest.RandomWithPrefix("tfacc")
vlanID1 := getTestVLAN(t)
vlanID2 := getTestVLAN(t)
vlanID3 := getTestVLAN(t)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
@@ -156,6 +157,31 @@ func TestAccNetwork_v6(t *testing.T) {
),
},
importStep("unifi_network.test"),
{
Config: testAccNetworkConfigDhcpV6(
name,
vlanID3,
"fd6a:37be:e364::1/64",
"fd6a:37be:e364::2",
"fd6a:37be:e364::7d1",
[]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("unifi_network.test", "vlan_id", strconv.Itoa(vlanID3)),
resource.TestCheckResourceAttr("unifi_network.test", "dhcp_v6_start", "fd6a:37be:e364::2"),
resource.TestCheckResourceAttr("unifi_network.test", "dhcp_v6_stop", "fd6a:37be:e364::7d1"),
resource.TestCheckResourceAttr("unifi_network.test", "dhcp_v6_lease", strconv.Itoa(12*60*60)),
),
},
{
Config: testAccNetworkConfigDhcpV6(
name,
vlanID3,
"fd6a:37be:e365::1/64",
"fd6a:37be:e364::2",
"fd6a:37be:e364::7d1",
[]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}),
ExpectError: regexp.MustCompile(regexp.QuoteMeta("api.err.InvalidDHCPv6Range")),
},
},
})
}
@@ -198,6 +224,21 @@ func TestAccNetwork_wan(t *testing.T) {
),
},
importStep("unifi_network.wan_test"),
{
Config: testWanV6NetworkConfig(name, "dhcpv6", 47),
ExpectError: regexp.MustCompile(regexp.QuoteMeta("expected wan_dhcp_v6_pd_size to be in the range (48 - 64)")),
},
{
Config: testWanV6NetworkConfig(name, "invalid", 48),
ExpectError: regexp.MustCompile(regexp.QuoteMeta("invalid value for wan_type_v6")),
},
{
Config: testWanV6NetworkConfig(name, "dhcpv6", 48),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_type_v6", "dhcpv6"),
resource.TestCheckResourceAttr("unifi_network.wan_test", "wan_dhcp_v6_pd_size", "48"),
),
},
},
})
}
@@ -318,6 +359,7 @@ func TestAccNetwork_dhcpRelay(t *testing.T) {
func TestAccNetwork_vlanOnly(t *testing.T) {
name := acctest.RandomWithPrefix("tfacc")
vlanID := getTestVLAN(t)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
@@ -327,9 +369,9 @@ func TestAccNetwork_vlanOnly(t *testing.T) {
// TODO: CheckDestroy: ,
Steps: []resource.TestStep{
{
Config: testAccNetworkVlanOnly(name),
Config: testAccNetworkVlanOnly(name, vlanID),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("unifi_network.test", "vlan_id", "101"),
resource.TestCheckResourceAttr("unifi_network.test", "vlan_id", strconv.Itoa(vlanID)),
),
},
{
@@ -453,6 +495,26 @@ output "wan_dns2" {
`, name, networkGroup, wanType, wanIP, wanEgressQOS, wanUsername, wanPassword, wanDNS1, wanDNS2)
}
func testWanV6NetworkConfig(name string, wanTypeV6 string, wanDhcpV6PdSize int) string {
return fmt.Sprintf(`
resource "unifi_network" "wan_test" {
name = "%s"
purpose = "wan"
wan_networkgroup = "WAN"
wan_type = "pppoe"
wan_ip = "192.168.1.1"
wan_egress_qos = 1
wan_username = "username"
x_wan_password = "password"
wan_dns = ["8.8.8.8", "4.4.4.4"]
wan_type_v6 = "%s"
wan_dhcp_v6_pd_size = %d
}
`, name, wanTypeV6, wanDhcpV6PdSize)
}
func testAccNetworkWithSiteConfig(name string, vlan int) string {
return fmt.Sprintf(`
locals {
@@ -527,7 +589,7 @@ resource "unifi_network" "test" {
`, name, vlan, dhcpRelay)
}
func testAccNetworkVlanOnly(name string) string {
func testAccNetworkVlanOnly(name string, vlan int) string {
return fmt.Sprintf(`
resource "unifi_site" "test" {
description = "%[1]s"
@@ -537,7 +599,33 @@ resource "unifi_network" "test" {
site = unifi_site.test.name
name = "test"
purpose = "vlan-only"
vlan_id = 101
vlan_id = %[2]d
}
`, name)
`, name, vlan)
}
func testAccNetworkConfigDhcpV6(name string, vlan int, gatewayIP string, dhcpdV6Start string, dhcpdV6Stop string, dhcpV6DNS []string) string {
return fmt.Sprintf(`
locals {
subnet = cidrsubnet("10.0.0.0/8", 6, %[2]d)
vlan_id = %[2]d
}
resource "unifi_network" "test" {
name = "%[1]s"
purpose = "corporate"
subnet = local.subnet
vlan_id = local.vlan_id
ipv6_static_subnet = "%[3]s"
dhcp_v6_dns_auto = false
dhcp_v6_dns = [%[6]s]
dhcp_v6_enabled = true
dhcp_v6_start = "%[4]s"
dhcp_v6_stop = "%[5]s"
dhcp_v6_lease = 12 * 60 * 60
}
`, name, vlan, gatewayIP, dhcpdV6Start, dhcpdV6Stop, strings.Join(quoteStrings(dhcpV6DNS), ","))
}

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"

View File

@@ -3,11 +3,12 @@ package provider
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"
"strings"
)
func resourceRadiusProfile() *schema.Resource {

View File

@@ -2,8 +2,9 @@ package provider
import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"testing"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)
func TestAccRadiusProfile_basic(t *testing.T) {

View File

@@ -2,6 +2,7 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"

View File

@@ -3,8 +3,8 @@ package provider
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"

View File

@@ -5,7 +5,6 @@ import (
"errors"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/paultyng/go-unifi/unifi"

View File

@@ -2,8 +2,8 @@ package provider
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/paultyng/go-unifi/unifi"
)