@liflig/cdk 2.18.5 → 2.18.6

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 (140) hide show
  1. package/assets/cloudtrail-slack-integration-lambda/main.py +267 -0
  2. package/assets/pipeline-slack-notification-lambda/index.py +300 -0
  3. package/assets/prepare-cdk-source-lambda/index.py +159 -0
  4. package/assets/slack-alarm-lambda/index.py +103 -0
  5. package/lib/alarms/database-alarms.d.ts +125 -0
  6. package/lib/alarms/database-alarms.js +171 -0
  7. package/lib/alarms/index.d.ts +3 -0
  8. package/lib/alarms/index.js +10 -0
  9. package/lib/alarms/service-alarms.d.ts +145 -0
  10. package/lib/alarms/service-alarms.js +148 -0
  11. package/lib/alarms/ses-alarms.d.ts +67 -0
  12. package/lib/alarms/ses-alarms.js +49 -0
  13. package/lib/alarms/slack-alarm.d.ts +25 -0
  14. package/lib/alarms/slack-alarm.js +47 -0
  15. package/lib/bastion-host.d.ts +41 -0
  16. package/lib/bastion-host.js +86 -0
  17. package/lib/bin/cdk-create-snapshots.d.ts +2 -0
  18. package/lib/bin/fetch-pipeline-variables.d.ts +2 -0
  19. package/lib/build-artifacts/index.d.ts +68 -0
  20. package/lib/build-artifacts/index.js +118 -0
  21. package/lib/cdk-deploy/cdk-deploy.d.ts +63 -0
  22. package/lib/cdk-deploy/cdk-deploy.js +175 -0
  23. package/lib/cdk-deploy/index.d.ts +1 -0
  24. package/lib/cdk-deploy/index.js +6 -0
  25. package/lib/cdk-deploy/start-deploy-handler.d.ts +8 -0
  26. package/lib/cdk-deploy/start-deploy-handler.js +72 -0
  27. package/lib/cdk-deploy/status-handler.d.ts +6 -0
  28. package/lib/cdk-deploy/status-handler.js +83 -0
  29. package/lib/cdk-pipelines/cloud-assembly-lookup-handler.d.ts +6 -0
  30. package/lib/cdk-pipelines/cloud-assembly-lookup-handler.js +63 -0
  31. package/lib/cdk-pipelines/index.d.ts +3 -0
  32. package/lib/cdk-pipelines/index.js +10 -0
  33. package/lib/cdk-pipelines/liflig-cdk-pipeline.d.ts +110 -0
  34. package/lib/cdk-pipelines/liflig-cdk-pipeline.js +232 -0
  35. package/lib/cdk-pipelines/slack-notification.d.ts +51 -0
  36. package/lib/cdk-pipelines/slack-notification.js +54 -0
  37. package/lib/cdk-pipelines/variables.d.ts +15 -0
  38. package/lib/cdk-pipelines/variables.js +80 -0
  39. package/lib/cloudtrail-slack-integration/cloudtrail-slack-integration.d.ts +47 -0
  40. package/lib/cloudtrail-slack-integration/cloudtrail-slack-integration.js +211 -0
  41. package/lib/cloudtrail-slack-integration/index.d.ts +1 -0
  42. package/lib/cloudtrail-slack-integration/index.js +6 -0
  43. package/lib/configure-parameters/configure-parameters.d.ts +61 -0
  44. package/lib/configure-parameters/configure-parameters.js +94 -0
  45. package/lib/configure-parameters/index.d.ts +1 -0
  46. package/lib/configure-parameters/index.js +6 -0
  47. package/lib/cross-region-ssm-parameter.d.ts +13 -0
  48. package/lib/cross-region-ssm-parameter.js +46 -0
  49. package/lib/ecs/cluster.d.ts +25 -0
  50. package/lib/ecs/cluster.js +70 -0
  51. package/lib/ecs/fargate-service.d.ts +63 -0
  52. package/lib/ecs/fargate-service.js +98 -0
  53. package/lib/ecs/index.d.ts +3 -0
  54. package/lib/ecs/index.js +10 -0
  55. package/lib/ecs/listener-rule.d.ts +25 -0
  56. package/lib/ecs/listener-rule.js +27 -0
  57. package/lib/ecs-update-image/artifact-status.d.ts +39 -0
  58. package/lib/ecs-update-image/artifact-status.js +41 -0
  59. package/lib/ecs-update-image/ecs-update-image.d.ts +41 -0
  60. package/lib/ecs-update-image/ecs-update-image.js +98 -0
  61. package/lib/ecs-update-image/index.d.ts +3 -0
  62. package/lib/ecs-update-image/index.js +10 -0
  63. package/lib/ecs-update-image/start-deploy-handler.d.ts +6 -0
  64. package/lib/ecs-update-image/start-deploy-handler.js +104 -0
  65. package/lib/ecs-update-image/status-handler.d.ts +11 -0
  66. package/lib/ecs-update-image/status-handler.js +74 -0
  67. package/lib/ecs-update-image/tag.d.ts +47 -0
  68. package/lib/ecs-update-image/tag.js +67 -0
  69. package/lib/feature-flags.d.ts +18 -0
  70. package/lib/feature-flags.js +48 -0
  71. package/lib/griid/artefact-bucket.d.ts +7 -0
  72. package/lib/griid/artefact-bucket.js +30 -0
  73. package/lib/griid/index.d.ts +4 -0
  74. package/lib/griid/index.js +18 -0
  75. package/lib/hosted-zone-with-param.d.ts +29 -0
  76. package/lib/hosted-zone-with-param.js +65 -0
  77. package/lib/index.d.ts +32 -0
  78. package/lib/kinesis/index.d.ts +1 -0
  79. package/lib/kinesis/index.js +6 -0
  80. package/lib/kinesis/kinesis-to-datadog-stream.d.ts +28 -0
  81. package/lib/kinesis/kinesis-to-datadog-stream.js +126 -0
  82. package/lib/load-balancer/index.d.ts +1 -0
  83. package/lib/load-balancer/index.js +6 -0
  84. package/lib/load-balancer/load-balancer.d.ts +16 -0
  85. package/lib/load-balancer/load-balancer.js +60 -0
  86. package/lib/pipelines/conventions.d.ts +14 -0
  87. package/lib/pipelines/conventions.js +24 -0
  88. package/lib/pipelines/deploy-env.d.ts +18 -0
  89. package/lib/pipelines/deploy-env.js +96 -0
  90. package/lib/pipelines/index.d.ts +2 -0
  91. package/lib/pipelines/index.js +8 -0
  92. package/lib/pipelines/liflig-cdk-deployer-deps.d.ts +13 -0
  93. package/lib/pipelines/liflig-cdk-deployer-deps.js +35 -0
  94. package/lib/pipelines/pipeline.d.ts +78 -0
  95. package/lib/pipelines/pipeline.js +224 -0
  96. package/lib/platform/index.d.ts +1 -0
  97. package/lib/platform/index.js +7 -0
  98. package/lib/platform/platform.d.ts +37 -0
  99. package/lib/platform/platform.js +57 -0
  100. package/lib/rds/database.d.ts +49 -0
  101. package/lib/rds/database.js +60 -0
  102. package/lib/rds/index.d.ts +1 -0
  103. package/lib/rds/index.js +6 -0
  104. package/lib/ses/configurationsetdeliveryoptions/index.d.ts +26 -0
  105. package/lib/ses/configurationsetdeliveryoptions/index.js +48 -0
  106. package/lib/ses/configurationsetsnsdestination/handler.d.ts +17 -0
  107. package/lib/ses/configurationsetsnsdestination/handler.js +75 -0
  108. package/lib/ses/configurationsetsnsdestination/index.d.ts +29 -0
  109. package/lib/ses/configurationsetsnsdestination/index.js +75 -0
  110. package/lib/ses/index.d.ts +4 -0
  111. package/lib/ses/index.js +12 -0
  112. package/lib/ses/sesdomain/handler.d.ts +10 -0
  113. package/lib/ses/sesdomain/handler.js +82 -0
  114. package/lib/ses/sesdomain/index.d.ts +57 -0
  115. package/lib/ses/sesdomain/index.js +94 -0
  116. package/lib/ses/sesverifyemail/handler.d.ts +9 -0
  117. package/lib/ses/sesverifyemail/handler.js +25 -0
  118. package/lib/ses/sesverifyemail/index.d.ts +13 -0
  119. package/lib/ses/sesverifyemail/index.js +51 -0
  120. package/lib/snapshots.d.ts +4 -0
  121. package/lib/snapshots.js +214 -0
  122. package/lib/ssm-parameter-backed-resource.d.ts +45 -0
  123. package/lib/ssm-parameter-backed-resource.js +67 -0
  124. package/lib/ssm-parameter-reader.d.ts +21 -0
  125. package/lib/ssm-parameter-reader.js +48 -0
  126. package/lib/tags.d.ts +8 -0
  127. package/lib/tags.js +36 -0
  128. package/lib/utils.d.ts +2 -0
  129. package/lib/utils.js +17 -0
  130. package/lib/webapp/index.d.ts +3 -0
  131. package/lib/webapp/index.js +10 -0
  132. package/lib/webapp/monitor.d.ts +187 -0
  133. package/lib/webapp/monitor.js +156 -0
  134. package/lib/webapp/security-headers.d.ts +38 -0
  135. package/lib/webapp/security-headers.js +129 -0
  136. package/lib/webapp/webapp.d.ts +116 -0
  137. package/lib/webapp/webapp.js +118 -0
  138. package/lib/webapp-deploy-via-role.d.ts +25 -0
  139. package/lib/webapp-deploy-via-role.js +32 -0
  140. package/package.json +3 -2
@@ -0,0 +1,159 @@
1
+ import datetime
2
+ import json
3
+ import os
4
+ import re
5
+ import shutil
6
+ import tempfile
7
+ import zipfile
8
+ from pathlib import Path
9
+
10
+ import boto3
11
+ from boto3.session import Session
12
+
13
+ s3 = boto3.client("s3")
14
+ codepipeline = boto3.client("codepipeline")
15
+ ssm = boto3.client("ssm")
16
+
17
+
18
+ def get_variables_from_parameters(namespace):
19
+ next_token = None
20
+ result = {}
21
+
22
+ prefix = f'/liflig-cdk/{namespace}/pipeline-variables/'
23
+ params = {
24
+ 'Path': prefix,
25
+ }
26
+
27
+ while True:
28
+ if next_token is not None:
29
+ params['NextToken'] = next_token
30
+ response = ssm.get_parameters_by_path(**params)
31
+
32
+ parameters = response['Parameters']
33
+ if len(parameters) == 0:
34
+ break
35
+
36
+ for parameter in parameters:
37
+ result[parameter['Name'][len(prefix) :]] = parameter['Value']
38
+
39
+ if 'NextToken' not in response:
40
+ break
41
+ next_token = response['NextToken']
42
+
43
+ return result
44
+
45
+
46
+ def handler(event, context):
47
+ job = event["CodePipeline.job"]
48
+ job_id = job["id"]
49
+
50
+ try:
51
+ user_parameters = json.loads(
52
+ job["data"]["actionConfiguration"]["configuration"]["UserParameters"]
53
+ )
54
+
55
+ files = s3.list_objects_v2(
56
+ Bucket=user_parameters["bucketName"],
57
+ Prefix=user_parameters["prefix"],
58
+ )
59
+
60
+ def get_data(key):
61
+ result = s3.get_object(Bucket=user_parameters["bucketName"], Key=key)
62
+ return result["Body"].read()
63
+
64
+ cdk_source_ref = None
65
+ now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
66
+ variables = {
67
+ # Special variable that can be used when reading variables
68
+ # to ensure it is not stale. In the pipeline, variables
69
+ # will never be stale, but locally it can be.
70
+ 'variablesTimestamp': now.isoformat(),
71
+ }
72
+
73
+ for file in files.get("Contents", []):
74
+ key = file["Key"]
75
+ filename = key[len(user_parameters["prefix"]) :]
76
+
77
+ print(f"File: {filename}")
78
+
79
+ if filename == "cdk-source.json":
80
+ cdk_source_ref = json.loads(get_data(key))
81
+ elif re.match(r"^variables.*\.json$", filename):
82
+ # Legacy variables from S3 scoped only to this pipeline.
83
+ # Consider removing this later.
84
+ # See https://jira.capraconsulting.no/browse/CALS-408 for context
85
+ variables.update(json.loads(get_data(key)))
86
+ else:
87
+ print("Ignoring unknown file")
88
+
89
+ if cdk_source_ref is None:
90
+ raise Exception("cdk-source.json not found")
91
+
92
+ # Modern variables from Parameter Store.
93
+ variables.update(
94
+ get_variables_from_parameters(user_parameters["parametersNamespace"])
95
+ )
96
+
97
+ s3_loc = job["data"]["outputArtifacts"][0]["location"]["s3Location"]
98
+
99
+ temp_dir = tempfile.mkdtemp()
100
+
101
+ with tempfile.NamedTemporaryFile() as tmp_file:
102
+ s3.download_file(
103
+ Bucket=cdk_source_ref["bucketName"],
104
+ Key=cdk_source_ref["bucketKey"],
105
+ Filename=tmp_file.name,
106
+ )
107
+
108
+ print(f"Downloaded zip size: {os.path.getsize(tmp_file.name)}")
109
+
110
+ with zipfile.ZipFile(tmp_file.name, "r") as zip_file:
111
+ zip_file.extractall(temp_dir)
112
+
113
+ for name, value in variables.items():
114
+ print(f"Variable: {name}={value}")
115
+
116
+ Path(os.path.join(temp_dir, "variables.json")).write_text(json.dumps(variables))
117
+
118
+ with tempfile.NamedTemporaryFile() as tmp_file:
119
+ with zipfile.ZipFile(tmp_file.name, "w", zipfile.ZIP_DEFLATED) as zip_file:
120
+ for root, dirs, files in os.walk(temp_dir):
121
+ for file in files:
122
+ fullpath = os.path.join(root, file)
123
+ arcname = str(Path(fullpath).relative_to(temp_dir))
124
+ print(f"Adding {arcname}")
125
+ zip_file.write(filename=fullpath, arcname=arcname)
126
+
127
+ credentials = job["data"]["artifactCredentials"]
128
+ s3_upload_client = Session(
129
+ aws_access_key_id=credentials["accessKeyId"],
130
+ aws_secret_access_key=credentials["secretAccessKey"],
131
+ aws_session_token=credentials["sessionToken"],
132
+ ).client("s3")
133
+
134
+ print(f"Generated zip size: {os.path.getsize(tmp_file.name)}")
135
+
136
+ s3_upload_client.upload_file(
137
+ Filename=tmp_file.name,
138
+ Bucket=s3_loc["bucketName"],
139
+ Key=s3_loc["objectKey"],
140
+ )
141
+
142
+ shutil.rmtree(temp_dir)
143
+
144
+ codepipeline.put_job_success_result(
145
+ jobId=job_id,
146
+ )
147
+
148
+ print("Success")
149
+ except Exception as e:
150
+ codepipeline.put_job_failure_result(
151
+ jobId=job_id,
152
+ failureDetails={
153
+ "message": str(e),
154
+ "type": "JobFailed",
155
+ "externalExecutionId": context.aws_request_id,
156
+ },
157
+ )
158
+
159
+ print(f"Failed: ${e}")
@@ -0,0 +1,103 @@
1
+ import json
2
+ import os
3
+ from urllib.request import Request, urlopen
4
+ from urllib.error import URLError, HTTPError
5
+
6
+ import boto3
7
+
8
+ secrets_manager = boto3.client("secretsmanager")
9
+
10
+ SLACK_URL_SECRET_NAME = os.getenv("SLACK_URL_SECRET_NAME", None)
11
+ PROJECT_NAME = os.getenv("PROJECT_NAME", "undefined")
12
+ ENVIRONMENT_NAME = os.getenv("ENVIRONMENT_NAME", "undefined")
13
+
14
+
15
+ def handler(event, context):
16
+ print("Event: " + json.dumps(event))
17
+ message = json.loads(event["Records"][0]["Sns"]["Message"])
18
+ region = event["Records"][0]["Sns"]["TopicArn"].split(":")[3]
19
+
20
+ return send_slack_notification(message, region)
21
+
22
+
23
+ def get_masked_slack_webhook_url(slack_webhook_url: str):
24
+ """
25
+ Return a string that masks the final path segment of a Slack webhook URL.
26
+ The URL is typically formatted as such: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
27
+ """
28
+ trimmed_url = slack_webhook_url.rstrip("/")
29
+ [*url, final_path_segment] = trimmed_url.split("/")
30
+ return "/".join(url + [len(final_path_segment) * "*"])
31
+
32
+
33
+ def get_secret(secret):
34
+ try:
35
+ return secrets_manager.get_secret_value(SecretId=secret)["SecretString"]
36
+ except Exception as e:
37
+ raise Exception(f"Error retrieving secret: {e}")
38
+
39
+
40
+ def send_slack_notification(message, region):
41
+ alarm_emojis = {
42
+ "ALARM": ":rotating_light:",
43
+ "INSUFFICIENT_DATA": ":warning:",
44
+ "OK": ":white_check_mark:",
45
+ }
46
+ if message["NewStateValue"] == "ALARM":
47
+ color = "danger"
48
+ else:
49
+ color = "good"
50
+ alarm_description = message["AlarmDescription"] or "Alarm is missing description"
51
+ attachments = [
52
+ {
53
+ "color": color,
54
+ "title_link": "https://console.aws.amazon.com/cloudwatch/home?region="
55
+ + region
56
+ + "#alarm:alarmFilter=ANY;name="
57
+ + message["AlarmName"],
58
+ "fallback": f"{alarm_emojis.get(message['NewStateValue'], '')} {message['AlarmName']}: {alarm_description}",
59
+ "fields": [
60
+ {"title": "Alarm Name", "value": message["AlarmName"], "short": False},
61
+ {
62
+ "title": "Alarm Description",
63
+ "value": alarm_description,
64
+ "short": False,
65
+ },
66
+ {"title": "Account", "value": message["AWSAccountId"], "short": True},
67
+ {"title": "Region", "value": region, "short": True},
68
+ {"title": "Project", "value": PROJECT_NAME, "short": True},
69
+ {"title": "Environment", "value": ENVIRONMENT_NAME, "short": True},
70
+ {
71
+ "title": "State Transition",
72
+ "value": message.get("OldStateValue", "Unknown")
73
+ + " -> "
74
+ + message["NewStateValue"],
75
+ "short": False,
76
+ },
77
+ {
78
+ "title": "Link to Alarm",
79
+ "value": "https://console.aws.amazon.com/cloudwatch/home?region="
80
+ + region
81
+ + "#alarm:alarmFilter=ANY;name="
82
+ + message["AlarmName"],
83
+ "short": False,
84
+ },
85
+ ],
86
+ }
87
+ ]
88
+
89
+ slackMessage = {
90
+ "attachments": attachments,
91
+ }
92
+
93
+ slack_url = get_secret(SLACK_URL_SECRET_NAME)
94
+
95
+ req = Request(slack_url, json.dumps(slackMessage).encode("utf-8"))
96
+ print(f"Posting message to Slack URL {get_masked_slack_webhook_url(slack_url)}")
97
+ try:
98
+ response = urlopen(req)
99
+ response.read()
100
+ except HTTPError as e:
101
+ raise Exception(f"Request to slack failed: {e.code} {e.reason}")
102
+ except URLError as e:
103
+ raise Exception(f"Server connection to slack failed: {e.reason}")
@@ -0,0 +1,125 @@
1
+ import * as constructs from "constructs";
2
+ import * as cdk from "aws-cdk-lib";
3
+ import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
4
+ import * as ec2 from "aws-cdk-lib/aws-ec2";
5
+ export interface DatabaseAlarmsProps {
6
+ /**
7
+ * The default action to use for CloudWatch alarm state changes
8
+ */
9
+ action: cloudwatch.IAlarmAction;
10
+ instanceIdentifier: string;
11
+ instanceType: ec2.InstanceType;
12
+ allocatedStorage: cdk.Size;
13
+ }
14
+ export declare class DatabaseAlarms extends constructs.Construct {
15
+ private readonly action;
16
+ private readonly databaseInstanceIdentifier;
17
+ private readonly instanceType;
18
+ private readonly allocatedStorage;
19
+ constructor(scope: constructs.Construct, id: string, props: DatabaseAlarmsProps);
20
+ /**
21
+ * Sets up a CloudWatch Alarm that triggers if the CPU credit balance for
22
+ * a burstable instance breach a certain threshold.
23
+ *
24
+ * NOTE: This alarm is only applicable for burstable instances, and a balance of 0 credits will only have performance
25
+ * implications for T2 instances. T3 and T4g instances will instead cost more for prolonged high CPU utilization after
26
+ * the balance is depleted.
27
+ */
28
+ addCpuCreditsAlarm(
29
+ /**
30
+ * Configuration for an alarm.
31
+ *
32
+ * @default Configured with sane defaults.
33
+ */
34
+ props?: {
35
+ /**
36
+ * An action to use for CloudWatch alarm state changes instead of the default action
37
+ */
38
+ action?: cloudwatch.IAlarmAction;
39
+ /**
40
+ * The CloudWatch Alarm will change its state to ALARM if the number of CPU credits drops below this threshold.
41
+ *
42
+ * See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html#earning-CPU-credits for an overview of maximum CPU credits for various instance types.
43
+ *
44
+ * @default 10% of the maximum earned CPU credits for the instance type.
45
+ */
46
+ threshold?: number;
47
+ }): void;
48
+ /**
49
+ * Sets up two CloudWatch Alarms for monitoring disk storage space:
50
+ * 1) one that triggers if the available disk storage space is low.
51
+ * 2) one that triggers if the available disk storage space is critcally low.
52
+ *
53
+ * You may want to use different alarm actions for the two alarms, e.g., one can be
54
+ * categorized as a "warning", while the other one can be considered an "alarm".
55
+ */
56
+ addStorageSpaceAlarms(props?: {
57
+ /**
58
+ * Configuration for an alarm.
59
+ *
60
+ * @default Configured with sane defaults.
61
+ */
62
+ lowStorageSpaceAlarm?: {
63
+ /**
64
+ * @default true
65
+ */
66
+ enabled?: boolean;
67
+ /**
68
+ * An action to use for CloudWatch alarm state changes instead of the default action
69
+ */
70
+ action?: cloudwatch.IAlarmAction;
71
+ /**
72
+ * @default 25% of the allocated storage.
73
+ */
74
+ threshold?: cdk.Size;
75
+ };
76
+ /**
77
+ * Configuration for an alarm.
78
+ *
79
+ * @default Configured with sane defaults.
80
+ */
81
+ criticallyLowStorageSpaceAlarm?: {
82
+ /**
83
+ * @default true
84
+ */
85
+ enabled?: boolean;
86
+ /**
87
+ * An action to use for CloudWatch alarm state changes instead of the default action
88
+ */
89
+ action?: cloudwatch.IAlarmAction;
90
+ /**
91
+ * @default 5% of the allocated storage.
92
+ */
93
+ threshold?: cdk.Size;
94
+ };
95
+ }): void;
96
+ /**
97
+ * Sets up a CloudWatch Alarm that triggers if the average CPU utilization for
98
+ * the RDS instance exceeds a given threshold.
99
+ */
100
+ addCpuUtilizationAlarm(
101
+ /**
102
+ * Configuration for an alarm.
103
+ *
104
+ * @default Configured with sane defaults.
105
+ */
106
+ props?: {
107
+ /**
108
+ * An action to use for CloudWatch alarm state changes instead of the default action
109
+ */
110
+ action?: cloudwatch.IAlarmAction;
111
+ /**
112
+ * The threshold defined as a percentage that determines if CPU utilization should trigger an alarm or not.
113
+ * @default 80
114
+ */
115
+ threshold?: number;
116
+ /**
117
+ * @default 5
118
+ */
119
+ evaluationPeriods?: number;
120
+ /**
121
+ * @default 2 minutes
122
+ */
123
+ period?: cdk.Duration;
124
+ }): void;
125
+ }
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseAlarms = void 0;
4
+ const constructs = require("constructs");
5
+ const cdk = require("aws-cdk-lib");
6
+ const cloudwatch = require("aws-cdk-lib/aws-cloudwatch");
7
+ // Based on https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html#earning-CPU-credits
8
+ const cpuCreditBalanceByInstanceType = {
9
+ "t2.nano": 72,
10
+ "t2.micro": 144,
11
+ "t2.small": 288,
12
+ "t2.medium": 576,
13
+ "t2.large": 864,
14
+ "t2.xlarge": 1296,
15
+ "t2.2xlarge": 1958.4,
16
+ "t3.nano": 144,
17
+ "t3.micro": 288,
18
+ "t3.small": 576,
19
+ "t3.medium": 576,
20
+ "t3.large": 864,
21
+ "t3.xlarge": 2304,
22
+ "t3.2xlarge": 4608,
23
+ "t3a.nano": 144,
24
+ "t3a.micro": 288,
25
+ "t3a.small": 576,
26
+ "t3a.medium": 576,
27
+ "t3a.large": 864,
28
+ "t3a.xlarge": 2304,
29
+ "t3a.2xlarge": 4608,
30
+ "t4g.nano": 144,
31
+ "t4g.micro": 288,
32
+ "t4g.small": 576,
33
+ "t4g.medium": 576,
34
+ "t4g.large": 864,
35
+ "t4g.xlarge": 2304,
36
+ "t4g.2xlarge": 4608,
37
+ };
38
+ class DatabaseAlarms extends constructs.Construct {
39
+ constructor(scope, id, props) {
40
+ super(scope, id);
41
+ this.action = props.action;
42
+ this.databaseInstanceIdentifier = props.instanceIdentifier;
43
+ this.instanceType = props.instanceType;
44
+ this.allocatedStorage = props.allocatedStorage;
45
+ }
46
+ /**
47
+ * Sets up a CloudWatch Alarm that triggers if the CPU credit balance for
48
+ * a burstable instance breach a certain threshold.
49
+ *
50
+ * NOTE: This alarm is only applicable for burstable instances, and a balance of 0 credits will only have performance
51
+ * implications for T2 instances. T3 and T4g instances will instead cost more for prolonged high CPU utilization after
52
+ * the balance is depleted.
53
+ */
54
+ addCpuCreditsAlarm(
55
+ /**
56
+ * Configuration for an alarm.
57
+ *
58
+ * @default Configured with sane defaults.
59
+ */
60
+ props) {
61
+ var _a;
62
+ if (!["t2.", "t3.", "t4g."].some((s) => this.instanceType.toString().startsWith(s))) {
63
+ throw new Error("CPU credits are only relevant for burstable instance types.");
64
+ }
65
+ const defaultThreshold = cpuCreditBalanceByInstanceType[this.instanceType.toString()] * 0.1;
66
+ const threshold = (_a = props === null || props === void 0 ? void 0 : props.threshold) !== null && _a !== void 0 ? _a : defaultThreshold;
67
+ if (!threshold) {
68
+ throw new Error(`No threshold supplied, and unable to determine a default value for instance type '${this.instanceType.toString()}'`);
69
+ }
70
+ new cloudwatch.Metric({
71
+ metricName: "CPUCreditBalance",
72
+ namespace: "AWS/RDS",
73
+ statistic: "Minimum",
74
+ period: cdk.Duration.minutes(5),
75
+ dimensionsMap: {
76
+ DBInstanceIdentifier: this.databaseInstanceIdentifier,
77
+ },
78
+ })
79
+ .createAlarm(this, "CreditsAlarm", {
80
+ alarmDescription: `Less than ${threshold} CPU credits remaining for RDS database '${this.databaseInstanceIdentifier}'. ${this.instanceType.toString().startsWith("t2.")
81
+ ? "If this reaches 0, the instance will be limited to a baseline CPU utilization."
82
+ : "If the balance is depleted, AWS adds additional charges."}.`,
83
+ comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
84
+ evaluationPeriods: 1,
85
+ threshold: threshold,
86
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
87
+ })
88
+ .addAlarmAction(this.action);
89
+ }
90
+ /**
91
+ * Sets up two CloudWatch Alarms for monitoring disk storage space:
92
+ * 1) one that triggers if the available disk storage space is low.
93
+ * 2) one that triggers if the available disk storage space is critcally low.
94
+ *
95
+ * You may want to use different alarm actions for the two alarms, e.g., one can be
96
+ * categorized as a "warning", while the other one can be considered an "alarm".
97
+ */
98
+ addStorageSpaceAlarms(props) {
99
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
100
+ const lowStorageSpaceAlarm = new cloudwatch.Metric({
101
+ metricName: "FreeStorageSpace",
102
+ namespace: "AWS/RDS",
103
+ statistic: "Minimum",
104
+ period: cdk.Duration.minutes(5),
105
+ dimensionsMap: {
106
+ DBInstanceIdentifier: this.databaseInstanceIdentifier,
107
+ },
108
+ }).createAlarm(this, "LowStorageSpaceAlarm", {
109
+ alarmDescription: `Low storage space available on RDS database '${this.databaseInstanceIdentifier}'.`,
110
+ comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
111
+ evaluationPeriods: 1,
112
+ threshold: (_c = (_b = (_a = props === null || props === void 0 ? void 0 : props.lowStorageSpaceAlarm) === null || _a === void 0 ? void 0 : _a.threshold) === null || _b === void 0 ? void 0 : _b.toBytes()) !== null && _c !== void 0 ? _c : this.allocatedStorage.toBytes() * 0.25,
113
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
114
+ });
115
+ if ((_e = (_d = props === null || props === void 0 ? void 0 : props.lowStorageSpaceAlarm) === null || _d === void 0 ? void 0 : _d.enabled) !== null && _e !== void 0 ? _e : true) {
116
+ lowStorageSpaceAlarm.addAlarmAction(((_f = props === null || props === void 0 ? void 0 : props.lowStorageSpaceAlarm) === null || _f === void 0 ? void 0 : _f.action) || this.action);
117
+ lowStorageSpaceAlarm.addOkAction(((_g = props === null || props === void 0 ? void 0 : props.lowStorageSpaceAlarm) === null || _g === void 0 ? void 0 : _g.action) || this.action);
118
+ }
119
+ const criticallyLowStorageSpaceAlarm = new cloudwatch.Metric({
120
+ metricName: "FreeStorageSpace",
121
+ namespace: "AWS/RDS",
122
+ statistic: "Minimum",
123
+ period: cdk.Duration.minutes(5),
124
+ dimensionsMap: {
125
+ DBInstanceIdentifier: this.databaseInstanceIdentifier,
126
+ },
127
+ }).createAlarm(this, "CriticallyLowStorageSpaceAlarm", {
128
+ alarmDescription: `Critically low storage space available on RDS database '${this.databaseInstanceIdentifier}'.`,
129
+ comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
130
+ evaluationPeriods: 1,
131
+ threshold: (_k = (_j = (_h = props === null || props === void 0 ? void 0 : props.criticallyLowStorageSpaceAlarm) === null || _h === void 0 ? void 0 : _h.threshold) === null || _j === void 0 ? void 0 : _j.toBytes()) !== null && _k !== void 0 ? _k : this.allocatedStorage.toBytes() * 0.05,
132
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
133
+ });
134
+ if ((_m = (_l = props === null || props === void 0 ? void 0 : props.criticallyLowStorageSpaceAlarm) === null || _l === void 0 ? void 0 : _l.enabled) !== null && _m !== void 0 ? _m : true) {
135
+ criticallyLowStorageSpaceAlarm.addAlarmAction(((_o = props === null || props === void 0 ? void 0 : props.criticallyLowStorageSpaceAlarm) === null || _o === void 0 ? void 0 : _o.action) || this.action);
136
+ criticallyLowStorageSpaceAlarm.addOkAction(((_p = props === null || props === void 0 ? void 0 : props.criticallyLowStorageSpaceAlarm) === null || _p === void 0 ? void 0 : _p.action) || this.action);
137
+ }
138
+ }
139
+ /**
140
+ * Sets up a CloudWatch Alarm that triggers if the average CPU utilization for
141
+ * the RDS instance exceeds a given threshold.
142
+ */
143
+ addCpuUtilizationAlarm(
144
+ /**
145
+ * Configuration for an alarm.
146
+ *
147
+ * @default Configured with sane defaults.
148
+ */
149
+ props) {
150
+ var _a, _b, _c, _d, _e;
151
+ const alarm = new cloudwatch.Metric({
152
+ metricName: "CPUUtilization",
153
+ namespace: "AWS/RDS",
154
+ statistic: "Average",
155
+ period: (_a = props === null || props === void 0 ? void 0 : props.period) !== null && _a !== void 0 ? _a : cdk.Duration.minutes(2),
156
+ dimensionsMap: {
157
+ DBInstanceIdentifier: this.databaseInstanceIdentifier,
158
+ },
159
+ }).createAlarm(this, "CpuUtilizationAlarm", {
160
+ alarmDescription: `RDS database '${this.databaseInstanceIdentifier}' has a higher than expected CPU utilization.`,
161
+ comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
162
+ evaluationPeriods: (_b = props === null || props === void 0 ? void 0 : props.evaluationPeriods) !== null && _b !== void 0 ? _b : 5,
163
+ threshold: (_c = props === null || props === void 0 ? void 0 : props.threshold) !== null && _c !== void 0 ? _c : 80,
164
+ treatMissingData: cloudwatch.TreatMissingData.IGNORE,
165
+ });
166
+ alarm.addAlarmAction((_d = props === null || props === void 0 ? void 0 : props.action) !== null && _d !== void 0 ? _d : this.action);
167
+ alarm.addOkAction((_e = props === null || props === void 0 ? void 0 : props.action) !== null && _e !== void 0 ? _e : this.action);
168
+ }
169
+ }
170
+ exports.DatabaseAlarms = DatabaseAlarms;
171
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJhc2UtYWxhcm1zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FsYXJtcy9kYXRhYmFzZS1hbGFybXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseUNBQXdDO0FBQ3hDLG1DQUFrQztBQUNsQyx5REFBd0Q7QUFheEQsNEhBQTRIO0FBQzVILE1BQU0sOEJBQThCLEdBRWhDO0lBQ0YsU0FBUyxFQUFFLEVBQUU7SUFDYixVQUFVLEVBQUUsR0FBRztJQUNmLFVBQVUsRUFBRSxHQUFHO0lBQ2YsV0FBVyxFQUFFLEdBQUc7SUFDaEIsVUFBVSxFQUFFLEdBQUc7SUFDZixXQUFXLEVBQUUsSUFBSTtJQUNqQixZQUFZLEVBQUUsTUFBTTtJQUNwQixTQUFTLEVBQUUsR0FBRztJQUNkLFVBQVUsRUFBRSxHQUFHO0lBQ2YsVUFBVSxFQUFFLEdBQUc7SUFDZixXQUFXLEVBQUUsR0FBRztJQUNoQixVQUFVLEVBQUUsR0FBRztJQUNmLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLFlBQVksRUFBRSxJQUFJO0lBQ2xCLFVBQVUsRUFBRSxHQUFHO0lBQ2YsV0FBVyxFQUFFLEdBQUc7SUFDaEIsV0FBVyxFQUFFLEdBQUc7SUFDaEIsWUFBWSxFQUFFLEdBQUc7SUFDakIsV0FBVyxFQUFFLEdBQUc7SUFDaEIsWUFBWSxFQUFFLElBQUk7SUFDbEIsYUFBYSxFQUFFLElBQUk7SUFDbkIsVUFBVSxFQUFFLEdBQUc7SUFDZixXQUFXLEVBQUUsR0FBRztJQUNoQixXQUFXLEVBQUUsR0FBRztJQUNoQixZQUFZLEVBQUUsR0FBRztJQUNqQixXQUFXLEVBQUUsR0FBRztJQUNoQixZQUFZLEVBQUUsSUFBSTtJQUNsQixhQUFhLEVBQUUsSUFBSTtDQUNwQixDQUFBO0FBRUQsTUFBYSxjQUFlLFNBQVEsVUFBVSxDQUFDLFNBQVM7SUFNdEQsWUFDRSxLQUEyQixFQUMzQixFQUFVLEVBQ1YsS0FBMEI7UUFFMUIsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFF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LDBCQUEwQjthQUN0RDtTQUNGLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLHFCQUFxQixFQUFFO1lBQzFDLGdCQUFnQixFQUFFLGlCQUFpQixJQUFJLENBQUMsMEJBQTBCLCtDQUErQztZQUNqSCxrQkFBa0IsRUFBRSxVQUFVLENBQUMsa0JBQWtCLENBQUMsc0JBQXNCO1lBQ3hFLGlCQUFpQixFQUFFLE1BQUEsS0FBSyxhQUFMLEtBQUssdUJBQUwsS0FBSyxDQUFFLGlCQUFpQixtQ0FBSSxDQUFDO1lBQ2hELFNBQVMsRUFBRSxNQUFBLEtBQUssYUFBTCxLQUFLLHVCQUFMLEtBQUssQ0FBRSxTQUFTLG1DQUFJLEVBQUU7WUFDakMsZ0JBQWdCLEVBQUUsVUFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU07U0FDckQsQ0FBQyxDQUFBO1FBQ0YsS0FBSyxDQUFDLGNBQWMsQ0FBQyxNQUFBLEtBQUssYUFBTCxLQUFLLHVCQUFMLEtBQUssQ0FBRSxNQUFNLG1DQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUNsRCxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQUEsS0FBSyxhQUFMLEtBQUssdUJBQUwsS0FBSyxDQUFFLE1BQU0sbUNBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ2pELENBQUM7Q0FDRjtBQWhQRCx3Q0FnUEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjb25zdHJ1Y3RzIGZyb20gXCJjb25zdHJ1Y3RzXCJcbmltcG9ydCAqIGFzIGNkayBmcm9tIFwiYXdzLWNkay1saWJcIlxuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIlxuaW1wb3J0ICogYXMgZWMyIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCJcblxuZXhwb3J0IGludGVyZmFjZSBEYXRhYmFzZUFsYXJtc1Byb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBkZWZhdWx0IGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlc1xuICAgKi9cbiAgYWN0aW9uOiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICBpbnN0YW5jZUlkZW50aWZpZXI6IHN0cmluZ1xuICBpbnN0YW5jZVR5cGU6IGVjMi5JbnN0YW5jZVR5cGVcbiAgYWxsb2NhdGVkU3RvcmFnZTogY2RrLlNpemVcbn1cblxuLy8gQmFzZWQgb24gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0VDMi9sYXRlc3QvVXNlckd1aWRlL2J1cnN0YWJsZS1jcmVkaXRzLWJhc2VsaW5lLWNvbmNlcHRzLmh0bWwjZWFybmluZy1DUFUtY3JlZGl0c1xuY29uc3QgY3B1Q3JlZGl0QmFsYW5jZUJ5SW5zdGFuY2VUeXBlOiB7XG4gIFtpbnN0YW5jZVR5cGU6IHN0cmluZ106IG51bWJlclxufSA9IHtcbiAgXCJ0Mi5uYW5vXCI6IDcyLFxuICBcInQyLm1pY3JvXCI6IDE0NCxcbiAgXCJ0Mi5zbWFsbFwiOiAyODgsXG4gIFwidDIubWVkaXVtXCI6IDU3NixcbiAgXCJ0Mi5sYXJnZVwiOiA4NjQsXG4gIFwidDIueGxhcmdlXCI6IDEyOTYsXG4gIFwidDIuMnhsYXJnZVwiOiAxOTU4LjQsXG4gIFwidDMubmFub1wiOiAxNDQsXG4gIFwidDMubWljcm9cIjogMjg4LFxuICBcInQzLnNtYWxsXCI6IDU3NixcbiAgXCJ0My5tZWRpdW1cIjogNTc2LFxuICBcInQzLmxhcmdlXCI6IDg2NCxcbiAgXCJ0My54bGFyZ2VcIjogMjMwNCxcbiAgXCJ0My4yeGxhcmdlXCI6IDQ2MDgsXG4gIFwidDNhLm5hbm9cIjogMTQ0LFxuICBcInQzYS5taWNyb1wiOiAyODgsXG4gIFwidDNhLnNtYWxsXCI6IDU3NixcbiAgXCJ0M2EubWVkaXVtXCI6IDU3NixcbiAgXCJ0M2EubGFyZ2VcIjogODY0LFxuICBcInQzYS54bGFyZ2VcIjogMjMwNCxcbiAgXCJ0M2EuMnhsYXJnZVwiOiA0NjA4LFxuICBcInQ0Zy5uYW5vXCI6IDE0NCxcbiAgXCJ0NGcubWljcm9cIjogMjg4LFxuICBcInQ0Zy5zbWFsbFwiOiA1NzYsXG4gIFwidDRnLm1lZGl1bVwiOiA1NzYsXG4gIFwidDRnLmxhcmdlXCI6IDg2NCxcbiAgXCJ0NGcueGxhcmdlXCI6IDIzMDQsXG4gIFwidDRnLjJ4bGFyZ2VcIjogNDYwOCxcbn1cblxuZXhwb3J0IGNsYXNzIERhdGFiYXNlQWxhcm1zIGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuICBwcml2YXRlIHJlYWRvbmx5IGFjdGlvbjogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgcHJpdmF0ZSByZWFkb25seSBkYXRhYmFzZUluc3RhbmNlSWRlbnRpZmllcjogc3RyaW5nXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5zdGFuY2VUeXBlOiBlYzIuSW5zdGFuY2VUeXBlXG4gIHByaXZhdGUgcmVhZG9ubHkgYWxsb2NhdGVkU3RvcmFnZTogY2RrLlNpemVcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogY29uc3RydWN0cy5Db25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcm9wczogRGF0YWJhc2VBbGFybXNQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKVxuXG4gICAgdGhpcy5hY3Rpb24gPSBwcm9wcy5hY3Rpb25cbiAgICB0aGlzLmRhdGFiYXNlSW5zdGFuY2VJZGVudGlmaWVyID0gcHJvcHMuaW5zdGFuY2VJZGVudGlmaWVyXG4gICAgdGhpcy5pbnN0YW5jZVR5cGUgPSBwcm9wcy5pbnN0YW5jZVR5cGVcbiAgICB0aGlzLmFsbG9jYXRlZFN0b3JhZ2UgPSBwcm9wcy5hbGxvY2F0ZWRTdG9yYWdlXG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCBhIENsb3VkV2F0Y2ggQWxhcm0gdGhhdCB0cmlnZ2VycyBpZiB0aGUgQ1BVIGNyZWRpdCBiYWxhbmNlIGZvclxuICAgKiBhIGJ1cnN0YWJsZSBpbnN0YW5jZSBicmVhY2ggYSBjZXJ0YWluIHRocmVzaG9sZC5cbiAgICpcbiAgICogTk9URTogVGhpcyBhbGFybSBpcyBvbmx5IGFwcGxpY2FibGUgZm9yIGJ1cnN0YWJsZSBpbnN0YW5jZXMsIGFuZCBhIGJhbGFuY2Ugb2YgMCBjcmVkaXRzIHdpbGwgb25seSBoYXZlIHBlcmZvcm1hbmNlXG4gICAqIGltcGxpY2F0aW9ucyBmb3IgVDIgaW5zdGFuY2VzLiBUMyBhbmQgVDRnIGluc3RhbmNlcyB3aWxsIGluc3RlYWQgY29zdCBtb3JlIGZvciBwcm9sb25nZWQgaGlnaCBDUFUgdXRpbGl6YXRpb24gYWZ0ZXJcbiAgICogdGhlIGJhbGFuY2UgaXMgZGVwbGV0ZWQuXG4gICAqL1xuICBhZGRDcHVDcmVkaXRzQWxhcm0oXG4gICAgLyoqXG4gICAgICogQ29uZmlndXJhdGlvbiBmb3IgYW4gYWxhcm0uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBDb25maWd1cmVkIHdpdGggc2FuZSBkZWZhdWx0cy5cbiAgICAgKi9cbiAgICBwcm9wcz86IHtcbiAgICAgIC8qKlxuICAgICAgICogQW4gYWN0aW9uIHRvIHVzZSBmb3IgQ2xvdWRXYXRjaCBhbGFybSBzdGF0ZSBjaGFuZ2VzIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgYWN0aW9uXG4gICAgICAgKi9cbiAgICAgIGFjdGlvbj86IGNsb3Vkd2F0Y2guSUFsYXJtQWN0aW9uXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBDbG91ZFdhdGNoIEFsYXJtIHdpbGwgY2hhbmdlIGl0cyBzdGF0ZSB0byBBTEFSTSBpZiB0aGUgbnVtYmVyIG9mIENQVSBjcmVkaXRzIGRyb3BzIGJlbG93IHRoaXMgdGhyZXNob2xkLlxuICAgICAgICpcbiAgICAgICAqIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTRUMyL2xhdGVzdC9Vc2VyR3VpZGUvYnVyc3RhYmxlLWNyZWRpdHMtYmFzZWxpbmUtY29uY2VwdHMuaHRtbCNlYXJuaW5nLUNQVS1jcmVkaXRzIGZvciBhbiBvdmVydmlldyBvZiBtYXhpbXVtIENQVSBjcmVkaXRzIGZvciB2YXJpb3VzIGluc3RhbmNlIHR5cGVzLlxuICAgICAgICpcbiAgICAgICAqIEBkZWZhdWx0IDEwJSBvZiB0aGUgbWF4aW11bSBlYXJuZWQgQ1BVIGNyZWRpdHMgZm9yIHRoZSBpbnN0YW5jZSB0eXBlLlxuICAgICAgICovXG4gICAgICB0aHJlc2hvbGQ/OiBudW1iZXJcbiAgICB9LFxuICApOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICAhW1widDIuXCIsIFwidDMuXCIsIFwidDRnLlwiXS5zb21lKChzKSA9PlxuICAgICAgICB0aGlzLmluc3RhbmNlVHlwZS50b1N0cmluZygpLnN0YXJ0c1dpdGgocyksXG4gICAgICApXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQ1BVIGNyZWRpdHMgYXJlIG9ubHkgcmVsZXZhbnQgZm9yIGJ1cnN0YWJsZSBpbnN0YW5jZSB0eXBlcy5cIixcbiAgICAgIClcbiAgICB9XG5cbiAgICBjb25zdCBkZWZhdWx0VGhyZXNob2xkID1cbiAgICAgIGNwdUNyZWRpdEJhbGFuY2VCeUluc3RhbmNlVHlwZVt0aGlzLmluc3RhbmNlVHlwZS50b1N0cmluZygpXSAqIDAuMVxuICAgIGNvbnN0IHRocmVzaG9sZCA9IHByb3BzPy50aHJlc2hvbGQgPz8gZGVmYXVsdFRocmVzaG9sZFxuICAgIGlmICghdGhyZXNob2xkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBObyB0aHJlc2hvbGQgc3VwcGxpZWQsIGFuZCB1bmFibGUgdG8gZGV0ZXJtaW5lIGEgZGVmYXVsdCB2YWx1ZSBmb3IgaW5zdGFuY2UgdHlwZSAnJHt0aGlzLmluc3RhbmNlVHlwZS50b1N0cmluZygpfSdgLFxuICAgICAgKVxuICAgIH1cbiAgICBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJDUFVDcmVkaXRCYWxhbmNlXCIsXG4gICAgICBuYW1lc3BhY2U6IFwiQVdTL1JEU1wiLFxuICAgICAgc3RhdGlzdGljOiBcIk1pbmltdW1cIixcbiAgICAgIHBlcmlvZDogY2RrLkR1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIERCSW5zdGFuY2VJZGVudGlmaWVyOiB0aGlzLmRhdGFiYXNlSW5zdGFuY2VJZGVudGlmaWVyLFxuICAgICAgfSxcbiAgICB9KVxuICAgICAgLmNyZWF0ZUFsYXJtKHRoaXMsIFwiQ3JlZGl0c0FsYXJtXCIsIHtcbiAgICAgICAgYWxhcm1EZXNjcmlwdGlvbjogYExlc3MgdGhhbiAke3RocmVzaG9sZH0gQ1BVIGNyZWRpdHMgcmVtYWluaW5nIGZvciBSRFMgZGF0YWJhc2UgJyR7XG4gICAgICAgICAgdGhpcy5kYXRhYmFzZUluc3RhbmNlSWRlbnRpZmllclxuICAgICAgICB9Jy4gJHtcbiAgICAgICAgICB0aGlzLmluc3RhbmNlVHlwZS50b1N0cmluZygpLnN0YXJ0c1dpdGgoXCJ0Mi5cIilcbiAgICAgICAgICAgID8gXCJJZiB0aGlzIHJlYWNoZXMgMCwgdGhlIGluc3RhbmNlIHdpbGwgYmUgbGltaXRlZCB0byBhIGJhc2VsaW5lIENQVSB1dGlsaXphdGlvbi5cIlxuICAgICAgICAgICAgOiBcIklmIHRoZSBiYWxhbmNlIGlzIGRlcGxldGVkLCBBV1MgYWRkcyBhZGRpdGlvbmFsIGNoYXJnZXMuXCJcbiAgICAgICAgfS5gLFxuICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IGNsb3Vkd2F0Y2guQ29tcGFyaXNvbk9wZXJhdG9yLkxFU1NfVEhBTl9USFJFU0hPTEQsXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiAxLFxuICAgICAgICB0aHJlc2hvbGQ6IHRocmVzaG9sZCxcbiAgICAgICAgdHJlYXRNaXNzaW5nRGF0YTogY2xvdWR3YXRjaC5UcmVhdE1pc3NpbmdEYXRhLklHTk9SRSxcbiAgICAgIH0pXG4gICAgICAuYWRkQWxhcm1BY3Rpb24odGhpcy5hY3Rpb24pXG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCB0d28gQ2xvdWRXYXRjaCBBbGFybXMgZm9yIG1vbml0b3JpbmcgZGlzayBzdG9yYWdlIHNwYWNlOlxuICAgKiAxKSBvbmUgdGhhdCB0cmlnZ2VycyBpZiB0aGUgYXZhaWxhYmxlIGRpc2sgc3RvcmFnZSBzcGFjZSBpcyBsb3cuXG4gICAqIDIpIG9uZSB0aGF0IHRyaWdnZXJzIGlmIHRoZSBhdmFpbGFibGUgZGlzayBzdG9yYWdlIHNwYWNlIGlzIGNyaXRjYWxseSBsb3cuXG4gICAqXG4gICAqIFlvdSBtYXkgd2FudCB0byB1c2UgZGlmZmVyZW50IGFsYXJtIGFjdGlvbnMgZm9yIHRoZSB0d28gYWxhcm1zLCBlLmcuLCBvbmUgY2FuIGJlXG4gICAqIGNhdGVnb3JpemVkIGFzIGEgXCJ3YXJuaW5nXCIsIHdoaWxlIHRoZSBvdGhlciBvbmUgY2FuIGJlIGNvbnNpZGVyZWQgYW4gXCJhbGFybVwiLlxuICAgKi9cbiAgYWRkU3RvcmFnZVNwYWNlQWxhcm1zKHByb3BzPzoge1xuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyYXRpb24gZm9yIGFuIGFsYXJtLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgQ29uZmlndXJlZCB3aXRoIHNhbmUgZGVmYXVsdHMuXG4gICAgICovXG4gICAgbG93U3RvcmFnZVNwYWNlQWxhcm0/OiB7XG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgICAqL1xuICAgICAgZW5hYmxlZD86IGJvb2xlYW5cbiAgICAgIC8qKlxuICAgICAgICogQW4gYWN0aW9uIHRvIHVzZSBmb3IgQ2xvdWRXYXRjaCBhbGFybSBzdGF0ZSBjaGFuZ2VzIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgYWN0aW9uXG4gICAgICAgKi9cbiAgICAgIGFjdGlvbj86IGNsb3Vkd2F0Y2guSUFsYXJtQWN0aW9uXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDI1JSBvZiB0aGUgYWxsb2NhdGVkIHN0b3JhZ2UuXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IGNkay5TaXplXG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyYXRpb24gZm9yIGFuIGFsYXJtLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgQ29uZmlndXJlZCB3aXRoIHNhbmUgZGVmYXVsdHMuXG4gICAgICovXG4gICAgY3JpdGljYWxseUxvd1N0b3JhZ2VTcGFjZUFsYXJtPzoge1xuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCB0cnVlXG4gICAgICAgKi9cbiAgICAgIGVuYWJsZWQ/OiBib29sZWFuXG4gICAgICAvKipcbiAgICAgICAqIEFuIGFjdGlvbiB0byB1c2UgZm9yIENsb3VkV2F0Y2ggYWxhcm0gc3RhdGUgY2hhbmdlcyBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGFjdGlvblxuICAgICAgICovXG4gICAgICBhY3Rpb24/OiBjbG91ZHdhdGNoLklBbGFybUFjdGlvblxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCA1JSBvZiB0aGUgYWxsb2NhdGVkIHN0b3JhZ2UuXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IGNkay5TaXplXG4gICAgfVxuICB9KTogdm9pZCB7XG4gICAgY29uc3QgbG93U3RvcmFnZVNwYWNlQWxhcm0gPSBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZTogXCJGcmVlU3RvcmFnZVNwYWNlXCIsXG4gICAgICBuYW1lc3BhY2U6IFwiQVdTL1JEU1wiLFxuICAgICAgc3RhdGlzdGljOiBcIk1pbmltdW1cIixcbiAgICAgIHBlcmlvZDogY2RrLkR1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIERCSW5zdGFuY2VJZGVudGlmaWVyOiB0aGlzLmRhdGFiYXNlSW5zdGFuY2VJZGVudGlmaWVyLFxuICAgICAgfSxcbiAgICB9KS5jcmVhdGVBbGFybSh0aGlzLCBcIkxvd1N0b3JhZ2VTcGFjZUFsYXJtXCIsIHtcbiAgICAgIGFsYXJtRGVzY3JpcHRpb246IGBMb3cgc3RvcmFnZSBzcGFjZSBhdmFpbGFibGUgb24gUkRTIGRhdGFiYXNlICcke3RoaXMuZGF0YWJhc2VJbnN0YW5jZUlkZW50aWZpZXJ9Jy5gLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5MRVNTX1RIQU5fVEhSRVNIT0xELFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IDEsXG4gICAgICB0aHJlc2hvbGQ6XG4gICAgICAgIHByb3BzPy5sb3dTdG9yYWdlU3BhY2VBbGFybT8udGhyZXNob2xkPy50b0J5dGVzKCkgPz9cbiAgICAgICAgdGhpcy5hbGxvY2F0ZWRTdG9yYWdlLnRvQnl0ZXMoKSAqIDAuMjUsXG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOiBjbG91ZHdhdGNoLlRyZWF0TWlzc2luZ0RhdGEuSUdOT1JFLFxuICAgIH0pXG4gICAgaWYgKHByb3BzPy5sb3dTdG9yYWdlU3BhY2VBbGFybT8uZW5hYmxlZCA/PyB0cnVlKSB7XG4gICAgICBsb3dTdG9yYWdlU3BhY2VBbGFybS5hZGRBbGFybUFjdGlvbihcbiAgICAgICAgcHJvcHM/Lmxvd1N0b3JhZ2VTcGFjZUFsYXJtPy5hY3Rpb24gfHwgdGhpcy5hY3Rpb24sXG4gICAgICApXG4gICAgICBsb3dTdG9yYWdlU3BhY2VBbGFybS5hZGRPa0FjdGlvbihcbiAgICAgICAgcHJvcHM/Lmxvd1N0b3JhZ2VTcGFjZUFsYXJtPy5hY3Rpb24gfHwgdGhpcy5hY3Rpb24sXG4gICAgICApXG4gICAgfVxuXG4gICAgY29uc3QgY3JpdGljYWxseUxvd1N0b3JhZ2VTcGFjZUFsYXJtID0gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIG1ldHJpY05hbWU6IFwiRnJlZVN0b3JhZ2VTcGFjZVwiLFxuICAgICAgbmFtZXNwYWNlOiBcIkFXUy9SRFNcIixcbiAgICAgIHN0YXRpc3RpYzogXCJNaW5pbXVtXCIsXG4gICAgICBwZXJpb2Q6IGNkay5EdXJhdGlvbi5taW51dGVzKDUpLFxuICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICBEQkluc3RhbmNlSWRlbnRpZmllcjogdGhpcy5kYXRhYmFzZUluc3RhbmNlSWRlbnRpZmllcixcbiAgICAgIH0sXG4gICAgfSkuY3JlYXRlQWxhcm0odGhpcywgXCJDcml0aWNhbGx5TG93U3RvcmFnZVNwYWNlQWxhcm1cIiwge1xuICAgICAgYWxhcm1EZXNjcmlwdGlvbjogYENyaXRpY2FsbHkgbG93IHN0b3JhZ2Ugc3BhY2UgYXZhaWxhYmxlIG9uIFJEUyBkYXRhYmFzZSAnJHt0aGlzLmRhdGFiYXNlSW5zdGFuY2VJZGVudGlmaWVyfScuYCxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuTEVTU19USEFOX1RIUkVTSE9MRCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiAxLFxuICAgICAgdGhyZXNob2xkOlxuICAgICAgICBwcm9wcz8uY3JpdGljYWxseUxvd1N0b3JhZ2VTcGFjZUFsYXJtPy50aHJlc2hvbGQ/LnRvQnl0ZXMoKSA/P1xuICAgICAgICB0aGlzLmFsbG9jYXRlZFN0b3JhZ2UudG9CeXRlcygpICogMC4wNSxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5JR05PUkUsXG4gICAgfSlcbiAgICBpZiAocHJvcHM/LmNyaXRpY2FsbHlMb3dTdG9yYWdlU3BhY2VBbGFybT8uZW5hYmxlZCA/PyB0cnVlKSB7XG4gICAgICBjcml0aWNhbGx5TG93U3RvcmFnZVNwYWNlQWxhcm0uYWRkQWxhcm1BY3Rpb24oXG4gICAgICAgIHByb3BzPy5jcml0aWNhbGx5TG93U3RvcmFnZVNwYWNlQWxhcm0/LmFjdGlvbiB8fCB0aGlzLmFjdGlvbixcbiAgICAgIClcbiAgICAgIGNyaXRpY2FsbHlMb3dTdG9yYWdlU3BhY2VBbGFybS5hZGRPa0FjdGlvbihcbiAgICAgICAgcHJvcHM/LmNyaXRpY2FsbHlMb3dTdG9yYWdlU3BhY2VBbGFybT8uYWN0aW9uIHx8IHRoaXMuYWN0aW9uLFxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHVwIGEgQ2xvdWRXYXRjaCBBbGFybSB0aGF0IHRyaWdnZXJzIGlmIHRoZSBhdmVyYWdlIENQVSB1dGlsaXphdGlvbiBmb3JcbiAgICogdGhlIFJEUyBpbnN0YW5jZSBleGNlZWRzIGEgZ2l2ZW4gdGhyZXNob2xkLlxuICAgKi9cbiAgYWRkQ3B1VXRpbGl6YXRpb25BbGFybShcbiAgICAvKipcbiAgICAgKiBDb25maWd1cmF0aW9uIGZvciBhbiBhbGFybS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IENvbmZpZ3VyZWQgd2l0aCBzYW5lIGRlZmF1bHRzLlxuICAgICAqL1xuICAgIHByb3BzPzoge1xuICAgICAgLyoqXG4gICAgICAgKiBBbiBhY3Rpb24gdG8gdXNlIGZvciBDbG91ZFdhdGNoIGFsYXJtIHN0YXRlIGNoYW5nZXMgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBhY3Rpb25cbiAgICAgICAqL1xuICAgICAgYWN0aW9uPzogY2xvdWR3YXRjaC5JQWxhcm1BY3Rpb25cbiAgICAgIC8qKlxuICAgICAgICogVGhlIHRocmVzaG9sZCBkZWZpbmVkIGFzIGEgcGVyY2VudGFnZSB0aGF0IGRldGVybWluZXMgaWYgQ1BVIHV0aWxpemF0aW9uIHNob3VsZCB0cmlnZ2VyIGFuIGFsYXJtIG9yIG5vdC5cbiAgICAgICAqIEBkZWZhdWx0IDgwXG4gICAgICAgKi9cbiAgICAgIHRocmVzaG9sZD86IG51bWJlclxuICAgICAgLyoqXG4gICAgICAgKiBAZGVmYXVsdCA1XG4gICAgICAgKi9cbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyXG4gICAgICAvKipcbiAgICAgICAqIEBkZWZhdWx0IDIgbWludXRlc1xuICAgICAgICovXG4gICAgICBwZXJpb2Q/OiBjZGsuRHVyYXRpb25cbiAgICB9LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBhbGFybSA9IG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICBtZXRyaWNOYW1lOiBcIkNQVVV0aWxpemF0aW9uXCIsXG4gICAgICBuYW1lc3BhY2U6IFwiQVdTL1JEU1wiLFxuICAgICAgc3RhdGlzdGljOiBcIkF2ZXJhZ2VcIixcbiAgICAgIHBlcmlvZDogcHJvcHM/LnBlcmlvZCA/PyBjZGsuRHVyYXRpb24ubWludXRlcygyKSxcbiAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgREJJbnN0YW5jZUlkZW50aWZpZXI6IHRoaXMuZGF0YWJhc2VJbnN0YW5jZUlkZW50aWZpZXIsXG4gICAgICB9LFxuICAgIH0pLmNyZWF0ZUFsYXJtKHRoaXMsIFwiQ3B1VXRpbGl6YXRpb25BbGFybVwiLCB7XG4gICAgICBhbGFybURlc2NyaXB0aW9uOiBgUkRTIGRhdGFiYXNlICcke3RoaXMuZGF0YWJhc2VJbnN0YW5jZUlkZW50aWZpZXJ9JyBoYXMgYSBoaWdoZXIgdGhhbiBleHBlY3RlZCBDUFUgdXRpbGl6YXRpb24uYCxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBwcm9wcz8uZXZhbHVhdGlvblBlcmlvZHMgPz8gNSxcbiAgICAgIHRocmVzaG9sZDogcHJvcHM/LnRocmVzaG9sZCA/PyA4MCxcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6IGNsb3Vkd2F0Y2guVHJlYXRNaXNzaW5nRGF0YS5JR05PUkUsXG4gICAgfSlcbiAgICBhbGFybS5hZGRBbGFybUFjdGlvbihwcm9wcz8uYWN0aW9uID8/IHRoaXMuYWN0aW9uKVxuICAgIGFsYXJtLmFkZE9rQWN0aW9uKHByb3BzPy5hY3Rpb24gPz8gdGhpcy5hY3Rpb24pXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,3 @@
1
+ export { DatabaseAlarms, DatabaseAlarmsProps } from "./database-alarms";
2
+ export { ServiceAlarms, ServiceAlarmsProps } from "./service-alarms";
3
+ export { SlackAlarm, SlackAlarmProps } from "./slack-alarm";
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SlackAlarm = exports.ServiceAlarms = exports.DatabaseAlarms = void 0;
4
+ var database_alarms_1 = require("./database-alarms");
5
+ Object.defineProperty(exports, "DatabaseAlarms", { enumerable: true, get: function () { return database_alarms_1.DatabaseAlarms; } });
6
+ var service_alarms_1 = require("./service-alarms");
7
+ Object.defineProperty(exports, "ServiceAlarms", { enumerable: true, get: function () { return service_alarms_1.ServiceAlarms; } });
8
+ var slack_alarm_1 = require("./slack-alarm");
9
+ Object.defineProperty(exports, "SlackAlarm", { enumerable: true, get: function () { return slack_alarm_1.SlackAlarm; } });
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWxhcm1zL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFEQUF1RTtBQUE5RCxpSEFBQSxjQUFjLE9BQUE7QUFDdkIsbURBQW9FO0FBQTNELCtHQUFBLGFBQWEsT0FBQTtBQUN0Qiw2Q0FBMkQ7QUFBbEQseUdBQUEsVUFBVSxPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgRGF0YWJhc2VBbGFybXMsIERhdGFiYXNlQWxhcm1zUHJvcHMgfSBmcm9tIFwiLi9kYXRhYmFzZS1hbGFybXNcIlxuZXhwb3J0IHsgU2VydmljZUFsYXJtcywgU2VydmljZUFsYXJtc1Byb3BzIH0gZnJvbSBcIi4vc2VydmljZS1hbGFybXNcIlxuZXhwb3J0IHsgU2xhY2tBbGFybSwgU2xhY2tBbGFybVByb3BzIH0gZnJvbSBcIi4vc2xhY2stYWxhcm1cIlxuIl19