@kumologica/sdk 3.4.0 → 3.5.0-beta10
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/create-commands/openapi.js +42 -0
- package/cli/commands/create.js +17 -8
- package/cli/commands/login.js +87 -0
- package/cli/commands/open.js +43 -2
- package/package.json +17 -6
- package/src/app/lib/ai/layout.js +75 -0
- package/src/app/lib/ai/openai.js +108 -0
- package/src/app/lib/ai/prompt.txt +583 -0
- package/src/app/lib/aws/ca-cloudwatch-api.js +2 -10
- package/src/app/lib/aws/ca-dynamodb-api.js +6 -10
- package/src/app/lib/aws/ca-elb-api.js +4 -24
- package/src/app/lib/aws/ca-events-api.js +5 -12
- package/src/app/lib/aws/ca-iot-api.js +3 -87
- package/src/app/lib/aws/ca-s3-api.js +17 -62
- package/src/app/lib/aws/ca-sns-api.js +6 -15
- package/src/app/lib/aws/ca-sqs-api.js +9 -6
- package/src/app/lib/aws/index.js +71 -86
- package/src/app/lib/aws/kl-apigw-api.js +40 -0
- package/src/app/lib/aws/kl-iam-api.js +5 -5
- package/src/app/lib/github/index.js +2 -17
- package/src/app/lib/serverless/index.js +10 -18
- package/src/app/lib/stores/settings-cloud-store.js +35 -2
- package/src/app/main.js +34 -32
- package/src/app/preload.js +36 -28
- package/src/app/ui/editor-client/public/red/red.js +926 -458
- package/src/app/ui/editor-client/public/red/red.min.js +2 -2
- package/src/app/ui/editor-client/public/red/style.min.css +1 -1
- package/src/app/ui/editor-client/src/js/nodes.js +19 -18
- package/src/app/ui/editor-client/src/js/red.js +6 -3
- package/src/app/ui/editor-client/src/js/ui/editor.js +70 -70
- package/src/app/ui/editor-client/src/js/ui/footer.js +145 -0
- package/src/app/ui/editor-client/src/js/ui/search.js +43 -34
- package/src/app/ui/editor-client/src/js/ui/sidebar.js +26 -24
- package/src/app/ui/editor-client/src/js/ui/signup.js +56 -0
- package/src/app/ui/editor-client/src/js/ui/tab-ai.js +210 -0
- package/src/app/ui/editor-client/src/js/ui/tab-awsDeploy.js +30 -5
- package/src/app/ui/editor-client/src/js/ui/tab-test.js +120 -99
- package/src/app/ui/editor-client/src/js/ui/update-panel.js +0 -1
- package/src/app/ui/editor-client/src/js/ui/view.js +201 -202
- package/src/app/ui/editor-client/src/sass/editor.scss +714 -645
- package/src/app/ui/editor-client/src/sass/sidebar.scss +21 -12
- package/src/app/ui/editor-client/src/sass/style.scss +101 -0
- package/src/app/ui/editor-client/src/sass/tab-ai.scss +68 -0
- package/src/app/ui/editor-client/src/sass/workspace.scss +12 -2
- package/src/app/ui/editor-client/templates/index.mst +45 -11
- package/src/server/DesignerServer.js +2 -1
- package/cli/.DS_Store +0 -0
- package/fixtures/.DS_Store +0 -0
- package/src/app/lib/aws/ca-apigw-api.js +0 -216
- package/src/app/lib/aws/ca-codecommit-api.js +0 -63
- package/src/app/lib/aws/kl-rekognition-api.js +0 -66
- package/src/app/lib/aws/kl-ssm-api.js +0 -24
package/src/app/lib/aws/index.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const AWS = require('aws-sdk');
|
|
4
3
|
const CAAWSCloudWatch = require('./ca-cloudwatch-api');
|
|
5
4
|
const CAS3 = require('./ca-s3-api');
|
|
6
5
|
const CASNS = require('./ca-sns-api');
|
|
7
6
|
const CASQS = require('./ca-sqs-api');
|
|
8
|
-
const
|
|
7
|
+
const KLAWSApiGateway = require('./kl-apigw-api');
|
|
8
|
+
const KLIAM = require('./kl-iam-api');
|
|
9
9
|
const CADynamoDb = require('./ca-dynamodb-api');
|
|
10
10
|
const CAEvents = require('./ca-events-api');
|
|
11
11
|
const AWSProfile = require('./aws-profile');
|
|
12
12
|
const { openFileOnEditor } = require('../utils/editor');
|
|
13
13
|
const { exp } = require('@kumologica/builder');
|
|
14
14
|
const { build } = require('@kumologica/builder');
|
|
15
|
-
|
|
15
|
+
const { CloudFormationClient } = require("@aws-sdk/client-cloudformation");
|
|
16
|
+
//const { IoTJobsDataPlane } = require('aws-sdk');
|
|
16
17
|
/**
|
|
17
18
|
* sample events:
|
|
18
19
|
* https://docs.aws.amazon.com/lambda/latest/dg/lambda-services.html
|
|
@@ -21,32 +22,29 @@ class AWSDeployer {
|
|
|
21
22
|
constructor(terminal) {
|
|
22
23
|
this.term = terminal;
|
|
23
24
|
this.awsProfile = new AWSProfile();
|
|
24
|
-
|
|
25
|
-
AWS.config.apiVersions = {
|
|
26
|
-
cloudformation: '2010-05-15',
|
|
27
|
-
};
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
async initAWS(profile) {
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
const { fromIni } = require("@aws-sdk/credential-providers");
|
|
29
|
+
const config = {
|
|
30
|
+
credentials: fromIni({profile: profile})
|
|
31
|
+
};
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
this.region = await this.awsProfile.getRegion(profile);
|
|
34
|
+
|
|
37
35
|
this.cw = false;
|
|
38
36
|
|
|
39
|
-
this.apiGateway = new
|
|
40
|
-
this.
|
|
41
|
-
this.
|
|
42
|
-
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
this.
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
49
|
-
this.events = new CAEvents(this.log.bind(this));
|
|
37
|
+
this.apiGateway = new KLAWSApiGateway(config, this.log.bind(this));
|
|
38
|
+
this.iam = new KLIAM(config, this.log.bind(this));
|
|
39
|
+
this.dynamoDb = new CADynamoDb(config, this.log.bind(this));
|
|
40
|
+
|
|
41
|
+
this.cf = new CloudFormationClient(config);
|
|
42
|
+
|
|
43
|
+
this.s3 = new CAS3(config, this.log.bind(this));
|
|
44
|
+
this.sns = new CASNS(config, this.log.bind(this));
|
|
45
|
+
this.sqs = new CASQS(config, this.log.bind(this));
|
|
46
|
+
this.cwLogs = new CAAWSCloudWatch(config, this.logCloud.bind(this));
|
|
47
|
+
this.events = new CAEvents(config, this.log.bind(this));
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
chalk(c, t) {
|
|
@@ -158,10 +156,10 @@ class AWSDeployer {
|
|
|
158
156
|
this.log(` ${this.chalk('#F5DEB3', 'flow:')} ${this.chalk('whiteBright', projectInfo.projectFlowName)}`, false);
|
|
159
157
|
this.log(` ${this.chalk('#F5DEB3', 'working directory:')} ${this.chalk('whiteBright', projectInfo.projectDir + "/deploy")}`, false);
|
|
160
158
|
this.log(` ${this.chalk('#F5DEB3', 'lambda parameters:')} ${this.chalk('whiteBright', JSON.stringify(params))}`, false);
|
|
161
|
-
this.log(` ${this.chalk('#F5DEB3', 'AWS profile:')} ${this.chalk('whiteBright',
|
|
159
|
+
this.log(` ${this.chalk('#F5DEB3', 'AWS profile:')} ${this.chalk('whiteBright', profile)}`, false);
|
|
162
160
|
|
|
163
161
|
await this.initAWS(profile);
|
|
164
|
-
this.log(` ${this.chalk('#F5DEB3', 'AWS region:')} ${this.chalk('whiteBright',
|
|
162
|
+
this.log(` ${this.chalk('#F5DEB3', 'AWS region:')} ${this.chalk('whiteBright', this.region)}`, false);
|
|
165
163
|
this.log('', false);
|
|
166
164
|
|
|
167
165
|
const settings = this.prepare(
|
|
@@ -177,6 +175,7 @@ class AWSDeployer {
|
|
|
177
175
|
settings.flowName
|
|
178
176
|
);
|
|
179
177
|
|
|
178
|
+
// calls builder
|
|
180
179
|
await this.buildLambda(settings, projectInfo);
|
|
181
180
|
|
|
182
181
|
const nodes = this.loadJsonFile(
|
|
@@ -185,6 +184,7 @@ class AWSDeployer {
|
|
|
185
184
|
|
|
186
185
|
flowListeners = this.processFlow(nodes);
|
|
187
186
|
|
|
187
|
+
// calls exp cf
|
|
188
188
|
const stackDetails = await this.executeStack(
|
|
189
189
|
settings,
|
|
190
190
|
params,
|
|
@@ -263,7 +263,7 @@ if (s.api && s.api.length > 0) {
|
|
|
263
263
|
apiId = output.RestApiId || "unknown api gateway";
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
let url = `https://${apiId}.execute-api.${
|
|
266
|
+
let url = `https://${apiId}.execute-api.${this.region}.amazonaws.com/${stage}`;
|
|
267
267
|
s.api.forEach(a => this.log(` ${(' ' + a.verb.toUpperCase()).slice(-6)} ${url}${a.url}`), this);
|
|
268
268
|
this.log('');
|
|
269
269
|
}
|
|
@@ -356,17 +356,6 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
356
356
|
// api
|
|
357
357
|
const apis = listener.filter(i => i.eventSource == 'api' && i.provider == 'aws')
|
|
358
358
|
.map(a => {return {url: a.apiUrl, verb: a.apiMethod}});
|
|
359
|
-
|
|
360
|
-
// validate if aws nodes got explicit credentials only
|
|
361
|
-
/*const awsNodes = flow.filter(i => ['Rekognition', 'S3', 'SQS', 'Cloudwatch', 'Dynamo DB', 'SNS', 'SES', 'SSM'].includes(i.type));
|
|
362
|
-
if (awsNodes && awsNodes.length > 0) {
|
|
363
|
-
awsNodes.forEach(n => {
|
|
364
|
-
if (!n.securitytype || n.securitytype != 'Credentials') {
|
|
365
|
-
throw new Error (`AWS Node ${n.name} must have explicit credentials set. Open this node and choose Credentials option.`);
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
}*/
|
|
369
|
-
|
|
370
359
|
const dynamodb = listener.filter(i => i.eventSource == 'dynamodb')
|
|
371
360
|
.map(a => {return {stream: a.stream, startingPosition: a.startingPosition}});
|
|
372
361
|
const s3 = listener.filter(i => i.eventSource == 's3')
|
|
@@ -510,14 +499,11 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
510
499
|
|
|
511
500
|
try {
|
|
512
501
|
this.log('Generating cloud formation script');
|
|
513
|
-
this.log(
|
|
514
|
-
` ${this.chalk('#F5DEB3', 'AWS profile:')} ${this.chalk('whiteBright', AWS.config.profile)}`,
|
|
515
|
-
false
|
|
516
|
-
);
|
|
502
|
+
this.log(` ${this.chalk('#F5DEB3', 'AWS profile:')} ${this.chalk('whiteBright', profile)}`, false);
|
|
517
503
|
|
|
518
504
|
await this.initAWS(profile);
|
|
519
505
|
|
|
520
|
-
this.log(` ${this.chalk('#F5DEB3', 'AWS region:')} ${this.chalk('whiteBright',
|
|
506
|
+
this.log(` ${this.chalk('#F5DEB3', 'AWS region:')} ${this.chalk('whiteBright', this.region)}`, false);
|
|
521
507
|
|
|
522
508
|
const settings = this.prepare(projectInfo.projectDir, projectInfo.projectFlowName, params.functionName, params.description);
|
|
523
509
|
|
|
@@ -527,7 +513,7 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
527
513
|
|
|
528
514
|
// NEW
|
|
529
515
|
const args = this.mapParams(params);
|
|
530
|
-
args.region =
|
|
516
|
+
args.region = this.region;
|
|
531
517
|
args["bucket-name"] = settings.deploymentBucketName;
|
|
532
518
|
args["project-directory"] = projectInfo.projectDir;
|
|
533
519
|
args["flow-file-name"] = projectInfo.projectFlowName;
|
|
@@ -535,6 +521,7 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
535
521
|
|
|
536
522
|
console.log(`args: ${JSON.stringify(args)}`);
|
|
537
523
|
const scriptFileName = exp("cloudformation", "aws", args);
|
|
524
|
+
|
|
538
525
|
this.log(`Cloudformation script has been created: ${scriptFileName}`);
|
|
539
526
|
console.log(`Cloudformation script has been created: ${scriptFileName}`);
|
|
540
527
|
|
|
@@ -565,7 +552,7 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
565
552
|
*/
|
|
566
553
|
async executeStack(settings, params, deploymentStartTimestamp, nodes, projectInfo) {
|
|
567
554
|
this.log(`Uploading zip file to bucket...`);
|
|
568
|
-
|
|
555
|
+
const body = fs.createReadStream(
|
|
569
556
|
path.join(settings.deployDir, settings.zipFileName)
|
|
570
557
|
);
|
|
571
558
|
|
|
@@ -576,7 +563,7 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
576
563
|
});
|
|
577
564
|
|
|
578
565
|
const args = this.mapParams(params);
|
|
579
|
-
args.region =
|
|
566
|
+
args.region = this.region;
|
|
580
567
|
args["bucket-name"] = settings.deploymentBucketName;
|
|
581
568
|
args["project-directory"] = projectInfo.projectDir;
|
|
582
569
|
args["flow-file-name"] = projectInfo.projectFlowName;
|
|
@@ -596,34 +583,30 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
596
583
|
this.log('Starting cloudformation stack...');
|
|
597
584
|
|
|
598
585
|
let stack = {};
|
|
586
|
+
const client = this.cf;
|
|
599
587
|
try {
|
|
600
|
-
|
|
588
|
+
const { CreateStackCommand, waitUntilStackCreateComplete, AlreadyExistsException } = require("@aws-sdk/client-cloudformation");
|
|
589
|
+
stack = await this.cf.send(new CreateStackCommand(stackParams));
|
|
590
|
+
|
|
601
591
|
this.log('Waiting for stack create complete...');
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
} catch (error) {
|
|
607
|
-
|
|
608
|
-
if (error.code == 'AlreadyExistsException') {
|
|
609
|
-
stack = await this.cf.updateStack(stackParams).promise();
|
|
610
|
-
this.log('Waiting for stack update complete...');
|
|
611
|
-
|
|
612
|
-
try {
|
|
613
|
-
await this.cf
|
|
614
|
-
.waitFor('stackUpdateComplete', {
|
|
615
|
-
StackName: stackParams.StackName,
|
|
616
|
-
})
|
|
617
|
-
.promise();
|
|
618
|
-
} catch (error) {
|
|
592
|
+
|
|
593
|
+
await waitUntilStackCreateComplete(
|
|
594
|
+
{ client, maxWaitTime: 600 },
|
|
595
|
+
{ StackName: stackParams.StackName })
|
|
619
596
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
597
|
+
} catch (AlreadyExistsException) {
|
|
598
|
+
const { UpdateStackCommand, waitUntilStackUpdateComplete } = require("@aws-sdk/client-cloudformation");
|
|
599
|
+
stack = await this.cf.send(new UpdateStackCommand(stackParams));
|
|
600
|
+
|
|
601
|
+
this.log('Waiting for stack update complete...');
|
|
602
|
+
|
|
603
|
+
try {
|
|
604
|
+
await waitUntilStackUpdateComplete(
|
|
605
|
+
{ client, maxWaitTime: 600 },
|
|
606
|
+
{ StackName: stackParams.StackName })
|
|
607
|
+
|
|
608
|
+
} catch (error) {
|
|
609
|
+
|
|
627
610
|
await this.describeStackEvents(
|
|
628
611
|
stackParams.StackName,
|
|
629
612
|
deploymentStartTimestamp
|
|
@@ -636,7 +619,8 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
636
619
|
}
|
|
637
620
|
|
|
638
621
|
async describeStack(stackName) {
|
|
639
|
-
|
|
622
|
+
const { DescribeStacksCommand } = require("@aws-sdk/client-cloudformation");
|
|
623
|
+
return await this.cf.send(new DescribeStacksCommand({ StackName: stackName }));
|
|
640
624
|
}
|
|
641
625
|
|
|
642
626
|
/*
|
|
@@ -647,9 +631,9 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
647
631
|
let events;
|
|
648
632
|
|
|
649
633
|
try {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
.
|
|
634
|
+
const { DescribeStackEventsCommand } = require("@aws-sdk/client-cloudformation");
|
|
635
|
+
|
|
636
|
+
events = await this.cf.send(new DescribeStackEventsCommand({ StackName: stackName }));
|
|
653
637
|
} catch (error) {
|
|
654
638
|
//this.log(`de: ${error}`);
|
|
655
639
|
// may throw stack does not exists for the first ever call
|
|
@@ -659,9 +643,11 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
659
643
|
return;
|
|
660
644
|
}
|
|
661
645
|
|
|
662
|
-
var deploymentEvents =
|
|
663
|
-
|
|
664
|
-
|
|
646
|
+
var deploymentEvents =
|
|
647
|
+
events.StackEvents
|
|
648
|
+
.filter((event) => event.Timestamp > deploymentStartTimestamp)
|
|
649
|
+
.sort((a, b) => a.Timestamp - b.Timestamp);
|
|
650
|
+
|
|
665
651
|
if (deploymentEvents == undefined || deploymentEvents.length == 0) {
|
|
666
652
|
return;
|
|
667
653
|
}
|
|
@@ -694,24 +680,26 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
694
680
|
return JSON.parse(fs.readFileSync(flowFileName));
|
|
695
681
|
}
|
|
696
682
|
|
|
697
|
-
|
|
698
|
-
fs.outputFileSync(path.join(baseDir, fileName), content, 'utf-8');
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
async listServices(type, profile) {
|
|
683
|
+
async listServices(type, profile, id) {
|
|
702
684
|
if (!profile) {
|
|
703
685
|
throw new Error(
|
|
704
686
|
`AWS profile has not been provided, unable to return list of ${type}. Select correct profile from list.`
|
|
705
687
|
);
|
|
706
688
|
}
|
|
707
689
|
|
|
708
|
-
|
|
690
|
+
await this.initAWS(profile);
|
|
709
691
|
|
|
710
692
|
let res = null;
|
|
711
693
|
switch (type) {
|
|
712
694
|
case 'api':
|
|
713
695
|
res = await this.apiGateway.getApiGateways();
|
|
714
696
|
break;
|
|
697
|
+
case 'api-resources':
|
|
698
|
+
res = await this.apiGateway.getResources(id);
|
|
699
|
+
break;
|
|
700
|
+
case 'api-stages':
|
|
701
|
+
res = await this.apiGateway.getStages(id);
|
|
702
|
+
break;
|
|
715
703
|
case 's3':
|
|
716
704
|
res = await this.s3.getBuckets();
|
|
717
705
|
break;
|
|
@@ -724,9 +712,6 @@ if (s.cwevents && s.cwevents.length > 0) {
|
|
|
724
712
|
case 'dynamodb':
|
|
725
713
|
res = await this.dynamoDb.listStreams();
|
|
726
714
|
break;
|
|
727
|
-
case 'cwlogs':
|
|
728
|
-
res = await this.cwLogs.listLogGroups();
|
|
729
|
-
break;
|
|
730
715
|
case 'alb':
|
|
731
716
|
res = await this.elb.listElbs();
|
|
732
717
|
break;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const jp = require('jsonpath');
|
|
2
|
+
|
|
3
|
+
class KLAWSApiGateway {
|
|
4
|
+
|
|
5
|
+
constructor(config, log) {
|
|
6
|
+
this.log = log;
|
|
7
|
+
this.triggerStage = "";
|
|
8
|
+
|
|
9
|
+
const { APIGatewayClient } = require("@aws-sdk/client-api-gateway");
|
|
10
|
+
this.apigateway = new APIGatewayClient(config);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async getResources(apiId) {
|
|
14
|
+
const { GetResourcesCommand } = require("@aws-sdk/client-api-gateway");
|
|
15
|
+
const res = this.apigateway.send(new GetResourcesCommand({ restApiId: apiId }));
|
|
16
|
+
|
|
17
|
+
return res.items.map(v => {
|
|
18
|
+
return {id: v.id, path: v.path, parentId: v.parentId}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getStages(apiId) {
|
|
23
|
+
const { GetStagesCommand } = require("@aws-sdk/client-api-gateway");
|
|
24
|
+
const st = this.apigateway.send(new GetStagesCommand({ restApiId: apiId }));
|
|
25
|
+
return st.items.map(v => {
|
|
26
|
+
return {id: v.deploymentId, name: v.stageName}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getApiGateways() {
|
|
31
|
+
const { GetRestApisCommand } = require("@aws-sdk/client-api-gateway");
|
|
32
|
+
const api = await this.apigateway.send(new GetRestApisCommand({}));
|
|
33
|
+
|
|
34
|
+
return api.items.map(v => {
|
|
35
|
+
return {id: v.id, name: v.name, arn: `arn-ccc`}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = KLAWSApiGateway;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
const AWS = require('aws-sdk');
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
2
|
* AWS JS API:
|
|
5
3
|
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html
|
|
6
4
|
*/
|
|
7
5
|
class KLIAM {
|
|
8
6
|
|
|
9
|
-
constructor(log) {
|
|
7
|
+
constructor(config, log) {
|
|
10
8
|
this.log = log;
|
|
11
|
-
|
|
9
|
+
const { IAMClient } = require("@aws-sdk/client-iam");
|
|
10
|
+
this.iam = new IAMClient(config);
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
/**
|
|
@@ -16,7 +15,8 @@ class KLIAM {
|
|
|
16
15
|
*/
|
|
17
16
|
async listRoles() {
|
|
18
17
|
|
|
19
|
-
const
|
|
18
|
+
const { ListRolesCommand } = require("@aws-sdk/client-iam");
|
|
19
|
+
const response = await this.iam.send(new ListRolesCommand({}));
|
|
20
20
|
|
|
21
21
|
return response.Roles.map(function(r) {
|
|
22
22
|
return {id: r.Arn, name: r.RoleName, arn: r.Arn};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const AWS = require('aws-sdk');
|
|
3
2
|
const { exp } = require('@kumologica/builder');
|
|
4
3
|
const AWSProfile = require('../aws/aws-profile');
|
|
5
4
|
const { openFileOnEditor } = require('../utils/editor');
|
|
@@ -9,28 +8,12 @@ class GithubDeployer {
|
|
|
9
8
|
this.term = terminal;
|
|
10
9
|
this.awsProfile = new AWSProfile();
|
|
11
10
|
|
|
12
|
-
AWS.config.apiVersions = {
|
|
13
|
-
cloudformation: '2010-05-15',
|
|
14
|
-
};
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
async initAWS(profile) {
|
|
18
|
-
AWS.config.credentials = new AWS.SharedIniFileCredentials({profile: profile});
|
|
19
14
|
|
|
20
15
|
const r = await this.awsProfile.getRegion(profile);
|
|
21
|
-
let s3 = new AWS.S3();
|
|
22
16
|
let bucketName = "CHANGE_IT_TO_REAL_BUCKET_NAME";
|
|
23
|
-
|
|
24
|
-
// find bucket
|
|
25
|
-
const buckets = await s3.listBuckets({}).promise();
|
|
26
|
-
|
|
27
|
-
if (buckets && buckets.Buckets) {
|
|
28
|
-
const bucket = buckets.Buckets.find(b => b.Name.startsWith('kumologica-designer-deploy'));
|
|
29
|
-
if (bucket) {
|
|
30
|
-
bucketName = bucket.Name;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
17
|
return {region: r, bucket: bucketName};
|
|
35
18
|
}
|
|
36
19
|
|
|
@@ -74,6 +57,8 @@ class GithubDeployer {
|
|
|
74
57
|
args.region = awsSettings.region;
|
|
75
58
|
args["bucket-name"] = awsSettings.bucket;
|
|
76
59
|
args["output-file-name"] = path.join(projectInfo.projectDir, '.github', 'workflows', 'workflow.yaml');
|
|
60
|
+
args["project-directory"] = projectInfo.projectDir;
|
|
61
|
+
args["flow-file-name"] = projectInfo.projectFlowName;
|
|
77
62
|
|
|
78
63
|
const wfDir = exp("github", "aws", args, console.log);
|
|
79
64
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const AWS = require('aws-sdk');
|
|
4
3
|
const yaml = require('js-yaml');
|
|
5
4
|
const AWSProfile = require('../aws/aws-profile');
|
|
6
5
|
const CASQS = require('../aws/ca-sqs-api');
|
|
@@ -18,18 +17,13 @@ class ServerlessDeployer {
|
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
async initAWS(profile) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
AWS.config.apiVersions = {
|
|
25
|
-
cloudformation: '2010-05-15'
|
|
20
|
+
const { fromIni } = require("@aws-sdk/credential-providers");
|
|
21
|
+
const config = {
|
|
22
|
+
credentials: fromIni({profile: profile})
|
|
26
23
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
AWS.config.update({region: region});
|
|
32
|
-
this.sqs = new CASQS(this.log.bind(this));
|
|
24
|
+
|
|
25
|
+
this.region = await this.awsProfile.getRegion(profile);
|
|
26
|
+
this.sqs = new CASQS(config, this.log.bind(this));
|
|
33
27
|
}
|
|
34
28
|
|
|
35
29
|
log(text, calog = true) {
|
|
@@ -90,17 +84,15 @@ class ServerlessDeployer {
|
|
|
90
84
|
|
|
91
85
|
await this.initAWS(profile);
|
|
92
86
|
|
|
93
|
-
console.log(`AWS.config = ${JSON.stringify(AWS.config)}`);
|
|
94
|
-
|
|
95
87
|
try {
|
|
96
88
|
this.log('Generating serverless.yml file');
|
|
97
|
-
this.log(` AWS profile: ${
|
|
98
|
-
this.log(` AWS region: ${
|
|
89
|
+
this.log(` AWS profile: ${profile}`, false);
|
|
90
|
+
this.log(` AWS region: ${this.region}`, false);
|
|
99
91
|
|
|
100
92
|
const settings = this.prepare(projectInfo.projectDir, projectInfo.projectFlowName, params.functionName, params.description);
|
|
101
93
|
const nodes = this.loadFlow(path.join(projectInfo.projectDir, projectInfo.projectFlowName));
|
|
102
94
|
|
|
103
|
-
const serverlessTemplate = await this.createServerlessTemplate(params, settings, nodes,
|
|
95
|
+
const serverlessTemplate = await this.createServerlessTemplate(params, settings, nodes, this.region);
|
|
104
96
|
this.createFile(projectInfo.projectDir, `serverless.yml`, serverlessTemplate);
|
|
105
97
|
|
|
106
98
|
const scriptFileName = path.join(projectInfo.projectDir, `serverless.yml`);
|
|
@@ -122,7 +114,7 @@ class ServerlessDeployer {
|
|
|
122
114
|
|
|
123
115
|
provider: {
|
|
124
116
|
name: "aws",
|
|
125
|
-
runtime: "
|
|
117
|
+
runtime: "nodejs18.x",
|
|
126
118
|
deploymentPrefix: "kumologica-sls"
|
|
127
119
|
},
|
|
128
120
|
functions: {},
|
|
@@ -52,7 +52,6 @@ class CloudConfigStore {
|
|
|
52
52
|
fsx.ensureDirSync(path.join(homedir, credsDir));
|
|
53
53
|
fs.writeFileSync(this.cloudConfigFileFullPath, defaultContent);
|
|
54
54
|
}
|
|
55
|
-
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
parseCloudConfigFile() {
|
|
@@ -81,6 +80,10 @@ class CloudConfigStore {
|
|
|
81
80
|
return this.getAliases('kumohub') || [];
|
|
82
81
|
}
|
|
83
82
|
|
|
83
|
+
getKumologicaDevAliases() {
|
|
84
|
+
return this.getAliases('kumologica.dev') || [];
|
|
85
|
+
}
|
|
86
|
+
|
|
84
87
|
getAWSAliases() {
|
|
85
88
|
return this.getAliases('aws') || [];
|
|
86
89
|
}
|
|
@@ -89,13 +92,18 @@ class CloudConfigStore {
|
|
|
89
92
|
return this.getAliases('azure') || [];
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
getKumohubAliasInfo(alias){
|
|
93
96
|
return this.getAliasInfo('kumohub', alias);
|
|
94
97
|
}
|
|
95
98
|
|
|
99
|
+
getKumologicaDevAliasInfo(alias){
|
|
100
|
+
return this.getAliasInfo('kumologica.dev', alias);
|
|
101
|
+
}
|
|
102
|
+
|
|
96
103
|
getAWSAliasInfo(alias){
|
|
97
104
|
return this.getAliasInfo('aws', alias);
|
|
98
105
|
}
|
|
106
|
+
|
|
99
107
|
getAzureAliasInfo(alias){
|
|
100
108
|
return this.getAliasInfo('azure', alias);
|
|
101
109
|
}
|
|
@@ -104,9 +112,34 @@ class CloudConfigStore {
|
|
|
104
112
|
return this.cloudConfigFileFullPath;
|
|
105
113
|
}
|
|
106
114
|
|
|
115
|
+
saveKumologicaDevAlias(tokens) {
|
|
116
|
+
let lines = this.readCloudConfigFile().split(/\n/).map(l=> l.trim());
|
|
117
|
+
|
|
118
|
+
// find [kumologica.dev]
|
|
119
|
+
const d = lines.indexOf("[kumologica.dev]");
|
|
120
|
+
|
|
121
|
+
if (d != -1) {
|
|
122
|
+
// if found then delete lines until next [ or the end
|
|
123
|
+
//ignore first [ it belongs to kumologica.dev
|
|
124
|
+
for (let i = d; i<lines.length; ) { // splice works like i++
|
|
125
|
+
if (lines[i].trim().startsWith("[") && i > d) {
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
lines.splice(i, 1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// add [kumologica.dev]
|
|
133
|
+
lines.push("[kumologica.dev]");
|
|
134
|
+
tokens.forEach(t => lines.push(t));
|
|
135
|
+
|
|
136
|
+
this.writeCloudConfigFile(lines.join('\n'));
|
|
137
|
+
}
|
|
138
|
+
|
|
107
139
|
writeCloudConfigFile(content){
|
|
108
140
|
fs.writeFileSync(this.cloudConfigFileFullPath, content);
|
|
109
141
|
}
|
|
142
|
+
|
|
110
143
|
readCloudConfigFile(){
|
|
111
144
|
const data = fs.readFileSync(this.cloudConfigFileFullPath, "utf-8");
|
|
112
145
|
const lines = data.split(/\r\n|\n/);
|