hhctl CLI and Terraform provider for Hammerhead
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
bf340cdab4
19 files changed
+2442
No files matched your search
@@ -0,0 +1,287 @@
|
||||
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
|
||||
}
|
||||
Reference in new issue
Block a user