cloudmason 1.1.13 → 1.1.15
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/commands/helpers/params.js +115 -72
- package/commands/update_app.js +4 -1
- package/main.js +7 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { SSMClient, GetParameterCommand,PutParameterCommand,GetParametersByPathCommand,DeleteParameterCommand } = require("@aws-sdk/client-ssm");
|
|
2
|
+
const { S3Client, PutObjectCommand, GetObjectCommand } = require("@aws-sdk/client-s3");
|
|
2
3
|
|
|
3
4
|
// ORG PARAMS
|
|
4
5
|
exports.getOrgConfig = async function(){
|
|
@@ -38,38 +39,26 @@ exports.getOrgBucket = async function(){
|
|
|
38
39
|
exports.listApps = async function(){
|
|
39
40
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
40
41
|
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const parameters = [];
|
|
44
|
-
let nextToken;
|
|
45
|
-
|
|
46
|
-
do {
|
|
47
|
-
const response = await ssmClient.send(new GetParametersByPathCommand({
|
|
48
|
-
Path: pathPrefix,
|
|
49
|
-
NextToken: nextToken
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
if (response.Parameters) {
|
|
53
|
-
parameters.push(...response.Parameters);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
nextToken = response.NextToken;
|
|
57
|
-
|
|
58
|
-
} while (nextToken);
|
|
59
|
-
const params = parameters.map(p=>{ return JSON.parse(p.Value) })
|
|
42
|
+
const appList = await readOrgConfig();
|
|
43
|
+
const params = appList;
|
|
60
44
|
return params;
|
|
61
45
|
}
|
|
62
46
|
|
|
47
|
+
|
|
48
|
+
|
|
63
49
|
exports.getApp = async function(appName){
|
|
64
50
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)
|
|
69
|
-
return app ? JSON.parse(app) : null;
|
|
51
|
+
const orgApps = await readOrgConfig();
|
|
52
|
+
const app = orgApps.find(a=>{ return a.name.toLowerCase() == appName.toLowerCase() });
|
|
53
|
+
return app ? app : null;
|
|
70
54
|
}
|
|
71
55
|
|
|
72
56
|
exports.addApp = async function(appName,appType,stackKey,nodeV,pyV){
|
|
57
|
+
const orgApps = await readOrgConfig();
|
|
58
|
+
const existingApp = orgApps.find(a=>{ return a.name.toLowerCase() == appName.toLowerCase() });
|
|
59
|
+
if (existingApp){
|
|
60
|
+
throw new Error('App already exists' + appName)
|
|
61
|
+
}
|
|
73
62
|
const appData = {
|
|
74
63
|
name: appName,
|
|
75
64
|
stack: appType,
|
|
@@ -81,14 +70,15 @@ exports.addApp = async function(appName,appType,stackKey,nodeV,pyV){
|
|
|
81
70
|
},
|
|
82
71
|
instances: []
|
|
83
72
|
}
|
|
84
|
-
|
|
85
|
-
await
|
|
73
|
+
orgApps.push(appData);
|
|
74
|
+
await writeOrgConfig(orgApps);
|
|
86
75
|
}
|
|
87
76
|
|
|
88
77
|
exports.deleteApp = async function(appName){
|
|
89
78
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
90
|
-
const
|
|
91
|
-
|
|
79
|
+
const orgApps = await readOrgConfig();
|
|
80
|
+
orgApps = orgApps.filter(a=>{ return a.name.toLowerCase() !== appName.toLowerCase() });
|
|
81
|
+
await writeOrgConfig(orgApps);
|
|
92
82
|
return true
|
|
93
83
|
}
|
|
94
84
|
|
|
@@ -96,12 +86,11 @@ exports.deleteApp = async function(appName){
|
|
|
96
86
|
exports.updateAppV = async function(appName,version,vParams){
|
|
97
87
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
98
88
|
if (!vParams.baseAMI_Name || !vParams.baseAMI_Id || !vParams.updated){ throw new Error('Missing version param' + vParams)}
|
|
99
|
-
const appKey = `/infra/apps/${appName.toLowerCase()}`
|
|
100
|
-
const appStr = await readParam(appKey,process.env.orgRegion);
|
|
101
|
-
const app = JSON.parse(appStr);
|
|
102
89
|
|
|
103
|
-
|
|
104
|
-
|
|
90
|
+
const [apps,i] = await readOrgConfig(appName);
|
|
91
|
+
apps[i].versions[version] = vParams;
|
|
92
|
+
|
|
93
|
+
await writeOrgConfig(apps);
|
|
105
94
|
}
|
|
106
95
|
|
|
107
96
|
// INSTANCE PARAMS
|
|
@@ -118,35 +107,29 @@ exports.setOrgParams = async function(orgName,VpcId,repo){
|
|
|
118
107
|
|
|
119
108
|
exports.addPid = async function(appName,productId){
|
|
120
109
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
const app = JSON.parse(appStr);
|
|
110
|
+
const [apps,i] = await readOrgConfig(appName);
|
|
111
|
+
apps[i].pid = productId;
|
|
124
112
|
|
|
125
|
-
|
|
126
|
-
await writeParam(appKey,JSON.stringify(app),process.env.orgRegion);
|
|
113
|
+
await writeOrgConfig(apps);
|
|
127
114
|
}
|
|
128
115
|
|
|
129
116
|
|
|
130
117
|
exports.addInstance = async function(appName,instanceName,params){
|
|
131
118
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
132
|
-
const
|
|
133
|
-
const appStr = await readParam(appKey,process.env.orgRegion);
|
|
134
|
-
const app = JSON.parse(appStr);
|
|
119
|
+
const [apps,i] = await readOrgConfig(appName);
|
|
135
120
|
|
|
136
|
-
const ei =
|
|
121
|
+
const ei = apps[i].instances.find(ins=>{ return ins.domain.toLowerCase() == instanceName.toLowerCase()});
|
|
137
122
|
if (ei){
|
|
138
123
|
throw new Error('Instance exists')
|
|
139
124
|
}
|
|
140
|
-
|
|
141
|
-
await
|
|
125
|
+
apps[i].instances.push(params);
|
|
126
|
+
await writeOrgConfig(apps);
|
|
142
127
|
}
|
|
143
128
|
|
|
144
129
|
exports.updateInstanceV = async function(appName,instanceName,version,build,amiId,amiName){
|
|
145
130
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
const app = JSON.parse(appStr);
|
|
149
|
-
const ei = app.instances.find(ins=>{ return ins.domain.toLowerCase() == instanceName.toLowerCase()});
|
|
131
|
+
const [apps,i] = await readOrgConfig(appName);
|
|
132
|
+
const ei = apps[i].instances.find(ins=>{ return ins.domain.toLowerCase() == instanceName.toLowerCase()});
|
|
150
133
|
if (!ei){ throw new Error('Instance not found') }
|
|
151
134
|
|
|
152
135
|
ei.version = version;
|
|
@@ -155,37 +138,53 @@ exports.updateInstanceV = async function(appName,instanceName,version,build,amiI
|
|
|
155
138
|
ei.amiName = amiName;
|
|
156
139
|
ei.cfParams.AmiId = amiId;
|
|
157
140
|
|
|
158
|
-
await
|
|
141
|
+
await writeOrgConfig(apps);
|
|
159
142
|
}
|
|
160
143
|
|
|
161
|
-
// exports.editInstance = async function(appName,instanceName,version,stack,cfParams){
|
|
162
|
-
// if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
163
|
-
// const appKey = `/infra/apps/${appName.toLowerCase()}`
|
|
164
|
-
// const appStr = await readParam(appKey,process.env.orgRegion);
|
|
165
|
-
// const app = JSON.parse(appStr);
|
|
166
|
-
|
|
167
|
-
// const ei = app.instances.find(ins=>{ return ins.domain.toLowerCase() == instanceName.toLowerCase()});
|
|
168
|
-
// if (!ei){ throw new Error('Instance not found') }
|
|
169
|
-
// ei.version = version;
|
|
170
|
-
// ei.stack = stack;
|
|
171
|
-
// ei.cfParams = cfParams;
|
|
172
|
-
// ei.lastDeployed = Date.now();
|
|
173
|
-
// await writeParam(appKey,JSON.stringify(app),process.env.orgRegion)
|
|
174
|
-
// }
|
|
175
|
-
|
|
176
144
|
exports.deleteInstance = async function(appName,instanceName){
|
|
177
145
|
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const ei = app.instances.find(ins=>{ return ins.domain.toLowerCase() == instanceName.toLowerCase()});
|
|
183
|
-
if (!ei){ throw new Error('Instance not found') }
|
|
184
|
-
app.instances = app.instances.filter(ins=>{ return ins.domain.toLowerCase() !== instanceName.toLowerCase()});
|
|
185
|
-
await writeParam(appKey,JSON.stringify(app),process.env.orgRegion)
|
|
146
|
+
const [apps,i] = await readOrgConfig(appName);
|
|
147
|
+
apps[i].instances = apps[i].instances.filter(ins=>{ return ins.domain.toLowerCase() !== instanceName.toLowerCase()});
|
|
148
|
+
|
|
149
|
+
await writeOrgConfig(apps);
|
|
186
150
|
}
|
|
187
151
|
|
|
152
|
+
exports.migrate = async function(){
|
|
153
|
+
if (!process.env.orgRegion){ throw new Error('Region not set') }
|
|
154
|
+
console.log('Migrating params to s3');
|
|
155
|
+
const migrated = await readParam('/infra/migrated',process.env.orgRegion);
|
|
156
|
+
if (migrated){
|
|
157
|
+
console.log('Already migrated');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const ssmClient = new SSMClient({ region: process.env.orgRegion }); // Set your preferred region
|
|
161
|
+
const pathPrefix = "/infra/apps/";
|
|
162
|
+
const parameters = [];
|
|
163
|
+
let nextToken;
|
|
164
|
+
|
|
165
|
+
do {
|
|
166
|
+
const response = await ssmClient.send(new GetParametersByPathCommand({
|
|
167
|
+
Path: pathPrefix,
|
|
168
|
+
NextToken: nextToken
|
|
169
|
+
}));
|
|
170
|
+
if (response.Parameters) {
|
|
171
|
+
parameters.push(...response.Parameters);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
nextToken = response.NextToken;
|
|
188
175
|
|
|
176
|
+
} while (nextToken);
|
|
177
|
+
// const params = parameters.map(p=>{ return JSON.parse(p.Value) })
|
|
178
|
+
const newStruct = [];
|
|
179
|
+
for (let i=0; i<parameters.length; i++){
|
|
180
|
+
newStruct.push(JSON.parse(parameters[i].Value))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await writeOrgConfig(newStruct);
|
|
184
|
+
await writeParam('/infra/migrated',`${Date.now()}`, process.env.orgRegion);
|
|
185
|
+
console.log('Successfully migrated');
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
189
188
|
|
|
190
189
|
|
|
191
190
|
|
|
@@ -250,4 +249,48 @@ async function deleteParam(name,region){
|
|
|
250
249
|
throw error;
|
|
251
250
|
}
|
|
252
251
|
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function writeOrgConfig(data){
|
|
255
|
+
const s3Client = new S3Client({ region: process.env.orgRegion }); // Use your desired region
|
|
256
|
+
|
|
257
|
+
// Stringify the data
|
|
258
|
+
const jsonString = JSON.stringify(data);
|
|
259
|
+
const bucketName = await readParam('/infra/infraBucket',process.env.orgRegion);
|
|
260
|
+
// Set up the PutObject parameters
|
|
261
|
+
const putParams = {
|
|
262
|
+
Bucket: bucketName,
|
|
263
|
+
Key: "org_config.json",
|
|
264
|
+
Body: jsonString,
|
|
265
|
+
ContentType: "application/json",
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const result = await s3Client.send(new PutObjectCommand(putParams));
|
|
269
|
+
console.log("Successfully uploaded JSON to S3:", result);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async function readOrgConfig(appName=null){
|
|
273
|
+
const s3 = new S3Client({ region: process.env.orgRegion }); // Change region if needed
|
|
274
|
+
const bucketName = await readParam('/infra/infraBucket',process.env.orgRegion);
|
|
275
|
+
const { Body } = await s3.send(new GetObjectCommand({
|
|
276
|
+
Bucket: bucketName,
|
|
277
|
+
Key: "org_config.json"
|
|
278
|
+
}));
|
|
279
|
+
const dataString = await streamToString(Body);
|
|
280
|
+
const data = JSON.parse(dataString);
|
|
281
|
+
if (!appName){
|
|
282
|
+
return data;
|
|
283
|
+
} else {
|
|
284
|
+
const indx = data.findIndex(a=>{ return a.name.toLowerCase() == appName.toLowerCase() });
|
|
285
|
+
return [data,indx];
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function streamToString(stream) {
|
|
290
|
+
return new Promise((resolve, reject) => {
|
|
291
|
+
const chunks = [];
|
|
292
|
+
stream.on("data", (chunk) => chunks.push(chunk));
|
|
293
|
+
stream.on("error", reject);
|
|
294
|
+
stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
295
|
+
});
|
|
253
296
|
}
|
package/commands/update_app.js
CHANGED
|
@@ -66,7 +66,10 @@ exports.main = async function(args){
|
|
|
66
66
|
node: app.nodeV,
|
|
67
67
|
py: app.pyV
|
|
68
68
|
});
|
|
69
|
-
|
|
69
|
+
console.log('Instance Launched:',instance_id);
|
|
70
|
+
console.log('Waiting 60s');
|
|
71
|
+
await sleep(60*1000);
|
|
72
|
+
console.log('Checking Instance Status');
|
|
70
73
|
await waitUntilInstanceReady(instance_id,process.env.orgRegion);
|
|
71
74
|
|
|
72
75
|
// Create AMI
|
package/main.js
CHANGED
|
@@ -30,6 +30,13 @@ const Commands = {
|
|
|
30
30
|
{n: 'region', desc: 'AWS Region for Core Assets. Default us-east-1', r: false}
|
|
31
31
|
]
|
|
32
32
|
},
|
|
33
|
+
'migrate': {
|
|
34
|
+
desc: "Migrate to version 2",
|
|
35
|
+
exec: require('./commands/helpers/params').migrate,
|
|
36
|
+
args: [
|
|
37
|
+
{n: 't', desc: 'Architecture type: asg | static', r: false}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
33
40
|
'new-app': {
|
|
34
41
|
desc: 'Add a new application',
|
|
35
42
|
exec: require('./commands/new_app').main,
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"cloudmason","version":"1.1.
|
|
1
|
+
{"name":"cloudmason","version":"1.1.15","description":"","main":"main.js","scripts":{"build":"node build.js"},"bin":{"mason":"./main.js"},"repository":{"type":"git","url":"https://github.com/kai-harvey/secure-saas.git"},"author":"Kai Harvey","license":"ISC","dependencies":{"@aws-sdk/client-acm":"^3.418.0","@aws-sdk/client-auto-scaling":"^3.470.0","@aws-sdk/client-cloudformation":"^3.418.0","@aws-sdk/client-ec2":"^3.416.0","@aws-sdk/client-iam":"^3.418.0","@aws-sdk/client-marketplace-catalog":"^3.716.0","@aws-sdk/client-route-53":"^3.425.0","@aws-sdk/client-s3":"^3.418.0","@aws-sdk/client-ssm":"^3.421.0","adm-zip":"^0.5.10","yaml":"^2.6.1"}}
|