UNPKG

@aws-cdk/aws-redshift-alpha

Version:

The CDK Construct Library for AWS::Redshift

552 lines 80.6 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cluster = exports.MaintenanceTrackName = exports.ResourceAction = exports.ClusterType = exports.NodeType = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = require("path"); const ec2 = require("aws-cdk-lib/aws-ec2"); const iam = require("aws-cdk-lib/aws-iam"); const lambda = require("aws-cdk-lib/aws-lambda"); const secretsmanager = require("aws-cdk-lib/aws-secretsmanager"); const core_1 = require("aws-cdk-lib/core"); const custom_resources_1 = require("aws-cdk-lib/custom-resources"); const database_secret_1 = require("./database-secret"); const endpoint_1 = require("./endpoint"); const parameter_group_1 = require("./parameter-group"); const aws_redshift_1 = require("aws-cdk-lib/aws-redshift"); const subnet_group_1 = require("./subnet-group"); const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource"); const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable"); /** * Possible Node Types to use in the cluster * used for defining `ClusterProps.nodeType`. */ var NodeType; (function (NodeType) { /** * ds2.xlarge */ NodeType["DS2_XLARGE"] = "ds2.xlarge"; /** * ds2.8xlarge */ NodeType["DS2_8XLARGE"] = "ds2.8xlarge"; /** * dc1.large */ NodeType["DC1_LARGE"] = "dc1.large"; /** * dc1.8xlarge */ NodeType["DC1_8XLARGE"] = "dc1.8xlarge"; /** * dc2.large */ NodeType["DC2_LARGE"] = "dc2.large"; /** * dc2.8xlarge */ NodeType["DC2_8XLARGE"] = "dc2.8xlarge"; /** * ra3.large */ NodeType["RA3_LARGE"] = "ra3.large"; /** * ra3.xlplus */ NodeType["RA3_XLPLUS"] = "ra3.xlplus"; /** * ra3.4xlarge */ NodeType["RA3_4XLARGE"] = "ra3.4xlarge"; /** * ra3.16xlarge */ NodeType["RA3_16XLARGE"] = "ra3.16xlarge"; })(NodeType || (exports.NodeType = NodeType = {})); /** * What cluster type to use. * Used by `ClusterProps.clusterType` */ var ClusterType; (function (ClusterType) { /** * single-node cluster, the `ClusterProps.numberOfNodes` parameter is not required */ ClusterType["SINGLE_NODE"] = "single-node"; /** * multi-node cluster, set the amount of nodes using `ClusterProps.numberOfNodes` parameter */ ClusterType["MULTI_NODE"] = "multi-node"; })(ClusterType || (exports.ClusterType = ClusterType = {})); /** * The Amazon Redshift operation */ var ResourceAction; (function (ResourceAction) { /** * Pause the cluster */ ResourceAction["PAUSE_CLUSTER"] = "pause-cluster"; /** * Resume the cluster */ ResourceAction["RESUME_CLUSTER"] = "resume-cluster"; /** * Failing over to the other availability zone * * @see https://docs.aws.amazon.com/redshift/latest/mgmt/test-cluster-multi-az.html */ ResourceAction["FAILOVER_PRIMARY_COMPUTE"] = "failover-primary-compute"; })(ResourceAction || (exports.ResourceAction = ResourceAction = {})); /** * The maintenance track for the cluster. * * @see https://docs.aws.amazon.com/redshift/latest/mgmt/managing-cluster-considerations.html#rs-mgmt-maintenance-tracks */ var MaintenanceTrackName; (function (MaintenanceTrackName) { /** * Updated to the most recently certified maintenance release. */ MaintenanceTrackName["CURRENT"] = "current"; /** * Update to the previously certified maintenance release. */ MaintenanceTrackName["TRAILING"] = "trailing"; })(MaintenanceTrackName || (exports.MaintenanceTrackName = MaintenanceTrackName = {})); /** * A new or imported clustered database. */ class ClusterBase extends core_1.Resource { /** * Renders the secret attachment target specifications. */ asSecretAttachmentTarget() { return { targetId: this.clusterName, targetType: secretsmanager.AttachmentTargetType.REDSHIFT_CLUSTER, }; } } /** * Create a Redshift cluster a given number of nodes. * * @resource AWS::Redshift::Cluster */ let Cluster = class Cluster extends ClusterBase { /** * Import an existing DatabaseCluster from properties */ static fromClusterAttributes(scope, id, attrs) { try { jsiiDeprecationWarnings._aws_cdk_aws_redshift_alpha_ClusterAttributes(attrs); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromClusterAttributes); } throw error; } class Import extends ClusterBase { constructor() { super(...arguments); this.connections = new ec2.Connections({ securityGroups: attrs.securityGroups, defaultPort: ec2.Port.tcp(attrs.clusterEndpointPort), }); this.clusterName = attrs.clusterName; this.instanceIdentifiers = []; this.clusterEndpoint = new endpoint_1.Endpoint(attrs.clusterEndpointAddress, attrs.clusterEndpointPort); } } return new Import(scope, id); } constructor(scope, id, props) { super(scope, id); try { jsiiDeprecationWarnings._aws_cdk_aws_redshift_alpha_ClusterProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, Cluster); } throw error; } // Enhanced CDK Analytics Telemetry (0, metadata_resource_1.addConstructMetadata)(this, props); this.vpc = props.vpc; this.vpcSubnets = props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }; this.parameterGroup = props.parameterGroup; this.roles = props?.roles ? [...props.roles] : []; const removalPolicy = props.removalPolicy ?? core_1.RemovalPolicy.RETAIN; const subnetGroup = props.subnetGroup ?? new subnet_group_1.ClusterSubnetGroup(this, 'Subnets', { description: `Subnets for ${id} Redshift cluster`, vpc: this.vpc, vpcSubnets: this.vpcSubnets, removalPolicy: removalPolicy, }); const securityGroups = props.securityGroups ?? [new ec2.SecurityGroup(this, 'SecurityGroup', { description: 'Redshift security group', vpc: this.vpc, })]; const securityGroupIds = securityGroups.map(sg => sg.securityGroupId); let secret; if (!props.masterUser.masterPassword) { secret = new database_secret_1.DatabaseSecret(this, 'Secret', { username: props.masterUser.masterUsername, encryptionKey: props.masterUser.encryptionKey, excludeCharacters: props.masterUser.excludeCharacters, }); } const clusterType = props.clusterType || ClusterType.MULTI_NODE; const nodeCount = this.validateNodeCount(clusterType, props.numberOfNodes); if (props.encrypted === false && props.encryptionKey !== undefined) { throw new Error('Cannot set property encryptionKey without enabling encryption!'); } this.singleUserRotationApplication = secretsmanager.SecretRotationApplication.REDSHIFT_ROTATION_SINGLE_USER; this.multiUserRotationApplication = secretsmanager.SecretRotationApplication.REDSHIFT_ROTATION_MULTI_USER; let loggingProperties; if (props.loggingProperties) { loggingProperties = { bucketName: props.loggingProperties.loggingBucket.bucketName, s3KeyPrefix: props.loggingProperties.loggingKeyPrefix, }; props.loggingProperties.loggingBucket.addToResourcePolicy(new iam.PolicyStatement({ actions: [ 's3:GetBucketAcl', 's3:PutObject', ], resources: [ props.loggingProperties.loggingBucket.arnForObjects('*'), props.loggingProperties.loggingBucket.bucketArn, ], principals: [ new iam.ServicePrincipal('redshift.amazonaws.com'), ], })); } const nodeType = props.nodeType || NodeType.DC2_LARGE; if (props.multiAz) { if (!nodeType.startsWith('ra3')) { throw new Error(`Multi-AZ cluster is only supported for RA3 node types, got: ${props.nodeType}`); } if (clusterType === ClusterType.SINGLE_NODE) { throw new Error('Multi-AZ cluster is not supported for `clusterType` single-node'); } } if (props.resourceAction === ResourceAction.FAILOVER_PRIMARY_COMPUTE && !props.multiAz) { throw new Error('ResourceAction.FAILOVER_PRIMARY_COMPUTE can only be used with multi-AZ clusters.'); } if (props.availabilityZoneRelocation && !nodeType.startsWith('ra3')) { throw new Error(`Availability zone relocation is supported for only RA3 node types, got: ${props.nodeType}`); } this.cluster = new aws_redshift_1.CfnCluster(this, 'Resource', { // Basic allowVersionUpgrade: true, maintenanceTrackName: props.maintenanceTrackName, automatedSnapshotRetentionPeriod: 1, clusterType, clusterIdentifier: props.clusterName, clusterSubnetGroupName: subnetGroup.clusterSubnetGroupName, vpcSecurityGroupIds: securityGroupIds, port: props.port, clusterParameterGroupName: props.parameterGroup && props.parameterGroup.clusterParameterGroupName, // Admin (unsafeUnwrap here is safe) masterUsername: secret?.secretValueFromJson('username').unsafeUnwrap() ?? props.masterUser.masterUsername, masterUserPassword: secret?.secretValueFromJson('password').unsafeUnwrap() ?? props.masterUser.masterPassword?.unsafeUnwrap() ?? 'default', preferredMaintenanceWindow: props.preferredMaintenanceWindow, nodeType, numberOfNodes: nodeCount, loggingProperties, iamRoles: core_1.Lazy.list({ produce: () => this.roles.map(role => role.roleArn) }, { omitEmpty: true }), dbName: props.defaultDatabaseName || 'default_db', publiclyAccessible: props.publiclyAccessible || false, // Encryption kmsKeyId: props.encryptionKey?.keyId, encrypted: props.encrypted ?? true, classic: props.classicResizing, elasticIp: props.elasticIp, enhancedVpcRouting: props.enhancedVpcRouting, multiAz: props.multiAz, resourceAction: props.resourceAction, availabilityZoneRelocation: props.availabilityZoneRelocation, }); this.cluster.applyRemovalPolicy(removalPolicy, { applyToUpdateReplacePolicy: true, }); this.clusterName = this.cluster.ref; // create a number token that represents the port of the cluster const portAttribute = core_1.Token.asNumber(this.cluster.attrEndpointPort); this.clusterEndpoint = new endpoint_1.Endpoint(this.cluster.attrEndpointAddress, portAttribute); if (secret) { this.secret = secret.attach(this); } const defaultPort = ec2.Port.tcp(this.clusterEndpoint.port); this.connections = new ec2.Connections({ securityGroups, defaultPort }); if (props.rebootForParameterChanges) { this.enableRebootForParameterChanges(); } // Add default role if specified and also available in the roles list if (props.defaultRole) { if (props.roles?.some(x => x === props.defaultRole)) { this.addDefaultIamRole(props.defaultRole); } else { throw new Error('Default role must be included in role list.'); } } } /** * Adds the single user rotation of the master password to this cluster. * * @param [automaticallyAfter=Duration.days(30)] Specifies the number of days after the previous rotation * before Secrets Manager triggers the next automatic rotation. */ addRotationSingleUser(automaticallyAfter) { if (!this.secret) { throw new Error('Cannot add single user rotation for a cluster without secret.'); } const id = 'RotationSingleUser'; const existing = this.node.tryFindChild(id); if (existing) { throw new Error('A single user rotation was already added to this cluster.'); } return new secretsmanager.SecretRotation(this, id, { secret: this.secret, automaticallyAfter, application: this.singleUserRotationApplication, vpc: this.vpc, vpcSubnets: this.vpcSubnets, target: this, }); } /** * Adds the multi user rotation to this cluster. */ addRotationMultiUser(id, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_redshift_alpha_RotationMultiUserOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addRotationMultiUser); } throw error; } if (!this.secret) { throw new Error('Cannot add multi user rotation for a cluster without secret.'); } return new secretsmanager.SecretRotation(this, id, { secret: options.secret, masterSecret: this.secret, automaticallyAfter: options.automaticallyAfter, application: this.multiUserRotationApplication, vpc: this.vpc, vpcSubnets: this.vpcSubnets, target: this, }); } validateNodeCount(clusterType, numberOfNodes) { if (clusterType === ClusterType.SINGLE_NODE) { // This property must not be set for single-node clusters; be generous and treat a value of 1 node as undefined. if (numberOfNodes !== undefined && numberOfNodes !== 1) { throw new Error('Number of nodes must be not be supplied or be 1 for cluster type single-node'); } return undefined; } else { if (core_1.Token.isUnresolved(numberOfNodes)) { return numberOfNodes; } const nodeCount = numberOfNodes ?? 2; if (nodeCount < 2 || nodeCount > 100) { throw new Error('Number of nodes for cluster type multi-node must be at least 2 and no more than 100'); } return nodeCount; } } /** * Adds a parameter to the Clusters' parameter group * * @param name the parameter name * @param value the parameter name */ addToParameterGroup(name, value) { if (!this.parameterGroup) { const param = {}; param[name] = value; this.parameterGroup = new parameter_group_1.ClusterParameterGroup(this, 'ParameterGroup', { description: this.cluster.clusterIdentifier ? `Parameter Group for the ${this.cluster.clusterIdentifier} Redshift cluster` : 'Cluster parameter group for family redshift-1.0', parameters: param, }); this.cluster.clusterParameterGroupName = this.parameterGroup.clusterParameterGroupName; } else if (this.parameterGroup instanceof parameter_group_1.ClusterParameterGroup) { this.parameterGroup.addParameter(name, value); } else { throw new Error('Cannot add a parameter to an imported parameter group.'); } } /** * Enables automatic cluster rebooting when changes to the cluster's parameter group require a restart to apply. */ enableRebootForParameterChanges() { if (this.node.tryFindChild('RedshiftClusterRebooterCustomResource')) { return; } const rebootFunction = new lambda.SingletonFunction(this, 'RedshiftClusterRebooterFunction', { uuid: '511e207f-13df-4b8b-b632-c32b30b65ac2', runtime: lambda.determineLatestNodeRuntime(this), code: lambda.Code.fromAsset(path.join(__dirname, '..', 'custom-resource-handlers', 'dist', 'aws-redshift-alpha', 'cluster-parameter-change-reboot-handler')), handler: 'index.handler', timeout: core_1.Duration.seconds(900), }); rebootFunction.addToRolePolicy(new iam.PolicyStatement({ actions: ['redshift:DescribeClusters'], resources: ['*'], })); rebootFunction.addToRolePolicy(new iam.PolicyStatement({ actions: ['redshift:RebootCluster'], resources: [ core_1.Stack.of(this).formatArn({ service: 'redshift', resource: 'cluster', resourceName: this.clusterName, arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME, }), ], })); const provider = new custom_resources_1.Provider(this, 'ResourceProvider', { onEventHandler: rebootFunction, }); const customResource = new core_1.CustomResource(this, 'RedshiftClusterRebooterCustomResource', { resourceType: 'Custom::RedshiftClusterRebooter', serviceToken: provider.serviceToken, properties: { ClusterId: this.clusterName, ParameterGroupName: core_1.Lazy.string({ produce: () => { if (!this.parameterGroup) { throw new Error('Cannot enable reboot for parameter changes when there is no associated ClusterParameterGroup.'); } return this.parameterGroup.clusterParameterGroupName; }, }), ParametersString: core_1.Lazy.string({ produce: () => { if (!(this.parameterGroup instanceof parameter_group_1.ClusterParameterGroup)) { throw new Error('Cannot enable reboot for parameter changes when using an imported parameter group.'); } return JSON.stringify(this.parameterGroup.parameters); }, }), }, }); core_1.Lazy.any({ produce: () => { if (!this.parameterGroup) { throw new Error('Cannot enable reboot for parameter changes when there is no associated ClusterParameterGroup.'); } customResource.node.addDependency(this, this.parameterGroup); }, }); } /** * Adds default IAM role to cluster. The default IAM role must be already associated to the cluster to be added as the default role. * * @param defaultIamRole the IAM role to be set as the default role */ addDefaultIamRole(defaultIamRole) { // Get list of IAM roles attached to cluster const clusterRoleList = this.roles ?? []; // Check to see if default role is included in list of cluster IAM roles var roleAlreadyOnCluster = false; for (var i = 0; i < clusterRoleList.length; i++) { if (clusterRoleList[i] === defaultIamRole) { roleAlreadyOnCluster = true; break; } } if (!roleAlreadyOnCluster) { throw new Error('Default role must be associated to the Redshift cluster to be set as the default role.'); } // On UPDATE or CREATE define the default IAM role. On DELETE, remove the default IAM role const defaultRoleCustomResource = new custom_resources_1.AwsCustomResource(this, 'default-role', { onUpdate: { service: 'Redshift', action: 'modifyClusterIamRoles', parameters: { ClusterIdentifier: this.cluster.ref, DefaultIamRoleArn: defaultIamRole.roleArn, }, physicalResourceId: custom_resources_1.PhysicalResourceId.of(`${defaultIamRole.roleArn}-${this.cluster.ref}`), }, onDelete: { service: 'Redshift', action: 'modifyClusterIamRoles', parameters: { ClusterIdentifier: this.cluster.ref, DefaultIamRoleArn: '', }, physicalResourceId: custom_resources_1.PhysicalResourceId.of(`${defaultIamRole.roleArn}-${this.cluster.ref}`), }, policy: custom_resources_1.AwsCustomResourcePolicy.fromSdkCalls({ resources: custom_resources_1.AwsCustomResourcePolicy.ANY_RESOURCE, }), installLatestAwsSdk: false, }); defaultIamRole.grantPassRole(defaultRoleCustomResource.grantPrincipal); } /** * Adds a role to the cluster * * @param role the role to add */ addIamRole(role) { const clusterRoleList = this.roles; if (clusterRoleList.includes(role)) { throw new Error(`Role '${role.roleArn}' is already attached to the cluster`); } clusterRoleList.push(role); } }; exports.Cluster = Cluster; _a = JSII_RTTI_SYMBOL_1; Cluster[_a] = { fqn: "@aws-cdk/aws-redshift-alpha.Cluster", version: "2.211.0-alpha.0" }; /** Uniquely identifies this class. */ Cluster.PROPERTY_INJECTION_ID = '@aws-cdk.aws-redshift-alpha.Cluster'; __decorate([ (0, metadata_resource_1.MethodMetadata)() ], Cluster.prototype, "addRotationSingleUser", null); __decorate([ (0, metadata_resource_1.MethodMetadata)() ], Cluster.prototype, "addRotationMultiUser", null); __decorate([ (0, metadata_resource_1.MethodMetadata)() ], Cluster.prototype, "addToParameterGroup", null); __decorate([ (0, metadata_resource_1.MethodMetadata)() ], Cluster.prototype, "enableRebootForParameterChanges", null); __decorate([ (0, metadata_resource_1.MethodMetadata)() ], Cluster.prototype, "addDefaultIamRole", null); __decorate([ (0, metadata_resource_1.MethodMetadata)() ], Cluster.prototype, "addIamRole", null); exports.Cluster = Cluster = __decorate([ prop_injectable_1.propertyInjectable ], Cluster); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsNkJBQTZCO0FBQzdCLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFFM0MsaURBQWlEO0FBRWpELGlFQUFpRTtBQUNqRSwyQ0FBNEk7QUFDNUksbUVBQXdIO0FBRXhILHVEQUFtRDtBQUNuRCx5Q0FBc0M7QUFDdEMsdURBQWtGO0FBQ2xGLDJEQUFzRDtBQUN0RCxpREFBeUU7QUFDekUsOEVBQThGO0FBQzlGLDBFQUEwRTtBQUUxRTs7O0dBR0c7QUFDSCxJQUFZLFFBa0RYO0FBbERELFdBQVksUUFBUTtJQUNsQjs7T0FFRztJQUNILHFDQUF5QixDQUFBO0lBRXpCOztPQUVHO0lBQ0gsdUNBQTJCLENBQUE7SUFFM0I7O09BRUc7SUFDSCxtQ0FBdUIsQ0FBQTtJQUV2Qjs7T0FFRztJQUNILHVDQUEyQixDQUFBO0lBRTNCOztPQUVHO0lBQ0gsbUNBQXVCLENBQUE7SUFFdkI7O09BRUc7SUFDSCx1Q0FBMkIsQ0FBQTtJQUUzQjs7T0FFRztJQUNILG1DQUF1QixDQUFBO0lBRXZCOztPQUVHO0lBQ0gscUNBQXlCLENBQUE7SUFFekI7O09BRUc7SUFDSCx1Q0FBMkIsQ0FBQTtJQUUzQjs7T0FFRztJQUNILHlDQUE2QixDQUFBO0FBQy9CLENBQUMsRUFsRFcsUUFBUSx3QkFBUixRQUFRLFFBa0RuQjtBQUVEOzs7R0FHRztBQUNILElBQVksV0FTWDtBQVRELFdBQVksV0FBVztJQUNyQjs7T0FFRztJQUNILDBDQUEyQixDQUFBO0lBQzNCOztPQUVHO0lBQ0gsd0NBQXlCLENBQUE7QUFDM0IsQ0FBQyxFQVRXLFdBQVcsMkJBQVgsV0FBVyxRQVN0QjtBQUVEOztHQUVHO0FBQ0gsSUFBWSxjQWlCWDtBQWpCRCxXQUFZLGNBQWM7SUFDeEI7O09BRUc7SUFDSCxpREFBK0IsQ0FBQTtJQUUvQjs7T0FFRztJQUNILG1EQUFpQyxD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QjtBQVFNO0lBRE4sSUFBQSxrQ0FBYyxHQUFFO3lDQVNoQjtrQkEvYlUsT0FBTztJQURuQixvQ0FBa0I7R0FDTixPQUFPLENBZ2NuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBrbXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWttcyc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgc2VjcmV0c21hbmFnZXIgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNlY3JldHNtYW5hZ2VyJztcbmltcG9ydCB7IEFybkZvcm1hdCwgQ3VzdG9tUmVzb3VyY2UsIER1cmF0aW9uLCBJUmVzb3VyY2UsIExhenksIFJlbW92YWxQb2xpY3ksIFJlc291cmNlLCBTZWNyZXRWYWx1ZSwgU3RhY2ssIFRva2VuIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZSc7XG5pbXBvcnQgeyBBd3NDdXN0b21SZXNvdXJjZSwgQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3ksIFBoeXNpY2FsUmVzb3VyY2VJZCwgUHJvdmlkZXIgfSBmcm9tICdhd3MtY2RrLWxpYi9jdXN0b20tcmVzb3VyY2VzJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgRGF0YWJhc2VTZWNyZXQgfSBmcm9tICcuL2RhdGFiYXNlLXNlY3JldCc7XG5pbXBvcnQgeyBFbmRwb2ludCB9IGZyb20gJy4vZW5kcG9pbnQnO1xuaW1wb3J0IHsgQ2x1c3RlclBhcmFtZXRlckdyb3VwLCBJQ2x1c3RlclBhcmFtZXRlckdyb3VwIH0gZnJvbSAnLi9wYXJhbWV0ZXItZ3JvdXAnO1xuaW1wb3J0IHsgQ2ZuQ2x1c3RlciB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1yZWRzaGlmdCc7XG5pbXBvcnQgeyBDbHVzdGVyU3VibmV0R3JvdXAsIElDbHVzdGVyU3VibmV0R3JvdXAgfSBmcm9tICcuL3N1Ym5ldC1ncm91cCc7XG5pbXBvcnQgeyBhZGRDb25zdHJ1Y3RNZXRhZGF0YSwgTWV0aG9kTWV0YWRhdGEgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlL2xpYi9tZXRhZGF0YS1yZXNvdXJjZSc7XG5pbXBvcnQgeyBwcm9wZXJ0eUluamVjdGFibGUgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlL2xpYi9wcm9wLWluamVjdGFibGUnO1xuXG4vKipcbiAqIFBvc3NpYmxlIE5vZGUgVHlwZXMgdG8gdXNlIGluIHRoZSBjbHVzdGVyXG4gKiB1c2VkIGZvciBkZWZpbmluZyBgQ2x1c3RlclByb3BzLm5vZGVUeXBlYC5cbiAqL1xuZXhwb3J0IGVudW0gTm9kZVR5cGUge1xuICAvKipcbiAgICogZHMyLnhsYXJnZVxuICAgKi9cbiAgRFMyX1hMQVJHRSA9ICdkczIueGxhcmdlJyxcblxuICAvKipcbiAgICogZHMyLjh4bGFyZ2VcbiAgICovXG4gIERTMl84WExBUkdFID0gJ2RzMi44eGxhcmdlJyxcblxuICAvKipcbiAgICogZGMxLmxhcmdlXG4gICAqL1xuICBEQzFfTEFSR0UgPSAnZGMxLmxhcmdlJyxcblxuICAvKipcbiAgICogZGMxLjh4bGFyZ2VcbiAgICovXG4gIERDMV84WExBUkdFID0gJ2RjMS44eGxhcmdlJyxcblxuICAvKipcbiAgICogZGMyLmxhcmdlXG4gICAqL1xuICBEQzJfTEFSR0UgPSAnZGMyLmxhcmdlJyxcblxuICAvKipcbiAgICogZGMyLjh4bGFyZ2VcbiAgICovXG4gIERDMl84WExBUkdFID0gJ2RjMi44eGxhcmdlJyxcblxuICAvKipcbiAgICogcmEzLmxhcmdlXG4gICAqL1xuICBSQTNfTEFSR0UgPSAncmEzLmxhcmdlJyxcblxuICAvKipcbiAgICogcmEzLnhscGx1c1xuICAgKi9cbiAgUkEzX1hMUExVUyA9ICdyYTMueGxwbHVzJyxcblxuICAvKipcbiAgICogcmEzLjR4bGFyZ2VcbiAgICovXG4gIFJBM180WExBUkdFID0gJ3JhMy40eGxhcmdlJyxcblxuICAvKipcbiAgICogcmEzLjE2eGxhcmdlXG4gICAqL1xuICBSQTNfMTZYTEFSR0UgPSAncmEzLjE2eGxhcmdlJyxcbn1cblxuLyoqXG4gKiBXaGF0IGNsdXN0ZXIgdHlwZSB0byB1c2UuXG4gKiBVc2VkIGJ5IGBDbHVzdGVyUHJvcHMuY2x1c3RlclR5cGVgXG4gKi9cbmV4cG9ydCBlbnVtIENsdXN0ZXJUeXBlIHtcbiAgLyoqXG4gICAqIHNpbmdsZS1ub2RlIGNsdXN0ZXIsIHRoZSBgQ2x1c3RlclByb3BzLm51bWJlck9mTm9kZXNgIHBhcmFtZXRlciBpcyBub3QgcmVxdWlyZWRcbiAgICovXG4gIFNJTkdMRV9OT0RFID0gJ3NpbmdsZS1ub2RlJyxcbiAgLyoqXG4gICAqIG11bHRpLW5vZGUgY2x1c3Rlciwgc2V0IHRoZSBhbW91bnQgb2Ygbm9kZXMgdXNpbmcgYENsdXN0ZXJQcm9wcy5udW1iZXJPZk5vZGVzYCBwYXJhbWV0ZXJcbiAgICovXG4gIE1VTFRJX05PREUgPSAnbXVsdGktbm9kZScsXG59XG5cbi8qKlxuICogVGhlIEFtYXpvbiBSZWRzaGlmdCBvcGVyYXRpb25cbiAqL1xuZXhwb3J0IGVudW0gUmVzb3VyY2VBY3Rpb24ge1xuICAvKipcbiAgICogUGF1c2UgdGhlIGNsdXN0ZXJcbiAgICovXG4gIFBBVVNFX0NMVVNURVIgPSAncGF1c2UtY2x1c3RlcicsXG5cbiAgLyoqXG4gICAqIFJlc3VtZSB0aGUgY2x1c3RlclxuICAgKi9cbiAgUkVTVU1FX0NMVVNURVIgPSAncmVzdW1lLWNsdXN0ZXInLFxuXG4gIC8qKlxuICAgKiBGYWlsaW5nIG92ZXIgdG8gdGhlIG90aGVyIGF2YWlsYWJpbGl0eSB6b25lXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3JlZHNoaWZ0L2xhdGVzdC9tZ210L3Rlc3QtY2x1c3Rlci1tdWx0aS1hei5odG1sXG4gICAqL1xuICBGQUlMT1ZFUl9QUklNQVJZX0NPTVBVVEUgPSAnZmFpbG92ZXItcHJpbWFyeS1jb21wdXRlJyxcbn1cblxuLyoqXG4gKiBVc2VybmFtZSBhbmQgcGFzc3dvcmQgY29tYmluYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2dpbiB7XG4gIC8qKlxuICAgKiBVc2VybmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgbWFzdGVyVXNlcm5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogUGFzc3dvcmRcbiAgICpcbiAgICogRG8gbm90IHB1dCBwYXNzd29yZHMgaW4geW91ciBDREsgY29kZSBkaXJlY3RseS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhIFNlY3JldHMgTWFuYWdlciBnZW5lcmF0ZWQgcGFzc3dvcmRcbiAgICovXG4gIHJlYWRvbmx5IG1hc3RlclBhc3N3b3JkPzogU2VjcmV0VmFsdWU7XG5cbiAgLyoqXG4gICAqIEtNUyBlbmNyeXB0aW9uIGtleSB0byBlbmNyeXB0IHRoZSBnZW5lcmF0ZWQgc2VjcmV0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgbWFzdGVyIGtleVxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBDaGFyYWN0ZXJzIHRvIG5vdCBpbmNsdWRlIGluIHRoZSBnZW5lcmF0ZWQgcGFzc3dvcmQuXG4gICAqXG4gICAqIEBkZWZhdWx0ICdcIkAvXFxcXFxcIFxcJydcbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGVDaGFyYWN0ZXJzPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIExvZ2dpbmcgYnVja2V0IGFuZCBTMyBwcmVmaXggY29tYmluYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2dnaW5nUHJvcGVydGllcyB7XG4gIC8qKlxuICAgKiBCdWNrZXQgdG8gc2VuZCBsb2dzIHRvLlxuICAgKiBMb2dnaW5nIGluZm9ybWF0aW9uIGluY2x1ZGVzIHF1ZXJpZXMgYW5kIGNvbm5lY3Rpb24gYXR0ZW1wdHMsIGZvciB0aGUgc3BlY2lmaWVkIEFtYXpvbiBSZWRzaGlmdCBjbHVzdGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9nZ2luZ0J1Y2tldDogczMuSUJ1Y2tldDtcblxuICAvKipcbiAgICogUHJlZml4IHVzZWQgZm9yIGxvZ2dpbmcuXG4gICAqL1xuICByZWFkb25seSBsb2dnaW5nS2V5UHJlZml4OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3B0aW9ucyB0byBhZGQgdGhlIG11bHRpIHVzZXIgcm90YXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSb3RhdGlvbk11bHRpVXNlck9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHNlY3JldCB0byByb3RhdGUuIEl0IG11c3QgYmUgYSBKU09OIHN0cmluZyB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OlxuICAgKiBgYGBcbiAgICoge1xuICAgKiAgIFwiZW5naW5lXCI6IDxyZXF1aXJlZDogZGF0YWJhc2UgZW5naW5lPixcbiAgICogICBcImhvc3RcIjogPHJlcXVpcmVkOiBpbnN0YW5jZSBob3N0IG5hbWU+LFxuICAgKiAgIFwidXNlcm5hbWVcIjogPHJlcXVpcmVkOiB1c2VybmFtZT4sXG4gICAqICAgXCJwYXNzd29yZFwiOiA8cmVxdWlyZWQ6IHBhc3N3b3JkPixcbiAgICogICBcImRibmFtZVwiOiA8b3B0aW9uYWw6IGRhdGFiYXNlIG5hbWU+LFxuICAgKiAgIFwicG9ydFwiOiA8b3B0aW9uYWw6IGlmIG5vdCBzcGVjaWZpZWQsIGRlZmF1bHQgcG9ydCB3aWxsIGJlIHVzZWQ+LFxuICAgKiAgIFwibWFzdGVyYXJuXCI6IDxyZXF1aXJlZDogdGhlIGFybiBvZiB0aGUgbWFzdGVyIHNlY3JldCB3aGljaCB3aWxsIGJlIHVzZWQgdG8gY3JlYXRlIHVzZXJzL2NoYW5nZSBwYXNzd29yZHM+XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICByZWFkb25seSBzZWNyZXQ6IHNlY3JldHNtYW5hZ2VyLklTZWNyZXQ7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIGRheXMgYWZ0ZXIgdGhlIHByZXZpb3VzIHJvdGF0aW9uIGJlZm9yZVxuICAgKiBTZWNyZXRzIE1hbmFnZXIgdHJpZ2dlcnMgdGhlIG5leHQgYXV0b21hdGljIHJvdGF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5kYXlzKDMwKVxuICAgKi9cbiAgcmVhZG9ubHkgYXV0b21hdGljYWxseUFmdGVyPzogRHVyYXRpb247XG59XG5cbi8qKlxuICogVGhlIG1haW50ZW5hbmNlIHRyYWNrIGZvciB0aGUgY2x1c3Rlci5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9yZWRzaGlmdC9sYXRlc3QvbWdtdC9tYW5hZ2luZy1jbHVzdGVyLWNvbnNpZGVyYXRpb25zLmh0bWwjcnMtbWdtdC1tYWludGVuYW5jZS10cmFja3NcbiAqL1xuZXhwb3J0IGVudW0gTWFpbnRlbmFuY2VUcmFja05hbWUge1xuICAvKipcbiAgICogVXBkYXRlZCB0byB0aGUgbW9zdCByZWNlbnRseSBjZXJ0aWZpZWQgbWFpbnRlbmFuY2UgcmVsZWFzZS5cbiAgICovXG4gIENVUlJFTlQgPSAnY3VycmVudCcsXG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0byB0aGUgcHJldmlvdXNseSBjZXJ0aWZpZWQgbWFpbnRlbmFuY2UgcmVsZWFzZS5cbiAgICovXG4gIFRSQUlMSU5HID0gJ3RyYWlsaW5nJyxcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBSZWRzaGlmdCBDbHVzdGVyIHdpdGggYSBnaXZlbiBudW1iZXIgb2Ygbm9kZXMuXG4gKiBJbXBsZW1lbnRlZCBieSBgQ2x1c3RlcmAgdmlhIGBDbHVzdGVyQmFzZWAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSUNsdXN0ZXIgZXh0ZW5kcyBJUmVzb3VyY2UsIGVjMi5JQ29ubmVjdGFibGUsIHNlY3JldHNtYW5hZ2VyLklTZWNyZXRBdHRhY2htZW50VGFyZ2V0IHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIGNsdXN0ZXJcbiAgICpcbiAgICogQGF0dHJpYnV0ZSBDbHVzdGVyTmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3Rlck5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGVuZHBvaW50IHRvIHVzZSBmb3IgcmVhZC93cml0ZSBvcGVyYXRpb25zXG4gICAqXG4gICAqIEBhdHRyaWJ1dGUgRW5kcG9pbnRBZGRyZXNzLEVuZHBvaW50UG9ydFxuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3RlckVuZHBvaW50OiBFbmRwb2ludDtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIHRoYXQgZGVzY3JpYmUgYW4gZXhpc3RpbmcgY2x1c3RlciBpbnN0YW5jZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsdXN0ZXJBdHRyaWJ1dGVzIHtcbiAgLyoqXG4gICAqIFRoZSBzZWN1cml0eSBncm91cHMgb2YgdGhlIHJlZHNoaWZ0IGNsdXN0ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgbm8gc2VjdXJpdHkgZ3JvdXBzIHdpbGwgYmUgYXR0YWNoZWQgdG8gdGhlIGltcG9ydFxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cHM/OiBlYzIuSVNlY3VyaXR5R3JvdXBbXTtcblxuICAvKipcbiAgICogSWRlbnRpZmllciBmb3IgdGhlIGNsdXN0ZXJcbiAgICovXG4gIHJlYWRvbmx5IGNsdXN0ZXJOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENsdXN0ZXIgZW5kcG9pbnQgYWRkcmVzc1xuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3RlckVuZHBvaW50QWRkcmVzczogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDbHVzdGVyIGVuZHBvaW50IHBvcnRcbiAgICovXG4gIHJlYWRvbmx5IGNsdXN0ZXJFbmRwb2ludFBvcnQ6IG51bWJlcjtcblxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgbmV3IGRhdGFiYXNlIGNsdXN0ZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbHVzdGVyUHJvcHMge1xuICAvKipcbiAgICogQW4gb3B0aW9uYWwgaWRlbnRpZmllciBmb3IgdGhlIGNsdXN0ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgLSBBIG5hbWUgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQuXG4gICAqL1xuICByZWFkb25seSBjbHVzdGVyTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBwYXJhbWV0ZXJzIHRvIHBhc3MgdG8gdGhlIGRhdGFiYXNlIGVuZ2luZVxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vcmVkc2hpZnQvbGF0ZXN0L21nbXQvd29ya2luZy13aXRoLXBhcmFtZXRlci1ncm91cHMuaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHBhcmFtZXRlciBncm91cC5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtZXRlckdyb3VwPzogSUNsdXN0ZXJQYXJhbWV0ZXJHcm91cDtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIGNvbXB1dGUgbm9kZXMgaW4gdGhlIGNsdXN0ZXIuIE9ubHkgc3BlY2lmeSB0aGlzIHByb3BlcnR5IGZvciBtdWx0aS1ub2RlIGNsdXN0ZXJzLlxuICAgKlxuICAgKiBWYWx1ZSBtdXN0IGJlIGF0IGxlYXN0IDIgYW5kIG5vIG1vcmUgdGhhbiAxMDAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gMiBpZiBgY2x1c3RlclR5cGVgIGlzIENsdXN0ZXJUeXBlLk1VTFRJX05PREUsIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAgICovXG4gIHJlYWRvbmx5IG51bWJlck9mTm9kZXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBub2RlIHR5cGUgdG8gYmUgcHJvdmlzaW9uZWQgZm9yIHRoZSBjbHVzdGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgTm9kZVR5cGUuREMyX0xBUkdFYFxuICAgKi9cbiAgcmVhZG9ubHkgbm9kZVR5cGU/OiBOb2RlVHlwZTtcblxuICAvKipcbiAgICogU2V0dGluZ3MgZm9yIHRoZSBpbmRpdmlkdWFsIGluc3RhbmNlcyB0aGF0IGFyZSBsYXVuY2hlZFxuICAgKlxuICAgKiBAZGVmYXVsdCBgQ2x1c3RlclR5cGUuTVVMVElfTk9ERWBcbiAgIC