@coalescesoftware/coa 1.0.112 → 1.0.115
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.
- package/bin/CLIProfile.js +22 -10
- package/bin/{Common.js → CommonCLI/CommonCLI.js} +28 -9
- package/bin/CommonCLI/CommonCLI.test.js +28 -0
- package/bin/CommonCLI.js +38 -6
- package/bin/Deploy/Deploy.js +70 -0
- package/bin/Deploy.js +1 -1
- package/bin/Package.js +758 -0
- package/bin/Plan/Plan.js +41 -0
- package/bin/Plan.js +2 -2
- package/bin/Refresh/Refresh.js +65 -0
- package/bin/RunOutput.js +82 -0
- package/bin/index.js +266 -29
- package/package.json +3 -2
- package/bin/CLIOperations.js +0 -135
- package/bin/Profile.js +0 -53
package/bin/CLIProfile.js
CHANGED
|
@@ -55,6 +55,7 @@ exports.GetDefaultLocationForCoaConfigFile = GetDefaultLocationForCoaConfigFile;
|
|
|
55
55
|
exports.ICLIProfileExample = {
|
|
56
56
|
profile: "Profile To Use",
|
|
57
57
|
environmentID: "Environment ID",
|
|
58
|
+
parameters: "Parameters",
|
|
58
59
|
snowflakeAccount: "Snowflake Account To Use",
|
|
59
60
|
snowflakeAuthType: "Snowflake Auth Type (Basic, KeyPair)",
|
|
60
61
|
snowflakeKeyPairPath: "Snowflake Key Pair Path",
|
|
@@ -68,21 +69,29 @@ exports.ICLIProfileExample = {
|
|
|
68
69
|
exclude: "Coalesce Node Selector"
|
|
69
70
|
};
|
|
70
71
|
const ReadCLIProfiles = (filePath) => {
|
|
71
|
-
|
|
72
|
+
let filePathToUse;
|
|
73
|
+
if (!filePath) {
|
|
74
|
+
filePathToUse = (0, exports.GetDefaultLocationForCoaConfigFile)();
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
filePathToUse = filePath;
|
|
78
|
+
}
|
|
79
|
+
return fs.promises.readFile(filePathToUse, 'utf-8')
|
|
80
|
+
.then((file) => {
|
|
72
81
|
return ini.parse(file);
|
|
73
|
-
})
|
|
82
|
+
})
|
|
83
|
+
.catch((err) => {
|
|
74
84
|
CLILogger.error("unable to read cli profile file filePath:", filePath, err);
|
|
75
|
-
|
|
85
|
+
if (!filePath) //if no filepath was specified, silently proceed
|
|
86
|
+
return {};
|
|
87
|
+
else //unable to proceed couldnt read file
|
|
88
|
+
throw new Error(`unable to read cli profile:${filePathToUse}`);
|
|
76
89
|
});
|
|
77
90
|
};
|
|
78
91
|
const GetFinalCLIProfile = (commandLineOverrides, configFileLocation) => {
|
|
79
92
|
let profileToUseOverride = commandLineOverrides.profile ? commandLineOverrides.profile : null;
|
|
80
|
-
return ReadCLIProfiles(configFileLocation)
|
|
81
|
-
|
|
82
|
-
}).catch((err) => {
|
|
83
|
-
//unable to read cli profiles
|
|
84
|
-
return {};
|
|
85
|
-
}).then((cliProfiles) => {
|
|
93
|
+
return ReadCLIProfiles(configFileLocation)
|
|
94
|
+
.then((cliProfiles) => {
|
|
86
95
|
const defaultCLIProfile = cliProfiles.default;
|
|
87
96
|
let finalCLIProfile = {};
|
|
88
97
|
//if theres a default cli profile, start with that
|
|
@@ -105,6 +114,8 @@ const GetFinalCLIProfile = (commandLineOverrides, configFileLocation) => {
|
|
|
105
114
|
return finalCLIProfile;
|
|
106
115
|
});
|
|
107
116
|
};
|
|
117
|
+
//Get CLI Config given command line overrides and a config file
|
|
118
|
+
//config file location can be null - which means to use default location
|
|
108
119
|
const GetCLIConfig = (commandLineOverrides, configFileLocation) => {
|
|
109
120
|
return GetFinalCLIProfile(commandLineOverrides, configFileLocation).then((cliProfile) => {
|
|
110
121
|
CLILogger.info("got final cli profile configFileLocation:", configFileLocation, JSON.stringify(RemoveCredentialsFromCLIProfile(cliProfile)));
|
|
@@ -124,7 +135,8 @@ const GetCLIConfig = (commandLineOverrides, configFileLocation) => {
|
|
|
124
135
|
snowflakeRole: cliProfile.snowflakeRole,
|
|
125
136
|
snowflakeUsername: cliProfile.snowflakeUsername,
|
|
126
137
|
snowflakeWarehouse: cliProfile.snowflakeWarehouse
|
|
127
|
-
}
|
|
138
|
+
},
|
|
139
|
+
runtimeParameters: cliProfile.parameters
|
|
128
140
|
};
|
|
129
141
|
Shared.Common.CleanupUndefinedValuesFromObject(cliConfig);
|
|
130
142
|
return cliConfig;
|
|
@@ -19,11 +19,32 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.GetUserConnectionForCLI = exports.CleanupCLIJob = void 0;
|
|
22
|
+
exports.GetUserConnectionForCLI = exports.CleanupCLIJob = exports.GetToken = exports.GetConfig = exports.ConsoleLog = void 0;
|
|
23
23
|
const Shared = __importStar(require("@coalescesoftware/shared"));
|
|
24
|
-
const fs = __importStar(require("fs"));
|
|
25
24
|
const crypto = __importStar(require("crypto"));
|
|
25
|
+
const fs = __importStar(require("fs"));
|
|
26
26
|
const RunnerBackendLogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.RunnerBackend);
|
|
27
|
+
exports.ConsoleLog = console.log;
|
|
28
|
+
const GetConfig = (path) => {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(fs.readFileSync(path, { encoding: "utf8" }));
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
(0, exports.ConsoleLog)(`Unable to read or parse config file: ${error}`);
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.GetConfig = GetConfig;
|
|
38
|
+
const GetToken = (path) => {
|
|
39
|
+
try {
|
|
40
|
+
return fs.readFileSync(path, { encoding: "utf8" }).trim();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
(0, exports.ConsoleLog)(`Unable to read token file: ${error}`);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.GetToken = GetToken;
|
|
27
48
|
const CleanupCLIJob = (runCompletion, firebase, logContext, action) => {
|
|
28
49
|
const cleanupPromise = new Promise((resolve, reject) => {
|
|
29
50
|
let promiseError = null;
|
|
@@ -75,20 +96,18 @@ const GetKeyPairKey = (keyPairPath) => {
|
|
|
75
96
|
const GetUserConnectionForCLI = (userID, runInfo) => {
|
|
76
97
|
return new Promise((resolve, reject) => {
|
|
77
98
|
var _a, _b, _c, _d;
|
|
99
|
+
Shared.Common.assert(Shared.Logging.LoggingArea.RunnerBackend, !!((_a = runInfo.userCredentials) === null || _a === void 0 ? void 0 : _a.snowflakeAuthType), "ERROR (GetUserConnectionForCLI): no auth type provided");
|
|
78
100
|
const output = {
|
|
79
101
|
connectionDetails: {
|
|
80
102
|
userID,
|
|
81
103
|
user: "mx2323",
|
|
82
104
|
role: "SYSADMIN",
|
|
83
105
|
warehouse: "COMPUTE_WH",
|
|
84
|
-
authenticator: (
|
|
106
|
+
authenticator: (_b = runInfo.userCredentials) === null || _b === void 0 ? void 0 : _b.snowflakeAuthType
|
|
85
107
|
},
|
|
86
|
-
connectionType: (
|
|
108
|
+
connectionType: (_c = runInfo.userCredentials) === null || _c === void 0 ? void 0 : _c.snowflakeAuthType
|
|
87
109
|
};
|
|
88
|
-
if (
|
|
89
|
-
reject(new Error("ERROR (GetUserConnectionForCLI): no auth type provided"));
|
|
90
|
-
}
|
|
91
|
-
else if (((_d = runInfo.userCredentials) === null || _d === void 0 ? void 0 : _d.snowflakeAuthType) === Shared.ConnectionOperations.EUserConnectionTypes.keyPair) {
|
|
110
|
+
if (((_d = runInfo.userCredentials) === null || _d === void 0 ? void 0 : _d.snowflakeAuthType) === Shared.ConnectionOperations.EUserConnectionTypes.keyPair) {
|
|
92
111
|
GetKeyPairKey(Shared.Common.getValueSafe(runInfo, ["userCredentials", "snowflakeKeyPairPath"], ""))
|
|
93
112
|
.then((keyPair) => {
|
|
94
113
|
output.connectionDetails.keyPair = keyPair;
|
|
@@ -104,4 +123,4 @@ const GetUserConnectionForCLI = (userID, runInfo) => {
|
|
|
104
123
|
});
|
|
105
124
|
};
|
|
106
125
|
exports.GetUserConnectionForCLI = GetUserConnectionForCLI;
|
|
107
|
-
//# sourceMappingURL=
|
|
126
|
+
//# sourceMappingURL=CommonCLI.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
const CommonCLI = __importStar(require("./CommonCLI"));
|
|
23
|
+
test("should fail to read and parse invalid JSON", () => {
|
|
24
|
+
expect(() => {
|
|
25
|
+
CommonCLI.GetConfig("cli/src/__mocks__/invalid.json");
|
|
26
|
+
}).toThrow("Unexpected token I in JSON at position 0");
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=CommonCLI.test.js.map
|
package/bin/CommonCLI.js
CHANGED
|
@@ -19,11 +19,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.GetUserConnectionForCLI = exports.CleanupCLIJob = void 0;
|
|
22
|
+
exports.FinishWithOutputFile = exports.ValidateRuntimeParameters = exports.GetRuntimeParametersFromFirestore = exports.GetUserConnectionForCLI = exports.CleanupCLIJob = void 0;
|
|
23
23
|
const Shared = __importStar(require("@coalescesoftware/shared"));
|
|
24
24
|
const fs = __importStar(require("fs"));
|
|
25
25
|
const crypto = __importStar(require("crypto"));
|
|
26
|
+
const RunOutput = __importStar(require("./RunOutput"));
|
|
26
27
|
const RunnerBackendLogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.RunnerBackend);
|
|
28
|
+
const LogCLIInternal = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL);
|
|
27
29
|
const CleanupCLIJob = (runCompletion, firebase, logContext, action) => {
|
|
28
30
|
const cleanupPromise = new Promise((resolve, reject) => {
|
|
29
31
|
let promiseError = null;
|
|
@@ -74,21 +76,20 @@ const GetKeyPairKey = (keyPairPath) => {
|
|
|
74
76
|
};
|
|
75
77
|
const GetUserConnectionForCLI = (userID, runInfo) => {
|
|
76
78
|
return new Promise((resolve, reject) => {
|
|
77
|
-
var _a, _b, _c, _d, _e, _f
|
|
79
|
+
var _a, _b, _c, _d, _e, _f;
|
|
78
80
|
const output = {
|
|
79
81
|
connectionDetails: {
|
|
80
82
|
userID,
|
|
81
83
|
user: (_a = runInfo.userCredentials) === null || _a === void 0 ? void 0 : _a.snowflakeUsername,
|
|
82
84
|
role: (_b = runInfo.userCredentials) === null || _b === void 0 ? void 0 : _b.snowflakeRole,
|
|
83
85
|
warehouse: (_c = runInfo.userCredentials) === null || _c === void 0 ? void 0 : _c.snowflakeWarehouse,
|
|
84
|
-
authenticator: (_d = runInfo.userCredentials) === null || _d === void 0 ? void 0 : _d.snowflakeAuthType
|
|
85
86
|
},
|
|
86
|
-
connectionType: (
|
|
87
|
+
connectionType: (_d = runInfo.userCredentials) === null || _d === void 0 ? void 0 : _d.snowflakeAuthType
|
|
87
88
|
};
|
|
88
|
-
if (!((
|
|
89
|
+
if (!((_e = runInfo.userCredentials) === null || _e === void 0 ? void 0 : _e.snowflakeAuthType)) {
|
|
89
90
|
reject(new Error("ERROR (GetUserConnectionForCLI): no auth type provided"));
|
|
90
91
|
}
|
|
91
|
-
else if (((
|
|
92
|
+
else if (((_f = runInfo.userCredentials) === null || _f === void 0 ? void 0 : _f.snowflakeAuthType) === Shared.ConnectionOperations.EUserConnectionTypes.keyPair) {
|
|
92
93
|
GetKeyPairKey(Shared.Common.getValueSafe(runInfo, ["userCredentials", "snowflakeKeyPairPath"], ""))
|
|
93
94
|
.then((keyPair) => {
|
|
94
95
|
output.connectionDetails.keyPair = keyPair;
|
|
@@ -104,4 +105,35 @@ const GetUserConnectionForCLI = (userID, runInfo) => {
|
|
|
104
105
|
});
|
|
105
106
|
};
|
|
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;
|
|
107
139
|
//# sourceMappingURL=CommonCLI.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
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/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, runInfo, RunSQL;
|
|
42
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined)
|
|
43
|
+
.then((teamDetails) => {
|
|
44
|
+
var _a;
|
|
45
|
+
teamDetailsStored = teamDetails;
|
|
46
|
+
const { teamInfo, teamInfo: { fbUserID: userID, fbTeamID: teamID } } = teamDetails;
|
|
47
|
+
firebase = teamDetails.firebase;
|
|
48
|
+
const environmentID = (_a = config.runDetails) === null || _a === void 0 ? void 0 : _a.environmentID;
|
|
49
|
+
logContext = Shared.Logging.CreateLogContext(teamID, environmentID, userID);
|
|
50
|
+
const connectionCache = new Shared.Snowflake.ConnectionStorageClass();
|
|
51
|
+
RunSQL = Shared.SQLExecutorCreators.CreateRunSQLWithoutScheduler(teamDetails, connectionCache);
|
|
52
|
+
runInfo = Shared.DeployOperations.CreateDeployRequestObject(plan.plan, plan.environmentState, teamInfo, plan.gitInfo, plan.targetEnvironment, "");
|
|
53
|
+
runInfo.userCredentials = config.userCredentials;
|
|
54
|
+
return CommonCLI.GetUserConnectionForCLI(userID, runInfo);
|
|
55
|
+
})
|
|
56
|
+
.then((connection) => {
|
|
57
|
+
LogCLI.infoContext(logContext, "Deploy starting (CLI)");
|
|
58
|
+
return Shared.SchedulerOperations.HandleDeploy(runInfo, teamDetailsStored, RunSQL, connection);
|
|
59
|
+
})
|
|
60
|
+
.then(({ runCounter, runCompletion }) => {
|
|
61
|
+
const cleanupPromise = CommonCLI.CleanupCLIJob(runCompletion, firebase, logContext, "Deploy");
|
|
62
|
+
return {
|
|
63
|
+
runCounter,
|
|
64
|
+
runCompletion: cleanupPromise,
|
|
65
|
+
logContext,
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
exports.DeployWithCLI = DeployWithCLI;
|
|
70
|
+
//# sourceMappingURL=Deploy.js.map
|
package/bin/Deploy.js
CHANGED
|
@@ -50,7 +50,7 @@ const DeployWithCLI = (plan, config, token) => {
|
|
|
50
50
|
logContext = Shared.Logging.CreateLogContext(teamID, environmentID, userID);
|
|
51
51
|
const connectionCache = new Shared.Snowflake.ConnectionStorageClass();
|
|
52
52
|
RunSQL = Shared.SQLExecutorCreators.CreateRunSQLWithoutScheduler(teamDetails, connectionCache);
|
|
53
|
-
runInfo = Shared.DeployOperations.CreateDeployRequestObject(plan.plan, plan.environmentState, teamInfo, plan.gitInfo, plan.targetEnvironment,
|
|
53
|
+
runInfo = Shared.DeployOperations.CreateDeployRequestObject(plan.plan, plan.environmentState, teamInfo, plan.gitInfo, plan.targetEnvironment, plan.runtimeParameters);
|
|
54
54
|
runInfo.userCredentials = config.userCredentials;
|
|
55
55
|
return CommonCLI.GetUserConnectionForCLI(userID, runInfo);
|
|
56
56
|
})
|