@fishawack/lab-env 5.7.0-beta.2 → 5.7.0-beta.3
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/CHANGELOG.md +42 -0
- package/_Test/provision.js +1 -8
- package/_Test/prune.js +8 -5
- package/bitbucket-pipelines.yml +2 -2
- package/cli.js +1 -0
- package/commands/create/cmds/dekey.js +13 -9
- package/commands/create/cmds/deprovision.js +29 -0
- package/commands/create/cmds/key.js +60 -41
- package/commands/create/cmds/provision.js +425 -55
- package/commands/create/cmds/rekey.js +218 -0
- package/commands/create/libs/output-credentials.js +59 -0
- package/commands/create/libs/parallel-runner.js +204 -0
- package/commands/create/libs/resolve-operator.js +59 -0
- package/commands/create/libs/utilities.js +71 -8
- package/commands/create/libs/vars.js +70 -86
- package/commands/create/services/aws/acm.js +4 -2
- package/commands/create/services/aws/cloudfront.js +51 -45
- package/commands/create/services/aws/ec2.js +132 -53
- package/commands/create/services/aws/elasticache.js +159 -0
- package/commands/create/services/aws/elasticbeanstalk.js +141 -60
- package/commands/create/services/aws/iam.js +159 -93
- package/commands/create/services/aws/index.js +1209 -466
- package/commands/create/services/aws/opensearch.js +25 -17
- package/commands/create/services/aws/rds.js +22 -34
- package/commands/create/services/aws/s3.js +14 -27
- package/commands/create/services/aws/secretsmanager.js +8 -15
- package/commands/create/services/aws/ses.js +195 -0
- package/commands/create/templates/elasticbeanstalk/.ebextensions/laravel/cron.config +45 -0
- package/commands/create/templates/elasticbeanstalk/.ebextensions/laravel/queue-worker.config +29 -0
- package/commands/create/templates/elasticbeanstalk/.ebextensions/laravel/software.config +12 -0
- package/commands/create/templates/elasticbeanstalk/.ebextensions/misc/setvars.config +2 -16
- package/commands/create/templates/elasticbeanstalk/.platform/confighooks/postdeploy/rewrite-flush.sh +1 -1
- package/commands/create/templates/elasticbeanstalk/.platform/confighooks/postdeploy/setvars.sh +19 -0
- package/commands/create/templates/elasticbeanstalk/.platform/hooks/postdeploy/restart_queue.sh +4 -0
- package/commands/create/templates/elasticbeanstalk/.platform/hooks/prebuild/setvars.sh +19 -0
- package/package.json +5 -2
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const fs = require("fs-extra");
|
|
2
|
+
const crypto = require("crypto");
|
|
2
3
|
const glob = require("glob");
|
|
4
|
+
const inquirer = require("inquirer");
|
|
3
5
|
const {
|
|
4
6
|
ElasticBeanstalkClient,
|
|
5
7
|
CreateApplicationCommand,
|
|
@@ -14,19 +16,26 @@ const {
|
|
|
14
16
|
UpdateEnvironmentCommand,
|
|
15
17
|
CreateApplicationVersionCommand,
|
|
16
18
|
ListAvailableSolutionStacksCommand,
|
|
19
|
+
ListTagsForResourceCommand,
|
|
17
20
|
RestartAppServerCommand,
|
|
18
21
|
} = require("@aws-sdk/client-elastic-beanstalk");
|
|
19
22
|
const { Spinner, poll } = require("../../libs/utilities");
|
|
20
|
-
const { eb } = require("../../libs/vars");
|
|
23
|
+
const { eb, secretGroups, awsClientConfig } = require("../../libs/vars");
|
|
24
|
+
const { template } = require("lodash");
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
const client = new ElasticBeanstalkClient({});
|
|
26
|
+
const getClient = () => new ElasticBeanstalkClient(awsClientConfig);
|
|
24
27
|
|
|
28
|
+
module.exports.createElasticBeanstalkApplication = async (name, tags = []) => {
|
|
25
29
|
let res = await Spinner.prototype.simple(
|
|
26
30
|
`Creating elasticbeanstalk application ${name}`,
|
|
27
31
|
() => {
|
|
28
|
-
return
|
|
29
|
-
new CreateApplicationCommand({
|
|
32
|
+
return getClient().send(
|
|
33
|
+
new CreateApplicationCommand({
|
|
34
|
+
ApplicationName: name,
|
|
35
|
+
Tags: [
|
|
36
|
+
{ Key: "client", Value: process.env.AWS_PROFILE },
|
|
37
|
+
].concat(tags),
|
|
38
|
+
}),
|
|
30
39
|
);
|
|
31
40
|
},
|
|
32
41
|
);
|
|
@@ -35,15 +44,36 @@ module.exports.createElasticBeanstalkApplication = async (name) => {
|
|
|
35
44
|
};
|
|
36
45
|
|
|
37
46
|
module.exports.describeEnvironment = async (name) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return client.send(
|
|
47
|
+
return getClient().send(
|
|
41
48
|
new DescribeEnvironmentsCommand({
|
|
42
49
|
EnvironmentNames: [name],
|
|
43
50
|
}),
|
|
44
51
|
);
|
|
45
52
|
};
|
|
46
53
|
|
|
54
|
+
module.exports.listEnvironments = async (applicationName) => {
|
|
55
|
+
const res = await Spinner.prototype.simple(
|
|
56
|
+
`Retrieving environments for ${applicationName}`,
|
|
57
|
+
() => {
|
|
58
|
+
return getClient().send(
|
|
59
|
+
new DescribeEnvironmentsCommand({
|
|
60
|
+
ApplicationName: applicationName,
|
|
61
|
+
IncludeDeleted: false,
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return (res.Environments || []).filter((e) => e.Status !== "Terminated");
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
module.exports.getEnvironmentTags = async (environmentArn) => {
|
|
71
|
+
const res = await getClient().send(
|
|
72
|
+
new ListTagsForResourceCommand({ ResourceArn: environmentArn }),
|
|
73
|
+
);
|
|
74
|
+
return res.ResourceTags || [];
|
|
75
|
+
};
|
|
76
|
+
|
|
47
77
|
module.exports.createElasticBeanstalkEnvironment = async (
|
|
48
78
|
name,
|
|
49
79
|
{ language },
|
|
@@ -51,13 +81,12 @@ module.exports.createElasticBeanstalkEnvironment = async (
|
|
|
51
81
|
OptionSettings,
|
|
52
82
|
CNAMEPrefix,
|
|
53
83
|
tags = [],
|
|
84
|
+
versionLabel,
|
|
54
85
|
) => {
|
|
55
|
-
const client = new ElasticBeanstalkClient({});
|
|
56
|
-
|
|
57
86
|
const solutions = await Spinner.prototype.simple(
|
|
58
87
|
`Retrieving available solution stacks`,
|
|
59
88
|
() => {
|
|
60
|
-
return
|
|
89
|
+
return getClient().send(new ListAvailableSolutionStacksCommand());
|
|
61
90
|
},
|
|
62
91
|
);
|
|
63
92
|
|
|
@@ -75,21 +104,23 @@ module.exports.createElasticBeanstalkEnvironment = async (
|
|
|
75
104
|
d.includes(stackName),
|
|
76
105
|
)[0];
|
|
77
106
|
|
|
107
|
+
const createParams = {
|
|
108
|
+
ApplicationName,
|
|
109
|
+
EnvironmentName: name,
|
|
110
|
+
SolutionStackName,
|
|
111
|
+
OptionSettings,
|
|
112
|
+
CNAMEPrefix,
|
|
113
|
+
Tags: [{ Key: "client", Value: process.env.AWS_PROFILE }].concat(tags),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (versionLabel) {
|
|
117
|
+
createParams.VersionLabel = versionLabel;
|
|
118
|
+
}
|
|
119
|
+
|
|
78
120
|
await Spinner.prototype.simple(
|
|
79
121
|
`Creating elasticbeanstalk environment ${name}`,
|
|
80
122
|
() => {
|
|
81
|
-
return
|
|
82
|
-
new CreateEnvironmentCommand({
|
|
83
|
-
ApplicationName,
|
|
84
|
-
EnvironmentName: name,
|
|
85
|
-
SolutionStackName,
|
|
86
|
-
OptionSettings,
|
|
87
|
-
CNAMEPrefix,
|
|
88
|
-
Tags: [
|
|
89
|
-
{ Key: "client", Value: process.env.AWS_PROFILE },
|
|
90
|
-
].concat(tags),
|
|
91
|
-
}),
|
|
92
|
-
);
|
|
123
|
+
return getClient().send(new CreateEnvironmentCommand(createParams));
|
|
93
124
|
},
|
|
94
125
|
);
|
|
95
126
|
|
|
@@ -112,12 +143,10 @@ module.exports.waitForElasticBeanstalkEnvironment = async (
|
|
|
112
143
|
waitFor = "Ready",
|
|
113
144
|
failIf,
|
|
114
145
|
) => {
|
|
115
|
-
const client = new ElasticBeanstalkClient({});
|
|
116
|
-
|
|
117
146
|
const res = await poll(
|
|
118
147
|
async () =>
|
|
119
148
|
(
|
|
120
|
-
await
|
|
149
|
+
await getClient().send(
|
|
121
150
|
new DescribeEnvironmentsCommand({
|
|
122
151
|
EnvironmentNames: [name],
|
|
123
152
|
}),
|
|
@@ -131,12 +160,10 @@ module.exports.waitForElasticBeanstalkEnvironment = async (
|
|
|
131
160
|
};
|
|
132
161
|
|
|
133
162
|
module.exports.removeElasticBeanstalkApplication = async (name) => {
|
|
134
|
-
const client = new ElasticBeanstalkClient({});
|
|
135
|
-
|
|
136
163
|
await Spinner.prototype.simple(
|
|
137
164
|
`Removing elasticbeanstalk application ${name}`,
|
|
138
165
|
() => {
|
|
139
|
-
return
|
|
166
|
+
return getClient().send(
|
|
140
167
|
new DeleteApplicationCommand({ ApplicationName: name }),
|
|
141
168
|
);
|
|
142
169
|
},
|
|
@@ -144,12 +171,10 @@ module.exports.removeElasticBeanstalkApplication = async (name) => {
|
|
|
144
171
|
};
|
|
145
172
|
|
|
146
173
|
module.exports.removeElasticBeanstalkEnvironment = async (name) => {
|
|
147
|
-
const client = new ElasticBeanstalkClient({});
|
|
148
|
-
|
|
149
174
|
await Spinner.prototype.simple(
|
|
150
175
|
`Removing elasticbeanstalk environment ${name}`,
|
|
151
176
|
() => {
|
|
152
|
-
return
|
|
177
|
+
return getClient().send(
|
|
153
178
|
new TerminateEnvironmentCommand({ EnvironmentName: name }),
|
|
154
179
|
);
|
|
155
180
|
},
|
|
@@ -166,25 +191,93 @@ module.exports.removeElasticBeanstalkEnvironment = async (name) => {
|
|
|
166
191
|
);
|
|
167
192
|
};
|
|
168
193
|
|
|
169
|
-
module.exports.copyElasticBeanstalkConfigs = async (configurations) => {
|
|
194
|
+
module.exports.copyElasticBeanstalkConfigs = async (configurations, branch) => {
|
|
170
195
|
const templates = `${__dirname}/../../templates/elasticbeanstalk`;
|
|
196
|
+
const templateData = {
|
|
197
|
+
...process.env,
|
|
198
|
+
SECRET_GROUPS: secretGroups.join(" "),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const checksumPath = `_IaC/${branch}/.lab-env-checksums.json`;
|
|
202
|
+
const checksums = fs.existsSync(checksumPath)
|
|
203
|
+
? JSON.parse(fs.readFileSync(checksumPath, "utf8"))
|
|
204
|
+
: {};
|
|
205
|
+
|
|
206
|
+
for (const globbed of configurations) {
|
|
207
|
+
const files = glob.sync(globbed, { cwd: `${templates}` });
|
|
208
|
+
|
|
209
|
+
for (const config of files) {
|
|
210
|
+
const content = fs.readFileSync(`${templates}/${config}`, "utf8");
|
|
211
|
+
const output = content.includes("<%=")
|
|
212
|
+
? template(content, { interpolate: /<%=([\s\S]+?)%>/g })(
|
|
213
|
+
templateData,
|
|
214
|
+
)
|
|
215
|
+
: content;
|
|
216
|
+
|
|
217
|
+
const dest = `_IaC/${branch}/${config}`;
|
|
218
|
+
const newHash = crypto
|
|
219
|
+
.createHash("md5")
|
|
220
|
+
.update(output)
|
|
221
|
+
.digest("hex");
|
|
222
|
+
|
|
223
|
+
if (fs.existsSync(dest)) {
|
|
224
|
+
const existing = fs.readFileSync(dest, "utf8");
|
|
225
|
+
|
|
226
|
+
if (existing === output) {
|
|
227
|
+
checksums[config] = newHash;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const existingHash = crypto
|
|
232
|
+
.createHash("md5")
|
|
233
|
+
.update(existing)
|
|
234
|
+
.digest("hex");
|
|
235
|
+
|
|
236
|
+
let shouldOverwrite;
|
|
237
|
+
|
|
238
|
+
if (checksums[config] && existingHash === checksums[config]) {
|
|
239
|
+
const { overwrite } = await inquirer.prompt([
|
|
240
|
+
{
|
|
241
|
+
type: "confirm",
|
|
242
|
+
name: "overwrite",
|
|
243
|
+
message: `${dest} has an updated template, overwrite?`,
|
|
244
|
+
default: true,
|
|
245
|
+
},
|
|
246
|
+
]);
|
|
247
|
+
shouldOverwrite = overwrite;
|
|
248
|
+
} else {
|
|
249
|
+
const { overwrite } = await inquirer.prompt([
|
|
250
|
+
{
|
|
251
|
+
type: "confirm",
|
|
252
|
+
name: "overwrite",
|
|
253
|
+
message: `${dest} has been modified, overwrite?`,
|
|
254
|
+
default: false,
|
|
255
|
+
},
|
|
256
|
+
]);
|
|
257
|
+
shouldOverwrite = overwrite;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (!shouldOverwrite) continue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
fs.outputFileSync(dest, output);
|
|
264
|
+
checksums[config] = newHash;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
171
267
|
|
|
172
|
-
|
|
173
|
-
glob.sync(globbed, { cwd: `${templates}` }).forEach((config) =>
|
|
174
|
-
fs.copySync(`${templates}/${config}`, config),
|
|
175
|
-
);
|
|
176
|
-
});
|
|
268
|
+
fs.outputFileSync(checksumPath, JSON.stringify(checksums, null, 2));
|
|
177
269
|
|
|
178
|
-
fs.outputFileSync(
|
|
270
|
+
fs.outputFileSync(
|
|
271
|
+
`_IaC/${branch}/.elasticbeanstalk/config.yml`,
|
|
272
|
+
eb.config(),
|
|
273
|
+
);
|
|
179
274
|
};
|
|
180
275
|
|
|
181
276
|
module.exports.listApplications = async () => {
|
|
182
|
-
const client = new ElasticBeanstalkClient({});
|
|
183
|
-
|
|
184
277
|
const res = await Spinner.prototype.simple(
|
|
185
278
|
`Retrieving elasticbeanstalk applications`,
|
|
186
279
|
() => {
|
|
187
|
-
return
|
|
280
|
+
return getClient().send(new DescribeApplicationsCommand({}));
|
|
188
281
|
},
|
|
189
282
|
);
|
|
190
283
|
|
|
@@ -192,13 +285,11 @@ module.exports.listApplications = async () => {
|
|
|
192
285
|
};
|
|
193
286
|
|
|
194
287
|
module.exports.listApplicationVersions = async (applicationName) => {
|
|
195
|
-
const client = new ElasticBeanstalkClient({});
|
|
196
|
-
|
|
197
288
|
let versions = [];
|
|
198
289
|
let nextToken;
|
|
199
290
|
|
|
200
291
|
do {
|
|
201
|
-
const res = await
|
|
292
|
+
const res = await getClient().send(
|
|
202
293
|
new DescribeApplicationVersionsCommand({
|
|
203
294
|
ApplicationName: applicationName,
|
|
204
295
|
...(nextToken ? { NextToken: nextToken } : {}),
|
|
@@ -216,9 +307,7 @@ module.exports.createApplicationVersion = async (
|
|
|
216
307
|
applicationName,
|
|
217
308
|
versionLabel,
|
|
218
309
|
) => {
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
const res = await client.send(
|
|
310
|
+
const res = await getClient().send(
|
|
222
311
|
new CreateApplicationVersionCommand({
|
|
223
312
|
ApplicationName: applicationName,
|
|
224
313
|
VersionLabel: versionLabel,
|
|
@@ -233,9 +322,7 @@ module.exports.deleteApplicationVersion = async (
|
|
|
233
322
|
applicationName,
|
|
234
323
|
versionLabel,
|
|
235
324
|
) => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
await client.send(
|
|
325
|
+
await getClient().send(
|
|
239
326
|
new DeleteApplicationVersionCommand({
|
|
240
327
|
ApplicationName: applicationName,
|
|
241
328
|
VersionLabel: versionLabel,
|
|
@@ -248,12 +335,10 @@ module.exports.describeConfigurationSettings = async (
|
|
|
248
335
|
applicationName,
|
|
249
336
|
environmentName,
|
|
250
337
|
) => {
|
|
251
|
-
const client = new ElasticBeanstalkClient({});
|
|
252
|
-
|
|
253
338
|
const res = await Spinner.prototype.simple(
|
|
254
339
|
`Retrieving configuration for ${environmentName}`,
|
|
255
340
|
() => {
|
|
256
|
-
return
|
|
341
|
+
return getClient().send(
|
|
257
342
|
new DescribeConfigurationSettingsCommand({
|
|
258
343
|
ApplicationName: applicationName,
|
|
259
344
|
EnvironmentName: environmentName,
|
|
@@ -270,12 +355,10 @@ module.exports.updateEnvironmentSettings = async (
|
|
|
270
355
|
optionSettings = [],
|
|
271
356
|
optionsToRemove = [],
|
|
272
357
|
) => {
|
|
273
|
-
const client = new ElasticBeanstalkClient({});
|
|
274
|
-
|
|
275
358
|
await Spinner.prototype.simple(
|
|
276
359
|
`Updating environment ${environmentName}`,
|
|
277
360
|
() => {
|
|
278
|
-
return
|
|
361
|
+
return getClient().send(
|
|
279
362
|
new UpdateEnvironmentCommand({
|
|
280
363
|
EnvironmentName: environmentName,
|
|
281
364
|
OptionSettings: optionSettings,
|
|
@@ -287,12 +370,10 @@ module.exports.updateEnvironmentSettings = async (
|
|
|
287
370
|
};
|
|
288
371
|
|
|
289
372
|
module.exports.restartAppServer = async (environmentName) => {
|
|
290
|
-
const client = new ElasticBeanstalkClient({});
|
|
291
|
-
|
|
292
373
|
await Spinner.prototype.simple(
|
|
293
374
|
`Restarting app server for ${environmentName}`,
|
|
294
375
|
() => {
|
|
295
|
-
return
|
|
376
|
+
return getClient().send(
|
|
296
377
|
new RestartAppServerCommand({
|
|
297
378
|
EnvironmentName: environmentName,
|
|
298
379
|
}),
|