@kumologica/sdk 3.2.0-beta1 → 3.2.0-beta11
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/cli/commands/deploy-commands/kumohub.js +4 -2
- package/cli/commands/deploy.js +3 -2
- package/cli/commands/export-commands/github-commands/aws.js +374 -0
- package/cli/commands/export-commands/github.js +6 -0
- package/package.json +18 -8
- package/src/app/lib/aws/ca-sqs-api.js +5 -1
- package/src/app/lib/aws/index.js +135 -175
- package/src/app/lib/github/index.js +242 -0
- package/src/app/preload.js +11 -1
- package/src/app/ui/editor-client/public/red/red.js +295 -216
- package/src/app/ui/editor-client/public/red/red.min.js +1 -1
- package/src/app/ui/editor-client/public/vendor/jsonata/jsonata.min.js +8 -1
- package/src/app/ui/editor-client/src/js/ui/editors/expression.js +169 -141
- package/src/app/ui/editor-client/src/js/ui/tab-awsDeploy.js +126 -75
- package/src/app/ui/editor-client/src/vendor/jsonata/formatter.js +8 -1
package/src/app/lib/aws/index.js
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const AWS = require('aws-sdk');
|
|
4
|
-
const AdmZip = require('adm-zip');
|
|
5
|
-
const util = require('util');
|
|
6
|
-
const exec = util.promisify(require('child_process').exec);
|
|
7
|
-
const rimraf = require('rimraf');
|
|
8
|
-
const { codegen } = require('@kumologica/builder');
|
|
9
4
|
const AWSCFTemplate = require('./cf');
|
|
10
5
|
const CAAWSCloudWatch = require('./ca-cloudwatch-api');
|
|
11
|
-
const CAAWSIot = require('./ca-iot-api');
|
|
12
6
|
const CAS3 = require('./ca-s3-api');
|
|
13
7
|
const CASNS = require('./ca-sns-api');
|
|
14
8
|
const CASQS = require('./ca-sqs-api');
|
|
15
9
|
const CAAWSApiGateway = require('./ca-apigw-api');
|
|
16
10
|
const CADynamoDb = require('./ca-dynamodb-api');
|
|
17
|
-
const CAElb = require('./ca-elb-api');
|
|
18
11
|
const CAEvents = require('./ca-events-api');
|
|
19
|
-
const CAAlexa = require('./ca-alexa-api');
|
|
20
|
-
const CACodeCommit = require('./ca-codecommit-api');
|
|
21
12
|
const AWSProfile = require('./aws-profile');
|
|
22
|
-
const KLIAM = require('./kl-iam-api');
|
|
23
13
|
const { openFileOnEditor } = require('../utils/editor');
|
|
14
|
+
const { exp } = require('@kumologica/builder');
|
|
15
|
+
const { build } = require('@kumologica/builder');
|
|
24
16
|
|
|
25
17
|
/**
|
|
26
18
|
* sample events:
|
|
@@ -45,7 +37,6 @@ class AWSDeployer {
|
|
|
45
37
|
|
|
46
38
|
this.cw = false;
|
|
47
39
|
|
|
48
|
-
this.iot = new CAAWSIot(this.log.bind(this));
|
|
49
40
|
this.apiGateway = new CAAWSApiGateway(this.log.bind(this));
|
|
50
41
|
this.dynamoDb = new CADynamoDb(this.log.bind(this));
|
|
51
42
|
this.cf = new AWS.CloudFormation();
|
|
@@ -57,11 +48,7 @@ class AWSDeployer {
|
|
|
57
48
|
this.cwLogs = new CAAWSCloudWatch(this.logCloud.bind(this));
|
|
58
49
|
this.cwevents = new AWS.CloudWatchEvents();
|
|
59
50
|
this.cognito = new AWS.CognitoIdentityServiceProvider();
|
|
60
|
-
this.elb = new CAElb(this.log.bind(this));
|
|
61
51
|
this.events = new CAEvents(this.log.bind(this));
|
|
62
|
-
this.alexa = new CAAlexa(this.log.bind(this));
|
|
63
|
-
this.codecommit = new CACodeCommit(this.log.bind(this));
|
|
64
|
-
this.iam = new KLIAM(this.log.bind(this));
|
|
65
52
|
}
|
|
66
53
|
|
|
67
54
|
chalk(c, t) {
|
|
@@ -107,23 +94,9 @@ class AWSDeployer {
|
|
|
107
94
|
}
|
|
108
95
|
|
|
109
96
|
prepare(projectDir, flowFileName, originaLambdaName) {
|
|
110
|
-
const deployDir = projectDir + '/deploy';
|
|
111
97
|
|
|
98
|
+
const deployDir = path.join(projectDir, "build");
|
|
112
99
|
const flowName = flowFileName.replace('.json', '');
|
|
113
|
-
|
|
114
|
-
// setup deployment directory
|
|
115
|
-
fs.ensureDirSync(deployDir);
|
|
116
|
-
fs.emptyDirSync(deployDir);
|
|
117
|
-
fs.ensureDirSync(deployDir + '/node_modules');
|
|
118
|
-
|
|
119
|
-
// copy project files
|
|
120
|
-
codegen.generateProjectCode(
|
|
121
|
-
deployDir,
|
|
122
|
-
flowFileName
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
this.processPackageJson(projectDir, deployDir);
|
|
126
|
-
|
|
127
100
|
const zipFileName = `${flowName}/lambda${Date.now()}.zip`;
|
|
128
101
|
const lambdaName = this.sanitizeLambdaName(originaLambdaName);
|
|
129
102
|
|
|
@@ -141,34 +114,6 @@ class AWSDeployer {
|
|
|
141
114
|
};
|
|
142
115
|
}
|
|
143
116
|
|
|
144
|
-
processPackageJson(projectDir, deployDir) {
|
|
145
|
-
|
|
146
|
-
const pckg = this.loadJsonFile(path.join(projectDir, 'package.json'));
|
|
147
|
-
|
|
148
|
-
// ensure dependencies contain runtime
|
|
149
|
-
if (!pckg.dependencies["@kumologica/runtime"]) {
|
|
150
|
-
pckg.dependencies["@kumologica/runtime"] = `^${pckg.version.substr(0, 1)}`;
|
|
151
|
-
this.createFile(deployDir, 'package.json', JSON.stringify(pckg));
|
|
152
|
-
|
|
153
|
-
} else {
|
|
154
|
-
fs.copySync(
|
|
155
|
-
path.join(projectDir, 'package.json'),
|
|
156
|
-
path.join(deployDir, 'package.json')
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (pckg.files) {
|
|
161
|
-
pckg.files.forEach(f => {
|
|
162
|
-
|
|
163
|
-
if (!["node_modules/**/*", "lambda.js" ].includes(f)) {
|
|
164
|
-
fs.copySync(
|
|
165
|
-
path.join(projectDir, f),
|
|
166
|
-
path.join(deployDir, f)
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
117
|
|
|
173
118
|
/**
|
|
174
119
|
*
|
|
@@ -234,7 +179,8 @@ class AWSDeployer {
|
|
|
234
179
|
settings.deploymentBucketName = await this.prepareS3Bucket(
|
|
235
180
|
settings.flowName
|
|
236
181
|
);
|
|
237
|
-
|
|
182
|
+
|
|
183
|
+
const zipFileName = await this.buildLambda(settings, projectInfo);
|
|
238
184
|
|
|
239
185
|
const nodes = this.loadJsonFile(
|
|
240
186
|
path.join(projectInfo.projectDir, projectInfo.projectFlowName)
|
|
@@ -246,7 +192,8 @@ class AWSDeployer {
|
|
|
246
192
|
settings,
|
|
247
193
|
params,
|
|
248
194
|
deploymentStart,
|
|
249
|
-
nodes
|
|
195
|
+
nodes,
|
|
196
|
+
projectInfo
|
|
250
197
|
);
|
|
251
198
|
lambdaArn = stackDetails.Stacks[0].Outputs[0].OutputValue;
|
|
252
199
|
|
|
@@ -421,6 +368,103 @@ class AWSDeployer {
|
|
|
421
368
|
};
|
|
422
369
|
}
|
|
423
370
|
|
|
371
|
+
mapParams(params) {
|
|
372
|
+
let vpcConf;
|
|
373
|
+
if (params.vpcConfig && params.vpcConfig.sn && params.vpcConfig.sn.length > 0
|
|
374
|
+
&& params.vpcConfig.sg && params.vpcConfig.sg.length > 0) {
|
|
375
|
+
let sn = params.vpcConfig.sn.split(",").map(s => s.trim());
|
|
376
|
+
let sg = params.vpcConfig.sg.split(",").map(s => s.trim());
|
|
377
|
+
|
|
378
|
+
vpcConf = JSON.stringify({
|
|
379
|
+
SubnetIds: sn,
|
|
380
|
+
SecurityGroupIds: sg
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
let tags;
|
|
385
|
+
if ( params.tags && params.tags.length > 0) {
|
|
386
|
+
tags = {};
|
|
387
|
+
params.tags.forEach(t => tags[t.key] = t.value)
|
|
388
|
+
tags = JSON.stringify(tags);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
let env;
|
|
392
|
+
if ( params.environment && params.environment.length > 0) {
|
|
393
|
+
env = {
|
|
394
|
+
Variables: {}
|
|
395
|
+
};
|
|
396
|
+
params.environment.forEach(e => env.Variables[e.key] = e.value)
|
|
397
|
+
env = JSON.stringify(env);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
let tracing;
|
|
401
|
+
if (params.xRay) {
|
|
402
|
+
tracing = '{"Mode":"Active"}';
|
|
403
|
+
}
|
|
404
|
+
// KL_TRIGGERS: '[{"api": {"apiId": "CHANGE_IT_TO_API_GATEWAY_ID", "parentId": "CHANGE_IT_TO_PARENT_ID", "stage": "test", "resource": "accounts"}}, {"event": {"expression": "cron(0 1 * * ? *)", "reference": "1am", "name": "CliBuildDemoEvent1am"}}, {"event": {"expression": "rate(1 minute)", "reference": "5min", "name": "CliBuildDemoEvent5min"}}]'
|
|
405
|
+
|
|
406
|
+
// "events":[{"source":"api","api":"qyhtzl0n39","stage":"test","parentId":"xfdg32","resource":"sample","authorizerId":"fdr3"}]
|
|
407
|
+
// "events":[{"source":"api","api":"qyhtzl0n39","stage":"test","parentId":"xfdg32","resource":"sample","authorizerId":"fdr3"},
|
|
408
|
+
//{"source":"dynamodb","stream":"arn:aws:dynamodb:ap-southeast-2:174842903734:table/contact_us/stream/2021-04-25T15:02:15.028","batchSize":"23","batchWindow":"3","startingPosition":"LATEST"},
|
|
409
|
+
//{"source":"sqs","stream":"https://sqs.ap-southeast-2.amazonaws.com/174842903734/devq2","batchSize":"32"},
|
|
410
|
+
//{"source":"kinesis","stream":"arn:aws:dynamodb:ap-southeast-2:174842903734:table/contact_us/stream/2021-04-25T15:02:15.028","batchSize":"34","batchWindow":"33","startingPosition":"LATEST"},
|
|
411
|
+
// {"source":"cwevents","rule":"arn:aws:events:ap-southeast-2:174842903734:rule/Test"},
|
|
412
|
+
//{"source":"sns","topic":"arn:aws:sns:ap-southeast-2:174842903734:t1"},
|
|
413
|
+
//{"source":"s3","bucket":"kumoexcelstore","eventType":"s3:ObjectCreated:*","prefix":"cc","suffix":"fd"}],"vpcConfig":{"sg":"","sn":""}}
|
|
414
|
+
///Users/wojtek/Development/kumologica/sdk/kumologica/packages/sdk/src/app/lib/github/index.js:114
|
|
415
|
+
let triggers;
|
|
416
|
+
if (params.events) {
|
|
417
|
+
triggers = [];
|
|
418
|
+
params.events.forEach(e => {
|
|
419
|
+
switch(e.source) {
|
|
420
|
+
case "api": triggers.push({"api": {"apiId": e.api, "stage": e.stage, "parentId": e.parentId, "resource": e.resource, "authorizerId": e.authorizerId}});
|
|
421
|
+
break;
|
|
422
|
+
case "sns": triggers.push({"sns": {"topicArn": e.topic}});
|
|
423
|
+
break;
|
|
424
|
+
case "sqs": triggers.push({"sqs": {"queueArn": e.queueArn, "batchSize": e.batchSize}});
|
|
425
|
+
break;
|
|
426
|
+
case "dynamodb": triggers.push({"dynamodb": {"streamArn": e.stream, "startingPosition": e.startingPosition, "batchSize": e.batchSize, "batchWindow": e.batchWindow}});
|
|
427
|
+
break;
|
|
428
|
+
case "kinesis": triggers.push({"kinesis": {"streamArn": e.stream, "startingPosition": e.startingPosition, "batchSize": e.batchSize, "batchWindow": e.batchWindow}});
|
|
429
|
+
break;
|
|
430
|
+
case "s3": triggers.push({"s3": {"bucket": e.bucket, "eventType": e.eventType, "prefix": e.prefix, "suffix": e.suffix}});
|
|
431
|
+
break;
|
|
432
|
+
case "cwevents": triggers.push({"event": {"expression": e.expression, "reference": e.reference, "name": e.name}});
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
})
|
|
436
|
+
triggers = JSON.stringify(triggers);
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
let args = {
|
|
440
|
+
"zip-file-name": params.zipFileName,
|
|
441
|
+
"bucket-name": params.bucketName,
|
|
442
|
+
"lambda-name": params.functionName,
|
|
443
|
+
"memory-size": params.memory,
|
|
444
|
+
"description": params.description,
|
|
445
|
+
"environment": env,
|
|
446
|
+
"tags": tags,
|
|
447
|
+
"timeout": params.timeout,
|
|
448
|
+
"triggers": triggers,
|
|
449
|
+
"vpc-config": vpcConf,
|
|
450
|
+
"role-arn": params.role,
|
|
451
|
+
"tracing-config": tracing,
|
|
452
|
+
"reserved-concurrency": params.reservedConcurrency
|
|
453
|
+
// not present
|
|
454
|
+
// "role-name": params.roleName,
|
|
455
|
+
// "layers": params.layers,
|
|
456
|
+
// "policy": params.policy,
|
|
457
|
+
// "strict-mode": params.strictMode,
|
|
458
|
+
// "log-retention-days": params.logRetentionDays,
|
|
459
|
+
// "file-system-configs": params.fileSystemConfigs,
|
|
460
|
+
// "dead-letter-config": params.deadLetterConfig,
|
|
461
|
+
// "runtime": params.runtime,
|
|
462
|
+
// "architectures": params.architectures,
|
|
463
|
+
// "kms-key-arn": params.kmsKeyArn,
|
|
464
|
+
}
|
|
465
|
+
return args;
|
|
466
|
+
}
|
|
467
|
+
|
|
424
468
|
async generateScript(projectInfo, params, profile) {
|
|
425
469
|
if (!profile) {
|
|
426
470
|
throw new Error(
|
|
@@ -446,28 +490,16 @@ class AWSDeployer {
|
|
|
446
490
|
settings.flowName
|
|
447
491
|
);
|
|
448
492
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
),
|
|
456
|
-
null,
|
|
457
|
-
2
|
|
458
|
-
);
|
|
493
|
+
// NEW
|
|
494
|
+
const args = this.mapParams(params);
|
|
495
|
+
args.region = AWS.config.region;
|
|
496
|
+
args["bucket-name"] = settings.deploymentBucketName;
|
|
497
|
+
args["project-directory"] = projectInfo.projectDir;
|
|
498
|
+
args["flow-file-name"] = projectInfo.projectFlowName;
|
|
459
499
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
`cf-${projectInfo.projectFlowName}`,
|
|
463
|
-
lambdaCfTemplate
|
|
464
|
-
);
|
|
500
|
+
const scriptFileName = exp("cloudformation", "aws", args);
|
|
501
|
+
this.log(`Cloudformation script has been created: ${scriptFileName}`);
|
|
465
502
|
|
|
466
|
-
const scriptFileName = path.join(
|
|
467
|
-
settings.deployDir,
|
|
468
|
-
`cf-${projectInfo.projectFlowName}`
|
|
469
|
-
);
|
|
470
|
-
this.log(`Cloud formation script created: ${scriptFileName}`);
|
|
471
503
|
openFileOnEditor(scriptFileName);
|
|
472
504
|
} catch (Error) {
|
|
473
505
|
this.log(`${this.chalk('redBright', 'Script creation failed.')}`);
|
|
@@ -476,49 +508,17 @@ class AWSDeployer {
|
|
|
476
508
|
}
|
|
477
509
|
}
|
|
478
510
|
|
|
479
|
-
|
|
480
511
|
/*
|
|
481
512
|
* Builds lambda and zips all sources.
|
|
482
|
-
*/
|
|
483
|
-
async buildLambda(settings) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const lines = response.stdout.split('\n');
|
|
492
|
-
for (var i = 0; i < lines.length; i++) {
|
|
493
|
-
if (lines[i]) {
|
|
494
|
-
this.log(lines[i], false);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
this.log('', false);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
this.log('Excluding optional dependencies...');
|
|
501
|
-
|
|
502
|
-
// for npm 8 on windows is creating symlink that causes recursions and zip to fail
|
|
503
|
-
const splitdir = path.dirname(settings.deployDir).split(path.sep);
|
|
504
|
-
const linkname = splitdir[splitdir.length-1];
|
|
505
|
-
try {
|
|
506
|
-
fs.unlinkSync(path.join(settings.deployDir, 'node_modules', linkname));
|
|
507
|
-
} catch (e) {
|
|
508
|
-
// ignore ENOENT
|
|
509
|
-
if (e.code !== "ENOENT") {
|
|
510
|
-
throw e;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// Remove aws-sdk library as it is provided by aws nodejs runtime.
|
|
515
|
-
// Reducing the resulting lambda zip file by more than 70%
|
|
516
|
-
rimraf.sync(path.join(settings.deployDir, 'node_modules', 'aws-sdk'));
|
|
517
|
-
|
|
518
|
-
this.log('Zipping lambda...');
|
|
519
|
-
const zip = new AdmZip();
|
|
520
|
-
zip.addLocalFolder(settings.deployDir);
|
|
521
|
-
zip.writeZip(path.join(settings.deployDir, settings.zipFileName));
|
|
513
|
+
*/
|
|
514
|
+
async buildLambda(settings, projectInfo) {
|
|
515
|
+
let args = {};
|
|
516
|
+
args["project-directory"] = projectInfo.projectDir;
|
|
517
|
+
args["flow-file-name"] = projectInfo.projectFlowName;
|
|
518
|
+
args["zip-file-name"] = settings.zipFileName;
|
|
519
|
+
|
|
520
|
+
const buildFileName = await build("aws", args);
|
|
521
|
+
return buildFileName;
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
/*
|
|
@@ -526,7 +526,7 @@ class AWSDeployer {
|
|
|
526
526
|
* and executes create or update stack.
|
|
527
527
|
* Returns stack id
|
|
528
528
|
*/
|
|
529
|
-
async executeStack(settings, params, deploymentStartTimestamp, nodes) {
|
|
529
|
+
async executeStack(settings, params, deploymentStartTimestamp, nodes, projectInfo) {
|
|
530
530
|
this.log(`Uploading zip file to bucket...`);
|
|
531
531
|
var body = fs.createReadStream(
|
|
532
532
|
path.join(settings.deployDir, settings.zipFileName)
|
|
@@ -535,19 +535,21 @@ class AWSDeployer {
|
|
|
535
535
|
await this.s3.upload({
|
|
536
536
|
Bucket: settings.deploymentBucketName,
|
|
537
537
|
Key: settings.zipFileName,
|
|
538
|
-
Body: body
|
|
538
|
+
Body: body
|
|
539
539
|
});
|
|
540
540
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
);
|
|
550
|
-
|
|
541
|
+
const args = this.mapParams(params);
|
|
542
|
+
args.region = AWS.config.region;
|
|
543
|
+
args["bucket-name"] = settings.deploymentBucketName;
|
|
544
|
+
args["project-directory"] = projectInfo.projectDir;
|
|
545
|
+
args["flow-file-name"] = projectInfo.projectFlowName;
|
|
546
|
+
args["zip-file-name"] = settings.zipFileName;
|
|
547
|
+
args.skipPrepare = "true"; // no need for cloudformation prepare
|
|
548
|
+
|
|
549
|
+
const scriptFileName = exp("cloudformation", "aws", args);
|
|
550
|
+
|
|
551
|
+
const lambdaCfTemplate = this.loadJsonFile(scriptFileName);
|
|
552
|
+
|
|
551
553
|
const stackParams = {
|
|
552
554
|
StackName: settings.stackName,
|
|
553
555
|
Capabilities: ['CAPABILITY_NAMED_IAM'],
|
|
@@ -593,48 +595,6 @@ class AWSDeployer {
|
|
|
593
595
|
return this.describeStack(stackParams.StackName);
|
|
594
596
|
}
|
|
595
597
|
|
|
596
|
-
/**
|
|
597
|
-
* Function links additional details for parameters that are not needed
|
|
598
|
-
* in ui but are required by cloud formation
|
|
599
|
-
*
|
|
600
|
-
* @param {*} params
|
|
601
|
-
*/
|
|
602
|
-
async prepareParams(params) {
|
|
603
|
-
for (var i = 0; i < params.events.length; i++) {
|
|
604
|
-
if (params.events[i].source === 'sqs') {
|
|
605
|
-
if (!params.events[i].stream) {
|
|
606
|
-
throw Error(`Missing Trigger Parameter: SQS Queue Url.`);
|
|
607
|
-
}
|
|
608
|
-
params.events[i].url = params.events[i].stream;
|
|
609
|
-
params.events[i].stream = await this.sqs.getQueueArn(
|
|
610
|
-
params.events[i].stream
|
|
611
|
-
);
|
|
612
|
-
} else if (params.events[i].source === 'codecommit') {
|
|
613
|
-
if (!params.events[i].repository) {
|
|
614
|
-
throw Error(`Missing Trigger Parameter: CodeCommit Repository.`);
|
|
615
|
-
}
|
|
616
|
-
const repository = await this.codecommit.getRepository(
|
|
617
|
-
params.events[i].repository
|
|
618
|
-
);
|
|
619
|
-
params.events[i].repositoryArn = repository.Arn;
|
|
620
|
-
params.events[i].account = repository.accountId;
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
return params;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
async prepareNodes(nodes) {
|
|
627
|
-
for (var i = 0; i < nodes.length; i++) {
|
|
628
|
-
if (nodes[i].type === 'SQS') {
|
|
629
|
-
if (!nodes[i].QueueUrl) {
|
|
630
|
-
throw Error(`Missing Node Parameter: SQS Queue Url.`);
|
|
631
|
-
}
|
|
632
|
-
nodes[i].QueueArn = await this.sqs.getQueueArn(nodes[i].QueueUrl);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
return nodes;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
598
|
async runTriggers(params, settings, lambdaArn) {
|
|
639
599
|
let response = {};
|
|
640
600
|
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const AWS = require('aws-sdk');
|
|
4
|
+
const { exp } = require('@kumologica/builder');
|
|
5
|
+
const AWSProfile = require('../aws/aws-profile');
|
|
6
|
+
const { openFileOnEditor } = require('../utils/editor');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* sample events:
|
|
10
|
+
* https://docs.aws.amazon.com/lambda/latest/dg/lambda-services.html
|
|
11
|
+
*/
|
|
12
|
+
class GithubDeployer {
|
|
13
|
+
constructor(terminal) {
|
|
14
|
+
this.term = terminal;
|
|
15
|
+
this.awsProfile = new AWSProfile();
|
|
16
|
+
|
|
17
|
+
AWS.config.apiVersions = {
|
|
18
|
+
cloudformation: '2010-05-15',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async initAWS(profile) {
|
|
23
|
+
AWS.config.credentials = new AWS.SharedIniFileCredentials({profile: profile});
|
|
24
|
+
|
|
25
|
+
const r = await this.awsProfile.getRegion(profile);
|
|
26
|
+
let s3 = new AWS.S3();
|
|
27
|
+
let bucketName = "CHANGE_IT_TO_REAL_BUCKET_NAME";
|
|
28
|
+
|
|
29
|
+
// find bucket
|
|
30
|
+
const buckets = await s3.listBuckets({}).promise();
|
|
31
|
+
|
|
32
|
+
if (buckets && buckets.Buckets) {
|
|
33
|
+
const bucket = buckets.Buckets.find(b => b.Name.startsWith('kumologica-designer-deploy'));
|
|
34
|
+
if (bucket) {
|
|
35
|
+
bucketName = bucket.Name;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {region: r, bucket: bucketName};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
chalk(c, t) {
|
|
43
|
+
if (c == 'whiteBright') {
|
|
44
|
+
c = '#FFFFFF';
|
|
45
|
+
} else if (c == 'redBright') {
|
|
46
|
+
c = '#FF0000';
|
|
47
|
+
} else if (c == 'yellowBright') {
|
|
48
|
+
c = '#FFFF00';
|
|
49
|
+
} else if (c == 'greenBright') {
|
|
50
|
+
c = '#00FF00';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return `<span style="color: ${c}">${t}</span>`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
log(text, calog = true) {
|
|
57
|
+
var t = text;
|
|
58
|
+
|
|
59
|
+
if (calog && this.chalk) {
|
|
60
|
+
t = `Kumologica: ${this.chalk('#F5DEB3', text)}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (this.term) {
|
|
64
|
+
this.term.emit('terminal-output', t);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
logCloud(text) {
|
|
69
|
+
if (this.term) {
|
|
70
|
+
this.term.emit('terminal-cloud', `${text}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
prepare(projectDir, flowFileName, originaLambdaName) {
|
|
75
|
+
const deployDir = projectDir + '/deploy';
|
|
76
|
+
|
|
77
|
+
const flowName = flowFileName.replace('.json', '');
|
|
78
|
+
|
|
79
|
+
// setup deployment directory
|
|
80
|
+
fs.ensureDirSync(deployDir);
|
|
81
|
+
fs.emptyDirSync(deployDir);
|
|
82
|
+
fs.ensureDirSync(deployDir + '/node_modules');
|
|
83
|
+
|
|
84
|
+
this.processPackageJson(projectDir, deployDir);
|
|
85
|
+
|
|
86
|
+
const zipFileName = `${flowName}/lambda${Date.now()}.zip`;
|
|
87
|
+
const lambdaName = this.sanitizeLambdaName(originaLambdaName);
|
|
88
|
+
|
|
89
|
+
const functionName = `kumologica-${lambdaName}-lambda`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async generateScript(projectInfo, params, profile) {
|
|
93
|
+
|
|
94
|
+
/*
|
|
95
|
+
|
|
96
|
+
projectInfo: {"projectName":"sockets",
|
|
97
|
+
"projectDir":"/Users/wojtek/Development/projects/sockets",
|
|
98
|
+
"projectFlowName":"sockets-flow.json"}
|
|
99
|
+
profile: kl
|
|
100
|
+
*/
|
|
101
|
+
try {
|
|
102
|
+
this.log('Generating github action workflow');
|
|
103
|
+
|
|
104
|
+
//console.log(`projectInfo: ${JSON.stringify(projectInfo)}`);
|
|
105
|
+
//console.log(`profile: ${profile}`);
|
|
106
|
+
|
|
107
|
+
const awsSettings = await this.initAWS(profile);
|
|
108
|
+
|
|
109
|
+
const args = this.mapParams(params);
|
|
110
|
+
args.region = awsSettings.region;
|
|
111
|
+
args["bucket-name"] = awsSettings.bucket;
|
|
112
|
+
|
|
113
|
+
let wf = exp("github", "aws", args, console.log);
|
|
114
|
+
|
|
115
|
+
const wfDir = path.join(projectInfo.projectDir, '.github', 'workspaces');
|
|
116
|
+
|
|
117
|
+
this.createFile (
|
|
118
|
+
wfDir, 'workflow.yaml',
|
|
119
|
+
wf
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
this.log(`Github action workflow created: ${path.join(wfDir, 'workflow.yaml')}`);
|
|
123
|
+
|
|
124
|
+
openFileOnEditor(path.join(wfDir, 'workflow.yaml'));
|
|
125
|
+
|
|
126
|
+
return;
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
this.log(` ${this.chalk('#F5DEB3', 'AWS region:')} ${this.chalk('whiteBright', AWS.config.region)}`, false);
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
} catch (Error) {
|
|
133
|
+
this.log(`${this.chalk('redBright', 'Github action workflow creation failed.')}`);
|
|
134
|
+
this.log(` ${this.chalk('redBright', Error)}`);
|
|
135
|
+
throw Error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
mapParams(params) {
|
|
140
|
+
let vpcConf;
|
|
141
|
+
if (params.vpcConfig && params.vpcConfig.sn && params.vpcConfig.sn.length > 0
|
|
142
|
+
&& params.vpcConfig.sg && params.vpcConfig.sg.length > 0) {
|
|
143
|
+
let sn = params.vpcConfig.sn.split(",").map(s => s.trim());
|
|
144
|
+
let sg = params.vpcConfig.sg.split(",").map(s => s.trim());
|
|
145
|
+
|
|
146
|
+
vpcConf = JSON.stringify({
|
|
147
|
+
SubnetIds: sn,
|
|
148
|
+
SecurityGroupIds: sg
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let tags;
|
|
153
|
+
if ( params.tags && params.tags.length > 0) {
|
|
154
|
+
tags = {};
|
|
155
|
+
params.tags.forEach(t => tags[t.key] = t.value)
|
|
156
|
+
tags = JSON.stringify(tags);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let env;
|
|
160
|
+
if ( params.environment && params.environment.length > 0) {
|
|
161
|
+
env = {
|
|
162
|
+
Variables: {}
|
|
163
|
+
};
|
|
164
|
+
params.environment.forEach(e => env.Variables[e.key] = e.value)
|
|
165
|
+
env = JSON.stringify(env);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let tracing;
|
|
169
|
+
if (params.xRay) {
|
|
170
|
+
tracing = '{"Mode":"Active"}';
|
|
171
|
+
}
|
|
172
|
+
// KL_TRIGGERS: '[{"api": {"apiId": "CHANGE_IT_TO_API_GATEWAY_ID", "parentId": "CHANGE_IT_TO_PARENT_ID", "stage": "test", "resource": "accounts"}}, {"event": {"expression": "cron(0 1 * * ? *)", "reference": "1am", "name": "CliBuildDemoEvent1am"}}, {"event": {"expression": "rate(1 minute)", "reference": "5min", "name": "CliBuildDemoEvent5min"}}]'
|
|
173
|
+
|
|
174
|
+
// "events":[{"source":"api","api":"qyhtzl0n39","stage":"test","parentId":"xfdg32","resource":"sample","authorizerId":"fdr3"}]
|
|
175
|
+
// "events":[{"source":"api","api":"qyhtzl0n39","stage":"test","parentId":"xfdg32","resource":"sample","authorizerId":"fdr3"},
|
|
176
|
+
//{"source":"dynamodb","stream":"arn:aws:dynamodb:ap-southeast-2:174842903734:table/contact_us/stream/2021-04-25T15:02:15.028","batchSize":"23","batchWindow":"3","startingPosition":"LATEST"},
|
|
177
|
+
//{"source":"sqs","stream":"https://sqs.ap-southeast-2.amazonaws.com/174842903734/devq2","batchSize":"32"},
|
|
178
|
+
//{"source":"kinesis","stream":"arn:aws:dynamodb:ap-southeast-2:174842903734:table/contact_us/stream/2021-04-25T15:02:15.028","batchSize":"34","batchWindow":"33","startingPosition":"LATEST"},
|
|
179
|
+
// {"source":"cwevents","rule":"arn:aws:events:ap-southeast-2:174842903734:rule/Test"},
|
|
180
|
+
//{"source":"sns","topic":"arn:aws:sns:ap-southeast-2:174842903734:t1"},
|
|
181
|
+
//{"source":"s3","bucket":"kumoexcelstore","eventType":"s3:ObjectCreated:*","prefix":"cc","suffix":"fd"}],"vpcConfig":{"sg":"","sn":""}}
|
|
182
|
+
///Users/wojtek/Development/kumologica/sdk/kumologica/packages/sdk/src/app/lib/github/index.js:114
|
|
183
|
+
let triggers;
|
|
184
|
+
if (params.events) {
|
|
185
|
+
triggers = [];
|
|
186
|
+
params.events.forEach(e => {
|
|
187
|
+
switch(e.source) {
|
|
188
|
+
case "api": triggers.push({"api": {"apiId": e.api, "stage": e.stage, "parentId": e.parentId, "resource": e.resource, "authorizerId": e.authorizerId}});
|
|
189
|
+
break;
|
|
190
|
+
case "sns": triggers.push({"sns": {"topicArn": e.topic}});
|
|
191
|
+
break;
|
|
192
|
+
case "sqs": triggers.push({"sqs": {"queueArn": e.queueArn, "batchSize": e.batchSize}});
|
|
193
|
+
break;
|
|
194
|
+
case "dynamodb": triggers.push({"dynamodb": {"streamArn": e.stream, "startingPosition": e.startingPosition, "batchSize": e.batchSize, "batchWindow": e.batchWindow}});
|
|
195
|
+
break;
|
|
196
|
+
case "kinesis": triggers.push({"kinesis": {"streamArn": e.stream, "startingPosition": e.startingPosition, "batchSize": e.batchSize, "batchWindow": e.batchWindow}});
|
|
197
|
+
break;
|
|
198
|
+
case "s3": triggers.push({"s3": {"bucket": e.bucket, "eventType": e.eventType, "prefix": e.prefix, "suffix": e.suffix}});
|
|
199
|
+
break;
|
|
200
|
+
case "cwevents": triggers.push({"event": {"expression": e.expression, "reference": e.reference, "name": e.name}});
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
triggers = JSON.stringify(triggers);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
let args = {
|
|
208
|
+
"zip-file-name": params.zipFileName,
|
|
209
|
+
"bucket-name": params.bucketName,
|
|
210
|
+
"lambda-name": params.functionName,
|
|
211
|
+
"memory-size": params.memory,
|
|
212
|
+
"description": params.description,
|
|
213
|
+
"environment": env,
|
|
214
|
+
"tags": tags,
|
|
215
|
+
"timeout": params.timeout,
|
|
216
|
+
"triggers": triggers,
|
|
217
|
+
"vpc-config": vpcConf,
|
|
218
|
+
"role-arn": params.role,
|
|
219
|
+
"tracing-config": tracing,
|
|
220
|
+
"reserved-concurrency": params.reservedConcurrency
|
|
221
|
+
// not present
|
|
222
|
+
// "role-name": params.roleName,
|
|
223
|
+
// "layers": params.layers,
|
|
224
|
+
// "policy": params.policy,
|
|
225
|
+
// "strict-mode": params.strictMode,
|
|
226
|
+
// "log-retention-days": params.logRetentionDays,
|
|
227
|
+
// "file-system-configs": params.fileSystemConfigs,
|
|
228
|
+
// "dead-letter-config": params.deadLetterConfig,
|
|
229
|
+
// "runtime": params.runtime,
|
|
230
|
+
// "architectures": params.architectures,
|
|
231
|
+
// "kms-key-arn": params.kmsKeyArn,
|
|
232
|
+
}
|
|
233
|
+
return args;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
createFile(baseDir, fileName, content) {
|
|
237
|
+
fs.outputFileSync(path.join(baseDir, fileName), content, 'utf-8');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
module.exports = GithubDeployer;
|