From 035e4af383e7af3c8343e399688cbc05f07608b3 Mon Sep 17 00:00:00 2001 From: Paul Tyng Date: Thu, 24 Sep 2020 17:06:03 -0400 Subject: [PATCH] Fix API path style issues (for UDM Pro) --- .github/workflows/acctest.yml | 2 +- controller.sh | 2 +- docs/index.md | 2 +- go.mod | 2 +- go.sum | 4 +- internal/provider/lazy_client.go | 171 +++++++++++++++++++++++-------- internal/provider/provider.go | 4 +- 7 files changed, 135 insertions(+), 52 deletions(-) diff --git a/.github/workflows/acctest.yml b/.github/workflows/acctest.yml index 2952f3a..a98c87c 100644 --- a/.github/workflows/acctest.yml +++ b/.github/workflows/acctest.yml @@ -76,7 +76,7 @@ jobs: UNIFI_USERNAME: tfacctest UNIFI_PASSWORD: tfacctest1234 - UNIFI_API: https://localhost:8443/api/ + UNIFI_API: https://localhost:8443/ UNIFI_ACC_WLAN_CONCURRENCY: "4" UNIFI_INSECURE: 'true' run: | diff --git a/controller.sh b/controller.sh index 448c828..8e17e22 100755 --- a/controller.sh +++ b/controller.sh @@ -36,7 +36,7 @@ case "$1" in TF_ACC=1 \ UNIFI_USERNAME=tfacctest \ UNIFI_PASSWORD=tfacctest1234 \ - UNIFI_API="https://localhost:${DOCKER_HTTPS_PORT}/api/" \ + UNIFI_API="https://localhost:${DOCKER_HTTPS_PORT}/" \ UNIFI_ACC_WLAN_CONCURRENCY="4" \ UNIFI_INSECURE="true" \ go test -v -cover -count 1 ./internal/provider diff --git a/docs/index.md b/docs/index.md index a06d61f..4f998bc 100644 --- a/docs/index.md +++ b/docs/index.md @@ -27,7 +27,7 @@ provider "unifi" { ### Optional - **allow_insecure** (Boolean, Optional) Skip verification of TLS certificates of API requests. You may need to set this to `true` if you are using your local API without setting up a signed certificate. Can be specified with the `UNIFI_INSECURE` environment variable. -- **api_url** (String, Optional) URL of the controller API. Can be specified with the `UNIFI_API` environment variable. This typically has the `/api` path appended to it, ie. `https://192.168.1.100:8443/api`. +- **api_url** (String, Optional) URL of the controller API. Can be specified with the `UNIFI_API` environment variable. You should **NOT** supply the path (`/api`), the SDK will discover the appropriate paths. This isto support UDM Pro style API paths as well as more standard controller paths. - **password** (String, Optional) Password for the user accessing the API. Can be specified with the `UNIFI_PASSWORD` environment variable. - **site** (String, Optional) The site in the Unifi controller this provider will manage. Can be specified with the `UNIFI_SITE` environment variable. Default: `default` - **username** (String, Optional) Local user name for the Unifi controller API. Can be specified with the `UNIFI_USERNAME` environment variable. diff --git a/go.mod b/go.mod index 127b759..81a9d79 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/terraform-plugin-docs v0.1.4 github.com/hashicorp/terraform-plugin-sdk/v2 v2.0.3 github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce // indirect - github.com/paultyng/go-unifi v1.6.0 + github.com/paultyng/go-unifi v1.7.0 github.com/posener/complete v1.2.1 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect ) diff --git a/go.sum b/go.sum index 3aa50ef..95ab53a 100644 --- a/go.sum +++ b/go.sum @@ -280,8 +280,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/paultyng/go-unifi v1.6.0 h1:kczxon8GDUinxiE3OxAIdDFaKb6q5n/xIBP698zULsk= -github.com/paultyng/go-unifi v1.6.0/go.mod h1:136w8wenUPfYXRTAYtKqYJ/u32ZFMHE9QVD3NQfEcuI= +github.com/paultyng/go-unifi v1.7.0 h1:N/RJ7kXLwEnhTzoCxyXQFI2CklWAywrfvZLjCpetWLA= +github.com/paultyng/go-unifi v1.7.0/go.mod h1:136w8wenUPfYXRTAYtKqYJ/u32ZFMHE9QVD3NQfEcuI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/internal/provider/lazy_client.go b/internal/provider/lazy_client.go index 799947c..db9a37f 100644 --- a/internal/provider/lazy_client.go +++ b/internal/provider/lazy_client.go @@ -50,179 +50,260 @@ func setHTTPClient(c *unifi.Client, insecure bool) { c.SetHTTPClient(httpClient) } +var initErr error + func (c *lazyClient) init(ctx context.Context) error { - var err error c.once.Do(func() { c.inner = &unifi.Client{} setHTTPClient(c.inner, c.insecure) - err = c.inner.SetBaseURL(c.baseURL) - if err != nil { + initErr = c.inner.SetBaseURL(c.baseURL) + if initErr != nil { return } - err = c.inner.Login(ctx, c.user, c.pass) + initErr = c.inner.Login(ctx, c.user, c.pass) }) - return err + return initErr } func (c *lazyClient) ListUserGroup(ctx context.Context, site string) ([]unifi.UserGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.ListUserGroup(ctx, site) } func (c *lazyClient) ListWLANGroup(ctx context.Context, site string) ([]unifi.WLANGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.ListWLANGroup(ctx, site) } func (c *lazyClient) DeleteNetwork(ctx context.Context, site, id, name string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteNetwork(ctx, site, id, name) } func (c *lazyClient) CreateNetwork(ctx context.Context, site string, d *unifi.Network) (*unifi.Network, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateNetwork(ctx, site, d) } func (c *lazyClient) GetNetwork(ctx context.Context, site, id string) (*unifi.Network, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetNetwork(ctx, site, id) } func (c *lazyClient) UpdateNetwork(ctx context.Context, site string, d *unifi.Network) (*unifi.Network, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateNetwork(ctx, site, d) } func (c *lazyClient) DeleteWLAN(ctx context.Context, site, id string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteWLAN(ctx, site, id) } func (c *lazyClient) CreateWLAN(ctx context.Context, site string, d *unifi.WLAN) (*unifi.WLAN, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateWLAN(ctx, site, d) } func (c *lazyClient) GetWLAN(ctx context.Context, site, id string) (*unifi.WLAN, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetWLAN(ctx, site, id) } func (c *lazyClient) UpdateWLAN(ctx context.Context, site string, d *unifi.WLAN) (*unifi.WLAN, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateWLAN(ctx, site, d) } func (c *lazyClient) DeleteUserGroup(ctx context.Context, site, id string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteUserGroup(ctx, site, id) } func (c *lazyClient) CreateUserGroup(ctx context.Context, site string, d *unifi.UserGroup) (*unifi.UserGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateUserGroup(ctx, site, d) } func (c *lazyClient) GetUserGroup(ctx context.Context, site, id string) (*unifi.UserGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetUserGroup(ctx, site, id) } func (c *lazyClient) UpdateUserGroup(ctx context.Context, site string, d *unifi.UserGroup) (*unifi.UserGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateUserGroup(ctx, site, d) } func (c *lazyClient) GetUser(ctx context.Context, site, id string) (*unifi.User, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetUser(ctx, site, id) } func (c *lazyClient) GetUserByMAC(ctx context.Context, site, mac string) (*unifi.User, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetUserByMAC(ctx, site, mac) } func (c *lazyClient) CreateUser(ctx context.Context, site string, d *unifi.User) (*unifi.User, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateUser(ctx, site, d) } func (c *lazyClient) UpdateUser(ctx context.Context, site string, d *unifi.User) (*unifi.User, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateUser(ctx, site, d) } func (c *lazyClient) DeleteUserByMAC(ctx context.Context, site, mac string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteUserByMAC(ctx, site, mac) } func (c *lazyClient) BlockUserByMAC(ctx context.Context, site, mac string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.BlockUserByMAC(ctx, site, mac) } func (c *lazyClient) UnblockUserByMAC(ctx context.Context, site, mac string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.UnblockUserByMAC(ctx, site, mac) } func (c *lazyClient) ListFirewallGroup(ctx context.Context, site string) ([]unifi.FirewallGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.ListFirewallGroup(ctx, site) } func (c *lazyClient) DeleteFirewallGroup(ctx context.Context, site, id string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteFirewallGroup(ctx, site, id) } func (c *lazyClient) CreateFirewallGroup(ctx context.Context, site string, d *unifi.FirewallGroup) (*unifi.FirewallGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateFirewallGroup(ctx, site, d) } func (c *lazyClient) GetFirewallGroup(ctx context.Context, site, id string) (*unifi.FirewallGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetFirewallGroup(ctx, site, id) } func (c *lazyClient) UpdateFirewallGroup(ctx context.Context, site string, d *unifi.FirewallGroup) (*unifi.FirewallGroup, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateFirewallGroup(ctx, site, d) } func (c *lazyClient) ListFirewallRule(ctx context.Context, site string) ([]unifi.FirewallRule, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.ListFirewallRule(ctx, site) } func (c *lazyClient) DeleteFirewallRule(ctx context.Context, site, id string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteFirewallRule(ctx, site, id) } func (c *lazyClient) CreateFirewallRule(ctx context.Context, site string, d *unifi.FirewallRule) (*unifi.FirewallRule, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateFirewallRule(ctx, site, d) } func (c *lazyClient) GetFirewallRule(ctx context.Context, site, id string) (*unifi.FirewallRule, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetFirewallRule(ctx, site, id) } func (c *lazyClient) UpdateFirewallRule(ctx context.Context, site string, d *unifi.FirewallRule) (*unifi.FirewallRule, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateFirewallRule(ctx, site, d) } func (c *lazyClient) GetPortForward(ctx context.Context, site, id string) (*unifi.PortForward, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetPortForward(ctx, site, id) } func (c *lazyClient) DeletePortForward(ctx context.Context, site, id string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeletePortForward(ctx, site, id) } func (c *lazyClient) CreatePortForward(ctx context.Context, site string, d *unifi.PortForward) (*unifi.PortForward, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreatePortForward(ctx, site, d) } func (c *lazyClient) UpdatePortForward(ctx context.Context, site string, d *unifi.PortForward) (*unifi.PortForward, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdatePortForward(ctx, site, d) } func (c *lazyClient) ListRADIUSProfile(ctx context.Context, site string) ([]unifi.RADIUSProfile, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.ListRADIUSProfile(ctx, site) } func (c *lazyClient) GetRADIUSProfile(ctx context.Context, site, id string) (*unifi.RADIUSProfile, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.GetRADIUSProfile(ctx, site, id) } func (c *lazyClient) DeleteRADIUSProfile(ctx context.Context, site, id string) error { - c.init(ctx) + if err := c.init(ctx); err != nil { + return err + } return c.inner.DeleteRADIUSProfile(ctx, site, id) } func (c *lazyClient) CreateRADIUSProfile(ctx context.Context, site string, d *unifi.RADIUSProfile) (*unifi.RADIUSProfile, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.CreateRADIUSProfile(ctx, site, d) } func (c *lazyClient) UpdateRADIUSProfile(ctx context.Context, site string, d *unifi.RADIUSProfile) (*unifi.RADIUSProfile, error) { - c.init(ctx) + if err := c.init(ctx); err != nil { + return nil, err + } return c.inner.UpdateRADIUSProfile(ctx, site, d) } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 8190cc0..9486653 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -40,7 +40,9 @@ func New() *schema.Provider { }, "api_url": { Description: "URL of the controller API. Can be specified with the `UNIFI_API` environment variable. " + - "This typically has the `/api` path appended to it, ie. `https://192.168.1.100:8443/api`.", + "You should **NOT** supply the path (`/api`), the SDK will discover the appropriate paths. This is" + + "to support UDM Pro style API paths as well as more standard controller paths.", + Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("UNIFI_API", ""),