Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web UI: replace run install manifest form #690

Merged
merged 29 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2a9a1a8
fix(striker-ui): empty inquire host response after successful add host
ylei-tsubame Jul 8, 2024
4fac7e4
fix(striker-ui-api): order server list
ylei-tsubame Jul 11, 2024
e097d44
fix(striker-ui-api): add host owner to host overview
ylei-tsubame Jul 13, 2024
10df5ca
fix(striker-ui-api): add switch in run manifest to allow reuse host
ylei-tsubame Jul 15, 2024
dcdf612
fix(striker-ui): correct empty message in manage host, fence
ylei-tsubame Jul 15, 2024
f4a9966
fix(striker-ui): remove overviews state in manage manifest
ylei-tsubame Jul 17, 2024
f55d104
fix(striker-ui): add anvil entry to host overview type
ylei-tsubame Jul 17, 2024
4553880
fix(striker-ui): add run manifest form using formik
ylei-tsubame Jul 20, 2024
52a368d
fix(striker-ui): correct displays, allow select swap, draft request i…
ylei-tsubame Jul 24, 2024
0e5ec0f
fix(striker-ui): align run manifest formik values to request schema
ylei-tsubame Jul 24, 2024
c3e9c77
fix(striker-ui): add run manifest schema, correct run manifest formik…
ylei-tsubame Jul 24, 2024
1d89205
fix(striker-ui): replace run manifest form
ylei-tsubame Jul 24, 2024
135ce6c
fix(striker-ui): simplify, add style presets in checkbox
ylei-tsubame Jul 24, 2024
0b6189d
fix(striker-ui): add reuse hosts checkbox in run manifest form
ylei-tsubame Jul 24, 2024
4cbd3a3
fix(striker-ui-api): align run manifest request body type with UI
ylei-tsubame Jul 24, 2024
5232290
fix(striker-ui): remove unused api run manifest request body type
ylei-tsubame Jul 24, 2024
f96a26d
fix(striker-ui): node->subnode in run manifest summary
ylei-tsubame Jul 24, 2024
fe52811
fix(striker-ui): reword success message in run manifest form
ylei-tsubame Jul 24, 2024
aa9a9b9
fix(striker-ui): correct skip behaviour in form summary
ylei-tsubame Jul 25, 2024
5420eb2
fix(striker-ui): allow rerun in run manifest form
ylei-tsubame Jul 25, 2024
a466d38
fix(striker-ui-api): include possible existing anvil node info in man…
ylei-tsubame Jul 25, 2024
e679b4a
fix(striker-ui-api): enable rerun in run manifest command
ylei-tsubame Jul 25, 2024
c206248
fix(striker-ui): guess hosts on fresh run manifest
ylei-tsubame Jul 25, 2024
739fe46
fix(striker-ui): resolve build type errors
ylei-tsubame Jul 25, 2024
2e2fa79
fix(striker-ui): update template, hosts on run manifest success
ylei-tsubame Jul 25, 2024
1b7164c
fix(striker-ui): ensure known host exists when initialize in run mani…
ylei-tsubame Jul 25, 2024
196e639
build(striker-ui-api): rebuild
ylei-tsubame Jul 25, 2024
b31b464
build(striker-ui): rebuild
ylei-tsubame Jul 25, 2024
ca1da1b
Merge branch 'main' into issues/651-manifest-without-mn
digimer Jul 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion striker-ui-api/out/index.js

Large diffs are not rendered by default.

88 changes: 70 additions & 18 deletions striker-ui-api/src/lib/request_handlers/command/runManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,38 @@ import {
getHostData,
getManifestData,
job,
query,
sub,
} from '../../accessModule';
import { ResponseError } from '../../ResponseError';
import { sanitize } from '../../sanitize';
import { perr } from '../../shell';

export const runManifest: RequestHandler<
{ manifestUuid: string },
undefined,
undefined | ResponseErrorBody,
RunManifestRequestBody
> = async (request, response) => {
const {
params: { manifestUuid },
params: { manifestUuid: rawManifestUuid },
body: {
debug = 2,
description: rawDescription,
hosts: rawHostList = {},
password: rawPassword,
rerun: rawRerun,
reuseHosts: rawReuseHosts,
} = {},
} = request;

const description = sanitize(rawDescription, 'string');
const password = sanitize(rawPassword, 'string');
const manifestUuid = sanitize(rawManifestUuid, 'string', {
modifierType: 'sql',
});
const rerun = sanitize(rawRerun, 'boolean');
const reuseHosts = sanitize(rawReuseHosts, 'boolean');

let description = sanitize(rawDescription, 'string');
let password = sanitize(rawPassword, 'string');

const hostList: ManifestExecutionHostList = {};

Expand All @@ -42,6 +52,48 @@ export const runManifest: RequestHandler<
response.status(400).send();
};

if (rerun) {
const sql = `
SELECT
a.anvil_description,
a.anvil_password
FROM anvils AS a
JOIN manifests AS b
ON a.anvil_name = b.manifest_name
WHERE b.manifest_uuid = '${manifestUuid}';`;

let rows: string[][];

try {
rows = await query<string[][]>(sql);
} catch (error) {
const rserror = new ResponseError(
'49e0e02',
`Failed to get existing record with manifest [${manifestUuid}]; CAUSE: ${error}`,
);

perr(rserror.toString());

return response.status(500).send(rserror.body);
}

if (!rows.length) {
const rserror = new ResponseError(
'2d42e16',
`No record found on rerun manifest [${manifestUuid}]`,
);

perr(rserror.toString());

return response.status(404).send(rserror.body);
}

// Assign existing values before value assertions.
({
0: [description, password],
} = rows);
}

try {
assert(
REP_PEACEFUL_STRING.test(description),
Expand All @@ -55,25 +107,25 @@ export const runManifest: RequestHandler<

const uniqueList: Record<string, boolean | undefined> = {};
const isHostListUnique = !Object.values(rawHostList).some(
({ hostNumber, hostType, hostUuid }) => {
const hostId = `${hostType}${hostNumber}`;
({ number, type, uuid }) => {
const id = `${type}${number}`;
assert(
/^node[12]$/.test(hostId),
`Host ID must be "node" followed by 1 or 2; got [${hostId}]`,
/^node[12]$/.test(id),
`Host ID must be "node" followed by 1 or 2; got [${id}]`,
);

assert(
REP_UUID.test(hostUuid),
`Host UUID assigned to ${hostId} must be a UUIDv4; got [${hostUuid}]`,
REP_UUID.test(uuid),
`Host UUID assigned to ${id} must be a UUIDv4; got [${uuid}]`,
);

const isIdDuplicate = Boolean(uniqueList[hostId]);
const isUuidDuplicate = Boolean(uniqueList[hostUuid]);
const isIdDuplicate = Boolean(uniqueList[id]);
const isUuidDuplicate = Boolean(uniqueList[uuid]);

uniqueList[hostId] = true;
uniqueList[hostUuid] = true;
uniqueList[id] = true;
uniqueList[uuid] = true;

hostList[hostId] = { hostNumber, hostType, hostUuid, hostId };
hostList[id] = { id, number, type, uuid };

return isIdDuplicate || isUuidDuplicate;
},
Expand Down Expand Up @@ -118,14 +170,14 @@ export const runManifest: RequestHandler<

try {
anParams = Object.values(hostList).reduce<Record<string, string>>(
(previous, { hostId = '', hostUuid }) => {
(previous, { id: hostId = '', uuid: hostUuid }) => {
const hostName = mapToHostNameData[hostUuid];
const { anvil_name: anName } = hostUuidMapToData[hostUuid];

if (anName) {
if (anName && !reuseHosts) {
assert(
anName !== manifestName,
`Host [${hostName}] cannot be used for [${manifestName}] because it belongs to [${anName}]`,
`Cannot use [${hostName}] for [${manifestName}] because it belongs to [${anName}]; set reuseHost:true to allow this`,
);
}

Expand Down
25 changes: 23 additions & 2 deletions striker-ui-api/src/lib/request_handlers/host/getHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,38 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => {
a.host_name,
a.host_status,
a.host_type,
a.host_uuid
a.host_uuid,
b.anvil_uuid,
b.anvil_name
FROM hosts AS a
LEFT JOIN anvils AS b
ON a.host_uuid IN (
b.anvil_node1_host_uuid,
b.anvil_node2_host_uuid,
b.anvil_dr1_host_uuid
)
${condition}
ORDER BY a.host_name ASC;`;

let afterQueryReturn: QueryResultModifierFunction | undefined =
buildQueryResultReducer<{ [hostUUID: string]: HostOverview }>(
(previous, [hostName, hostStatus, hostType, hostUUID]) => {
(previous, row) => {
const [hostName, hostStatus, hostType, hostUUID, anvilUuid, anvilName] =
row;

const key = toLocal(hostUUID, localHostUUID);

let anvil: HostOverview['anvil'];

if (anvilUuid) {
anvil = {
name: anvilName,
uuid: anvilUuid,
};
}

previous[key] = {
anvil,
hostName,
hostStatus,
hostType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { RequestHandler } from 'express';

import { getManifestData } from '../../accessModule';
import { getManifestData, query } from '../../accessModule';
import { getEntityParts } from '../../disassembleEntityId';
import { ResponseError } from '../../ResponseError';
import { perr, pout, poutvar } from '../../shell';
import { sanitize } from '../../sanitize';

const handleSortEntries = <T extends [string, unknown]>(
[aId]: T,
Expand Down Expand Up @@ -69,9 +71,13 @@ const handleSortNetworks = <T extends [string, unknown]>(

export const getManifestDetail: RequestHandler = async (request, response) => {
const {
params: { manifestUUID: manifestUuid },
params: { manifestUUID: rawManifestUuid },
} = request;

const manifestUuid = sanitize(rawManifestUuid, 'string', {
modifierType: 'sql',
});

let rawManifestListData: AnvilDataManifestListHash | undefined;

try {
Expand Down Expand Up @@ -109,7 +115,49 @@ export const getManifestDetail: RequestHandler = async (request, response) => {
},
} = rawManifestListData;

const sql = `
SELECT
anvil_uuid,
anvil_description,
anvil_node1_host_uuid,
anvil_node2_host_uuid
FROM anvils
WHERE anvil_name = '${name}';`;

let rows: string[][];

try {
rows = await query<string[][]>(sql);
} catch (error) {
const rserror = new ResponseError(
'26bd07d',
`Failed to find existing record with manifest name [${name}]; CAUSE: ${error}`,
);

perr(rserror.toString());

return response.status(500).send(rserror.body);
}

let anvil: ManifestDetail['anvil'];

if (rows.length > 0) {
const {
0: [uuid, description, subnode1Uuid, subnode2Uuid],
} = rows;

anvil = {
description,
hosts: {
1: { uuid: subnode1Uuid },
2: { uuid: subnode2Uuid },
},
uuid,
};
}

const manifestData: ManifestDetail = {
anvil,
domain,
hostConfig: {
hosts: Object.entries(machine)
Expand Down
25 changes: 13 additions & 12 deletions striker-ui-api/src/lib/request_handlers/server/getServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const getServer = buildGetRequestHandler(

const condAnvilUUIDs = join(sanitize(anvilUUIDs, 'string[]'), {
beforeReturn: (toReturn) =>
toReturn ? `AND ser.server_anvil_uuid IN (${toReturn})` : '',
toReturn ? `AND a.server_anvil_uuid IN (${toReturn})` : '',
elementWrapper: "'",
separator: ', ',
});
Expand Down Expand Up @@ -51,16 +51,17 @@ export const getServer = buildGetRequestHandler(

return `
SELECT
ser.server_uuid,
ser.server_name,
ser.server_state,
ser.server_host_uuid,
anv.anvil_uuid,
anv.anvil_name
FROM servers AS ser
JOIN anvils AS anv
ON ser.server_anvil_uuid = anv.anvil_uuid
WHERE ser.server_state != '${DELETED}'
${condAnvilUUIDs};`;
a.server_uuid,
a.server_name,
a.server_state,
a.server_host_uuid,
b.anvil_uuid,
b.anvil_name
FROM servers AS a
JOIN anvils AS b
ON a.server_anvil_uuid = b.anvil_uuid
WHERE a.server_state != '${DELETED}'
${condAnvilUUIDs}
ORDER BY a.server_name;`;
},
);
4 changes: 4 additions & 0 deletions striker-ui-api/src/types/ApiHost.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type HostIpmi = {
};

type HostOverview = {
anvil?: {
name: string;
uuid: string;
};
hostName: string;
hostStatus: string;
hostType: string;
Expand Down
19 changes: 12 additions & 7 deletions striker-ui-api/src/types/ApiManifest.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ type ManifestDetailHostList = {
};

type ManifestDetail = {
anvil?: {
description: string;
hosts: Record<string, { uuid: string }>;
uuid: string;
};
domain: string;
hostConfig: {
hosts: ManifestDetailHostList;
Expand All @@ -74,15 +79,13 @@ type ManifestDetail = {
};

type ManifestExecutionHost = {
hostId?: string;
hostNumber: number;
hostType: string;
hostUuid: string;
id?: string;
number: number;
type: string;
uuid: string;
};

type ManifestExecutionHostList = {
[hostId: string]: ManifestExecutionHost;
};
type ManifestExecutionHostList = Record<string, ManifestExecutionHost>;

type ManifestTemplate = {
domain: string;
Expand All @@ -109,4 +112,6 @@ type RunManifestRequestBody = {
description: string;
hosts: ManifestExecutionHostList;
password: string;
rerun?: boolean;
reuseHosts?: boolean;
};
Loading