Экспорт QUIK — отдельная служба bj-quikexport; модули, выделенные из ядра, ставятся с обновлением
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>
This commit is contained in:
@@ -95,13 +95,16 @@ func (u *Updater) CheckForUpdate(ctx context.Context) (UpdateStatus, error) {
|
||||
}
|
||||
st.Available, st.Notes = m.Version, m.Notes
|
||||
st.Components = release.Plan("", m, release.LoadInstalled(release.InstalledFile), BuildVersion)
|
||||
release.MarkSplitModules(st.Components, u.allowed)
|
||||
var upd []string
|
||||
avail := map[string]string{}
|
||||
for _, c := range st.Components {
|
||||
if c.Available != "" {
|
||||
avail[c.Name] = c.Available
|
||||
}
|
||||
if c.Update {
|
||||
if c.New {
|
||||
upd = append(upd, c.Name+" "+c.Available+" (установка модуля)")
|
||||
} else if c.Update {
|
||||
upd = append(upd, c.Name+" "+c.Available)
|
||||
}
|
||||
}
|
||||
@@ -150,6 +153,7 @@ func (u *Updater) ApplyUpdate(ctx context.Context, names []string) (string, erro
|
||||
return "", fmt.Errorf("манифест: %w", err)
|
||||
}
|
||||
plan := release.Plan("", m, release.LoadInstalled(release.InstalledFile), BuildVersion)
|
||||
release.MarkSplitModules(plan, u.allowed)
|
||||
want := map[string]bool{}
|
||||
for _, n := range names {
|
||||
want[n] = true
|
||||
@@ -167,6 +171,29 @@ func (u *Updater) ApplyUpdate(ctx context.Context, names []string) (string, erro
|
||||
if len(selected) == 0 {
|
||||
return "", fmt.Errorf("нечего обновлять: все установленные компоненты актуальны (релиз %s)", m.Version)
|
||||
}
|
||||
// Прежний root-установщик не умеет впервые ставить выделенные из ядра модули: пока он сам не
|
||||
// обновлён, такие модули откладываются — их поставит ensureSplitModules после перезапуска.
|
||||
installerOutdated := false
|
||||
for _, c := range plan {
|
||||
if c.Name == "bj-component-install" && c.Update {
|
||||
installerOutdated = true
|
||||
}
|
||||
}
|
||||
var deferred []string
|
||||
if installerOutdated {
|
||||
kept := selected[:0]
|
||||
for _, c := range selected {
|
||||
if c.New {
|
||||
deferred = append(deferred, c.Name)
|
||||
continue
|
||||
}
|
||||
kept = append(kept, c)
|
||||
}
|
||||
selected = kept
|
||||
if len(selected) == 0 {
|
||||
return "", fmt.Errorf("сначала обновите установщик обновлений (bj-component-install): текущий не ставит модули %s", strings.Join(deferred, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
cleanupStaging(24 * time.Hour)
|
||||
staging := filepath.Join(updateStagingDir, fmt.Sprintf("%d", time.Now().UnixNano()))
|
||||
@@ -180,6 +207,7 @@ func (u *Updater) ApplyUpdate(ctx context.Context, names []string) (string, erro
|
||||
var list []string
|
||||
var req struct {
|
||||
Names []string `json:"names"`
|
||||
New []string `json:"new,omitempty"`
|
||||
}
|
||||
for _, c := range selected {
|
||||
for _, a := range m.Artifacts {
|
||||
@@ -190,6 +218,9 @@ func (u *Updater) ApplyUpdate(ctx context.Context, names []string) (string, erro
|
||||
}
|
||||
}
|
||||
req.Names = append(req.Names, c.Name)
|
||||
if c.New {
|
||||
req.New = append(req.New, c.Name)
|
||||
}
|
||||
list = append(list, c.Name+" "+c.Available)
|
||||
}
|
||||
rb, _ := json.Marshal(req)
|
||||
@@ -212,9 +243,42 @@ func (u *Updater) ApplyUpdate(ctx context.Context, names []string) (string, erro
|
||||
}
|
||||
msg += "; перезапущены службы: " + strings.Join(units, ", ")
|
||||
}
|
||||
if len(deferred) > 0 {
|
||||
msg += "; модули " + strings.Join(deferred, ", ") + " будут установлены после перезапуска bj-server новым установщиком"
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// allowed — разрешён ли лицензией признак компонента.
|
||||
func (u *Updater) allowed(feature string) bool { return moduleAllowed(u.rc, feature) }
|
||||
|
||||
// ensureSplitModules — выделенные из ядра модули, которые входят в лицензию, но ещё не стоят на этом
|
||||
// сервере (например, ядро обновилось прежним установщиком), ставятся сами: без своих служб разделы
|
||||
// этих модулей в bj не работают. Раз за запуск bj-server; ошибки — только в журнал и «Последнюю проверку».
|
||||
func (u *Updater) ensureSplitModules(ctx context.Context) {
|
||||
var names []string
|
||||
for _, c := range release.Plan("", nil, release.LoadInstalled(release.InstalledFile), BuildVersion) {
|
||||
if c.FromCore && !c.Present && u.allowed(c.Feature) {
|
||||
names = append(names, c.Name)
|
||||
}
|
||||
}
|
||||
if len(names) == 0 {
|
||||
return
|
||||
}
|
||||
cctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
|
||||
defer cancel()
|
||||
msg, err := u.ApplyUpdate(cctx, names)
|
||||
if err != nil {
|
||||
msg = "Установка модулей " + strings.Join(names, ", ") + " не выполнена: " + err.Error()
|
||||
} else {
|
||||
msg = "Установка модулей: " + msg
|
||||
}
|
||||
log.Printf("lk-gateway: %s", msg)
|
||||
cfg := u.rc.Snapshot().Update
|
||||
cfg.LastResult, cfg.LastCheck = msg, time.Now().UTC()
|
||||
_ = u.rc.SaveUpdateSettings(cfg)
|
||||
}
|
||||
|
||||
// updateComponentRows — компоненты для раздела «Обновления» без обращения к артефактории:
|
||||
// установленное на этом сервере и версии из последней проверки.
|
||||
func updateComponentRows(rc *RuntimeConfig) ([]release.ComponentState, bool) {
|
||||
@@ -227,9 +291,12 @@ func updateComponentRows(rc *RuntimeConfig) ([]release.ComponentState, bool) {
|
||||
r.Update = r.Available != "" && (r.Present || r.Core) && (r.Installed == "" || release.IsNewer(r.Available, r.Installed))
|
||||
if r.Present || r.Core || r.Available != "" {
|
||||
out = append(out, r)
|
||||
any = any || r.Update
|
||||
}
|
||||
}
|
||||
release.MarkSplitModules(out, func(f string) bool { return moduleAllowed(rc, f) })
|
||||
for _, r := range out {
|
||||
any = any || r.Update
|
||||
}
|
||||
return out, any
|
||||
}
|
||||
|
||||
@@ -273,6 +340,7 @@ func (u *Updater) updateLoop(ctx context.Context) {
|
||||
return
|
||||
case <-time.After(time.Minute):
|
||||
cleanupStaging(time.Hour)
|
||||
u.ensureSplitModules(ctx)
|
||||
check()
|
||||
}
|
||||
for {
|
||||
|
||||
Reference in New Issue
Block a user