package client import ( "fmt" "net/http" ) func notFound(what string) error { return &APIError{http.StatusNotFound, "no such " + what} } // ---- organizations ---- func (c *Client) Orgs() ([]Org, error) { var out []Org return out, c.do("GET", "/api/orgs", nil, &out) } // CreateOrg needs a server key. func (c *Client) CreateOrg(name string, allowLocal bool) (*Org, error) { var out Org err := c.do("POST", "/api/orgs", map[string]any{"name": name, "allowLocal": allowLocal}, &out) return &out, err } func (c *Client) DeleteOrg(id string) error { return c.do("DELETE", "/api/orgs/"+esc(id), nil, nil) } func (c *Client) State() (*State, error) { p, err := c.orgPath("/state") if err != nil { return nil, err } var out State return &out, c.do("GET", p, nil, &out) } // ---- edges ---- func (c *Client) Edges() ([]Edge, error) { var out []Edge return out, c.do("GET", "/api/edges", nil, &out) } func (c *Client) GetEdge(id string) (*Edge, error) { edges, err := c.Edges() if err != nil { return nil, err } for i := range edges { if edges[i].ID == id { return &edges[i], nil } } return nil, notFound("edge") } // CreateEdge needs a server key. The result carries the edge's token. func (c *Client) CreateEdge(e Edge) (*Edge, error) { var out Edge err := c.do("POST", "/api/edges", e, &out) return &out, err } func (c *Client) UpdateEdge(e Edge) (*Edge, error) { var out Edge err := c.do("PUT", "/api/edges/"+esc(e.ID), e, &out) return &out, err } func (c *Client) DeleteEdge(id string) error { return c.do("DELETE", "/api/edges/"+esc(id), nil, nil) } // ---- sites ---- func (c *Client) Sites() ([]Site, error) { st, err := c.State() if err != nil { return nil, err } return st.Sites, nil } func (c *Client) GetSite(id string) (*Site, error) { sites, err := c.Sites() if err != nil { return nil, err } for i := range sites { if sites[i].ID == id { return &sites[i], nil } } return nil, notFound("site") } // CreateSite returns the site including its agent token. func (c *Client) CreateSite(name string, tags []string) (*Site, error) { p, err := c.orgPath("/sites") if err != nil { return nil, err } var out Site if err := c.do("POST", p, map[string]string{"name": name}, &out); err != nil { return nil, err } if len(tags) > 0 { if err := c.UpdateSite(out.ID, name, tags); err != nil { return &out, err } out.Tags = tags } return &out, nil } func (c *Client) UpdateSite(id, name string, tags []string) error { p, err := c.orgPath("/sites/%s", esc(id)) if err != nil { return err } if tags == nil { tags = []string{} } return c.do("PUT", p, map[string]any{"name": name, "tags": tags}, nil) } func (c *Client) DeleteSite(id string) error { p, err := c.orgPath("/sites/%s", esc(id)) if err != nil { return err } return c.do("DELETE", p, nil, nil) } // ---- domains ---- func (c *Client) Domains() ([]Domain, error) { st, err := c.State() if err != nil { return nil, err } return st.Domains, nil } func (c *Client) GetDomain(id string) (*Domain, error) { ds, err := c.Domains() if err != nil { return nil, err } for i := range ds { if ds[i].ID == id { return &ds[i], nil } } return nil, notFound("domain") } func (c *Client) CreateDomain(d Domain) (*Domain, error) { p, err := c.orgPath("/domains") if err != nil { return nil, err } var out Domain return &out, c.do("POST", p, d, &out) } func (c *Client) DeleteDomain(id string) error { p, err := c.orgPath("/domains/%s", esc(id)) if err != nil { return err } return c.do("DELETE", p, nil, nil) } // ---- ports ---- func (c *Client) Ports() ([]Port, error) { st, err := c.State() if err != nil { return nil, err } return st.Mappings, nil } func (c *Client) GetPort(id string) (*Port, error) { ps, err := c.Ports() if err != nil { return nil, err } for i := range ps { if ps[i].ID == id { return &ps[i], nil } } return nil, notFound("port") } func (c *Client) CreatePort(pt Port) (*Port, error) { p, err := c.orgPath("/mappings") if err != nil { return nil, err } var out Port return &out, c.do("POST", p, pt, &out) } // UpdatePort replaces the port; every field is overwritten. func (c *Client) UpdatePort(pt Port) (*Port, error) { p, err := c.orgPath("/mappings/%s", esc(pt.ID)) if err != nil { return nil, err } var out Port return &out, c.do("PUT", p, pt, &out) } func (c *Client) DeletePort(id string) error { p, err := c.orgPath("/mappings/%s", esc(id)) if err != nil { return err } return c.do("DELETE", p, nil, nil) } // ---- alert channels (the organization's, or with server=true the server-level ones) ---- func (c *Client) alertPath(server bool, format string, args ...any) (string, error) { if server { return "/api/admin/alerts" + fmt.Sprintf(format, args...), nil } return c.orgPath("/alerts"+format, args...) } func (c *Client) Alerts(server bool) (*Alerts, error) { p, err := c.alertPath(server, "") if err != nil { return nil, err } var out Alerts return &out, c.do("GET", p, nil, &out) } func (c *Client) CreateChannel(server bool, ch Channel) (string, error) { p, err := c.alertPath(server, "/channels") if err != nil { return "", err } var out struct { ID string `json:"id"` } err = c.do("POST", p, ch, &out) return out.ID, err } func (c *Client) UpdateChannel(server bool, ch Channel) error { p, err := c.alertPath(server, "/channels/%s", esc(ch.ID)) if err != nil { return err } return c.do("PUT", p, ch, nil) } func (c *Client) DeleteChannel(server bool, id string) error { p, err := c.alertPath(server, "/channels/%s", esc(id)) if err != nil { return err } return c.do("DELETE", p, nil, nil) } func (c *Client) TestChannel(server bool, id string) error { p, err := c.alertPath(server, "/channels/%s/test", esc(id)) if err != nil { return err } return c.do("POST", p, nil, nil) } // CreateOrgKey returns the key's id and its secret token (shown once). func (c *Client) CreateOrgKey(name string) (id, key string, err error) { p, err := c.orgPath("/apikeys") if err != nil { return } var out struct { ID string `json:"id"` Key string `json:"key"` } err = c.do("POST", p, map[string]string{"name": name}, &out) return out.ID, out.Key, err }