carlin 1.31.11 → 1.31.13
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/dist/index.js +4477 -4
- package/package.json +10 -10
- package/dist/cli.js +0 -246
- package/dist/config.js +0 -11
- package/dist/deploy/addDefaults.cloudformation.js +0 -151
- package/dist/deploy/baseStack/command.js +0 -9
- package/dist/deploy/baseStack/config.js +0 -30
- package/dist/deploy/baseStack/deployBaseStack.js +0 -62
- package/dist/deploy/baseStack/getBaseStackResource.js +0 -27
- package/dist/deploy/baseStack/getBucketTemplate.js +0 -46
- package/dist/deploy/baseStack/getLambdaImageBuilderTemplate.js +0 -188
- package/dist/deploy/baseStack/getLambdaLayerBuilderTemplate.js +0 -142
- package/dist/deploy/baseStack/getVpcTemplate.js +0 -169
- package/dist/deploy/cicd/cicd.template.js +0 -938
- package/dist/deploy/cicd/command.js +0 -31
- package/dist/deploy/cicd/command.options.js +0 -79
- package/dist/deploy/cicd/config.js +0 -8
- package/dist/deploy/cicd/deployCicd.js +0 -121
- package/dist/deploy/cicd/ecsTaskReportCommand.js +0 -55
- package/dist/deploy/cicd/getCicdStackName.js +0 -11
- package/dist/deploy/cicd/getTriggerPipelineObjectKey.js +0 -11
- package/dist/deploy/cicd/lambdas/cicdApiV1.handler.js +0 -124
- package/dist/deploy/cicd/lambdas/ecsTaskReport.handler.js +0 -126
- package/dist/deploy/cicd/lambdas/executeTasks.js +0 -67
- package/dist/deploy/cicd/lambdas/getProcessEnvVariable.js +0 -10
- package/dist/deploy/cicd/lambdas/githubWebhooksApiV1.handler.js +0 -148
- package/dist/deploy/cicd/lambdas/imageUpdaterSchedule.handler.js +0 -44
- package/dist/deploy/cicd/lambdas/index.js +0 -13
- package/dist/deploy/cicd/lambdas/pipelines.handler.js +0 -160
- package/dist/deploy/cicd/lambdas/putApprovalResultManualTask.js +0 -51
- package/dist/deploy/cicd/lambdas/shConditionalCommands.js +0 -30
- package/dist/deploy/cicd/pipelines.js +0 -86
- package/dist/deploy/cicd/readSSHKey.js +0 -34
- package/dist/deploy/cloudformation.core.js +0 -379
- package/dist/deploy/cloudformation.js +0 -189
- package/dist/deploy/command.js +0 -205
- package/dist/deploy/lambda/buildLambdaSingleFile.js +0 -67
- package/dist/deploy/lambda/deployLambdaCode.js +0 -43
- package/dist/deploy/lambda/deployLambdaLayers.js +0 -36
- package/dist/deploy/lambda/uploadCodeToECR.js +0 -53
- package/dist/deploy/lambda/uploadCodeToS3.js +0 -33
- package/dist/deploy/lambdaLayer/command.js +0 -50
- package/dist/deploy/lambdaLayer/deployLambdaLayer.js +0 -139
- package/dist/deploy/lambdaLayer/getPackageLambdaLayerStackName.js +0 -21
- package/dist/deploy/readDockerfile.js +0 -40
- package/dist/deploy/s3.js +0 -210
- package/dist/deploy/stackName.js +0 -85
- package/dist/deploy/staticApp/command.js +0 -86
- package/dist/deploy/staticApp/deployStaticApp.js +0 -65
- package/dist/deploy/staticApp/findDefaultBuildFolder.js +0 -44
- package/dist/deploy/staticApp/getStaticAppBucket.js +0 -19
- package/dist/deploy/staticApp/invalidateCloudFront.js +0 -44
- package/dist/deploy/staticApp/removeOldVersions.js +0 -56
- package/dist/deploy/staticApp/staticApp.template.js +0 -371
- package/dist/deploy/staticApp/uploadBuiltAppToS3.js +0 -28
- package/dist/deploy/utils.js +0 -31
- package/dist/deploy/vercel/command.js +0 -31
- package/dist/deploy/vercel/deployVercel.js +0 -59
- package/dist/generateEnv/generateEnv.js +0 -64
- package/dist/generateEnv/generateEnvCommand.js +0 -29
- package/dist/utils/addGroupToOptions.js +0 -11
- package/dist/utils/cloudFormationTemplate.js +0 -142
- package/dist/utils/codeBuild.js +0 -52
- package/dist/utils/environmentVariables.js +0 -16
- package/dist/utils/exec.js +0 -26
- package/dist/utils/formatCode.js +0 -34
- package/dist/utils/getAwsAccountId.js +0 -10
- package/dist/utils/getCurrentBranch.js +0 -35
- package/dist/utils/getEnvironment.js +0 -8
- package/dist/utils/getIamPath.js +0 -6
- package/dist/utils/getProjectName.js +0 -35
- package/dist/utils/index.js +0 -31
- package/dist/utils/packageJson.js +0 -32
- package/dist/utils/spawn.js +0 -34
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.validateTemplate = exports.destroy = exports.canDestroyStack = exports.deploy = exports.defaultTemplatePaths = exports.enableTerminationProtection = exports.updateStack = exports.createStack = exports.deleteStack = exports.printStackOutputsAfterDeploy = exports.getStackOutput = exports.describeStack = exports.describeStackEvents = exports.doesStackExist = exports.describeStackResource = exports.describeStacks = exports.cloudFormationV2 = exports.cloudformation = void 0;
|
|
30
|
-
const fs = __importStar(require("fs"));
|
|
31
|
-
const path = __importStar(require("path"));
|
|
32
|
-
const config_1 = require("./baseStack/config");
|
|
33
|
-
const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
|
|
34
|
-
const utils_1 = require("../utils");
|
|
35
|
-
const addDefaults_cloudformation_1 = require("./addDefaults.cloudformation");
|
|
36
|
-
const s3_1 = require("./s3");
|
|
37
|
-
const getBaseStackResource_1 = require("./baseStack/getBaseStackResource");
|
|
38
|
-
const aws_sdk_1 = __importDefault(require("aws-sdk"));
|
|
39
|
-
const npmlog_1 = __importDefault(require("npmlog"));
|
|
40
|
-
const logPrefix = 'cloudformation';
|
|
41
|
-
npmlog_1.default.addLevel('event', 10000, { fg: 'yellow' });
|
|
42
|
-
npmlog_1.default.addLevel('output', 10000, { fg: 'blue' });
|
|
43
|
-
/**
|
|
44
|
-
* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html
|
|
45
|
-
*/
|
|
46
|
-
const TEMPLATE_BODY_MAX_SIZE = 51200;
|
|
47
|
-
const isTemplateBodyGreaterThanMaxSize = (template) => {
|
|
48
|
-
return (Buffer.byteLength(JSON.stringify(template), 'utf8') >=
|
|
49
|
-
TEMPLATE_BODY_MAX_SIZE);
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* Update CloudFormation template to base stack bucket.
|
|
53
|
-
* @param input.stackName: CloudFormation stack name.
|
|
54
|
-
* @param input.template: CloudFormation template.
|
|
55
|
-
*/
|
|
56
|
-
const uploadTemplateToBaseStackBucket = async ({ stackName, template, }) => {
|
|
57
|
-
const bucketName = await (0, getBaseStackResource_1.getBaseStackResource)('BASE_STACK_BUCKET_LOGICAL_NAME');
|
|
58
|
-
const { url } = await (0, s3_1.uploadFileToS3)({
|
|
59
|
-
bucket: bucketName,
|
|
60
|
-
contentType: 'application/json',
|
|
61
|
-
key: `${config_1.BASE_STACK_BUCKET_TEMPLATES_FOLDER}/${stackName}.json`,
|
|
62
|
-
file: Buffer.from(JSON.stringify(template, null, 2)),
|
|
63
|
-
});
|
|
64
|
-
return { url };
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* CloudFormation client cache to avoid creating multiple clients.
|
|
68
|
-
* Each client is created with different parameters.
|
|
69
|
-
*/
|
|
70
|
-
const cloudFormationClients = {};
|
|
71
|
-
const cloudformation = () => {
|
|
72
|
-
const cloudFormationClientConfig = {
|
|
73
|
-
apiVersion: '2010-05-15',
|
|
74
|
-
region: (0, utils_1.getEnvVar)('REGION'),
|
|
75
|
-
};
|
|
76
|
-
const key = JSON.stringify(cloudFormationClientConfig);
|
|
77
|
-
if (!cloudFormationClients[key]) {
|
|
78
|
-
cloudFormationClients[key] = new client_cloudformation_1.CloudFormationClient({
|
|
79
|
-
apiVersion: '2010-05-15',
|
|
80
|
-
region: (0, utils_1.getEnvVar)('REGION'),
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
return cloudFormationClients[key];
|
|
84
|
-
};
|
|
85
|
-
exports.cloudformation = cloudformation;
|
|
86
|
-
const cloudFormationV2 = () => {
|
|
87
|
-
return new aws_sdk_1.default.CloudFormation({ apiVersion: '2010-05-15' });
|
|
88
|
-
};
|
|
89
|
-
exports.cloudFormationV2 = cloudFormationV2;
|
|
90
|
-
const describeStacks = async ({ stackName, } = {}) => {
|
|
91
|
-
const { Stacks } = await (0, exports.cloudformation)().send(new client_cloudformation_1.DescribeStacksCommand({ StackName: stackName }));
|
|
92
|
-
return Stacks;
|
|
93
|
-
};
|
|
94
|
-
exports.describeStacks = describeStacks;
|
|
95
|
-
const describeStackResource = async (input) => {
|
|
96
|
-
return (0, exports.cloudformation)().send(new client_cloudformation_1.DescribeStackResourceCommand(input));
|
|
97
|
-
};
|
|
98
|
-
exports.describeStackResource = describeStackResource;
|
|
99
|
-
const doesStackExist = async ({ stackName }) => {
|
|
100
|
-
npmlog_1.default.info(logPrefix, `Checking if stack ${stackName} already exists...`);
|
|
101
|
-
try {
|
|
102
|
-
await (0, exports.describeStacks)({ stackName });
|
|
103
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} already exists.`);
|
|
104
|
-
return true;
|
|
105
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
if (error.Code === 'ValidationError') {
|
|
109
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} does not exist.`);
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
throw error;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
exports.doesStackExist = doesStackExist;
|
|
116
|
-
const describeStackEvents = async ({ stackName, }) => {
|
|
117
|
-
npmlog_1.default.error(logPrefix, 'Stack events:');
|
|
118
|
-
const { StackEvents } = await (0, exports.cloudformation)().send(new client_cloudformation_1.DescribeStackEventsCommand({ StackName: stackName }));
|
|
119
|
-
const events = (StackEvents || [])
|
|
120
|
-
.filter(({ Timestamp }) => {
|
|
121
|
-
return Date.now() - Number(Timestamp) < 10 * 60 * 1000;
|
|
122
|
-
})
|
|
123
|
-
.filter(({ ResourceStatusReason }) => {
|
|
124
|
-
return ResourceStatusReason;
|
|
125
|
-
})
|
|
126
|
-
/**
|
|
127
|
-
* Show newer events last.
|
|
128
|
-
*/
|
|
129
|
-
.reverse();
|
|
130
|
-
events.forEach(({ LogicalResourceId, ResourceStatusReason }) => {
|
|
131
|
-
return npmlog_1.default.event(LogicalResourceId, ResourceStatusReason);
|
|
132
|
-
});
|
|
133
|
-
return events;
|
|
134
|
-
};
|
|
135
|
-
exports.describeStackEvents = describeStackEvents;
|
|
136
|
-
const describeStack = async ({ stackName }) => {
|
|
137
|
-
const stacks = await (0, exports.describeStacks)({ stackName });
|
|
138
|
-
if (!stacks) {
|
|
139
|
-
throw new Error(`Stack ${stackName} not found and cannot be described.`);
|
|
140
|
-
}
|
|
141
|
-
return stacks[0];
|
|
142
|
-
};
|
|
143
|
-
exports.describeStack = describeStack;
|
|
144
|
-
const getStackOutput = async ({ stackName, outputKey, }) => {
|
|
145
|
-
const { Outputs = [] } = await (0, exports.describeStack)({ stackName });
|
|
146
|
-
const output = Outputs?.find(({ OutputKey }) => {
|
|
147
|
-
return OutputKey === outputKey;
|
|
148
|
-
});
|
|
149
|
-
if (!output) {
|
|
150
|
-
throw new Error(`Output ${outputKey} doesn't exist on ${stackName} stack`);
|
|
151
|
-
}
|
|
152
|
-
return output;
|
|
153
|
-
};
|
|
154
|
-
exports.getStackOutput = getStackOutput;
|
|
155
|
-
const saveEnvironmentOutput = async ({ outputs, stackName, }) => {
|
|
156
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
157
|
-
const envFile = { stackName };
|
|
158
|
-
envFile.outputs = outputs.reduce((acc, output) => {
|
|
159
|
-
if (!output.OutputKey || !output) {
|
|
160
|
-
return acc;
|
|
161
|
-
}
|
|
162
|
-
return {
|
|
163
|
-
...acc,
|
|
164
|
-
[output.OutputKey]: output,
|
|
165
|
-
};
|
|
166
|
-
}, {});
|
|
167
|
-
const dotCarlinFolderPath = path.join(process.cwd(), '.carlin');
|
|
168
|
-
if (!fs.existsSync(dotCarlinFolderPath)) {
|
|
169
|
-
await fs.promises.mkdir(dotCarlinFolderPath);
|
|
170
|
-
}
|
|
171
|
-
const filePath = path.join(dotCarlinFolderPath, `${stackName}.json`);
|
|
172
|
-
await fs.promises.writeFile(filePath, JSON.stringify(envFile, null, 2));
|
|
173
|
-
};
|
|
174
|
-
const printStackOutputsAfterDeploy = async ({ stackName, }) => {
|
|
175
|
-
const { EnableTerminationProtection, StackName, Outputs = [], } = await (0, exports.describeStack)({ stackName });
|
|
176
|
-
await saveEnvironmentOutput({ stackName, outputs: Outputs });
|
|
177
|
-
npmlog_1.default.output('Describe Stack');
|
|
178
|
-
npmlog_1.default.output('StackName', StackName);
|
|
179
|
-
npmlog_1.default.output('EnableTerminationProtection', EnableTerminationProtection);
|
|
180
|
-
Outputs.forEach(({ OutputKey, OutputValue, Description, ExportName }) => {
|
|
181
|
-
npmlog_1.default.output(`${OutputKey}`, [
|
|
182
|
-
'',
|
|
183
|
-
`OutputKey: ${OutputKey}`,
|
|
184
|
-
`OutputValue: ${OutputValue}`,
|
|
185
|
-
`Description: ${Description}`,
|
|
186
|
-
`ExportName: ${ExportName}`,
|
|
187
|
-
'',
|
|
188
|
-
].join('\n'));
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
exports.printStackOutputsAfterDeploy = printStackOutputsAfterDeploy;
|
|
192
|
-
const deleteStack = async ({ stackName }) => {
|
|
193
|
-
npmlog_1.default.info(logPrefix, `Deleting stack ${stackName}...`);
|
|
194
|
-
await (0, exports.cloudformation)().send(new client_cloudformation_1.DeleteStackCommand({ StackName: stackName }));
|
|
195
|
-
try {
|
|
196
|
-
await (0, exports.cloudFormationV2)()
|
|
197
|
-
.waitFor('stackDeleteComplete', { StackName: stackName })
|
|
198
|
-
.promise();
|
|
199
|
-
}
|
|
200
|
-
catch (err) {
|
|
201
|
-
npmlog_1.default.error(logPrefix, `An error occurred when deleting stack ${stackName}.`);
|
|
202
|
-
await (0, exports.describeStackEvents)({ stackName });
|
|
203
|
-
throw err;
|
|
204
|
-
}
|
|
205
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} deleted.`);
|
|
206
|
-
};
|
|
207
|
-
exports.deleteStack = deleteStack;
|
|
208
|
-
const createStack = async ({ params, }) => {
|
|
209
|
-
const { StackName: stackName = '' } = params;
|
|
210
|
-
npmlog_1.default.info(logPrefix, `Creating stack ${stackName}...`);
|
|
211
|
-
await (0, exports.cloudformation)().send(new client_cloudformation_1.CreateStackCommand(params));
|
|
212
|
-
try {
|
|
213
|
-
await (0, exports.cloudFormationV2)()
|
|
214
|
-
.waitFor('stackCreateComplete', { StackName: stackName })
|
|
215
|
-
.promise();
|
|
216
|
-
}
|
|
217
|
-
catch (err) {
|
|
218
|
-
npmlog_1.default.error(logPrefix, `An error occurred when creating stack ${stackName}.`);
|
|
219
|
-
await (0, exports.describeStackEvents)({ stackName });
|
|
220
|
-
await (0, exports.deleteStack)({ stackName });
|
|
221
|
-
throw err;
|
|
222
|
-
}
|
|
223
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} was created.`);
|
|
224
|
-
};
|
|
225
|
-
exports.createStack = createStack;
|
|
226
|
-
const updateStack = async ({ params, }) => {
|
|
227
|
-
const { StackName: stackName = '' } = params;
|
|
228
|
-
npmlog_1.default.info(logPrefix, `Updating stack ${stackName}...`);
|
|
229
|
-
try {
|
|
230
|
-
await (0, exports.cloudformation)().send(new client_cloudformation_1.UpdateStackCommand(params));
|
|
231
|
-
await (0, exports.cloudFormationV2)()
|
|
232
|
-
.waitFor('stackUpdateComplete', { StackName: stackName })
|
|
233
|
-
.promise();
|
|
234
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
235
|
-
}
|
|
236
|
-
catch (error) {
|
|
237
|
-
if (error.message === 'No updates are to be performed.') {
|
|
238
|
-
npmlog_1.default.info(logPrefix, error.message);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
npmlog_1.default.error(logPrefix, 'An error occurred when updating stack.');
|
|
242
|
-
await (0, exports.describeStackEvents)({ stackName });
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} was updated.`);
|
|
246
|
-
};
|
|
247
|
-
exports.updateStack = updateStack;
|
|
248
|
-
const enableTerminationProtection = async ({ stackName, }) => {
|
|
249
|
-
npmlog_1.default.info(logPrefix, `Enabling termination protection...`);
|
|
250
|
-
try {
|
|
251
|
-
await (0, exports.cloudformation)().send(new client_cloudformation_1.UpdateTerminationProtectionCommand({
|
|
252
|
-
EnableTerminationProtection: true,
|
|
253
|
-
StackName: stackName,
|
|
254
|
-
}));
|
|
255
|
-
}
|
|
256
|
-
catch (err) {
|
|
257
|
-
npmlog_1.default.error(logPrefix, 'An error occurred when enabling termination protection');
|
|
258
|
-
throw err;
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
exports.enableTerminationProtection = enableTerminationProtection;
|
|
262
|
-
exports.defaultTemplatePaths = ['ts', 'js', 'yaml', 'yml', 'json'].map((extension) => {
|
|
263
|
-
return `src/cloudformation.${extension}`;
|
|
264
|
-
});
|
|
265
|
-
/**
|
|
266
|
-
* 1. Add defaults to CloudFormation template and parameters.
|
|
267
|
-
* 1. Check is CloudFormation template body is greater than max size limit.
|
|
268
|
-
* 1. If is greater, upload to S3 base stack.
|
|
269
|
-
* 1. If stack exists, update the stack, else create a new stack.
|
|
270
|
-
* 1. If `terminationProtection` option is true or `environment` is defined,
|
|
271
|
-
* then stack termination protection will be enabled.
|
|
272
|
-
*/
|
|
273
|
-
const deploy = async ({ terminationProtection = false, ...paramsAndTemplate }) => {
|
|
274
|
-
const { params, template } = await (0, addDefaults_cloudformation_1.addDefaults)(paramsAndTemplate);
|
|
275
|
-
const stackName = params.StackName;
|
|
276
|
-
if (!stackName) {
|
|
277
|
-
throw new Error('StackName is required');
|
|
278
|
-
}
|
|
279
|
-
delete params.TemplateBody;
|
|
280
|
-
delete params.TemplateURL;
|
|
281
|
-
if (isTemplateBodyGreaterThanMaxSize(template)) {
|
|
282
|
-
const { url } = await uploadTemplateToBaseStackBucket({
|
|
283
|
-
stackName,
|
|
284
|
-
template,
|
|
285
|
-
});
|
|
286
|
-
params.TemplateURL = url;
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
params.TemplateBody = JSON.stringify(template);
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* CAPABILITY_AUTO_EXPAND allows serverless transform.
|
|
293
|
-
*/
|
|
294
|
-
params.Capabilities = [
|
|
295
|
-
'CAPABILITY_AUTO_EXPAND',
|
|
296
|
-
'CAPABILITY_IAM',
|
|
297
|
-
'CAPABILITY_NAMED_IAM',
|
|
298
|
-
];
|
|
299
|
-
if (await (0, exports.doesStackExist)({ stackName })) {
|
|
300
|
-
await (0, exports.updateStack)({ params });
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
await (0, exports.createStack)({ params });
|
|
304
|
-
}
|
|
305
|
-
if (terminationProtection || !!(0, utils_1.getEnvironment)()) {
|
|
306
|
-
await (0, exports.enableTerminationProtection)({ stackName });
|
|
307
|
-
}
|
|
308
|
-
await (0, exports.printStackOutputsAfterDeploy)({ stackName });
|
|
309
|
-
return (0, exports.describeStack)({ stackName });
|
|
310
|
-
};
|
|
311
|
-
exports.deploy = deploy;
|
|
312
|
-
const canDestroyStack = async ({ stackName }) => {
|
|
313
|
-
const { EnableTerminationProtection } = await (0, exports.describeStack)({ stackName });
|
|
314
|
-
if (EnableTerminationProtection) {
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
return true;
|
|
318
|
-
};
|
|
319
|
-
exports.canDestroyStack = canDestroyStack;
|
|
320
|
-
const emptyStackBuckets = async ({ stackName }) => {
|
|
321
|
-
const buckets = [];
|
|
322
|
-
await (async ({ nextToken }) => {
|
|
323
|
-
const { NextToken, StackResourceSummaries } = await (0, exports.cloudformation)().send(new client_cloudformation_1.ListStackResourcesCommand({
|
|
324
|
-
StackName: stackName,
|
|
325
|
-
NextToken: nextToken,
|
|
326
|
-
}));
|
|
327
|
-
if (NextToken) {
|
|
328
|
-
// await getBuckets({ nextToken: NextToken });
|
|
329
|
-
}
|
|
330
|
-
(StackResourceSummaries || []).forEach(({ ResourceType, PhysicalResourceId }) => {
|
|
331
|
-
if (ResourceType === 'AWS::S3::Bucket' && PhysicalResourceId) {
|
|
332
|
-
buckets.push(PhysicalResourceId);
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
})({});
|
|
336
|
-
return Promise.all(buckets.map((bucket) => {
|
|
337
|
-
return (0, s3_1.emptyS3Directory)({ bucket });
|
|
338
|
-
}));
|
|
339
|
-
};
|
|
340
|
-
/**
|
|
341
|
-
* 1. Check if `environment` is defined. If defined, return. It doesn't destroy
|
|
342
|
-
* stacks with defined `environment`.
|
|
343
|
-
* 1. Check if termination protection is disabled.
|
|
344
|
-
* 1. If the stack deployed buckets, empty all buckets.
|
|
345
|
-
* 1. Delete the stack.
|
|
346
|
-
*/
|
|
347
|
-
const destroy = async ({ stackName }) => {
|
|
348
|
-
const environment = (0, utils_1.getEnvironment)();
|
|
349
|
-
if (environment) {
|
|
350
|
-
npmlog_1.default.info(logPrefix, `Cannot destroy stack when environment (${environment}) is defined.`);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
if (!(await (0, exports.doesStackExist)({ stackName }))) {
|
|
354
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} doesn't exist.`);
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
if (!(await (0, exports.canDestroyStack)({ stackName }))) {
|
|
358
|
-
const message = `Stack ${stackName} cannot be destroyed while TerminationProtection is enabled.`;
|
|
359
|
-
throw new Error(message);
|
|
360
|
-
}
|
|
361
|
-
await emptyStackBuckets({ stackName });
|
|
362
|
-
await (0, exports.deleteStack)({ stackName });
|
|
363
|
-
};
|
|
364
|
-
exports.destroy = destroy;
|
|
365
|
-
const validateTemplate = async ({ stackName, template, }) => {
|
|
366
|
-
const validateTemplateCommandInput = {};
|
|
367
|
-
if (isTemplateBodyGreaterThanMaxSize(template)) {
|
|
368
|
-
const { url } = await uploadTemplateToBaseStackBucket({
|
|
369
|
-
stackName,
|
|
370
|
-
template,
|
|
371
|
-
});
|
|
372
|
-
validateTemplateCommandInput.TemplateURL = url;
|
|
373
|
-
}
|
|
374
|
-
else {
|
|
375
|
-
validateTemplateCommandInput.TemplateBody = JSON.stringify(template);
|
|
376
|
-
}
|
|
377
|
-
await (0, exports.cloudformation)().send(new client_cloudformation_1.ValidateTemplateCommand(validateTemplateCommandInput));
|
|
378
|
-
};
|
|
379
|
-
exports.validateTemplate = validateTemplate;
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.destroyCloudFormation = exports.deployCloudFormation = exports.defaultTemplatePaths = void 0;
|
|
7
|
-
const utils_1 = require("../utils");
|
|
8
|
-
const cloudformation_core_1 = require("./cloudformation.core");
|
|
9
|
-
const deployLambdaCode_1 = require("./lambda/deployLambdaCode");
|
|
10
|
-
const s3_1 = require("./s3");
|
|
11
|
-
const cloudformation_1 = require("@ttoss/cloudformation");
|
|
12
|
-
const stackName_1 = require("./stackName");
|
|
13
|
-
const utils_2 = require("./utils");
|
|
14
|
-
const npmlog_1 = __importDefault(require("npmlog"));
|
|
15
|
-
const logPrefix = 'cloudformation';
|
|
16
|
-
npmlog_1.default.addLevel('event', 10000, { fg: 'yellow' });
|
|
17
|
-
npmlog_1.default.addLevel('output', 10000, { fg: 'blue' });
|
|
18
|
-
exports.defaultTemplatePaths = ['ts', 'js', 'yaml', 'yml', 'json'].map((extension) => {
|
|
19
|
-
return `./src/cloudformation.${extension}`;
|
|
20
|
-
});
|
|
21
|
-
const deployCloudFormation = async ({ lambdaDockerfile, lambdaInput, lambdaImage, lambdaExternals = [], parameters, template, templatePath, }) => {
|
|
22
|
-
try {
|
|
23
|
-
const { stackName } = await (0, utils_2.handleDeployInitialization)({ logPrefix });
|
|
24
|
-
const cloudFormationTemplate = (() => {
|
|
25
|
-
if (template) {
|
|
26
|
-
return { ...template };
|
|
27
|
-
}
|
|
28
|
-
return (0, cloudformation_1.findAndReadCloudFormationTemplate)({ templatePath });
|
|
29
|
-
})();
|
|
30
|
-
/**
|
|
31
|
-
* Add Parameters passed on CLI to CloudFormation template if they don't exist.
|
|
32
|
-
* Also, automatically add the Type of the parameter.
|
|
33
|
-
*/
|
|
34
|
-
parameters?.forEach((parameter) => {
|
|
35
|
-
if (cloudFormationTemplate.Parameters?.[parameter.key]) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (!cloudFormationTemplate.Parameters) {
|
|
39
|
-
cloudFormationTemplate.Parameters = {};
|
|
40
|
-
}
|
|
41
|
-
const type = (() => {
|
|
42
|
-
if (typeof parameter.value === 'string') {
|
|
43
|
-
return 'String';
|
|
44
|
-
}
|
|
45
|
-
if (typeof parameter.value === 'number') {
|
|
46
|
-
return 'Number';
|
|
47
|
-
}
|
|
48
|
-
throw new Error(`Parameter assertion failed. Parameter ${parameter.key} value ${parameter.value} is not mapped.`);
|
|
49
|
-
})();
|
|
50
|
-
cloudFormationTemplate.Parameters[parameter.key] = {
|
|
51
|
-
Type: type,
|
|
52
|
-
};
|
|
53
|
-
});
|
|
54
|
-
await (0, cloudformation_core_1.validateTemplate)({ stackName, template: cloudFormationTemplate });
|
|
55
|
-
const params = {
|
|
56
|
-
StackName: stackName,
|
|
57
|
-
Parameters: parameters?.map((parameter) => {
|
|
58
|
-
return {
|
|
59
|
-
ParameterKey: parameter.key,
|
|
60
|
-
ParameterValue: parameter.value,
|
|
61
|
-
UsePreviousValue: parameter.usePreviousValue,
|
|
62
|
-
ResolvedValue: parameter.resolvedValue,
|
|
63
|
-
};
|
|
64
|
-
}) || [],
|
|
65
|
-
};
|
|
66
|
-
const deployCloudFormationDeployLambdaCode = async () => {
|
|
67
|
-
const response = await (0, deployLambdaCode_1.deployLambdaCode)({
|
|
68
|
-
lambdaDockerfile,
|
|
69
|
-
lambdaExternals,
|
|
70
|
-
lambdaInput,
|
|
71
|
-
lambdaImage,
|
|
72
|
-
stackName,
|
|
73
|
-
});
|
|
74
|
-
if (response) {
|
|
75
|
-
const { bucket, key, versionId, imageUri } = response;
|
|
76
|
-
if (imageUri) {
|
|
77
|
-
cloudFormationTemplate.Parameters = {
|
|
78
|
-
LambdaImageUri: { Type: 'String' },
|
|
79
|
-
...cloudFormationTemplate.Parameters,
|
|
80
|
-
};
|
|
81
|
-
params.Parameters.push({
|
|
82
|
-
ParameterKey: 'LambdaImageUri',
|
|
83
|
-
ParameterValue: imageUri,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
else if (bucket && key && versionId) {
|
|
87
|
-
/**
|
|
88
|
-
* Add Parameters to CloudFormation template.
|
|
89
|
-
*/
|
|
90
|
-
cloudFormationTemplate.Parameters = {
|
|
91
|
-
LambdaS3Bucket: { Type: 'String' },
|
|
92
|
-
LambdaS3Key: { Type: 'String' },
|
|
93
|
-
LambdaS3ObjectVersion: { Type: 'String' },
|
|
94
|
-
...cloudFormationTemplate.Parameters,
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Add S3Bucket and S3Key to params.
|
|
98
|
-
*/
|
|
99
|
-
params.Parameters.push({
|
|
100
|
-
ParameterKey: 'LambdaS3Bucket',
|
|
101
|
-
ParameterValue: bucket,
|
|
102
|
-
}, {
|
|
103
|
-
ParameterKey: 'LambdaS3Key',
|
|
104
|
-
ParameterValue: key,
|
|
105
|
-
},
|
|
106
|
-
/**
|
|
107
|
-
* Used by CloudFormation AWS::Lambda::Function
|
|
108
|
-
* @see {@link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html}
|
|
109
|
-
* and by CloudFormation AWS::Serverless::Function
|
|
110
|
-
* @see {@link https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-functioncode.html}
|
|
111
|
-
*/
|
|
112
|
-
{
|
|
113
|
-
ParameterKey: 'LambdaS3ObjectVersion',
|
|
114
|
-
ParameterValue: versionId,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
await deployCloudFormationDeployLambdaCode();
|
|
120
|
-
const output = await (0, cloudformation_core_1.deploy)({
|
|
121
|
-
params,
|
|
122
|
-
template: cloudFormationTemplate,
|
|
123
|
-
});
|
|
124
|
-
return output;
|
|
125
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
-
}
|
|
127
|
-
catch (error) {
|
|
128
|
-
return (0, utils_2.handleDeployError)({ error, logPrefix });
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
exports.deployCloudFormation = deployCloudFormation;
|
|
132
|
-
const emptyStackBuckets = async ({ stackName }) => {
|
|
133
|
-
const buckets = [];
|
|
134
|
-
await (async ({ nextToken }) => {
|
|
135
|
-
const {
|
|
136
|
-
// NextToken,
|
|
137
|
-
StackResourceSummaries, } = await (0, cloudformation_core_1.cloudFormationV2)()
|
|
138
|
-
.listStackResources({ StackName: stackName, NextToken: nextToken })
|
|
139
|
-
.promise();
|
|
140
|
-
// if (NextToken) {
|
|
141
|
-
// await getBuckets({ nextToken: NextToken });
|
|
142
|
-
// }
|
|
143
|
-
(StackResourceSummaries || []).forEach(({ ResourceType, PhysicalResourceId }) => {
|
|
144
|
-
if (ResourceType === 'AWS::S3::Bucket' && PhysicalResourceId) {
|
|
145
|
-
buckets.push(PhysicalResourceId);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
})({});
|
|
149
|
-
return Promise.all(buckets.map((bucket) => {
|
|
150
|
-
return (0, s3_1.emptyS3Directory)({ bucket });
|
|
151
|
-
}));
|
|
152
|
-
};
|
|
153
|
-
/**
|
|
154
|
-
* 1. Check if `environment` is defined. If defined, return. It doesn't destroy
|
|
155
|
-
* stacks with defined `environment`.
|
|
156
|
-
* 1. Check if termination protection is disabled.
|
|
157
|
-
* 1. If the stack deployed buckets, empty all buckets.
|
|
158
|
-
* 1. Delete the stack.
|
|
159
|
-
*/
|
|
160
|
-
const destroy = async ({ stackName }) => {
|
|
161
|
-
const environment = (0, utils_1.getEnvironment)();
|
|
162
|
-
if (environment) {
|
|
163
|
-
npmlog_1.default.info(logPrefix, `Cannot destroy stack when environment (${environment}) is defined.`);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (!(await (0, cloudformation_core_1.doesStackExist)({ stackName }))) {
|
|
167
|
-
npmlog_1.default.info(logPrefix, `Stack ${stackName} doesn't exist.`);
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if (!(await (0, cloudformation_core_1.canDestroyStack)({ stackName }))) {
|
|
171
|
-
const message = `Stack ${stackName} cannot be destroyed while TerminationProtection is enabled.`;
|
|
172
|
-
throw new Error(message);
|
|
173
|
-
}
|
|
174
|
-
await emptyStackBuckets({ stackName });
|
|
175
|
-
await (0, cloudformation_core_1.deleteStack)({ stackName });
|
|
176
|
-
};
|
|
177
|
-
const destroyCloudFormation = async ({ stackName: defaultStackName, } = {}) => {
|
|
178
|
-
try {
|
|
179
|
-
npmlog_1.default.info(logPrefix, 'CAUTION! Starting CloudFormation destroy...');
|
|
180
|
-
const stackName = defaultStackName || (await (0, stackName_1.getStackName)());
|
|
181
|
-
npmlog_1.default.info(logPrefix, `stackName: ${stackName}`);
|
|
182
|
-
await destroy({ stackName });
|
|
183
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
(0, utils_2.handleDeployError)({ error, logPrefix });
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
exports.destroyCloudFormation = destroyCloudFormation;
|