85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
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
|
|
}
|