@brunwig/mup-aws-beanstalk 0.8.7 → 2.0.5
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/.babelrc +15 -4
- package/.eslintrc.yml +2 -2
- package/.yarn/install-state.gz +0 -0
- package/docs/getting-started.md +1 -1
- package/docs/index.md +22 -6
- package/index.js +1 -1
- package/lib/assets/Procfile +1 -0
- package/lib/assets/health-check.js +9 -1
- package/lib/assets/health-check.js.map +1 -1
- package/lib/assets/nginx-server.conf +5 -0
- package/lib/assets/node.sh +37 -7
- package/lib/assets/npm.sh +14 -0
- package/lib/assets/prevent-npm.sh +4 -0
- package/lib/assets/role-start.sh +61 -0
- package/lib/assets/start.sh +1 -1
- package/lib/assets/yarn.sh +17 -0
- package/lib/aws.js +43 -77
- package/lib/aws.js.map +1 -1
- package/lib/certificates.js +56 -59
- package/lib/certificates.js.map +1 -1
- package/lib/command-handlers.js +613 -637
- package/lib/command-handlers.js.map +1 -1
- package/lib/commands.js +144 -111
- package/lib/commands.js.map +1 -1
- package/lib/deployment-logs.js +127 -0
- package/lib/deployment-logs.js.map +1 -0
- package/lib/download.js +11 -18
- package/lib/download.js.map +1 -1
- package/lib/eb-config.js +246 -242
- package/lib/eb-config.js.map +1 -1
- package/lib/env-ready.js +87 -88
- package/lib/env-ready.js.map +1 -1
- package/lib/env-settings.js +13 -14
- package/lib/env-settings.js.map +1 -1
- package/lib/index.js +111 -81
- package/lib/index.js.map +1 -1
- package/lib/policies.js +130 -115
- package/lib/policies.js.map +1 -1
- package/lib/prepare-bundle.js +187 -194
- package/lib/prepare-bundle.js.map +1 -1
- package/lib/recheck.js +16 -13
- package/lib/recheck.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/lib/upload.js +35 -49
- package/lib/upload.js.map +1 -1
- package/lib/utils.js +556 -577
- package/lib/utils.js.map +1 -1
- package/lib/validate.js +61 -59
- package/lib/validate.js.map +1 -1
- package/lib/versions.js +74 -81
- package/lib/versions.js.map +1 -1
- package/package.json +60 -26
- package/readme.md +2 -1
- package/tsconfig.json +41 -0
package/lib/command-handlers.js
CHANGED
|
@@ -1,694 +1,670 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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;
|
|
5
17
|
});
|
|
6
|
-
|
|
7
|
-
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.setup = setup;
|
|
8
40
|
exports.deploy = deploy;
|
|
9
|
-
exports.events = events;
|
|
10
|
-
exports.fullLogs = fullLogs;
|
|
11
41
|
exports.logs = logs;
|
|
12
|
-
exports.
|
|
42
|
+
exports.fullLogs = fullLogs;
|
|
13
43
|
exports.logsNginx = logsNginx;
|
|
14
|
-
exports.
|
|
15
|
-
exports.restart = restart;
|
|
16
|
-
exports.setup = setup;
|
|
17
|
-
exports.shell = shell;
|
|
18
|
-
exports.ssl = ssl;
|
|
44
|
+
exports.logsEb = logsEb;
|
|
19
45
|
exports.start = start;
|
|
20
|
-
exports.status = status;
|
|
21
46
|
exports.stop = stop;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
exports.restart = restart;
|
|
48
|
+
exports.clean = clean;
|
|
49
|
+
exports.reconfig = reconfig;
|
|
50
|
+
exports.events = events;
|
|
51
|
+
exports.status = status;
|
|
52
|
+
exports.ssl = ssl;
|
|
53
|
+
exports.shell = shell;
|
|
54
|
+
exports.debug = debug;
|
|
55
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
56
|
+
const ssh2_1 = require("ssh2");
|
|
57
|
+
const aws_1 = require("./aws");
|
|
58
|
+
const certificates_1 = require("./certificates");
|
|
59
|
+
const policies_1 = require("./policies");
|
|
60
|
+
const upload_1 = __importStar(require("./upload"));
|
|
61
|
+
const prepare_bundle_1 = require("./prepare-bundle");
|
|
62
|
+
const utils_1 = require("./utils");
|
|
63
|
+
const versions_1 = require("./versions");
|
|
64
|
+
const env_settings_1 = require("./env-settings");
|
|
65
|
+
const eb_config_1 = require("./eb-config");
|
|
66
|
+
const env_ready_1 = require("./env-ready");
|
|
67
|
+
const deployment_logs_1 = require("./deployment-logs");
|
|
68
|
+
const client_elastic_beanstalk_1 = require("@aws-sdk/client-elastic-beanstalk");
|
|
42
69
|
async function setup(api) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
eventTargetRole: eventTargetRoleName,
|
|
55
|
-
eventTargetPolicyName,
|
|
56
|
-
eventTargetPassRoleName,
|
|
57
|
-
automationDocument
|
|
58
|
-
} = (0, _utils.names)(config);
|
|
59
|
-
(0, _utils.logStep)('=> @Brunwig/mup-aws-beanstalk');
|
|
60
|
-
(0, _utils.logStep)('=> Setting up');
|
|
61
|
-
|
|
62
|
-
// Create bucket if needed
|
|
63
|
-
const {
|
|
64
|
-
Buckets
|
|
65
|
-
} = await _aws.s3.listBuckets().promise();
|
|
66
|
-
const beanstalkBucketCreated = await (0, _utils.ensureBucketExists)(Buckets, bucketName, appConfig.region);
|
|
67
|
-
if (beanstalkBucketCreated) {
|
|
68
|
-
console.log(' Created Bucket');
|
|
69
|
-
}
|
|
70
|
-
(0, _utils.logStep)('=> Ensuring IAM Roles and Instance Profiles are setup');
|
|
71
|
-
|
|
72
|
-
// Create role and instance profile
|
|
73
|
-
await (0, _utils.ensureRoleExists)(instanceProfile, _policies.rolePolicy);
|
|
74
|
-
await (0, _utils.ensureInstanceProfileExists)(config, instanceProfile);
|
|
75
|
-
await (0, _utils.ensurePoliciesAttached)(config, instanceProfile, ['arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier', 'arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker', 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier', ...(appConfig.gracefulShutdown ? ['arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM'] : [])]);
|
|
76
|
-
await (0, _utils.ensureRoleAdded)(config, instanceProfile, instanceProfile);
|
|
77
|
-
|
|
78
|
-
// Create role used by enhanced health
|
|
79
|
-
await (0, _utils.ensureRoleExists)(serviceRoleName, _policies.serviceRole);
|
|
80
|
-
await (0, _utils.ensurePoliciesAttached)(config, serviceRoleName, ['arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth', 'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService']);
|
|
81
|
-
if (appConfig.gracefulShutdown) {
|
|
82
|
-
const accountId = await (0, _utils.getAccountId)();
|
|
83
|
-
const policy = (0, _policies.eventTargetRolePolicy)(accountId, environmentName, appConfig.region || 'us-east-1');
|
|
84
|
-
const passPolicy = (0, _policies.passRolePolicy)(accountId, eventTargetRoleName);
|
|
85
|
-
await (0, _utils.ensureRoleExists)(eventTargetRoleName, _policies.eventTargetRole, true);
|
|
86
|
-
await (0, _utils.ensureInlinePolicyAttached)(eventTargetRoleName, eventTargetPolicyName, policy);
|
|
87
|
-
await (0, _utils.ensureInlinePolicyAttached)(eventTargetRoleName, eventTargetPassRoleName, passPolicy);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Create beanstalk application if needed
|
|
91
|
-
const {
|
|
92
|
-
Applications
|
|
93
|
-
} = await _aws.beanstalk.describeApplications().promise();
|
|
94
|
-
if (!Applications.find(app => app.ApplicationName === appName)) {
|
|
95
|
-
const params = {
|
|
96
|
-
ApplicationName: appName,
|
|
97
|
-
Description: `App "${appConfig.name}" managed by Meteor Up`
|
|
98
|
-
};
|
|
99
|
-
await _aws.beanstalk.createApplication(params).promise();
|
|
100
|
-
console.log(' Created Beanstalk application');
|
|
101
|
-
}
|
|
102
|
-
if (appConfig.gracefulShutdown) {
|
|
103
|
-
(0, _utils.logStep)('=> Ensuring Graceful Shutdown is setup');
|
|
104
|
-
const existingBucket = (0, _utils.findBucketWithPrefix)(Buckets, trailBucketPrefix);
|
|
105
|
-
const trailBucketName = existingBucket ? existingBucket.Name : (0, _utils.createUniqueName)(trailBucketPrefix);
|
|
106
|
-
const region = appConfig.region || 'us-east-1';
|
|
107
|
-
const accountId = await (0, _utils.getAccountId)();
|
|
108
|
-
const policy = (0, _policies.trailBucketPolicy)(accountId, trailBucketName);
|
|
109
|
-
const trailBucketCreated = await (0, _utils.ensureBucketExists)(Buckets, trailBucketName, appConfig.region);
|
|
110
|
-
await (0, _utils.ensureBucketPolicyAttached)(trailBucketName, policy);
|
|
111
|
-
if (trailBucketCreated) {
|
|
112
|
-
console.log(' Created bucket for Cloud Trail');
|
|
70
|
+
const config = api.getConfig();
|
|
71
|
+
const appConfig = config.app;
|
|
72
|
+
const { bucket: bucketName, app: appName, instanceProfile, serviceRole: serviceRoleName, trailBucketPrefix, trailName, deregisterRuleName, environment: environmentName, eventTargetRole: eventTargetRoleName, eventTargetPolicyName, eventTargetPassRoleName, automationDocument } = (0, utils_1.names)(config);
|
|
73
|
+
(0, utils_1.logStep)('=> @Brunwig/mup-aws-beanstalk');
|
|
74
|
+
(0, utils_1.logStep)('=> Setting up');
|
|
75
|
+
// Create bucket if needed
|
|
76
|
+
const listBucketResult = await aws_1.s3.listBuckets({});
|
|
77
|
+
const Buckets = listBucketResult.Buckets;
|
|
78
|
+
const beanstalkBucketCreated = await (0, utils_1.ensureBucketExists)(Buckets, bucketName, appConfig.region);
|
|
79
|
+
if (beanstalkBucketCreated) {
|
|
80
|
+
console.log(' Created Bucket');
|
|
113
81
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
82
|
+
(0, utils_1.logStep)('=> Ensuring IAM Roles and Instance Profiles are setup');
|
|
83
|
+
// Create role and instance profile
|
|
84
|
+
await (0, utils_1.ensureRoleExists)(instanceProfile, policies_1.rolePolicy);
|
|
85
|
+
await (0, utils_1.ensureInstanceProfileExists)(instanceProfile);
|
|
86
|
+
await (0, utils_1.ensurePoliciesAttached)(instanceProfile, [
|
|
87
|
+
'arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier',
|
|
88
|
+
'arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker',
|
|
89
|
+
'arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier',
|
|
90
|
+
...appConfig.gracefulShutdown ? ['arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM'] : []
|
|
91
|
+
]);
|
|
92
|
+
await (0, utils_1.ensureRoleAdded)(instanceProfile, instanceProfile);
|
|
93
|
+
// Create role used by enhanced health
|
|
94
|
+
await (0, utils_1.ensureRoleExists)(serviceRoleName, policies_1.serviceRole);
|
|
95
|
+
await (0, utils_1.ensurePoliciesAttached)(serviceRoleName, [
|
|
96
|
+
'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth',
|
|
97
|
+
'arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService'
|
|
98
|
+
]);
|
|
99
|
+
if (appConfig.gracefulShutdown) {
|
|
100
|
+
const accountId = await (0, utils_1.getAccountId)();
|
|
101
|
+
const policy = (0, policies_1.eventTargetRolePolicy)(accountId, environmentName, appConfig.region || 'us-east-1');
|
|
102
|
+
const passPolicy = (0, policies_1.passRolePolicy)(accountId, eventTargetRoleName);
|
|
103
|
+
await (0, utils_1.ensureRoleExists)(eventTargetRoleName, policies_1.eventTargetRole, true);
|
|
104
|
+
await (0, utils_1.ensureInlinePolicyAttached)(eventTargetRoleName, eventTargetPolicyName, policy);
|
|
105
|
+
await (0, utils_1.ensureInlinePolicyAttached)(eventTargetRoleName, eventTargetPassRoleName, passPolicy);
|
|
127
106
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
107
|
+
// Create beanstalk application if needed
|
|
108
|
+
const { Applications } = await aws_1.beanstalk.describeApplications({});
|
|
109
|
+
if (!(Applications === null || Applications === void 0 ? void 0 : Applications.find(app => app.ApplicationName === appName))) {
|
|
110
|
+
const params = {
|
|
111
|
+
ApplicationName: appName,
|
|
112
|
+
Description: `App "${appConfig.name}" managed by Meteor Up`
|
|
113
|
+
};
|
|
114
|
+
await aws_1.beanstalk.createApplication(params);
|
|
115
|
+
console.log(' Created Beanstalk application');
|
|
131
116
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
117
|
+
if (appConfig.gracefulShutdown) {
|
|
118
|
+
(0, utils_1.logStep)('=> Ensuring Graceful Shutdown is setup');
|
|
119
|
+
const existingBucket = (0, utils_1.findBucketWithPrefix)(Buckets, trailBucketPrefix);
|
|
120
|
+
const trailBucketName = existingBucket ?
|
|
121
|
+
existingBucket.Name :
|
|
122
|
+
(0, utils_1.createUniqueName)(trailBucketPrefix);
|
|
123
|
+
const region = appConfig.region || 'us-east-1';
|
|
124
|
+
const accountId = await (0, utils_1.getAccountId)();
|
|
125
|
+
const policy = (0, policies_1.trailBucketPolicy)(accountId, trailBucketName);
|
|
126
|
+
const trailBucketCreated = await (0, utils_1.ensureBucketExists)(Buckets, trailBucketName, appConfig.region);
|
|
127
|
+
await (0, utils_1.ensureBucketPolicyAttached)(trailBucketName, policy);
|
|
128
|
+
if (trailBucketCreated) {
|
|
129
|
+
console.log(' Created bucket for Cloud Trail');
|
|
130
|
+
}
|
|
131
|
+
const params = {
|
|
132
|
+
trailNameList: [
|
|
133
|
+
trailName
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
const { trailList } = await aws_1.cloudTrail.describeTrails(params);
|
|
137
|
+
if (trailList.length === 0) {
|
|
138
|
+
const createParams = {
|
|
139
|
+
Name: trailName,
|
|
140
|
+
S3BucketName: trailBucketName
|
|
141
|
+
};
|
|
142
|
+
await aws_1.cloudTrail.createTrail(createParams);
|
|
143
|
+
console.log(' Created CloudTrail trail');
|
|
144
|
+
}
|
|
145
|
+
const createdDocument = await (0, utils_1.ensureSsmDocument)(automationDocument, (0, policies_1.gracefulShutdownAutomationDocument)());
|
|
146
|
+
if (createdDocument) {
|
|
147
|
+
console.log(' Created SSM Automation Document');
|
|
148
|
+
}
|
|
149
|
+
const createdRule = await (0, utils_1.ensureCloudWatchRule)(deregisterRuleName, 'Used by Meteor Up for graceful shutdown', policies_1.DeregisterEvent);
|
|
150
|
+
if (createdRule) {
|
|
151
|
+
console.log(' Created Cloud Watch rule');
|
|
152
|
+
}
|
|
153
|
+
const target = (0, policies_1.deregisterEventTarget)(environmentName, eventTargetRoleName, accountId, region);
|
|
154
|
+
const createdTarget = await (0, utils_1.ensureRuleTargetExists)(deregisterRuleName, target);
|
|
155
|
+
if (createdTarget) {
|
|
156
|
+
console.log(' Created target for Cloud Watch rule');
|
|
157
|
+
}
|
|
140
158
|
}
|
|
141
|
-
}
|
|
142
159
|
}
|
|
143
160
|
async function deploy(api) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
app,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (willBuild) {
|
|
160
|
-
await api.runCommand('meteor.build');
|
|
161
|
-
(0, _prepareBundle.injectFiles)(api, app, nextVersion, config.app);
|
|
162
|
-
await (0, _prepareBundle.archiveApp)(config.app.buildOptions.buildLocation, api);
|
|
163
|
-
}
|
|
164
|
-
(0, _utils.logStep)('=> Uploading bundle');
|
|
165
|
-
const key = `${bundlePrefix}${nextVersion}`;
|
|
166
|
-
await (0, _upload.default)(config.app, bucket, `${bundlePrefix}${nextVersion}`, bundlePath);
|
|
167
|
-
(0, _utils.logStep)('=> Creating version');
|
|
168
|
-
await _aws.beanstalk.createApplicationVersion({
|
|
169
|
-
ApplicationName: app,
|
|
170
|
-
VersionLabel: nextVersion.toString(),
|
|
171
|
-
Description: (0, _utils.createVersionDescription)(api, config.app),
|
|
172
|
-
SourceBundle: {
|
|
173
|
-
S3Bucket: bucket,
|
|
174
|
-
S3Key: key
|
|
161
|
+
var _a, _b, _c;
|
|
162
|
+
await api.runCommand('beanstalk.setup');
|
|
163
|
+
const config = api.getConfig();
|
|
164
|
+
const { app, bucket, bundlePrefix, environment } = (0, utils_1.names)(config);
|
|
165
|
+
const version = await (0, versions_1.largestVersion)(api);
|
|
166
|
+
const nextVersion = version + 1;
|
|
167
|
+
// Mutates the config, so the meteor.build command will have the correct build location
|
|
168
|
+
config.app.buildOptions.buildLocation = ((_a = config.app.buildOptions) === null || _a === void 0 ? void 0 : _a.buildLocation) ||
|
|
169
|
+
(0, utils_1.tmpBuildPath)(config.app.path, api);
|
|
170
|
+
const bundlePath = api.resolvePath(config.app.buildOptions.buildLocation, 'bundle.zip');
|
|
171
|
+
const willBuild = (0, utils_1.shouldRebuild)(bundlePath, api.getOptions()['cached-build']);
|
|
172
|
+
if (willBuild) {
|
|
173
|
+
await api.runCommand('meteor.build');
|
|
174
|
+
(0, prepare_bundle_1.injectFiles)(api, app, nextVersion, config.app);
|
|
175
|
+
await (0, prepare_bundle_1.archiveApp)(config.app.buildOptions.buildLocation, api);
|
|
175
176
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
177
|
+
const key = `${bundlePrefix}${nextVersion}`;
|
|
178
|
+
(0, utils_1.logStep)(`=> Uploading bundle ${key} ${bundlePath}`);
|
|
179
|
+
await (0, upload_1.default)(bucket, `${bundlePrefix}${nextVersion}`, bundlePath);
|
|
180
|
+
(0, utils_1.logStep)('=> Creating version');
|
|
181
|
+
await aws_1.beanstalk.createApplicationVersion({
|
|
182
|
+
ApplicationName: app,
|
|
183
|
+
VersionLabel: nextVersion.toString(),
|
|
184
|
+
Description: (0, utils_1.createVersionDescription)(api, config.app),
|
|
185
|
+
SourceBundle: {
|
|
186
|
+
S3Bucket: bucket,
|
|
187
|
+
S3Key: key
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
await api.runCommand('beanstalk.reconfig');
|
|
191
|
+
await (0, env_ready_1.waitForEnvReady)(config, true);
|
|
192
|
+
(0, utils_1.logStep)('=> Deploying new version');
|
|
193
|
+
const { toRemove, toUpdate } = await (0, eb_config_1.prepareUpdateEnvironment)(api);
|
|
194
|
+
const eventLog = [];
|
|
195
|
+
if (api.verbose) {
|
|
196
|
+
console.log('EB Config changes:');
|
|
197
|
+
console.dir({
|
|
198
|
+
toRemove,
|
|
199
|
+
toUpdate
|
|
200
|
+
});
|
|
201
|
+
if (config.app.streamLogs) {
|
|
202
|
+
await (0, deployment_logs_1.startLogStreamListener)(api, eventLog, 'var/log/web.stdout.log');
|
|
203
|
+
await (0, deployment_logs_1.startLogStreamListener)(api, eventLog, 'var/log/eb-hooks.log');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
await aws_1.beanstalk.updateEnvironment({
|
|
207
|
+
EnvironmentName: environment,
|
|
208
|
+
VersionLabel: nextVersion.toString(),
|
|
209
|
+
OptionSettings: toUpdate,
|
|
210
|
+
OptionsToRemove: toRemove
|
|
189
211
|
});
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
await (0, env_ready_1.waitForEnvReady)(config, true, eventLog);
|
|
213
|
+
(0, deployment_logs_1.stopLogStreamListener)();
|
|
214
|
+
// XXX Is this necessary?
|
|
215
|
+
// const {
|
|
216
|
+
// Environments
|
|
217
|
+
// } = await beanstalk.describeEnvironments({
|
|
218
|
+
// ApplicationName: app,
|
|
219
|
+
// EnvironmentNames: [environment]
|
|
220
|
+
// });
|
|
221
|
+
await api.runCommand('beanstalk.clean');
|
|
222
|
+
await api.runCommand('beanstalk.ssl');
|
|
223
|
+
// Check if deploy succeeded
|
|
224
|
+
const { Environments: finalEnvironments } = await aws_1.beanstalk.describeEnvironments({
|
|
225
|
+
ApplicationName: app,
|
|
226
|
+
EnvironmentNames: [environment]
|
|
227
|
+
});
|
|
228
|
+
const waitSeconds = 31;
|
|
229
|
+
if (nextVersion.toString() === ((_b = finalEnvironments === null || finalEnvironments === void 0 ? void 0 : finalEnvironments[0]) === null || _b === void 0 ? void 0 : _b.VersionLabel)) {
|
|
230
|
+
if (finalEnvironments[0].Health === client_elastic_beanstalk_1.EnvironmentHealth.Red) {
|
|
231
|
+
console.log(`Health status: ${finalEnvironments[0].Health}, waiting ${waitSeconds} seconds to ensure health status is stable`);
|
|
232
|
+
await new Promise((resolve) => {
|
|
233
|
+
setTimeout(resolve, waitSeconds * 1000);
|
|
234
|
+
});
|
|
235
|
+
const { Environments: reCheckedEnvironments } = await aws_1.beanstalk.describeEnvironments({
|
|
236
|
+
ApplicationName: app,
|
|
237
|
+
EnvironmentNames: [environment]
|
|
238
|
+
});
|
|
239
|
+
if ((reCheckedEnvironments === null || reCheckedEnvironments === void 0 ? void 0 : reCheckedEnvironments[0].Health) === client_elastic_beanstalk_1.EnvironmentHealth.Red) {
|
|
240
|
+
console.log(chalk_1.default.red(`Deploy Failed with invalid Health Status. Visit the Aws Elastic Beanstalk console to view the logs from the failed deploy.`));
|
|
241
|
+
process.exitCode = 1;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (config.app.envType === "worker") {
|
|
245
|
+
console.log(chalk_1.default.green(`Worker is running.`));
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
console.log(chalk_1.default.green(`App is running at ${finalEnvironments[0].CNAME}`));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.log(chalk_1.default.red(`Deploy Failed. Version expected ${nextVersion.toString()} (found ${(_c = finalEnvironments === null || finalEnvironments === void 0 ? void 0 : finalEnvironments[0]) === null || _c === void 0 ? void 0 : _c.VersionLabel}). Visit the Aws Elastic Beanstalk console to view the logs from the failed deploy.`));
|
|
253
|
+
process.exitCode = 1;
|
|
254
|
+
}
|
|
220
255
|
}
|
|
221
256
|
async function logs(api) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}) => {
|
|
227
|
-
console.log(`${instance} `, data[0] || data[1]);
|
|
228
|
-
});
|
|
257
|
+
const logsContent = await (0, utils_1.getLogs)(api, ['web.stdout.log', 'nodejs/nodejs.log']);
|
|
258
|
+
logsContent.forEach(({ instance, data }) => {
|
|
259
|
+
console.log(`${instance} `, data[0] || data[1]);
|
|
260
|
+
});
|
|
229
261
|
}
|
|
230
262
|
async function fullLogs(api) {
|
|
231
|
-
|
|
232
|
-
|
|
263
|
+
const logsContent = await (0, utils_1.downloadFullServerLogs)(api);
|
|
264
|
+
(0, utils_1.logStep)(`=> downloadFullServerLogs: ${JSON.stringify(logsContent, null, '\t')}`);
|
|
233
265
|
}
|
|
234
266
|
async function logsNginx(api) {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
console.log(`${instance} `, data[0]);
|
|
241
|
-
console.log(`${instance} `, data[1]);
|
|
242
|
-
});
|
|
267
|
+
const logsContent = await (0, utils_1.getLogs)(api, ['nginx/error.log', 'nginx/access.log']);
|
|
268
|
+
logsContent.forEach(({ instance, data }) => {
|
|
269
|
+
console.log(`${instance} `, data[0]);
|
|
270
|
+
console.log(`${instance} `, data[1]);
|
|
271
|
+
});
|
|
243
272
|
}
|
|
244
273
|
async function logsEb(api) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}) => {
|
|
250
|
-
console.log(`${instance} `, data[0] || data[1]);
|
|
251
|
-
});
|
|
274
|
+
const logsContent = await (0, utils_1.getLogs)(api, ['eb-engine.log', 'eb-activity.log']);
|
|
275
|
+
logsContent.forEach(({ data, instance }) => {
|
|
276
|
+
console.log(`${instance} `, data[0] || data[1]);
|
|
277
|
+
});
|
|
252
278
|
}
|
|
253
279
|
async function start(api) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
EnvironmentResources
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
await _aws.autoScaling.updateAutoScalingGroup({
|
|
270
|
-
AutoScalingGroupName: autoScalingGroup,
|
|
271
|
-
MaxSize: maxInstances,
|
|
272
|
-
MinSize: minInstances,
|
|
273
|
-
DesiredCapacity: minInstances
|
|
274
|
-
}).promise();
|
|
275
|
-
await (0, _envReady.waitForHealth)(config);
|
|
280
|
+
const config = api.getConfig();
|
|
281
|
+
const { environment } = (0, utils_1.names)(config);
|
|
282
|
+
(0, utils_1.logStep)('=> Starting App');
|
|
283
|
+
const { EnvironmentResources } = await aws_1.beanstalk.describeEnvironmentResources({
|
|
284
|
+
EnvironmentName: environment
|
|
285
|
+
});
|
|
286
|
+
const autoScalingGroup = EnvironmentResources.AutoScalingGroups[0].Name;
|
|
287
|
+
const { minInstances, maxInstances } = config.app;
|
|
288
|
+
await aws_1.autoScaling.updateAutoScalingGroup({
|
|
289
|
+
AutoScalingGroupName: autoScalingGroup,
|
|
290
|
+
MaxSize: maxInstances,
|
|
291
|
+
MinSize: minInstances,
|
|
292
|
+
DesiredCapacity: minInstances
|
|
293
|
+
});
|
|
294
|
+
await (0, env_ready_1.waitForHealth)(config, undefined, false);
|
|
276
295
|
}
|
|
277
296
|
async function stop(api) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
EnvironmentResources
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
MinSize: 0,
|
|
293
|
-
DesiredCapacity: 0
|
|
294
|
-
}).promise();
|
|
295
|
-
await (0, _envReady.waitForHealth)(config, 'Grey');
|
|
297
|
+
const config = api.getConfig();
|
|
298
|
+
const { environment } = (0, utils_1.names)(config);
|
|
299
|
+
(0, utils_1.logStep)('=> Stopping App');
|
|
300
|
+
const { EnvironmentResources } = await aws_1.beanstalk.describeEnvironmentResources({
|
|
301
|
+
EnvironmentName: environment
|
|
302
|
+
});
|
|
303
|
+
const autoScalingGroup = EnvironmentResources.AutoScalingGroups[0].Name;
|
|
304
|
+
await aws_1.autoScaling.updateAutoScalingGroup({
|
|
305
|
+
AutoScalingGroupName: autoScalingGroup,
|
|
306
|
+
MaxSize: 0,
|
|
307
|
+
MinSize: 0,
|
|
308
|
+
DesiredCapacity: 0
|
|
309
|
+
});
|
|
310
|
+
await (0, env_ready_1.waitForHealth)(config, 'Grey', false);
|
|
296
311
|
}
|
|
297
312
|
async function restart(api) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}).promise();
|
|
306
|
-
await (0, _envReady.waitForEnvReady)(config, false);
|
|
313
|
+
const config = api.getConfig();
|
|
314
|
+
const { environment } = (0, utils_1.names)(config);
|
|
315
|
+
(0, utils_1.logStep)('=> Restarting App');
|
|
316
|
+
await aws_1.beanstalk.restartAppServer({
|
|
317
|
+
EnvironmentName: environment
|
|
318
|
+
});
|
|
319
|
+
await (0, env_ready_1.waitForEnvReady)(config, false);
|
|
307
320
|
}
|
|
308
321
|
async function clean(api) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
versions
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// TODO: remove bundles
|
|
336
|
-
|
|
337
|
-
await Promise.all(promises);
|
|
322
|
+
const config = api.getConfig();
|
|
323
|
+
const { app, bucket } = (0, utils_1.names)(config);
|
|
324
|
+
(0, utils_1.logStep)('=> Finding old versions');
|
|
325
|
+
const { versions } = await (0, versions_1.oldVersions)(api);
|
|
326
|
+
const envVersions = await (0, versions_1.oldEnvVersions)(api);
|
|
327
|
+
(0, utils_1.logStep)('=> Removing old versions');
|
|
328
|
+
const promises = [];
|
|
329
|
+
for (let i = 0; i < versions.length; i++) {
|
|
330
|
+
promises.push(aws_1.beanstalk.deleteApplicationVersion({
|
|
331
|
+
ApplicationName: app,
|
|
332
|
+
VersionLabel: versions[i].toString(),
|
|
333
|
+
DeleteSourceBundle: true
|
|
334
|
+
}));
|
|
335
|
+
console.log(" - ", versions[i].toString());
|
|
336
|
+
}
|
|
337
|
+
for (let i = 0; i < envVersions.length; i++) {
|
|
338
|
+
promises.push(aws_1.s3.deleteObject({
|
|
339
|
+
Bucket: bucket,
|
|
340
|
+
Key: `env/${envVersions[i]}.txt`
|
|
341
|
+
}));
|
|
342
|
+
console.log(" - ", `env/${envVersions[i]}.txt`, bucket);
|
|
343
|
+
}
|
|
344
|
+
// TODO: remove bundles
|
|
345
|
+
await Promise.all(promises);
|
|
338
346
|
}
|
|
339
347
|
async function reconfig(api) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
348
|
+
const config = api.getConfig();
|
|
349
|
+
const { app, environment, bucket } = (0, utils_1.names)(config);
|
|
350
|
+
const deploying = !!api.commandHistory.find(entry => entry.name === 'beanstalk.deploy');
|
|
351
|
+
(0, utils_1.logStep)('=> @Brunwig/mup-aws-beanstalk');
|
|
352
|
+
(0, utils_1.logStep)('=> Configuring Beanstalk environment');
|
|
353
|
+
// check if env exists
|
|
354
|
+
const { Environments } = await aws_1.beanstalk.describeEnvironments({
|
|
355
|
+
ApplicationName: app,
|
|
356
|
+
EnvironmentNames: [environment]
|
|
357
|
+
});
|
|
358
|
+
const environmentExists = Environments.find(env => env.Status !== 'Terminated');
|
|
359
|
+
if (!environmentExists) {
|
|
360
|
+
const desiredEbConfig = (0, eb_config_1.createDesiredConfig)(api.getConfig(), api.getSettings(), config.app.longEnvVars ? 1 : false);
|
|
361
|
+
if (config.app.longEnvVars) {
|
|
362
|
+
const envContent = (0, env_settings_1.createEnvFile)(config.app.env, api.getSettings());
|
|
363
|
+
await (0, upload_1.uploadEnvFile)(bucket, 1, envContent);
|
|
364
|
+
}
|
|
365
|
+
const platformArn = await (0, utils_1.selectPlatformArn)(api.getConfig().app.awsPlatformBranchName);
|
|
366
|
+
const [version] = await (0, versions_1.ebVersions)(api);
|
|
367
|
+
// Whether this is a web or worker environment
|
|
368
|
+
const envTierConfig = (0, eb_config_1.getEnvTierConfig)(config.app.envType);
|
|
369
|
+
await aws_1.beanstalk.createEnvironment({
|
|
370
|
+
ApplicationName: app,
|
|
371
|
+
EnvironmentName: environment,
|
|
372
|
+
Description: `Environment for ${config.app.name}, managed by Meteor Up`,
|
|
373
|
+
VersionLabel: version.toString(),
|
|
374
|
+
PlatformArn: platformArn,
|
|
375
|
+
Tier: envTierConfig,
|
|
376
|
+
OptionSettings: desiredEbConfig.OptionSettings
|
|
377
|
+
});
|
|
378
|
+
console.log(' Created Environment');
|
|
379
|
+
await (0, env_ready_1.waitForEnvReady)(config, false);
|
|
362
380
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
console.dir({
|
|
385
|
-
toRemove,
|
|
386
|
-
toUpdate
|
|
387
|
-
});
|
|
381
|
+
else if (!deploying) {
|
|
382
|
+
// If we are deploying, the environment will be updated
|
|
383
|
+
// at the same time we update the environment version
|
|
384
|
+
const { toRemove, toUpdate } = await (0, eb_config_1.prepareUpdateEnvironment)(api);
|
|
385
|
+
if (api.verbose) {
|
|
386
|
+
console.log('EB Config changes:');
|
|
387
|
+
console.dir({
|
|
388
|
+
toRemove,
|
|
389
|
+
toUpdate
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
if (toRemove.length > 0 || toUpdate.length > 0) {
|
|
393
|
+
await (0, env_ready_1.waitForEnvReady)(config, true);
|
|
394
|
+
await aws_1.beanstalk.updateEnvironment({
|
|
395
|
+
EnvironmentName: environment,
|
|
396
|
+
OptionSettings: toUpdate,
|
|
397
|
+
OptionsToRemove: toRemove
|
|
398
|
+
});
|
|
399
|
+
console.log(' Updated Environment');
|
|
400
|
+
await (0, env_ready_1.waitForEnvReady)(config, true);
|
|
401
|
+
}
|
|
388
402
|
}
|
|
389
|
-
|
|
390
|
-
await (0, _envReady.waitForEnvReady)(config, true);
|
|
391
|
-
await _aws.beanstalk.updateEnvironment({
|
|
403
|
+
const { ConfigurationSettings } = await aws_1.beanstalk.describeConfigurationSettings({
|
|
392
404
|
EnvironmentName: environment,
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
405
|
+
ApplicationName: app
|
|
406
|
+
});
|
|
407
|
+
if ((0, eb_config_1.scalingConfigChanged)(ConfigurationSettings[0].OptionSettings, config)) {
|
|
408
|
+
(0, utils_1.logStep)('=> Configuring scaling');
|
|
409
|
+
await aws_1.beanstalk.updateEnvironment({
|
|
410
|
+
EnvironmentName: environment,
|
|
411
|
+
OptionSettings: (0, eb_config_1.scalingConfig)(config.app).OptionSettings
|
|
412
|
+
});
|
|
413
|
+
await (0, env_ready_1.waitForEnvReady)(config, true);
|
|
398
414
|
}
|
|
399
|
-
}
|
|
400
|
-
const {
|
|
401
|
-
ConfigurationSettings
|
|
402
|
-
} = await _aws.beanstalk.describeConfigurationSettings({
|
|
403
|
-
EnvironmentName: environment,
|
|
404
|
-
ApplicationName: app
|
|
405
|
-
}).promise();
|
|
406
|
-
if ((0, _ebConfig.scalingConfigChanged)(ConfigurationSettings[0].OptionSettings, config)) {
|
|
407
|
-
(0, _utils.logStep)('=> Configuring scaling');
|
|
408
|
-
await _aws.beanstalk.updateEnvironment({
|
|
409
|
-
EnvironmentName: environment,
|
|
410
|
-
OptionSettings: (0, _ebConfig.scalingConfig)(config.app).OptionSettings
|
|
411
|
-
}).promise();
|
|
412
|
-
await (0, _envReady.waitForEnvReady)(config, true);
|
|
413
|
-
}
|
|
414
415
|
}
|
|
415
416
|
async function events(api) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
} = await _aws.beanstalk.describeEvents({
|
|
422
|
-
EnvironmentName: environment
|
|
423
|
-
}).promise();
|
|
424
|
-
console.log(envEvents.map(ev => `${ev.EventDate}: ${ev.Message}`).join('\n'));
|
|
417
|
+
const { environment } = (0, utils_1.names)(api.getConfig());
|
|
418
|
+
const { Events: envEvents } = await aws_1.beanstalk.describeEvents({
|
|
419
|
+
EnvironmentName: environment
|
|
420
|
+
});
|
|
421
|
+
console.log(envEvents.map(ev => `${ev.EventDate}: ${ev.Message}`).join('\n'));
|
|
425
422
|
}
|
|
426
423
|
async function status(api) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
424
|
+
const { environment } = (0, utils_1.names)(api.getConfig());
|
|
425
|
+
let result;
|
|
426
|
+
try {
|
|
427
|
+
result = await aws_1.beanstalk.describeEnvironmentHealth({
|
|
428
|
+
AttributeNames: [
|
|
429
|
+
'All'
|
|
430
|
+
],
|
|
431
|
+
EnvironmentName: environment
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
catch (e) {
|
|
435
|
+
// @ts-ignore
|
|
436
|
+
if (e.message.includes('No Environment found for EnvironmentName')) {
|
|
437
|
+
console.log(' AWS Beanstalk environment does not exist');
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
throw e;
|
|
441
|
+
}
|
|
442
|
+
const { InstanceHealthList } = await aws_1.beanstalk.describeInstancesHealth({
|
|
443
|
+
AttributeNames: [
|
|
444
|
+
'All'
|
|
445
|
+
],
|
|
446
|
+
EnvironmentName: environment
|
|
447
|
+
});
|
|
448
|
+
const { RequestCount, Duration, StatusCodes, Latency } = result.ApplicationMetrics;
|
|
449
|
+
console.log(`Environment Status: ${result.Status}`);
|
|
450
|
+
console.log(`Health Status: ${(0, utils_1.coloredStatusText)(result.Color, result.HealthStatus)}`);
|
|
451
|
+
if (result.Causes.length > 0) {
|
|
452
|
+
console.log('Causes: ');
|
|
453
|
+
result.Causes.forEach(cause => console.log(` ${cause}`));
|
|
454
|
+
}
|
|
455
|
+
console.log('');
|
|
456
|
+
console.log(`=== Metrics For Last ${Duration || 'Unknown'} Minutes ===`);
|
|
457
|
+
console.log(` Requests: ${RequestCount}`);
|
|
458
|
+
if (StatusCodes) {
|
|
459
|
+
console.log(' Status Codes');
|
|
460
|
+
console.log(` 2xx: ${StatusCodes.Status2xx}`);
|
|
461
|
+
console.log(` 3xx: ${StatusCodes.Status3xx}`);
|
|
462
|
+
console.log(` 4xx: ${StatusCodes.Status4xx}`);
|
|
463
|
+
console.log(` 5xx: ${StatusCodes.Status5xx}`);
|
|
464
|
+
}
|
|
465
|
+
if (Latency) {
|
|
466
|
+
console.log(' Latency');
|
|
467
|
+
console.log(` 99.9%: ${Latency.P999}`);
|
|
468
|
+
console.log(` 99% : ${Latency.P99}`);
|
|
469
|
+
console.log(` 95% : ${Latency.P95}`);
|
|
470
|
+
console.log(` 90% : ${Latency.P90}`);
|
|
471
|
+
console.log(` 85% : ${Latency.P85}`);
|
|
472
|
+
console.log(` 75% : ${Latency.P75}`);
|
|
473
|
+
console.log(` 50% : ${Latency.P50}`);
|
|
474
|
+
console.log(` 10% : ${Latency.P10}`);
|
|
475
|
+
}
|
|
476
|
+
console.log('');
|
|
477
|
+
console.log('=== Instances ===');
|
|
478
|
+
InstanceHealthList.forEach((instance) => {
|
|
479
|
+
console.log(` ${instance.InstanceId}: ${(0, utils_1.coloredStatusText)(instance.Color, instance.HealthStatus)}`);
|
|
480
|
+
});
|
|
481
|
+
if (InstanceHealthList.length === 0) {
|
|
482
|
+
console.log(' 0 Instances');
|
|
440
483
|
}
|
|
441
|
-
throw e;
|
|
442
|
-
}
|
|
443
|
-
const {
|
|
444
|
-
InstanceHealthList
|
|
445
|
-
} = await _aws.beanstalk.describeInstancesHealth({
|
|
446
|
-
AttributeNames: ['All'],
|
|
447
|
-
EnvironmentName: environment
|
|
448
|
-
}).promise();
|
|
449
|
-
const {
|
|
450
|
-
RequestCount,
|
|
451
|
-
Duration,
|
|
452
|
-
StatusCodes,
|
|
453
|
-
Latency
|
|
454
|
-
} = result.ApplicationMetrics;
|
|
455
|
-
console.log(`Environment Status: ${result.Status}`);
|
|
456
|
-
console.log(`Health Status: ${(0, _utils.coloredStatusText)(result.Color, result.HealthStatus)}`);
|
|
457
|
-
if (result.Causes.length > 0) {
|
|
458
|
-
console.log('Causes: ');
|
|
459
|
-
result.Causes.forEach(cause => console.log(` ${cause}`));
|
|
460
|
-
}
|
|
461
|
-
console.log('');
|
|
462
|
-
console.log(`=== Metrics For Last ${Duration || 'Unknown'} Minutes ===`);
|
|
463
|
-
console.log(` Requests: ${RequestCount}`);
|
|
464
|
-
if (StatusCodes) {
|
|
465
|
-
console.log(' Status Codes');
|
|
466
|
-
console.log(` 2xx: ${StatusCodes.Status2xx}`);
|
|
467
|
-
console.log(` 3xx: ${StatusCodes.Status3xx}`);
|
|
468
|
-
console.log(` 4xx: ${StatusCodes.Status4xx}`);
|
|
469
|
-
console.log(` 5xx: ${StatusCodes.Status5xx}`);
|
|
470
|
-
}
|
|
471
|
-
if (Latency) {
|
|
472
|
-
console.log(' Latency');
|
|
473
|
-
console.log(` 99.9%: ${Latency.P999}`);
|
|
474
|
-
console.log(` 99% : ${Latency.P99}`);
|
|
475
|
-
console.log(` 95% : ${Latency.P95}`);
|
|
476
|
-
console.log(` 90% : ${Latency.P90}`);
|
|
477
|
-
console.log(` 85% : ${Latency.P85}`);
|
|
478
|
-
console.log(` 75% : ${Latency.P75}`);
|
|
479
|
-
console.log(` 50% : ${Latency.P50}`);
|
|
480
|
-
console.log(` 10% : ${Latency.P10}`);
|
|
481
|
-
}
|
|
482
|
-
console.log('');
|
|
483
|
-
console.log('=== Instances ===');
|
|
484
|
-
InstanceHealthList.forEach(instance => {
|
|
485
|
-
console.log(` ${instance.InstanceId}: ${(0, _utils.coloredStatusText)(instance.Color, instance.HealthStatus)}`);
|
|
486
|
-
});
|
|
487
|
-
if (InstanceHealthList.length === 0) {
|
|
488
|
-
console.log(' 0 Instances');
|
|
489
|
-
}
|
|
490
484
|
}
|
|
491
485
|
async function ssl(api) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
await (0,
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const {
|
|
502
|
-
CertificateSummaryList
|
|
503
|
-
} = await _aws.acm.listCertificates().promise();
|
|
504
|
-
let found = null;
|
|
505
|
-
for (let i = 0; i < CertificateSummaryList.length; i++) {
|
|
506
|
-
const {
|
|
507
|
-
DomainName,
|
|
508
|
-
CertificateArn
|
|
509
|
-
} = CertificateSummaryList[i];
|
|
510
|
-
if (DomainName === domains[0]) {
|
|
511
|
-
const {
|
|
512
|
-
Certificate
|
|
513
|
-
} = await _aws.acm.describeCertificate({
|
|
514
|
-
// eslint-disable-line no-await-in-loop
|
|
515
|
-
CertificateArn
|
|
516
|
-
}).promise();
|
|
517
|
-
if (domains.join(',') === Certificate.SubjectAlternativeNames.join(',')) {
|
|
518
|
-
found = CertificateSummaryList[i];
|
|
519
|
-
}
|
|
486
|
+
const config = api.getConfig();
|
|
487
|
+
// Worker envs don't need ssl
|
|
488
|
+
if (config.app.envType !== 'webserver')
|
|
489
|
+
return;
|
|
490
|
+
await (0, env_ready_1.waitForEnvReady)(config, true);
|
|
491
|
+
if (!config.app || !config.app.sslDomains) {
|
|
492
|
+
(0, utils_1.logStep)('=> Updating Beanstalk SSL Config');
|
|
493
|
+
await (0, certificates_1.ensureSSLConfigured)(config);
|
|
494
|
+
return;
|
|
520
495
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
let checks = 0;
|
|
536
|
-
let certificate;
|
|
537
|
-
|
|
538
|
-
/* eslint-disable no-await-in-loop */
|
|
539
|
-
while (!emailsProvided && checks < 5) {
|
|
540
|
-
const {
|
|
541
|
-
Certificate
|
|
542
|
-
} = await _aws.acm.describeCertificate({
|
|
543
|
-
CertificateArn: certificateArn
|
|
544
|
-
}).promise();
|
|
545
|
-
const validationOptions = Certificate.DomainValidationOptions[0];
|
|
546
|
-
if (typeof validationOptions.ValidationEmails === 'undefined') {
|
|
547
|
-
emailsProvided = true;
|
|
548
|
-
certificate = Certificate;
|
|
549
|
-
} else if (validationOptions.ValidationEmails.length > 0 || checks === 6) {
|
|
550
|
-
emailsProvided = true;
|
|
551
|
-
certificate = Certificate;
|
|
552
|
-
} else {
|
|
553
|
-
checks += 1;
|
|
554
|
-
await new Promise(resolve => {
|
|
555
|
-
setTimeout(resolve, 1000 * 10);
|
|
556
|
-
});
|
|
496
|
+
(0, utils_1.logStep)('=> Checking Certificate Status');
|
|
497
|
+
const domains = config.app.sslDomains;
|
|
498
|
+
const { CertificateSummaryList } = await aws_1.acm.listCertificates({});
|
|
499
|
+
let found = null;
|
|
500
|
+
for (let i = 0; i < CertificateSummaryList.length; i++) {
|
|
501
|
+
const { DomainName, CertificateArn } = CertificateSummaryList[i];
|
|
502
|
+
if (DomainName === domains[0]) {
|
|
503
|
+
const { Certificate } = await aws_1.acm.describeCertificate({
|
|
504
|
+
CertificateArn
|
|
505
|
+
});
|
|
506
|
+
if (domains.join(',') === Certificate.SubjectAlternativeNames.join(',')) {
|
|
507
|
+
found = CertificateSummaryList[i];
|
|
508
|
+
}
|
|
509
|
+
}
|
|
557
510
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
ValidationDomain,
|
|
565
|
-
ValidationStatus
|
|
566
|
-
}) => {
|
|
567
|
-
if (ValidationStatus === 'SUCCESS') {
|
|
568
|
-
console.log(_chalk.default.green(`${ValidationDomain || DomainName} has been verified`));
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
console.log(_chalk.default.yellow(`${ValidationDomain || DomainName} is pending validation`));
|
|
572
|
-
if (ValidationEmails) {
|
|
573
|
-
console.log('Emails with instructions have been sent to:');
|
|
574
|
-
ValidationEmails.forEach(email => {
|
|
575
|
-
console.log(` ${email}`);
|
|
511
|
+
let certificateArn;
|
|
512
|
+
if (!found) {
|
|
513
|
+
(0, utils_1.logStep)('=> Requesting Certificate');
|
|
514
|
+
const result = await aws_1.acm.requestCertificate({
|
|
515
|
+
DomainName: domains.shift(),
|
|
516
|
+
SubjectAlternativeNames: domains.length > 0 ? domains : undefined
|
|
576
517
|
});
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
518
|
+
certificateArn = result.CertificateArn;
|
|
519
|
+
}
|
|
520
|
+
if (found) {
|
|
521
|
+
certificateArn = found.CertificateArn;
|
|
522
|
+
}
|
|
523
|
+
let emailsProvided = false;
|
|
524
|
+
let checks = 0;
|
|
525
|
+
let certificate;
|
|
526
|
+
/* eslint-disable no-await-in-loop */
|
|
527
|
+
while (!emailsProvided && checks < 5) {
|
|
528
|
+
const certRes = await aws_1.acm.describeCertificate({
|
|
529
|
+
CertificateArn: certificateArn
|
|
530
|
+
});
|
|
531
|
+
const Certificate = certRes.Certificate;
|
|
532
|
+
const validationOptions = Certificate.DomainValidationOptions[0];
|
|
533
|
+
if (typeof validationOptions.ValidationEmails === 'undefined') {
|
|
534
|
+
emailsProvided = true;
|
|
535
|
+
certificate = Certificate;
|
|
536
|
+
}
|
|
537
|
+
else if (validationOptions.ValidationEmails.length > 0 || checks === 6) {
|
|
538
|
+
emailsProvided = true;
|
|
539
|
+
certificate = Certificate;
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
checks += 1;
|
|
543
|
+
await new Promise((resolve) => {
|
|
544
|
+
setTimeout(resolve, 1000 * 10);
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (certificate && certificate.Status === 'PENDING_VALIDATION') {
|
|
549
|
+
console.log('Certificate is pending validation.');
|
|
550
|
+
certificate.DomainValidationOptions.forEach(({ DomainName, ValidationEmails, ValidationDomain, ValidationStatus }) => {
|
|
551
|
+
if (ValidationStatus === 'SUCCESS') {
|
|
552
|
+
console.log(chalk_1.default.green(`${ValidationDomain || DomainName} has been verified`));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
console.log(chalk_1.default.yellow(`${ValidationDomain || DomainName} is pending validation`));
|
|
556
|
+
if (ValidationEmails) {
|
|
557
|
+
console.log('Emails with instructions have been sent to:');
|
|
558
|
+
ValidationEmails.forEach((email) => {
|
|
559
|
+
console.log(` ${email}`);
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
console.log('Run "mup beanstalk ssl" after you have verified the domains, or to check the verification status');
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
else if (certificate && certificate.Status === 'ISSUED') {
|
|
566
|
+
console.log(chalk_1.default.green('Certificate has been issued'));
|
|
567
|
+
(0, utils_1.logStep)('=> Updating Beanstalk SSL config');
|
|
568
|
+
await (0, certificates_1.ensureSSLConfigured)(config, certificateArn);
|
|
569
|
+
}
|
|
585
570
|
}
|
|
586
571
|
async function shell(api) {
|
|
587
|
-
|
|
588
|
-
selected
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
stream.setWindow(process.stdout.rows, process.stdout.columns);
|
|
621
|
-
});
|
|
622
|
-
});
|
|
623
|
-
}).connect(sshOptions);
|
|
572
|
+
const { selected, description } = await (0, utils_1.pickInstance)(api.getConfig(), api.getArgs()[2]);
|
|
573
|
+
if (!selected) {
|
|
574
|
+
console.log(description);
|
|
575
|
+
console.log('Run "mup beanstalk shell <instance id>"');
|
|
576
|
+
process.exitCode = 1;
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const { sshOptions, removeSSHAccess } = await (0, utils_1.connectToInstance)(api, selected, 'mup beanstalk shell');
|
|
580
|
+
const conn = new ssh2_1.Client();
|
|
581
|
+
conn.on('ready', () => {
|
|
582
|
+
conn.exec('sudo node /home/webapp/meteor-shell.js', {
|
|
583
|
+
pty: true
|
|
584
|
+
}, (err, stream) => {
|
|
585
|
+
if (err) {
|
|
586
|
+
throw err;
|
|
587
|
+
}
|
|
588
|
+
stream.on('close', async () => {
|
|
589
|
+
conn.end();
|
|
590
|
+
await removeSSHAccess();
|
|
591
|
+
process.exit();
|
|
592
|
+
});
|
|
593
|
+
process.stdin.setRawMode(true);
|
|
594
|
+
process.stdin.pipe(stream);
|
|
595
|
+
stream.pipe(process.stdout);
|
|
596
|
+
stream.stderr.pipe(process.stderr);
|
|
597
|
+
// @ts-ignore
|
|
598
|
+
stream.setWindow(process.stdout.rows, process.stdout.columns);
|
|
599
|
+
process.stdout.on('resize', () => {
|
|
600
|
+
// @ts-ignore
|
|
601
|
+
stream.setWindow(process.stdout.rows, process.stdout.columns);
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
}).connect(sshOptions);
|
|
624
605
|
}
|
|
625
606
|
async function debug(api) {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
selected
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
console.log('Run "mup beanstalk debug <instance id>"');
|
|
634
|
-
process.exitCode = 1;
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
const {
|
|
638
|
-
sshOptions,
|
|
639
|
-
removeSSHAccess
|
|
640
|
-
} = await (0, _utils.connectToInstance)(api, selected, 'mup beanstalk debug');
|
|
641
|
-
const conn = new _ssh.Client();
|
|
642
|
-
conn.on('ready', async () => {
|
|
643
|
-
const result = await (0, _utils.executeSSHCommand)(conn, 'sudo pkill -USR1 -u webapp -n node || sudo pkill -USR1 -u nodejs -n node');
|
|
644
|
-
if (api.verbose) {
|
|
645
|
-
console.log(result.output);
|
|
607
|
+
const config = api.getConfig();
|
|
608
|
+
const { selected, description } = await (0, utils_1.pickInstance)(config, api.getArgs()[2]);
|
|
609
|
+
if (!selected) {
|
|
610
|
+
console.log(description);
|
|
611
|
+
console.log('Run "mup beanstalk debug <instance id>"');
|
|
612
|
+
process.exitCode = 1;
|
|
613
|
+
return;
|
|
646
614
|
}
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
localAddress: '0.0.0.0',
|
|
654
|
-
localPort: 9229,
|
|
655
|
-
remoteAddress: '127.0.0.1',
|
|
656
|
-
remotePort: 9229,
|
|
657
|
-
onError(error) {
|
|
658
|
-
console.error(error);
|
|
659
|
-
},
|
|
660
|
-
onReady() {
|
|
661
|
-
console.log('Connected to server');
|
|
662
|
-
console.log('');
|
|
663
|
-
console.log('Debugger listening on ws://127.0.0.1:9229');
|
|
664
|
-
console.log('');
|
|
665
|
-
console.log('To debug:');
|
|
666
|
-
console.log('1. Open chrome://inspect in Chrome');
|
|
667
|
-
console.log('2. Select "Open dedicated DevTools for Node"');
|
|
668
|
-
console.log('3. Wait a minute while it connects and loads the app.');
|
|
669
|
-
console.log(' When it is ready, the app\'s files will appear in the Sources tab');
|
|
670
|
-
console.log('');
|
|
671
|
-
console.log('Warning: Do not use breakpoints when debugging a production server.');
|
|
672
|
-
console.log('They will pause your server when hit, causing it to not handle methods or subscriptions.');
|
|
673
|
-
console.log('Use logpoints or something else that does not pause the server');
|
|
674
|
-
console.log('');
|
|
675
|
-
console.log('The debugger will be enabled until the next time the app is restarted,');
|
|
676
|
-
console.log('though only accessible while this command is running');
|
|
677
|
-
},
|
|
678
|
-
onConnection() {
|
|
679
|
-
if (!loggedConnection) {
|
|
680
|
-
// It isn't guaranteed the debugger is connected, but not many
|
|
681
|
-
// other tools will try to connect to port 9229.
|
|
682
|
-
console.log('');
|
|
683
|
-
console.log('Detected by debugger');
|
|
684
|
-
loggedConnection = true;
|
|
615
|
+
const { sshOptions, removeSSHAccess } = await (0, utils_1.connectToInstance)(api, selected, 'mup beanstalk debug');
|
|
616
|
+
const conn = new ssh2_1.Client();
|
|
617
|
+
conn.on('ready', async () => {
|
|
618
|
+
const result = await (0, utils_1.executeSSHCommand)(conn, 'sudo pkill -USR1 -u webapp -n node || sudo pkill -USR1 -u nodejs -n node');
|
|
619
|
+
if (api.verbose) {
|
|
620
|
+
console.log(result.output);
|
|
685
621
|
}
|
|
686
|
-
|
|
622
|
+
const server = {
|
|
623
|
+
...sshOptions,
|
|
624
|
+
pem: api.resolvePath(config.app.sshKey.privateKey)
|
|
625
|
+
};
|
|
626
|
+
let loggedConnection = false;
|
|
627
|
+
api.forwardPort({
|
|
628
|
+
server,
|
|
629
|
+
localAddress: '0.0.0.0',
|
|
630
|
+
localPort: 9229,
|
|
631
|
+
remoteAddress: '127.0.0.1',
|
|
632
|
+
remotePort: 9229,
|
|
633
|
+
onError(error) {
|
|
634
|
+
console.error(error);
|
|
635
|
+
},
|
|
636
|
+
onReady() {
|
|
637
|
+
console.log('Connected to server');
|
|
638
|
+
console.log('');
|
|
639
|
+
console.log('Debugger listening on ws://127.0.0.1:9229');
|
|
640
|
+
console.log('');
|
|
641
|
+
console.log('To debug:');
|
|
642
|
+
console.log('1. Open chrome://inspect in Chrome');
|
|
643
|
+
console.log('2. Select "Open dedicated DevTools for Node"');
|
|
644
|
+
console.log('3. Wait a minute while it connects and loads the app.');
|
|
645
|
+
console.log(' When it is ready, the app\'s files will appear in the Sources tab');
|
|
646
|
+
console.log('');
|
|
647
|
+
console.log('Warning: Do not use breakpoints when debugging a production server.');
|
|
648
|
+
console.log('They will pause your server when hit, causing it to not handle methods or subscriptions.');
|
|
649
|
+
console.log('Use logpoints or something else that does not pause the server');
|
|
650
|
+
console.log('');
|
|
651
|
+
console.log('The debugger will be enabled until the next time the app is restarted,');
|
|
652
|
+
console.log('though only accessible while this command is running');
|
|
653
|
+
},
|
|
654
|
+
onConnection() {
|
|
655
|
+
if (!loggedConnection) {
|
|
656
|
+
// It isn't guaranteed the debugger is connected, but not many
|
|
657
|
+
// other tools will try to connect to port 9229.
|
|
658
|
+
console.log('');
|
|
659
|
+
console.log('Detected by debugger');
|
|
660
|
+
loggedConnection = true;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
}).connect(sshOptions);
|
|
665
|
+
process.on('SIGINT', async () => {
|
|
666
|
+
await removeSSHAccess();
|
|
667
|
+
process.exit();
|
|
687
668
|
});
|
|
688
|
-
}).connect(sshOptions);
|
|
689
|
-
process.on('SIGINT', async () => {
|
|
690
|
-
await removeSSHAccess();
|
|
691
|
-
process.exit();
|
|
692
|
-
});
|
|
693
669
|
}
|
|
694
670
|
//# sourceMappingURL=command-handlers.js.map
|