@fishawack/lab-env 5.7.0-beta.2 → 5.7.0-beta.4
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 +51 -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 +178 -98
- package/commands/create/services/aws/index.js +1202 -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/commands/scan.js +1 -1
- package/package.json +5 -2
|
@@ -18,6 +18,11 @@ module.exports = [
|
|
|
18
18
|
describe: "Branch to configure",
|
|
19
19
|
type: "string",
|
|
20
20
|
});
|
|
21
|
+
yargs.option("green-blue", {
|
|
22
|
+
alias: "g",
|
|
23
|
+
describe: "Clone an existing environment (pass source branch name)",
|
|
24
|
+
type: "string",
|
|
25
|
+
});
|
|
21
26
|
},
|
|
22
27
|
async (argv) => {
|
|
23
28
|
let branch = argv.branch || _.branch;
|
|
@@ -38,6 +43,190 @@ module.exports = [
|
|
|
38
43
|
process.exit(1);
|
|
39
44
|
}
|
|
40
45
|
|
|
46
|
+
// Green/Blue clone flow — entirely separate path
|
|
47
|
+
if (argv.greenBlue) {
|
|
48
|
+
let gbAnswers = await inquirer.prompt([client, region]);
|
|
49
|
+
|
|
50
|
+
setAWSClientDefaults(gbAnswers.client, gbAnswers.region);
|
|
51
|
+
|
|
52
|
+
// List existing EB applications
|
|
53
|
+
const applications = await aws.elasticbeanstalk.listApplications();
|
|
54
|
+
|
|
55
|
+
if (!applications.length) {
|
|
56
|
+
console.log(
|
|
57
|
+
utilities.colorize(
|
|
58
|
+
"\n ✗ No EB applications found in this account/region\n",
|
|
59
|
+
"error",
|
|
60
|
+
),
|
|
61
|
+
);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// List all environments across applications
|
|
66
|
+
let allEnvironments = [];
|
|
67
|
+
for (const app of applications) {
|
|
68
|
+
const envs = await aws.elasticbeanstalk.listEnvironments(
|
|
69
|
+
app.ApplicationName,
|
|
70
|
+
);
|
|
71
|
+
allEnvironments = allEnvironments.concat(
|
|
72
|
+
envs.map((e) => ({
|
|
73
|
+
...e,
|
|
74
|
+
ApplicationName: app.ApplicationName,
|
|
75
|
+
})),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!allEnvironments.length) {
|
|
80
|
+
console.log(
|
|
81
|
+
utilities.colorize(
|
|
82
|
+
"\n ✗ No active EB environments found\n",
|
|
83
|
+
"error",
|
|
84
|
+
),
|
|
85
|
+
);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const { sourceEnv } = await inquirer.prompt([
|
|
90
|
+
{
|
|
91
|
+
type: "list",
|
|
92
|
+
name: "sourceEnv",
|
|
93
|
+
message: "Which environment should be cloned?",
|
|
94
|
+
choices: allEnvironments.map((e) => ({
|
|
95
|
+
name: `${e.EnvironmentName} (${e.Status})`,
|
|
96
|
+
value: e,
|
|
97
|
+
})),
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
// Validate branch doesn't conflict with source
|
|
102
|
+
const sourceSlug = sourceEnv.EnvironmentName;
|
|
103
|
+
const newSlug = aws.slug(
|
|
104
|
+
_.repoSafe,
|
|
105
|
+
gbAnswers.client,
|
|
106
|
+
branch,
|
|
107
|
+
"eb",
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (newSlug === sourceSlug) {
|
|
111
|
+
const { newBranch } = await inquirer.prompt([
|
|
112
|
+
{
|
|
113
|
+
type: "input",
|
|
114
|
+
name: "newBranch",
|
|
115
|
+
message:
|
|
116
|
+
"Branch conflicts with source. Enter a different branch name:",
|
|
117
|
+
default: `${branch}-green`,
|
|
118
|
+
validate: (input) => {
|
|
119
|
+
const slug = aws.slug(
|
|
120
|
+
_.repoSafe,
|
|
121
|
+
gbAnswers.client,
|
|
122
|
+
input,
|
|
123
|
+
"eb",
|
|
124
|
+
);
|
|
125
|
+
if (slug === sourceSlug) {
|
|
126
|
+
return "Branch still conflicts with source environment";
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
]);
|
|
132
|
+
branch = newBranch;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const slug = aws.slug(_.repoSafe, gbAnswers.client, branch, "eb");
|
|
136
|
+
|
|
137
|
+
// Check the clone doesn't already exist
|
|
138
|
+
const { Environments } =
|
|
139
|
+
await aws.elasticbeanstalk.describeEnvironment(slug);
|
|
140
|
+
const active = (Environments || []).filter(
|
|
141
|
+
(e) => e.Status !== "Terminated",
|
|
142
|
+
);
|
|
143
|
+
if (active.length) {
|
|
144
|
+
console.log(
|
|
145
|
+
utilities.colorize(
|
|
146
|
+
`\n ✗ Environment "${slug}" already exists (${active[0].Status})\n`,
|
|
147
|
+
"error",
|
|
148
|
+
),
|
|
149
|
+
);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const environmentChoices = ["production", "staging", "test"];
|
|
154
|
+
const defaultEnvironment =
|
|
155
|
+
environmentChoices.find((e) =>
|
|
156
|
+
branch.toLowerCase().includes(e),
|
|
157
|
+
) || "test";
|
|
158
|
+
|
|
159
|
+
// Get environment tag from source
|
|
160
|
+
const sourceTags = await aws.elasticbeanstalk.getEnvironmentTags(
|
|
161
|
+
sourceEnv.EnvironmentArn,
|
|
162
|
+
);
|
|
163
|
+
const sourceEnvTag = sourceTags.find(
|
|
164
|
+
(t) => t.Key === "environment",
|
|
165
|
+
);
|
|
166
|
+
const envTagValue = sourceEnvTag
|
|
167
|
+
? sourceEnvTag.Value
|
|
168
|
+
: defaultEnvironment;
|
|
169
|
+
|
|
170
|
+
const tags = [
|
|
171
|
+
{ Key: "repository", Value: _.repo },
|
|
172
|
+
{ Key: "environment", Value: envTagValue },
|
|
173
|
+
{ Key: "branch", Value: branch },
|
|
174
|
+
{ Key: "automated", Value: "true" },
|
|
175
|
+
{ Key: "cloned-from", Value: sourceEnv.EnvironmentName },
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
const infastructure = await aws.fullstackClone(
|
|
180
|
+
slug,
|
|
181
|
+
tags,
|
|
182
|
+
_.repoSafe,
|
|
183
|
+
branch,
|
|
184
|
+
sourceEnv.ApplicationName,
|
|
185
|
+
sourceEnv.EnvironmentName,
|
|
186
|
+
sourceEnv.VersionLabel,
|
|
187
|
+
argv.greenBlue,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const config = {};
|
|
191
|
+
config[branch] = {
|
|
192
|
+
deploy: {
|
|
193
|
+
url: infastructure.url,
|
|
194
|
+
location: "/var/www/html",
|
|
195
|
+
"aws-eb": infastructure.environment,
|
|
196
|
+
environment: envTagValue,
|
|
197
|
+
paths: infastructure.paths,
|
|
198
|
+
"cloned-from": sourceEnv.EnvironmentName,
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
if (infastructure.copy) {
|
|
203
|
+
config[branch].copy = infastructure.copy;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let stringify = JSON.stringify(config, null, 4);
|
|
207
|
+
let output = stringify
|
|
208
|
+
.substring(1, stringify.length - 1)
|
|
209
|
+
.trim();
|
|
210
|
+
utilities.copyToClipboard(output);
|
|
211
|
+
console.log(
|
|
212
|
+
utilities.colorize(
|
|
213
|
+
`\n${output}\n\n(copied to clipboard)`,
|
|
214
|
+
"title",
|
|
215
|
+
),
|
|
216
|
+
);
|
|
217
|
+
} catch (e) {
|
|
218
|
+
console.log(e.message);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const environmentChoices = ["production", "staging", "test"];
|
|
226
|
+
const defaultEnvironment =
|
|
227
|
+
environmentChoices.find((e) => branch.toLowerCase().includes(e)) ||
|
|
228
|
+
"test";
|
|
229
|
+
|
|
41
230
|
let answers = await inquirer.prompt([stack]);
|
|
42
231
|
|
|
43
232
|
// Prompt for redirects if static stack and no existing redirects
|
|
@@ -207,12 +396,6 @@ module.exports = [
|
|
|
207
396
|
value: "default",
|
|
208
397
|
}),
|
|
209
398
|
},
|
|
210
|
-
{
|
|
211
|
-
type: "list",
|
|
212
|
-
name: "availability",
|
|
213
|
-
message: "What availability is required?",
|
|
214
|
-
choices: ["low", "high"],
|
|
215
|
-
},
|
|
216
399
|
region,
|
|
217
400
|
{
|
|
218
401
|
type: "confirm",
|
|
@@ -239,6 +422,18 @@ module.exports = [
|
|
|
239
422
|
message: "Does this site need OpenSearch?",
|
|
240
423
|
default: false,
|
|
241
424
|
},
|
|
425
|
+
{
|
|
426
|
+
type: "confirm",
|
|
427
|
+
name: "cache",
|
|
428
|
+
message: "Does this site need cache (Valkey)?",
|
|
429
|
+
default: false,
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
type: "confirm",
|
|
433
|
+
name: "mail",
|
|
434
|
+
message: "Does this site need email (SES)?",
|
|
435
|
+
default: false,
|
|
436
|
+
},
|
|
242
437
|
])),
|
|
243
438
|
};
|
|
244
439
|
}
|
|
@@ -246,15 +441,19 @@ module.exports = [
|
|
|
246
441
|
|
|
247
442
|
answers = {
|
|
248
443
|
...answers,
|
|
249
|
-
...(await inquirer.prompt(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
444
|
+
...(await inquirer.prompt(
|
|
445
|
+
answers.stack === "static"
|
|
446
|
+
? [
|
|
447
|
+
client,
|
|
448
|
+
{
|
|
449
|
+
type: "confirm",
|
|
450
|
+
name: "protected",
|
|
451
|
+
message: "Should the site be password protected?",
|
|
452
|
+
default: true,
|
|
453
|
+
},
|
|
454
|
+
]
|
|
455
|
+
: [client],
|
|
456
|
+
)),
|
|
258
457
|
};
|
|
259
458
|
|
|
260
459
|
let credentials = [];
|
|
@@ -316,12 +515,15 @@ module.exports = [
|
|
|
316
515
|
storage: null,
|
|
317
516
|
database: null,
|
|
318
517
|
opensearch: null,
|
|
518
|
+
cache: null,
|
|
519
|
+
mail: null,
|
|
319
520
|
};
|
|
320
521
|
let existingEnvironment = false;
|
|
321
522
|
let existingResources = {
|
|
322
523
|
storage: false,
|
|
323
524
|
database: false,
|
|
324
525
|
opensearch: false,
|
|
526
|
+
cache: false,
|
|
325
527
|
};
|
|
326
528
|
let snapshot = null;
|
|
327
529
|
|
|
@@ -334,6 +536,7 @@ module.exports = [
|
|
|
334
536
|
storage: answers.storage,
|
|
335
537
|
database: answers.database,
|
|
336
538
|
opensearch: answers.opensearch,
|
|
539
|
+
cache: answers.cache,
|
|
337
540
|
},
|
|
338
541
|
);
|
|
339
542
|
|
|
@@ -382,6 +585,14 @@ module.exports = [
|
|
|
382
585
|
existingResources.opensearch = true;
|
|
383
586
|
}
|
|
384
587
|
|
|
588
|
+
if (existing.cache) {
|
|
589
|
+
new utilities.Spinner(
|
|
590
|
+
"ElastiCache cluster already exists, skipping creation",
|
|
591
|
+
true,
|
|
592
|
+
).ora.info();
|
|
593
|
+
existingResources.cache = true;
|
|
594
|
+
}
|
|
595
|
+
|
|
385
596
|
// Snapshot restore prompt — only if database is needed and doesn't already exist
|
|
386
597
|
if (answers.database && !existing.database) {
|
|
387
598
|
const { restore } = await inquirer.prompt([
|
|
@@ -449,8 +660,144 @@ module.exports = [
|
|
|
449
660
|
).ora.info();
|
|
450
661
|
}
|
|
451
662
|
|
|
663
|
+
if (existingSecrets.cache) {
|
|
664
|
+
new utilities.Spinner(
|
|
665
|
+
"Cache secret already exists, reusing existing values",
|
|
666
|
+
true,
|
|
667
|
+
).ora.info();
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (existingSecrets.mail) {
|
|
671
|
+
new utilities.Spinner(
|
|
672
|
+
"Mail secret already exists, reusing existing values",
|
|
673
|
+
true,
|
|
674
|
+
).ora.info();
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// SES detail prompts — only if mail requested and not already configured
|
|
678
|
+
if (answers.mail && !existingSecrets.mail) {
|
|
679
|
+
const identities = await aws.ses.listVerifiedIdentities();
|
|
680
|
+
|
|
681
|
+
if (!identities.length) {
|
|
682
|
+
new utilities.Spinner(
|
|
683
|
+
"No verified SES identities found, skipping email setup",
|
|
684
|
+
true,
|
|
685
|
+
).ora.warn();
|
|
686
|
+
answers.mail = false;
|
|
687
|
+
} else {
|
|
688
|
+
const defaultIdentity = answers.appDomain
|
|
689
|
+
? identities.find(
|
|
690
|
+
(id) =>
|
|
691
|
+
answers.appDomain.endsWith(id) ||
|
|
692
|
+
id === answers.appDomain,
|
|
693
|
+
) || identities[0]
|
|
694
|
+
: identities[0];
|
|
695
|
+
|
|
696
|
+
const { sesIdentity } = await inquirer.prompt([
|
|
697
|
+
{
|
|
698
|
+
type: "list",
|
|
699
|
+
name: "sesIdentity",
|
|
700
|
+
message:
|
|
701
|
+
"Which verified SES domain should be used?",
|
|
702
|
+
choices: identities,
|
|
703
|
+
default: defaultIdentity,
|
|
704
|
+
},
|
|
705
|
+
]);
|
|
706
|
+
|
|
707
|
+
const { mailFromAddress } = await inquirer.prompt([
|
|
708
|
+
{
|
|
709
|
+
type: "input",
|
|
710
|
+
name: "mailFromAddress",
|
|
711
|
+
message: "Mail from address:",
|
|
712
|
+
default: `noreply@${sesIdentity}`,
|
|
713
|
+
validate: (input) => {
|
|
714
|
+
if (!input.includes("@")) {
|
|
715
|
+
return "Must be a valid email address";
|
|
716
|
+
}
|
|
717
|
+
const domain = input.split("@")[1];
|
|
718
|
+
if (
|
|
719
|
+
domain === sesIdentity ||
|
|
720
|
+
domain.endsWith(`.${sesIdentity}`)
|
|
721
|
+
) {
|
|
722
|
+
return true;
|
|
723
|
+
}
|
|
724
|
+
return `Address must be under the verified identity ${sesIdentity}`;
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
]);
|
|
728
|
+
|
|
729
|
+
const { mailFromName } = await inquirer.prompt([
|
|
730
|
+
{
|
|
731
|
+
type: "input",
|
|
732
|
+
name: "mailFromName",
|
|
733
|
+
message: "Mail from name:",
|
|
734
|
+
default:
|
|
735
|
+
answers.appName ||
|
|
736
|
+
_.repoSafe
|
|
737
|
+
.replace(/-/g, " ")
|
|
738
|
+
.replace(/^./, (c) => c.toUpperCase()),
|
|
739
|
+
validate: (input) =>
|
|
740
|
+
!!input.length || "From name is required",
|
|
741
|
+
},
|
|
742
|
+
]);
|
|
743
|
+
|
|
744
|
+
answers.mailData = {
|
|
745
|
+
fromAddress: mailFromAddress,
|
|
746
|
+
fromName: mailFromName,
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Resolve environment tag
|
|
752
|
+
if (existingEnvironment) {
|
|
753
|
+
const envTags = await aws.elasticbeanstalk.getEnvironmentTags(
|
|
754
|
+
existingEnvironment.EnvironmentArn,
|
|
755
|
+
);
|
|
756
|
+
const envTag = envTags.find((t) => t.Key === "environment");
|
|
757
|
+
answers.environment = envTag
|
|
758
|
+
? envTag.Value
|
|
759
|
+
: defaultEnvironment;
|
|
760
|
+
new utilities.Spinner(
|
|
761
|
+
`Using existing environment tag: ${answers.environment}`,
|
|
762
|
+
true,
|
|
763
|
+
).ora.info();
|
|
764
|
+
} else {
|
|
765
|
+
answers = {
|
|
766
|
+
...answers,
|
|
767
|
+
...(await inquirer.prompt([
|
|
768
|
+
{
|
|
769
|
+
type: "list",
|
|
770
|
+
name: "environment",
|
|
771
|
+
message: "What environment is this?",
|
|
772
|
+
choices: environmentChoices,
|
|
773
|
+
default: defaultEnvironment,
|
|
774
|
+
},
|
|
775
|
+
])),
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
452
779
|
// EB-specific prompts — only for new environments
|
|
453
|
-
if (!existingEnvironment
|
|
780
|
+
if (!existingEnvironment) {
|
|
781
|
+
answers = {
|
|
782
|
+
...answers,
|
|
783
|
+
...(await inquirer.prompt([
|
|
784
|
+
{
|
|
785
|
+
type: "list",
|
|
786
|
+
name: "instanceType",
|
|
787
|
+
message: "What instance size is required?",
|
|
788
|
+
choices: [
|
|
789
|
+
{ name: "Small", value: "t3.small" },
|
|
790
|
+
{ name: "Medium", value: "t3.medium" },
|
|
791
|
+
{ name: "Large", value: "t3.large" },
|
|
792
|
+
{ name: "XLarge", value: "t3.xlarge" },
|
|
793
|
+
],
|
|
794
|
+
default: "t3.small",
|
|
795
|
+
},
|
|
796
|
+
])),
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (!existingEnvironment) {
|
|
454
801
|
answers = {
|
|
455
802
|
...answers,
|
|
456
803
|
...(await inquirer.prompt([
|
|
@@ -473,7 +820,9 @@ module.exports = [
|
|
|
473
820
|
type: "input",
|
|
474
821
|
name: "appName",
|
|
475
822
|
message: "What is the app name?",
|
|
476
|
-
default: _.repoSafe
|
|
823
|
+
default: _.repoSafe
|
|
824
|
+
.replace(/-/g, " ")
|
|
825
|
+
.replace(/^./, (c) => c.toUpperCase()),
|
|
477
826
|
validate: (v) =>
|
|
478
827
|
/^[a-zA-Z0-9 ]+$/.test(v) ||
|
|
479
828
|
"Alphanumeric characters and spaces only",
|
|
@@ -493,50 +842,62 @@ module.exports = [
|
|
|
493
842
|
])),
|
|
494
843
|
};
|
|
495
844
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
`No ACM certificates match ${answers.appDomain}, HTTPS listener must be configured manually`,
|
|
525
|
-
true,
|
|
526
|
-
).ora.info();
|
|
527
|
-
}
|
|
845
|
+
const matchingCerts = await aws.acm.findCertificatesForDomain(
|
|
846
|
+
answers.appDomain,
|
|
847
|
+
);
|
|
848
|
+
|
|
849
|
+
if (matchingCerts.length) {
|
|
850
|
+
answers = {
|
|
851
|
+
...answers,
|
|
852
|
+
...(await inquirer.prompt([
|
|
853
|
+
{
|
|
854
|
+
type: "list",
|
|
855
|
+
name: "certArn",
|
|
856
|
+
message:
|
|
857
|
+
"Which ACM certificate should be used for HTTPS?",
|
|
858
|
+
choices: [
|
|
859
|
+
...matchingCerts.map((c) => ({
|
|
860
|
+
name: c.DomainName,
|
|
861
|
+
value: c.CertificateArn,
|
|
862
|
+
})),
|
|
863
|
+
{ name: "None", value: null },
|
|
864
|
+
],
|
|
865
|
+
},
|
|
866
|
+
])),
|
|
867
|
+
};
|
|
868
|
+
} else {
|
|
869
|
+
new utilities.Spinner(
|
|
870
|
+
`No ACM certificates match ${answers.appDomain}, HTTPS listener must be configured manually`,
|
|
871
|
+
true,
|
|
872
|
+
).ora.info();
|
|
528
873
|
}
|
|
529
874
|
}
|
|
530
875
|
}
|
|
531
876
|
|
|
877
|
+
if (answers.stack === "static") {
|
|
878
|
+
answers = {
|
|
879
|
+
...answers,
|
|
880
|
+
...(await inquirer.prompt([
|
|
881
|
+
{
|
|
882
|
+
type: "list",
|
|
883
|
+
name: "environment",
|
|
884
|
+
message: "What environment is this?",
|
|
885
|
+
choices: environmentChoices,
|
|
886
|
+
default: defaultEnvironment,
|
|
887
|
+
},
|
|
888
|
+
])),
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
|
|
532
892
|
try {
|
|
533
893
|
if (answers.stack === "static") {
|
|
534
894
|
infastructure = await aws.static(
|
|
535
895
|
slug,
|
|
536
896
|
[
|
|
537
897
|
{ Key: "repository", Value: _.repo },
|
|
538
|
-
{ Key: "environment", Value:
|
|
539
|
-
{ Key: "
|
|
898
|
+
{ Key: "environment", Value: answers.environment },
|
|
899
|
+
{ Key: "branch", Value: branch },
|
|
900
|
+
{ Key: "automated", Value: "true" },
|
|
540
901
|
],
|
|
541
902
|
credentials,
|
|
542
903
|
_.repoSafe,
|
|
@@ -549,17 +910,18 @@ module.exports = [
|
|
|
549
910
|
slug,
|
|
550
911
|
[
|
|
551
912
|
{ Key: "repository", Value: _.repo },
|
|
552
|
-
{ Key: "environment", Value:
|
|
553
|
-
{ Key: "
|
|
913
|
+
{ Key: "environment", Value: answers.environment },
|
|
914
|
+
{ Key: "branch", Value: branch },
|
|
915
|
+
{ Key: "automated", Value: "true" },
|
|
554
916
|
],
|
|
555
|
-
credentials,
|
|
556
917
|
_.repoSafe,
|
|
557
918
|
branch,
|
|
558
919
|
answers.framework,
|
|
559
|
-
answers.availability,
|
|
560
920
|
answers.database,
|
|
561
921
|
answers.storage,
|
|
562
922
|
answers.opensearch,
|
|
923
|
+
answers.cache,
|
|
924
|
+
answers.mail,
|
|
563
925
|
existingSecrets,
|
|
564
926
|
snapshot,
|
|
565
927
|
answers.elbScheme || "public",
|
|
@@ -568,6 +930,8 @@ module.exports = [
|
|
|
568
930
|
answers.appName,
|
|
569
931
|
answers.appDomain,
|
|
570
932
|
answers.certArn,
|
|
933
|
+
answers.instanceType,
|
|
934
|
+
answers.mailData,
|
|
571
935
|
);
|
|
572
936
|
}
|
|
573
937
|
} catch (e) {
|
|
@@ -582,16 +946,22 @@ module.exports = [
|
|
|
582
946
|
location: infastructure.bucket.slice(1), // Remove / from start
|
|
583
947
|
"aws-s3": answers.client,
|
|
584
948
|
"aws-cloudfront": infastructure.cloudfront,
|
|
949
|
+
environment: answers.environment,
|
|
585
950
|
}
|
|
586
951
|
: {
|
|
587
952
|
url: infastructure.url,
|
|
588
953
|
location: "/var/www/html",
|
|
589
954
|
"aws-eb": infastructure.environment,
|
|
955
|
+
environment: answers.environment,
|
|
590
956
|
paths: infastructure.paths,
|
|
591
957
|
};
|
|
592
958
|
|
|
593
959
|
config[branch] = { deploy };
|
|
594
960
|
|
|
961
|
+
if (infastructure.copy) {
|
|
962
|
+
config[branch].copy = infastructure.copy;
|
|
963
|
+
}
|
|
964
|
+
|
|
595
965
|
if (credentials.length) {
|
|
596
966
|
config[branch].deploy.users = credentials;
|
|
597
967
|
}
|