Агенты подхватывают изменения с сервера: каталог и самообновление
CI / test (push) Successful in 1m29s
CI / test (push) Successful in 1m29s
- сервер отдаёт агенту итоговый каталог (встроенный каталог сервера + переопределения клиента); если каталог не подходит версии агента — встроенный каталог агента и предупреждение - самообновление перед бэкапом: версия сервера новее → скачивание с того же сервера (только /dl/...), проверка sha256 и запуска новой версии, подмена с откатом, перезапуск через exec; при ошибке бэкап идёт текущей версией - галочка «Автообновление» у клиента (по умолчанию включена), версия агента в списке и карточке, отставшие подсвечены; версия сервера в шапке - миграция существующей базы: колонки auto_update и agent_version - backupctl backup --no-update Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1947b26913
commit
488abc2d34
21 files changed
+674
-51
No files matched your search
+45
-3
@@ -9,6 +9,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -17,8 +18,20 @@ import (
|
||||
|
||||
type AgentConfig struct {
|
||||
Domain string `json:"domain"`
|
||||
ConfigYAML string `json:"config_yaml"`
|
||||
ConfigYAML string `json:"config_yaml"` // только переопределения клиента (для старых агентов)
|
||||
HeavyDue bool `json:"heavy_due"`
|
||||
// CatalogYAML — итоговый каталог: встроенный каталог сервера + переопределения клиента.
|
||||
// Агент берёт его вместо своего встроенного, поэтому новые категории приходят без обновления агента.
|
||||
CatalogYAML string `json:"catalog_yaml,omitempty"`
|
||||
ServerVersion string `json:"server_version,omitempty"`
|
||||
Update *AgentUpdate `json:"update,omitempty"` // есть, если агенту пора обновиться
|
||||
}
|
||||
|
||||
// AgentUpdate — новая версия агента. Path — путь на том же сервере (/dl/...), чужие адреса агент не принимает.
|
||||
type AgentUpdate struct {
|
||||
Version string `json:"version"`
|
||||
Path string `json:"path"`
|
||||
SHA256 string `json:"sha256"`
|
||||
}
|
||||
|
||||
type PartInfo struct {
|
||||
@@ -100,9 +113,38 @@ func jsonBody(v any) io.Reader {
|
||||
return bytes.NewReader(data)
|
||||
}
|
||||
|
||||
func (c *Client) AgentConfig(ctx context.Context) (*AgentConfig, error) {
|
||||
// AgentConfig запрашивает настройки агента; arch и version нужны серверу, чтобы предложить обновление.
|
||||
func (c *Client) AgentConfig(ctx context.Context, arch, version string) (*AgentConfig, error) {
|
||||
var out AgentConfig
|
||||
return &out, c.do(ctx, http.MethodGet, "/api/v1/agent/config", nil, &out)
|
||||
q := url.Values{}
|
||||
if arch != "" {
|
||||
q.Set("arch", arch)
|
||||
}
|
||||
if version != "" {
|
||||
q.Set("version", version)
|
||||
}
|
||||
path := "/api/v1/agent/config"
|
||||
if len(q) > 0 {
|
||||
path += "?" + q.Encode()
|
||||
}
|
||||
return &out, c.do(ctx, http.MethodGet, path, nil, &out)
|
||||
}
|
||||
|
||||
// Download открывает поток файла с этого же сервера (path вида /dl/...).
|
||||
func (c *Client) Download(ctx context.Context, path string) (io.ReadCloser, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.Server+path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := c.HTTP.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
resp.Body.Close()
|
||||
return nil, &Error{Status: resp.StatusCode, Msg: resp.Status}
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateBackup(ctx context.Context, m *manifest.Manifest) (int64, error) {
|
||||
|
||||
Reference in new issue
Block a user