@coalescesoftware/coa 1.0.156 → 1.0.159

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.GetCLIConfig = exports.ICLIProfileExample = exports.GetDefaultLocationForCoaConfigFile = void 0;
23
+ /* eslint-disable multiline-comment-style */
24
+ const Shared = __importStar(require("@coalescesoftware/shared"));
25
+ const immer = __importStar(require("immer"));
26
+ const os = require('os');
27
+ const path = require('path');
28
+ const ini = require('ini');
29
+ const fs = require('fs');
30
+ const RemoveCredentialsFromCLIProfile = (cliProfile) => {
31
+ return immer.produce(cliProfile, (draft) => {
32
+ if (draft.snowflakePassword)
33
+ draft.snowflakePassword = '<REDACTED>';
34
+ if (draft.snowflakeAccount)
35
+ draft.snowflakeAccount = '<REDACTED>';
36
+ });
37
+ };
38
+ const RemoveCredentialsFromCLIProfiles = (cliProfiles) => {
39
+ return immer.produce(cliProfiles, (draftState) => {
40
+ Object.keys(draftState).forEach((cliProfileName) => {
41
+ draftState[cliProfileName] = RemoveCredentialsFromCLIProfile(cliProfiles[cliProfileName]);
42
+ });
43
+ });
44
+ };
45
+ const CLILogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL);
46
+ const GetDefaultLocationForCoaConfigFile = () => {
47
+ const homedir = os.homedir();
48
+ const coaConfigLocation = path.join(homedir, ".coa/config");
49
+ CLILogger.info("using default location", coaConfigLocation);
50
+ return coaConfigLocation;
51
+ };
52
+ exports.GetDefaultLocationForCoaConfigFile = GetDefaultLocationForCoaConfigFile;
53
+ //voodoo typescript magic in order to get runtime and compiletime ICLIProfile code
54
+ //https://stackoverflow.com/questions/45670705/iterate-over-interface-properties-in-typescript
55
+ exports.ICLIProfileExample = {
56
+ profile: "Profile To Use",
57
+ environmentID: "Environment ID",
58
+ parameters: "Parameters",
59
+ snowflakeAccount: "Snowflake Account To Use",
60
+ snowflakeAuthType: "Snowflake Auth Type (Basic, KeyPair)",
61
+ snowflakeKeyPairPath: "Snowflake Key Pair Path",
62
+ snowflakeKeyPairPass: "Snowflake Key Pair Pass",
63
+ snowflakePassword: "Snowflake Password",
64
+ snowflakeRole: "Snowflake Role",
65
+ snowflakeUsername: "Snowflake Username",
66
+ snowflakeWarehouse: "Snowflake Warehouse",
67
+ token: "Coalesce Token",
68
+ jobID: "Coalesce JobID",
69
+ include: "Coalesce Node Selector",
70
+ exclude: "Coalesce Node Selector"
71
+ };
72
+ const ReadCLIProfiles = (filePath) => {
73
+ let filePathToUse;
74
+ if (!filePath) {
75
+ filePathToUse = (0, exports.GetDefaultLocationForCoaConfigFile)();
76
+ }
77
+ else {
78
+ filePathToUse = filePath;
79
+ }
80
+ return fs.promises.readFile(filePathToUse, 'utf-8')
81
+ .then((file) => {
82
+ return ini.parse(file);
83
+ })
84
+ .catch((err) => {
85
+ CLILogger.error("unable to read cli profile file filePath:", filePath, err);
86
+ if (!filePath) //if no filepath was specified, silently proceed
87
+ return {};
88
+ else //unable to proceed couldnt read file
89
+ throw new Error(`unable to read cli profile:${filePathToUse}`);
90
+ });
91
+ };
92
+ const GetFinalCLIProfile = (commandLineOverrides, configFileLocation) => {
93
+ let profileToUseOverride = commandLineOverrides.profile ? commandLineOverrides.profile : null;
94
+ return ReadCLIProfiles(configFileLocation)
95
+ .then((cliProfiles) => {
96
+ const defaultCLIProfile = cliProfiles.default;
97
+ let finalCLIProfile = {};
98
+ //if theres a default cli profile, start with that
99
+ if (defaultCLIProfile) {
100
+ finalCLIProfile = defaultCLIProfile;
101
+ }
102
+ //if a profile has been specified, use that
103
+ const profileToUse = profileToUseOverride || //cli override
104
+ (!!defaultCLIProfile && defaultCLIProfile.profile) //default profile exists
105
+ || "";
106
+ CLILogger.info("using profile", profileToUse, "cliProfiles", JSON.stringify(RemoveCredentialsFromCLIProfiles(cliProfiles)));
107
+ if (profileToUse) {
108
+ if (!(profileToUse in cliProfiles)) {
109
+ throw new Error(`unable to find profile ${profileToUse}`);
110
+ }
111
+ const coaConfigProfile = cliProfiles[profileToUse];
112
+ finalCLIProfile = Object.assign(Object.assign({}, finalCLIProfile), coaConfigProfile);
113
+ }
114
+ finalCLIProfile = Object.assign(Object.assign({}, finalCLIProfile), commandLineOverrides);
115
+ return finalCLIProfile;
116
+ });
117
+ };
118
+ //Get CLI Config given command line overrides and a config file
119
+ //config file location can be null - which means to use default location
120
+ const GetCLIConfig = (commandLineOverrides, configFileLocation) => {
121
+ return GetFinalCLIProfile(commandLineOverrides, configFileLocation).then((cliProfile) => {
122
+ CLILogger.info("got final cli profile configFileLocation:", configFileLocation, JSON.stringify(RemoveCredentialsFromCLIProfile(cliProfile)));
123
+ const cliConfig = {
124
+ token: cliProfile.token,
125
+ runDetails: {
126
+ environmentID: cliProfile.environmentID,
127
+ jobID: cliProfile.jobID,
128
+ includeNodesSelector: cliProfile.include,
129
+ excludeNodesSelector: cliProfile.exclude
130
+ },
131
+ userCredentials: {
132
+ snowflakeAccount: cliProfile.snowflakeAccount,
133
+ snowflakeAuthType: cliProfile.snowflakeAuthType,
134
+ snowflakePassword: cliProfile.snowflakePassword,
135
+ snowflakeKeyPairPath: cliProfile.snowflakeKeyPairPath,
136
+ snowflakeKeyPairPass: cliProfile.snowflakeKeyPairPass,
137
+ snowflakeRole: cliProfile.snowflakeRole,
138
+ snowflakeUsername: cliProfile.snowflakeUsername,
139
+ snowflakeWarehouse: cliProfile.snowflakeWarehouse
140
+ },
141
+ runtimeParameters: cliProfile.parameters
142
+ };
143
+ Shared.Common.CleanupUndefinedValuesFromObject(cliConfig);
144
+ return cliConfig;
145
+ });
146
+ };
147
+ exports.GetCLIConfig = GetCLIConfig;
148
+ // TODO: create a profile class that takes the cmd object in the constructor
149
+ // store contents of configuration file
150
+ // if no config file path option
151
+ // check if there's a valid configuration file in the current working directory or home directory
152
+ // if none exists
153
+ // create a configuration file with empty default profile
154
+ // prompt user to either rerun the command with valid config file, per-command flags for all profile values, or run `coa init` to go through prompts for creating a profile
155
+ // if a configuration file exists, but any required property holds a falsy value
156
+ // inform user which fields are missing and prompt to run `coa init` to fill out invalid fields
157
+ // method: validate configuration file
158
+ // method: get final profile for current command
159
+ // create a function getCLIProfile that returns a CLI profile, this should return a promise that resolve in CLI profile
160
+ // hardcode a profile
161
+ //# sourceMappingURL=CLIProfile.js.map
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.FinishWithOutputFile = exports.ValidateRuntimeParameters = exports.GetRuntimeParametersFromFirestore = exports.GetUserConnectionForCLI = exports.CleanupCLIJob = void 0;
23
+ const Shared = __importStar(require("@coalescesoftware/shared"));
24
+ const fs = __importStar(require("fs"));
25
+ const crypto = __importStar(require("crypto"));
26
+ const RunOutput = __importStar(require("./RunOutput"));
27
+ const RunnerBackendLogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.RunnerBackend);
28
+ const LogCLIInternal = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL);
29
+ const CleanupCLIJob = (runCompletion, firebase, logContext, action) => {
30
+ const cleanupPromise = new Promise((resolve, reject) => {
31
+ let promiseError = null;
32
+ runCompletion
33
+ .catch((error) => {
34
+ promiseError = error;
35
+ })
36
+ .finally(() => {
37
+ try {
38
+ if (firebase) {
39
+ Shared.Common.DeleteFirebaseInstance(firebase);
40
+ }
41
+ }
42
+ catch (error) {
43
+ RunnerBackendLogger.errorContext(logContext, `Error during ${action}WithCLI Finally cleanup: `, error);
44
+ }
45
+ if (promiseError) {
46
+ reject(promiseError);
47
+ }
48
+ else {
49
+ resolve();
50
+ }
51
+ });
52
+ });
53
+ return cleanupPromise;
54
+ };
55
+ exports.CleanupCLIJob = CleanupCLIJob;
56
+ const GetKeyPairKey = (keyPairPath, keyPairPass) => {
57
+ return new Promise((resolve, reject) => {
58
+ Shared.Common.assert(Shared.Logging.LoggingArea.RunnerBackend, !!keyPairPath, "ERROR (GetKeyPairPath): invalid or missing keyPairPath");
59
+ const privateKeyFile = fs.readFileSync(keyPairPath);
60
+ const privateKeyObject = crypto.createPrivateKey({
61
+ key: privateKeyFile,
62
+ format: "pem",
63
+ passphrase: keyPairPass
64
+ });
65
+ const privateKey = privateKeyObject.export({
66
+ format: "pem",
67
+ type: "pkcs8"
68
+ });
69
+ if (!privateKey) {
70
+ reject(new Error("ERROR (GetKeyPairPath): invalid or missing privateKey"));
71
+ }
72
+ else {
73
+ resolve(privateKey);
74
+ }
75
+ });
76
+ };
77
+ const GetUserConnectionForCLI = (userID, runInfo) => {
78
+ return new Promise((resolve, reject) => {
79
+ var _a, _b, _c, _d, _e, _f;
80
+ const output = {
81
+ connectionDetails: {
82
+ userID,
83
+ user: (_a = runInfo.userCredentials) === null || _a === void 0 ? void 0 : _a.snowflakeUsername,
84
+ role: (_b = runInfo.userCredentials) === null || _b === void 0 ? void 0 : _b.snowflakeRole,
85
+ warehouse: (_c = runInfo.userCredentials) === null || _c === void 0 ? void 0 : _c.snowflakeWarehouse,
86
+ },
87
+ connectionType: (_d = runInfo.userCredentials) === null || _d === void 0 ? void 0 : _d.snowflakeAuthType
88
+ };
89
+ if (!((_e = runInfo.userCredentials) === null || _e === void 0 ? void 0 : _e.snowflakeAuthType)) {
90
+ reject(new Error("ERROR (GetUserConnectionForCLI): no auth type provided"));
91
+ }
92
+ else if (((_f = runInfo.userCredentials) === null || _f === void 0 ? void 0 : _f.snowflakeAuthType) === Shared.ConnectionOperations.EUserConnectionTypes.keyPair) {
93
+ GetKeyPairKey(Shared.Common.getValueSafe(runInfo, ["userCredentials", "snowflakeKeyPairPath"], ""), Shared.Common.getValueSafe(runInfo, ["userCredentials", "snowflakeKeyPairPass"], ""))
94
+ .then((keyPair) => {
95
+ output.connectionDetails.keyPair = keyPair;
96
+ resolve(output);
97
+ })
98
+ .catch((err) => {
99
+ reject(err);
100
+ });
101
+ }
102
+ else {
103
+ resolve(output);
104
+ }
105
+ });
106
+ };
107
+ exports.GetUserConnectionForCLI = GetUserConnectionForCLI;
108
+ ////////
109
+ // Runtime Parameters
110
+ ///////
111
+ const GetRuntimeParametersFromFirestore = (firestore, teamID, environmentID) => {
112
+ return Shared.CommonOperations.getWorkspaceDocumentRefAdmin(firestore, teamID, environmentID).get().then((workspace) => {
113
+ return workspace.get("runTimeParameters");
114
+ });
115
+ };
116
+ exports.GetRuntimeParametersFromFirestore = GetRuntimeParametersFromFirestore;
117
+ const ValidateRuntimeParameters = (runtimeParameters) => {
118
+ try {
119
+ JSON.parse(runtimeParameters);
120
+ }
121
+ catch (error) {
122
+ throw new Error(`Failed to parse runtime parameters: ${error.message}`);
123
+ }
124
+ };
125
+ exports.ValidateRuntimeParameters = ValidateRuntimeParameters;
126
+ ////////
127
+ // Output File
128
+ ///////
129
+ const FinishWithOutputFile = (logContextToUse, outputFilePath, runCounter, token) => {
130
+ if (!outputFilePath) {
131
+ return Promise.resolve();
132
+ }
133
+ else {
134
+ LogCLIInternal.infoContext(logContextToUse, "saving run results to file", outputFilePath);
135
+ return RunOutput.SaveRunOutputToFile(outputFilePath, runCounter.toString(), token);
136
+ }
137
+ };
138
+ exports.FinishWithOutputFile = FinishWithOutputFile;
139
+ //# sourceMappingURL=CommonCLI.js.map
package/bin/Deploy.js ADDED
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.DeployWithCLI = void 0;
23
+ const Shared = __importStar(require("@coalescesoftware/shared"));
24
+ const CommonCLI = __importStar(require("./CommonCLI"));
25
+ const CryptoJS = require("crypto-js");
26
+ const v8 = require("v8");
27
+ Shared.Snowflake.CryptoJS = CryptoJS;
28
+ Shared.Snowflake.salt = CryptoJS.lib.WordArray.random(128 / 8);
29
+ Shared.Snowflake.v8 = v8;
30
+ const LogCLI = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI);
31
+ /**
32
+ *
33
+ * @param plan
34
+ * @param config
35
+ * @param token
36
+ * @returns
37
+ */
38
+ const DeployWithCLI = (plan, config, token) => {
39
+ let firebase;
40
+ let logContext;
41
+ let teamDetailsStored;
42
+ let RunSQL;
43
+ let runInfo;
44
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined).then((teamDetails) => {
45
+ var _a;
46
+ teamDetailsStored = teamDetails;
47
+ const { teamInfo, teamInfo: { fbUserID: userID, fbTeamID: teamID } } = teamDetails;
48
+ firebase = teamDetails.firebase;
49
+ const environmentID = +((_a = config.runDetails) === null || _a === void 0 ? void 0 : _a.environmentID);
50
+ logContext = Shared.Logging.CreateLogContext(teamID, environmentID, userID);
51
+ const connectionCache = new Shared.Snowflake.ConnectionStorageClass();
52
+ RunSQL = Shared.SQLExecutorCreators.CreateRunSQLWithoutScheduler(teamDetails, connectionCache);
53
+ runInfo = Shared.DeployOperations.CreateDeployRequestObject(plan.plan, plan.environmentState, teamInfo, plan.gitInfo, plan.targetEnvironment, plan.runtimeParameters);
54
+ runInfo.userCredentials = config.userCredentials;
55
+ return CommonCLI.GetUserConnectionForCLI(userID, runInfo);
56
+ })
57
+ .then((connection) => {
58
+ LogCLI.infoContext(logContext, "Deploy starting (CLI)");
59
+ return Shared.SchedulerOperations.BECLI_HandleDeploy(runInfo, teamDetailsStored, RunSQL, connection);
60
+ })
61
+ .then(({ runCounter, runCompletion }) => {
62
+ const cleanupPromise = CommonCLI.CleanupCLIJob(runCompletion, firebase, logContext, "Deploy");
63
+ return {
64
+ runCounter,
65
+ runCompletion: cleanupPromise,
66
+ logContext,
67
+ };
68
+ });
69
+ };
70
+ exports.DeployWithCLI = DeployWithCLI;
71
+ //# sourceMappingURL=Deploy.js.map