fix(striker-ui-api): allow get manifest detail

main
Tsu-ba-me 2 years ago
parent 7575bf8aed
commit a066fb7ede
  1. 250
      striker-ui-api/src/lib/request_handlers/manifest/getManifestDetail.ts
  2. 1
      striker-ui-api/src/lib/request_handlers/manifest/index.ts
  3. 6
      striker-ui-api/src/routes/manifest.ts
  4. 69
      striker-ui-api/src/types/APIManifest.d.ts
  5. 68
      striker-ui-api/src/types/GetAnvilDataFunction.d.ts

@ -0,0 +1,250 @@
import { RequestHandler } from 'express';
import { getAnvilData } from '../../accessModule';
import { getEntityParts } from '../../disassembleEntityId';
import { stderr, stdout } from '../../shell';
const handleSortEntries = <T extends [string, unknown]>(
[aId]: T,
[bId]: T,
): number => {
const { name: at, number: an } = getEntityParts(aId);
const { name: bt, number: bn } = getEntityParts(bId);
let result = 0;
if (at === bt) {
if (an > bn) {
result = 1;
} else if (an < bn) {
result = -1;
}
} else if (at > bt) {
result = 1;
} else if (at < bt) {
result = -1;
}
return result;
};
const handleSortNetworks = <T extends [string, unknown]>(
[aId]: T,
[bId]: T,
): number => {
const isAIfn = /^ifn/.test(aId);
const isBIfn = /^ifn/.test(bId);
const { name: at, number: an } = getEntityParts(aId);
const { name: bt, number: bn } = getEntityParts(bId);
let result = 0;
if (at === bt) {
if (an > bn) {
result = 1;
} else if (an < bn) {
result = -1;
}
} else if (isAIfn) {
result = 1;
} else if (isBIfn) {
result = -1;
} else if (at > bt) {
result = 1;
} else if (at < bt) {
result = -1;
}
return result;
};
export const getManifestDetail: RequestHandler = (request, response) => {
const {
params: { manifestUUID },
} = request;
let rawManifestListData: AnvilDataManifestListHash | undefined;
try {
({ manifests: rawManifestListData } = getAnvilData<{
manifests?: AnvilDataManifestListHash;
}>(
{ manifests: true },
{
predata: [['Striker->load_manifest', { manifest_uuid: manifestUUID }]],
},
));
} catch (subError) {
stderr(
`Failed to get install manifest ${manifestUUID}; CAUSE: ${subError}`,
);
response.status(500).send();
return;
}
stdout(
`Raw install manifest list:\n${JSON.stringify(
rawManifestListData,
null,
2,
)}`,
);
if (!rawManifestListData) {
response.status(404).send();
return;
}
const {
manifest_uuid: {
[manifestUUID]: {
parsed: {
domain,
fences: fenceUuidList = {},
machine,
name,
networks: { dns: dnsCsv, mtu, name: networkList, ntp: ntpCsv },
prefix,
sequence,
upses: upsUuidList = {},
},
},
},
} = rawManifestListData;
const manifestData: ManifestDetail = {
domain,
hostConfig: {
hosts: Object.entries(machine)
.sort(handleSortEntries)
.reduce<ManifestDetailHostList>(
(
previous,
[hostId, { fence = {}, ipmi_ip: ipmiIp, network, ups = {} }],
) => {
const { name: hostType, number: hostNumber } =
getEntityParts(hostId);
stdout(`host=${hostType},n=${hostNumber}`);
previous[hostId] = {
fences: Object.entries(fence)
.sort(handleSortEntries)
.reduce<ManifestDetailFenceList>(
(fences, [fenceName, { port: fencePort }]) => {
const fenceUuidContainer = fenceUuidList[fenceName];
if (fenceUuidContainer) {
const { uuid: fenceUuid } = fenceUuidContainer;
fences[fenceName] = {
fenceName,
fencePort,
fenceUuid,
};
}
return fences;
},
{},
),
hostNumber,
hostType,
ipmiIp,
networks: Object.entries(network)
.sort(handleSortNetworks)
.reduce<ManifestDetailHostNetworkList>(
(hostNetworks, [networkId, { ip: networkIp }]) => {
const { name: networkType, number: networkNumber } =
getEntityParts(networkId);
stdout(`hostnetwork=${networkType},n=${networkNumber}`);
hostNetworks[networkId] = {
networkIp,
networkNumber,
networkType,
};
return hostNetworks;
},
{},
),
upses: Object.entries(ups)
.sort(handleSortEntries)
.reduce<ManifestDetailUpsList>((upses, [upsName, { used }]) => {
const upsUuidContainer = upsUuidList[upsName];
if (upsUuidContainer) {
const { uuid: upsUuid } = upsUuidContainer;
upses[upsName] = {
isUsed: Boolean(used),
upsName,
upsUuid,
};
}
return upses;
}, {}),
};
return previous;
},
{},
),
},
name,
networkConfig: {
dnsCsv,
mtu: Number.parseInt(mtu),
networks: Object.entries(networkList)
.sort(handleSortNetworks)
.reduce<ManifestDetailNetworkList>(
(
networks,
[
networkId,
{
gateway: networkGateway,
network: networkMinIp,
subnet: networkSubnetMask,
},
],
) => {
const { name: networkType, number: networkNumber } =
getEntityParts(networkId);
stdout(`network=${networkType},n=${networkNumber}`);
networks[networkId] = {
networkGateway,
networkMinIp,
networkNumber,
networkSubnetMask,
networkType,
};
return networks;
},
{},
),
ntpCsv,
},
prefix,
sequence,
};
stdout(
`Extracted install manifest data:\n${JSON.stringify(
manifestData,
null,
2,
)}`,
);
response.status(200).send(manifestData);
};

@ -1,2 +1,3 @@
export * from './getManifest';
export * from './getManifestDetail';
export * from './getManifestTemplate';

@ -2,11 +2,15 @@ import express from 'express';
import {
getManifest,
getManifestDetail,
getManifestTemplate,
} from '../lib/request_handlers/manifest';
const router = express.Router();
router.get('/', getManifest).get('/template', getManifestTemplate);
router
.get('/', getManifest)
.get('/template', getManifestTemplate)
.get('/:manifestUUID', getManifestDetail);
export default router;

@ -2,3 +2,72 @@ type ManifestOverview = {
manifestName: string;
manifestUUID: string;
};
type ManifestDetailNetwork = {
networkGateway: string;
networkMinIp: string;
networkNumber: number;
networkSubnetMask: string;
networkType: string;
};
type ManifestDetailNetworkList = {
[networkId: string]: ManifestDetailNetwork;
};
type ManifestDetailFence = {
fenceName: string;
fencePort: string;
fenceUuid: string;
};
type ManifestDetailFenceList = {
[fenceId: string]: ManifestDetailFence;
};
type ManifestDetailHostNetwork = {
networkIp: string;
networkNumber: number;
networkType: string;
};
type ManifestDetailHostNetworkList = {
[networkId: string]: ManifestDetailHostNetwork;
};
type ManifestDetailUps = {
isUsed: boolean;
upsName: string;
upsUuid: string;
};
type ManifestDetailUpsList = {
[upsId: string]: ManifestDetailUps;
};
type ManifestDetailHostList = {
[hostId: string]: {
fences: ManifestDetailFenceList;
hostNumber: number;
hostType: string;
ipmiIp: string;
networks: ManifestDetailHostNetworkList;
upses: ManifestDetailUpsList;
};
};
type ManifestDetail = {
domain: string;
hostConfig: {
hosts: ManifestDetailHostList;
};
name: string;
networkConfig: {
dnsCsv: string;
mtu: number;
networks: ManifestDetailNetworkList;
ntpCsv: string;
};
prefix: string;
sequence: string;
};

@ -13,6 +13,74 @@ type AnvilDataDatabaseHash = {
};
};
type AnvilDataManifestListHash = {
manifest_uuid: {
[manifestUUID: string]: {
parsed: {
domain: string;
fences?: {
[fenceId: string]: {
uuid: string;
};
};
machine: {
[hostId: string]: {
fence?: {
[fenceName: string]: {
port: string;
};
};
ipmi_ip: string;
name: string;
network: {
[networkId: string]: {
ip: string;
};
};
ups?: {
[upsName: string]: {
used: string;
};
};
};
};
name: string;
networks: {
count: {
[networkType: string]: number;
};
dns: string;
mtu: string;
name: {
[networkId: string]: {
gateway: string;
network: string;
subnet: string;
};
};
ntp: string;
};
prefix: string;
sequence: string;
upses?: {
[upsId: string]: {
uuid: string;
};
};
};
};
};
name_to_uuid: Record<string, string>;
} & Record<
string,
{
manifest_last_ran: number;
manifest_name: string;
manifest_note: string;
manifest_xml: string;
}
>;
type AnvilDataUPSHash = {
[upsName: string]: {
agent: string;

Loading…
Cancel
Save