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.
@@ -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 ssmClient = new SSMClient({ region: process.env.orgRegion }); // Set your preferred region
42
- const pathPrefix = "/infra/apps/";
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 app = await readParam(
66
- `/infra/apps/${appName.toLowerCase()}`,
67
- process.env.orgRegion
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
- const paramPath = `/infra/apps/${appName.toLowerCase()}`;
85
- await writeParam(paramPath,JSON.stringify(appData),process.env.orgRegion);
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 paramPath = `/infra/apps/${appName.toLowerCase()}`;
91
- await deleteParam(paramPath,process.env.orgRegion);
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
- app.versions[version] = vParams;
104
- await writeParam(appKey,JSON.stringify(app),process.env.orgRegion);
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 appKey = `/infra/apps/${appName.toLowerCase()}`
122
- const appStr = await readParam(appKey,process.env.orgRegion);
123
- const app = JSON.parse(appStr);
110
+ const [apps,i] = await readOrgConfig(appName);
111
+ apps[i].pid = productId;
124
112
 
125
- app.pid = productId;
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 appKey = `/infra/apps/${appName.toLowerCase()}`
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 = app.instances.find(ins=>{ return ins.domain.toLowerCase() == instanceName.toLowerCase()});
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
- app.instances.push(params);
141
- await writeParam(appKey,JSON.stringify(app),process.env.orgRegion)
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 appKey = `/infra/apps/${appName.toLowerCase()}`
147
- const appStr = await readParam(appKey,process.env.orgRegion);
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 writeParam(appKey,JSON.stringify(app),process.env.orgRegion)
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 appKey = `/infra/apps/${appName.toLowerCase()}`
179
- const appStr = await readParam(appKey,process.env.orgRegion);
180
- const app = JSON.parse(appStr);
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
  }
@@ -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.13","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"}}
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"}}