97e99b72c7
bj-quikexport (modules/quikexport + cmd/bj-quikexport, 127.0.0.1:8084): управление ARQA quikexport перенесено из bj-server. Настройки у службы в /var/lib/bj/.bj/quik-export/settings.json (при первом запуске переносятся из setup.json), раздел отдаётся фрагментом с индикатором меню, действия отвечают X-BJ-Flash. bj-server встраивает раздел в «Настройку», проксирует формы /admin/setup/quikexport/… и передаёт лицензию (X-BJ-Licensed). Общая проверка служебного ключа — modules/modkit (им пользуется и bj-npr), общее для прокси — lkgateway/modules.go. Выделенные из ядра модули (bj-npr, bj-quikexport: Component.FromCore) при обновлении ставятся и там, где их ещё нет, если входят в лицензию: release.MarkSplitModules, request.json "new", root-установщик ставит и включает unit-файл из комплекта. Если в обновлении меняется сам установщик, модули ставятся после перезапуска bj-server (ensureSplitModules). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
88 lines
3.2 KiB
Go
88 lines
3.2 KiB
Go
package release
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func writeComp(t *testing.T, root, name, body string) string {
|
|
t.Helper()
|
|
c, _ := ComponentByName(name)
|
|
p := c.PathAt(root)
|
|
if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(p, []byte(body), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sha, _, err := HashFile(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return sha
|
|
}
|
|
|
|
func state(states []ComponentState, name string) ComponentState {
|
|
for _, s := range states {
|
|
if s.Name == name {
|
|
return s
|
|
}
|
|
}
|
|
return ComponentState{}
|
|
}
|
|
|
|
func TestPlanIndependentVersions(t *testing.T) {
|
|
root := t.TempDir()
|
|
npr := writeComp(t, root, "bj-npr", "npr 1.0.0")
|
|
writeComp(t, root, "bj-server", "core old")
|
|
installed := map[string]Installed{
|
|
"bj-npr": {Version: "1.0.0", SHA256: npr},
|
|
"bj-server": {Version: "2.0.0", SHA256: "другой файл"},
|
|
}
|
|
m := &Manifest{Version: "2026.09.1", Artifacts: []Artifact{
|
|
{Name: "bj-server", Version: "2.1.0", SHA256: "new-core"},
|
|
{Name: "bj-npr", Version: "1.0.0", SHA256: npr},
|
|
{Name: "bj-quikexport", Version: "1.2.0", SHA256: "qe"},
|
|
}}
|
|
st := Plan(root, m, installed, "2.0.0")
|
|
|
|
if s := state(st, "bj-npr"); !s.Present || s.Installed != "1.0.0" || !s.SameFile || s.Update {
|
|
t.Fatalf("bj-npr актуален и не должен обновляться: %+v", s)
|
|
}
|
|
// Запись об ядре не совпала по sha — берётся версия работающего bj-server, релиз новее.
|
|
if s := state(st, "bj-server"); s.Installed != "2.0.0" || s.Available != "2.1.0" || !s.Update {
|
|
t.Fatalf("ядро должно обновиться до 2.1.0: %+v", s)
|
|
}
|
|
// Модуль не установлен на этом сервере — не ставим.
|
|
if s := state(st, "bj-quikexport"); s.Present || s.Update {
|
|
t.Fatalf("неустановленный модуль не должен предлагаться: %+v", s)
|
|
}
|
|
// Старая версия в релизе не предлагается (без отката).
|
|
m.Artifacts[1] = Artifact{Name: "bj-npr", Version: "0.9.0", SHA256: "old"}
|
|
if s := state(Plan(root, m, installed, "2.0.0"), "bj-npr"); s.Update {
|
|
t.Fatalf("откат на 0.9.0 не должен предлагаться: %+v", s)
|
|
}
|
|
}
|
|
|
|
func TestSplitModulesInstalledWithCore(t *testing.T) {
|
|
root := t.TempDir()
|
|
writeComp(t, root, "bj-server", "core")
|
|
m := &Manifest{Version: "2026.09.2", Artifacts: []Artifact{
|
|
{Name: "bj-npr", Version: "0.1.0", SHA256: "n"},
|
|
{Name: "bj-quikexport", Version: "0.1.0", SHA256: "q"},
|
|
{Name: "bj-lk", Version: "0.2.0", SHA256: "l"},
|
|
}}
|
|
st := Plan(root, m, nil, "2.0.0")
|
|
MarkSplitModules(st, func(f string) bool { return f == "npr" || f == "web-cabinet" })
|
|
if s := state(st, "bj-npr"); !s.Update || !s.New {
|
|
t.Fatalf("выделенный из ядра модуль по лицензии должен ставиться: %+v", s)
|
|
}
|
|
if s := state(st, "bj-quikexport"); s.Update || s.New {
|
|
t.Fatalf("модуль без лицензии не ставится: %+v", s)
|
|
}
|
|
if s := state(st, "bj-lk"); s.Update || s.New {
|
|
t.Fatalf("самостоятельный модуль обновлением не ставится: %+v", s)
|
|
}
|
|
}
|