homelab/services/games-console/cli/api/client.go
Dan V deb6c38d7b chore: commit homelab setup — deployment, services, orchestration, skill
- Add .gitignore: exclude compiled binaries, build artifacts, and Helm
  values files containing real secrets (authentik, prometheus)
- Add all Kubernetes deployment manifests (deployment/)
- Add services source code: ha-sync, device-inventory, games-console,
  paperclip, parts-inventory
- Add Ansible orchestration: playbooks, roles, inventory, cloud-init
- Add hardware specs, execution plans, scripts, HOMELAB.md
- Add skills/homelab/SKILL.md + skills/install.sh to preserve Copilot skill
- Remove previously-tracked inventory-cli binary from git index

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-09 08:10:32 +02:00

159 lines
4.1 KiB
Go

package api
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
// Server mirrors the backend Server type.
type Server struct {
Name string `json:"name"`
Type string `json:"type"`
Image string `json:"image"`
Replicas int32 `json:"replicas"`
Ready int32 `json:"ready"`
Status string `json:"status"`
NodePort int32 `json:"nodePort,omitempty"`
Port int32 `json:"port"`
EnvVars map[string]string `json:"envVars"`
CreatedAt string `json:"createdAt"`
}
type CreateServerRequest struct {
Name string `json:"name"`
Type string `json:"type"`
Image string `json:"image"`
Port int32 `json:"port"`
NodePort int32 `json:"nodePort,omitempty"`
EnvVars map[string]string `json:"envVars"`
}
type UpdateServerRequest struct {
Image string `json:"image,omitempty"`
EnvVars map[string]string `json:"envVars,omitempty"`
}
// Client is an HTTP client for the games-console backend.
type Client struct {
BaseURL string
http *http.Client
}
func NewClient(baseURL string) *Client {
return &Client{BaseURL: baseURL, http: &http.Client{}}
}
func (c *Client) ListServers() ([]Server, error) {
var servers []Server
return servers, c.get("/api/servers", &servers)
}
func (c *Client) GetServer(name string) (*Server, error) {
var s Server
return &s, c.get("/api/servers/"+name, &s)
}
func (c *Client) CreateServer(req CreateServerRequest) (*Server, error) {
var s Server
return &s, c.post("/api/servers", req, &s)
}
func (c *Client) UpdateServer(name string, req UpdateServerRequest) (*Server, error) {
var s Server
return &s, c.put("/api/servers/"+name, req, &s)
}
func (c *Client) DeleteServer(name string) error {
return c.delete("/api/servers/" + name)
}
func (c *Client) GetLogs(name string, lines int) (string, error) {
var resp struct {
Logs string `json:"logs"`
}
return resp.Logs, c.get(fmt.Sprintf("/api/servers/%s/logs?lines=%d", name, lines), &resp)
}
func (c *Client) GetHealth(name string) (map[string]interface{}, error) {
var resp map[string]interface{}
return resp, c.get("/api/servers/"+name+"/health", &resp)
}
func (c *Client) Start(name string) error {
return c.postAction("/api/servers/" + name + "/start")
}
func (c *Client) Stop(name string) error {
return c.postAction("/api/servers/" + name + "/stop")
}
func (c *Client) Restart(name string) error {
return c.postAction("/api/servers/" + name + "/restart")
}
// --- HTTP helpers ---
func (c *Client) get(path string, out interface{}) error {
resp, err := c.http.Get(c.BaseURL + path)
if err != nil {
return err
}
return decode(resp, out)
}
func (c *Client) post(path string, body interface{}, out interface{}) error {
b, _ := json.Marshal(body)
resp, err := c.http.Post(c.BaseURL+path, "application/json", bytes.NewReader(b))
if err != nil {
return err
}
return decode(resp, out)
}
func (c *Client) postAction(path string) error {
resp, err := c.http.Post(c.BaseURL+path, "application/json", nil)
if err != nil {
return err
}
resp.Body.Close()
if resp.StatusCode >= 400 {
return fmt.Errorf("server returned %d", resp.StatusCode)
}
return nil
}
func (c *Client) put(path string, body interface{}, out interface{}) error {
b, _ := json.Marshal(body)
req, _ := http.NewRequest(http.MethodPut, c.BaseURL+path, bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
resp, err := c.http.Do(req)
if err != nil {
return err
}
return decode(resp, out)
}
func (c *Client) delete(path string) error {
req, _ := http.NewRequest(http.MethodDelete, c.BaseURL+path, nil)
resp, err := c.http.Do(req)
if err != nil {
return err
}
resp.Body.Close()
if resp.StatusCode >= 400 {
return fmt.Errorf("server returned %d", resp.StatusCode)
}
return nil
}
func decode(resp *http.Response, out interface{}) error {
defer resp.Body.Close()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("server error %d: %s", resp.StatusCode, string(body))
}
return json.NewDecoder(resp.Body).Decode(out)
}