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:
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
`
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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), ","))
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user