Initial version

Extracted from paultyng/terraform-provider-unifi@ef25893f14
This commit is contained in:
Paul Tyng
2020-01-10 14:31:12 -05:00
commit 435ecf9d6f
135 changed files with 6973 additions and 0 deletions

145
unifi/unifi.go Normal file
View File

@@ -0,0 +1,145 @@
package unifi //
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"net/url"
)
type NotFoundError struct{}
func (err *NotFoundError) Error() string {
return "not found"
}
type APIError struct {
RC string
Message string
}
func (err *APIError) Error() string {
return err.Message
}
type Client struct {
c *http.Client
baseURL *url.URL
}
func (c *Client) SetBaseURL(base string) error {
var err error
c.baseURL, err = url.Parse(base)
if err != nil {
return err
}
return nil
}
func (c *Client) SetHTTPClient(hc *http.Client) error {
c.c = hc
return nil
}
func (c *Client) Login(user, pass string) error {
if c.c == nil {
c.c = &http.Client{}
jar, _ := cookiejar.New(nil)
c.c.Jar = jar
}
err := c.do("POST", "login", &struct {
Username string `json:"username"`
Password string `json:"password"`
}{
Username: user,
Password: pass,
}, nil)
if err != nil {
return err
}
return nil
}
func (c *Client) do(method, relativeURL string, reqBody interface{}, respBody interface{}) error {
var (
reqReader io.Reader
err error
reqBytes []byte
)
if reqBody != nil {
reqBytes, err = json.Marshal(reqBody)
if err != nil {
return err
}
reqReader = bytes.NewReader(reqBytes)
}
reqURL, err := url.Parse(relativeURL)
if err != nil {
return err
}
url := c.baseURL.ResolveReference(reqURL)
req, err := http.NewRequest(method, url.String(), reqReader)
if err != nil {
return err
}
req.Header.Set("User-Agent", "terraform-provider-unifi/0.1")
resp, err := c.c.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusNotFound {
return &NotFoundError{}
}
if resp.StatusCode != 200 {
fmt.Printf("Request Body:\n%s\n", string(reqBytes))
errBody := struct {
Meta meta `json:"meta"`
}{}
err = json.NewDecoder(resp.Body).Decode(&errBody)
return fmt.Errorf("%s %s (%s) for %s %s", errBody.Meta.RC, errBody.Meta.Message, resp.Status, method, url.String())
}
if respBody == nil || resp.ContentLength == 0 {
return nil
}
// TODO: check rc in addition to status code?
err = json.NewDecoder(resp.Body).Decode(respBody)
if err != nil {
return err
}
return nil
}
type meta struct {
RC string `json:"rc"`
Message string `json:"msg"`
}
func (m *meta) error() error {
if m.RC != "ok" {
return &APIError{
RC: m.RC,
Message: m.Message,
}
}
return nil
}