@gammarers/aws-rds-database-running-schedule-stack
Version:
AWS RDS Database Running Scheduler
208 lines β’ 31.8 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RDSDatabaseRunningScheduleStack = exports.RDSDatabaseRunningScheduleStackMachineLogLevel = exports.RDSDatabaseRunningScheduleStackResourceNamingType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_resource_naming_1 = require("@gammarers/aws-resource-naming");
Object.defineProperty(exports, "RDSDatabaseRunningScheduleStackResourceNamingType", { enumerable: true, get: function () { return aws_resource_naming_1.ResourceNamingType; } });
const aws_sns_slack_message_lambda_subscription_1 = require("@gammarers/aws-sns-slack-message-lambda-subscription");
const cdk = require("aws-cdk-lib");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const iam = require("aws-cdk-lib/aws-iam");
const logs = require("aws-cdk-lib/aws-logs");
const scheduler = require("aws-cdk-lib/aws-scheduler");
const sns = require("aws-cdk-lib/aws-sns");
const aws_stepfunctions_1 = require("aws-cdk-lib/aws-stepfunctions");
Object.defineProperty(exports, "RDSDatabaseRunningScheduleStackMachineLogLevel", { enumerable: true, get: function () { return aws_stepfunctions_1.LogLevel; } });
const running_control_state_machine_1 = require("./resources/running-control-state-machine");
class RDSDatabaseRunningScheduleStack extends aws_cdk_lib_1.Stack {
constructor(scope, id, props) {
super(scope, id, props);
// π Create random 8 length string
const random = aws_resource_naming_1.ResourceNaming.createRandomString(`${cdk.Names.uniqueId(scope)}-${cdk.Names.uniqueId(this)}`);
// π Definition auto naming
const autoNaming = {
notificationTopicName: `rds-db-running-schedule-notification-${random}-topic`,
notificationTopicDisplayName: 'RDS DB Running Schedule Notification Topic',
stateMachineName: `rds-db-running-schedule-${random}-state-machine`,
stateMachineRoleName: `rds-db-running-schedule-${random}-state-machine-role`,
schedulerRoleName: `rds-db-running-scheduler-${random}-exec-role`,
startScheduleName: `rds-database-running-stop-${random}-schedule`,
stopScheduleName: `rds-database-running-start-${random}-schedule`,
};
// πγfinal naming
const names = aws_resource_naming_1.ResourceNaming.naming(autoNaming, props.resourceNamingOption);
// π SNS Topic for notifications
const topic = new sns.Topic(this, 'NotificationTopic', {
topicName: names.notificationTopicName,
displayName: names.notificationTopicDisplayName,
});
// π Subscribe an email endpoint to the topic
const emails = props.notifications?.emails ?? [];
for (const [index, value] of emails.entries()) {
new sns.Subscription(this, `SubscriptionEmail${index.toString().padStart(3, '0')}`, {
topic,
protocol: sns.SubscriptionProtocol.EMAIL,
endpoint: value,
});
}
// π Subscription slack webhook
if (props.notifications?.slack) {
new aws_sns_slack_message_lambda_subscription_1.SNSSlackMessageLambdaSubscription(this, 'SNSSlackMessageLambdaSubscription', {
topic,
slackWebhookSecretName: props.notifications.slack.webhookSecretName,
});
}
// π StepFunctions State Machine
const stateMachine = new running_control_state_machine_1.RunningControlStateMachine(this, 'StateMachine', {
stateMachineName: names.stateMachineName,
notificationTopic: topic,
timeout: (() => {
if (props.timeoutOption?.stateMachineTimeout) {
return props.timeoutOption?.stateMachineTimeout;
}
return aws_cdk_lib_1.Duration.hours(1);
})(),
logs: (() => {
if (props.logOption?.machineLogLevel) {
return {
destination: new logs.LogGroup(this, 'StateMachineLogGroup', {
logGroupName: (() => {
if (names.stateMachineName) {
return `/aws/states/${names.stateMachineName}`;
}
return undefined;
})(),
}),
level: props.logOption.machineLogLevel,
};
}
return undefined;
})(),
});
// π rename role name & description.
if (names.stateMachineRoleName) {
const role = stateMachine.node.findChild('Role');
const cfnRole = role.node.defaultChild;
cfnRole.addPropertyOverride('RoleName', names.stateMachineRoleName);
cfnRole.addPropertyOverride('Description', 'RDS DB Running machine role.');
const policy = role.node.findChild('DefaultPolicy');
const cfnPolicy = policy.node.defaultChild;
cfnPolicy.addPropertyOverride('PolicyName', `rds-db-running-schedule-${random}-state-machine-policy`);
}
// π StateMachine Exec Role of Scheduler
const schedulerExecRole = new iam.Role(this, 'SchedulerExecutionRole', {
roleName: names.schedulerRoleName,
description: 'RDS DB Running scheduler role',
assumedBy: new iam.ServicePrincipal('scheduler.amazonaws.com'),
inlinePolicies: {
'state-machine-exec-policy': new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'states:StartExecution',
],
resources: [
stateMachine.stateMachineArn,
],
}),
],
}),
},
});
// π Schedule state
const sheduleState = (() => {
if (props.enableScheduling === undefined || props.enableScheduling) {
return 'ENABLED';
}
else {
return 'DISABLED';
}
})();
// π Stop Schedule expression
const stopScheduleExpression = (() => {
// default: weekday 21:10
const minute = props.stopSchedule?.minute ?? '10';
const hour = props.stopSchedule?.hour ?? '21';
const week = props.stopSchedule?.week ?? 'MON-FRI';
return `cron(${minute} ${hour} ? * ${week} *)`;
})();
// π Start Schedule expression
const startScheduleExpression = (() => {
// default: weekday 07:50
const minute = props.startSchedule?.minute ?? '50';
const hour = props.startSchedule?.hour ?? '7';
const week = props.startSchedule?.week ?? 'MON-FRI';
return `cron(${minute} ${hour} ? * ${week} *)`;
})();
// π Stop DB schedule
new DBRuningSchedule(this, 'StopDatabaseRunningSchedule', {
name: names.startScheduleName,
description: 'stop database(instance/cluster) running stop schedule.',
sheduleState,
timezone: props.stopSchedule?.timezone ?? 'UTC',
expression: stopScheduleExpression,
target: {
stateMachineArn: stateMachine.stateMachineArn,
roleArn: schedulerExecRole.roleArn,
resourceTag: {
key: props.targetResource.tagKey,
values: props.targetResource.tagValues,
},
input: { mode: 'Stop' },
},
});
// π Start DB schedule
new DBRuningSchedule(this, 'StartDatabaseRunningSchedule', {
name: names.stopScheduleName,
description: 'start db instance schedule.',
sheduleState,
timezone: props.startSchedule?.timezone ?? 'UTC',
expression: startScheduleExpression,
target: {
stateMachineArn: stateMachine.stateMachineArn,
roleArn: schedulerExecRole.roleArn,
resourceTag: {
key: props.targetResource.tagKey,
values: props.targetResource.tagValues,
},
input: { mode: 'Start' },
},
});
}
}
exports.RDSDatabaseRunningScheduleStack = RDSDatabaseRunningScheduleStack;
_a = JSII_RTTI_SYMBOL_1;
RDSDatabaseRunningScheduleStack[_a] = { fqn: "@gammarers/aws-rds-database-running-schedule-stack.RDSDatabaseRunningScheduleStack", version: "2.8.4" };
class DBRuningSchedule extends scheduler.CfnSchedule {
constructor(scope, id, props) {
super(scope, id, {
name: props.name,
description: props.description,
state: props.sheduleState,
//groupName: scheduleGroup.name, // default
flexibleTimeWindow: {
mode: 'OFF',
},
scheduleExpressionTimezone: props.timezone,
scheduleExpression: props.expression,
target: {
arn: props.target.stateMachineArn,
roleArn: props.target.roleArn,
input: JSON.stringify({
Params: {
TagKey: props.target.resourceTag.key,
TagValues: props.target.resourceTag.values,
Mode: props.target.input.mode,
},
}),
retryPolicy: {
maximumEventAgeInSeconds: 60,
maximumRetryAttempts: 0,
},
},
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx3RUFLd0M7QUFhdEMsa0lBZHNCLHdDQUFpRCxPQWN0QjtBQVpuRCxvSEFBeUc7QUFDekcsbUNBQW1DO0FBQ25DLDZDQUEwRDtBQUMxRCwyQ0FBMkM7QUFDM0MsNkNBQTZDO0FBQzdDLHVEQUF1RDtBQUN2RCwyQ0FBMkM7QUFDM0MscUVBQTJHO0FBTXpHLCtIQU5tQiw0QkFBOEMsT0FNbkI7QUFKaEQsNkZBQXVGO0FBNER2RixNQUFhLCtCQUFnQyxTQUFRLG1CQUFLO0lBQ3hELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBMkM7UUFDbkYsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFeEIsbUNBQW1DO1FBQ25DLE1BQU0sTUFBTSxHQUFHLG9DQUFjLENBQUMsa0JBQWtCLENBQUMsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0csNEJBQTRCO1FBQzVCLE1BQU0sVUFBVSxHQUFHO1lBQ2pCLHFCQUFxQixFQUFFLHdDQUF3QyxNQUFNLFFBQVE7WUFDN0UsNEJBQTRCLEVBQUUsNENBQTRDO1lBQzFFLGdCQUFnQixFQUFFLDJCQUEyQixNQUFNLGdCQUFnQjtZQUNuRSxvQkFBb0IsRUFBRSwyQkFBMkIsTUFBTSxxQkFBcUI7WUFDNUUsaUJBQWlCLEVBQUUsNEJBQTRCLE1BQU0sWUFBWTtZQUNqRSxpQkFBaUIsRUFBRSw2QkFBNkIsTUFBTSxXQUFXO1lBQ2pFLGdCQUFnQixFQUFFLDhCQUE4QixNQUFNLFdBQVc7U0FDbEUsQ0FBQztRQUNGLGtCQUFrQjtRQUNsQixNQUFNLEtBQUssR0FBRyxvQ0FBYyxDQUFDLE1BQU0s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MkNBQTJDO1lBQzNDLGtCQUFrQixFQUFFO2dCQUNsQixJQUFJLEVBQUUsS0FBSzthQUNaO1lBQ0QsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLFFBQVE7WUFDMUMsa0JBQWtCLEVBQUUsS0FBSyxDQUFDLFVBQVU7WUFDcEMsTUFBTSxFQUFFO2dCQUNOLEdBQUcsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLGVBQWU7Z0JBQ2pDLE9BQU8sRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU87Z0JBQzdCLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUNwQixNQUFNLEVBQUU7d0JBQ04sTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUc7d0JBQ3BDLFNBQVMsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNO3dCQUMxQyxJQUFJLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSTtxQkFDOUI7aUJBQ0YsQ0FBQztnQkFDRixXQUFXLEVBQUU7b0JBQ1gsd0JBQXdCLEVBQUUsRUFBRTtvQkFDNUIsb0JBQW9CLEVBQUUsQ0FBQztpQkFDeEI7YUFDRjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIFJlc291cmNlQXV0b05hbWluZyxcbiAgUmVzb3VyY2VEZWZhdWx0TmFtaW5nLFxuICBSZXNvdXJjZU5hbWluZyxcbiAgUmVzb3VyY2VOYW1pbmdUeXBlIGFzIFJEU0RhdGFiYXNlUnVubmluZ1NjaGVkdWxlU3RhY2tSZXNvdXJjZU5hbWluZ1R5cGUsXG59IGZyb20gJ0BnYW1tYXJlcnMvYXdzLXJlc291cmNlLW5hbWluZyc7XG5pbXBvcnQgeyBTTlNTbGFja01lc3NhZ2VMYW1iZGFTdWJzY3JpcHRpb24gfSBmcm9tICdAZ2FtbWFyZXJzL2F3cy1zbnMtc2xhY2stbWVzc2FnZS1sYW1iZGEtc3Vic2NyaXB0aW9uJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBEdXJhdGlvbiwgU3RhY2ssIFN0YWNrUHJvcHMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsb2dzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHNjaGVkdWxlciBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc2NoZWR1bGVyJztcbmltcG9ydCAqIGFzIHNucyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zJztcbmltcG9ydCB7IExvZ0xldmVsIGFzIFJEU0RhdGFiYXNlUnVubmluZ1NjaGVkdWxlU3RhY2tNYWNoaW5lTG9nTGV2ZWwgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IFJ1bm5pbmdDb250cm9sU3RhdGVNYWNoaW5lIH0gZnJvbSAnLi9yZXNvdXJjZXMvcnVubmluZy1jb250cm9sLXN0YXRlLW1hY2hpbmUnO1xuXG5leHBvcnQge1xuICBSRFNEYXRhYmFzZVJ1bm5pbmdTY2hlZHVsZVN0YWNrUmVzb3VyY2VOYW1pbmdUeXBlLFxuICBSRFNEYXRhYmFzZVJ1bm5pbmdTY2hlZHVsZVN0YWNrTWFjaGluZUxvZ0xldmVsLFxufTtcblxuZXhwb3J0IGludGVyZmFjZSBSZXNvdXJjZUN1c3RvbU5hbWluZyB7XG4gIHJlYWRvbmx5IHR5cGU6IFJEU0RhdGFiYXNlUnVubmluZ1NjaGVkdWxlU3RhY2tSZXNvdXJjZU5hbWluZ1R5cGUuQ1VTVE9NO1xuICByZWFkb25seSBub3RpZmljYXRpb25Ub3BpY05hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgbm90aWZpY2F0aW9uVG9waWNEaXNwbGF5TmFtZTogc3RyaW5nO1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmVOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0YXRlTWFjaGluZVJvbGVOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNjaGVkdWxlclJvbGVOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0YXJ0U2NoZWR1bGVOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0b3BTY2hlZHVsZU5hbWU6IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgUmVzb3VyY2VOYW1pbmdPcHRpb24gPSBSZXNvdXJjZURlZmF1bHROYW1pbmcgfCBSZXNvdXJjZUF1dG9OYW1pbmcgfCBSZXNvdXJjZUN1c3RvbU5hbWluZztcblxuZXhwb3J0IGludGVyZmFjZSBTY2hlZHVsZSB7XG4gIHJlYWRvbmx5IHRpbWV6b25lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG1pbnV0ZT86IHN0cmluZztcbiAgcmVhZG9ubHkgaG91cj86IHN0cmluZztcbiAgcmVhZG9ubHkgd2Vlaz86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUYXJnZXRSZXNvdXJjZSB7XG4gIHJlYWRvbmx5IHRhZ0tleTogc3RyaW5nO1xuICByZWFkb25seSB0YWdWYWx1ZXM6IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNsYWNrIHtcbiAgcmVhZG9ubHkgd2ViaG9va1NlY3JldE5hbWU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOb3RpZmljYXRpb25zIHtcbiAgcmVhZG9ubHkgZW1haWxzPzogc3RyaW5nW107XG4gIHJlYWRvbmx5IHNsYWNrPzogU2xhY2s7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9nT3B0aW9uIHtcbiAgcmVhZG9ubHkgbWFjaGluZUxvZ0xldmVsPzogUkRTRGF0YWJhc2VSdW5uaW5nU2NoZWR1bGVTdGFja01hY2hpbmVMb2dMZXZlbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUaW1lb3V0T3B0aW9uIHtcbiAgcmVhZG9ubHkgc3RhdGVNYWNoaW5lVGltZW91dD86IER1cmF0aW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJEU0RhdGFiYXNlUnVubmluZ1NjaGVkdWxlU3RhY2tQcm9wcyBleHRlbmRzIFN0YWNrUHJvcHMge1xuICByZWFkb25seSB0YXJnZXRSZXNvdXJjZTogVGFyZ2V0UmVzb3VyY2U7XG4gIHJlYWRvbmx5IGVuYWJsZVNjaGVkdWxpbmc/OiBib29sZWFuO1xuICByZWFkb25seSBzdG9wU2NoZWR1bGU/OiBTY2hlZHVsZTtcbiAgcmVhZG9ubHkgc3RhcnRTY2hlZHVsZT86IFNjaGVkdWxlO1xuICByZWFkb25seSBub3RpZmljYXRpb25zPzogTm90aWZpY2F0aW9ucztcbiAgcmVhZG9ubHkgcmVzb3VyY2VOYW1pbmdPcHRpb24/OiBSZXNvdXJjZU5hbWluZ09wdGlvbjtcbiAgcmVhZG9ubHkgdGltZW91dE9wdGlvbj86IFRpbWVvdXRPcHRpb247XG4gIHJlYWRvbmx5IGxvZ09wdGlvbj86IExvZ09wdGlvbjtcbn1cblxuZXhwb3J0IGNsYXNzIFJEU0RhdGFiYXNlUnVubmluZ1NjaGVkdWxlU3RhY2sgZXh0ZW5kcyBTdGFjayB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBSRFNEYXRhYmFzZVJ1bm5pbmdTY2hlZHVsZVN0YWNrUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcblxuICAgIC8vIPCfkYcgQ3JlYXRlIHJhbmRvbSA4IGxlbmd0aCBzdHJpbmdcbiAgICBjb25zdCByYW5kb20gPSBSZXNvdXJjZU5hbWluZy5jcmVhdGVSYW5kb21TdHJpbmcoYCR7Y2RrLk5hbWVzLnVuaXF1ZUlkKHNjb3BlKX0tJHtjZGsuTmFtZXMudW5pcXVlSWQodGhpcyl9YCk7XG4gICAgLy8g8J+RhyBEZWZpbml0aW9uIGF1dG8gbmFtaW5nXG4gICAgY29uc3QgYXV0b05hbWluZyA9IHtcbiAgICAgIG5vdGlmaWNhdGlvblRvcGljTmFtZTogYHJkcy1kYi1ydW5uaW5nLXNjaGVkdWxlLW5vdGlmaWNhdGlvbi0ke3JhbmRvbX0tdG9waWNgLFxuICAgICAgbm90aWZpY2F0aW9uVG9waWNEaXNwbGF5TmFtZTogJ1JEUyBEQiBSdW5uaW5nIFNjaGVkdWxlIE5vdGlmaWNhdGlvbiBUb3BpYycsXG4gICAgICBzdGF0ZU1hY2hpbmVOYW1lOiBgcmRzLWRiLXJ1bm5pbmctc2NoZWR1bGUtJHtyYW5kb219LXN0YXRlLW1hY2hpbmVgLFxuICAgICAgc3RhdGVNYWNoaW5lUm9sZU5hbWU6IGByZHMtZGItcnVubmluZy1zY2hlZHVsZS0ke3JhbmRvbX0tc3RhdGUtbWFjaGluZS1yb2xlYCxcbiAgICAgIHNjaGVkdWxlclJvbGVOYW1lOiBgcmRzLWRiLXJ1bm5pbmctc2NoZWR1bGVyLSR7cmFuZG9tfS1leGVjLXJvbGVgLFxuICAgICAgc3RhcnRTY2hlZHVsZU5hbWU6IGByZHMtZGF0YWJhc2UtcnVubmluZy1zdG9wLSR7cmFuZG9tfS1zY2hlZHVsZWAsXG4gICAgICBzdG9wU2NoZWR1bGVOYW1lOiBgcmRzLWRhdGFiYXNlLXJ1bm5pbmctc3RhcnQtJHtyYW5kb219LXNjaGVkdWxlYCxcbiAgICB9O1xuICAgIC8vIPCfkYfjgIBmaW5hbCBuYW1pbmdcbiAgICBjb25zdCBuYW1lcyA9IFJlc291cmNlTmFtaW5nLm5hbWluZyhhdXRvTmFtaW5nLCBwcm9wcy5yZXNvdXJjZU5hbWluZ09wdGlvbiBhcyBSZXNvdXJjZU5hbWluZy5SZXNvdXJjZU5hbWluZ09wdGlvbik7XG5cbiAgICAvLyDwn5GHIFNOUyBUb3BpYyBmb3Igbm90aWZpY2F0aW9uc1xuICAgIGNvbnN0IHRvcGljOiBzbnMuVG9waWMgPSBuZXcgc25zLlRvcGljKHRoaXMsICdOb3RpZmljYXRpb25Ub3BpYycsIHtcbiAgICAgIHRvcGljTmFtZTogbmFtZXMubm90aWZpY2F0aW9uVG9waWNOYW1lLFxuICAgICAgZGlzcGxheU5hbWU6IG5hbWVzLm5vdGlmaWNhdGlvblRvcGljRGlzcGxheU5hbWUsXG4gICAgfSk7XG5cbiAgICAvLyDwn5GHIFN1YnNjcmliZSBhbiBlbWFpbCBlbmRwb2ludCB0byB0aGUgdG9waWNcbiAgICBjb25zdCBlbWFpbHMgPSBwcm9wcy5ub3RpZmljYXRpb25zPy5lbWFpbHMgPz8gW107XG4gICAgZm9yIChjb25zdCBbaW5kZXgsIHZhbHVlXSBvZiBlbWFpbHMuZW50cmllcygpKSB7XG4gICAgICBuZXcgc25zLlN1YnNjcmlwdGlvbih0aGlzLCBgU3Vic2NyaXB0aW9uRW1haWwke2luZGV4LnRvU3RyaW5nKCkucGFkU3RhcnQoMywgJzAnKX1gLCB7XG4gICAgICAgIHRvcGljLFxuICAgICAgICBwcm90b2NvbDogc25zLlN1YnNjcmlwdGlvblByb3RvY29sLkVNQUlMLFxuICAgICAgICBlbmRwb2ludDogdmFsdWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyDwn5GHIFN1YnNjcmlwdGlvbiBzbGFjayB3ZWJob29rXG4gICAgaWYgKHByb3BzLm5vdGlmaWNhdGlvbnM/LnNsYWNrKSB7XG4gICAgICBuZXcgU05TU2xhY2tNZXNzYWdlTGFtYmRhU3Vic2NyaXB0aW9uKHRoaXMsICdTTlNTbGFja01lc3NhZ2VMYW1iZGFTdWJzY3JpcHRpb24nLCB7XG4gICAgICAgIHRvcGljLFxuICAgICAgICBzbGFja1dlYmhvb2tTZWNyZXROYW1lOiBwcm9wcy5ub3RpZmljYXRpb25zLnNsYWNrLndlYmhvb2tTZWNyZXROYW1lLFxuICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvLyDwn5GHIFN0ZXBGdW5jdGlvbnMgU3RhdGUgTWFjaGluZVxuICAgIGNvbnN0IHN0YXRlTWFjaGluZSA9IG5ldyBSdW5uaW5nQ29udHJvbFN0YXRlTWFjaGluZSh0aGlzLCAnU3RhdGVNYWNoaW5lJywge1xuICAgICAgc3RhdGVNYWNoaW5lTmFtZTogbmFtZXMuc3RhdGVNYWNoaW5lTmFtZSxcbiAgICAgIG5vdGlmaWNhdGlvblRvcGljOiB0b3BpYyxcbiAgICAgIHRpbWVvdXQ6ICgoKSA9PiB7XG4gICAgICAgIGlmIChwcm9wcy50aW1lb3V0T3B0aW9uPy5zdGF0ZU1hY2hpbmVUaW1lb3V0KSB7XG4gICAgICAgICAgcmV0dXJuIHByb3BzLnRpbWVvdXRPcHRpb24/LnN0YXRlTWFjaGluZVRpbWVvdXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIER1cmF0aW9uLmhvdXJzKDEpO1xuICAgICAgfSkoKSxcbiAgICAgIGxvZ3M6ICgoKSA9PiB7XG4gICAgICAgIGlmIChwcm9wcy5sb2dPcHRpb24/Lm1hY2hpbmVMb2dMZXZlbCkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkZXN0aW5hdGlvbjogbmV3IGxvZ3MuTG9nR3JvdXAodGhpcywgJ1N0YXRlTWFjaGluZUxvZ0dyb3VwJywge1xuICAgICAgICAgICAgICBsb2dHcm91cE5hbWU6ICgoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG5hbWVzLnN0YXRlTWFjaGluZU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgL2F3cy9zdGF0ZXMvJHtuYW1lcy5zdGF0ZU1hY2hpbmVOYW1lfWA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgIH0pKCksXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGxldmVsOiBwcm9wcy5sb2dPcHRpb24ubWFjaGluZUxvZ0xldmVsLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pKCksXG4gICAgfSk7XG5cbiAgICAvLyDwn5GHIHJlbmFtZSByb2xlIG5hbWUgJiBkZXNjcmlwdGlvbi5cbiAgICBpZiAobmFtZXMuc3RhdGVNYWNoaW5lUm9sZU5hbWUpIHtcbiAgICAgIGNvbnN0IHJvbGUgPSBzdGF0ZU1hY2hpbmUubm9kZS5maW5kQ2hpbGQoJ1JvbGUnKSBhcyBpYW0uUm9sZTtcbiAgICAgIGNvbnN0IGNmblJvbGUgPSByb2xlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGlhbS5DZm5Sb2xlO1xuICAgICAgY2ZuUm9sZS5hZGRQcm9wZXJ0eU92ZXJyaWRlKCdSb2xlTmFtZScsIG5hbWVzLnN0YXRlTWFjaGluZVJvbGVOYW1lKTtcbiAgICAgIGNmblJvbGUuYWRkUHJvcGVydHlPdmVycmlkZSgnRGVzY3JpcHRpb24nLCAnUkRTIERCIFJ1bm5pbmcgbWFjaGluZSByb2xlLicpO1xuICAgICAgY29uc3QgcG9saWN5ID0gcm9sZS5ub2RlLmZpbmRDaGlsZCgnRGVmYXVsdFBvbGljeScpIGFzIGlhbS5Qb2xpY3k7XG4gICAgICBjb25zdCBjZm5Qb2xpY3kgPSBwb2xpY3kubm9kZS5kZWZhdWx0Q2hpbGQgYXMgaWFtLkNmblBvbGljeTtcbiAgICAgIGNmblBvbGljeS5hZGRQcm9wZXJ0eU92ZXJyaWRlKCdQb2xpY3lOYW1lJywgYHJkcy1kYi1ydW5uaW5nLXNjaGVkdWxlLSR7cmFuZG9tfS1zdGF0ZS1tYWNoaW5lLXBvbGljeWApO1xuICAgIH1cblxuICAgIC8vIPCfkYcgU3RhdGVNYWNoaW5lIEV4ZWMgUm9sZSBvZiBTY2hlZHVsZXJcbiAgICBjb25zdCBzY2hlZHVsZXJFeGVjUm9sZSA9IG5ldyBpYW0uUm9sZSh0aGlzLCAnU2NoZWR1bGVyRXhlY3V0aW9uUm9sZScsIHtcbiAgICAgIHJvbGVOYW1lOiBuYW1lcy5zY2hlZHVsZXJSb2xlTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnUkRTIERCIFJ1bm5pbmcgc2NoZWR1bGVyIHJvbGUnLFxuICAgICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ3NjaGVkdWxlci5hbWF6b25hd3MuY29tJyksXG4gICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICAnc3RhdGUtbWFjaGluZS1leGVjLXBvbGljeSc6IG5ldyBpYW0uUG9saWN5RG9jdW1lbnQoe1xuICAgICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAgICAgJ3N0YXRlczpTdGFydEV4ZWN1dGlvbicsXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgICAgICAgIHN0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmVBcm4sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyDwn5GHIFNjaGVkdWxlIHN0YXRlXG4gICAgY29uc3Qgc2hlZHVsZVN0YXRlOiBzdHJpbmcgPSAoKCkgPT4ge1xuICAgICAgaWYgKHByb3BzLmVuYWJsZVNjaGVkdWxpbmcgPT09IHVuZGVmaW5lZCB8fCBwcm9wcy5lbmFibGVTY2hlZHVsaW5nKSB7XG4gICAgICAgIHJldHVybiAnRU5BQkxFRCc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gJ0RJU0FCTEVEJztcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgLy8g8J+RhyBTdG9wIFNjaGVkdWxlIGV4cHJlc3Npb25cbiAgICBjb25zdCBzdG9wU2NoZWR1bGVFeHByZXNzaW9uOiBzdHJpbmcgPSAoKCkgPT4ge1xuICAgICAgLy8gZGVmYXVsdDogd2Vla2RheSAyMToxMFxuICAgICAgY29uc3QgbWludXRlOiBzdHJpbmcgPSBwcm9wcy5zdG9wU2NoZWR1bGU/Lm1pbnV0ZSA/PyAnMTAnO1xuICAgICAgY29uc3QgaG91cjogc3RyaW5nID0gcHJvcHMuc3RvcFNjaGVkdWxlPy5ob3VyID8/ICcyMSc7XG4gICAgICBjb25zdCB3ZWVrOiBzdHJpbmcgPSBwcm9wcy5zdG9wU2NoZWR1bGU/LndlZWsgPz8gJ01PTi1GUkknO1xuICAgICAgcmV0dXJuIGBjcm9uKCR7bWludXRlfSAke2hvdXJ9ID8gKiAke3dlZWt9ICopYDtcbiAgICB9KSgpO1xuXG4gICAgLy8g8J+RhyBTdGFydCBTY2hlZHVsZSBleHByZXNzaW9uXG4gICAgY29uc3Qgc3RhcnRTY2hlZHVsZUV4cHJlc3Npb246IHN0cmluZyA9ICgoKSA9PiB7XG4gICAgICAvLyBkZWZhdWx0OiB3ZWVrZGF5IDA3OjUwXG4gICAgICBjb25zdCBtaW51dGU6IHN0cmluZyA9IHByb3BzLnN0YXJ0U2NoZWR1bGU/Lm1pbnV0ZSA/PyAnNTAnO1xuICAgICAgY29uc3QgaG91cjogc3RyaW5nID0gcHJvcHMuc3RhcnRTY2hlZHVsZT8uaG91ciA/PyAnNyc7XG4gICAgICBjb25zdCB3ZWVrOiBzdHJpbmcgPSBwcm9wcy5zdGFydFNjaGVkdWxlPy53ZWVrID8/ICdNT04tRlJJJztcbiAgICAgIHJldHVybiBgY3Jvbigke21pbnV0ZX0gJHtob3VyfSA/ICogJHt3ZWVrfSAqKWA7XG4gICAgfSkoKTtcblxuICAgIC8vIPCfkYcgU3RvcCBEQiBzY2hlZHVsZVxuICAgIG5ldyBEQlJ1bmluZ1NjaGVkdWxlKHRoaXMsICdTdG9wRGF0YWJhc2VSdW5uaW5nU2NoZWR1bGUnLCB7XG4gICAgICBuYW1lOiBuYW1lcy5zdGFydFNjaGVkdWxlTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnc3RvcCBkYXRhYmFzZShpbnN0YW5jZS9jbHVzdGVyKSBydW5uaW5nIHN0b3Agc2NoZWR1bGUuJyxcbiAgICAgIHNoZWR1bGVTdGF0ZSxcbiAgICAgIHRpbWV6b25lOiBwcm9wcy5zdG9wU2NoZWR1bGU/LnRpbWV6b25lID8/ICdVVEMnLFxuICAgICAgZXhwcmVzc2lvbjogc3RvcFNjaGVkdWxlRXhwcmVzc2lvbixcbiAgICAgIHRhcmdldDoge1xuICAgICAgICBzdGF0ZU1hY2hpbmVBcm46IHN0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmVBcm4sXG4gICAgICAgIHJvbGVBcm46IHNjaGVkdWxlckV4ZWNSb2xlLnJvbGVBcm4sXG4gICAgICAgIHJlc291cmNlVGFnOiB7XG4gICAgICAgICAga2V5OiBwcm9wcy50YXJnZXRSZXNvdXJjZS50YWdLZXksXG4gICAgICAgICAgdmFsdWVzOiBwcm9wcy50YXJnZXRSZXNvdXJjZS50YWdWYWx1ZXMsXG4gICAgICAgIH0sXG4gICAgICAgIGlucHV0OiB7IG1vZGU6ICdTdG9wJyB9LFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIPCfkYcgU3RhcnQgREIgc2NoZWR1bGVcbiAgICBuZXcgREJSdW5pbmdTY2hlZHVsZSh0aGlzLCAnU3RhcnREYXRhYmFzZVJ1bm5pbmdTY2hlZHVsZScsIHtcbiAgICAgIG5hbWU6IG5hbWVzLnN0b3BTY2hlZHVsZU5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogJ3N0YXJ0IGRiIGluc3RhbmNlIHNjaGVkdWxlLicsXG4gICAgICBzaGVkdWxlU3RhdGUsXG4gICAgICB0aW1lem9uZTogcHJvcHMuc3RhcnRTY2hlZHVsZT8udGltZXpvbmUgPz8gJ1VUQycsXG4gICAgICBleHByZXNzaW9uOiBzdGFydFNjaGVkdWxlRXhwcmVzc2lvbixcbiAgICAgIHRhcmdldDoge1xuICAgICAgICBzdGF0ZU1hY2hpbmVBcm46IHN0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmVBcm4sXG4gICAgICAgIHJvbGVBcm46IHNjaGVkdWxlckV4ZWNSb2xlLnJvbGVBcm4sXG4gICAgICAgIHJlc291cmNlVGFnOiB7XG4gICAgICAgICAga2V5OiBwcm9wcy50YXJnZXRSZXNvdXJjZS50YWdLZXksXG4gICAgICAgICAgdmFsdWVzOiBwcm9wcy50YXJnZXRSZXNvdXJjZS50YWdWYWx1ZXMsXG4gICAgICAgIH0sXG4gICAgICAgIGlucHV0OiB7IG1vZGU6ICdTdGFydCcgfSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgfVxufVxuXG5pbnRlcmZhY2UgREJSdW5pbmdTY2hlZHVsZVByb3BzIHtcbiAgbmFtZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgc2hlZHVsZVN0YXRlOiBzdHJpbmc7XG4gIHRpbWV6b25lOiBzdHJpbmc7XG4gIGV4cHJlc3Npb246IHN0cmluZztcbiAgdGFyZ2V0OiB7XG4gICAgc3RhdGVNYWNoaW5lQXJuOiBzdHJpbmc7XG4gICAgcm9sZUFybjogc3RyaW5nO1xuICAgIHJlc291cmNlVGFnOiB7XG4gICAgICBrZXk6IHN0cmluZztcbiAgICAgIHZhbHVlczogc3RyaW5nW107XG4gICAgfTtcbiAgICBpbnB1dDoge1xuICAgICAgbW9kZTogc3RyaW5nO1xuICAgIH07XG4gIH07XG59XG5cbmNsYXNzIERCUnVuaW5nU2NoZWR1bGUgZXh0ZW5kcyBzY2hlZHVsZXIuQ2ZuU2NoZWR1bGUge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogREJSdW5pbmdTY2hlZHVsZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBuYW1lOiBwcm9wcy5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uLFxuICAgICAgc3RhdGU6IHByb3BzLnNoZWR1bGVTdGF0ZSxcbiAgICAgIC8vZ3JvdXBOYW1lOiBzY2hlZHVsZUdyb3VwLm5hbWUsIC8vIGRlZmF1bHRcbiAgICAgIGZsZXhpYmxlVGltZVdpbmRvdzoge1xuICAgICAgICBtb2RlOiAnT0ZGJyxcbiAgICAgIH0sXG4gICAgICBzY2hlZHVsZUV4cHJlc3Npb25UaW1lem9uZTogcHJvcHMudGltZXpvbmUsXG4gICAgICBzY2hlZHVsZUV4cHJlc3Npb246IHByb3BzLmV4cHJlc3Npb24sXG4gICAgICB0YXJnZXQ6IHtcbiAgICAgICAgYXJuOiBwcm9wcy50YXJnZXQuc3RhdGVNYWNoaW5lQXJuLFxuICAgICAgICByb2xlQXJuOiBwcm9wcy50YXJnZXQucm9sZUFybixcbiAgICAgICAgaW5wdXQ6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBQYXJhbXM6IHtcbiAgICAgICAgICAgIFRhZ0tleTogcHJvcHMudGFyZ2V0LnJlc291cmNlVGFnLmtleSxcbiAgICAgICAgICAgIFRhZ1ZhbHVlczogcHJvcHMudGFyZ2V0LnJlc291cmNlVGFnLnZhbHVlcyxcbiAgICAgICAgICAgIE1vZGU6IHByb3BzLnRhcmdldC5pbnB1dC5tb2RlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgICByZXRyeVBvbGljeToge1xuICAgICAgICAgIG1heGltdW1FdmVudEFnZUluU2Vjb25kczogNjAsXG4gICAgICAgICAgbWF4aW11bVJldHJ5QXR0ZW1wdHM6IDAsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG4iXX0=