Implemented recursive type loader for API types

feature/node-rewrite
Sven Slootweg 6 years ago
parent f8f35c5dcf
commit 4944d3560d

@ -5,11 +5,9 @@ const graphql = require("graphql");
const fs = require("fs");
const path = require("path");
const matchOrError = require("../match-or-error");
const upperSnakeCase = require("../upper-snake-case");
const All = require("../graphql/symbols/all");
const createGraphQLInterface = require("../graphql/index");
const {ID, LocalProperties, createDataObject} = require("../graphql/data-object");
const All = require("../graphql/symbols/all");
const loadTypes = require("../graphql/type-loader");
const createLoaders = require("./loaders");
@ -44,132 +42,12 @@ new graphql.GraphQLScalarType({
let schema = graphql.buildSchema(fs.readFileSync(path.resolve(__dirname, "../schemas/main.gql"), "utf8"));
function createBlockDevice({ name, path }) {
if (name != null) {
path = `/dev/${name}`;
} else if (path != null) {
let match = matchOrError(/^\/dev\/(.+)$/, path);
name = match[0];
}
/* FIXME: parent */
return createDataObject({
[LocalProperties]: {
path: path
},
lsblk: {
[ID]: name,
name: "name",
size: "size",
mountpoint: "mountpoint",
deviceNumber: "deviceNumber",
removable: "removable",
readOnly: "readOnly",
children: (device) => {
return device.children.map((child) => {
return createBlockDevice({ name: child.name });
});
}
}
});
}
function createPhysicalVolume({ path }) {
return createDataObject({
[LocalProperties]: {
path: path,
blockDevice: () => {
return createBlockDevice({ path: path });
}
},
lvmPhysicalVolumes: {
[ID]: path,
volumeGroup: (volume) => {
if (volume.volumeGroup != null) {
return createVolumeGroup({ name: volume.volumeGroup });
}
},
format: "format",
size: "totalSpace",
freeSpace: "freeSpace",
duplicate: "isDuplicate",
allocatable: "isAllocatable",
used: "isUsed",
exported: "isExported",
missing: "isMissing"
}
});
}
function createVolumeGroup({ name }) {
return createDataObject({
[LocalProperties]: {
name: name
}
});
}
function createDrive({ path }) {
return createDataObject({
[LocalProperties]: {
path: path,
blockDevice: () => {
return createBlockDevice({ path: path });
},
/* FIXME: allBlockDevices, for representing every single block device that's hosted on this physical drive, linearly. Need to figure out how that works with representation of mdraid arrays, LVM volumes, etc. */
},
smartctlScan: {
[ID]: path,
interface: "interface"
},
smartctlInfo: {
[ID]: path,
model: "model",
modelFamily: "modelFamily",
smartAvailable: "smartAvailable",
smartEnabled: "smartEnabled",
serialNumber: "serialNumber",
wwn: "wwn",
firmwareVersion: "firmwareVersion",
size: "size",
rpm: "rpm",
logicalSectorSize: (device) => device.sectorSizes.logical,
physicalSectorSize: (device) => device.sectorSizes.physical,
formFactor: "formFactor",
ataVersion: "ataVersion",
sataVersion: "sataVersion"
},
smartctlAttributes: {
[ID]: path,
smartAttributes: (attributes) => {
return attributes.map((attribute) => {
return Object.assign({}, attribute, {
type: upperSnakeCase(attribute.type),
updatedWhen: upperSnakeCase(attribute.updatedWhen)
});
});
},
smartHealth: (attributes) => {
let failed = attributes.filter((item) => {
return (item.failingNow === true || item.failedBefore === true);
});
let deteriorating = attributes.filter((item) => {
return (item.type === "preFail" && item.worstValueSeen < 100);
});
if (failed.length > 0) {
return "FAILING";
} else if (deteriorating.length > 0) {
return "DETERIORATING";
} else {
return "HEALTHY";
}
}
}
let types = loadTypes({
Drive: require("./types/drive"),
BlockDevice: require("./types/block-device"),
LVMPhysicalVolume: require("./types/lvm-physical-volume"),
LVMVolumeGroup: require("./types/lvm-volume-group"),
});
}
module.exports = function () {
return createGraphQLInterface(schema, { loaderFactory: createLoaders }, {
@ -183,7 +61,7 @@ module.exports = function () {
}
}).then((devices) => {
return devices.map((device) => {
return createDrive({ path: device.path });
return types.Drive({ path: device.path });
});
});
}
@ -198,7 +76,7 @@ module.exports = function () {
}
}).then((devices) => {
return devices.map((device) => {
return createBlockDevice({ name: device.name });
return types.BlockDevice({ name: device.name });
});
});
},
@ -212,7 +90,7 @@ module.exports = function () {
}
}).then((volumes) => {
return volumes.map((volume) => {
return createPhysicalVolume({ path: volume.path });
return types.LVMPhysicalVolume({ path: volume.path });
});
});
}

@ -0,0 +1,37 @@
"use strict";
const {createDataObject, LocalProperties, ID} = require("../../graphql/data-object");
const matchOrError = require("../../match-or-error");
module.exports = function (_types) {
return function BlockDevice({ name, path }) {
if (name != null) {
path = `/dev/${name}`;
} else if (path != null) {
let match = matchOrError(/^\/dev\/(.+)$/, path);
name = match[0];
}
/* FIXME: parent */
return createDataObject({
[LocalProperties]: {
path: path
},
lsblk: {
[ID]: name,
name: "name",
size: "size",
mountpoint: "mountpoint",
deviceNumber: "deviceNumber",
removable: "removable",
readOnly: "readOnly",
children: (device) => {
return device.children.map((child) => {
return BlockDevice({ name: child.name });
});
}
}
});
};
};

@ -0,0 +1,67 @@
"use strict";
const {createDataObject, LocalProperties, ID} = require("../../graphql/data-object");
const upperSnakeCase = require("../../upper-snake-case");
module.exports = function (types) {
return function Drive({ path }) {
return createDataObject({
[LocalProperties]: {
path: path,
blockDevice: () => {
return types.BlockDevice({ path: path });
},
/* FIXME: allBlockDevices, for representing every single block device that's hosted on this physical drive, linearly. Need to figure out how that works with representation of mdraid arrays, LVM volumes, etc. */
},
smartctlScan: {
[ID]: path,
interface: "interface"
},
smartctlInfo: {
[ID]: path,
model: "model",
modelFamily: "modelFamily",
smartAvailable: "smartAvailable",
smartEnabled: "smartEnabled",
serialNumber: "serialNumber",
wwn: "wwn",
firmwareVersion: "firmwareVersion",
size: "size",
rpm: "rpm",
logicalSectorSize: (device) => device.sectorSizes.logical,
physicalSectorSize: (device) => device.sectorSizes.physical,
formFactor: "formFactor",
ataVersion: "ataVersion",
sataVersion: "sataVersion"
},
smartctlAttributes: {
[ID]: path,
smartAttributes: (attributes) => {
return attributes.map((attribute) => {
return Object.assign({}, attribute, {
type: upperSnakeCase(attribute.type),
updatedWhen: upperSnakeCase(attribute.updatedWhen)
});
});
},
smartHealth: (attributes) => {
let failed = attributes.filter((item) => {
return (item.failingNow === true || item.failedBefore === true);
});
let deteriorating = attributes.filter((item) => {
return (item.type === "preFail" && item.worstValueSeen < 100);
});
if (failed.length > 0) {
return "FAILING";
} else if (deteriorating.length > 0) {
return "DETERIORATING";
} else {
return "HEALTHY";
}
}
}
});
};
};

@ -0,0 +1,32 @@
"use strict";
const {createDataObject, LocalProperties, ID} = require("../../graphql/data-object");
module.exports = function (types) {
return function LVMPhysicalVolume({ path }) {
return createDataObject({
[LocalProperties]: {
path: path,
blockDevice: () => {
return types.BlockDevice({ path: path });
}
},
lvmPhysicalVolumes: {
[ID]: path,
volumeGroup: (volume) => {
if (volume.volumeGroup != null) {
return types.LVMVolumeGroup({ name: volume.volumeGroup });
}
},
format: "format",
size: "totalSpace",
freeSpace: "freeSpace",
duplicate: "isDuplicate",
allocatable: "isAllocatable",
used: "isUsed",
exported: "isExported",
missing: "isMissing"
}
});
};
};

@ -0,0 +1,13 @@
"use strict";
const {createDataObject, LocalProperties} = require("../../graphql/data-object");
module.exports = function (_types) {
return function createVolumeGroup({ name }) {
return createDataObject({
[LocalProperties]: {
name: name
}
});
};
};

@ -0,0 +1,11 @@
"use strict";
module.exports = function loadTypes(types) {
let loadedTypes = {};
for (let [name, module_] of Object.entries(types)) {
loadedTypes[name] = module_(loadedTypes);
}
return loadedTypes;
};
Loading…
Cancel
Save