@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.
- package/assets/cloudtrail-slack-integration-lambda/main.py +267 -0
- package/assets/pipeline-slack-notification-lambda/index.py +300 -0
- package/assets/prepare-cdk-source-lambda/index.py +159 -0
- package/assets/slack-alarm-lambda/index.py +103 -0
- package/lib/alarms/database-alarms.d.ts +125 -0
- package/lib/alarms/database-alarms.js +171 -0
- package/lib/alarms/index.d.ts +3 -0
- package/lib/alarms/index.js +10 -0
- package/lib/alarms/service-alarms.d.ts +145 -0
- package/lib/alarms/service-alarms.js +148 -0
- package/lib/alarms/ses-alarms.d.ts +67 -0
- package/lib/alarms/ses-alarms.js +49 -0
- package/lib/alarms/slack-alarm.d.ts +25 -0
- package/lib/alarms/slack-alarm.js +47 -0
- package/lib/bastion-host.d.ts +41 -0
- package/lib/bastion-host.js +86 -0
- package/lib/bin/cdk-create-snapshots.d.ts +2 -0
- package/lib/bin/fetch-pipeline-variables.d.ts +2 -0
- package/lib/build-artifacts/index.d.ts +68 -0
- package/lib/build-artifacts/index.js +118 -0
- package/lib/cdk-deploy/cdk-deploy.d.ts +63 -0
- package/lib/cdk-deploy/cdk-deploy.js +175 -0
- package/lib/cdk-deploy/index.d.ts +1 -0
- package/lib/cdk-deploy/index.js +6 -0
- package/lib/cdk-deploy/start-deploy-handler.d.ts +8 -0
- package/lib/cdk-deploy/start-deploy-handler.js +72 -0
- package/lib/cdk-deploy/status-handler.d.ts +6 -0
- package/lib/cdk-deploy/status-handler.js +83 -0
- package/lib/cdk-pipelines/cloud-assembly-lookup-handler.d.ts +6 -0
- package/lib/cdk-pipelines/cloud-assembly-lookup-handler.js +63 -0
- package/lib/cdk-pipelines/index.d.ts +3 -0
- package/lib/cdk-pipelines/index.js +10 -0
- package/lib/cdk-pipelines/liflig-cdk-pipeline.d.ts +110 -0
- package/lib/cdk-pipelines/liflig-cdk-pipeline.js +232 -0
- package/lib/cdk-pipelines/slack-notification.d.ts +51 -0
- package/lib/cdk-pipelines/slack-notification.js +54 -0
- package/lib/cdk-pipelines/variables.d.ts +15 -0
- package/lib/cdk-pipelines/variables.js +80 -0
- package/lib/cloudtrail-slack-integration/cloudtrail-slack-integration.d.ts +47 -0
- package/lib/cloudtrail-slack-integration/cloudtrail-slack-integration.js +211 -0
- package/lib/cloudtrail-slack-integration/index.d.ts +1 -0
- package/lib/cloudtrail-slack-integration/index.js +6 -0
- package/lib/configure-parameters/configure-parameters.d.ts +61 -0
- package/lib/configure-parameters/configure-parameters.js +94 -0
- package/lib/configure-parameters/index.d.ts +1 -0
- package/lib/configure-parameters/index.js +6 -0
- package/lib/cross-region-ssm-parameter.d.ts +13 -0
- package/lib/cross-region-ssm-parameter.js +46 -0
- package/lib/ecs/cluster.d.ts +25 -0
- package/lib/ecs/cluster.js +70 -0
- package/lib/ecs/fargate-service.d.ts +63 -0
- package/lib/ecs/fargate-service.js +98 -0
- package/lib/ecs/index.d.ts +3 -0
- package/lib/ecs/index.js +10 -0
- package/lib/ecs/listener-rule.d.ts +25 -0
- package/lib/ecs/listener-rule.js +27 -0
- package/lib/ecs-update-image/artifact-status.d.ts +39 -0
- package/lib/ecs-update-image/artifact-status.js +41 -0
- package/lib/ecs-update-image/ecs-update-image.d.ts +41 -0
- package/lib/ecs-update-image/ecs-update-image.js +98 -0
- package/lib/ecs-update-image/index.d.ts +3 -0
- package/lib/ecs-update-image/index.js +10 -0
- package/lib/ecs-update-image/start-deploy-handler.d.ts +6 -0
- package/lib/ecs-update-image/start-deploy-handler.js +104 -0
- package/lib/ecs-update-image/status-handler.d.ts +11 -0
- package/lib/ecs-update-image/status-handler.js +74 -0
- package/lib/ecs-update-image/tag.d.ts +47 -0
- package/lib/ecs-update-image/tag.js +67 -0
- package/lib/feature-flags.d.ts +18 -0
- package/lib/feature-flags.js +48 -0
- package/lib/griid/artefact-bucket.d.ts +7 -0
- package/lib/griid/artefact-bucket.js +30 -0
- package/lib/griid/index.d.ts +4 -0
- package/lib/griid/index.js +18 -0
- package/lib/hosted-zone-with-param.d.ts +29 -0
- package/lib/hosted-zone-with-param.js +65 -0
- package/lib/index.d.ts +32 -0
- package/lib/kinesis/index.d.ts +1 -0
- package/lib/kinesis/index.js +6 -0
- package/lib/kinesis/kinesis-to-datadog-stream.d.ts +28 -0
- package/lib/kinesis/kinesis-to-datadog-stream.js +126 -0
- package/lib/load-balancer/index.d.ts +1 -0
- package/lib/load-balancer/index.js +6 -0
- package/lib/load-balancer/load-balancer.d.ts +16 -0
- package/lib/load-balancer/load-balancer.js +60 -0
- package/lib/pipelines/conventions.d.ts +14 -0
- package/lib/pipelines/conventions.js +24 -0
- package/lib/pipelines/deploy-env.d.ts +18 -0
- package/lib/pipelines/deploy-env.js +96 -0
- package/lib/pipelines/index.d.ts +2 -0
- package/lib/pipelines/index.js +8 -0
- package/lib/pipelines/liflig-cdk-deployer-deps.d.ts +13 -0
- package/lib/pipelines/liflig-cdk-deployer-deps.js +35 -0
- package/lib/pipelines/pipeline.d.ts +78 -0
- package/lib/pipelines/pipeline.js +224 -0
- package/lib/platform/index.d.ts +1 -0
- package/lib/platform/index.js +7 -0
- package/lib/platform/platform.d.ts +37 -0
- package/lib/platform/platform.js +57 -0
- package/lib/rds/database.d.ts +49 -0
- package/lib/rds/database.js +60 -0
- package/lib/rds/index.d.ts +1 -0
- package/lib/rds/index.js +6 -0
- package/lib/ses/configurationsetdeliveryoptions/index.d.ts +26 -0
- package/lib/ses/configurationsetdeliveryoptions/index.js +48 -0
- package/lib/ses/configurationsetsnsdestination/handler.d.ts +17 -0
- package/lib/ses/configurationsetsnsdestination/handler.js +75 -0
- package/lib/ses/configurationsetsnsdestination/index.d.ts +29 -0
- package/lib/ses/configurationsetsnsdestination/index.js +75 -0
- package/lib/ses/index.d.ts +4 -0
- package/lib/ses/index.js +12 -0
- package/lib/ses/sesdomain/handler.d.ts +10 -0
- package/lib/ses/sesdomain/handler.js +82 -0
- package/lib/ses/sesdomain/index.d.ts +57 -0
- package/lib/ses/sesdomain/index.js +94 -0
- package/lib/ses/sesverifyemail/handler.d.ts +9 -0
- package/lib/ses/sesverifyemail/handler.js +25 -0
- package/lib/ses/sesverifyemail/index.d.ts +13 -0
- package/lib/ses/sesverifyemail/index.js +51 -0
- package/lib/snapshots.d.ts +4 -0
- package/lib/snapshots.js +214 -0
- package/lib/ssm-parameter-backed-resource.d.ts +45 -0
- package/lib/ssm-parameter-backed-resource.js +67 -0
- package/lib/ssm-parameter-reader.d.ts +21 -0
- package/lib/ssm-parameter-reader.js +48 -0
- package/lib/tags.d.ts +8 -0
- package/lib/tags.js +36 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +17 -0
- package/lib/webapp/index.d.ts +3 -0
- package/lib/webapp/index.js +10 -0
- package/lib/webapp/monitor.d.ts +187 -0
- package/lib/webapp/monitor.js +156 -0
- package/lib/webapp/security-headers.d.ts +38 -0
- package/lib/webapp/security-headers.js +129 -0
- package/lib/webapp/webapp.d.ts +116 -0
- package/lib/webapp/webapp.js +118 -0
- package/lib/webapp-deploy-via-role.d.ts +25 -0
- package/lib/webapp-deploy-via-role.js +32 -0
- 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,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
|