From 1a67188feb13d3205237f6a529b1d4cc96fb2ab5 Mon Sep 17 00:00:00 2001 From: Paul Tyng Date: Wed, 19 Feb 2020 10:37:27 -0500 Subject: [PATCH] Add unifi_user ip and hostname Bump go-unifi to 1.1.0 --- go.mod | 2 +- go.sum | 4 +- internal/provider/cidr.go | 47 ++++++++++++++++++++++ internal/provider/resource_network.go | 9 +++-- internal/provider/resource_network_test.go | 25 ++++++++++-- internal/provider/resource_user.go | 26 ++++++++++++ internal/provider/{types.go => strings.go} | 0 7 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 internal/provider/cidr.go rename internal/provider/{types.go => strings.go} (100%) diff --git a/go.mod b/go.mod index 4e2711b..aa40006 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/hashicorp/yamux v0.0.0-20190923154419-df201c70410d // indirect github.com/jstemmer/go-junit-report v0.9.1 // indirect github.com/mattn/go-isatty v0.0.11 // indirect - github.com/paultyng/go-unifi v1.0.2 + github.com/paultyng/go-unifi v1.1.0 github.com/posener/complete v1.2.3 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/ulikunitz/xz v0.5.6 // indirect diff --git a/go.sum b/go.sum index e72bdda..59c8aed 100644 --- a/go.sum +++ b/go.sum @@ -310,8 +310,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paultyng/go-unifi v1.0.2 h1:1A7JVNbvgQOeZ1T2Z5Snl3CHKsix3MWm/p3sYDbJWMU= -github.com/paultyng/go-unifi v1.0.2/go.mod h1:L8VrStOsfwfMx4lk8vxlOJS0D6Pj4rkV4wHAj8yP0dc= +github.com/paultyng/go-unifi v1.1.0 h1:muFZHYGu+FdycoCd3w0nkmoMAflxlBYuI5MLWWDFWnc= +github.com/paultyng/go-unifi v1.1.0/go.mod h1:L8VrStOsfwfMx4lk8vxlOJS0D6Pj4rkV4wHAj8yP0dc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/internal/provider/cidr.go b/internal/provider/cidr.go new file mode 100644 index 0000000..86d7f1d --- /dev/null +++ b/internal/provider/cidr.go @@ -0,0 +1,47 @@ +package provider + +import ( + "net" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func cidrDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + _, oldNet, err := net.ParseCIDR(old) + if err != nil { + return false + } + + _, newNet, err := net.ParseCIDR(new) + if err != nil { + return false + } + + return oldNet.String() == newNet.String() +} + +func cidrZeroBased(cidr string) string { + _, cidrNet, err := net.ParseCIDR(cidr) + if err != nil { + return "" + } + if len(cidrNet.Mask) == net.IPv6len { + return "" + } + + return cidrNet.String() +} + +func cidrOneBased(cidr string) string { + _, cidrNet, err := net.ParseCIDR(cidr) + if err != nil { + return "" + } + if len(cidrNet.Mask) == net.IPv6len { + return "" + } + + cidrNet.IP[3]++ + + return cidrNet.String() +} diff --git a/internal/provider/resource_network.go b/internal/provider/resource_network.go index d285ec7..79c7373 100644 --- a/internal/provider/resource_network.go +++ b/internal/provider/resource_network.go @@ -32,8 +32,9 @@ func resourceNetwork() *schema.Resource { Optional: true, }, "subnet": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: cidrDiffSuppress, }, "network_group": { Type: schema.TypeString, @@ -94,7 +95,7 @@ func resourceNetworkGetResourceData(d *schema.ResourceData) (*unifi.Network, err Name: d.Get("name").(string), Purpose: d.Get("purpose").(string), VLAN: vlan, - IPSubnet: d.Get("subnet").(string), + IPSubnet: cidrOneBased(d.Get("subnet").(string)), NetworkGroup: d.Get("network_group").(string), DHCPDStart: d.Get("dhcp_start").(string), DHCPDStop: d.Get("dhcp_stop").(string), @@ -127,7 +128,7 @@ func resourceNetworkSetResourceData(resp *unifi.Network, d *schema.ResourceData) d.Set("name", resp.Name) d.Set("purpose", resp.Purpose) d.Set("vlan_id", vlan) - d.Set("subnet", resp.IPSubnet) + d.Set("subnet", cidrZeroBased(resp.IPSubnet)) d.Set("network_group", resp.NetworkGroup) d.Set("dhcp_start", resp.DHCPDStart) d.Set("dhcp_stop", resp.DHCPDStop) diff --git a/internal/provider/resource_network_test.go b/internal/provider/resource_network_test.go index 382eba6..6f8c163 100644 --- a/internal/provider/resource_network_test.go +++ b/internal/provider/resource_network_test.go @@ -14,19 +14,19 @@ func TestAccNetwork_basic(t *testing.T) { // TODO: CheckDestroy: , Steps: []resource.TestStep{ { - Config: testAccNetworkConfig("10.0.202.1/24", 202, true), + Config: testAccNetworkConfig("10.0.202.0/24", 202, true), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("unifi_network.test", "domain_name", "foo.local"), - resource.TestCheckResourceAttr("unifi_network.test", "subnet", "10.0.202.1/24"), + resource.TestCheckResourceAttr("unifi_network.test", "subnet", "10.0.202.0/24"), resource.TestCheckResourceAttr("unifi_network.test", "vlan_id", "202"), resource.TestCheckResourceAttr("unifi_network.test", "igmp_snooping", "true"), ), }, importStep("unifi_network.test"), { - Config: testAccNetworkConfig("10.0.203.1/24", 203, false), + Config: testAccNetworkConfig("10.0.203.0/24", 203, false), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("unifi_network.test", "subnet", "10.0.203.1/24"), + resource.TestCheckResourceAttr("unifi_network.test", "subnet", "10.0.203.0/24"), resource.TestCheckResourceAttr("unifi_network.test", "vlan_id", "203"), resource.TestCheckResourceAttr("unifi_network.test", "igmp_snooping", "false"), ), @@ -36,6 +36,23 @@ func TestAccNetwork_basic(t *testing.T) { }) } +func TestAccNetwork_weird_cidr(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + Providers: providers, + PreCheck: func() { preCheck(t) }, + // TODO: CheckDestroy: , + Steps: []resource.TestStep{ + { + Config: testAccNetworkConfig("10.0.202.3/24", 202, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("unifi_network.test", "subnet", "10.0.202.0/24"), + ), + }, + importStep("unifi_network.test"), + }, + }) +} + func testAccNetworkConfig(subnet string, vlan int, igmpSnoop bool) string { return fmt.Sprintf(` variable "subnet" { diff --git a/internal/provider/resource_user.go b/internal/provider/resource_user.go index 4815e05..50197ff 100644 --- a/internal/provider/resource_user.go +++ b/internal/provider/resource_user.go @@ -41,6 +41,7 @@ func resourceUser() *schema.Resource { Type: schema.TypeString, Optional: true, }, + // TODO: combine this with output IP for a single attribute ip_address? "fixed_ip": { Type: schema.TypeString, Optional: true, @@ -66,6 +67,16 @@ func resourceUser() *schema.Resource { Optional: true, Default: false, }, + + // computed only attributes + "hostname": { + Type: schema.TypeString, + Computed: true, + }, + "ip": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -145,6 +156,9 @@ func resourceUserSetResourceData(resp *unifi.User, d *schema.ResourceData) error d.Set("network_id", resp.NetworkID) d.Set("blocked", resp.Blocked) + d.Set("hostname", resp.Hostname) + d.Set("ip", resp.IP) + return nil } @@ -162,6 +176,18 @@ func resourceUserRead(d *schema.ResourceData, meta interface{}) error { return err } + // for some reason the IP address is only on this endpoint, so issue another request + macResp, err := c.c.GetUserByMAC(c.site, resp.MAC) + if _, ok := err.(*unifi.NotFoundError); ok { + d.SetId("") + return nil + } + if err != nil { + return err + } + + resp.IP = macResp.IP + return resourceUserSetResourceData(resp, d) } diff --git a/internal/provider/types.go b/internal/provider/strings.go similarity index 100% rename from internal/provider/types.go rename to internal/provider/strings.go