Skip to content

Commit

Permalink
feat: strict json schema properties on config
Browse files Browse the repository at this point in the history
  • Loading branch information
wdavidw committed Mar 19, 2024
1 parent 588fb9c commit 03d9880
Show file tree
Hide file tree
Showing 157 changed files with 957 additions and 979 deletions.
32 changes: 17 additions & 15 deletions packages/core/lib/actions/execute/assert/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,26 @@ export default {
if (config.content && config.trim) {
config.content = config.content.trim();
}
const configForExecute = utils.object.filter(config, ['code', 'content', 'not', 'trim']);
// Command exit code
if (config.code != null) {
const {code} = await this.execute(config, {
$relax: true
});
if (!config.not) {
if (!config.code.includes(code)) {
throw utils.error('NIKITA_EXECUTE_ASSERT_EXIT_CODE', ['an unexpected exit code was encountered,', `got ${JSON.stringify(code)}`, config.code.length === 1 ? `while expecting ${config.code}.` : `while expecting one of ${JSON.stringify(config.code)}.`]);
}
} else {
if (config.code.includes(code)) {
throw utils.error('NIKITA_EXECUTE_ASSERT_NOT_EXIT_CODE', ['an unexpected exit code was encountered,', `got ${JSON.stringify(code)}`, config.code.length === 1 ? `while expecting anything but ${config.code}.` : `while expecting anything but one of ${JSON.stringify(config.code)}.`]);
}
const res = await this.execute({
...configForExecute,
$relax: true
});
const code = res.error ? res.error.exit_code : res.code
const expectedCodes = utils.array.flatten(config.code.true, config.code.false);
if (!config.not) {
if (!expectedCodes.includes(code)) {
throw utils.error('NIKITA_EXECUTE_ASSERT_EXIT_CODE', ['an unexpected exit code was encountered,', `got ${JSON.stringify(code)}`, expectedCodes.length === 1 ? `while expecting ${expectedCodes}.` : `while expecting one of ${JSON.stringify(expectedCodes)}.`]);
}
} else {
if (expectedCodes.includes(code)) {
throw utils.error('NIKITA_EXECUTE_ASSERT_NOT_EXIT_CODE', ['an unexpected exit code was encountered,', `got ${JSON.stringify(code)}`, expectedCodes.length === 1 ? `while expecting anything but ${expectedCodes}.` : `while expecting anything but one of ${JSON.stringify(expectedCodes)}.`]);
}
}
// Content is a string or a buffer
if ((config.content != null) && typeof config.content === 'string') {
let {stdout} = await this.execute(config);
let {stdout} = await this.execute(configForExecute);
if (config.trim) {
stdout = stdout.trim();
}
Expand All @@ -46,7 +48,7 @@ export default {
}
// Content is a regexp
if ((config.content != null) && utils.regexp.is(config.content)) {
let {stdout} = await this.execute(config);
let {stdout} = await this.execute(configForExecute);
if (config.trim) {
stdout = stdout.trim();
}
Expand All @@ -64,7 +66,7 @@ export default {
hooks: {
on_action: function({config, metadata}) {
if (!config.content) {
return config.code != null ? config.code : config.code = [0];
return config.code != null ? config.code : config.code = {true: [0]};
}
}
},
Expand Down
9 changes: 1 addition & 8 deletions packages/core/lib/actions/execute/assert/schema.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
{
"config": {
"type": "object",
"$ref": "module://@nikitajs/core/actions/execute#/definitions/config",
"properties": {
"code": {
"type": ["array", "integer"],
"coercion": true,
"items": {
"type": "integer"
},
"description": "Expected exit code, activated by default unless content is provided."
},
"content": {
"oneOf": [
{
Expand Down
22 changes: 10 additions & 12 deletions packages/core/lib/actions/execute/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
"type": ["boolean", "string"],
"description": "Run this command inside a root directory with the arc-chroot command or any provided string, require the \"arch_chroot_rootdir\" option if activated."
},
"arch_chroot_rootdir": {
"type": "string",
"description": "Path to the mount point corresponding to the root directory, required if the \"arch_chroot\" option is activated."
},
"arch_chroot_tmpdir": {
"type": "string",
"description": "Temporary path used with arch_chroot."
},
"bash": {
"type": ["boolean", "string"],
"description": "Serialize the command into a file and execute it with bash."
Expand Down Expand Up @@ -184,18 +192,8 @@
"description": "Unix user id."
}
},
"dependencies": {
"arch_chroot": {
"properties": {
"arch_chroot_rootdir": {
"type": "string",
"description": "Path to the mount point corresponding to the root directory, required if the \"arch_chroot\" option is activated."
}
},
"required": [
"arch_chroot_rootdir"
]
}
"dependentRequired": {
"arch_chroot": ["arch_chroot_rootdir"]
},
"required": [
"command"
Expand Down
79 changes: 67 additions & 12 deletions packages/core/lib/actions/fs/assert/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,58 @@ const errors = {
});
},
NIKITA_FS_ASSERT_CONTENT_UNMATCH: function({config, expect}) {
return utils.error('NIKITA_FS_ASSERT_CONTENT_UNMATCH', ['content does not match the provided regexp,', `expect ${JSON.stringify(expect.toString())}`, `to match ${config.content.toString()},`, `location is ${JSON.stringify(config.target)}.`], {
return utils.error('NIKITA_FS_ASSERT_CONTENT_UNMATCH', [
'content does not match the provided regexp,',
`expect ${JSON.stringify(expect.toString())}`,
`to match ${config.content.toString()},`,
`location is ${JSON.stringify(config.target)}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_CONTENT_MATCH: function({config, expect}) {
return utils.error('NIKITA_FS_ASSERT_CONTENT_MATCH', ['content is matching the provided regexp,', `got ${JSON.stringify(expect.toString())}`, `to match ${config.content.toString()},`, `location is ${JSON.stringify(config.target)}.`], {
return utils.error('NIKITA_FS_ASSERT_CONTENT_MATCH', [
'content is matching the provided regexp,',
`got ${JSON.stringify(expect.toString())}`,
`to match ${config.content.toString()},`,
`location is ${JSON.stringify(config.target)}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_FILETYPE_INVALID_VALUE: function({config}) {
return utils.error('NIKITA_FS_ASSERT_FILETYPE_INVALID_VALUE', [
'provided filetype is not supported,',
`got ${JSON.stringify(config.filetype)}.`
], {
target: config.target,
});
},
NIKITA_FS_ASSERT_FILETYPE_INVALID_TYPE: function({config}) {
return utils.error('NIKITA_FS_ASSERT_FILETYPE_INVALID_TYPE', [
'filetype must be a string or a number,',
`got ${JSON.stringify(config.filetype)}.`
], {
target: config.target,
});
},
NIKITA_FS_ASSERT_HASH_UNMATCH: function({config, algo, hash}) {
return utils.error('NIKITA_FS_ASSERT_HASH_UNMATCH', [`an invalid ${algo} signature was computed,`, `expect ${JSON.stringify(hash.expected)},`, `got ${JSON.stringify(hash.actual)}.`], {
return utils.error('NIKITA_FS_ASSERT_HASH_UNMATCH', [
`an invalid ${algo} signature was computed,`,
`expect ${JSON.stringify(hash.expected)},`,
`got ${JSON.stringify(hash.actual)}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_HASH_MATCH: function({config, algo, hash}) {
return utils.error('NIKITA_FS_ASSERT_HASH_MATCH', [`the ${algo} signatures are matching,`, `not expecting to equal ${JSON.stringify(hash)}.`], {
return utils.error('NIKITA_FS_ASSERT_HASH_MATCH', [
`the ${algo} signatures are matching,`,
`not expecting to equal ${JSON.stringify(hash)}.`
], {
target: config.target,
message: config.error
});
Expand All @@ -63,7 +96,11 @@ const errors = {
const expect = config.mode.map(function(mode) {
return pad(4, utils.mode.stringify(mode), '0');
});
return utils.error("NIKITA_FS_ASSERT_MODE_UNMATCH", ['content permission don\'t match the provided mode,', `expect ${expect},`, `got ${utils.mode.stringify(mode).slice(-4)}.`], {
return utils.error("NIKITA_FS_ASSERT_MODE_UNMATCH", [
'content permission don\'t match the provided mode,',
`expect ${expect},`,
`got ${utils.mode.stringify(mode).slice(-4)}.`
], {
target: config.target,
message: config.error
});
Expand All @@ -72,31 +109,47 @@ const errors = {
const expect = config.mode.map(function(mode) {
return pad(4, utils.mode.stringify(mode), '0');
});
return utils.error("NIKITA_FS_ASSERT_MODE_MATCH", ['the content permission match the provided mode,', `not expecting to equal ${expect}.`], {
return utils.error("NIKITA_FS_ASSERT_MODE_MATCH", [
'the content permission match the provided mode,',
`not expecting to equal ${expect}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_UID_UNMATCH: function({config, actual}) {
return utils.error('NIKITA_FS_ASSERT_UID_UNMATCH', ['the uid of the target does not match the expected value,', `expected ${JSON.stringify(config.uid)},`, `got ${JSON.stringify(actual)}.`], {
return utils.error('NIKITA_FS_ASSERT_UID_UNMATCH', [
'the uid of the target does not match the expected value,',
`expected ${JSON.stringify(config.uid)},`, `got ${JSON.stringify(actual)}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_UID_MATCH: function({config}) {
return utils.error('NIKITA_FS_ASSERT_UID_MATCH', ['the uid of the target match the provided value,', `not expecting to equal ${JSON.stringify(config.uid)}.`], {
return utils.error('NIKITA_FS_ASSERT_UID_MATCH', [
'the uid of the target match the provided value,',
`not expecting to equal ${JSON.stringify(config.uid)}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_GID_UNMATCH: function({config, actual}) {
return utils.error('NIKITA_FS_ASSERT_GID_UNMATCH', ['the gid of the target does not match the expected value,', `expected ${JSON.stringify(config.uid)},`, `got ${JSON.stringify(actual)}.`], {
return utils.error('NIKITA_FS_ASSERT_GID_UNMATCH', [
'the gid of the target does not match the expected value,',
`expected ${JSON.stringify(config.uid)},`,
`got ${JSON.stringify(actual)}.`
], {
target: config.target,
message: config.error
});
},
NIKITA_FS_ASSERT_GID_MATCH: function({config}) {
return utils.error('NIKITA_FS_ASSERT_GID_MATCH', ['the gid of the target match the provided value,', `not expecting to equal ${JSON.stringify(config.uid)}.`], {
return utils.error('NIKITA_FS_ASSERT_GID_MATCH', [
'the gid of the target match the provided value,',
`not expecting to equal ${JSON.stringify(config.uid)}.`
], {
target: config.target,
message: config.error
});
Expand Down Expand Up @@ -149,10 +202,12 @@ export default {
results.push(fs.constants.S_IFSOCK);
break;
default:
results.push(filetype);
throw errors.NIKITA_FS_ASSERT_FILETYPE_INVALID_VALUE({config});
}
} else {
} else if (typeof filetype === 'number') {
results.push(filetype);
} else {
throw errors.NIKITA_FS_ASSERT_FILETYPE_INVALID_TYPE({config});
}
}
return results;
Expand Down
4 changes: 4 additions & 0 deletions packages/core/lib/actions/fs/assert/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"default": "utf8",
"description": "Content encoding, see the Node.js supported Buffer encoding."
},
"error": {
"type": "string",
"description": "Error message to use with failed assertions."
},
"filetype": {
"type": "array",
"coercion": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"typeof": "function",
"description": "User provided function receiving the newly created readable stream. The user is responsible for pumping new content from it."
},
"sudo": {
"$ref": "module://@nikitajs/core/actions/execute#/definitions/config/properties/sudo"
},
"target": {
"oneOf": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"typeof": "function",
"description": "User provided function receiving the newly created writable stream. The user is responsible for writing new content and for closing the stream."
},
"sudo": {
"$ref": "module://@nikitajs/core/actions/execute#/definitions/config/properties/sudo"
},
"target": {
"oneOf": [
{
Expand Down
11 changes: 11 additions & 0 deletions packages/core/lib/actions/fs/base/readFile/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
"encoding": {
"$ref": "module://@nikitajs/core/actions/fs/base/createReadStream#/definitions/config/properties/encoding"
},
"format": {
"oneOf": [
{
"type": "string"
},
{
"typeof": "function"
}
],
"description": "Parse the file content."
},
"target": {
"oneOf": [
{
Expand Down
6 changes: 2 additions & 4 deletions packages/core/lib/actions/fs/base/stat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import dedent from 'dedent';
import utils from '@nikitajs/core/utils';
import { escapeshellarg as esa } from "@nikitajs/core/utils/string";
import definitionsIn from './schema.in.json' assert { type: "json" };
import definitionsOut from './schema.out.json' assert { type: "json" };
import definitions from './schema.json' assert { type: "json" };

const errors = {
NIKITA_FS_STAT_TARGET_ENOENT: ({config, error}) =>
Expand Down Expand Up @@ -57,7 +56,6 @@ export default {
argument_to_config: 'target',
log: false,
raw_output: true,
definitions: definitionsIn
definitions: definitions
},
definitions_output: definitionsOut
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"config": {
"type": "object",
"additionalProperties": false,
"properties": {
"dereference": {
"type": "boolean",
Expand All @@ -25,6 +26,7 @@
},
"output": {
"type": "object",
"additionalProperties": true,
"properties": {
"stats": {
"type": "object",
Expand Down
33 changes: 0 additions & 33 deletions packages/core/lib/actions/fs/base/stat/schema.out.json

This file was deleted.

4 changes: 2 additions & 2 deletions packages/core/lib/actions/fs/base/writeFile/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import utils from '@nikitajs/core/utils';
import definitions from "./schema.json" assert { type: "json" };

const errors = {
NIKITA_FS_STAT_TARGET_ENOENT: ({config, err}) =>
NIKITA_FS_TARGET_INVALID: ({config, err}) =>
utils.error('NIKITA_FS_TARGET_INVALID', [
'the target location is absolute',
'but this is not suported in SSH mode,',
Expand All @@ -28,7 +28,7 @@ export default {
// Normalization
config.target = config.cwd ? path.resolve(config.cwd, config.target) : path.normalize(config.target);
if (ssh && !path.isAbsolute(config.target)) {
throw NIKITA_FS_STAT_TARGET_ENOENT({
throw errors.NIKITA_FS_TARGET_INVALID({
config: config,
err: err
});
Expand Down
2 changes: 1 addition & 1 deletion packages/core/lib/actions/fs/copy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export default {
return await this.fs.copy({
target: target,
source: source,
source_stat: stats,
source_stats: stats,
uid: uid,
gid: gid,
mode: mode,
Expand Down
Loading

0 comments on commit 03d9880

Please sign in to comment.