cdk-emrserverless-with-delta-lake
Version:
A construct for the quick demo of EMR Serverless.
441 lines • 79.7 kB
JavaScript
"use strict";
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmrStudioTaggingExpert = exports.EmrStudioServiceRole = exports.EmrStudio = exports.StudioAuthMode = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cdk = require("aws-cdk-lib");
const ec2 = require("aws-cdk-lib/aws-ec2");
const emr = require("aws-cdk-lib/aws-emr");
const iam = require("aws-cdk-lib/aws-iam");
const lambda = require("aws-cdk-lib/aws-lambda");
const logs = require("aws-cdk-lib/aws-logs");
const cr = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
const emr_studio_cluster_templates_1 = require("./emr-studio-cluster-templates");
const emr_studio_sgs_1 = require("./emr-studio-sgs");
/**
* What kind of authentication the Studio uses.
*/
var StudioAuthMode;
(function (StudioAuthMode) {
/**
* the Studio authenticates users using AWS SSO.
*/
StudioAuthMode["AWS_SSO"] = "SSO";
/**
* the Studio authenticates users using AWS IAM.
*/
StudioAuthMode["AWS_IAM"] = "IAM";
})(StudioAuthMode || (exports.StudioAuthMode = StudioAuthMode = {}));
/**
* Creates an EMR Studio for EMR Serverless applications.
*
* The Studio is not only for EMR Serverless applications but also for launching an EMR cluster via a cluster template created in this constrcut to check out results transformed by EMR serverless applications.
*
* For what Studio can do further, please refer to [Amazon EMR Studio](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-studio.html).
*
* ```ts
* const workspaceBucket = new WorkSpaceBucket(this, 'EmrStudio');
* const emrStudio = new EmrStudio(this, '', {
* workSpaceBucket: workspaceBucket,
* subnetIds: ['subnet1', 'subnet2', 'subnet3']
* });
* ```
*/
class EmrStudio extends constructs_1.Construct {
constructor(scope, name, props) {
super(scope, name);
/**
* Add `{'for-use-with-amazon-emr-managed-policies', 'true'}` to a specific construct.
*
* Please refer to [Create an EMR Studio service role](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-studio-service-role.html) for detail.
* @param entity a construct that is intended to be added the specific tag.
*/
this.addProperTag = (entity) => {
cdk.Tags.of(entity).add('for-use-with-amazon-emr-managed-policies', 'true');
};
const baseVpc = (props.vpcId !== undefined) ? ec2.Vpc.fromLookup(this, 'EmrBaseVpc', { vpcId: props.vpcId }) : ec2.Vpc.fromLookup(this, 'DefaultVpc', { isDefault: true });
if (props.vpcId === undefined) {
console.log('`vpcId` is not set for the EmrStudio construct, therefore, the default VPC is chosen.');
}
const defaultSubnetIds = [];
baseVpc.publicSubnets.forEach((subnet) => {
defaultSubnetIds.push(subnet.subnetId);
});
if (props.subnetIds === undefined) {
console.log('`subnetIds` for the `EmrStudio` construct is not set, therefore, public subnets from the chosen VPC is chosen.');
}
;
const subnetIds = (props.subnetIds !== undefined) ? props.subnetIds : defaultSubnetIds;
console.log(`${subnetIds.toString()} are selected for the EMR Studio`);
const workSpaceSecurityGroup = new emr_studio_sgs_1.EmrStudioWorkspaceSecurityGroup(this, 'Workspace', { vpc: baseVpc });
const engineSecurityGroup = new emr_studio_sgs_1.EmrStudioEngineSecurityGroup(this, 'Engine', { vpc: baseVpc });
workSpaceSecurityGroup.entity.connections.allowTo(engineSecurityGroup.entity, ec2.Port.tcp(18888), 'Allow traffic to any resources in the Engine security group for EMR Studio.');
workSpaceSecurityGroup.entity.addEgressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), 'Allow traffic to the internet to link publicly hosted Git repositories to Workspaces.');
this.addProperTag(workSpaceSecurityGroup);
this.addProperTag(engineSecurityGroup);
const taggingExpert = new EmrStudioTaggingExpert(this, 'TaggingExpert');
const lambdaInvoker = new cr.Provider(this, 'LambdaInvoker', {
onEventHandler: taggingExpert.functionEntity,
logRetention: logs.RetentionDays.THREE_MONTHS,
});
new cdk.CustomResource(this, 'TagVpcSubnetCr', {
serviceToken: lambdaInvoker.serviceToken,
resourceType: 'Custom::TagVpcSubnets',
properties: {
VpcId: baseVpc.vpcId,
SubnetIds: subnetIds.toString(),
},
});
const serviceRoleName = props.serviceRoleName ?? 'emr-studio-service-role';
if (props.serviceRoleName == undefined) {
console.log('`serviceRoleName` is set by default value: \'emr-studio-service-role\'');
}
const emrStudioServiceRole = new EmrStudioServiceRole(this, 'Service', {
workSpaceBucket: props.workSpaceBucket,
roleName: serviceRoleName,
});
const authMode = props.authMode ?? StudioAuthMode.AWS_IAM;
const engineSecurityGroupId = props.engineSecurityGroupId ?? engineSecurityGroup.entity.securityGroupId;
const workspaceSecurityGroupId = props.workSpaceSecurityGroupId ?? workSpaceSecurityGroup.entity.securityGroupId;
const serviceRoleArn = (props.serviceRoleArn !== undefined) ? props.serviceRoleArn : emrStudioServiceRole.roleEntity.roleArn;
this.entity = new emr.CfnStudio(this, 'EmrStudio', {
authMode: authMode,
defaultS3Location: `s3://${props.workSpaceBucket.bucketEntity.bucketName}/`,
engineSecurityGroupId: engineSecurityGroupId,
name: props.studioName ?? 'emr-sutdio-quicklaunch',
serviceRole: serviceRoleArn,
subnetIds: subnetIds,
vpcId: baseVpc.vpcId,
workspaceSecurityGroupId: workspaceSecurityGroupId,
description: props.description ?? 'EMR Studio Quick Launch - by scott.hsieh',
tags: [{
key: 'Purpose',
value: 'Demo',
},
{
key: 'DemoContributor',
value: 'scott.hsieh',
}],
userRole: (props.authMode == StudioAuthMode.AWS_SSO) ? props.userRoleArn : undefined,
});
new emr_studio_cluster_templates_1.EmrStudioDeveloperStack(this, 'ClusterTempalte', {
providerName: props.serviceCatalogProps?.providerName,
group: props.serviceCatalogProps?.group,
user: props.serviceCatalogProps?.user,
role: props.serviceCatalogProps?.role,
});
new cdk.CfnOutput(this, 'EmrStudioArn', { value: cdk.stringToCloudFormation(this.entity.getAtt('Arn')), description: 'The ARN of the EMR Studio' });
new cdk.CfnOutput(this, 'EmrStudioId', { value: cdk.stringToCloudFormation(this.entity.getAtt('StudioId')), description: 'The ID of the Amazon EMR Studio.' });
new cdk.CfnOutput(this, 'EmrStudioUrl', { value: cdk.stringToCloudFormation(this.entity.getAtt('Url')), description: 'The unique access URL of the Amazon EMR Studio.' });
}
}
exports.EmrStudio = EmrStudio;
_a = JSII_RTTI_SYMBOL_1;
EmrStudio[_a] = { fqn: "cdk-emrserverless-with-delta-lake.EmrStudio", version: "2.0.823" };
/**
* Creates a default service role for an EMR Studio.
*
* For detail, please refer to [Create an EMR Studio service role](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-studio-service-role.html).
*
* ```ts
* const workSpaceBucket = new WorkSpaceBucket(this, 'WorkSpace');
* const emrStudioServiceRole = new EmrStudioServiceRole(this, 'Service', {
* workSpaceBucket: workSpaceBucket
* });
* ```
*/
class EmrStudioServiceRole extends constructs_1.Construct {
constructor(scope, name, props) {
super(scope, name);
this.roleEntity = new iam.Role(this, 'IamRole', {
roleName: (props !== undefined) ? props.roleName : 'Emr-Studio-Quick-Demo-Service-Role',
assumedBy: new iam.ServicePrincipal('elasticmapreduce.amazonaws.com', {
conditions: {
['StringEquals']: {
'aws:SourceAccount': cdk.Aws.ACCOUNT_ID,
},
['ArnLike']: {
'aws:SourceArn': `arn:aws:elasticmapreduce:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:*`,
},
},
}),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEMRServicePolicy_v2'),
],
inlinePolicies: {
['emr-studio-quick-demo-additional-policy']: new iam.PolicyDocument({
assignSids: true,
statements: [
new iam.PolicyStatement({
sid: 'AllowEMRReadOnlyActions',
effect: iam.Effect.ALLOW,
actions: [
'elasticmapreduce:ListInstances',
'elasticmapreduce:DescribeCluster',
'elasticmapreduce:ListSteps',
],
resources: [
'*',
],
}),
new iam.PolicyStatement({
sid: 'AllowEC2ENIActionsWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'ec2:CreateNetworkInterfacePermission',
'ec2:DeleteNetworkInterface',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:network-interface/*`,
],
conditions: {
['StringEquals']: {
'aws:ResourceTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowEC2ENIAttributeAction',
effect: iam.Effect.ALLOW,
actions: [
'ec2:ModifyNetworkInterfaceAttribute',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:instance/*`,
`arn:${cdk.Aws.PARTITION}:ec2:*:*:network-interface/*`,
`arn:${cdk.Aws.PARTITION}:ec2:*:*:security-group/*`,
],
}),
new iam.PolicyStatement({
sid: 'AllowEC2SecurityGroupActionsWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'ec2:AuthorizeSecurityGroupEgress',
'ec2:AuthorizeSecurityGroupIngress',
'ec2:RevokeSecurityGroupEgress',
'ec2:RevokeSecurityGroupIngress',
'ec2:DeleteNetworkInterfacePermission',
],
resources: [
'*',
],
conditions: {
['StringEquals']: {
'aws:ResourceTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowDefaultEC2SecurityGroupsCreationWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'ec2:AuthorizeSecurityGroupEgress',
'ec2:AuthorizeSecurityGroupIngress',
'ec2:RevokeSecurityGroupEgress',
'ec2:RevokeSecurityGroupIngress',
'ec2:DeleteNetworkInterfacePermission',
],
resources: [
'*',
],
conditions: {
['StringEquals']: {
'aws:RequestTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowDefaultEC2SecurityGroupsCreationInVPCWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'ec2:CreateSecurityGroup',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:vpc/*`,
],
conditions: {
['StringEquals']: {
'aws:ResourceTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowAddingEMRTagsDuringDefaultSecurityGroupCreation',
effect: iam.Effect.ALLOW,
actions: [
'ec2:CreateTags',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:security-group/*`,
],
conditions: {
['StringEquals']: {
'aws:RequestTag/for-use-with-amazon-emr-managed-policies': 'true',
'ec2:CreateAction': 'CreateSecurityGroup',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowEC2ENICreationWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'ec2:CreateNetworkInterface',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:network-interface/*`,
],
conditions: {
['StringEquals']: {
'aws:RequestTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowEC2ENICreationInSubnetAndSecurityGroupWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'ec2:CreateNetworkInterface',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:subnet/*`,
`arn:${cdk.Aws.PARTITION}:ec2:*:*:security-group/*`,
],
conditions: {
['StringEquals']: {
'aws:ResourceTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowAddingTagsDuringEC2ENICreation',
effect: iam.Effect.ALLOW,
actions: [
'ec2:CreateTags',
],
resources: [
`arn:${cdk.Aws.PARTITION}:ec2:*:*:network-interface/*`,
],
conditions: {
['StringEquals']: {
'ec2:CreateAction': 'CreateNetworkInterface',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowEC2ReadOnlyActions',
effect: iam.Effect.ALLOW,
actions: [
'ec2:DescribeSecurityGroups',
'ec2:DescribeNetworkInterfaces',
'ec2:DescribeTags',
'ec2:DescribeInstances',
'ec2:DescribeSubnets',
'ec2:DescribeVpcs',
],
resources: [
'*',
],
}),
new iam.PolicyStatement({
sid: 'AllowSecretsManagerReadOnlyActionsWithEMRTags',
effect: iam.Effect.ALLOW,
actions: [
'secretsmanager:GetSecretValue',
],
resources: [
`arn:${cdk.Aws.PARTITION}:secretsmanager:*:*:secret:*`,
],
conditions: {
['StringEquals']: {
'aws:ResourceTag/for-use-with-amazon-emr-managed-policies': 'true',
},
},
}),
new iam.PolicyStatement({
sid: 'AllowWorkspaceCollaboration',
effect: iam.Effect.ALLOW,
actions: [
'iam:GetUser',
'iam:GetRole',
'iam:ListUsers',
'iam:ListRoles',
'sso:GetManagedApplicationInstance',
'sso-directory:SearchUsers',
],
resources: [
'*',
],
}),
new iam.PolicyStatement({
sid: 'AllowWorkSpaceBucketPermissions',
effect: iam.Effect.ALLOW,
actions: [
's3:PutObject',
's3:GetObject',
's3:GetEncryptionConfiguration',
's3:ListBucket',
's3:DeleteObject',
],
resources: [
`${props.workSpaceBucket.bucketEntity.bucketArn}`,
`${props.workSpaceBucket.bucketEntity.bucketArn}/*`,
],
}),
],
}),
},
});
new cdk.CfnOutput(this, 'OEmrStudioServiceRoleArn', { value: this.roleEntity.roleArn, description: 'The ARN of the servcie role used by the EMR Studio for quick demo.' });
}
}
exports.EmrStudioServiceRole = EmrStudioServiceRole;
_b = JSII_RTTI_SYMBOL_1;
EmrStudioServiceRole[_b] = { fqn: "cdk-emrserverless-with-delta-lake.EmrStudioServiceRole", version: "2.0.823" };
/**
* Creates a Lambda function for the custom resource which can add necessary tag onto the VPC and subnets for the EMR Studio during deployment.
*
* For detail on the tag, please refer to [How to create a service role for EMR Studio](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-studio-service-role.html#emr-studio-service-role-instructions)
*/
class EmrStudioTaggingExpert extends constructs_1.Construct {
constructor(scope, name) {
super(scope, name);
const lambdaRole = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
description: 'An execution role for the Lambda function which tags specific resources for the EMR Studio.',
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
iam.ManagedPolicy.fromAwsManagedPolicyName('AWSXRayDaemonWriteAccess'),
],
roleName: 'Tagging-Expert-Role',
inlinePolicies: {
LambdaForBranchPolicy: new iam.PolicyDocument({
assignSids: true,
statements: [new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['ec2:CreateTags', 'ec2:DeleteTags'],
resources: [`arn:${cdk.Aws.PARTITION}:ec2:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:vpc/*`,
`arn:${cdk.Aws.PARTITION}:ec2:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:subnet/*`],
})],
}),
},
});
this.functionEntity = new lambda.Function(this, 'Function', {
functionName: 'emr-studio-tagging-specific-resources',
description: 'Tags specific EC2 resources, i.e., the VPC and subnets for the EMR Studio.',
logRetention: logs.RetentionDays.THREE_MONTHS,
runtime: lambda.Runtime.PYTHON_3_12,
architecture: lambda.Architecture.ARM_64,
code: lambda.Code.fromInline('import json\r\nfrom typing import List\r\n\r\nimport boto3\r\nfrom botocore.exceptions import ClientError, ParamValidationError\r\n\r\n\r\ndef lambda_handler(event, context):\r\n print(json.dumps(event, indent=4))\r\n request_type = event["RequestType"]\r\n props = event["ResourceProperties"]\r\n vpc_id: str = props.get(\'VpcId\')\r\n subnet_ids: List[str] = props.get(\'SubnetIds\').split(\',\')\r\n resources_list = [vpc_id] + subnet_ids\r\n ec2_client = boto3.client(\'ec2\')\r\n if(request_type in [\'Create\']):\r\n try:\r\n response = ec2_client.create_tags(\r\n Resources=resources_list,\r\n Tags=[\r\n {\r\n \'Key\': \'for-use-with-amazon-emr-managed-policies\',\r\n \'Value\': \'true\'\r\n }\r\n ]\r\n )\r\n metadata = response.get(\'ResponseMetadata\')\r\n status_code = metadata.get(\'HTTPStatusCode\')\r\n print(f\'HTTP status code: {status_code}\')\r\n if status_code == 200:\r\n resources = \',\'.join(resources_list)\r\n tag_value = json.dumps({\r\n \'Key\': \'for-use-with-amazon-emr-managed-policies\',\r\n \'Value\': \'true\'\r\n }, indent=4)\r\n print(f\'{resources} has been added {tag_value}\')\r\n except ClientError as e:\r\n print(f\'Unexpected error: {e}\')\r\n except ParamValidationError as e:\r\n print(f\'Parameter validation error: {e}\')\r\n if(request_type == \'Delete\'):\r\n try:\r\n response = ec2_client.delete_tags(\r\n Resources=resources_list,\r\n Tags=[\r\n {\r\n \'Key\': \'for-use-with-amazon-emr-managed-policies\',\r\n \'Value\': \'true\'\r\n }\r\n ]\r\n )\r\n metadata = response.get(\'ResponseMetadata\')\r\n status_code = metadata.get(\'HTTPStatusCode\')\r\n print(f\'HTTP status code: {status_code}\')\r\n if status_code == 200:\r\n resources = \',\'.join(resources_list)\r\n tag_value = json.dumps({\r\n \'Key\': \'for-use-with-amazon-emr-managed-policies\',\r\n \'Value\': \'true\'\r\n }, indent=4)\r\n print(f\'{resources} has been removed {tag_value}\')\r\n except ClientError as e:\r\n print(f\'Unexpected error: {e}\')\r\n except ParamValidationError as e:\r\n print(f\'Parameter validation error: {e}\')\r\n'),
handler: 'index.lambda_handler',
memorySize: 128,
role: lambdaRole,
timeout: cdk.Duration.seconds(20),
tracing: lambda.Tracing.ACTIVE,
});
}
}
exports.EmrStudioTaggingExpert = EmrStudioTaggingExpert;
_c = JSII_RTTI_SYMBOL_1;
EmrStudioTaggingExpert[_c] = { fqn: "cdk-emrserverless-with-delta-lake.EmrStudioTaggingExpert", version: "2.0.823" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1yLXN0dWRpby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lbXItc3R1ZGlvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQW1DO0FBQ25DLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsMkNBQTJDO0FBQzNDLGlEQUFpRDtBQUNqRCw2Q0FBNkM7QUFDN0MsbURBQW1EO0FBQ25ELDJDQUF1QztBQUV2QyxpRkFBdUc7QUFDdkcscURBQWlHO0FBRWpHOztHQUVHO0FBQ0gsSUFBWSxjQVNYO0FBVEQsV0FBWSxjQUFjO0lBQ3hCOzs2REFFeUQ7SUFDekQsaUNBQWUsQ0FBQTtJQUNmOzs2REFFeUQ7SUFDekQsaUNBQWUsQ0FBQTtBQUNqQixDQUFDLEVBVFcsY0FBYyw4QkFBZCxjQUFjLFFBU3pCO0FBb0ZEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBYSxTQUFVLFNBQVEsc0JBQVM7SUFFdEMsWUFBWSxLQUFnQixFQUFFLElBQVksRUFBRSxLQUFxQjtRQUMvRCxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBZ0ZyQjs7Ozs7bUNBSzJCO1FBQ25CLGlCQUFZLEdBQUcsQ0FBQyxNQUFpQixFQUFFLEVBQUU7WUFDM0MsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLDBDQUEwQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzlFLENBQUMsQ0FBQztRQXZGQSxNQUFNLE9BQU8sR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUs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T0FBTyxDQUFDLE1BQU07U0FDL0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUF4Q0gsd0RBeUNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGVjMiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGVtciBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZW1yJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgY3IgZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IFdvcmtTcGFjZUJ1Y2tldCB9IGZyb20gJy4vYnVja2V0cyc7XG5pbXBvcnQgeyBFbXJTdHVkaW9EZXZlbG9wZXJTdGFjaywgRW1yU3R1ZGlvRGV2ZWxvcGVyU3RhY2tQcm9wcyB9IGZyb20gJy4vZW1yLXN0dWRpby1jbHVzdGVyLXRlbXBsYXRlcyc7XG5pbXBvcnQgeyBFbXJTdHVkaW9FbmdpbmVTZWN1cml0eUdyb3VwLCBFbXJTdHVkaW9Xb3Jrc3BhY2VTZWN1cml0eUdyb3VwIH0gZnJvbSAnLi9lbXItc3R1ZGlvLXNncyc7XG5cbi8qKlxuICogV2hhdCBraW5kIG9mIGF1dGhlbnRpY2F0aW9uIHRoZSBTdHVkaW8gdXNlcy5cbiAqL1xuZXhwb3J0IGVudW0gU3R1ZGlvQXV0aE1vZGUge1xuICAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogdGhlIFN0dWRpbyBhdXRoZW50aWNhdGVzIHVzZXJzIHVzaW5nIEFXUyBTU08uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICBBV1NfU1NPID0gJ1NTTycsXG4gIC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiB0aGUgU3R1ZGlvIGF1dGhlbnRpY2F0ZXMgdXNlcnMgdXNpbmcgQVdTIElBTS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4gIEFXU19JQU0gPSAnSUFNJyxcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgRU1SIFN0dWRpbywgbWFpbmx5IGZvciBFTVIgU2VydmVybGVzcyBhcHBsaWNhdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRW1yU3R1ZGlvUHJvcHMge1xuICAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIFRoZSBjdXN0b20gY29uc3RydWN0IGFzIHRoZSB3b3Jrc3BhY2UgUzMgYnVja2V0LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqL1xuICByZWFkb25seSB3b3JrU3BhY2VCdWNrZXQ6IFdvcmtTcGFjZUJ1Y2tldDtcbiAgLyoqXG4gICAgICogVGhlIHN1Ym5ldCBJRHMgZm9yIHRoZSBFTVIgc3R1ZGlvLlxuICAgICAqIFlvdSBjYW4gc2VsZWN0IHRoZSBzdWJuZXRzIGZyb20gdGhlIGRlZmF1bHQgVlBDIGluIHlvdXIgQVdTIGFjY291bnQuXG4gICAgICovXG4gIHJlYWRvbmx5IHN1Ym5ldElkcz86IEFycmF5PHN0cmluZz47XG4gIC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogU3BlY2lmaWVzIHdoZXRoZXIgdGhlIFN0dWRpbyBhdXRoZW50aWNhdGVzIHVzZXJzIHVzaW5nIEFXUyBTU08gb3IgSUFNLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEBkZWZhdWx0IC0gU3R1ZGlvQXV0aE1vZGUuQVdTX0lBTS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKi9cbiAgcmVhZG9ubHkgYXV0aE1vZGU/OiBTdHVkaW9BdXRoTW9kZTtcbiAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIFRoZSBJRCBvZiB0aGUgQW1hem9uIEVNUiBTdHVkaW8gRW5naW5lIHNlY3VyaXR5IGdyb3VwLiBUaGUgRW5naW5lIHNlY3VyaXR5IGdyb3VwIGFsbG93cyBpbmJvdW5kIG5ldHdvcmsgdHJhZmZpYyBmcm9tIHRoZSBXb3Jrc3BhY2Ugc2VjdXJpdHkgZ3JvdXAsIGFuZCBpdCBtdXN0IGJlIGluIHRoZSBzYW1lIFZQQyBzcGVjaWZpZWQgYnkgVnBjSWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEBkZWZhdWx0IC0gYSBzZWN1cml0eSBncm91cCBjcmVhdGVkIGJ5IGBFbXJTdHVkaW9FbmdpbmVTZWN1cml0eUdyb3VwYC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4gIHJlYWRvbmx5IGVuZ2luZVNlY3VyaXR5R3JvdXBJZD86IHN0cmluZztcbiAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIFRoZSBJRCBvZiB0aGUgc2VjdXJpdHkgZ3JvdXAgdXNlZCBieSB0aGUgd29ya3NwYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiAgQGRlZmF1bHQgLSBhIHNlY3VyaXR5IGdyb3VwIGNyZWF0ZWQgYnkgYEVtclN0dWRpb1dvcmtzcGFjZVNlY3VyaXR5R3JvdXBgLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKi9cbiAgcmVhZG9ubHkgd29ya1NwYWNlU2VjdXJpdHlHcm91cElkPzogc3RyaW5nO1xuICAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogQSBkZXNjcmlwdGl2ZSBuYW1lIGZvciB0aGUgQW1hem9uIEVNUiBTdHVkaW8uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEBkZWZhdWx0IC0gJ2Vtci1zdXRkaW8tcXVpY2tsYXVuY2gnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICByZWFkb25seSBzdHVkaW9OYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogVXNlZCBieSB0aGUgRU1SIFN0dWRpby5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogQGRlZmF1bHQgLSAnVGhlIGRlZmF1bHQgVlBDIHdpbGwgYmUgdXNlZC4nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICByZWFkb25seSB2cGNJZD86IHN0cmluZztcbiAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEEgZGV0YWlsZWQgZGVzY3JpcHRpb24gb2YgdGhlIEFtYXpvbiBFTVIgU3R1ZGlvLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBAZGVmYXVsdCAtICdFTVIgU3R1ZGlvIFF1aWNrIExhdW5jaCAtIGJ5IHNjb3R0LmhzaWVoJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBUaGUgY3VzdG9tIHNlcnZpY2Ugcm9sZSBmb3IgdGhlIEVNUiBTdHVkaW8uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEBsaW5rIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9lbXIvbGF0ZXN0L01hbmFnZW1lbnRHdWlkZS9lbXItc3R1ZGlvLXNlcnZpY2Utcm9sZS5odG1sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEBkZWZhdWx0IC0gZXN0YWJsaXNoZWQgYnkgdGhlIGNvbnN0cnVjdCwgRW1yU3R1ZGlvU2VydmljZVJvbGUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEEgbmFtZSBmb3IgdGhlIHNlcnZpY2Ugcm9sZSBvZiBhbiBFTVIgU3R1ZGlvLiBGb3IgdmFsaWQgdmFsdWVzLCBzZWUgdGhlIFJvbGVOYW1lIHBhcmFtZXRlciBmb3IgdGhlIENyZWF0ZVJvbGUgYWN0aW9uIGluIHRoZSBJQU0gQVBJIFJlZmVyZW5jZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBJTVBPUlRBTlQ6IElmIHlvdSBzcGVjaWZ5IGEgbmFtZSwgeW91IGNhbm5vdCBwZXJmb3JtIHVwZGF0ZXMgdGhhdCByZXF1aXJlIHJlcGxhY2VtZW50IG9mIHRoaXMgcmVzb3VyY2UuIFlvdSBjYW4gcGVyZm9ybSB1cGRhdGVzIHRoYXQgcmVxdWlyZSBubyBvciBzb21lIGludGVycnVwdGlvbi4gSWYgeW91IG11c3QgcmVwbGFjZSB0aGUgcmVzb3VyY2UsIHNwZWNpZnkgYSBuZXcgbmFtZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBJZiB5b3Ugc3BlY2lmeSBhIG5hbWUsIHlvdSBtdXN0IHNwZWNpZnkgdGhlIENBUEFCSUxJVFlfTkFNRURfSUFNIHZhbHVlIHRvIGFja25vd2xlZGdlIHlvdXIgdGVtcGxhdGUncyBjYXBhYmlsaXRpZXMuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgQWNrbm93bGVkZ2luZyBJQU0gUmVzb3VyY2VzIGluIEFXUyBDbG91ZEZvcm1hdGlvbiBUZW1wbGF0ZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogQGRlZmF1bHQgLSAnZW1yLXN0dWRpby1zZXJ2aWNlLXJvbGUnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZVJvbGVOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBzZXJ2aWNlUm9sZUFybj86IHN0cmluZztcbiAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIFRoZSBjdXN0b20gdXNlciByb2xlIGZvciB0aGUgRU1SIFN0dWRpbyB3aGVuIGF1dGhlbnRpY2F0aW9uIGlzIEFXUyBTU08uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIEN1cnJlbnRseSwgaWYgeW91IGNob29zZSB0byBlc3RhYmxpc2ggYW4gRU1SIHNlcnZlcmxlc3MgYXBwbGljYXRpb24gd2hlcmUgdGhlIGF1dGhlbnRpY2F0aW9uIG1lY2hhbmlzbSB1c2VkIGJ5IHRoZSBFTVIgU3R1ZGlvIGlzIEFXUyBTU08sIHlvdSBuZWVkIHRvIGNyZWF0ZSBhIHVzZXIgcm9sZSBieSB5b3Vyc2VsZiBhbmQgYXNzaWduIHRoZSByb2xlIGFybiB0byB0aGlzIGFyZ3VtZW50IGlmIEFXUyBTU08gaXMgY2hvc2VuIGFzIGF1dGhlbnRpY2F0aW9uIGZvciB0aGUgRU1SIFN0dWRpbztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogQGxpbmsgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vtci9sYXRlc3QvTWFuYWdlbWVudEd1aWRlL2Vtci1zdHVkaW8tdXNlci1wZXJtaXNzaW9ucy5odG1sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICByZWFkb25seSB1c2VyUm9sZUFybj86IHN0cmluZztcbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIHdoaWNoIGtpbmQgb2YgaWRlbnRpdHkgd2lsbCBiZSBhc3NvY2lhdGVkIHdpdGggdGhlIFByb2R1Y3Qgb2YgdGhlIFBvcmZvbGlvIGluIEFXUyBTZXJ2aWNlIENhdGFsb2cgZm9yIEVNUiBjbHVzdGVyIHRlbXBsYXRlcy5cbiAgICpcbiAgICogWW91IGNhbiBjaG9vc2UgZWl0aGVyIGFuIElBTSBncm91cCwgSUFNIHJvbGUsIG9yIElBTSB1c2VyLiBJZiB5b3UgbGVhdmUgaXQgZW1wdHksIGFuIElBTSB1c2VyIG5hbWVkIGBBZG1pbmlzdHJhdG9yYCB3aXRoIHRoZSBgQWRtaW5pc3RyYXRvckFjY2Vzc2AgcG93ZXIgbmVlZHMgdG8gYmUgY3JlYXRlZCBmaXJzdC5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VDYXRhbG9nUHJvcHM/OiBFbXJTdHVkaW9EZXZlbG9wZXJTdGFja1Byb3BzO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gRU1SIFN0dWRpbyBmb3IgRU1SIFNlcnZlcmxlc3MgYXBwbGljYXRpb25zLlxuICpcbiAqIFRoZSBTdHVkaW8gaXMgbm90IG9ubHkgZm9yIEVNUiBTZXJ2ZXJsZXNzIGFwcGxpY2F0aW9ucyBidXQgYWxzbyBmb3IgbGF1bmNoaW5nIGFuIEVNUiBjbHVzdGVyIHZpYSBhIGNsdXN0ZXIgdGVtcGxhdGUgY3JlYXRlZCBpbiB0aGlzIGNvbnN0cmN1dCB0byBjaGVjayBvdXQgcmVzdWx0cyB0cmFuc2Zvcm1lZCBieSBFTVIgc2VydmVybGVzcyBhcHBsaWNhdGlvbnMuXG4gKlxuICogRm9yIHdoYXQgU3R1ZGlvIGNhbiB