package appupdate import ( "bytes" "context" "encoding/json" "errors" "fmt" "io" "net" "net/http" "time" "github.com/root-kdw12/hetzner-api-dyndns-records-webinterface/internal/updateprotocol" ) type AgentClient struct { socket string } func NewAgentClient(socket string) *AgentClient { return &AgentClient{socket: socket} } func (c *AgentClient) Start(ctx context.Context, request updateprotocol.Request) error { encoded, err := json.Marshal(request) if err != nil { return err } response, err := c.do(ctx, http.MethodPost, "/v1/update", bytes.NewReader(encoded)) if err != nil { return err } defer response.Body.Close() if response.StatusCode == http.StatusAccepted { return nil } if response.StatusCode == http.StatusConflict { return errors.New("ein Software-Update läuft bereits") } return fmt.Errorf("Update-Agent antwortet mit HTTP %d", response.StatusCode) } func (c *AgentClient) Status(ctx context.Context) (updateprotocol.Status, error) { response, err := c.do(ctx, http.MethodGet, "/v1/status", nil) if err != nil { return updateprotocol.Status{}, err } defer response.Body.Close() if response.StatusCode != http.StatusOK { return updateprotocol.Status{}, fmt.Errorf("Update-Agent antwortet mit HTTP %d", response.StatusCode) } var status updateprotocol.Status if err := json.NewDecoder(io.LimitReader(response.Body, 64<<10)).Decode(&status); err != nil { return updateprotocol.Status{}, fmt.Errorf("Status des Update-Agents lesen: %w", err) } return status, nil } func (c *AgentClient) do(ctx context.Context, method, path string, body io.Reader) (*http.Response, error) { if c == nil || c.socket == "" { return nil, errors.New("Update-Agent ist nicht konfiguriert") } transport := &http.Transport{ DisableKeepAlives: true, DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { dialer := net.Dialer{Timeout: time.Second} return dialer.DialContext(ctx, "unix", c.socket) }, } client := &http.Client{Transport: transport, Timeout: 3 * time.Second} request, err := http.NewRequestWithContext(ctx, method, "http://update-agent"+path, body) if err != nil { return nil, err } if body != nil { request.Header.Set("Content-Type", "application/json") } response, err := client.Do(request) if err != nil { return nil, errors.New("Update-Agent ist nicht erreichbar") } return response, nil }