diff --git a/cmd/bj-installer/main.go b/cmd/bj-installer/main.go index 36ff6d2..7623d6b 100644 --- a/cmd/bj-installer/main.go +++ b/cmd/bj-installer/main.go @@ -634,7 +634,12 @@ func (in *installer) componentsFromBundle() (string, error) { default: src := filepath.Join(in.bundle, art.File) if _, err := os.Stat(src); err != nil { - return "", fmt.Errorf("в релизе нет файла %s", art.File) + if c.Name == "bj-server" { + return "", fmt.Errorf("в релизе нет файла %s", art.File) + } + // в образ кладётся не всё: недостающее поставит первое обновление после ввода ключа + skipped = append(skipped, c.Title+" (поставится обновлением)") + continue } body, err := os.ReadFile(src) if err != nil { diff --git a/deploy/iso/build-iso-ubuntu.sh b/deploy/iso/build-iso-ubuntu.sh index 6471743..ce1d14b 100755 --- a/deploy/iso/build-iso-ubuntu.sh +++ b/deploy/iso/build-iso-ubuntu.sh @@ -31,7 +31,7 @@ echo "$CHANNEL" > "$WORK/bj/channel"; echo "$VERSION" > "$WORK/bj/version" # ядро bj: подписанный манифест + bj-server, bj-component-install [ -s "$BUNDLE/manifest.json" ] || { echo "в $BUNDLE нет manifest.json"; exit 1; } cp "$BUNDLE/manifest.json" "$WORK/bj/bundle/" -FILES=$(python3 -c 'import json,sys,base64;s=json.load(open(sys.argv[1]));m=json.loads(base64.b64decode(s["payload"]));print(" ".join(a["file"] for a in m["artifacts"] if a["name"] in ("bj-server","bj-component-install")))' "$BUNDLE/manifest.json") +FILES=$(python3 -c 'import json,sys,base64;s=json.load(open(sys.argv[1]));m=json.loads(base64.b64decode(s["payload"]));print(" ".join(a["file"] for a in m["artifacts"] if a["name"] in ("bj-server","bj-component-install","bj-installer","crypto-service.jar")))' "$BUNDLE/manifest.json") [ -n "$FILES" ] || { echo "в релизе нет компонентов ядра"; exit 1; } for f in $FILES; do cp "$BUNDLE/$f" "$WORK/bj/bundle/"; done diff --git a/internal/lkgateway/setup.go b/internal/lkgateway/setup.go index dab39bf..4209fd9 100644 --- a/internal/lkgateway/setup.go +++ b/internal/lkgateway/setup.go @@ -238,30 +238,21 @@ func (h *setupHandlers) renderWizard(w http.ResponseWriter, r *http.Request) { d.Done.NSD = s.NSD.IGWBaseURL != "" && s.NSD.Profile != "" d.Done.TestRun = s.LastTest != nil || (!d.DevMode && d.Done.NSD) // вне режима разработки тестовой заявки нет - // Определяем текущий шаг. - step := 1 + // Мастер идёт по порядку: каждый шаг показывается, даже если он уже выполнен (установщиком, + // лицензией) — на нём написано, что сделано, и пользователь сам нажимает «Далее». Без ?step + // продолжаем со следующего за последним пройденным шагом. + progress := wizardProgress() + step := progress + 1 if v := r.URL.Query().Get("step"); v != "" { if n, err := strconv.Atoi(v); err == nil && n >= 1 && n <= 7 { step = n + if n-1 > progress { + setWizardProgress(n - 1) + } } - } else { - // Авто: первый незавершённый. - switch { - case !d.Done.License: - step = 1 - case !d.Done.Postgres: - step = 2 - case !d.Done.Depo: - step = 3 - case !d.Done.Crypto: - step = 4 - case !d.Done.Certs: - step = 5 - case !d.Done.NSD: - step = 6 - default: - step = 7 - } + } + if step > 7 { + step = 7 } d.Step = step if step == 1 && d.Done.License { @@ -273,35 +264,26 @@ func (h *setupHandlers) renderWizard(w http.ResponseWriter, r *http.Request) { } cancel() } - d.AutoDone = wizardAutoDone(&d) render(w, h.tpl.a.wizard, d) } -// wizardAutoDone — пояснения к шагам до текущего, которые уже выполнены: мастер переходит к первому -// незавершённому шагу сам, и без пояснения непонятно, почему предыдущие отмечены галочкой. -func wizardAutoDone(d *WizardData) []string { - var out []string - if d.Step > 1 && d.Done.License { - out = append(out, "1. Лицензия — активирована: "+d.Lic.Tenant+".") +// wizardProgressFile — номер последнего пройденного шага мастера (переход «Далее» на шаг N +// означает, что шаги до N пройдены). +const wizardProgressFile = "/var/lib/bj/.bj/wizard-progress" + +func wizardProgress() int { + b, err := os.ReadFile(wizardProgressFile) + if err != nil { + return 0 } - if d.Step > 2 && d.Done.Postgres { - t := "2. База bj — готова" - if d.PGSummary != "" { - t += " (" + d.PGSummary + ")" - } - out = append(out, t+": её создал установщик, настраивать ничего не нужно.") + n, _ := strconv.Atoi(strings.TrimSpace(string(b))) + return n +} + +func setWizardProgress(n int) { + if err := os.WriteFile(wizardProgressFile, []byte(strconv.Itoa(n)+"\n"), 0o600); err != nil { + log.Printf("wizard: прогресс мастера не сохранён: %v", err) } - if d.Step > 3 && d.Done.Depo { - if !d.DepoLicensed { - out = append(out, "3. Учёт DEPO — не нужен: модуль обмена с DEPO и QUIK не входит в лицензию. Когда модуль добавят, шаг станет доступен.") - } else { - out = append(out, "3. Учёт DEPO — подключение уже сохранено ("+d.Settings.Fancy.Server+").") - } - } - if d.Step > 4 && d.Done.Crypto && d.ValidataVer != "" { - out = append(out, "4. Валидата — установлена вместе с bj (версия "+d.ValidataVer+").") - } - return out } // dsnSummary — «host:port, база name» из строки подключения PostgreSQL, без логина и пароля. diff --git a/internal/lkgateway/web/templates/admin_wizard.html b/internal/lkgateway/web/templates/admin_wizard.html index 3f62de2..db80274 100644 --- a/internal/lkgateway/web/templates/admin_wizard.html +++ b/internal/lkgateway/web/templates/admin_wizard.html @@ -41,11 +41,7 @@
Уже готово — эти шаги пропущены, делать там ничего не нужно:
- {{range .AutoDone}}✓ {{.}}
{{end}} -Открыть любой шаг можно кнопками «← К шагу» внизу.
-✓ Лицензия активна: {{.Lic.Tenant}}, план {{.Lic.Plan}}, модули: {{if .Lic.Features}}{{range $i, $f := .Lic.Features}}{{if $i}}, {{end}}{{$f}}{{end}}{{else}}только ядро{{end}}; {{.Lic.Message}}
{{end}} {{with .Update}}{{if .HasUpdate}}Есть обновление: версия {{.Available}}
+На сервере лицензий есть что поставить (выпуск {{.Available}})
Образ установил ту версию bj, с которой был собран. На сервере лицензий есть более новая — с исправлениями ядра, установщика и служб. Поставьте её сейчас, до настройки: bj перезапустится примерно на 10 секунд, затем обновите страницу.
{{.Message}}