cloudmason 0.0.1 → 1.0.2
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/.github/workflows/CODEOWNERS +1 -0
- package/.github/workflows/main.yml +27 -27
- package/README.md +373 -25
- package/build.js +20 -20
- package/commands/delete.js +67 -28
- package/commands/helpers/cf.js +181 -117
- package/commands/helpers/common.js +82 -0
- package/commands/helpers/ec2.js +154 -40
- package/commands/helpers/params.js +231 -178
- package/commands/helpers/s3.js +186 -67
- package/commands/helpers/stacks/asg.yaml +420 -224
- package/commands/helpers/stacks/infra.yaml +102 -106
- package/commands/helpers/stacks.js +25 -25
- package/commands/index.html +22 -0
- package/commands/init_org.js +54 -61
- package/commands/inspect.js +40 -0
- package/commands/launch_app.js +80 -57
- package/commands/list_apps.js +21 -21
- package/commands/new_app.js +44 -50
- package/commands/new_instance.js +133 -186
- package/commands/reset_stack.js +27 -27
- package/commands/starter.js +21 -0
- package/commands/starters/asg_node/index.js +62 -0
- package/commands/starters/asg_node/mason.txt +1 -0
- package/commands/starters/asg_node/modules/appConfig.js +131 -0
- package/commands/starters/asg_node/package-lock.json +5877 -0
- package/commands/starters/asg_node/package.json +23 -0
- package/commands/starters/asg_node/public/css/favicon-16x16.png +0 -0
- package/commands/starters/asg_node/public/css/fonts/Lato-Bold.ttf +0 -0
- package/commands/starters/asg_node/public/css/fonts/Lato-Regular.ttf +0 -0
- package/commands/starters/asg_node/public/css/fonts/Montserrat-Var.ttf +0 -0
- package/commands/starters/asg_node/public/css/fonts/OpenSans.ttf +0 -0
- package/commands/starters/asg_node/public/css/fonts/bpmn.woff2 +0 -0
- package/commands/starters/asg_node/public/css/fonts/fonts.css +17 -0
- package/commands/starters/asg_node/public/css/index.css +9 -0
- package/commands/starters/asg_node/public/index.html +15 -0
- package/commands/starters/asg_node/public/js/index.js +5 -0
- package/commands/starters/asg_node/start.sh +4 -0
- package/commands/update_app.js +235 -272
- package/commands/update_stack.js +27 -0
- package/commands/utils.js +32 -32
- package/main.js +262 -220
- package/package.json +1 -28
- package/test.bat +16 -9
- package/commands/delete_app.js +0 -28
- package/commands/helpers/stacks/asg_draft.json +0 -321
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cloudmason_demo",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node index.js"
|
|
8
|
+
},
|
|
9
|
+
"author": "",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"2": "^3.0.0",
|
|
13
|
+
"@aws-sdk/client-dynamodb": "^3.478.0",
|
|
14
|
+
"@aws-sdk/client-s3": "^3.476.0",
|
|
15
|
+
"@aws-sdk/client-ssm": "^3.476.0",
|
|
16
|
+
"@aws-sdk/lib-dynamodb": "^3.478.0",
|
|
17
|
+
"aws-jwt-verify": "^4.0.0",
|
|
18
|
+
"express": "^4.18.2",
|
|
19
|
+
"jsonwebtoken": "^9.0.2",
|
|
20
|
+
"jws": "^4.0.0",
|
|
21
|
+
"node-fetch": "^2.7.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* Fonts */
|
|
2
|
+
@font-face {
|
|
3
|
+
font-family: 'bpmn';
|
|
4
|
+
font-weight: normal;
|
|
5
|
+
font-style: normal;
|
|
6
|
+
src: url('./bpmn.woff2') format('woff2');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: 'Montserrat';
|
|
11
|
+
src: url('./Montserrat-Var.ttf');
|
|
12
|
+
}
|
|
13
|
+
@font-face {
|
|
14
|
+
font-family: 'OpenSans';
|
|
15
|
+
src: url('./OpenSans.ttf');
|
|
16
|
+
font-weight: 1 1000;
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>CloudMason</title>
|
|
7
|
+
<link rel="icon" type="image/png" href="./css/favicon-16x16.png">
|
|
8
|
+
<link rel="stylesheet" build="fonts" href="./css/fonts/fonts.css">
|
|
9
|
+
<link rel="stylesheet" build="index.css" href="./css/index.css">
|
|
10
|
+
<script build="inline" src="./js/index.js"></script>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div class="hello-world">Hello World5</div>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
package/commands/update_app.js
CHANGED
|
@@ -1,272 +1,235 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (!
|
|
19
|
-
console.log('
|
|
20
|
-
throw new Error('
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
if (!
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
const
|
|
32
|
-
if (args.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
var success = false;
|
|
69
|
-
let ami_id;
|
|
70
|
-
try {
|
|
71
|
-
ami_id = await createAMI(instance_id, appVID,process.env.orgRegion)
|
|
72
|
-
success = true;
|
|
73
|
-
} catch(e){
|
|
74
|
-
console.log("Error Creating AMI:" + e)
|
|
75
|
-
}
|
|
76
|
-
await terminateInstance(instance_id,process.env.orgRegion)
|
|
77
|
-
if (success === false){ throw new Error("Error - Build Not Complete") }
|
|
78
|
-
|
|
79
|
-
// --- IV UPDATE PARAMS ---
|
|
80
|
-
const versionInfo = {
|
|
81
|
-
baseAMI_Name: appVID,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
async function createAMI(instance_id,image_name,region){
|
|
239
|
-
console.log(`Building ${image_name} in ${region}`)
|
|
240
|
-
const client = new EC2Client({region});
|
|
241
|
-
const input = { // CreateImageRequest
|
|
242
|
-
Description: `Base Application Image`,
|
|
243
|
-
DryRun: false,
|
|
244
|
-
InstanceId: instance_id, // required
|
|
245
|
-
Name: image_name, // required
|
|
246
|
-
NoReboot: true
|
|
247
|
-
};
|
|
248
|
-
const command = new CreateImageCommand(input);
|
|
249
|
-
const response = await client.send(command);
|
|
250
|
-
console.log(`Created Image ${image_name} ID:${response.ImageId}`)
|
|
251
|
-
return response.ImageId;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
async function terminateInstance(instance_id,region){
|
|
255
|
-
console.log('Terminating Instance ' + instance_id)
|
|
256
|
-
const client = new EC2Client({region});
|
|
257
|
-
const input = { // TerminateInstancesRequest
|
|
258
|
-
InstanceIds: [ instance_id ],
|
|
259
|
-
DryRun: false,
|
|
260
|
-
};
|
|
261
|
-
const command = new TerminateInstancesCommand(input);
|
|
262
|
-
const response = await client.send(command);
|
|
263
|
-
return true;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
async function sleep(time){
|
|
268
|
-
return new Promise(function (resolve, reject) {
|
|
269
|
-
setTimeout(function () { resolve(true);
|
|
270
|
-
}, time);
|
|
271
|
-
});
|
|
272
|
-
}
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const EC2 = require('./helpers/ec2');
|
|
4
|
+
const { EC2Client, RunInstancesCommand,CreateImageCommand,TerminateInstancesCommand,DescribeInstanceStatusCommand,DeregisterImageCommand,DescribeImagesCommand,CopyImageCommand } = require("@aws-sdk/client-ec2");
|
|
5
|
+
|
|
6
|
+
const AdmZip = require("adm-zip");
|
|
7
|
+
|
|
8
|
+
const Params = require('./helpers/params')
|
|
9
|
+
const S3 = require('./helpers/s3');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const INSTANCE_TYPE="t2.micro"
|
|
13
|
+
|
|
14
|
+
exports.main = async function(args){
|
|
15
|
+
console.log(`Updating ${args.app} v${args.v}`);
|
|
16
|
+
|
|
17
|
+
// Check Version Format
|
|
18
|
+
if (!args.v.match(/^[1-9][0-9]{0,4}\.[0-9]{0,4}$/)){
|
|
19
|
+
console.log('Invalid Version Format. Use format [major].[minor] without leading 0s')
|
|
20
|
+
throw new Error('Invalid Version Format');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Get App
|
|
24
|
+
const app = await Params.getApp(args.app);
|
|
25
|
+
if (!app){
|
|
26
|
+
console.log('Err: No app named ' + args.app);
|
|
27
|
+
throw new Error('Err: No app named ' + args.app)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// --- I PREP ZIP ---
|
|
31
|
+
const zipPath = path.resolve(args.path);
|
|
32
|
+
if (!fs.existsSync(zipPath)){ throw new Error("Path not found:" + args.path)}
|
|
33
|
+
const zipFilePath = await prepZip(zipPath);
|
|
34
|
+
await S3.uploadInfraFile(`apps/${args.app}/${args.v}/app.zip`,zipFilePath);
|
|
35
|
+
|
|
36
|
+
// --- II UPDATE STACK ---
|
|
37
|
+
// If stack arg, upload stack
|
|
38
|
+
const stackKey = `apps/${args.app}/${args.v}/stack.yaml`;
|
|
39
|
+
// If no stack arg, upload default stack if none exists
|
|
40
|
+
const stackExists = await S3.infraFileExists(stackKey)
|
|
41
|
+
if (!stackExists){
|
|
42
|
+
console.log('Copying default stack to ' + `apps/${args.app}/${args.v}`);
|
|
43
|
+
await S3.copyInfraFile(app.stackKey,stackKey)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// --- III BUILD IMAGE ---
|
|
47
|
+
// Launch ec2
|
|
48
|
+
const orgParams = await Params.getOrgConfig();
|
|
49
|
+
|
|
50
|
+
// const awsLinuxAMI = await findLinuxAMI(process.env.orgRegion);
|
|
51
|
+
const awsLinuxAMI = EC2.awsLinuxAMI(process.env.orgRegion);
|
|
52
|
+
const instance_id = await launchInstance({
|
|
53
|
+
app: app.name,
|
|
54
|
+
linuxAMI: awsLinuxAMI,
|
|
55
|
+
version: args.v,
|
|
56
|
+
sec_group: orgParams.buildSecGroup,
|
|
57
|
+
iam: orgParams.buildInstanceProfile,
|
|
58
|
+
node: app.nodeV,
|
|
59
|
+
py: app.pyV
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
await waitUntilInstanceReady(instance_id,process.env.orgRegion);
|
|
63
|
+
|
|
64
|
+
// Create AMI
|
|
65
|
+
const buildNumber = (app.versions[args.v]?.currentBuild || 0) + 1;
|
|
66
|
+
const appVID = `${app.name.toLowerCase()}-v${args.v}.${buildNumber}`;
|
|
67
|
+
|
|
68
|
+
var success = false;
|
|
69
|
+
let ami_id;
|
|
70
|
+
try {
|
|
71
|
+
ami_id = await createAMI(instance_id, appVID,process.env.orgRegion)
|
|
72
|
+
success = true;
|
|
73
|
+
} catch(e){
|
|
74
|
+
console.log("Error Creating AMI:" + e)
|
|
75
|
+
}
|
|
76
|
+
await terminateInstance(instance_id,process.env.orgRegion)
|
|
77
|
+
if (success === false){ throw new Error("Error - Build Not Complete") }
|
|
78
|
+
|
|
79
|
+
// --- IV UPDATE PARAMS ---
|
|
80
|
+
const versionInfo = {
|
|
81
|
+
baseAMI_Name: appVID,
|
|
82
|
+
stackPath: stackKey,
|
|
83
|
+
stackURL: `https://s3.${process.env.orgRegion}.amazonaws.com/${process.env.orgBucket}/apps/${args.app.toLowerCase()}/${args.v}/stack.yaml`,
|
|
84
|
+
baseAMI_Id: ami_id,
|
|
85
|
+
currentBuild: buildNumber,
|
|
86
|
+
updated: Date.now()
|
|
87
|
+
}
|
|
88
|
+
await Params.updateAppV(app.name,args.v,versionInfo);
|
|
89
|
+
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
///////////////////////////////////////////////
|
|
96
|
+
///////////////////////////////////////////////
|
|
97
|
+
///////////////////////////////////////////////
|
|
98
|
+
|
|
99
|
+
async function prepZip(appPath){
|
|
100
|
+
console.log('Zipping ' + appPath);
|
|
101
|
+
const inPath = path.resolve(appPath);
|
|
102
|
+
let zipPath = path.resolve(`./app.zip`);
|
|
103
|
+
|
|
104
|
+
const pathStat = fs.statSync(inPath);
|
|
105
|
+
// If dir, zip
|
|
106
|
+
if (!pathStat.isFile()){
|
|
107
|
+
const zip = new AdmZip();
|
|
108
|
+
zip.addLocalFolder(inPath);
|
|
109
|
+
zip.writeZip(zipPath);
|
|
110
|
+
} else {
|
|
111
|
+
// If not zip, throw error
|
|
112
|
+
if (path.extname(inPath) !== '.zip'){
|
|
113
|
+
console.log('ERROR:Not a .zip file >>' + inPath)
|
|
114
|
+
throw 'ERROR:Not a .zip file >>' + inPath;
|
|
115
|
+
}
|
|
116
|
+
// Copy .zip file
|
|
117
|
+
fs.copyFileSync(inPath,zipPath);
|
|
118
|
+
}
|
|
119
|
+
process.on('exit', function(){ fs.unlinkSync(zipPath) });
|
|
120
|
+
return zipPath;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function launchInstance(launchParams){
|
|
124
|
+
console.log('Launching Instance in ' + process.env.orgRegion);
|
|
125
|
+
const nodeRepo = launchParams.node === '' ? 'echo default_version' : `https://rpm.nodesource.com/setup_${launchParams.node}.x | sudo bash -`;
|
|
126
|
+
const user_data = [
|
|
127
|
+
`#!/bin/bash -xe`,
|
|
128
|
+
nodeRepo,
|
|
129
|
+
`yum -y install nodejs`,
|
|
130
|
+
`yum -y install python3`,
|
|
131
|
+
`yum -y install unzip`,
|
|
132
|
+
`cd /home/ec2-user`,
|
|
133
|
+
`aws s3 cp s3://${process.env.orgBucket}/apps/${launchParams.app.toLowerCase()}/${launchParams.version}/app.zip .`,
|
|
134
|
+
`unzip app.zip -d app`,
|
|
135
|
+
`rm -r app.zip`
|
|
136
|
+
].join('\n')
|
|
137
|
+
|
|
138
|
+
const ud_b64 = Buffer.from(user_data).toString('base64');
|
|
139
|
+
|
|
140
|
+
const client = new EC2Client({region: process.env.orgRegion });
|
|
141
|
+
|
|
142
|
+
const createInstanceParams = {
|
|
143
|
+
ImageId: launchParams.linuxAMI,
|
|
144
|
+
InstanceType: INSTANCE_TYPE,
|
|
145
|
+
SecurityGroupIds: [
|
|
146
|
+
launchParams.sec_group
|
|
147
|
+
],
|
|
148
|
+
MinCount: 1,
|
|
149
|
+
MaxCount: 1,
|
|
150
|
+
UserData: ud_b64,
|
|
151
|
+
IamInstanceProfile: {
|
|
152
|
+
Arn: launchParams.iam
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const command = new RunInstancesCommand(createInstanceParams);
|
|
156
|
+
const response = await client.send(command);
|
|
157
|
+
const instance_id = response.Instances[0].InstanceId
|
|
158
|
+
|
|
159
|
+
console.log('Instance Launched:',instance_id);
|
|
160
|
+
return instance_id;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function waitUntilInstanceReady(instance_id,region){
|
|
164
|
+
console.log(`Awaiting ${instance_id} status of ok`)
|
|
165
|
+
const client = new EC2Client({region});
|
|
166
|
+
const input = { // DescribeInstanceStatusRequest
|
|
167
|
+
InstanceIds: [ // InstanceIdStringList
|
|
168
|
+
instance_id
|
|
169
|
+
],
|
|
170
|
+
DryRun: false,
|
|
171
|
+
IncludeAllInstances: true
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
let totalSleepTime = 0;
|
|
175
|
+
let ok = false;
|
|
176
|
+
const command = new DescribeInstanceStatusCommand(input);
|
|
177
|
+
for (let i=0; i<50; i++){
|
|
178
|
+
const response = await client.send(command);
|
|
179
|
+
const status = response.InstanceStatuses[0].InstanceStatus.Status;
|
|
180
|
+
console.log(`\tCheck ${i+1} @ ${totalSleepTime}s: EC2 Status is ${status}`)
|
|
181
|
+
if (status !== 'ok'){
|
|
182
|
+
await sleep(10000);
|
|
183
|
+
totalSleepTime += 10;
|
|
184
|
+
} else {
|
|
185
|
+
console.log('Ec2 Instance Ready:' + status);
|
|
186
|
+
ok = true;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (ok === false){
|
|
192
|
+
console.log('ERR:::', `Ec2 Instance Not Ready After ${totalSleepTime}s`)
|
|
193
|
+
throw `Ec2 Instance Not Ready After ${totalSleepTime}s`
|
|
194
|
+
} else {
|
|
195
|
+
console.log(`Instance Ready After ${totalSleepTime}s. Waiting 30s to Proceed`);
|
|
196
|
+
await sleep(30);
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function createAMI(instance_id,image_name,region){
|
|
202
|
+
console.log(`Building ${image_name} in ${region}`)
|
|
203
|
+
const client = new EC2Client({region});
|
|
204
|
+
const input = { // CreateImageRequest
|
|
205
|
+
Description: `Base Application Image`,
|
|
206
|
+
DryRun: false,
|
|
207
|
+
InstanceId: instance_id, // required
|
|
208
|
+
Name: image_name, // required
|
|
209
|
+
NoReboot: true
|
|
210
|
+
};
|
|
211
|
+
const command = new CreateImageCommand(input);
|
|
212
|
+
const response = await client.send(command);
|
|
213
|
+
console.log(`Created Image ${image_name} ID:${response.ImageId}`)
|
|
214
|
+
return response.ImageId;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function terminateInstance(instance_id,region){
|
|
218
|
+
console.log('Terminating Instance ' + instance_id)
|
|
219
|
+
const client = new EC2Client({region});
|
|
220
|
+
const input = { // TerminateInstancesRequest
|
|
221
|
+
InstanceIds: [ instance_id ],
|
|
222
|
+
DryRun: false,
|
|
223
|
+
};
|
|
224
|
+
const command = new TerminateInstancesCommand(input);
|
|
225
|
+
const response = await client.send(command);
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
async function sleep(time){
|
|
231
|
+
return new Promise(function (resolve, reject) {
|
|
232
|
+
setTimeout(function () { resolve(true);
|
|
233
|
+
}, time);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const S3 = require('./helpers/s3');
|
|
2
|
+
const Params = require('./helpers/params');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
exports.main = async function(args){
|
|
7
|
+
// Get App
|
|
8
|
+
const app = await Params.getApp(args.app);
|
|
9
|
+
if (!app){
|
|
10
|
+
console.log('Err: No app named ' + args.app);
|
|
11
|
+
throw new Error('Err: No app named ' + args.app)
|
|
12
|
+
}
|
|
13
|
+
if (args.default === undefined && !app.versions[args.v]){
|
|
14
|
+
console.log('Err: No app version ' + args.app + ' ' + args.v);
|
|
15
|
+
throw new Error('Err: No app version ' + args.app + ' ' + args.v)
|
|
16
|
+
}
|
|
17
|
+
if (args.default === null && args.v){
|
|
18
|
+
console.log('Err: Cannot set default and specify version');
|
|
19
|
+
throw new Error('Err: Cannot set default version and specify version')
|
|
20
|
+
}
|
|
21
|
+
const stackPath = path.resolve(args.stack);
|
|
22
|
+
if (!fs.existsSync(stackPath)){ throw new Error("Stack file not found:" + args.stack)}
|
|
23
|
+
|
|
24
|
+
console.log(`Upating v${args.v || 'Default'} stack for ${args.app}`);
|
|
25
|
+
const stackKey = args.default === null ? `apps/${args.app}/default_stack.yaml` : `apps/${args.app}/${args.v}/stack.yaml`;
|
|
26
|
+
await S3.uploadInfraFile(stackKey,stackPath);
|
|
27
|
+
}
|