serverless-tag-resources 1.2.51 → 3.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.
package/index.js CHANGED
@@ -1,608 +1,93 @@
1
1
  "use strict";
2
- const aws = require("aws-sdk");
2
+
3
+ const { tagResources } = require("./src/template-tagger");
4
+ const { updateTagsPostDeploy } = require("./src/post-deploy-tagger");
5
+ const { validateTags } = require("./src/validation");
6
+ const { configFromProvider } = require("./src/aws-clients");
3
7
 
4
8
  class TagResourcesServerlessPlugin {
5
9
  constructor(serverless, options) {
6
10
  this.serverless = serverless;
7
11
  this.options = options;
8
- this.awsService = this.serverless.getProvider("aws");
9
- this.stage = this.awsService.getStage();
10
- this.region = this.awsService.getRegion();
11
- this.partition = this.awsService.partition || "aws";
12
- aws.config.update({ region: this.region });
13
- const credentials = this.awsService.getCredentials();
14
- this.cfnService = new aws.CloudFormation(credentials);
15
- this.ssmService = new aws.SSM(credentials);
16
- this.iamService = new aws.IAM(credentials);
17
- this.rdsService = new aws.RDS(credentials);
18
- this.pinpointService = new aws.Pinpoint(credentials);
19
- this.apigwv2Service = new aws.ApiGatewayV2(credentials);
20
- this.firehoseService = new aws.Firehose(credentials);
21
- this.ec2Service = new aws.EC2(credentials);
22
-
23
- this.unsupportedTypes = [
24
- "AWS::Lambda::Version",
25
- "AWS::Lambda::EventSourceMapping",
26
- "AWS::Lambda::LayerVersion",
27
- "AWS::Lambda::EventInvokeConfig",
28
- "AWS::Lambda::Alias",
29
- "AWS::Lambda::Permission",
30
- "AWS::Lambda::EventSourceMapping",
31
- "AWS::Lambda::LayerVersionPermission",
32
- "AWS::Lambda::Url",
33
- "AWS::Logs::LogStream",
34
- "AWS::Logs::Destination",
35
- "AWS::Logs::MetricFilter",
36
- "AWS::Logs::QueryDefinition",
37
- "AWS::Logs::ResourcePolicy",
38
- "AWS::Logs::SubscriptionFilter",
39
- "AWS::ApiGateway::Account",
40
- "AWS::ApiGateway::ApiKey",
41
- "AWS::ApiGateway::Method",
42
- "AWS::ApiGateway::Deployment",
43
- "AWS::ApiGateway::UsagePlanKey",
44
- "AWS::ApiGateway::BasePathMapping",
45
- "AWS::ApiGateway::Resource",
46
- "AWS::ApiGateway::Model",
47
- "AWS::ApiGatewayV2::Integration",
48
- "AWS::ApiGatewayV2::Route",
49
- "AWS::ApiGatewayV2::ApiMapping",
50
- "AWS::ApiGatewayV2::ApiGatewayManagedOverrides",
51
- "AWS::ApiGatewayV2::Authorizer",
52
- "AWS::ApiGatewayV2::Deployment",
53
- "AWS::ApiGatewayV2::Integration",
54
- "AWS::ApiGatewayV2::IntegrationResponse",
55
- "AWS::ApiGatewayV2::Model",
56
- "AWS::ApiGatewayV2::Route",
57
- "AWS::ApiGatewayV2::RouteResponse",
58
- "AWS::ApiGateway::RequestValidator",
59
- "AWS::ApiGateway::GatewayResponse",
60
- "AWS::ApiGateway::Authorizer",
61
- "AWS::AppSync::DataSource",
62
- "AWS::AppSync::ApiKey",
63
- "AWS::AppSync::ApiCache",
64
- "AWS::AppSync::DomainName",
65
- "AWS::AppSync::DomainNameApiAssociation",
66
- "AWS::AppSync::FunctionConfiguration",
67
- "AWS::AppSync::GraphQLSchema",
68
- "AWS::AppSync::Resolver",
69
- "AWS::AutoScaling::AutoScalingGroup",
70
- "AWS::Backup::BackupVault",
71
- "AWS::Backup::BackupSelection",
72
- "AWS::Backup::BackupPlan",
73
- "AWS::CodeDeploy::Application",
74
- "AWS::CodeDeploy::DeploymentConfig",
75
- "AWS::Cognito::IdentityPool",
76
- "AWS::Cognito::IdentityPoolRoleAttachment",
77
- "AWS::Cognito::UserPool",
78
- "AWS::Cognito::UserPoolDomain",
79
- "AWS::Cognito::UserPoolClient",
80
- "AWS::Cognito::UserPoolGroup",
81
- "AWS::Cognito::UserPoolUser",
82
- "AWS::Cognito::UserPoolUserToGroupAttachment",
83
- "AWS::Cognito::UserPoolIdentityProvider",
84
- "AWS::Cognito::UserPoolResourceServer",
85
- "AWS::CloudWatch::Alarm",
86
- "AWS::CloudWatch::Dashboard",
87
- "AWS::CloudFront::CloudFrontOriginAccessIdentity",
88
- "AWS::CloudFront::OriginAccessControl",
89
- "AWS::CloudFront::OriginRequestPolicy",
90
- "AWS::CloudFront::Function",
91
- "AWS::CloudFront::ResponseHeadersPolicy",
92
- "AWS::CloudFront::CachePolicy",
93
- "AWS::ElasticBeanstalk::ApplicationVersion",
94
- "AWS::ElasticBeanstalk::ConfigurationTemplate",
95
- "AWS::ElasticLoadBalancingV2::Listener",
96
- "AWS::ElasticLoadBalancingV2::ListenerRule",
97
- "AWS::ECS::ClusterCapacityProviderAssociations",
98
- "AWS::EC2::SecurityGroupEgress",
99
- "AWS::EC2::SecurityGroupIngress",
100
- "AWS::ECS::PrimaryTaskSet",
101
- "AWS::EC2::LaunchTemplate",
102
- "AWS::Events::Rule",
103
- "AWS::Events::EventBus",
104
- "AWS::Events::EventBusPolicy",
105
- "AWS::Events::Connection",
106
- "AWS::Events::ApiDestination",
107
- "AWS::Events::Endpoint",
108
- "AWS::Events::Archive",
109
- "AWS::EFS::FileSystem",
110
- "AWS::EFS::MountTarget",
111
- "AWS::EFS::AccessPoint",
112
- "AWS::GlobalAccelerator::Listener",
113
- "AWS::GlobalAccelerator::EndpointGroup",
114
- "AWS::Glue::Database",
115
- "AWS::Glue::Crawler",
116
- "AWS::Glue::Classifier",
117
- "AWS::Glue::Connection",
118
- "AWS::Glue::DataCatalogEncryptionSettings",
119
- "AWS::Glue::Partition",
120
- "AWS::Glue::SchemaVersion",
121
- "AWS::Glue::SchemaVersionMetadata",
122
- "AWS::Glue::SecurityConfiguration",
123
- "AWS::Glue::Table",
124
- "AWS::Grafana::Workspace",
125
- "AWS::KMS::Alias",
126
- "AWS::Route53::HostedZone",
127
- "AWS::Route53::RecordSet",
128
- "AWS::Route53::RecordSetGroup",
129
- "AWS::Route53::HealthCheck",
130
- "AWS::RDS::DBProxyTargetGroup",
131
- "AWS::S3::AccessPoint",
132
- "AWS::S3::MultiRegionAccessPoint",
133
- "AWS::S3::MultiRegionAccessPointPolicy",
134
- "AWS::SES::ReceiptRuleSet",
135
- "AWS::SES::ReceiptRule",
136
- "AWS::SES::ConfigurationSet",
137
- "AWS::SES::ConfigurationSetEventDestination",
138
- "AWS::SES::ReceiptFilter",
139
- "AWS::SES::Template",
140
- "AWS::SNS::Subscription",
141
- "AWS::SNS::TopicPolicy",
142
- "AWS::SQS::QueuePolicy",
143
- "AWS::S3::BucketPolicy",
144
- "AWS::SSM::ResourceDataSync",
145
- "AWS::SecretsManager::SecretTargetAttachment",
146
- "AWS::SecretsManager::RotationSchedule",
147
- "AWS::SecretsManager::ResourcePolicy",
148
- "AWS::IAM::Policy",
149
- "AWS::IAM::AccessKey",
150
- "AWS::IAM::UserToGroupAddition",
151
- "AWS::IAM::ServiceLinkedRole",
152
- "AWS::IAM::ManagedPolicy",
153
- "AWS::IAM::InstanceProfile",
154
- "AWS::IAM::Group",
155
- "AWS::IAM::ManagedPolicy",
156
- "AWS::IAM::RolePolicy",
157
- "AWS::EC2::VPCGatewayAttachment",
158
- "AWS::EC2::Route",
159
- "AWS::EC2::SubnetRouteTableAssociation",
160
- "AWS::EC2::VPCDHCPOptionsAssociation",
161
- "AWS::EC2::VPCEndpoint",
162
- "AWS::EC2::TransitGatewayRoute",
163
- "AWS::EC2::TransitGatewayRouteTableAssociation",
164
- "AWS::EC2::TransitGatewayRouteTablePropagation",
165
- "AWS::EC2::IPAMAllocation",
166
- "AWS::EC2::IPAMPoolCidr",
167
- "AWS::ApplicationAutoScaling::ScalableTarget",
168
- "AWS::ApplicationAutoScaling::ScalingPolicy",
169
- "AWS::WAFv2::WebACLAssociation",
170
- "AWS::WAFv2::LoggingConfiguration",
171
- "AWS::OpenSearchServerless::AccessPolicy",
172
- "AWS::OpenSearchServerless::SecurityPolicy",
173
- "AWS::OpenSearchServerless::VpcEndpoint",
174
- "AWS::PinpointEmail::ConfigurationSetEventDestination",
175
- "AWS::Pinpoint::ADMChannel",
176
- "AWS::Pinpoint::APNSChannel",
177
- "AWS::Pinpoint::APNSSandboxChannel",
178
- "AWS::Pinpoint::APNSVoipChannel",
179
- "AWS::Pinpoint::APNSVoipSandboxChannel",
180
- "AWS::Pinpoint::ApplicationSettings",
181
- "AWS::Pinpoint::BaiduChannel",
182
- "AWS::Pinpoint::EmailChannel",
183
- "AWS::Pinpoint::EventStream",
184
- "AWS::Pinpoint::GCMChannel",
185
- "AWS::Pinpoint::SMSChannel",
186
- "AWS::Pinpoint::VoiceChannel",
187
- "AWS::Pipes::Pipe",
188
- "AWS::QLDB::Ledger",
189
- "AWS::Scheduler::Schedule",
190
- ];
191
-
192
- this.tagDictBasedTypes = [
193
- "AWS::SSM::Parameter",
194
- "AWS::Pinpoint::App",
195
- /***Estos deben caer en algun momento***/
196
- // "AWS::Pinpoint::Campaign",
197
- // "AWS::Pinpoint::EmailTemplate",
198
- // "AWS::Pinpoint::PushTemplate",
199
- // "AWS::Pinpoint::SmsTemplate",
200
- // "AWS::Pinpoint::Segment",
201
- /***Fin Estos***/
202
- "AWS::ApiGatewayV2::Api",
203
- "AWS::ApiGatewayV2::Stage",
204
- "AWS::ApiGatewayV2::DomainName",
205
- "AWS::ApiGatewayV2::VpcLink",
206
- "AWS::Glue::Job",
207
- "AWS::Glue::Crawler",
208
- "AWS::Glue::DevEndpoint",
209
- "AWS::Glue::MLTransform",
210
- "AWS::Glue::Trigger",
211
- "AWS::Glue::Workflow",
212
- "AWS::Batch::JobDefinition",
213
- "AWS::Batch::ComputeEnvironment",
214
- "AWS::Batch::JobQueue",
215
- "AWS::Batch::SchedulingPolicy",
216
- ];
217
12
 
218
- this.otherBasedTypes = [
219
- // "AWS::IAM::Role",
220
- "AWS::RDS::DBCluster",
221
- "AWS::KinesisFirehose::DeliveryStream",
222
- ];
13
+ const awsProvider = this.serverless.getProvider("aws");
14
+ this.stage = awsProvider.getStage();
15
+ this.region = awsProvider.getRegion();
16
+ this.partition = awsProvider.partition || "aws";
17
+ this.awsConfig = configFromProvider(awsProvider);
223
18
 
224
- this.haveRelatedTypes = ["AWS::EC2::Instance"];
19
+ // Plugin config from custom.datamart
20
+ this.pluginConfig = (this.serverless.service.custom || {}).datamart || {};
225
21
 
226
22
  this.hooks = {
227
- "before:package:finalize": this.tagResources.bind(this),
228
- "after:deploy:deploy": this.updateTagsPostDeploy.bind(this),
23
+ "before:package:finalize": this.onBeforePackageFinalize.bind(this),
24
+ "after:deploy:deploy": this.onAfterDeploy.bind(this),
229
25
  };
230
26
  }
231
27
 
232
- _getRegion() {
233
- return this.region;
234
- }
235
-
236
- _getStage() {
237
- return this.stage;
238
- }
239
-
240
- _getPartition() {
241
- return this.partition;
28
+ _log(message) {
29
+ this.serverless.cli.log(message);
242
30
  }
243
31
 
244
- _getTagNames(srcArray) {
245
- var tagNames = [];
246
- srcArray.forEach(function (element) {
247
- tagNames.push(element["Key"].toLowerCase());
248
- });
249
- return tagNames;
32
+ _getStackTags() {
33
+ return this.serverless.service.provider.stackTags || {};
250
34
  }
251
35
 
252
- _listBasedStackTags() {
253
- var stackTags = [];
254
- if (typeof this.serverless.service.provider.stackTags === "object") {
255
- var tags = this.serverless.service.provider.stackTags;
256
- Object.keys(tags).forEach(function (key) {
257
- stackTags.push({ Key: key, Value: tags[key] });
258
- });
259
- }
260
- //Add stage
261
- let stageTag = [{ Key: "Stage", Value: this._getStage() }];
262
- stackTags.concat(
263
- stageTag.filter(
264
- (obj) =>
265
- this._getTagNames(stackTags).indexOf(obj["Key"].toLowerCase()) === -1
266
- )
267
- );
268
- return stackTags;
269
- }
36
+ onBeforePackageFinalize() {
37
+ const stackTags = this._getStackTags();
270
38
 
271
- _dictBasedStackTags() {
272
- let stackTags = new Object();
273
- if (typeof this.serverless.service.provider.stackTags === "object") {
274
- stackTags = this.serverless.service.provider.stackTags;
275
- }
276
- //Add stage
277
- stackTags.Stage = this._getStage();
278
- return stackTags;
279
- }
280
-
281
- _excludeAWSTagsFilter(tag) {
282
- if ("Key" in tag && tag.Key.toLowerCase().includes("aws:")) {
283
- return false;
284
- } else {
285
- return true;
286
- }
287
- }
288
-
289
- async getEc2Resources(reservations) {
290
- let resources = [];
291
- for (let reservation of reservations) {
292
- let owner = reservation.OwnerId;
293
- for (let instance of reservation.Instances) {
294
- //Adding Volumes
295
- instance.BlockDeviceMappings.forEach((volume) => {
296
- resources.push(volume.Ebs.VolumeId);
297
- });
298
- //Adding NI
299
- for (let network of instance.NetworkInterfaces) {
300
- resources.push(network.NetworkInterfaceId);
301
- //Verify & Adding EIP
302
- if (network.Association) {
303
- let association = network.Association;
304
- if (association.IpOwnerId === owner) {
305
- let eipParams = {
306
- PublicIps: [association.PublicIp],
307
- };
308
- let addressResult = await this.ec2Service
309
- .describeAddresses(eipParams)
310
- .promise();
311
- addressResult.Addresses.forEach((address) => {
312
- resources.push(address.AllocationId);
313
- });
314
- }
315
- }
316
- //Adding SG
317
- network.Groups.forEach((group) => {
318
- resources.push(group.GroupId);
319
- });
320
- }
39
+ // Validation (optional)
40
+ if (this.pluginConfig.validation) {
41
+ this._log("TAGGING: Validating tags...");
42
+ const result = validateTags(stackTags, this.stage);
43
+ if (!result.valid) {
44
+ const msg = `Tag validation failed:\n ${result.errors.join("\n ")}`;
45
+ throw new this.serverless.classes.Error(msg);
321
46
  }
47
+ this._log("TAGGING: Validation passed");
322
48
  }
323
- return resources;
324
- }
325
49
 
326
- tagDictBasedResources(objResources, logicalID) {
327
- let stackTags = Object.assign({}, this._dictBasedStackTags());
328
- var tags = objResources.Resources[logicalID]["Properties"]["Tags"];
329
- if (tags) {
330
- for (var key in stackTags) {
331
- objResources.Resources[logicalID]["Properties"]["Tags"][key] =
332
- stackTags[key];
333
- }
334
- } else {
335
- objResources.Resources[logicalID]["Properties"]["Tags"] = stackTags;
336
- }
337
- //Adding/Updating Resource tag
338
- let tagResource = false;
339
- if (objResources.Resources[logicalID]["Properties"]["Tags"]) {
340
- for (var key in objResources.Resources[logicalID]["Properties"]["Tags"]) {
341
- if (key === "Resource") {
342
- objResources.Resources[logicalID]["Properties"]["Tags"]["Resource"] =
343
- logicalID;
344
- tagResource = true;
345
- }
346
- }
347
- }
348
- if (!tagResource) {
349
- objResources.Resources[logicalID]["Properties"]["Tags"]["Resource"] =
350
- logicalID;
50
+ // Tag compiled CloudFormation template
51
+ this._log("TAGGING: Updating tags in CloudFormation template...");
52
+ const cfTemplate =
53
+ this.serverless.service.provider.compiledCloudFormationTemplate;
54
+ if (cfTemplate && cfTemplate.Resources) {
55
+ tagResources(
56
+ cfTemplate.Resources,
57
+ stackTags,
58
+ this.stage,
59
+ this._log.bind(this)
60
+ );
351
61
  }
352
- }
353
62
 
354
- tagListBasedResources(objResources, logicalID) {
355
- let stackTags = [...this._listBasedStackTags()];
356
- var tags = objResources.Resources[logicalID]["Properties"]["Tags"];
357
- if (tags) {
358
- objResources.Resources[logicalID]["Properties"]["Tags"] = tags.concat(
359
- stackTags.filter(
360
- (obj) =>
361
- this._getTagNames(tags).indexOf(obj["Key"].toLowerCase()) === -1
362
- )
63
+ // Tag custom resources section
64
+ const awsResources = this.serverless.service.resources;
65
+ if (awsResources && awsResources.Resources) {
66
+ tagResources(
67
+ awsResources.Resources,
68
+ stackTags,
69
+ this.stage,
70
+ this._log.bind(this)
363
71
  );
364
- } else {
365
- objResources.Resources[logicalID]["Properties"]["Tags"] = stackTags;
366
- }
367
- //Adding/Updating Resource tag
368
- let tagResource = false;
369
- if (objResources.Resources[logicalID]["Properties"]["Tags"]) {
370
- objResources.Resources[logicalID]["Properties"]["Tags"].forEach((tag) => {
371
- if (tag["Key"] === "Resource") {
372
- tag["Value"] = logicalID;
373
- tagResource = true;
374
- }
375
- });
376
- }
377
- if (!tagResource) {
378
- objResources.Resources[logicalID]["Properties"]["Tags"].push({
379
- Key: "Resource",
380
- Value: logicalID,
381
- });
382
72
  }
383
73
  }
384
74
 
385
- async updateTagsPostDeploy() {
386
- this.serverless.cli.log("TAGGING: Updating tags post deploy...");
387
- const awsService = this.serverless.getProvider("aws");
388
- const stackName = awsService.naming.getStackName();
389
- const cfParams = { StackName: stackName };
390
-
391
- let cfStackResources = await this.cfnService
392
- .describeStackResources(cfParams)
393
- .promise();
75
+ async onAfterDeploy() {
76
+ this._log("TAGGING: Updating tags post-deploy...");
77
+ const awsProvider = this.serverless.getProvider("aws");
78
+ const stackName = awsProvider.naming.getStackName();
394
79
 
395
- await this.updateDictBasedTags(cfStackResources);
396
- await this.updateOtherResourcesTags(cfStackResources);
397
- await this.tagRelatedResources(cfStackResources);
398
- }
399
-
400
- async tagRelatedResources(cfStackResources) {
401
- this.serverless.cli.log(
402
- "TAGGING: Updating related resources on stackTags..."
80
+ await updateTagsPostDeploy(
81
+ this.awsConfig,
82
+ stackName,
83
+ this._getStackTags(),
84
+ this.stage,
85
+ this.partition,
86
+ this.region,
87
+ this._log.bind(this)
403
88
  );
404
- cfStackResources.StackResources.forEach(async (resource) => {
405
- let tagsList = [...this._listBasedStackTags()];
406
- // tagsList.push({ "Key": 'Resource', "Value": resource.LogicalResourceId })
407
- if (this.haveRelatedTypes.indexOf(resource.ResourceType) !== -1) {
408
- switch (resource.ResourceType) {
409
- case "AWS::EC2::Instance":
410
- let paramsEc2 = {
411
- InstanceIds: [resource.PhysicalResourceId],
412
- };
413
- let instancesResult = await this.ec2Service
414
- .describeInstances(paramsEc2)
415
- .promise();
416
- let ec2Tags = instancesResult.Reservations[0].Instances[0].Tags;
417
- ec2Tags = ec2Tags.filter(this._excludeAWSTagsFilter);
418
- let resources = await this.getEc2Resources(
419
- instancesResult.Reservations
420
- );
421
- let tagsParams = {
422
- Resources: resources,
423
- Tags: ec2Tags,
424
- };
425
- await this.ec2Service.createTags(tagsParams).promise();
426
- this.serverless.cli.log(
427
- `Related Resources Ids tagged: ${JSON.stringify(resources)}`
428
- );
429
- break;
430
- }
431
- }
432
- });
433
- }
434
89
 
435
- async updateOtherResourcesTags(cfStackResources) {
436
- this.serverless.cli.log(
437
- "TAGGING: Updating others list based resources on stackTags..."
438
- );
439
- cfStackResources.StackResources.forEach(async (resource) => {
440
- let tagsList = [...this._listBasedStackTags()];
441
- tagsList.push({ Key: "Resource", Value: resource.LogicalResourceId });
442
- if (this.otherBasedTypes.indexOf(resource.ResourceType) !== -1) {
443
- switch (resource.ResourceType) {
444
- case "AWS::IAM::Role":
445
- let iamParams = {
446
- RoleName: resource.PhysicalResourceId,
447
- Tags: tagsList,
448
- };
449
- await this.iamService.tagRole(iamParams).promise();
450
- break;
451
- case "AWS::RDS::DBCluster":
452
- let cfStack = resource.StackId.split(":");
453
- let accountId = cfStack[4];
454
- let rdsParams = {
455
- ResourceName: `arn:${this._getPartition()}:rds:${this._getRegion()}:${accountId}:cluster:${
456
- resource.PhysicalResourceId
457
- }`,
458
- Tags: tagsList,
459
- };
460
- await this.rdsService.addTagsToResource(rdsParams).promise();
461
- break;
462
- case "AWS::KinesisFirehose::DeliveryStream":
463
- let firehoseParams = {
464
- DeliveryStreamName: resource.PhysicalResourceId,
465
- Tags: tagsList,
466
- };
467
- await this.firehoseService
468
- .tagDeliveryStream(firehoseParams)
469
- .promise();
470
- break;
471
- }
472
- }
473
- });
474
- }
475
-
476
- async updateDictBasedTags(cfStackResources) {
477
- this.serverless.cli.log(
478
- "TAGGING: Updating dict based resources on stackTags..."
479
- );
480
- cfStackResources.StackResources.forEach(async (resource) => {
481
- let tagsList = [...this._listBasedStackTags()];
482
- tagsList.push({ Key: "Resource", Value: resource.LogicalResourceId });
483
- let tagsMap = Object.assign({}, this._dictBasedStackTags());
484
- tagsMap.Resource = resource.LogicalResourceId;
485
- if (this.tagDictBasedTypes.indexOf(resource.ResourceType) !== -1) {
486
- switch (resource.ResourceType) {
487
- case "AWS::SSM::Parameter":
488
- let ssmParams = {
489
- ResourceId: resource.PhysicalResourceId,
490
- ResourceType: "Parameter",
491
- Tags: tagsList,
492
- };
493
- await this.ssmService.addTagsToResource(ssmParams).promise();
494
- break;
495
- case "AWS::Pinpoint::App":
496
- let appParams = {
497
- ApplicationId: resource.PhysicalResourceId,
498
- };
499
- let ppApp = await this.pinpointService.getApp(appParams).promise();
500
- // this.serverless.cli.log(`ppApp: ${JSON.stringify(ppApp)}`)
501
- let pinpParams = {
502
- ResourceArn: ppApp.ApplicationResponse.Arn,
503
- TagsModel: {
504
- tags: {
505
- ...tagsMap,
506
- },
507
- },
508
- };
509
- await this.pinpointService.tagResource(pinpParams).promise();
510
- break;
511
- case "AWS::ApiGatewayV2::Api":
512
- let apiv2Params = {
513
- ResourceArn: `arn:${this._getPartition()}:apigateway:${this._getRegion()}::/apis/${
514
- resource.PhysicalResourceId
515
- }`,
516
- Tags: {
517
- ...tagsMap,
518
- },
519
- };
520
- await this.apigwv2Service.tagResource(apiv2Params).promise();
521
- break;
522
- case "AWS::ApiGatewayV2::Stage":
523
- let apiV2 = cfStackResources.StackResources.find(
524
- (resource) => resource.ResourceType == "AWS::ApiGatewayV2::Api"
525
- );
526
- let stageV2Params = {
527
- ResourceArn: `arn:${this._getPartition()}:apigateway:${this._getRegion()}::/apis/${
528
- apiV2.PhysicalResourceId
529
- }/stages/${resource.PhysicalResourceId}`,
530
- Tags: {
531
- ...tagsMap,
532
- },
533
- };
534
- await this.apigwv2Service.tagResource(stageV2Params).promise();
535
- break;
536
- }
537
- }
538
- });
539
- }
540
-
541
- tagResources() {
542
- this.serverless.cli.log("TAGGING: Updating tags based on stackTags...");
543
- let self = this;
544
- const cfTemplate =
545
- this.serverless.service.provider.compiledCloudFormationTemplate || null;
546
- const awsResources = this.serverless.service.resources || null;
547
- //Tag serverless resources
548
- if (cfTemplate && cfTemplate.Resources) {
549
- Object.keys(cfTemplate.Resources).forEach((logicalID) => {
550
- let resourceType = cfTemplate.Resources[logicalID]["Type"];
551
- this.serverless.cli.log(
552
- `TAGGING: validating resource type => ${resourceType}`
553
- );
554
- let stackTags = [...this._listBasedStackTags()];
555
- if (
556
- self.unsupportedTypes.indexOf(resourceType) == -1 &&
557
- Array.isArray(stackTags) &&
558
- resourceType.toLowerCase().indexOf("custom::") == -1
559
- ) {
560
- if (cfTemplate.Resources[logicalID]["Properties"]) {
561
- if (self.tagDictBasedTypes.indexOf(resourceType) !== -1) {
562
- // this.tagDictBasedResources(cfTemplate, logicalID)
563
- this.serverless.cli.log(
564
- `TAGGING: dict based resource => ${resourceType}`
565
- );
566
- } else if (self.otherBasedTypes.indexOf(resourceType) == -1) {
567
- this.tagListBasedResources(cfTemplate, logicalID);
568
- }
569
- } else {
570
- self.serverless.cli.log(
571
- "Properties not available for " + resourceType
572
- );
573
- }
574
- }
575
- if (self.unsupportedTypes.indexOf(resourceType) == -1) {
576
- cfTemplate.Resources[logicalID]["Properties"];
577
- }
578
- });
579
- }
580
- //Tag cloudformation specified resources
581
- if (awsResources && awsResources.Resources) {
582
- Object.keys(awsResources.Resources).forEach((logicalID) => {
583
- let resourceType = awsResources.Resources[logicalID]["Type"];
584
- let stackTags = [...this._listBasedStackTags()];
585
- if (
586
- self.unsupportedTypes.indexOf(resourceType) == -1 &&
587
- Array.isArray(stackTags) /*&& stackTags.length > 0*/
588
- ) {
589
- if (awsResources.Resources[logicalID]["Properties"]) {
590
- if (self.tagDictBasedTypes.indexOf(resourceType) !== -1) {
591
- // this.tagDictBasedResources(awsResources, logicalID)
592
- this.serverless.cli.log(
593
- `TAGGING: dict based resource => ${resourceType}`
594
- );
595
- } else if (self.otherBasedTypes.indexOf(resourceType) == -1) {
596
- this.tagListBasedResources(awsResources, logicalID);
597
- }
598
- } else {
599
- self.serverless.cli.log(
600
- "Properties not available for " + resourceType
601
- );
602
- }
603
- }
604
- });
605
- }
90
+ this._log("TAGGING: Post-deploy tagging complete");
606
91
  }
607
92
  }
608
93