feat: add Go SDK package (REST client + VL1 agent + TAP device)
This commit is contained in:
210
sdk/api.go
Normal file
210
sdk/api.go
Normal file
@@ -0,0 +1,210 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (c *Client) doReq(method, path string, body, out interface{}) error {
|
||||
url := strings.TrimRight(c.cfg.ControllerURL, "/") + path
|
||||
var r io.Reader
|
||||
if body != nil {
|
||||
data, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal body: %w", err)
|
||||
}
|
||||
r = bytes.NewReader(data)
|
||||
}
|
||||
req, err := http.NewRequest(method, url, r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create request: %w", err)
|
||||
}
|
||||
if c.cfg.Token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.cfg.Token)
|
||||
}
|
||||
if r != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
resp, err := c.httpc.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("do request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read response: %w", err)
|
||||
}
|
||||
if resp.StatusCode >= 400 {
|
||||
var errResp struct{ Error string `json:"error"` }
|
||||
if json.Unmarshal(respData, &errResp) == nil && errResp.Error != "" {
|
||||
return fmt.Errorf("%s", errResp.Error)
|
||||
}
|
||||
return fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(respData))
|
||||
}
|
||||
if out != nil {
|
||||
if err := json.Unmarshal(respData, out); err != nil {
|
||||
return fmt.Errorf("unmarshal response: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Login(username, password string) error {
|
||||
var resp AuthResponse
|
||||
if err := c.doReq("POST", "/api/v1/auth/login", map[string]string{
|
||||
"username": username,
|
||||
"password": password,
|
||||
}, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
c.cfg.Token = resp.Token
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Register(username, password string) (*User, error) {
|
||||
var resp AuthResponse
|
||||
if err := c.doReq("POST", "/api/v1/auth/register", map[string]string{
|
||||
"username": username,
|
||||
"password": password,
|
||||
}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.cfg.Token = resp.Token
|
||||
return resp.User, nil
|
||||
}
|
||||
|
||||
func (c *Client) InitAdmin(username, password string) (*User, error) {
|
||||
var resp AuthResponse
|
||||
if err := c.doReq("POST", "/api/v1/auth/init", map[string]string{
|
||||
"username": username,
|
||||
"password": password,
|
||||
}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.cfg.Token = resp.Token
|
||||
return resp.User, nil
|
||||
}
|
||||
|
||||
func (c *Client) CheckAdmin() (bool, error) {
|
||||
var resp struct{ AdminExists bool `json:"admin_exists"` }
|
||||
if err := c.doReq("GET", "/api/v1/admin/check", nil, &resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return resp.AdminExists, nil
|
||||
}
|
||||
|
||||
func (c *Client) Dashboard() (*DashboardStats, error) {
|
||||
var stats DashboardStats
|
||||
if err := c.doReq("GET", "/api/v1/dashboard", nil, &stats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &stats, nil
|
||||
}
|
||||
|
||||
func (c *Client) AdminDashboard() (*DashboardStats, error) {
|
||||
var stats DashboardStats
|
||||
if err := c.doReq("GET", "/api/v1/admin/dashboard", nil, &stats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &stats, nil
|
||||
}
|
||||
|
||||
func (c *Client) Profile() (*ProfileResponse, error) {
|
||||
var resp ProfileResponse
|
||||
if err := c.doReq("GET", "/api/v1/user/profile", nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateNetwork(name, ipRange string) (*Network, error) {
|
||||
body := map[string]string{"name": name}
|
||||
if ipRange != "" {
|
||||
body["ip_range"] = ipRange
|
||||
}
|
||||
var resp struct{ Network *Network `json:"network"` }
|
||||
if err := c.doReq("POST", "/api/v1/network/create", body, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Network, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListNetworks() ([]Network, error) {
|
||||
var resp NetworkListResponse
|
||||
if err := c.doReq("GET", "/api/v1/network/list", nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Networks, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetNetwork(id uint32) (*Network, error) {
|
||||
var resp struct{ Network *Network `json:"network"` }
|
||||
if err := c.doReq("GET", fmt.Sprintf("/api/v1/network/%d", id), nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Network, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteNetwork(id uint32) error {
|
||||
return c.doReq("DELETE", fmt.Sprintf("/api/v1/network/%d", id), nil, nil)
|
||||
}
|
||||
|
||||
func (c *Client) NetworkMembers(id uint32) ([]NetworkMember, error) {
|
||||
var resp MembersResponse
|
||||
if err := c.doReq("GET", fmt.Sprintf("/api/v1/network/%d/members", id), nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Members, nil
|
||||
}
|
||||
|
||||
func (c *Client) AuthorizeMember(networkID uint32, nodeID string) error {
|
||||
return c.doReq("POST", fmt.Sprintf("/api/v1/network/%d/authorize", networkID),
|
||||
map[string]string{"node_id": nodeID}, nil)
|
||||
}
|
||||
|
||||
func (c *Client) DeauthorizeMember(networkID uint32, nodeID string) error {
|
||||
return c.doReq("POST", fmt.Sprintf("/api/v1/network/%d/deauthorize", networkID),
|
||||
map[string]string{"node_id": nodeID}, nil)
|
||||
}
|
||||
|
||||
func (c *Client) RegisterNode(nodeID, publicKey, name, ipAddr string, port int, version string) (*Node, error) {
|
||||
body := map[string]interface{}{
|
||||
"node_id": nodeID,
|
||||
"public_key": publicKey,
|
||||
"name": name,
|
||||
}
|
||||
if ipAddr != "" {
|
||||
body["ip_address"] = ipAddr
|
||||
}
|
||||
if port > 0 {
|
||||
body["port"] = port
|
||||
}
|
||||
if version != "" {
|
||||
body["version"] = version
|
||||
}
|
||||
var resp struct{ Node *Node `json:"node"` }
|
||||
if err := c.doReq("POST", "/api/v1/node/register", body, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Node, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListNodes() ([]Node, error) {
|
||||
var resp NodeListResponse
|
||||
if err := c.doReq("GET", "/api/v1/node/list", nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Nodes, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListOnlineNodes() ([]Node, error) {
|
||||
var resp NodeListResponse
|
||||
if err := c.doReq("GET", "/api/v1/node/online", nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Nodes, nil
|
||||
}
|
||||
Reference in New Issue
Block a user