@cdklabs/cdk-appflow
Version:
*Note:* this library is currently in technical preview.
185 lines • 25.8 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.S3Destination = exports.S3OutputFilePrefixType = exports.S3OutputFilePrefixFormat = exports.S3OutputFilePrefixHierarchy = exports.S3OutputFileType = exports.S3OutputAggregationType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const type_1 = require("./type");
const appflow_permissions_manager_1 = require("../core/appflow-permissions-manager");
const flows_1 = require("../core/flows");
var S3OutputAggregationType;
(function (S3OutputAggregationType) {
S3OutputAggregationType["NONE"] = "None";
S3OutputAggregationType["SINGLE_FILE"] = "SingleFile";
})(S3OutputAggregationType || (exports.S3OutputAggregationType = S3OutputAggregationType = {}));
/**
* Output file type supported by Amazon S3 Destination connector
*/
var S3OutputFileType;
(function (S3OutputFileType) {
/**
* CSV file type
*/
S3OutputFileType["CSV"] = "CSV";
/**
* JSON file type
*/
S3OutputFileType["JSON"] = "JSON";
/**
* Parquet file type
*/
S3OutputFileType["PARQUET"] = "PARQUET";
})(S3OutputFileType || (exports.S3OutputFileType = S3OutputFileType = {}));
var S3OutputFilePrefixHierarchy;
(function (S3OutputFilePrefixHierarchy) {
S3OutputFilePrefixHierarchy["EXECUTION_ID"] = "EXECUTION_ID";
S3OutputFilePrefixHierarchy["SCHEMA_VERSION"] = "SCHEMA_VERSION";
})(S3OutputFilePrefixHierarchy || (exports.S3OutputFilePrefixHierarchy = S3OutputFilePrefixHierarchy = {}));
var S3OutputFilePrefixFormat;
(function (S3OutputFilePrefixFormat) {
S3OutputFilePrefixFormat["DAY"] = "DAY";
S3OutputFilePrefixFormat["HOUR"] = "HOUR";
S3OutputFilePrefixFormat["MINUTE"] = "MINUTE";
S3OutputFilePrefixFormat["MONTH"] = "MONTH";
S3OutputFilePrefixFormat["YEAR"] = "YEAR";
})(S3OutputFilePrefixFormat || (exports.S3OutputFilePrefixFormat = S3OutputFilePrefixFormat = {}));
var S3OutputFilePrefixType;
(function (S3OutputFilePrefixType) {
S3OutputFilePrefixType["FILENAME"] = "FILENAME";
S3OutputFilePrefixType["PATH"] = "PATH";
S3OutputFilePrefixType["PATH_AND_FILE"] = "PATH_AND_FILE";
})(S3OutputFilePrefixType || (exports.S3OutputFilePrefixType = S3OutputFilePrefixType = {}));
class S3Destination {
constructor(props) {
this.props = props;
this.connectorType = type_1.S3ConnectorType.instance;
this.compatibleFlows = [
flows_1.FlowType.ON_DEMAND,
flows_1.FlowType.SCHEDULED,
];
}
buildAggregationConfig(aggregation) {
return (aggregation && {
aggregationType: aggregation.type,
// TODO: make sure it should use mebibytes
targetFileSize: aggregation.fileSize && aggregation.fileSize,
});
}
buildPrefixConfig(filePrefix) {
return (filePrefix && {
pathPrefixHierarchy: filePrefix.hierarchy,
prefixFormat: filePrefix.format,
prefixType: filePrefix.type,
});
}
bind(flow) {
if (!this.compatibleFlows.includes(flow.type)) {
throw new Error(`Flow of type ${flow.type} does not support S3 as a destination`);
}
this.tryAddNodeDependency(flow, this.props.location.bucket);
appflow_permissions_manager_1.AppFlowPermissionsManager.instance().grantBucketWrite(this.props.location.bucket);
if (this.props.catalog) {
const role = this.props.catalog.role ??
this.buildRoleAndPolicyForCatalog(flow, this.props.catalog.database, this.props.catalog.tablePrefix);
this.tryAddNodeDependency(flow, this.props.catalog.database);
this.tryAddNodeDependency(flow, role);
flow._addCatalog({
glueDataCatalog: {
databaseName: this.props.catalog.database.databaseName,
tablePrefix: this.props.catalog.tablePrefix,
roleArn: role.roleArn,
},
});
}
return {
connectorType: this.connectorType.asProfileConnectorType,
destinationConnectorProperties: this.buildDestinationConnectorProperties(),
};
}
/**
* see: https://docs.aws.amazon.com/appflow/latest/userguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-access-gdc
* see: https://docs.aws.amazon.com/appflow/latest/userguide/security_iam_service-role-policies.html#access-gdc
* @param flow
* @param database - the AWS Glue database
* @param tablePrefix - the prefix for the tables that will be created in the AWS Glue database
* @returns a tuple consisting of a role for cataloguing with a specified policy
*/
buildRoleAndPolicyForCatalog(flow, database, tablePrefix) {
const role = new aws_iam_1.Role(flow.stack, `${flow.node.id}GlueAccessRole`, {
assumedBy: new aws_iam_1.ServicePrincipal("appflow.amazonaws.com"),
});
// see: https://docs.aws.amazon.com/appflow/latest/userguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-access-gdc
role.addToPolicy(new aws_iam_1.PolicyStatement({
effect: aws_iam_1.Effect.ALLOW,
actions: [
"glue:BatchCreatePartition",
"glue:CreatePartitionIndex",
"glue:DeleteDatabase",
"glue:GetTableVersions",
"glue:GetPartitions",
"glue:BatchDeletePartition",
"glue:DeleteTableVersion",
"glue:UpdateTable",
"glue:DeleteTable",
"glue:DeletePartitionIndex",
"glue:GetTableVersion",
"glue:CreatePartition",
"glue:UntagResource",
"glue:UpdatePartition",
"glue:TagResource",
"glue:UpdateDatabase",
"glue:CreateTable",
"glue:BatchUpdatePartition",
"glue:GetTables",
"glue:BatchGetPartition",
"glue:GetDatabases",
"glue:GetPartitionIndexes",
"glue:GetTable",
"glue:GetDatabase",
"glue:GetPartition",
"glue:CreateDatabase",
"glue:BatchDeleteTableVersion",
"glue:BatchDeleteTable",
"glue:DeletePartition",
],
resources: [
database.catalogArn,
database.databaseArn,
aws_cdk_lib_1.Stack.of(flow).formatArn({
service: "glue",
resource: "table",
resourceName: `${database.databaseName}/${tablePrefix}*`,
}),
],
}));
return role;
}
buildDestinationConnectorProperties() {
const bucketName = this.props.location.bucket.bucketName;
if (!bucketName) {
throw new Error("bucketName is required");
}
return {
s3: {
bucketName: bucketName,
bucketPrefix: this.props.location.prefix,
s3OutputFormatConfig: this.props.formatting && {
aggregationConfig: this.buildAggregationConfig(this.props.formatting.aggregation),
fileType: this.props.formatting.fileType ?? S3OutputFileType.JSON,
prefixConfig: this.buildPrefixConfig(this.props.formatting.filePrefix),
preserveSourceDataTyping: this.props.formatting.preserveSourceDataTypes,
},
},
};
}
tryAddNodeDependency(scope, resource) {
if (resource && typeof resource !== "string") {
scope.node.addDependency(resource);
}
}
}
exports.S3Destination = S3Destination;
_a = JSII_RTTI_SYMBOL_1;
S3Destination[_a] = { fqn: "@cdklabs/cdk-appflow.S3Destination", version: "0.2.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzdGluYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvczMvZGVzdGluYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFLQSw2Q0FBb0M7QUFFcEMsaURBTTZCO0FBRTdCLGlDQUF5QztBQUN6QyxxRkFBZ0Y7QUFFaEYseUNBQWdEO0FBd0NoRCxJQUFZLHVCQUdYO0FBSEQsV0FBWSx1QkFBdUI7SUFDakMsd0NBQWEsQ0FBQTtJQUNiLHFEQUEwQixDQUFBO0FBQzVCLENBQUMsRUFIVyx1QkFBdUIsdUNBQXZCLHVCQUF1QixRQUdsQztBQUVEOztHQUVHO0FBQ0gsSUFBWSxnQkFhWDtBQWJELFdBQVksZ0JBQWdCO0lBQzFCOztPQUVHO0lBQ0gsK0JBQVcsQ0FBQTtJQUNYOztPQUVHO0lBQ0gsaUNBQWEsQ0FBQTtJQUNiOztPQUVHO0lBQ0gsdUNBQW1CLENBQUE7QUFDckIsQ0FBQyxFQWJXLGdCQUFnQixnQ0FBaEIsZ0JBQWdCLFFBYTNCO0FBRUQsSUFBWSwyQkFHWDtBQUhELFdBQVksMkJBQTJCO0lBQ3JDLDREQUE2QixDQUFBO0lBQzdCLGdFQUFpQyxDQUFBO0FBQ25DLENBQUMsRUFIVywyQkFBMkIsMkNBQTNCLDJCQUEyQixRQUd0QztBQUVELElBQVksd0JBTVg7QUFORCxXQUFZLHdCQUF3QjtJQUNsQyx1Q0FBVyxDQUFBO0lBQ1gseUNBQWEsQ0FBQTtJQUNiLDZDQUFpQixDQUFBO0lBQ2pCLDJDQUFlLENBQUE7SUFDZix5Q0FBYSxDQUFBO0FBQ2YsQ0FBQyxFQU5XLHdCQUF3Qix3Q0FBeEIsd0JBQXdCLFFBTW5DO0FBRUQsSUFBWSxzQkFJWDtBQUpELFdBQVksc0JBQXNCO0lBQ2hDLCtDQUFxQixDQUFBO0lBQ3JCLHVDQUFhLENBQUE7SUFDYix5REFBK0IsQ0FBQTtBQUNqQyxDQUFDLEVBSlcsc0JBQXNCLHNDQUF0QixzQkFBc0IsUUFJakM7QUFxQ0QsTUFBYSxhQUFhO0lBUXhCLFlBQTZCLEtBQXlC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QztRQUVELE9BQU87WUFDTCxFQUFFLEVBQUU7Z0JBQ0YsVUFBVSxFQUFFLFVBQVU7Z0JBQ3RCLFlBQVksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNO2dCQUN4QyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsSUFBSTtvQkFDN0MsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLHNCQUFzQixDQUM1QyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQ2xDO29CQUNELFFBQVEsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLElBQUksZ0JBQWdCLENBQUMsSUFBSTtvQkFDakUsWUFBWSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FDbEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUNqQztvQkFDRCx3QkFBd0IsRUFDdEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsdUJBQXVCO2lCQUNoRDthQUNGO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFTyxvQkFBb0IsQ0FDMUIsS0FBaUIsRUFDakIsUUFBOEI7UUFFOUIsSUFBSSxRQUFRLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDckMsQ0FBQztJQUNILENBQUM7O0FBMUtILHNDQTJLQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4qL1xuaW1wb3J0IHsgSURhdGFiYXNlIH0gZnJvbSBcIkBhd3MtY2RrL2F3cy1nbHVlLWFscGhhXCI7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgQ2ZuRmxvdyB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXBwZmxvd1wiO1xuaW1wb3J0IHtcbiAgRWZmZWN0LFxuICBJUm9sZSxcbiAgUG9saWN5U3RhdGVtZW50LFxuICBSb2xlLFxuICBTZXJ2aWNlUHJpbmNpcGFsLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiO1xuaW1wb3J0IHsgSUNvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBTM0Nvbm5lY3RvclR5cGUgfSBmcm9tIFwiLi90eXBlXCI7XG5pbXBvcnQgeyBBcHBGbG93UGVybWlzc2lvbnNNYW5hZ2VyIH0gZnJvbSBcIi4uL2NvcmUvYXBwZmxvdy1wZXJtaXNzaW9ucy1tYW5hZ2VyXCI7XG5pbXBvcnQgeyBDb25uZWN0b3JUeXBlIH0gZnJvbSBcIi4uL2NvcmUvY29ubmVjdG9ycy9jb25uZWN0b3ItdHlwZVwiO1xuaW1wb3J0IHsgRmxvd1R5cGUsIElGbG93IH0gZnJvbSBcIi4uL2NvcmUvZmxvd3NcIjtcbmltcG9ydCB7IFMzTG9jYXRpb24gfSBmcm9tIFwiLi4vY29yZS9zMy1sb2NhdGlvblwiO1xuaW1wb3J0IHsgSURlc3RpbmF0aW9uIH0gZnJvbSBcIi4uL2NvcmUvdmVydGljZXMvZGVzdGluYXRpb25cIjtcblxuZXhwb3J0IGludGVyZmFjZSBTM0ZpbGVBZ2dyZWdhdGlvbiB7XG4gIHJlYWRvbmx5IHR5cGU/OiBTM091dHB1dEFnZ3JlZ2F0aW9uVHlwZTtcbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIHNpemUsIGluIE1CLCBvZiB0aGUgZmlsZSBjb250YWluaW5nIHBvcnRpb24gb2YgaW5jb21pbmcgZGF0YVxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZVNpemU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUzNPdXRwdXRGaWxlUHJlZml4IHtcbiAgcmVhZG9ubHkgaGllcmFyY2h5PzogUzNPdXRwdXRGaWxlUHJlZml4SGllcmFyY2h5W107XG4gIHJlYWRvbmx5IGZvcm1hdD86IFMzT3V0cHV0RmlsZVByZWZpeEZvcm1hdDtcbiAgcmVhZG9ubHkgdHlwZT86IFMzT3V0cHV0RmlsZVByZWZpeFR5cGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUzNPdXRwdXRGb3JtYXR0aW5nIHtcbiAgLyoqXG4gICAqIFNldHMgYW4gYWdncmVnYXRpb24gYXBwcm9hY2ggcGVyIGZsb3cgcnVuXG4gICAqL1xuICByZWFkb25seSBhZ2dyZWdhdGlvbj86IFMzRmlsZUFnZ3JlZ2F0aW9uO1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBmaWxlIHR5cGUgZm9yIHRoZSBvdXRwdXQgZmlsZXNcbiAgICogQGRlZmF1bHQgLSBKU09OIGZpbGUgdHlwZVxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZVR5cGU/OiBTM091dHB1dEZpbGVUeXBlO1xuICAvKipcbiAgICogU2V0cyBhIHByZWZpeCBhcHByb2FjaCBmb3IgZmlsZXMgZ2VuZXJhdGVkIGR1cmluZyBhIGZsb3cgZXhlY3V0aW9uXG4gICAqL1xuICByZWFkb25seSBmaWxlUHJlZml4PzogUzNPdXRwdXRGaWxlUHJlZml4O1xuICAvKipcbiAgICogU3BlY2lmaWVzIHdoZXRoZXIgQXBwRmxvdyBzaG91bGQgYXR0ZW1wdCBkYXRhIHR5cGUgbWFwcGluZyBmcm9tIHNvdXJjZSB3aGVuIHRoZSBkZXN0aW5hdGlvbiBvdXRwdXQgZmlsZSB0eXBlIGlzIFBhcnF1ZXRcbiAgICogQGRlZmF1bHQgLSBkbyBub3QgcHJlc2VydmUgc291cmNlIGRhdGEgZmlsZXNcbiAgICovXG4gIHJlYWRvbmx5IHByZXNlcnZlU291cmNlRGF0YVR5cGVzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGVudW0gUzNPdXRwdXRBZ2dyZWdhdGlvblR5cGUge1xuICBOT05FID0gXCJOb25lXCIsXG4gIFNJTkdMRV9GSUxFID0gXCJTaW5nbGVGaWxlXCIsXG59XG5cbi8qKlxuICogT3V0cHV0IGZpbGUgdHlwZSBzdXBwb3J0ZWQgYnkgQW1hem9uIFMzIERlc3RpbmF0aW9uIGNvbm5lY3RvclxuICovXG5leHBvcnQgZW51bSBTM091dHB1dEZpbGVUeXBlIHtcbiAgLyoqXG4gICAqIENTViBmaWxlIHR5cGVcbiAgICovXG4gIENTViA9IFwiQ1NWXCIsXG4gIC8qKlxuICAgKiBKU09OIGZpbGUgdHlwZVxuICAgKi9cbiAgSlNPTiA9IFwiSlNPTlwiLFxuICAvKipcbiAgICogUGFycXVldCBmaWxlIHR5cGVcbiAgICovXG4gIFBBUlFVRVQgPSBcIlBBUlFVRVRcIixcbn1cblxuZXhwb3J0IGVudW0gUzNPdXRwdXRGaWxlUHJlZml4SGllcmFyY2h5IHtcbiAgRVhFQ1VUSU9OX0lEID0gXCJFWEVDVVRJT05fSURcIixcbiAgU0NIRU1BX1ZFUlNJT04gPSBcIlNDSEVNQV9WRVJTSU9OXCIsXG59XG5cbmV4cG9ydCBlbnVtIFMzT3V0cHV0RmlsZVByZWZpeEZvcm1hdCB7XG4gIERBWSA9IFwiREFZXCIsXG4gIEhPVVIgPSBcIkhPVVJcIixcbiAgTUlOVVRFID0gXCJNSU5VVEVcIixcbiAgTU9OVEggPSBcIk1PTlRIXCIsXG4gIFlFQVIgPSBcIllFQVJcIixcbn1cblxuZXhwb3J0IGVudW0gUzNPdXRwdXRGaWxlUHJlZml4VHlwZSB7XG4gIEZJTEVOQU1FID0gXCJGSUxFTkFNRVwiLFxuICBQQVRIID0gXCJQQVRIXCIsXG4gIFBBVEhfQU5EX0ZJTEUgPSBcIlBBVEhfQU5EX0ZJTEVcIixcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTM0NhdGFsb2cge1xuICAvKipcbiAgICogVGhlIElBTSBSb2xlIHRoYXQgd2lsbCBiZSB1c2VkIGZvciBkYXRhIGNhdGFsb2cgb3BlcmF0aW9uc1xuICAgKiBAZGVmYXVsdCAtIEEgbmV3IHJvbGUgd2lsbCBiZSBjcmVhdGVkXG4gICAqL1xuICByZWFkb25seSByb2xlPzogSVJvbGU7XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgR2x1ZSBkYXRhYmFzZSB0aGF0IHdpbGwgY29udGFpbiB0aGUgdGFibGVzIGNyZWF0ZWQgd2hlbiB0aGUgZmxvdyBleGVjdXRlc1xuICAgKi9cbiAgcmVhZG9ubHkgZGF0YWJhc2U6IElEYXRhYmFzZTtcblxuICAvKipcbiAgICogVGhlIHByZWZpeCBmb3IgdGhlIHRhYmxlcyBjcmVhdGVkIGluIHRoZSBBV1MgR2x1ZSBkYXRhYmFzZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVQcmVmaXg6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTM0Rlc3RpbmF0aW9uUHJvcHMge1xuICAvKipcbiAgICogVGhlIFMzIGxvY2F0aW9uIG9mIHRoZSBmaWxlcyB3aXRoIHRoZSByZXRyaWV2ZWQgZGF0YVxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb246IFMzTG9jYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgR2x1ZSBjYXRhbG9naW5nIG9wdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGNhdGFsb2c/OiBTM0NhdGFsb2c7XG5cbiAgLyoqXG4gICAqIFRoZSBmb3JtYXR0aW5nIG9wdGlvbnMgZm9yIHRoZSBvdXRwdXQgZmlsZXNcbiAgICovXG4gIHJlYWRvbmx5IGZvcm1hdHRpbmc/OiBTM091dHB1dEZvcm1hdHRpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTM0Rlc3RpbmF0aW9uIGltcGxlbWVudHMgSURlc3RpbmF0aW9uIHtcbiAgcHVibGljIHJlYWRvbmx5IGNvbm5lY3RvclR5cGU6IENvbm5lY3RvclR5cGUgPSBTM0Nvbm5lY3RvclR5cGUuaW5zdGFuY2U7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb21wYXRpYmxlRmxvd3M6IEZsb3dUeXBlW10gPSBbXG4gICAgRmxvd1R5cGUuT05fREVNQU5ELFxuICAgIEZsb3dUeXBlLlNDSEVEVUxFRCxcbiAgXTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBTM0Rlc3RpbmF0aW9uUHJvcHMpIHt9XG5cbiAgcHJpdmF0ZSBidWlsZEFnZ3JlZ2F0aW9uQ29uZmlnKGFnZ3JlZ2F0aW9uPzogUzNGaWxlQWdncmVnYXRpb24pIHtcbiAgICByZXR1cm4gKFxuICAgICAgYWdncmVnYXRpb24gJiYge1xuICAgICAgICBhZ2dyZWdhdGlvblR5cGU6IGFnZ3JlZ2F0aW9uLnR5cGUsXG4gICAgICAgIC8vIFRPRE86IG1ha2Ugc3VyZSBpdCBzaG91bGQgdXNlIG1lYmlieXRlc1xuICAgICAgICB0YXJnZXRGaWxlU2l6ZTogYWdncmVnYXRpb24uZmlsZVNpemUgJiYgYWdncmVnYXRpb24uZmlsZVNpemUsXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRQcmVmaXhDb25maWcoZmlsZVByZWZpeD86IFMzT3V0cHV0RmlsZVByZWZpeCkge1xuICAgIHJldHVybiAoXG4gICAgICBmaWxlUHJlZml4ICYmIHtcbiAgICAgICAgcGF0aFByZWZpeEhpZXJhcmNoeTogZmlsZVByZWZpeC5oaWVyYXJjaHksXG4gICAgICAgIHByZWZpeEZvcm1hdDogZmlsZVByZWZpeC5mb3JtYXQsXG4gICAgICAgIHByZWZpeFR5cGU6IGZpbGVQcmVmaXgudHlwZSxcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgYmluZChmbG93OiBJRmxvdyk6IENmbkZsb3cuRGVzdGluYXRpb25GbG93Q29uZmlnUHJvcGVydHkge1xuICAgIGlmICghdGhpcy5jb21wYXRpYmxlRmxvd3MuaW5jbHVkZXMoZmxvdy50eXBlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmxvdyBvZiB0eXBlICR7Zmxvdy50eXBlfSBkb2VzIG5vdCBzdXBwb3J0IFMzIGFzIGEgZGVzdGluYXRpb25gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLnRyeUFkZE5vZGVEZXBlbmRlbmN5KGZsb3csIHRoaXMucHJvcHMubG9jYXRpb24uYnVja2V0KTtcblxuICAgIEFwcEZsb3dQZXJtaXNzaW9uc01hbmFnZXIuaW5zdGFuY2UoKS5ncmFudEJ1Y2tldFdyaXRlKFxuICAgICAgdGhpcy5wcm9wcy5sb2NhdGlvbi5idWNrZXQsXG4gICAgKTtcblxuICAgIGlmICh0aGlzLnByb3BzLmNhdGFsb2cpIHtcbiAgICAgIGNvbnN0IHJvbGUgPVxuICAgICAgICB0aGlzLnByb3BzLmNhdGFsb2cucm9sZSA/P1xuICAgICAgICB0aGlzLmJ1aWxkUm9sZUFuZFBvbGljeUZvckNhdGFsb2coXG4gICAgICAgICAgZmxvdyxcbiAgICAgICAgICB0aGlzLnByb3BzLmNhdGFsb2cuZGF0YWJhc2UsXG4gICAgICAgICAgdGhpcy5wcm9wcy5jYXRhbG9nLnRhYmxlUHJlZml4LFxuICAgICAgICApO1xuXG4gICAgICB0aGlzLnRyeUFkZE5vZGVEZXBlbmRlbmN5KGZsb3csIHRoaXMucHJvcHMuY2F0YWxvZy5kYXRhYmFzZSk7XG4gICAgICB0aGlzLnRyeUFkZE5vZGVEZXBlbmRlbmN5KGZsb3csIHJvbGUpO1xuXG4gICAgICBmbG93Ll9hZGRDYXRhbG9nKHtcbiAgICAgICAgZ2x1ZURhdGFDYXRhbG9nOiB7XG4gICAgICAgICAgZGF0YWJhc2VOYW1lOiB0aGlzLnByb3BzLmNhdGFsb2cuZGF0YWJhc2UuZGF0YWJhc2VOYW1lLFxuICAgICAgICAgIHRhYmxlUHJlZml4OiB0aGlzLnByb3BzLmNhdGFsb2cudGFibGVQcmVmaXgsXG4gICAgICAgICAgcm9sZUFybjogcm9sZS5yb2xlQXJuLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbm5lY3RvclR5cGU6IHRoaXMuY29ubmVjdG9yVHlwZS5hc1Byb2ZpbGVDb25uZWN0b3JUeXBlLFxuICAgICAgZGVzdGluYXRpb25Db25uZWN0b3JQcm9wZXJ0aWVzOlxuICAgICAgICB0aGlzLmJ1aWxkRGVzdGluYXRpb25Db25uZWN0b3JQcm9wZXJ0aWVzKCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzZWU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93L2xhdGVzdC91c2VyZ3VpZGUvc2VjdXJpdHlfaWFtX2lkLWJhc2VkLXBvbGljeS1leGFtcGxlcy5odG1sI3NlY3VyaXR5X2lhbV9pZC1iYXNlZC1wb2xpY3ktZXhhbXBsZXMtYWNjZXNzLWdkY1xuICAgKiBzZWU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93L2xhdGVzdC91c2VyZ3VpZGUvc2VjdXJpdHlfaWFtX3NlcnZpY2Utcm9sZS1wb2xpY2llcy5odG1sI2FjY2Vzcy1nZGNcbiAgICogQHBhcmFtIGZsb3dcbiAgICogQHBhcmFtIGRhdGFiYXNlIC0gdGhlIEFXUyBHbHVlIGRhdGFiYXNlXG4gICAqIEBwYXJhbSB0YWJsZVByZWZpeCAtIHRoZSBwcmVmaXggZm9yIHRoZSB0YWJsZXMgdGhhdCB3aWxsIGJlIGNyZWF0ZWQgaW4gdGhlIEFXUyBHbHVlIGRhdGFiYXNlXG4gICAqIEByZXR1cm5zIGEgdHVwbGUgY29uc2lzdGluZyBvZiBhIHJvbGUgZm9yIGNhdGFsb2d1aW5nIHdpdGggYSBzcGVjaWZpZWQgcG9saWN5XG4gICAqL1xuICBwcml2YXRlIGJ1aWxkUm9sZUFuZFBvbGljeUZvckNhdGFsb2coXG4gICAgZmxvdzogSUZsb3csXG4gICAgZGF0YWJhc2U6IElEYXRhYmFzZSxcbiAgICB0YWJsZVByZWZpeDogc3RyaW5nLFxuICApIHtcbiAgICBjb25zdCByb2xlID0gbmV3IFJvbGUoZmxvdy5zdGFjaywgYCR7Zmxvdy5ub2RlLmlkfUdsdWVBY2Nlc3NSb2xlYCwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbChcImFwcGZsb3cuYW1hem9uYXdzLmNvbVwiKSxcbiAgICB9KTtcblxuICAgIC8vIHNlZTogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvbGF0ZXN0L3VzZXJndWlkZS9zZWN1cml0eV9pYW1faWQtYmFzZWQtcG9saWN5LWV4YW1wbGVzLmh0bWwjc2VjdXJpdHlfaWFtX2lkLWJhc2VkLXBvbGljeS1leGFtcGxlcy1hY2Nlc3MtZ2RjXG4gICAgcm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiZ2x1ZTpCYXRjaENyZWF0ZVBhcnRpdGlvblwiLFxuICAgICAgICAgIFwiZ2x1ZTpDcmVhdGVQYXJ0aXRpb25JbmRleFwiLFxuICAgICAgICAgIFwiZ2x1ZTpEZWxldGVEYXRhYmFzZVwiLFxuICAgICAgICAgIFwiZ2x1ZTpHZXRUYWJsZVZlcnNpb25zXCIsXG4gICAgICAgICAgXCJnbHVlOkdldFBhcnRpdGlvbnNcIixcbiAgICAgICAgICBcImdsdWU6QmF0Y2hEZWxldGVQYXJ0aXRpb25cIixcbiAgICAgICAgICBcImdsdWU6RGVsZXRlVGFibGVWZXJzaW9uXCIsXG4gICAgICAgICAgXCJnbHVlOlVwZGF0ZVRhYmxlXCIsXG4gICAgICAgICAgXCJnbHVlOkRlbGV0ZVRhYmxlXCIsXG4gICAgICAgICAgXCJnbHVlOkRlbGV0ZVBhcnRpdGlvbkluZGV4XCIsXG4gICAgICAgICAgXCJnbHVlOkdldFRhYmxlVmVyc2lvblwiLFxuICAgICAgICAgIFwiZ2x1ZTpDcmVhdGVQYXJ0aXRpb25cIixcbiAgICAgICAgICBcImdsdWU6VW50YWdSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiZ2x1ZTpVcGRhdGVQYXJ0aXRpb25cIixcbiAgICAgICAgICBcImdsdWU6VGFnUmVzb3VyY2VcIixcbiAgICAgICAgICBcImdsdWU6VXBkYXRlRGF0YWJhc2VcIixcbiAgICAgICAgICBcImdsdWU6Q3JlYXRlVGFibGVcIixcbiAgICAgICAgICBcImdsdWU6QmF0Y2hVcGRhdGVQYXJ0aXRpb25cIixcbiAgICAgICAgICBcImdsdWU6R2V0VGFibGVzXCIsXG4gICAgICAgICAgXCJnbHVlOkJhdGNoR2V0UGFydGl0aW9uXCIsXG4gICAgICAgICAgXCJnbHVlOkdldERhdGFiYXNlc1wiLFxuICAgICAgICAgIFwiZ2x1ZTpHZXRQYXJ0aXRpb25JbmRleGVzXCIsXG4gICAgICAgICAgXCJnbHVlOkdldFRhYmxlXCIsXG4gICAgICAgICAgXCJnbHVlOkdldERhdGFiYXNlXCIsXG4gICAgICAgICAgXCJnbHVlOkdldFBhcnRpdGlvblwiLFxuICAgICAgICAgIFwiZ2x1ZTpDcmVhdGVEYXRhYmFzZVwiLFxuICAgICAgICAgIFwiZ2x1ZTpCYXRjaERlbGV0ZVRhYmxlVmVyc2lvblwiLFxuICAgICAgICAgIFwiZ2x1ZTpCYXRjaERlbGV0ZVRhYmxlXCIsXG4gICAgICAgICAgXCJnbHVlOkRlbGV0ZVBhcnRpdGlvblwiLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICBkYXRhYmFzZS5jYXRhbG9nQXJuLFxuICAgICAgICAgIGRhdGFiYXNlLmRhdGFiYXNlQXJuLFxuICAgICAgICAgIFN0YWNrLm9mKGZsb3cpLmZvcm1hdEFybih7XG4gICAgICAgICAgICBzZXJ2aWNlOiBcImdsdWVcIixcbiAgICAgICAgICAgIHJlc291cmNlOiBcInRhYmxlXCIsXG4gICAgICAgICAgICByZXNvdXJjZU5hbWU6IGAke2RhdGFiYXNlLmRhdGFiYXNlTmFtZX0vJHt0YWJsZVByZWZpeH0qYCxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIHJvbGU7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkRGVzdGluYXRpb25Db25uZWN0b3JQcm9wZXJ0aWVzKCk6IENmbkZsb3cuRGVzdGluYXRpb25Db25uZWN0b3JQcm9wZXJ0aWVzUHJvcGVydHkge1xuICAgIGNvbnN0IGJ1Y2tldE5hbWUgPSB0aGlzLnByb3BzLmxvY2F0aW9uLmJ1Y2tldC5idWNrZXROYW1lO1xuXG4gICAgaWYgKCFidWNrZXROYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJidWNrZXROYW1lIGlzIHJlcXVpcmVkXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzMzoge1xuICAgICAgICBidWNrZXROYW1lOiBidWNrZXROYW1lLFxuICAgICAgICBidWNrZXRQcmVmaXg6IHRoaXMucHJvcHMubG9jYXRpb24ucHJlZml4LFxuICAgICAgICBzM091dHB1dEZvcm1hdENvbmZpZzogdGhpcy5wcm9wcy5mb3JtYXR0aW5nICYmIHtcbiAgICAgICAgICBhZ2dyZWdhdGlvbkNvbmZpZzogdGhpcy5idWlsZEFnZ3JlZ2F0aW9uQ29uZmlnKFxuICAgICAgICAgICAgdGhpcy5wcm9wcy5mb3JtYXR0aW5nLmFnZ3JlZ2F0aW9uLFxuICAgICAgICAgICksXG4gICAgICAgICAgZmlsZVR5cGU6IHRoaXMucHJvcHMuZm9ybWF0dGluZy5maWxlVHlwZSA/PyBTM091dHB1dEZpbGVUeXBlLkpTT04sXG4gICAgICAgICAgcHJlZml4Q29uZmlnOiB0aGlzLmJ1aWxkUHJlZml4Q29uZmlnKFxuICAgICAgICAgICAgdGhpcy5wcm9wcy5mb3JtYXR0aW5nLmZpbGVQcmVmaXgsXG4gICAgICAgICAgKSxcbiAgICAgICAgICBwcmVzZXJ2ZVNvdXJjZURhdGFUeXBpbmc6XG4gICAgICAgICAgICB0aGlzLnByb3BzLmZvcm1hdHRpbmcucHJlc2VydmVTb3VyY2VEYXRhVHlwZXMsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHRyeUFkZE5vZGVEZXBlbmRlbmN5KFxuICAgIHNjb3BlOiBJQ29uc3RydWN0LFxuICAgIHJlc291cmNlPzogSUNvbnN0cnVjdCB8IHN0cmluZyxcbiAgKSB7XG4gICAgaWYgKHJlc291cmNlICYmIHR5cGVvZiByZXNvdXJjZSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgc2NvcGUubm9kZS5hZGREZXBlbmRlbmN5KHJlc291cmNlKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==