@webda/aws 2.0.0-beta.3 → 2.1.0

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.
Files changed (72) hide show
  1. package/lib/deployers/cloudformation.d.ts +3 -3
  2. package/lib/deployers/cloudformation.js +673 -694
  3. package/lib/deployers/cloudformation.js.map +1 -1
  4. package/lib/deployers/cloudformation.spec.js +428 -477
  5. package/lib/deployers/cloudformation.spec.js.map +1 -1
  6. package/lib/deployers/index.js +282 -342
  7. package/lib/deployers/index.js.map +1 -1
  8. package/lib/deployers/index.spec.d.ts +1 -1
  9. package/lib/deployers/index.spec.js +445 -510
  10. package/lib/deployers/index.spec.js.map +1 -1
  11. package/lib/deployers/lambda-entrypoint.js +4 -16
  12. package/lib/deployers/lambda-entrypoint.js.map +1 -1
  13. package/lib/deployers/lambdapackager.d.ts +1 -1
  14. package/lib/deployers/lambdapackager.js +14 -53
  15. package/lib/deployers/lambdapackager.js.map +1 -1
  16. package/lib/deployers/lambdapackager.spec.js +25 -61
  17. package/lib/deployers/lambdapackager.spec.js.map +1 -1
  18. package/lib/index.d.ts +1 -1
  19. package/lib/index.js +1 -17
  20. package/lib/index.js.map +1 -1
  21. package/lib/index.spec.d.ts +1 -1
  22. package/lib/index.spec.js +28 -75
  23. package/lib/index.spec.js.map +1 -1
  24. package/lib/services/aws-mixin.d.ts +2 -0
  25. package/lib/services/aws-mixin.js +2 -7
  26. package/lib/services/aws-mixin.js.map +1 -1
  27. package/lib/services/cloudwatchlogger.d.ts +3 -1
  28. package/lib/services/cloudwatchlogger.js +63 -104
  29. package/lib/services/cloudwatchlogger.js.map +1 -1
  30. package/lib/services/cloudwatchlogger.spec.js +57 -100
  31. package/lib/services/cloudwatchlogger.spec.js.map +1 -1
  32. package/lib/services/dynamodb.d.ts +4 -2
  33. package/lib/services/dynamodb.js +457 -498
  34. package/lib/services/dynamodb.js.map +1 -1
  35. package/lib/services/dynamodb.spec.d.ts +2 -2
  36. package/lib/services/dynamodb.spec.js +231 -302
  37. package/lib/services/dynamodb.spec.js.map +1 -1
  38. package/lib/services/index.d.ts +9 -9
  39. package/lib/services/index.js +8 -24
  40. package/lib/services/index.js.map +1 -1
  41. package/lib/services/lambdacaller.d.ts +2 -0
  42. package/lib/services/lambdacaller.js +15 -29
  43. package/lib/services/lambdacaller.js.map +1 -1
  44. package/lib/services/lambdacaller.spec.js +43 -81
  45. package/lib/services/lambdacaller.spec.js.map +1 -1
  46. package/lib/services/lambdaserver.js +167 -190
  47. package/lib/services/lambdaserver.js.map +1 -1
  48. package/lib/services/lambdaserver.spec.js +266 -354
  49. package/lib/services/lambdaserver.spec.js.map +1 -1
  50. package/lib/services/route53.js +112 -137
  51. package/lib/services/route53.js.map +1 -1
  52. package/lib/services/route53.spec.js +56 -92
  53. package/lib/services/route53.spec.js.map +1 -1
  54. package/lib/services/s3binary.d.ts +6 -2
  55. package/lib/services/s3binary.js +189 -251
  56. package/lib/services/s3binary.js.map +1 -1
  57. package/lib/services/s3binary.spec.js +185 -254
  58. package/lib/services/s3binary.spec.js.map +1 -1
  59. package/lib/services/secretsmanager.d.ts +2 -0
  60. package/lib/services/secretsmanager.js +32 -56
  61. package/lib/services/secretsmanager.js.map +1 -1
  62. package/lib/services/secretsmanager.spec.js +50 -93
  63. package/lib/services/secretsmanager.spec.js.map +1 -1
  64. package/lib/services/sqsqueue.d.ts +5 -7
  65. package/lib/services/sqsqueue.js +70 -99
  66. package/lib/services/sqsqueue.js.map +1 -1
  67. package/lib/services/sqsqueue.spec.js +95 -145
  68. package/lib/services/sqsqueue.spec.js.map +1 -1
  69. package/lib/shell.js +19 -38
  70. package/lib/shell.js.map +1 -1
  71. package/package.json +12 -9
  72. package/webda.module.json +54 -6
@@ -1,350 +1,302 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
- Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.CloudFormationDeployer = exports.LAMBDA_LATEST_VERSION = void 0;
36
- const client_api_gateway_1 = require("@aws-sdk/client-api-gateway");
37
- const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
38
- const client_sts_1 = require("@aws-sdk/client-sts");
39
- const core_1 = require("@webda/core");
40
- const fs = __importStar(require("fs"));
41
- const path = __importStar(require("path"));
42
- const YAML = __importStar(require("yaml"));
43
- const _1 = require(".");
1
+ import { APIGateway } from "@aws-sdk/client-api-gateway";
2
+ import { CloudFormation } from "@aws-sdk/client-cloudformation";
3
+ import { STS } from "@aws-sdk/client-sts";
4
+ import { JSONUtils, WebdaError } from "@webda/core";
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import * as YAML from "yaml";
8
+ import { AWSDeployer } from "./index.js";
44
9
  const LAMBDA_LATEST_VERSION = "nodejs14.x";
45
- exports.LAMBDA_LATEST_VERSION = LAMBDA_LATEST_VERSION;
46
10
  /**
47
11
  * Deploy the application and its resources using AWS CloudFormation
48
12
  *
49
- * @WebdaDeployer
13
+ * @WebdaDeployer WebdaAWSDeployer/CloudFormation
50
14
  */
51
- class CloudFormationDeployer extends _1.AWSDeployer {
15
+ export default class CloudFormationDeployer extends AWSDeployer {
52
16
  constructor(manager, resources) {
53
17
  super(manager, resources);
54
18
  this.template = {};
55
19
  this.result = {};
56
20
  }
57
- defaultResources() {
58
- const _super = Object.create(null, {
59
- defaultResources: { get: () => super.defaultResources }
60
- });
21
+ async defaultResources() {
61
22
  var _a, _b, _c;
62
- var _d, _e, _f;
63
- return __awaiter(this, void 0, void 0, function* () {
64
- yield _super.defaultResources.call(this);
65
- let packageDesc = this.getApplication().getPackageDescription();
66
- packageDesc.webda = packageDesc.webda || {};
67
- packageDesc.webda.aws = packageDesc.webda.aws || {};
68
- if (this.resources.ResourcesToImport) {
69
- if (!this.resources.ChangeSetType) {
70
- this.resources.ChangeSetType = "IMPORT";
71
- }
72
- if (this.resources.ChangeSetType !== "IMPORT") {
73
- throw new Error("ChangeSetType cannot be anything else than IMPORT if you have ResourcesToImport set");
74
- }
23
+ await super.defaultResources();
24
+ let packageDesc = this.getApplication().getPackageDescription();
25
+ packageDesc.webda = packageDesc.webda || {};
26
+ packageDesc.webda.aws = packageDesc.webda.aws || {};
27
+ if (this.resources.ResourcesToImport) {
28
+ if (!this.resources.ChangeSetType) {
29
+ this.resources.ChangeSetType = "IMPORT";
75
30
  }
76
- this.resources.ChangeSetType = this.resources.ChangeSetType || "CREATE";
77
- this.resources.AssetsBucket = this.resources.AssetsBucket || packageDesc.webda.aws.AssetsBucket;
78
- if (!this.resources.AssetsBucket) {
79
- throw new core_1.WebdaError("ASSETS_BUCKET_REQUIRED", "AssetsBucket must be defined");
80
- }
81
- this.resources.AssetsPrefix = this.resources.AssetsPrefix || "${deployment}/${deployer.name}/";
82
- this.resources.Description = this.resources.Description || "Deployed by @webda/aws/cloudformation";
83
- this.resources.FileName = this.resources.FileName || `cloudformation-${this.resources.name}`;
84
- this.resources.StackName = this.resources.StackName || this.resources.name;
85
- this.resources.Format = this.resources.Format || "JSON";
86
- this.resources.OpenAPIFileName = this.resources.OpenAPIFileName || "${resources.name}-openapi-${package.version}";
87
- this.resources.OpenAPITitle = this.resources.OpenAPITitle || this.resources.name;
88
- // Default Lambda value
89
- if (this.resources.Lambda) {
90
- let zipPath = "lambda-${package.version}.zip";
91
- if (this.resources.LambdaPackager) {
92
- zipPath = this.resources.LambdaPackager.zipPath;
93
- }
94
- (_a = (_d = this.resources).LambdaPackager) !== null && _a !== void 0 ? _a : (_d.LambdaPackager = { zipPath });
95
- this.resources.LambdaPackager.zipPath = zipPath;
96
- this.resources.Lambda.Runtime = this.resources.Lambda.Runtime || LAMBDA_LATEST_VERSION;
97
- this.resources.Lambda.MemorySize = this.resources.Lambda.MemorySize || 2048;
98
- this.resources.Lambda.Timeout = this.resources.Lambda.Timeout || 30;
99
- this.resources.Lambda.Handler =
100
- this.resources.Lambda.Handler || "node_modules/@webda/aws/lib/deployers/lambda-entrypoint.handler";
101
- this.resources.Lambda.FunctionName = this.resources.Lambda.FunctionName || this.resources.name;
102
- if (!this.resources.Lambda.Role) {
103
- this.resources.Lambda.Role = { "Fn::GetAtt": ["Role", "Arn"] };
104
- // If no role is specified auto enable Role and Policy creation
105
- this.resources.Role = this.resources.Role || {};
106
- this.resources.Policy = this.resources.Policy || {};
107
- }
31
+ if (this.resources.ChangeSetType !== "IMPORT") {
32
+ throw new Error("ChangeSetType cannot be anything else than IMPORT if you have ResourcesToImport set");
33
+ }
34
+ }
35
+ this.resources.ChangeSetType = this.resources.ChangeSetType || "CREATE";
36
+ this.resources.AssetsBucket = this.resources.AssetsBucket || packageDesc.webda.aws.AssetsBucket;
37
+ if (!this.resources.AssetsBucket) {
38
+ throw new WebdaError("ASSETS_BUCKET_REQUIRED", "AssetsBucket must be defined");
39
+ }
40
+ this.resources.AssetsPrefix = this.resources.AssetsPrefix || "${deployment}/${deployer.name}/";
41
+ this.resources.Description = this.resources.Description || "Deployed by @webda/aws/cloudformation";
42
+ this.resources.FileName = this.resources.FileName || `cloudformation-${this.resources.name}`;
43
+ this.resources.StackName = this.resources.StackName || this.resources.name;
44
+ this.resources.Format = this.resources.Format || "JSON";
45
+ this.resources.OpenAPIFileName = this.resources.OpenAPIFileName || "${resources.name}-openapi-${package.version}";
46
+ this.resources.OpenAPITitle = this.resources.OpenAPITitle || this.resources.name;
47
+ // Default Lambda value
48
+ if (this.resources.Lambda) {
49
+ let zipPath = "lambda-${package.version}.zip";
50
+ if (this.resources.LambdaPackager) {
51
+ zipPath = this.resources.LambdaPackager.zipPath;
52
+ }
53
+ (_a = this.resources).LambdaPackager ?? (_a.LambdaPackager = { zipPath });
54
+ this.resources.LambdaPackager.zipPath = zipPath;
55
+ this.resources.Lambda.Runtime = this.resources.Lambda.Runtime || LAMBDA_LATEST_VERSION;
56
+ this.resources.Lambda.MemorySize = this.resources.Lambda.MemorySize || 2048;
57
+ this.resources.Lambda.Timeout = this.resources.Lambda.Timeout || 30;
58
+ this.resources.Lambda.Handler =
59
+ this.resources.Lambda.Handler || "node_modules/@webda/aws/lib/deployers/lambda-entrypoint.handler";
60
+ this.resources.Lambda.FunctionName = this.resources.Lambda.FunctionName || this.resources.name;
61
+ if (!this.resources.Lambda.Role) {
62
+ this.resources.Lambda.Role = { "Fn::GetAtt": ["Role", "Arn"] };
63
+ // If no role is specified auto enable Role and Policy creation
64
+ this.resources.Role = this.resources.Role || {};
65
+ this.resources.Policy = this.resources.Policy || {};
108
66
  }
109
- // Default Role
67
+ }
68
+ // Default Role
69
+ if (this.resources.Role) {
70
+ this.resources.Role.RoleName = this.resources.Role.RoleName || `${this.resources.name}Role`;
71
+ if (!this.resources.Role.Policies || this.resources.Role.Policies.length === 0) {
72
+ this.resources.Policy = this.resources.Policy || {};
73
+ }
74
+ this.resources.Role.AssumeRolePolicyDocument = this.resources.Role.AssumeRolePolicyDocument || {
75
+ Statement: []
76
+ };
77
+ this.resources.Role.AssumeRolePolicyDocument.Statement =
78
+ this.resources.Role.AssumeRolePolicyDocument.Statement || [];
79
+ this.resources.Role.AssumeRolePolicyDocument.Version =
80
+ this.resources.Role.AssumeRolePolicyDocument.Version || "2012-10-17";
81
+ }
82
+ // Default Policy
83
+ if (this.resources.Policy) {
84
+ this.resources.Policy.PolicyName = this.resources.Policy.PolicyName || `${this.resources.name}Policy`;
85
+ this.resources.Policy.Roles = this.resources.Policy.Roles || [];
110
86
  if (this.resources.Role) {
111
- this.resources.Role.RoleName = this.resources.Role.RoleName || `${this.resources.name}Role`;
112
- if (!this.resources.Role.Policies || this.resources.Role.Policies.length === 0) {
113
- this.resources.Policy = this.resources.Policy || {};
114
- }
115
- this.resources.Role.AssumeRolePolicyDocument = this.resources.Role.AssumeRolePolicyDocument || {
116
- Statement: []
117
- };
118
- this.resources.Role.AssumeRolePolicyDocument.Statement =
119
- this.resources.Role.AssumeRolePolicyDocument.Statement || [];
120
- this.resources.Role.AssumeRolePolicyDocument.Version =
121
- this.resources.Role.AssumeRolePolicyDocument.Version || "2012-10-17";
122
- }
123
- // Default Policy
124
- if (this.resources.Policy) {
125
- this.resources.Policy.PolicyName = this.resources.Policy.PolicyName || `${this.resources.name}Policy`;
126
- this.resources.Policy.Roles = this.resources.Policy.Roles || [];
127
- if (this.resources.Role) {
128
- this.resources.Policy.Roles.push({ Ref: "Role" });
129
- }
130
- this.resources.Policy.PolicyDocument = this.resources.Policy.PolicyDocument || { Statement: [] };
131
- }
132
- this.resources.Tags = this.transformMapTagsToArray(this.resources.Tags || []);
133
- if (this.resources.APIGatewayStage) {
134
- this.resources.APIGatewayStage.StageName =
135
- // @ts-ignore
136
- this.resources.APIGatewayStage.StageName || this.getApplication().currentDeployment;
137
- }
138
- // Activate Domain
139
- if (this.resources.APIGatewayDomain) {
140
- (_b = (_e = this.resources.APIGatewayDomain).SecurityPolicy) !== null && _b !== void 0 ? _b : (_e.SecurityPolicy = "TLS_1_2");
141
- }
142
- // Default BasePathMapping
143
- if (this.resources.APIGatewayBasePathMapping) {
144
- this.resources.APIGatewayBasePathMapping.BasePath = this.resources.APIGatewayBasePathMapping.BasePath || "";
145
- (_c = (_f = this.resources.APIGatewayBasePathMapping).DomainName) !== null && _c !== void 0 ? _c : (_f.DomainName = this.resources.APIGatewayDomain.DomainName);
146
- if (this.resources.APIGatewayBasePathMapping.DomainName.endsWith(".")) {
147
- this.resources.APIGatewayBasePathMapping.DomainName =
148
- this.resources.APIGatewayBasePathMapping.DomainName.substring(0, this.resources.APIGatewayBasePathMapping.DomainName.length - 1);
149
- }
87
+ this.resources.Policy.Roles.push({ Ref: "Role" });
150
88
  }
151
- // Activate Domain
152
- if (this.resources.APIGatewayV2Domain) {
153
- // Enable BasePathMapping if does not exist
154
- this.resources.APIGatewayV2ApiMapping = this.resources.APIGatewayV2ApiMapping || {};
155
- this.resources.APIGatewayV2Domain.DomainNameConfigurations =
156
- this.resources.APIGatewayV2Domain.DomainNameConfigurations || [];
157
- }
158
- // Default BasePathMapping
159
- if (this.resources.APIGatewayV2ApiMapping) {
160
- this.resources.APIGatewayV2ApiMapping.BasePath = this.resources.APIGatewayV2ApiMapping.BasePath || "";
161
- this.resources.APIGatewayV2ApiMapping.DomainName =
162
- this.resources.APIGatewayV2ApiMapping.DomainName || this.resources.APIGatewayDomain.DomainName;
163
- if (this.resources.APIGatewayV2ApiMapping.DomainName.endsWith(".")) {
164
- this.resources.APIGatewayV2ApiMapping.DomainName = this.resources.APIGatewayV2ApiMapping.DomainName.substring(0, this.resources.APIGatewayV2ApiMapping.DomainName.length - 1);
165
- }
89
+ this.resources.Policy.PolicyDocument = this.resources.Policy.PolicyDocument || { Statement: [] };
90
+ }
91
+ this.resources.Tags = this.transformMapTagsToArray(this.resources.Tags || []);
92
+ if (this.resources.APIGatewayStage) {
93
+ this.resources.APIGatewayStage.StageName =
94
+ // @ts-ignore
95
+ this.resources.APIGatewayStage.StageName || this.getApplication().currentDeployment;
96
+ }
97
+ // Activate Domain
98
+ if (this.resources.APIGatewayDomain) {
99
+ (_b = this.resources.APIGatewayDomain).SecurityPolicy ?? (_b.SecurityPolicy = "TLS_1_2");
100
+ }
101
+ // Default BasePathMapping
102
+ if (this.resources.APIGatewayBasePathMapping) {
103
+ this.resources.APIGatewayBasePathMapping.BasePath = this.resources.APIGatewayBasePathMapping.BasePath || "";
104
+ (_c = this.resources.APIGatewayBasePathMapping).DomainName ?? (_c.DomainName = this.resources.APIGatewayDomain.DomainName);
105
+ if (this.resources.APIGatewayBasePathMapping.DomainName.endsWith(".")) {
106
+ this.resources.APIGatewayBasePathMapping.DomainName =
107
+ this.resources.APIGatewayBasePathMapping.DomainName.substring(0, this.resources.APIGatewayBasePathMapping.DomainName.length - 1);
166
108
  }
167
- this.resources.Statics = (this.resources.Statics || []);
168
- this.resources.Statics.forEach(conf => {
169
- // Should move to init
170
- if (!conf.AssetsPath) {
171
- conf.AssetsPath = conf.Source;
172
- if (conf.AssetsPath.startsWith("/")) {
173
- conf.AssetsPath = conf.AssetsPath.substring(1);
174
- }
175
- if (!conf.AssetsPath.endsWith("/")) {
176
- conf.AssetsPath += "/";
177
- }
178
- }
179
- if (conf.CloudFront) {
180
- let DistributionConfig = conf.CloudFront.DistributionConfig || {};
181
- DistributionConfig.Aliases = DistributionConfig.Aliases || [];
182
- if (DistributionConfig.Aliases.indexOf(conf.DomainName) < 0) {
183
- DistributionConfig.Aliases.push(conf.DomainName);
184
- }
185
- DistributionConfig.PriceClass = DistributionConfig.PriceClass || "PriceClass_100";
186
- DistributionConfig.Comment = DistributionConfig.Comment || "Deployed with @webda/aws/cloudformation";
187
- if (DistributionConfig.Enabled === undefined) {
188
- DistributionConfig.Enabled = true;
189
- }
190
- if (!DistributionConfig.DefaultCacheBehavior) {
191
- DistributionConfig.DefaultCacheBehavior = {
192
- AllowedMethods: ["GET", "HEAD"],
193
- ViewerProtocolPolicy: "redirect-to-https",
194
- TargetOriginId: conf.DomainName,
195
- ForwardedValues: {
196
- QueryString: false
197
- }
198
- };
199
- }
200
- if (!DistributionConfig.Origins) {
201
- DistributionConfig.Origins = [
202
- {
203
- DomainName: `${this.resources.AssetsBucket}.s3.amazonaws.com`,
204
- Id: conf.DomainName,
205
- OriginPath: `/${conf.AssetsPath.substring(0, conf.AssetsPath.length - 1)}`,
206
- S3OriginConfig: {}
207
- }
208
- ];
209
- }
210
- conf.CloudFront.DistributionConfig = DistributionConfig;
109
+ }
110
+ // Activate Domain
111
+ if (this.resources.APIGatewayV2Domain) {
112
+ // Enable BasePathMapping if does not exist
113
+ this.resources.APIGatewayV2ApiMapping = this.resources.APIGatewayV2ApiMapping || {};
114
+ this.resources.APIGatewayV2Domain.DomainNameConfigurations =
115
+ this.resources.APIGatewayV2Domain.DomainNameConfigurations || [];
116
+ }
117
+ // Default BasePathMapping
118
+ if (this.resources.APIGatewayV2ApiMapping) {
119
+ this.resources.APIGatewayV2ApiMapping.BasePath = this.resources.APIGatewayV2ApiMapping.BasePath || "";
120
+ this.resources.APIGatewayV2ApiMapping.DomainName =
121
+ this.resources.APIGatewayV2ApiMapping.DomainName || this.resources.APIGatewayDomain.DomainName;
122
+ if (this.resources.APIGatewayV2ApiMapping.DomainName.endsWith(".")) {
123
+ this.resources.APIGatewayV2ApiMapping.DomainName = this.resources.APIGatewayV2ApiMapping.DomainName.substring(0, this.resources.APIGatewayV2ApiMapping.DomainName.length - 1);
124
+ }
125
+ }
126
+ this.resources.Statics = (this.resources.Statics || []);
127
+ this.resources.Statics.forEach(conf => {
128
+ // Should move to init
129
+ if (!conf.AssetsPath) {
130
+ conf.AssetsPath = conf.Source;
131
+ if (conf.AssetsPath.startsWith("/")) {
132
+ conf.AssetsPath = conf.AssetsPath.substring(1);
133
+ }
134
+ if (!conf.AssetsPath.endsWith("/")) {
135
+ conf.AssetsPath += "/";
136
+ }
137
+ }
138
+ if (conf.CloudFront) {
139
+ let DistributionConfig = conf.CloudFront.DistributionConfig || {};
140
+ DistributionConfig.Aliases = DistributionConfig.Aliases || [];
141
+ if (DistributionConfig.Aliases.indexOf(conf.DomainName) < 0) {
142
+ DistributionConfig.Aliases.push(conf.DomainName);
143
+ }
144
+ DistributionConfig.PriceClass = DistributionConfig.PriceClass || "PriceClass_100";
145
+ DistributionConfig.Comment = DistributionConfig.Comment || "Deployed with @webda/aws/cloudformation";
146
+ if (DistributionConfig.Enabled === undefined) {
147
+ DistributionConfig.Enabled = true;
148
+ }
149
+ if (!DistributionConfig.DefaultCacheBehavior) {
150
+ DistributionConfig.DefaultCacheBehavior = {
151
+ AllowedMethods: ["GET", "HEAD"],
152
+ ViewerProtocolPolicy: "redirect-to-https",
153
+ TargetOriginId: conf.DomainName,
154
+ ForwardedValues: {
155
+ QueryString: false
156
+ }
157
+ };
211
158
  }
212
- });
213
- // Manage Docker build
214
- if (this.resources.Docker) {
215
- this.resources.Docker.push = this.resources.Docker.push === undefined ? true : this.resources.Docker.push;
216
- this.resources.Docker.includeRepository =
217
- this.resources.Docker.includeRepository === undefined ? true : this.resources.Docker.includeRepository;
218
- if (this.resources.Docker.includeRepository && this.resources.Docker.tag) {
219
- let accountId = (yield this.getAWSIdentity()).Account;
220
- this.resources.Docker.tag =
221
- accountId + ".dkr.ecr.eu-west-1.amazonaws.com/${package.webda.aws.Repository}:" + this.resources.Docker.tag;
159
+ if (!DistributionConfig.Origins) {
160
+ DistributionConfig.Origins = [
161
+ {
162
+ DomainName: `${this.resources.AssetsBucket}.s3.amazonaws.com`,
163
+ Id: conf.DomainName,
164
+ OriginPath: `/${conf.AssetsPath.substring(0, conf.AssetsPath.length - 1)}`,
165
+ S3OriginConfig: {}
166
+ }
167
+ ];
222
168
  }
169
+ conf.CloudFront.DistributionConfig = DistributionConfig;
223
170
  }
224
171
  });
172
+ // Manage Docker build
173
+ if (this.resources.Docker) {
174
+ this.resources.Docker.push = this.resources.Docker.push === undefined ? true : this.resources.Docker.push;
175
+ this.resources.Docker.includeRepository =
176
+ this.resources.Docker.includeRepository === undefined ? true : this.resources.Docker.includeRepository;
177
+ if (this.resources.Docker.includeRepository && this.resources.Docker.tag) {
178
+ let accountId = (await this.getAWSIdentity()).Account;
179
+ this.resources.Docker.tag =
180
+ accountId + ".dkr.ecr.eu-west-1.amazonaws.com/${package.webda.aws.Repository}:" + this.resources.Docker.tag;
181
+ }
182
+ }
225
183
  }
226
- deploy() {
227
- return __awaiter(this, void 0, void 0, function* () {
228
- const { Description } = this.resources;
229
- this.template = {
230
- Description,
231
- Resources: Object.assign({}, this.resources.CustomResources)
232
- };
233
- this.result = {};
234
- // Ensure S3 bucket exist
235
- this.logger.log("DEBUG", "Check assets bucket", this.resources.AssetsBucket);
236
- yield this.createBucket(this.resources.AssetsBucket);
237
- // Check if we need OpenAPI export
238
- let openapi = yield this.completeOpenAPI(this.manager.getWebda().exportOpenAPI(false));
239
- this.openapiS3Object = this.getStringified(openapi, this.resources.OpenAPIFileName);
240
- yield this.putFilesOnBucket(this.resources.AssetsBucket, [this.openapiS3Object]);
241
- // If APIGatewayImportOpenApi update REST API
242
- if (this.resources.APIGatewayImportOpenApi) {
243
- this.logger.log("INFO", "Importing open api");
244
- yield this.importOpenApi(openapi);
245
- }
246
- // Build Docker if needed
247
- if (this.resources.Docker && this.resources.Docker.tag) {
248
- this.logger.log("INFO", "Building Docker image", this.resources.Docker.tag);
249
- yield this.buildDocker();
250
- }
251
- this.logger.log("INFO", "Uploading statics");
252
- // Upload any Statics
253
- yield this.uploadStatics();
254
- // Dynamicly call each methods
255
- for (let i in this.resources) {
256
- if (this[i] && typeof this[i] === "function") {
257
- this.logger.log("TRACE", "Add CloudFormation Resource", i);
258
- yield this[i]();
259
- }
184
+ async deploy() {
185
+ const { Description } = this.resources;
186
+ this.template = {
187
+ Description,
188
+ Resources: { ...this.resources.CustomResources }
189
+ };
190
+ this.result = {};
191
+ // Ensure S3 bucket exist
192
+ this.logger.log("DEBUG", "Check assets bucket", this.resources.AssetsBucket);
193
+ await this.createBucket(this.resources.AssetsBucket);
194
+ // Check if we need OpenAPI export
195
+ let openapi = await this.completeOpenAPI(this.manager.getWebda().exportOpenAPI(false));
196
+ this.openapiS3Object = this.getStringified(openapi, this.resources.OpenAPIFileName);
197
+ await this.putFilesOnBucket(this.resources.AssetsBucket, [this.openapiS3Object]);
198
+ // If APIGatewayImportOpenApi update REST API
199
+ if (this.resources.APIGatewayImportOpenApi) {
200
+ this.logger.log("INFO", "Importing open api");
201
+ await this.importOpenApi(openapi);
202
+ }
203
+ // Build Docker if needed
204
+ if (this.resources.Docker && this.resources.Docker.tag) {
205
+ this.logger.log("INFO", "Building Docker image", this.resources.Docker.tag);
206
+ await this.buildDocker();
207
+ }
208
+ this.logger.log("INFO", "Uploading statics");
209
+ // Upload any Statics
210
+ await this.uploadStatics();
211
+ // Dynamicly call each methods
212
+ for (let i in this.resources) {
213
+ if (this[i] && typeof this[i] === "function") {
214
+ this.logger.log("TRACE", "Add CloudFormation Resource", i);
215
+ await this[i]();
260
216
  }
261
- // Add any static
262
- for (let i in this.resources.Statics) {
263
- this.logger.log("TRACE", "Add Static Resource", i);
264
- yield this.createStatic(this.resources.Statics[i]);
265
- }
266
- this.logger.log("INFO", "Deploy with CloudFormation");
267
- // Upload new version it
268
- yield this.sendCloudFormationTemplate();
269
- // Load the stack
270
- yield this.createCloudFormation();
271
- return this.result;
272
- });
217
+ }
218
+ // Add any static
219
+ for (let i in this.resources.Statics) {
220
+ this.logger.log("TRACE", "Add Static Resource", i);
221
+ await this.createStatic(this.resources.Statics[i]);
222
+ }
223
+ this.logger.log("INFO", "Deploy with CloudFormation");
224
+ // Upload new version it
225
+ await this.sendCloudFormationTemplate();
226
+ // Load the stack
227
+ await this.createCloudFormation();
228
+ return this.result;
273
229
  }
274
230
  /**
275
231
  * Upload any asset to bucket
276
232
  */
277
- uploadStatics() {
278
- return __awaiter(this, void 0, void 0, function* () {
279
- for (let i in this.resources.Statics) {
280
- const { Source, AssetsPath } = this.resources.Statics[i];
281
- yield this.putFolderOnBucket(this.resources.AssetsBucket, this.manager.getApplication().getAppPath(Source), AssetsPath);
282
- }
283
- });
233
+ async uploadStatics() {
234
+ for (let i in this.resources.Statics) {
235
+ const { Source, AssetsPath } = this.resources.Statics[i];
236
+ await this.putFolderOnBucket(this.resources.AssetsBucket, this.manager.getApplication().getAppPath(Source), AssetsPath);
237
+ }
284
238
  }
285
- createStatic(info) {
286
- return __awaiter(this, void 0, void 0, function* () {
287
- const { DomainName, CloudFront, Bucket } = info;
288
- info.Bucket = info.Bucket || {};
289
- // Create bucket
290
- let resPrefix = `Static${DomainName.replace(/\./g, "")}`;
291
- if (Bucket) {
292
- this.template.Resources[`${resPrefix}Bucket`] = {
293
- Type: "AWS::S3::Bucket",
294
- Properties: Object.assign(Object.assign({}, info.Bucket), { BucketName: DomainName, Tags: this.getDefaultTags(info.Bucket.Tags) })
295
- };
296
- }
297
- if (CloudFront) {
298
- if (!CloudFront.DistributionConfig.ViewerCertificate) {
299
- CloudFront.DistributionConfig.ViewerCertificate = {
300
- AcmCertificateArn: (yield this.getCertificate(DomainName)).CertificateArn,
301
- SslSupportMethod: "sni-only"
302
- };
239
+ async createStatic(info) {
240
+ const { DomainName, CloudFront, Bucket } = info;
241
+ info.Bucket = info.Bucket || {};
242
+ // Create bucket
243
+ let resPrefix = `Static${DomainName.replace(/\./g, "")}`;
244
+ if (Bucket) {
245
+ this.template.Resources[`${resPrefix}Bucket`] = {
246
+ Type: "AWS::S3::Bucket",
247
+ Properties: {
248
+ ...info.Bucket,
249
+ BucketName: DomainName,
250
+ Tags: this.getDefaultTags(info.Bucket.Tags)
303
251
  }
304
- this.template.Resources[`${resPrefix}CloudFront`] = {
305
- Type: "AWS::CloudFront::Distribution",
306
- Properties: {
307
- DistributionConfig: CloudFront.DistributionConfig,
308
- Tags: this.getDefaultTags(info.CloudFront.Tags)
309
- }
252
+ };
253
+ }
254
+ if (CloudFront) {
255
+ if (!CloudFront.DistributionConfig.ViewerCertificate) {
256
+ CloudFront.DistributionConfig.ViewerCertificate = {
257
+ AcmCertificateArn: (await this.getCertificate(DomainName)).CertificateArn,
258
+ SslSupportMethod: "sni-only"
310
259
  };
311
- yield this.createCloudFormationDNSEntry({ "Fn::GetAtt": [`${resPrefix}CloudFront`, "DomainName"] }, DomainName, "Z2FDTNDATAQYW2" // Constant as seen here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget-1.html#cfn-route53-aliastarget-hostedzoneid
312
- );
313
260
  }
314
- });
261
+ this.template.Resources[`${resPrefix}CloudFront`] = {
262
+ Type: "AWS::CloudFront::Distribution",
263
+ Properties: {
264
+ DistributionConfig: CloudFront.DistributionConfig,
265
+ Tags: this.getDefaultTags(info.CloudFront.Tags)
266
+ }
267
+ };
268
+ await this.createCloudFormationDNSEntry({ "Fn::GetAtt": [`${resPrefix}CloudFront`, "DomainName"] }, DomainName, "Z2FDTNDATAQYW2" // Constant as seen here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget-1.html#cfn-route53-aliastarget-hostedzoneid
269
+ );
270
+ }
315
271
  }
316
272
  /**
317
273
  * Copy the CloudFormation template to the Assets bucket
318
274
  */
319
- sendCloudFormationTemplate() {
320
- return __awaiter(this, void 0, void 0, function* () {
321
- let res = this.getStringified(this.template, this.resources.FileName);
322
- this.result.CloudFormation = {
323
- Bucket: this.resources.AssetsBucket,
324
- Key: res.key
325
- };
326
- this.result.CloudFormationContent = res.src.toString();
327
- yield this.putFilesOnBucket(this.resources.AssetsBucket, [res]);
328
- });
275
+ async sendCloudFormationTemplate() {
276
+ let res = this.getStringified(this.template, this.resources.FileName);
277
+ this.result.CloudFormation = {
278
+ Bucket: this.resources.AssetsBucket,
279
+ Key: res.key
280
+ };
281
+ this.result.CloudFormationContent = res.src.toString();
282
+ await this.putFilesOnBucket(this.resources.AssetsBucket, [res]);
329
283
  }
330
284
  /**
331
285
  * Delete the CloudFormation stack
332
286
  * @returns
333
287
  */
334
- deleteCloudFormation() {
335
- return __awaiter(this, void 0, void 0, function* () {
336
- let cloudformation = new client_cloudformation_1.CloudFormation({});
337
- yield cloudformation.deleteStack({ StackName: this.resources.StackName });
338
- return this.waitFor((resolve) => __awaiter(this, void 0, void 0, function* () {
339
- try {
340
- yield cloudformation.describeStacks({ StackName: this.resources.StackName });
341
- }
342
- catch (err) {
343
- resolve();
344
- return true;
345
- }
346
- }), 50, "Waiting on stack to be deleted", 5000);
347
- });
288
+ async deleteCloudFormation() {
289
+ let cloudformation = new CloudFormation({});
290
+ await cloudformation.deleteStack({ StackName: this.resources.StackName });
291
+ return this.waitFor(async (resolve) => {
292
+ try {
293
+ await cloudformation.describeStacks({ StackName: this.resources.StackName });
294
+ }
295
+ catch (err) {
296
+ resolve();
297
+ return true;
298
+ }
299
+ }, 50, "Waiting on stack to be deleted", 5000);
348
300
  }
349
301
  /**
350
302
  *
@@ -353,36 +305,32 @@ class CloudFormationDeployer extends _1.AWSDeployer {
353
305
  * @param HostedZoneId
354
306
  * @returns
355
307
  */
356
- createCloudFormationDNSEntry(ref, domain, HostedZoneId) {
357
- return __awaiter(this, void 0, void 0, function* () {
358
- let zone = yield this.getZoneForDomainName(domain);
359
- if (!zone) {
360
- this.logger.log("WARN", "Cannot find Route53 zone for", domain, ", you will have to create manually the CNAME");
361
- return;
362
- }
363
- // Possible conflict if my.name.domain.io and myn.ame.domain.io exists
364
- this.template.Resources[`DNSEntry${domain.replace(/\./g, "")}`] = {
365
- Type: "AWS::Route53::RecordSet",
366
- Properties: {
367
- AliasTarget: { DNSName: ref, HostedZoneId },
368
- Comment: "Created by @webda/aws/cloudformation",
369
- Type: "A",
370
- Name: domain,
371
- HostedZoneId: zone.Id
372
- }
373
- };
374
- });
308
+ async createCloudFormationDNSEntry(ref, domain, HostedZoneId) {
309
+ let zone = await this.getZoneForDomainName(domain);
310
+ if (!zone) {
311
+ this.logger.log("WARN", "Cannot find Route53 zone for", domain, ", you will have to create manually the CNAME");
312
+ return;
313
+ }
314
+ // Possible conflict if my.name.domain.io and myn.ame.domain.io exists
315
+ this.template.Resources[`DNSEntry${domain.replace(/\./g, "")}`] = {
316
+ Type: "AWS::Route53::RecordSet",
317
+ Properties: {
318
+ AliasTarget: { DNSName: ref, HostedZoneId },
319
+ Comment: "Created by @webda/aws/cloudformation",
320
+ Type: "A",
321
+ Name: domain,
322
+ HostedZoneId: zone.Id
323
+ }
324
+ };
375
325
  }
376
- importOpenApi(openapi) {
377
- return __awaiter(this, void 0, void 0, function* () {
378
- let apigateway = new client_api_gateway_1.APIGateway({});
379
- console.log("Creating API Gateway");
380
- yield apigateway.putRestApi({
381
- body: Buffer.from(JSON.stringify(openapi)),
382
- failOnWarnings: false,
383
- restApiId: this.resources.APIGatewayImportOpenApi,
384
- mode: "overwrite"
385
- });
326
+ async importOpenApi(openapi) {
327
+ let apigateway = new APIGateway({});
328
+ console.log("Creating API Gateway");
329
+ await apigateway.putRestApi({
330
+ body: Buffer.from(JSON.stringify(openapi)),
331
+ failOnWarnings: false,
332
+ restApiId: this.resources.APIGatewayImportOpenApi,
333
+ mode: "overwrite"
386
334
  });
387
335
  }
388
336
  /**
@@ -390,213 +338,229 @@ class CloudFormationDeployer extends _1.AWSDeployer {
390
338
  * @param cloudformation
391
339
  * @returns
392
340
  */
393
- createCloudFormationChangeSet(cloudformation) {
394
- return __awaiter(this, void 0, void 0, function* () {
395
- let changeSetParams = Object.assign(Object.assign({}, this.resources.StackOptions), { StackName: this.resources.StackName, ChangeSetName: "WebdaCloudFormationDeployer", Capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"], Tags: this.getDefaultTags("StackOptions"), TemplateURL: `https://${this.result.CloudFormation.Bucket}.s3.amazonaws.com/${this.result.CloudFormation.Key}`, ResourcesToImport: this.resources.ResourcesToImport });
396
- let changeSet;
397
- try {
398
- changeSet = yield cloudformation.createChangeSet(Object.assign(Object.assign({}, changeSetParams), { ChangeSetType: this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE" }));
341
+ async createCloudFormationChangeSet(cloudformation) {
342
+ let changeSetParams = {
343
+ ...this.resources.StackOptions,
344
+ StackName: this.resources.StackName,
345
+ ChangeSetName: "WebdaCloudFormationDeployer",
346
+ Capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
347
+ Tags: this.getDefaultTags("StackOptions"),
348
+ TemplateURL: `https://${this.result.CloudFormation.Bucket}.s3.amazonaws.com/${this.result.CloudFormation.Key}`,
349
+ ResourcesToImport: this.resources.ResourcesToImport
350
+ };
351
+ let changeSet;
352
+ try {
353
+ changeSet = await cloudformation.createChangeSet({
354
+ ...changeSetParams,
355
+ ChangeSetType: this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE"
356
+ });
357
+ }
358
+ catch (err) {
359
+ if (err.message.endsWith(" is in ROLLBACK_COMPLETE state and can not be updated.")) {
360
+ this.logger.log("WARN", "Deleting buguous stack");
361
+ await this.deleteCloudFormation();
362
+ changeSet = await cloudformation.createChangeSet({
363
+ ...changeSetParams,
364
+ ChangeSetType: this.resources.ChangeSetType
365
+ });
399
366
  }
400
- catch (err) {
401
- if (err.message.endsWith(" is in ROLLBACK_COMPLETE state and can not be updated.")) {
402
- this.logger.log("WARN", "Deleting buguous stack");
403
- yield this.deleteCloudFormation();
404
- changeSet = yield cloudformation.createChangeSet(Object.assign(Object.assign({}, changeSetParams), { ChangeSetType: this.resources.ChangeSetType }));
405
- }
406
- else if (err.message === `Stack [${this.resources.StackName}] does not exist`) {
407
- changeSet = yield cloudformation.createChangeSet(Object.assign(Object.assign({}, changeSetParams), { ChangeSetType: this.resources.ChangeSetType }));
408
- }
409
- else if (err.message.endsWith(" state and can not be updated.")) {
410
- yield this.waitFor((resolve) => __awaiter(this, void 0, void 0, function* () {
411
- let res = yield cloudformation.describeStacks({
412
- StackName: this.resources.StackName
413
- });
414
- if (res.Stacks.length === 0) {
415
- // If it disapeared, recreate
416
- changeSet = yield cloudformation.createChangeSet(Object.assign(Object.assign({}, changeSetParams), { ChangeSetType: this.resources.ChangeSetType }));
417
- resolve();
418
- return true;
419
- }
420
- if (res.Stacks[0].StackStatus.endsWith("COMPLETE")) {
421
- changeSet = yield cloudformation.createChangeSet(Object.assign(Object.assign({}, changeSetParams), { ChangeSetType: this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE" }));
422
- resolve();
423
- return true;
424
- }
425
- return false;
426
- }), 50, "Waiting for COMPLETE state", 5000);
427
- }
428
- else if (err.code === "AlreadyExistsException") {
429
- this.logger.log("WARN", "ChangeSet exists and need to be clean");
430
- yield cloudformation.deleteChangeSet({
431
- StackName: this.resources.StackName,
432
- ChangeSetName: "WebdaCloudFormationDeployer"
367
+ else if (err.message === `Stack [${this.resources.StackName}] does not exist`) {
368
+ changeSet = await cloudformation.createChangeSet({
369
+ ...changeSetParams,
370
+ ChangeSetType: this.resources.ChangeSetType
371
+ });
372
+ }
373
+ else if (err.message.endsWith(" state and can not be updated.")) {
374
+ await this.waitFor(async (resolve) => {
375
+ let res = await cloudformation.describeStacks({
376
+ StackName: this.resources.StackName
433
377
  });
434
- changeSet = yield cloudformation.createChangeSet(Object.assign(Object.assign({}, changeSetParams), { ChangeSetType: this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE" }));
435
- }
436
- else {
437
- throw err;
438
- }
378
+ if (res.Stacks.length === 0) {
379
+ // If it disapeared, recreate
380
+ changeSet = await cloudformation.createChangeSet({
381
+ ...changeSetParams,
382
+ ChangeSetType: this.resources.ChangeSetType
383
+ });
384
+ resolve();
385
+ return true;
386
+ }
387
+ if (res.Stacks[0].StackStatus.endsWith("COMPLETE")) {
388
+ changeSet = await cloudformation.createChangeSet({
389
+ ...changeSetParams,
390
+ ChangeSetType: this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE"
391
+ });
392
+ resolve();
393
+ return true;
394
+ }
395
+ return false;
396
+ }, 50, "Waiting for COMPLETE state", 5000);
397
+ }
398
+ else if (err.code === "AlreadyExistsException") {
399
+ this.logger.log("WARN", "ChangeSet exists and need to be clean");
400
+ await cloudformation.deleteChangeSet({
401
+ StackName: this.resources.StackName,
402
+ ChangeSetName: "WebdaCloudFormationDeployer"
403
+ });
404
+ changeSet = await cloudformation.createChangeSet({
405
+ ...changeSetParams,
406
+ ChangeSetType: this.resources.ChangeSetType === "IMPORT" ? "IMPORT" : "UPDATE"
407
+ });
439
408
  }
440
- return changeSet;
441
- });
409
+ else {
410
+ throw err;
411
+ }
412
+ }
413
+ return changeSet;
442
414
  }
443
415
  /**
444
416
  * Upload and create the cloudformation stack or update it
445
417
  * @returns
446
418
  */
447
- createCloudFormation() {
448
- return __awaiter(this, void 0, void 0, function* () {
449
- let cloudformation = new client_cloudformation_1.CloudFormation({});
450
- let changeSet = yield this.createCloudFormationChangeSet(cloudformation);
451
- // Wait for change set
452
- this.logger.log("TRACE", `ChangeSet: ${changeSet}`);
453
- // It will trigger an exception if timeout
454
- let changes = yield this.waitFor((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
455
- let localChanges = yield cloudformation.describeChangeSet({
456
- ChangeSetName: "WebdaCloudFormationDeployer",
457
- StackName: this.resources.StackName
458
- });
459
- if (localChanges.Status === "FAILED" || localChanges.Status === "CREATE_COMPLETE") {
460
- resolve(localChanges);
461
- return true;
462
- }
463
- if (localChanges.Status === "ROLLBACK_COMPLETE") {
464
- reject();
465
- }
466
- }), 50, "Waiting for ChangeSet to be ready...", 5000);
467
- if (changes.Status === "FAILED") {
468
- if (changes.StatusReason ===
469
- "The submitted information didn't contain changes. Submit different information to create a change set.") {
470
- this.logger.log("INFO", "No changes to be made");
471
- }
472
- else {
473
- this.logger.log("ERROR", "Cannot execute ChangeSet:", changes.StatusReason);
474
- }
475
- return;
476
- }
477
- changes.Changes.filter(j => j.Type === "Resource").forEach(({ ResourceChange: info }) => this.logger.log("INFO", `${info.Action.toUpperCase().padEnd(38)} ${info.ResourceType.padEnd(30)} ${info.LogicalResourceId}`));
478
- this.logger.log("INFO", "Executing Change Set");
479
- let lastEvent = (yield cloudformation.describeStackEvents({ StackName: this.resources.StackName })).StackEvents.shift();
480
- yield cloudformation.executeChangeSet({
419
+ async createCloudFormation() {
420
+ let cloudformation = new CloudFormation({});
421
+ let changeSet = await this.createCloudFormationChangeSet(cloudformation);
422
+ // Wait for change set
423
+ this.logger.log("TRACE", `ChangeSet: ${changeSet}`);
424
+ // It will trigger an exception if timeout
425
+ let changes = await this.waitFor(async (resolve, reject) => {
426
+ let localChanges = await cloudformation.describeChangeSet({
481
427
  ChangeSetName: "WebdaCloudFormationDeployer",
482
428
  StackName: this.resources.StackName
483
429
  });
484
- // Wait for the completion of change and display events in the meantime
485
- this.logger.log("INFO", "Waiting for update completion");
486
- let i = 0;
487
- let Timeout = true;
488
- do {
489
- let events = (yield cloudformation.describeStackEvents({ StackName: this.resources.StackName })).StackEvents;
490
- let display = lastEvent ? false : true;
491
- let event;
492
- while ((event = events.pop())) {
493
- if (display) {
494
- this.logger.log("INFO", `${event.ResourceStatus.padEnd(38)} ${event.ResourceType.padEnd(30)} ${event.LogicalResourceId}`);
495
- lastEvent = event;
496
- if (lastEvent.LogicalResourceId === this.resources.StackName &&
497
- (lastEvent.ResourceStatus === "UPDATE_COMPLETE" ||
498
- lastEvent.ResourceStatus === "CREATE_COMPLETE" ||
499
- lastEvent.ResourceStatus === "ROLLBACK_COMPLETE" ||
500
- lastEvent.ResourceStatus === "UPDATE_ROLLBACK_COMPLETE")) {
501
- Timeout = false;
502
- break;
503
- }
504
- }
505
- else if (event.EventId === lastEvent.EventId) {
506
- display = true;
430
+ if (localChanges.Status === "FAILED" || localChanges.Status === "CREATE_COMPLETE") {
431
+ resolve(localChanges);
432
+ return true;
433
+ }
434
+ if (localChanges.Status === "ROLLBACK_COMPLETE") {
435
+ reject();
436
+ }
437
+ }, 50, "Waiting for ChangeSet to be ready...", 5000);
438
+ if (changes.Status === "FAILED") {
439
+ if (changes.StatusReason ===
440
+ "The submitted information didn't contain changes. Submit different information to create a change set.") {
441
+ this.logger.log("INFO", "No changes to be made");
442
+ }
443
+ else {
444
+ this.logger.log("ERROR", "Cannot execute ChangeSet:", changes.StatusReason);
445
+ }
446
+ return;
447
+ }
448
+ changes.Changes.filter(j => j.Type === "Resource").forEach(({ ResourceChange: info }) => this.logger.log("INFO", `${info.Action.toUpperCase().padEnd(38)} ${info.ResourceType.padEnd(30)} ${info.LogicalResourceId}`));
449
+ this.logger.log("INFO", "Executing Change Set");
450
+ let lastEvent = (await cloudformation.describeStackEvents({ StackName: this.resources.StackName })).StackEvents.shift();
451
+ await cloudformation.executeChangeSet({
452
+ ChangeSetName: "WebdaCloudFormationDeployer",
453
+ StackName: this.resources.StackName
454
+ });
455
+ // Wait for the completion of change and display events in the meantime
456
+ this.logger.log("INFO", "Waiting for update completion");
457
+ let i = 0;
458
+ let Timeout = true;
459
+ do {
460
+ let events = (await cloudformation.describeStackEvents({ StackName: this.resources.StackName })).StackEvents;
461
+ let display = lastEvent ? false : true;
462
+ let event;
463
+ while ((event = events.pop())) {
464
+ if (display) {
465
+ this.logger.log("INFO", `${event.ResourceStatus.padEnd(38)} ${event.ResourceType.padEnd(30)} ${event.LogicalResourceId}`);
466
+ lastEvent = event;
467
+ if (lastEvent.LogicalResourceId === this.resources.StackName &&
468
+ (lastEvent.ResourceStatus === "UPDATE_COMPLETE" ||
469
+ lastEvent.ResourceStatus === "CREATE_COMPLETE" ||
470
+ lastEvent.ResourceStatus === "ROLLBACK_COMPLETE" ||
471
+ lastEvent.ResourceStatus === "UPDATE_ROLLBACK_COMPLETE")) {
472
+ Timeout = false;
473
+ break;
507
474
  }
508
475
  }
509
- // If we are done do not pause
510
- if (Timeout) {
511
- yield this.sleep(10);
512
- i++;
476
+ else if (event.EventId === lastEvent.EventId) {
477
+ display = true;
513
478
  }
514
- } while (i < 60 && Timeout);
479
+ }
480
+ // If we are done do not pause
515
481
  if (Timeout) {
516
- this.logger.log("WARN", "Timeout while waiting for stack to update");
517
- return;
518
- }
519
- /*
520
- CloudFormation does not update Stage when resources are modified
521
-
522
- https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update
523
- */
524
- if (this.APIGateway) {
525
- let NextToken = undefined;
526
- let stageName;
527
- let restApiId;
528
- // Retrieve resources
529
- do {
530
- let res = yield cloudformation.listStackResources({ StackName: this.resources.StackName, NextToken });
531
- NextToken = res.NextToken;
532
- res.StackResourceSummaries.forEach(resource => {
533
- if (resource.ResourceType === "AWS::ApiGateway::Stage") {
534
- stageName = resource.PhysicalResourceId;
535
- }
536
- else if (resource.ResourceType === "AWS::ApiGateway::RestApi") {
537
- restApiId = resource.PhysicalResourceId;
538
- }
539
- });
540
- } while (NextToken);
541
- // Get RestAPIId
542
- if (restApiId && stageName) {
543
- const gw = new client_api_gateway_1.APIGateway({});
544
- yield gw.createDeployment({
545
- restApiId,
546
- stageName
547
- });
548
- }
482
+ await this.sleep(10);
483
+ i++;
549
484
  }
550
- });
485
+ } while (i < 60 && Timeout);
486
+ if (Timeout) {
487
+ this.logger.log("WARN", "Timeout while waiting for stack to update");
488
+ return;
489
+ }
490
+ /*
491
+ CloudFormation does not update Stage when resources are modified
492
+
493
+ https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update
494
+ */
495
+ if (this.APIGateway) {
496
+ let NextToken = undefined;
497
+ let stageName;
498
+ let restApiId;
499
+ // Retrieve resources
500
+ do {
501
+ let res = await cloudformation.listStackResources({ StackName: this.resources.StackName, NextToken });
502
+ NextToken = res.NextToken;
503
+ res.StackResourceSummaries.forEach(resource => {
504
+ if (resource.ResourceType === "AWS::ApiGateway::Stage") {
505
+ stageName = resource.PhysicalResourceId;
506
+ }
507
+ else if (resource.ResourceType === "AWS::ApiGateway::RestApi") {
508
+ restApiId = resource.PhysicalResourceId;
509
+ }
510
+ });
511
+ } while (NextToken);
512
+ // Get RestAPIId
513
+ if (restApiId && stageName) {
514
+ const gw = new APIGateway({});
515
+ await gw.createDeployment({
516
+ restApiId,
517
+ stageName
518
+ });
519
+ }
520
+ }
551
521
  }
552
522
  /**
553
523
  * Pause for x seconds
554
524
  * @param seconds
555
525
  */
556
- sleep(sec) {
557
- return __awaiter(this, void 0, void 0, function* () {
558
- yield new Promise(resolve => setTimeout(resolve, sec * 1000));
559
- });
526
+ async sleep(sec) {
527
+ await new Promise(resolve => setTimeout(resolve, sec * 1000));
560
528
  }
561
- Resources() {
562
- return __awaiter(this, void 0, void 0, function* () {
563
- let services = this.manager.getWebda().getServices();
564
- // Build policy
565
- for (let i in services) {
566
- if ("getCloudFormation" in services[i]) {
567
- // Update to match recuring policy - might need to split if policy too big
568
- let res = services[i].getCloudFormation(this);
569
- for (let j in res) {
570
- this.template.Resources[`Service${i}_${j}`] = res[j];
571
- }
529
+ async Resources() {
530
+ let services = this.manager.getWebda().getServices();
531
+ // Build policy
532
+ for (let i in services) {
533
+ if ("getCloudFormation" in services[i]) {
534
+ // Update to match recuring policy - might need to split if policy too big
535
+ let res = services[i].getCloudFormation(this);
536
+ for (let j in res) {
537
+ this.template.Resources[`Service${i}_${j}`] = res[j];
572
538
  }
573
539
  }
574
- });
540
+ }
575
541
  }
576
542
  getRegion() {
577
543
  return "us-east-1";
578
544
  }
579
- completeOpenAPI(openapi) {
580
- return __awaiter(this, void 0, void 0, function* () {
581
- openapi.info.title = this.resources.OpenAPITitle;
582
- let info = yield this.getAWSIdentity();
583
- let arn = `arn:aws:lambda:${this.getRegion()}:${info.Account}:function:${this.resources.Lambda.FunctionName}`;
584
- for (let p in openapi.paths) {
585
- // Not using mockCors as the {@link RequestFilter.checkRequest} can be dynamic
586
- // Invalid mapping expression parameter specified: method.response.header.Access-Control-Allow-Credentials
587
- if (!openapi.paths[p]["options"]) {
588
- openapi.paths[p]["options"] = {};
589
- }
590
- for (let m in openapi.paths[p]) {
591
- openapi.paths[p][m]["x-amazon-apigateway-integration"] = {
592
- httpMethod: "POST",
593
- uri: `arn:aws:apigateway:${this.getRegion()}:lambda:path/2015-03-31/functions/${arn}/invocations`,
594
- type: "aws_proxy"
595
- };
596
- }
545
+ async completeOpenAPI(openapi) {
546
+ openapi.info.title = this.resources.OpenAPITitle;
547
+ let info = await this.getAWSIdentity();
548
+ let arn = `arn:aws:lambda:${this.getRegion()}:${info.Account}:function:${this.resources.Lambda.FunctionName}`;
549
+ for (let p in openapi.paths) {
550
+ // Not using mockCors as the {@link RequestFilter.checkRequest} can be dynamic
551
+ // Invalid mapping expression parameter specified: method.response.header.Access-Control-Allow-Credentials
552
+ if (!openapi.paths[p]["options"]) {
553
+ openapi.paths[p]["options"] = {};
554
+ }
555
+ for (let m in openapi.paths[p]) {
556
+ openapi.paths[p][m]["x-amazon-apigateway-integration"] = {
557
+ httpMethod: "POST",
558
+ uri: `arn:aws:apigateway:${this.getRegion()}:lambda:path/2015-03-31/functions/${arn}/invocations`,
559
+ type: "aws_proxy"
560
+ };
597
561
  }
598
- return openapi;
599
- });
562
+ }
563
+ return openapi;
600
564
  }
601
565
  getStringified(object, filename, addPrefix = true) {
602
566
  let key = addPrefix ? `${this.resources.AssetsPrefix}${filename}` : filename;
@@ -630,81 +594,98 @@ class CloudFormationDeployer extends _1.AWSDeployer {
630
594
  src
631
595
  };
632
596
  }
633
- APIGateway() {
634
- return __awaiter(this, void 0, void 0, function* () {
635
- this.template.Resources.APIGateway = {
636
- Type: "AWS::ApiGateway::RestApi",
637
- Properties: Object.assign(Object.assign({}, this.resources.APIGateway), { Tags: this.getDefaultTags("APIGateway"), BodyS3Location: {
638
- Bucket: this.resources.AssetsBucket,
639
- Key: this.openapiS3Object.key
640
- } }),
641
- DependsOn: "LambdaFunction"
642
- };
643
- this.template.Resources.LambdaApiGatewayPermission = {
644
- Type: "AWS::Lambda::Permission",
645
- Properties: {
646
- Action: "lambda:InvokeFunction",
647
- FunctionName: this.resources.Lambda.FunctionName,
648
- Principal: "apigateway.amazonaws.com",
649
- SourceArn: {
650
- "Fn::Join": [
651
- ":",
652
- [
653
- "arn:aws:execute-api",
654
- { Ref: "AWS::Region" },
655
- { Ref: "AWS::AccountId" },
656
- { "Fn::Join": ["", [{ Ref: "APIGateway" }, "/*"]] }
657
- ]
597
+ async APIGateway() {
598
+ this.template.Resources.APIGateway = {
599
+ Type: "AWS::ApiGateway::RestApi",
600
+ Properties: {
601
+ ...this.resources.APIGateway,
602
+ Tags: this.getDefaultTags("APIGateway"),
603
+ BodyS3Location: {
604
+ Bucket: this.resources.AssetsBucket,
605
+ Key: this.openapiS3Object.key
606
+ }
607
+ },
608
+ DependsOn: "LambdaFunction"
609
+ };
610
+ this.template.Resources.LambdaApiGatewayPermission = {
611
+ Type: "AWS::Lambda::Permission",
612
+ Properties: {
613
+ Action: "lambda:InvokeFunction",
614
+ FunctionName: this.resources.Lambda.FunctionName,
615
+ Principal: "apigateway.amazonaws.com",
616
+ SourceArn: {
617
+ "Fn::Join": [
618
+ ":",
619
+ [
620
+ "arn:aws:execute-api",
621
+ { Ref: "AWS::Region" },
622
+ { Ref: "AWS::AccountId" },
623
+ { "Fn::Join": ["", [{ Ref: "APIGateway" }, "/*"]] }
658
624
  ]
659
- }
660
- },
661
- DependsOn: "LambdaFunction"
662
- };
663
- this.template.Resources.APIGatewayDeployment = {
664
- Type: "AWS::ApiGateway::Deployment",
665
- Properties: Object.assign(Object.assign({}, this.resources.APIGatewayDeployment), { RestApiId: { Ref: "APIGateway" } })
666
- };
667
- // SourceArn: "arn:aws:execute-api:" + AWS.config.region + ":" + awsId + ":" + this.restApiId + "/*"
668
- this.template.Resources.APIGatewayStage = {
669
- Type: "AWS::ApiGateway::Stage",
670
- Properties: Object.assign(Object.assign({}, this.resources.APIGatewayStage), { Tags: this.getDefaultTags("APIGatewayStage"), DeploymentId: { Ref: "APIGatewayDeployment" }, RestApiId: { Ref: "APIGateway" } })
671
- };
672
- });
673
- }
674
- APIGatewayDomain() {
675
- return __awaiter(this, void 0, void 0, function* () {
676
- let region;
677
- if (this.resources.APIGatewayDomain.EndpointConfiguration) {
678
- if (this.resources.APIGatewayDomain.EndpointConfiguration.Types.indexOf("EDGE") >= 0) {
679
- region = "us-east-1";
625
+ ]
680
626
  }
627
+ },
628
+ DependsOn: "LambdaFunction"
629
+ };
630
+ this.template.Resources.APIGatewayDeployment = {
631
+ Type: "AWS::ApiGateway::Deployment",
632
+ Properties: {
633
+ ...this.resources.APIGatewayDeployment,
634
+ RestApiId: { Ref: "APIGateway" }
681
635
  }
682
- else {
636
+ };
637
+ // SourceArn: "arn:aws:execute-api:" + AWS.config.region + ":" + awsId + ":" + this.restApiId + "/*"
638
+ this.template.Resources.APIGatewayStage = {
639
+ Type: "AWS::ApiGateway::Stage",
640
+ Properties: {
641
+ ...this.resources.APIGatewayStage,
642
+ Tags: this.getDefaultTags("APIGatewayStage"),
643
+ DeploymentId: { Ref: "APIGatewayDeployment" },
644
+ RestApiId: { Ref: "APIGateway" }
645
+ }
646
+ };
647
+ }
648
+ async APIGatewayDomain() {
649
+ let region;
650
+ if (this.resources.APIGatewayDomain.EndpointConfiguration) {
651
+ if (this.resources.APIGatewayDomain.EndpointConfiguration.Types.indexOf("EDGE") >= 0) {
683
652
  region = "us-east-1";
684
653
  }
685
- if (!this.resources.APIGatewayDomain.CertificateArn) {
686
- this.resources.APIGatewayDomain.CertificateArn = (yield this.getCertificate(this.resources.APIGatewayDomain.DomainName, region)).CertificateArn;
654
+ }
655
+ else {
656
+ region = "us-east-1";
657
+ }
658
+ if (!this.resources.APIGatewayDomain.CertificateArn) {
659
+ this.resources.APIGatewayDomain.CertificateArn = (await this.getCertificate(this.resources.APIGatewayDomain.DomainName, region)).CertificateArn;
660
+ }
661
+ this.template.Resources.APIGatewayDomain = {
662
+ Type: "AWS::ApiGateway::DomainName",
663
+ Properties: {
664
+ ...this.resources.APIGatewayDomain,
665
+ Tags: this.getDefaultTags("APIGatewayDomain")
687
666
  }
688
- this.template.Resources.APIGatewayDomain = {
689
- Type: "AWS::ApiGateway::DomainName",
690
- Properties: Object.assign(Object.assign({}, this.resources.APIGatewayDomain), { Tags: this.getDefaultTags("APIGatewayDomain") })
691
- };
692
- this.template.Resources.APIGatewayBasePathMapping = {
693
- Type: "AWS::ApiGateway::BasePathMapping",
694
- Properties: Object.assign(Object.assign({}, this.resources.APIGatewayBasePathMapping), { DomainName: { Ref: "APIGatewayDomain" }, RestApiId: { Ref: "APIGateway" }, Stage: { Ref: "APIGatewayStage" } })
695
- };
696
- // Should do conditional with RegionalDomainName/RegionalHostedZoneId
697
- yield this.createCloudFormationDNSEntry({ "Fn::GetAtt": ["APIGatewayDomain", "DistributionDomainName"] }, this.resources.APIGatewayDomain.DomainName, { "Fn::GetAtt": ["APIGatewayDomain", "DistributionHostedZoneId"] });
698
- });
667
+ };
668
+ this.template.Resources.APIGatewayBasePathMapping = {
669
+ Type: "AWS::ApiGateway::BasePathMapping",
670
+ Properties: {
671
+ ...this.resources.APIGatewayBasePathMapping,
672
+ DomainName: { Ref: "APIGatewayDomain" },
673
+ RestApiId: { Ref: "APIGateway" },
674
+ Stage: { Ref: "APIGatewayStage" }
675
+ }
676
+ };
677
+ // Should do conditional with RegionalDomainName/RegionalHostedZoneId
678
+ await this.createCloudFormationDNSEntry({ "Fn::GetAtt": ["APIGatewayDomain", "DistributionDomainName"] }, this.resources.APIGatewayDomain.DomainName, { "Fn::GetAtt": ["APIGatewayDomain", "DistributionHostedZoneId"] });
699
679
  }
700
- Policy() {
701
- return __awaiter(this, void 0, void 0, function* () {
702
- let PolicyDocument = JSON.stringify(yield this.getPolicyDocument(this.resources.Policy.PolicyDocument.Statement), undefined, 2);
703
- this.template.Resources.Policy = {
704
- Type: "AWS::IAM::Policy",
705
- Properties: Object.assign(Object.assign({}, this.resources.Policy), { PolicyDocument })
706
- };
707
- });
680
+ async Policy() {
681
+ let PolicyDocument = JSON.stringify(await this.getPolicyDocument(this.resources.Policy.PolicyDocument.Statement), undefined, 2);
682
+ this.template.Resources.Policy = {
683
+ Type: "AWS::IAM::Policy",
684
+ Properties: {
685
+ ...this.resources.Policy,
686
+ PolicyDocument
687
+ }
688
+ };
708
689
  }
709
690
  addAssumeRolePolicyStatement(...statements) {
710
691
  // If we have a Role generation only
@@ -712,67 +693,68 @@ class CloudFormationDeployer extends _1.AWSDeployer {
712
693
  this.resources.Role.AssumeRolePolicyDocument.Statement.push(...statements);
713
694
  }
714
695
  }
715
- Role() {
716
- return __awaiter(this, void 0, void 0, function* () {
717
- // add auto generation
718
- let AssumeRolePolicyDocument = JSON.stringify(this.resources.Role.AssumeRolePolicyDocument, undefined, 2);
719
- this.template.Resources.Role = {
720
- Type: "AWS::IAM::Role",
721
- Properties: Object.assign(Object.assign({}, this.resources.Role), { AssumeRolePolicyDocument, Tags: this.getDefaultTags("Role") })
722
- };
723
- });
696
+ async Role() {
697
+ // add auto generation
698
+ let AssumeRolePolicyDocument = JSON.stringify(this.resources.Role.AssumeRolePolicyDocument, undefined, 2);
699
+ this.template.Resources.Role = {
700
+ Type: "AWS::IAM::Role",
701
+ Properties: {
702
+ ...this.resources.Role,
703
+ AssumeRolePolicyDocument,
704
+ Tags: this.getDefaultTags("Role")
705
+ }
706
+ };
724
707
  }
725
- Lambda() {
726
- return __awaiter(this, void 0, void 0, function* () {
727
- const Code = yield this.generateLambdaPackage();
728
- this.addAssumeRolePolicyStatement({
729
- Effect: "Allow",
730
- Principal: { Service: "lambda.amazonaws.com" },
731
- Action: "sts:AssumeRole"
732
- });
733
- this.template.Resources.LambdaFunction = {
734
- Type: "AWS::Lambda::Function",
735
- Properties: Object.assign(Object.assign({}, this.resources.Lambda), { Code, Tags: this.getDefaultTags("Lambda") })
736
- };
708
+ async Lambda() {
709
+ const Code = await this.generateLambdaPackage();
710
+ this.addAssumeRolePolicyStatement({
711
+ Effect: "Allow",
712
+ Principal: { Service: "lambda.amazonaws.com" },
713
+ Action: "sts:AssumeRole"
737
714
  });
715
+ this.template.Resources.LambdaFunction = {
716
+ Type: "AWS::Lambda::Function",
717
+ Properties: {
718
+ ...this.resources.Lambda,
719
+ Code,
720
+ Tags: this.getDefaultTags("Lambda")
721
+ }
722
+ };
738
723
  }
739
- buildDocker() {
740
- return __awaiter(this, void 0, void 0, function* () {
741
- // Launch the Docker deployment
742
- yield this.manager.run("WebdaDeployer/Docker", Object.assign({}, this.resources.Docker));
724
+ async buildDocker() {
725
+ // Launch the Docker deployment
726
+ await this.manager.run("WebdaDeployer/Docker", {
727
+ ...this.resources.Docker
743
728
  });
744
729
  }
745
- Fargate() {
746
- return __awaiter(this, void 0, void 0, function* () {
747
- this.addAssumeRolePolicyStatement({
748
- Effect: "Allow",
749
- Principal: { Service: "ecs-tasks.amazonaws.com" },
750
- Action: "sts:AssumeRole"
751
- });
730
+ async Fargate() {
731
+ this.addAssumeRolePolicyStatement({
732
+ Effect: "Allow",
733
+ Principal: { Service: "ecs-tasks.amazonaws.com" },
734
+ Action: "sts:AssumeRole"
752
735
  });
753
736
  }
754
- generateLambdaPackage() {
755
- return __awaiter(this, void 0, void 0, function* () {
756
- const { AssetsBucket: S3Bucket, LambdaPackager, AssetsPrefix = "", KeepPackage = false } = this.resources;
757
- const { zipPath: ZipPath } = LambdaPackager;
758
- let result = {
759
- S3Bucket,
760
- S3Key: AssetsPrefix + path.basename(ZipPath)
761
- };
762
- // Create the package
763
- yield this.manager.run("WebdaAWSDeployer/LambdaPackager", LambdaPackager);
764
- // Copy package to S3
765
- yield this.putFilesOnBucket(result.S3Bucket, [
766
- {
767
- key: result.S3Key,
768
- src: ZipPath
769
- }
770
- ]);
771
- if (!KeepPackage) {
772
- fs.unlinkSync(ZipPath);
773
- }
774
- return result;
775
- });
737
+ async generateLambdaPackage() {
738
+ const { AssetsBucket: S3Bucket, LambdaPackager, AssetsPrefix = "", KeepPackage = false } = this.resources;
739
+ const { zipPath: ZipPath } = LambdaPackager;
740
+ let result = {
741
+ S3Bucket,
742
+ S3Key: AssetsPrefix + path.basename(ZipPath)
743
+ };
744
+ // Create the package
745
+ await this.manager.run("WebdaAWSDeployer/LambdaPackager", LambdaPackager);
746
+ // Copy package to S3
747
+ await this.putFilesOnBucket(result.S3Bucket, [
748
+ {
749
+ key: result.S3Key,
750
+ src: ZipPath
751
+ }
752
+ ]);
753
+ /* c8 ignore next 3 */
754
+ if (!KeepPackage) {
755
+ fs.unlinkSync(ZipPath);
756
+ }
757
+ return result;
776
758
  }
777
759
  /**
778
760
  * Init the project on AWS
@@ -787,65 +769,62 @@ class CloudFormationDeployer extends _1.AWSDeployer {
787
769
  * @param console
788
770
  * @returns
789
771
  */
790
- static init(console) {
791
- return __awaiter(this, void 0, void 0, function* () {
792
- let packageDescr = console.app.getAppPath("package.json");
793
- if (!fs.existsSync(packageDescr)) {
794
- console.log("ERROR", "package.json not found");
795
- return -1;
796
- }
797
- let pkg = core_1.JSONUtils.loadFile(packageDescr);
798
- pkg.webda = pkg.webda || {};
799
- let sts = new client_sts_1.STS({});
800
- let identity;
801
- try {
802
- identity = yield sts.getCallerIdentity({});
803
- }
804
- catch (ex) {
805
- console.log("ERROR", "Cannot retrieve your AWS credentials, make sure to have a correct AWS setup");
806
- return -1;
807
- }
808
- let pkgName = (pkg.name || "").replace(/@/g, "").replace(/\//g, "-");
809
- let StackName = `webda-${pkgName}-global`;
810
- if (!pkg.webda.aws) {
811
- console.log("INFO", `This will create a small CloudFormation on your AWS account (${identity.Account}) and region (${sts.config.region || process.env.AWS_DEFAULT_REGION || "us-east-1"})`);
812
- console.log("INFO", `The stack will be called ${StackName}`);
813
- pkg.webda.aws = {
814
- AssetsBucket: `webda-${pkgName}-assets`,
815
- Repository: `webda-${pkgName}`
816
- };
817
- let cloudformation = new client_cloudformation_1.CloudFormation({});
818
- yield cloudformation.createStack({
819
- StackName,
820
- TemplateBody: JSON.stringify({
821
- Resources: {
822
- WebdaAssetsBucket: {
823
- Type: "AWS::S3::Bucket",
824
- Properties: {
825
- BucketName: pkg.webda.aws.AssetsBucket
826
- }
827
- },
828
- WebdaECR: {
829
- Type: "AWS::ECR::Repository",
830
- Properties: {
831
- RepositoryName: pkg.webda.aws.Repository
832
- }
772
+ static async init(console) {
773
+ let packageDescr = console.app.getAppPath("package.json");
774
+ if (!fs.existsSync(packageDescr)) {
775
+ console.log("ERROR", "package.json not found");
776
+ return -1;
777
+ }
778
+ let pkg = JSONUtils.loadFile(packageDescr);
779
+ pkg.webda = pkg.webda || {};
780
+ let sts = new STS({});
781
+ let identity;
782
+ try {
783
+ identity = await sts.getCallerIdentity({});
784
+ }
785
+ catch (ex) {
786
+ console.log("ERROR", "Cannot retrieve your AWS credentials, make sure to have a correct AWS setup");
787
+ return -1;
788
+ }
789
+ let pkgName = (pkg.name || "").replace(/@/g, "").replace(/\//g, "-");
790
+ let StackName = `webda-${pkgName}-global`;
791
+ if (!pkg.webda.aws) {
792
+ console.log("INFO", `This will create a small CloudFormation on your AWS account (${identity.Account}) and region (${sts.config.region || process.env.AWS_DEFAULT_REGION || "us-east-1"})`);
793
+ console.log("INFO", `The stack will be called ${StackName}`);
794
+ pkg.webda.aws = {
795
+ AssetsBucket: `webda-${pkgName}-assets`,
796
+ Repository: `webda-${pkgName}`
797
+ };
798
+ let cloudformation = new CloudFormation({});
799
+ await cloudformation.createStack({
800
+ StackName,
801
+ TemplateBody: JSON.stringify({
802
+ Resources: {
803
+ WebdaAssetsBucket: {
804
+ Type: "AWS::S3::Bucket",
805
+ Properties: {
806
+ BucketName: pkg.webda.aws.AssetsBucket
807
+ }
808
+ },
809
+ WebdaECR: {
810
+ Type: "AWS::ECR::Repository",
811
+ Properties: {
812
+ RepositoryName: pkg.webda.aws.Repository
833
813
  }
834
814
  }
835
- })
836
- });
837
- console.log("INFO", "Updating package description with default information");
838
- core_1.JSONUtils.saveFile(pkg, packageDescr);
839
- return 0;
840
- }
841
- else {
842
- // Check if stack already exists
843
- console.log("WARN", "Default information are already in your package.json");
844
- return -1;
845
- }
846
- });
815
+ }
816
+ })
817
+ });
818
+ console.log("INFO", "Updating package description with default information");
819
+ JSONUtils.saveFile(pkg, packageDescr);
820
+ return 0;
821
+ }
822
+ else {
823
+ // Check if stack already exists
824
+ console.log("WARN", "Default information are already in your package.json");
825
+ return -1;
826
+ }
847
827
  }
848
828
  }
849
- exports.default = CloudFormationDeployer;
850
- exports.CloudFormationDeployer = CloudFormationDeployer;
829
+ export { LAMBDA_LATEST_VERSION, CloudFormationDeployer };
851
830
  //# sourceMappingURL=cloudformation.js.map