fix: platform-specific placeholder in agent update log modal (v0.5.13)
Windows WinRM updates no longer show the Linux /var/log/update_script.log hint while output is still empty.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
|
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
|
||||||
|
|
||||||
APP_NAME = "Security Alert Center"
|
APP_NAME = "Security Alert Center"
|
||||||
APP_VERSION = "0.5.12"
|
APP_VERSION = "0.5.13"
|
||||||
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
|
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
|
||||||
|
|||||||
@@ -67,8 +67,6 @@ import { fetchHostRemoteJob, type HostRemoteActionJobStatus } from "../api";
|
|||||||
|
|
||||||
const LOG_POLL_MS = 1500;
|
const LOG_POLL_MS = 1500;
|
||||||
const AUTO_CLOSE_MS = 30_000;
|
const AUTO_CLOSE_MS = 30_000;
|
||||||
const PLACEHOLDER =
|
|
||||||
"Ожидание лога с хоста…\n(обновление /var/log/update_script.log)";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
hostId: number;
|
hostId: number;
|
||||||
@@ -78,6 +76,7 @@ const props = defineProps<{
|
|||||||
ok: boolean | null;
|
ok: boolean | null;
|
||||||
message: string;
|
message: string;
|
||||||
output: string;
|
output: string;
|
||||||
|
logPlaceholder: string;
|
||||||
logVisible: boolean;
|
logVisible: boolean;
|
||||||
sessionStartedAt: string;
|
sessionStartedAt: string;
|
||||||
}>();
|
}>();
|
||||||
@@ -135,7 +134,7 @@ const displayMessage = computed(() => {
|
|||||||
|
|
||||||
const displayOutput = computed(() => {
|
const displayOutput = computed(() => {
|
||||||
const text = (polledOutput.value || props.output).trim();
|
const text = (polledOutput.value || props.output).trim();
|
||||||
return text || PLACEHOLDER;
|
return text || props.logPlaceholder;
|
||||||
});
|
});
|
||||||
|
|
||||||
function stopPoll() {
|
function stopPoll() {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
:ok="entry.ok"
|
:ok="entry.ok"
|
||||||
:message="entry.message"
|
:message="entry.message"
|
||||||
:output="entry.output"
|
:output="entry.output"
|
||||||
|
:log-placeholder="entry.logPlaceholder"
|
||||||
:log-visible="entry.logVisible"
|
:log-visible="entry.logVisible"
|
||||||
:session-started-at="entry.sessionStartedAt"
|
:session-started-at="entry.sessionStartedAt"
|
||||||
@close="closeHostRemoteActionLog(entry.id)"
|
@close="closeHostRemoteActionLog(entry.id)"
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export type HostRemoteActionLogEntry = {
|
|||||||
title: string;
|
title: string;
|
||||||
message: string;
|
message: string;
|
||||||
output: string;
|
output: string;
|
||||||
|
/** Текст в окне лога, пока output с сервера ещё пустой */
|
||||||
|
logPlaceholder: string;
|
||||||
/** ISO-время открытия окна — отсекаем stale success от прошлого job */
|
/** ISO-время открытия окна — отсекаем stale success от прошлого job */
|
||||||
sessionStartedAt: string;
|
sessionStartedAt: string;
|
||||||
};
|
};
|
||||||
@@ -189,6 +191,7 @@ async function executeRemoteAction(
|
|||||||
export async function pollHostRemoteAction(
|
export async function pollHostRemoteAction(
|
||||||
hostId: number,
|
hostId: number,
|
||||||
title: string,
|
title: string,
|
||||||
|
logPlaceholder?: string,
|
||||||
): Promise<HostRemoteActionJobStatus | null> {
|
): Promise<HostRemoteActionJobStatus | null> {
|
||||||
const existingPromise = hostRunningPromises.get(hostId);
|
const existingPromise = hostRunningPromises.get(hostId);
|
||||||
if (existingPromise) {
|
if (existingPromise) {
|
||||||
@@ -209,6 +212,7 @@ export async function pollHostRemoteAction(
|
|||||||
title,
|
title,
|
||||||
message: "Выполняется на удалённом хосте…",
|
message: "Выполняется на удалённом хосте…",
|
||||||
output: "",
|
output: "",
|
||||||
|
logPlaceholder: logPlaceholder || "Ожидание лога с хоста…",
|
||||||
sessionStartedAt: new Date().toISOString(),
|
sessionStartedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
hostRemoteActionLogs.push(entry);
|
hostRemoteActionLogs.push(entry);
|
||||||
@@ -240,6 +244,7 @@ export async function runHostRemoteAction(
|
|||||||
hostId: number,
|
hostId: number,
|
||||||
title: string,
|
title: string,
|
||||||
kind: HostRemoteActionKind,
|
kind: HostRemoteActionKind,
|
||||||
|
logPlaceholder?: string,
|
||||||
): Promise<HostRemoteActionJobStatus | null> {
|
): Promise<HostRemoteActionJobStatus | null> {
|
||||||
const existingPromise = hostRunningPromises.get(hostId);
|
const existingPromise = hostRunningPromises.get(hostId);
|
||||||
if (existingPromise) {
|
if (existingPromise) {
|
||||||
@@ -260,6 +265,7 @@ export async function runHostRemoteAction(
|
|||||||
title,
|
title,
|
||||||
message: "Запуск на сервере SAC…",
|
message: "Запуск на сервере SAC…",
|
||||||
output: "",
|
output: "",
|
||||||
|
logPlaceholder: logPlaceholder || "Ожидание лога с хоста…",
|
||||||
sessionStartedAt: new Date().toISOString(),
|
sessionStartedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
hostRemoteActionLogs.push(entry);
|
hostRemoteActionLogs.push(entry);
|
||||||
|
|||||||
@@ -58,3 +58,37 @@ export function remoteActionTitleForHost(host: HostSummary): string {
|
|||||||
}
|
}
|
||||||
return `Обновление ssh-monitor (SSH): ${label}`;
|
return `Обновление ssh-monitor (SSH): ${label}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LOG_PLACEHOLDER_SSH_UPDATE =
|
||||||
|
"Ожидание лога с хоста…\n(обновление /var/log/update_script.log)";
|
||||||
|
|
||||||
|
const LOG_PLACEHOLDER_WINRM =
|
||||||
|
"Ожидание вывода с хоста…\n(WinRM: Deploy-LoginMonitor.ps1)";
|
||||||
|
|
||||||
|
const LOG_PLACEHOLDER_GENERIC = "Ожидание лога с хоста…";
|
||||||
|
|
||||||
|
export function remoteActionLogPlaceholder(
|
||||||
|
host: Pick<HostSummary, "os_family" | "product"> | null | undefined,
|
||||||
|
kind: HostRemoteActionKind | null,
|
||||||
|
): string {
|
||||||
|
if (kind === "ssh-update") {
|
||||||
|
return LOG_PLACEHOLDER_SSH_UPDATE;
|
||||||
|
}
|
||||||
|
if (host && isWindowsAgentHost(host)) {
|
||||||
|
return LOG_PLACEHOLDER_WINRM;
|
||||||
|
}
|
||||||
|
if (kind === "fallback") {
|
||||||
|
return LOG_PLACEHOLDER_SSH_UPDATE;
|
||||||
|
}
|
||||||
|
return LOG_PLACEHOLDER_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function remoteActionLogPlaceholderFromTitle(title: string): string {
|
||||||
|
if (/winrm/i.test(title)) {
|
||||||
|
return LOG_PLACEHOLDER_WINRM;
|
||||||
|
}
|
||||||
|
if (/ssh-monitor|\/var\/log\/update_script/i.test(title)) {
|
||||||
|
return LOG_PLACEHOLDER_SSH_UPDATE;
|
||||||
|
}
|
||||||
|
return LOG_PLACEHOLDER_GENERIC;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
|
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
|
||||||
export const APP_NAME = "Security Alert Center";
|
export const APP_NAME = "Security Alert Center";
|
||||||
export const APP_VERSION = "0.5.12";
|
export const APP_VERSION = "0.5.13";
|
||||||
export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;
|
export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
isLinuxAgentHost,
|
isLinuxAgentHost,
|
||||||
remoteActionKindForHost,
|
remoteActionKindForHost,
|
||||||
|
remoteActionLogPlaceholder,
|
||||||
remoteActionTitleForHost,
|
remoteActionTitleForHost,
|
||||||
type AgentGitVersions,
|
type AgentGitVersions,
|
||||||
} from "../utils/hostAgentUpgrade";
|
} from "../utils/hostAgentUpgrade";
|
||||||
@@ -638,7 +639,7 @@ async function runRequestAgentUpdate() {
|
|||||||
async function runAgentFallback() {
|
async function runAgentFallback() {
|
||||||
agentControlMessage.value = "";
|
agentControlMessage.value = "";
|
||||||
const title = isWindowsHost.value ? "Обновление через WinRM" : "Fallback SSH (ssh-monitor)";
|
const title = isWindowsHost.value ? "Обновление через WinRM" : "Fallback SSH (ssh-monitor)";
|
||||||
const job = await runHostRemoteAction(hostId.value, title, "fallback");
|
const job = await runHostRemoteAction(hostId.value, title, "fallback", remoteActionLogPlaceholder(host.value, "fallback"));
|
||||||
if (job) {
|
if (job) {
|
||||||
agentControlOk.value = job.ok ?? false;
|
agentControlOk.value = job.ok ?? false;
|
||||||
if (job.ok) {
|
if (job.ok) {
|
||||||
@@ -706,6 +707,7 @@ async function runAgentUpdate() {
|
|||||||
hostId.value,
|
hostId.value,
|
||||||
"Обновление ssh-monitor (SSH)",
|
"Обновление ssh-monitor (SSH)",
|
||||||
"ssh-update",
|
"ssh-update",
|
||||||
|
remoteActionLogPlaceholder(host.value, "ssh-update"),
|
||||||
);
|
);
|
||||||
if (job?.ok) {
|
if (job?.ok) {
|
||||||
const detail = await fetchHost(hostId.value);
|
const detail = await fetchHost(hostId.value);
|
||||||
@@ -728,6 +730,7 @@ async function runAgentUpgradeFromCell() {
|
|||||||
hostId.value,
|
hostId.value,
|
||||||
remoteActionTitleForHost(host.value),
|
remoteActionTitleForHost(host.value),
|
||||||
kind,
|
kind,
|
||||||
|
remoteActionLogPlaceholder(host.value, kind),
|
||||||
);
|
);
|
||||||
if (job?.ok) {
|
if (job?.ok) {
|
||||||
const detail = await fetchHost(hostId.value);
|
const detail = await fetchHost(hostId.value);
|
||||||
|
|||||||
@@ -135,6 +135,8 @@ import { isAgentVersionOutdated } from "../utils/agentVersion";
|
|||||||
import {
|
import {
|
||||||
isGitAgentUpgradeAvailable,
|
isGitAgentUpgradeAvailable,
|
||||||
remoteActionKindForHost,
|
remoteActionKindForHost,
|
||||||
|
remoteActionLogPlaceholder,
|
||||||
|
remoteActionLogPlaceholderFromTitle,
|
||||||
remoteActionTitleForHost,
|
remoteActionTitleForHost,
|
||||||
} from "../utils/hostAgentUpgrade";
|
} from "../utils/hostAgentUpgrade";
|
||||||
import {
|
import {
|
||||||
@@ -289,7 +291,12 @@ async function startAgentUpgrade(h: HostSummary) {
|
|||||||
}
|
}
|
||||||
const kind = remoteActionKindForHost(h);
|
const kind = remoteActionKindForHost(h);
|
||||||
if (!kind) return;
|
if (!kind) return;
|
||||||
void runHostRemoteAction(h.id, remoteActionTitleForHost(h), kind);
|
void runHostRemoteAction(
|
||||||
|
h.id,
|
||||||
|
remoteActionTitleForHost(h),
|
||||||
|
kind,
|
||||||
|
remoteActionLogPlaceholder(h, kind),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function openHost(id: number) {
|
function openHost(id: number) {
|
||||||
@@ -450,7 +457,11 @@ interface HostDeleteResponse {
|
|||||||
|
|
||||||
async function onManualAddStarted(payload: { hostId: number; title: string }) {
|
async function onManualAddStarted(payload: { hostId: number; title: string }) {
|
||||||
await loadHosts();
|
await loadHosts();
|
||||||
void pollHostRemoteAction(payload.hostId, payload.title);
|
void pollHostRemoteAction(
|
||||||
|
payload.hostId,
|
||||||
|
payload.title,
|
||||||
|
remoteActionLogPlaceholderFromTitle(payload.title),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function confirmDelete(h: HostSummary) {
|
async function confirmDelete(h: HostSummary) {
|
||||||
|
|||||||
Reference in New Issue
Block a user