This is an automated email from the ASF dual-hosted git repository. dcremonini pushed a commit to branch feat/allow_digits_in_configuration_key_names in repository https://gitbox.apache.org/repos/asf/openserverless-task.git
commit 3f0dad68a473491b17c63f7e01a406d54d2efff8 Author: Daniele Cremonini <[email protected]> AuthorDate: Mon Sep 30 22:09:00 2024 +0200 feat: allow digit in a non leading position (e.g. MINIO_CONFIG_INGRESS_S3) --- util/config/configurator.js | 58 +++++++--------------- util/config/configurator/configurator.ts | 2 +- util/config/configurator/tests/fixtures/valid.json | 6 +++ util/config/configurator/tests/index.test.ts | 11 +++- 4 files changed, 36 insertions(+), 41 deletions(-) diff --git a/util/config/configurator.js b/util/config/configurator.js index 8eb7f70..ddd2877 100644 --- a/util/config/configurator.js +++ b/util/config/configurator.js @@ -662,7 +662,7 @@ async function askMissingData(missingData) { let askedForPassword = false; if (Array.isArray(prompt.type)) { const selected = await ie({ - message: `Pick a value for '${key}'`, + message: prompt.label || `Pick a value for '${key}'`, options: prompt.type.map((v2) => ({ label: v2, value: v2 })) }); if (!selected) { @@ -672,7 +672,7 @@ async function askMissingData(missingData) { inputFromPrompt = selected.toString(); } else if (prompt.type === "bool") { const selected = await ie({ - message: `Pick a true/false for '${key}'`, + message: prompt.label || `Pick a true/false for '${key}'`, options: [ { label: "true", value: "true" }, { label: "false", value: "false" } @@ -685,7 +685,7 @@ async function askMissingData(missingData) { inputFromPrompt = selected.toString(); } else if (prompt.type === "password") { const input = await re({ - message: `Enter password value for ${key}` + message: prompt.label || `Enter password value for ${key}` }); if (hD(input)) { ue("Operation cancelled"); @@ -695,7 +695,7 @@ async function askMissingData(missingData) { askedForPassword = true; } else { const input = await te({ - message: `Enter value for ${key} (${prompt.type})` + message: prompt.label || `Enter value for ${key} (${prompt.type})` }); if (hD(input)) { ue("Operation cancelled"); @@ -767,56 +767,36 @@ async function parsePositionalFile(path) { return { success: false, message: NotValidJsonMsg }; } } -function validateConfigJson(body) { +function isInputConfigValid(body) { if (Object.keys(body).length === 0) { - return { success: false, message: BadConfigMsg }; + return false; } for (const key in body) { + console.log("PROD - isInputConfigValid - " + key); const value = body[key]; if (typeof value !== "object") { - return { success: false, message: BadConfigMsg }; + return false; } if (!value.type) { - return { success: false, message: BadConfigMsg }; + return false; } if (!["string", "int", "float", "bool", "password"].includes(value.type) && !Array.isArray(value.type)) { - return { success: false, message: BadConfigMsg }; + return false; } } for (const key in body) { - if (!/^[A-Z][A-Z_]*[A-Z]$/.test(key)) { - return { success: false, message: BadConfigMsg }; + const resCheck = /^[A-Z][A-Z_]*[A-Z]$/.test(key); + console.log("PROD - isInputConfigValid - regexp check - for --- " + key + ", " + resCheck); + if (!/^[A-Z][A-Z0-9]*(_[A-Z][A-Z0-9]*)*$/.test(key)) { + return false; } } - return { success: true }; + return true; } var OPS = process.env.OPS || "ops"; var AdditionalArgsMsg = "Additional arguments will be ignored."; var NotValidJsonMsg = "Not a valid JSON file"; -var BadConfigMsg = `Bad configuration file. - -The configuration file must be an non-empty JSON with the following structure: - -{ - "KEY": { - type: "string" - }, - "OTHER_KEY": { - type: "int" - }, - ... -} - -The keys must be uppercase words (separated by underscores). -The value for the "type" key must be either string with the following values: -- string -- int -- float -- bool -- password - -or an array of strings with specific values (an enum). -`; +var BadConfigMsg = "Bad configuration file. Check the help message (-h) to see the expected format."; var HelpMsg = ` Usage: config <configjson> @@ -832,6 +812,7 @@ The config.json file must be a JSON file with the following structure: "type": "string" }, "OTHER_KEY": { + "label": "An optional custom message", "type": "int" }, ... @@ -870,9 +851,8 @@ async function main() { return process.exit(1); } const config = jsonRes.body; - const validationRes = validateConfigJson(config); - if (!validationRes.success) { - ue(validationRes.message); + if (!isInputConfigValid(config)) { + ue(BadConfigMsg); return process.exit(1); } const { exitCode, stderr, stdout } = await $2`${OPS} -config -d`.quiet(); diff --git a/util/config/configurator/configurator.ts b/util/config/configurator/configurator.ts index b24bb35..ec7befa 100644 --- a/util/config/configurator/configurator.ts +++ b/util/config/configurator/configurator.ts @@ -306,7 +306,7 @@ export function isInputConfigValid(body: Record<string, any>): boolean { // 3. Check that all the keys are uppercase and can only have underscores not at the beginning or end for (const key in body) { - if (!/^[A-Z][A-Z_]*[A-Z]$/.test(key)) { + if (!/^[A-Z][A-Z_]|[0-9]*[A-Z]|[0-9]$/.test(key)) { return false; } } diff --git a/util/config/configurator/tests/fixtures/valid.json b/util/config/configurator/tests/fixtures/valid.json index 1587c92..8ad24f6 100644 --- a/util/config/configurator/tests/fixtures/valid.json +++ b/util/config/configurator/tests/fixtures/valid.json @@ -1,5 +1,11 @@ { "HELLO": { "type": "string" + }, + "HELLO3": { + "type": "string" + }, + "HELLO_3": { + "type": "string" } } diff --git a/util/config/configurator/tests/index.test.ts b/util/config/configurator/tests/index.test.ts index bdf74d0..0d10cc3 100644 --- a/util/config/configurator/tests/index.test.ts +++ b/util/config/configurator/tests/index.test.ts @@ -56,11 +56,18 @@ describe("validateConfigJson", () => { test("valid json", async () => { const res = isInputConfigValid({ HELLO: { type: "string" }, + HELLO3: { type: "string" }, + HELLO33: { type: "string" }, + HELLO_3: { type: "string" }, + HELLO_33: { type: "string" }, + HELLO_A_1_B_2: { type: "string" }, + HELLO_A1B2: { type: "string" }, HELLO_INT: { type: "int" }, HELLO_FLOAT: { type: "float" }, HELLO_BOOL: { type: "bool" }, HELLOPASS: { type: "password" }, HELLOENUM: { type: ["a", "b", "c"] }, + HELLOENUM3: { type: ["a", "b", "c"] }, }); expect(res).toBe(true); }); @@ -109,6 +116,8 @@ describe("parsePositionalFile", () => { test("valid json", async () => { const jsonRes = await parsePositionalFile("tests//fixtures/valid.json"); expect(jsonRes.success).toBe(true); - expect(jsonRes.body).toEqual({ HELLO: { type: "string" } }); + expect(jsonRes.body).toHaveProperty("HELLO", { type: "string" } ); + expect(jsonRes.body).toHaveProperty("HELLO3", { type: "string" } ); + expect(jsonRes.body).toHaveProperty("HELLO_3", { type: "string" }); }); });
