diff --git a/src/commands/infra/generate.test.ts b/src/commands/infra/generate.test.ts index c0d642824..a5b5b6182 100644 --- a/src/commands/infra/generate.test.ts +++ b/src/commands/infra/generate.test.ts @@ -188,7 +188,7 @@ describe("test gitClone function", () => { it("negative Test", async () => { const git = simpleGit(); git.clone = (): Promise => { - throw new Error("Error"); + throw Error("Error"); }; await expect(gitClone(git, "source", "path")).rejects.toThrow(); @@ -221,7 +221,7 @@ describe("Validate remote git source", () => { }); }); -jest.spyOn(generate, "gitClone").mockReturnValue(Promise.resolve()); +jest.spyOn(generate, "gitClone").mockResolvedValue(); jest.spyOn(generate, "createGenerated").mockReturnValue(); jest.spyOn(generate, "checkTfvars").mockReturnValue(); jest.spyOn(generate, "writeTfvarsFile").mockReturnValue(); @@ -302,9 +302,7 @@ describe("fetch execute function", () => { template: "", version: "", }); - jest - .spyOn(generate, "generateConfig") - .mockReturnValueOnce(Promise.resolve()); + jest.spyOn(generate, "generateConfig").mockResolvedValueOnce(); const exitFn = jest.fn(); await execute( @@ -394,9 +392,9 @@ describe("test validateRemoteSource function", () => { describe("test retryRemoteValidate function", () => { it("positive test", async () => { jest.spyOn(fsExtra, "removeSync").mockReturnValueOnce(); - jest.spyOn(generate, "gitClone").mockReturnValueOnce(Promise.resolve()); - jest.spyOn(generate, "gitFetchPull").mockReturnValueOnce(Promise.resolve()); - jest.spyOn(generate, "gitCheckout").mockReturnValueOnce(Promise.resolve()); + jest.spyOn(generate, "gitClone").mockResolvedValueOnce(); + jest.spyOn(generate, "gitFetchPull").mockResolvedValueOnce(); + jest.spyOn(generate, "gitCheckout").mockResolvedValueOnce(); await retryRemoteValidate("source", "sourcePath", "safeLoggingUrl", "0.1"); }); it("negative test", async () => { diff --git a/src/commands/infra/generate.ts b/src/commands/infra/generate.ts index f1939310c..033af823f 100644 --- a/src/commands/infra/generate.ts +++ b/src/commands/infra/generate.ts @@ -21,7 +21,7 @@ import { spkTemplatesPath, } from "./infra_common"; import { copyTfTemplate } from "./scaffold"; -import { build as buildError } from "../../lib/errorBuilder"; +import { build as buildError, log as logError } from "../../lib/errorBuilder"; import { errorStatusCode } from "../../lib/errorStatusCode"; interface CommandOptions { @@ -68,8 +68,9 @@ export const execute = async ( ); await exitFn(0); } catch (err) { - logger.error("Error occurred while generating project deployment files"); - logger.error(err); + logError( + buildError(errorStatusCode.CMD_EXE_ERR, "infra-generate-cmd-failed", err) + ); await exitFn(1); } }; @@ -119,7 +120,10 @@ export const validateDefinition = ( return DefinitionYAMLExistence.PARENT_ONLY; } - throw new Error(`${DEFINITION_YAML} was not found in ${parentPath}`); + throw buildError(errorStatusCode.ENV_SETTING_ERR, { + errorKey: "infra-defn-yaml-not-found", + values: [DEFINITION_YAML, parentPath], + }); }; export const getDefinitionYaml = (dir: string): InfraConfigYaml => { @@ -175,11 +179,10 @@ export const validateTemplateSources = ( ); return source; } - throw new Error( - `The ${DEFINITION_YAML} file is invalid. \ -There is a missing field for it's sources. \ -Template: ${source.template} source: ${source.source} version: ${source.version}` - ); + throw buildError(errorStatusCode.INCORRECT_DEFINITION, { + errorKey: "infra-defn-yaml-invalid", + values: [DEFINITION_YAML, source.template, source.source, source.version], + }); }; export const checkRemoteGitExist = async ( @@ -298,7 +301,7 @@ export const validateRemoteSource = async ( } else { throw buildError( errorStatusCode.GIT_OPS_ERR, - "infra-err-validating-remote-git", + "infra-err-validating-remote-git-after-retry", err ); } @@ -310,7 +313,11 @@ export const validateRemoteSource = async ( ); } } else { - throw err; + throw buildError( + errorStatusCode.GIT_OPS_ERR, + "infra-err-validating-remote-git", + err + ); } } }; @@ -353,6 +360,10 @@ export const generateConfigWithParentEqProjectPath = async ( writeTfvarsFile(spkTfvarsObject, parentDirectory, SPK_TFVARS); await copyTfTemplate(templatePath, parentDirectory, true); } else { + // Consider the case where the only common configuration is just + // backend configuration, and no common variable configuration. + // Thus, it is not "necessary" for a parent definition.yaml to + // have a variables block in a multi-cluster. logger.warn(`Variables are not defined in the definition.yaml`); } if (parentInfraConfig.backend) { @@ -360,6 +371,11 @@ export const generateConfigWithParentEqProjectPath = async ( checkTfvars(parentDirectory, BACKEND_TFVARS); writeTfvarsFile(backendTfvarsObject, parentDirectory, BACKEND_TFVARS); } else { + // Not all templates will require a remote backend + // (i.e Bedrock's azure-simple). + // If a remote backend is not configured for a template, + // it will be impossible to be able to use spk infra in a + // pipeline, but this can still work locally. logger.warn( `A remote backend configuration is not defined in the definition.yaml` ); diff --git a/src/commands/infra/scaffold.ts b/src/commands/infra/scaffold.ts index c1d8ef09e..1916a6b13 100644 --- a/src/commands/infra/scaffold.ts +++ b/src/commands/infra/scaffold.ts @@ -278,23 +278,24 @@ export const scaffold = (values: CommandOptions): void => { if (fs.existsSync(tfVariableFile)) { logger.info(`A ${VARIABLES_TF} file found : ${tfVariableFile}`); - const data: string = fs.readFileSync(tfVariableFile, "utf8"); + const data = fs.readFileSync(tfVariableFile, "utf8"); if (data) { const baseDef = generateClusterDefinition(values, backendData, data); + // baseDef shall be always defined based on what generateClusterDefinition + // function returns. hence we do not need to check if it is defined or not const definitionYaml = yaml.safeDump(baseDef); - if (baseDef) { - const confPath: string = path.format({ - base: DEFINITION_YAML, - dir: values.name, - root: "/ignored", - }); - fs.writeFileSync(confPath, definitionYaml, "utf8"); - } else { - throw Error(`Unable to generate cluster definition.`); - } + const confPath: string = path.format({ + base: DEFINITION_YAML, + dir: values.name, + root: "/ignored", + }); + fs.writeFileSync(confPath, definitionYaml, "utf8"); } else { - throw Error(`Unable to read variable file: ${tfVariableFile}.`); + throw buildError(errorStatusCode.ENV_SETTING_ERR, { + errorKey: "infra-unable-read-var-file", + values: [tfVariableFile], + }); } } } catch (err) { diff --git a/src/lib/errorStatusCode.ts b/src/lib/errorStatusCode.ts index 7b18d6859..5b34ee267 100644 --- a/src/lib/errorStatusCode.ts +++ b/src/lib/errorStatusCode.ts @@ -7,5 +7,6 @@ export enum errorStatusCode { EXE_FLOW_ERR = 1002, ENV_SETTING_ERR = 1010, FILE_IO_ERR = 1011, + INCORRECT_DEFINITION = 1012, GIT_OPS_ERR = 1100, } diff --git a/src/lib/i18n.json b/src/lib/i18n.json index 4b83c5657..71bfc0ad7 100644 --- a/src/lib/i18n.json +++ b/src/lib/i18n.json @@ -16,9 +16,16 @@ "storageKeVaultName": "Enter key vault name (have the value as empty and hit enter key to skip)" }, "errors": { - "infra-scaffold-cmd-failed": "Scaffold Command was not successfully executed.", + "infra-scaffold-cmd-failed": "Infra scaffold Command was not successfully executed.", "infra-scaffold-cmd-src-missing": "Value for source is required because it cannot be constructed with properties in spk-config.yaml. Provide value for source.", "infra-scaffold-cmd-values-missing": "Values for name, version and/or 'template were missing. Provide value for values for them.", + + "infra-generate-cmd-failed": "Infra generate Command was not successfully executed.", + + "infra-defn-yaml-not-found": "{0} was not found in {1}", + "infra-defn-yaml-invalid": "The {0} file is invalid. There are missing fields. template: {1} source: {2} version: {3}.", + "infra-unable-read-var-file": "Could read variable file: {0}. Make sure that it exists.", + "infra-err-validating-remote-git": "Could not determine error when validating remote git source.", "infra-err-retry-validating-remote-git": "Failure error thrown during retrying validating remote git source.", "infra-err-locate-tf-env": "Could not find Terraform environment. Ensure template path {0} exists.",