UNPKG

@aws-cdk/aws-redshift-alpha

Version:

The CDK Construct Library for AWS::Redshift

185 lines 36.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = handler; const redshift_data_1 = require("./redshift-data"); const types_1 = require("./types"); const util_1 = require("./util"); async function handler(props, event) { const tableNamePrefix = props.tableName.prefix; const getTableNameSuffix = (generateSuffix) => generateSuffix === 'true' ? `${event.StackId.substring(event.StackId.length - 12)}` : ''; const tableColumns = props.tableColumns; const tableAndClusterProps = props; const useColumnIds = props.useColumnIds; let tableName = tableNamePrefix + getTableNameSuffix(props.tableName.generateSuffix); if (event.RequestType === 'Create') { tableName = await createTable(tableNamePrefix, getTableNameSuffix(props.tableName.generateSuffix), tableColumns, tableAndClusterProps); return { PhysicalResourceId: (0, util_1.makePhysicalId)(tableName, tableAndClusterProps, event.StackId.substring(event.StackId.length - 12)) }; } else if (event.RequestType === 'Delete') { await dropTable(event.PhysicalResourceId.includes(event.StackId.substring(event.StackId.length - 12)) ? tableName : event.PhysicalResourceId, tableAndClusterProps); return; } else if (event.RequestType === 'Update') { const isTableV2 = event.PhysicalResourceId.includes(event.StackId.substring(event.StackId.length - 12)); const oldTableName = event.OldResourceProperties.tableName.prefix + getTableNameSuffix(event.OldResourceProperties.tableName.generateSuffix); tableName = await updateTable(isTableV2 ? oldTableName : event.PhysicalResourceId, tableNamePrefix, getTableNameSuffix(props.tableName.generateSuffix), tableColumns, useColumnIds, tableAndClusterProps, event.OldResourceProperties, isTableV2); return { PhysicalResourceId: event.PhysicalResourceId }; } else { /* eslint-disable-next-line dot-notation */ throw new Error(`Unrecognized event type: ${event['RequestType']}`); } } async function createTable(tableNamePrefix, tableNameSuffix, tableColumns, tableAndClusterProps) { const tableName = tableNamePrefix + tableNameSuffix; const tableColumnsString = tableColumns.map(column => `${column.name} ${column.dataType}${getEncodingColumnString(column)}`).join(); let statement = `CREATE TABLE ${tableName} (${tableColumnsString})`; if (tableAndClusterProps.distStyle) { statement += ` DISTSTYLE ${tableAndClusterProps.distStyle}`; } const distKeyColumn = (0, util_1.getDistKeyColumn)(tableColumns); if (distKeyColumn) { statement += ` DISTKEY(${distKeyColumn.name})`; } const sortKeyColumns = (0, util_1.getSortKeyColumns)(tableColumns); if (sortKeyColumns.length > 0) { const sortKeyColumnsString = getSortKeyColumnsString(sortKeyColumns); statement += ` ${tableAndClusterProps.sortStyle} SORTKEY(${sortKeyColumnsString})`; } await (0, redshift_data_1.executeStatement)(statement, tableAndClusterProps); for (const column of tableColumns) { if (column.comment) { await (0, redshift_data_1.executeStatement)(`COMMENT ON COLUMN ${tableName}.${column.name} IS '${column.comment}'`, tableAndClusterProps); } } if (tableAndClusterProps.tableComment) { await (0, redshift_data_1.executeStatement)(`COMMENT ON TABLE ${tableName} IS '${tableAndClusterProps.tableComment}'`, tableAndClusterProps); } return tableName; } async function dropTable(tableName, clusterProps) { await (0, redshift_data_1.executeStatement)(`DROP TABLE ${tableName}`, clusterProps); } async function updateTable(tableName, tableNamePrefix, tableNameSuffix, tableColumns, useColumnIds, tableAndClusterProps, oldResourceProperties, isTableV2) { const alterationStatements = []; const newTableName = tableNamePrefix + tableNameSuffix; const oldClusterProps = oldResourceProperties; if (tableAndClusterProps.clusterName !== oldClusterProps.clusterName || tableAndClusterProps.databaseName !== oldClusterProps.databaseName) { return createTable(tableNamePrefix, tableNameSuffix, tableColumns, tableAndClusterProps); } const oldTableColumns = oldResourceProperties.tableColumns; const columnDeletions = oldTableColumns.filter(oldColumn => (tableColumns.every(column => { if (useColumnIds) { return oldColumn.id ? oldColumn.id !== column.id : oldColumn.name !== column.name; } return oldColumn.name !== column.name; }))); if (columnDeletions.length > 0) { alterationStatements.push(...columnDeletions.map(column => `ALTER TABLE ${tableName} DROP COLUMN ${column.name}`)); } const columnAdditions = tableColumns.filter(column => { return !oldTableColumns.some(oldColumn => { if (useColumnIds) { return oldColumn.id ? oldColumn.id === column.id : oldColumn.name === column.name; } return oldColumn.name === column.name; }); }).map(column => `ADD ${column.name} ${column.dataType}`); if (columnAdditions.length > 0) { alterationStatements.push(...columnAdditions.map(addition => `ALTER TABLE ${tableName} ${addition}`)); } const columnEncoding = tableColumns.filter(column => { return oldTableColumns.some(oldColumn => column.name === oldColumn.name && column.encoding !== oldColumn.encoding); }).map(column => `ALTER COLUMN ${column.name} ENCODE ${column.encoding || 'AUTO'}`); if (columnEncoding.length > 0) { alterationStatements.push(`ALTER TABLE ${tableName} ${columnEncoding.join(', ')}`); } const columnComments = tableColumns.filter(column => { return oldTableColumns.some(oldColumn => column.name === oldColumn.name && column.comment !== oldColumn.comment); }).map(column => `COMMENT ON COLUMN ${tableName}.${column.name} IS ${column.comment ? `'${column.comment}'` : 'NULL'}`); if (columnComments.length > 0) { alterationStatements.push(...columnComments); } if (useColumnIds) { const columnNameUpdates = tableColumns.reduce((updates, column) => { const oldColumn = oldTableColumns.find(oldCol => oldCol.id && oldCol.id === column.id); if (oldColumn && oldColumn.name !== column.name) { updates[oldColumn.name] = column.name; } return updates; }, {}); if (Object.keys(columnNameUpdates).length > 0) { alterationStatements.push(...Object.entries(columnNameUpdates).map(([oldName, newName]) => (`ALTER TABLE ${tableName} RENAME COLUMN ${oldName} TO ${newName}`))); } } const oldDistStyle = oldResourceProperties.distStyle; if ((!oldDistStyle && tableAndClusterProps.distStyle) || (oldDistStyle && !tableAndClusterProps.distStyle)) { return createTable(tableNamePrefix, tableNameSuffix, tableColumns, tableAndClusterProps); } else if (oldDistStyle !== tableAndClusterProps.distStyle) { alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTSTYLE ${tableAndClusterProps.distStyle}`); } const oldDistKey = (0, util_1.getDistKeyColumn)(oldTableColumns)?.name; const newDistKey = (0, util_1.getDistKeyColumn)(tableColumns)?.name; if (!oldDistKey && newDistKey) { // Table has no existing distribution key, add a new one alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTSTYLE KEY DISTKEY ${newDistKey}`); } else if (oldDistKey && !newDistKey) { // Table has a distribution key, remove and set to AUTO alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTSTYLE AUTO`); } else if (oldDistKey !== newDistKey) { // Table has an existing distribution key, change it alterationStatements.push(`ALTER TABLE ${tableName} ALTER DISTKEY ${newDistKey}`); } const oldSortKeyColumns = (0, util_1.getSortKeyColumns)(oldTableColumns); const newSortKeyColumns = (0, util_1.getSortKeyColumns)(tableColumns); const oldSortStyle = oldResourceProperties.sortStyle; const newSortStyle = tableAndClusterProps.sortStyle; if ((oldSortStyle === newSortStyle && !(0, util_1.areColumnsEqual)(oldSortKeyColumns, newSortKeyColumns)) || (oldSortStyle !== newSortStyle)) { switch (newSortStyle) { case types_1.TableSortStyle.INTERLEAVED: // INTERLEAVED sort key addition requires replacement. // https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE.html return createTable(tableNamePrefix, tableNameSuffix, tableColumns, tableAndClusterProps); case types_1.TableSortStyle.COMPOUND: { const sortKeyColumnsString = getSortKeyColumnsString(newSortKeyColumns); alterationStatements.push(`ALTER TABLE ${tableName} ALTER ${newSortStyle} SORTKEY(${sortKeyColumnsString})`); break; } case types_1.TableSortStyle.AUTO: { alterationStatements.push(`ALTER TABLE ${tableName} ALTER SORTKEY ${newSortStyle}`); break; } } } const oldComment = oldResourceProperties.tableComment; const newComment = tableAndClusterProps.tableComment; if (oldComment !== newComment) { alterationStatements.push(`COMMENT ON TABLE ${tableName} IS ${newComment ? `'${newComment}'` : 'NULL'}`); } // Limited by human input // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism await Promise.all(alterationStatements.map(statement => (0, redshift_data_1.executeStatement)(statement, tableAndClusterProps))); if (isTableV2) { const oldTableNamePrefix = oldResourceProperties.tableName.prefix; if (tableNamePrefix !== oldTableNamePrefix) { await (0, redshift_data_1.executeStatement)(`ALTER TABLE ${tableName} RENAME TO ${newTableName}`, tableAndClusterProps); return tableNamePrefix + tableNameSuffix; } } return tableName; } function getSortKeyColumnsString(sortKeyColumns) { return sortKeyColumns.map(column => column.name).join(); } function getEncodingColumnString(column) { if (column.encoding) { return ` ENCODE ${column.encoding}`; } return ''; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0YWJsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU9BLDBCQW1DQztBQXhDRCxtREFBbUQ7QUFDbkQsbUNBQTZFO0FBQzdFLGlDQUE4RjtBQUd2RixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQTJCLEVBQUUsS0FBa0Q7SUFDM0csTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7SUFDL0MsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLGNBQXNCLEVBQUUsRUFBRSxDQUFDLGNBQWMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2hKLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUM7SUFDeEMsTUFBTSxvQkFBb0IsR0FBRyxLQUFLLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQztJQUN4QyxJQUFJLFNBQVMsR0FBRyxlQUFlLEdBQUcsa0JBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUVyRixJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDbkMsU0FBUyxHQUFHLE1BQU0sV0FBVyxDQUFDLGVBQWUsRUFBRSxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxFQUFFLFlBQVksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3ZJLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxJQUFBLHFCQUFjLEVBQUMsU0FBUyxFQUFFLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxH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QUNwQixPQUFPLFdBQVcsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3RDLENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLXVucmVzb2x2ZWQgKi9cbmltcG9ydCAqIGFzIEFXU0xhbWJkYSBmcm9tICdhd3MtbGFtYmRhJztcbmltcG9ydCB7IGV4ZWN1dGVTdGF0ZW1lbnQgfSBmcm9tICcuL3JlZHNoaWZ0LWRhdGEnO1xuaW1wb3J0IHsgQ2x1c3RlclByb3BzLCBUYWJsZUFuZENsdXN0ZXJQcm9wcywgVGFibGVTb3J0U3R5bGUgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGFyZUNvbHVtbnNFcXVhbCwgZ2V0RGlzdEtleUNvbHVtbiwgZ2V0U29ydEtleUNvbHVtbnMsIG1ha2VQaHlzaWNhbElkIH0gZnJvbSAnLi91dGlsJztcbmltcG9ydCB7IENvbHVtbiB9IGZyb20gJy4uLy4uL3RhYmxlJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIocHJvcHM6IFRhYmxlQW5kQ2x1c3RlclByb3BzLCBldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCkge1xuICBjb25zdCB0YWJsZU5hbWVQcmVmaXggPSBwcm9wcy50YWJsZU5hbWUucHJlZml4O1xuICBjb25zdCBnZXRUYWJsZU5hbWVTdWZmaXggPSAoZ2VuZXJhdGVTdWZmaXg6IHN0cmluZykgPT4gZ2VuZXJhdGVTdWZmaXggPT09ICd0cnVlJyA/IGAke2V2ZW50LlN0YWNrSWQuc3Vic3RyaW5nKGV2ZW50LlN0YWNrSWQubGVuZ3RoIC0gMTIpfWAgOiAnJztcbiAgY29uc3QgdGFibGVDb2x1bW5zID0gcHJvcHMudGFibGVDb2x1bW5zO1xuICBjb25zdCB0YWJsZUFuZENsdXN0ZXJQcm9wcyA9IHByb3BzO1xuICBjb25zdCB1c2VDb2x1bW5JZHMgPSBwcm9wcy51c2VDb2x1bW5JZHM7XG4gIGxldCB0YWJsZU5hbWUgPSB0YWJsZU5hbWVQcmVmaXggKyBnZXRUYWJsZU5hbWVTdWZmaXgocHJvcHMudGFibGVOYW1lLmdlbmVyYXRlU3VmZml4KTtcblxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdDcmVhdGUnKSB7XG4gICAgdGFibGVOYW1lID0gYXdhaXQgY3JlYXRlVGFibGUodGFibGVOYW1lUHJlZml4LCBnZXRUYWJsZU5hbWVTdWZmaXgocHJvcHMudGFibGVOYW1lLmdlbmVyYXRlU3VmZml4KSwgdGFibGVDb2x1bW5zLCB0YWJsZUFuZENsdXN0ZXJQcm9wcyk7XG4gICAgcmV0dXJuIHsgUGh5c2ljYWxSZXNvdXJjZUlkOiBtYWtlUGh5c2ljYWxJZCh0YWJsZU5hbWUsIHRhYmxlQW5kQ2x1c3RlclByb3BzLCBldmVudC5TdGFja0lkLnN1YnN0cmluZyhldmVudC5TdGFja0lkLmxlbmd0aCAtIDEyKSkgfTtcbiAgfSBlbHNlIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScpIHtcbiAgICBhd2FpdCBkcm9wVGFibGUoXG4gICAgICBldmVudC5QaHlzaWNhbFJlc291cmNlSWQuaW5jbHVkZXMoZXZlbnQuU3RhY2tJZC5zdWJzdHJpbmcoZXZlbnQuU3RhY2tJZC5sZW5ndGggLSAxMikpID8gdGFibGVOYW1lIDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgICAgdGFibGVBbmRDbHVzdGVyUHJvcHMsXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH0gZWxzZSBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnKSB7XG4gICAgY29uc3QgaXNUYWJsZVYyID0gZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkLmluY2x1ZGVzKGV2ZW50LlN0YWNrSWQuc3Vic3RyaW5nKGV2ZW50LlN0YWNrSWQubGVuZ3RoIC0gMTIpKTtcbiAgICBjb25zdCBvbGRUYWJsZU5hbWUgPSBldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMudGFibGVOYW1lLnByZWZpeCArIGdldFRhYmxlTmFtZVN1ZmZpeChldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMudGFibGVOYW1lLmdlbmVyYXRlU3VmZml4KTtcbiAgICB0YWJsZU5hbWUgPSBhd2FpdCB1cGRhdGVUYWJsZShcbiAgICAgIGlzVGFibGVWMiA/IG9sZFRhYmxlTmFtZSA6IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCxcbiAgICAgIHRhYmxlTmFtZVByZWZpeCxcbiAgICAgIGdldFRhYmxlTmFtZVN1ZmZpeChwcm9wcy50YWJsZU5hbWUuZ2VuZXJhdGVTdWZmaXgpLFxuICAgICAgdGFibGVDb2x1bW5zLFxuICAgICAgdXNlQ29sdW1uSWRzLFxuICAgICAgdGFibGVBbmRDbHVzdGVyUHJvcHMsXG4gICAgICBldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMgYXMgdW5rbm93biBhcyBUYWJsZUFuZENsdXN0ZXJQcm9wcyxcbiAgICAgIGlzVGFibGVWMixcbiAgICApO1xuICAgIHJldHVybiB7IFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkIH07XG4gIH0gZWxzZSB7XG4gICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRvdC1ub3RhdGlvbiAqL1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5yZWNvZ25pemVkIGV2ZW50IHR5cGU6ICR7ZXZlbnRbJ1JlcXVlc3RUeXBlJ119YCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlVGFibGUoXG4gIHRhYmxlTmFtZVByZWZpeDogc3RyaW5nLFxuICB0YWJsZU5hbWVTdWZmaXg6IHN0cmluZyxcbiAgdGFibGVDb2x1bW5zOiBDb2x1bW5bXSxcbiAgdGFibGVBbmRDbHVzdGVyUHJvcHM6IFRhYmxlQW5kQ2x1c3RlclByb3BzLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgdGFibGVOYW1lID0gdGFibGVOYW1lUHJlZml4ICsgdGFibGVOYW1lU3VmZml4O1xuICBjb25zdCB0YWJsZUNvbHVtbnNTdHJpbmcgPSB0YWJsZUNvbHVtbnMubWFwKGNvbHVtbiA9PiBgJHtjb2x1bW4ubmFtZX0gJHtjb2x1bW4uZGF0YVR5cGV9JHtnZXRFbmNvZGluZ0NvbHVtblN0cmluZyhjb2x1bW4pfWApLmpvaW4oKTtcblxuICBsZXQgc3RhdGVtZW50ID0gYENSRUFURSBUQUJMRSAke3RhYmxlTmFtZX0gKCR7dGFibGVDb2x1bW5zU3RyaW5nfSlgO1xuXG4gIGlmICh0YWJsZUFuZENsdXN0ZXJQcm9wcy5kaXN0U3R5bGUpIHtcbiAgICBzdGF0ZW1lbnQgKz0gYCBESVNUU1RZTEUgJHt0YWJsZUFuZENsdXN0ZXJQcm9wcy5kaXN0U3R5bGV9YDtcbiAgfVxuXG4gIGNvbnN0IGRpc3RLZXlDb2x1bW4gPSBnZXREaXN0S2V5Q29sdW1uKHRhYmxlQ29sdW1ucyk7XG4gIGlmIChkaXN0S2V5Q29sdW1uKSB7XG4gICAgc3RhdGVtZW50ICs9IGAgRElTVEtFWSgke2Rpc3RLZXlDb2x1bW4ubmFtZX0pYDtcbiAgfVxuXG4gIGNvbnN0IHNvcnRLZXlDb2x1bW5zID0gZ2V0U29ydEtleUNvbHVtbnModGFibGVDb2x1bW5zKTtcbiAgaWYgKHNvcnRLZXlDb2x1bW5zLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBzb3J0S2V5Q29sdW1uc1N0cmluZyA9IGdldFNvcnRLZXlDb2x1bW5zU3RyaW5nKHNvcnRLZXlDb2x1bW5zKTtcbiAgICBzdGF0ZW1lbnQgKz0gYCAke3RhYmxlQW5kQ2x1c3RlclByb3BzLnNvcnRTdHlsZX0gU09SVEtFWSgke3NvcnRLZXlDb2x1bW5zU3RyaW5nfSlgO1xuICB9XG5cbiAgYXdhaXQgZXhlY3V0ZVN0YXRlbWVudChzdGF0ZW1lbnQsIHRhYmxlQW5kQ2x1c3RlclByb3BzKTtcblxuICBmb3IgKGNvbnN0IGNvbHVtbiBvZiB0YWJsZUNvbHVtbnMpIHtcbiAgICBpZiAoY29sdW1uLmNvbW1lbnQpIHtcbiAgICAgIGF3YWl0IGV4ZWN1dGVTdGF0ZW1lbnQoYENPTU1FTlQgT04gQ09MVU1OICR7dGFibGVOYW1lfS4ke2NvbHVtbi5uYW1lfSBJUyAnJHtjb2x1bW4uY29tbWVudH0nYCwgdGFibGVBbmRDbHVzdGVyUHJvcHMpO1xuICAgIH1cbiAgfVxuICBpZiAodGFibGVBbmRDbHVzdGVyUHJvcHMudGFibGVDb21tZW50KSB7XG4gICAgYXdhaXQgZXhlY3V0ZVN0YXRlbWVudChgQ09NTUVOVCBPTiBUQUJMRSAke3RhYmxlTmFtZX0gSVMgJyR7dGFibGVBbmRDbHVzdGVyUHJvcHMudGFibGVDb21tZW50fSdgLCB0YWJsZUFuZENsdXN0ZXJQcm9wcyk7XG4gIH1cblxuICByZXR1cm4gdGFibGVOYW1lO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkcm9wVGFibGUodGFibGVOYW1lOiBzdHJpbmcsIGNsdXN0ZXJQcm9wczogQ2x1c3RlclByb3BzKSB7XG4gIGF3YWl0IGV4ZWN1dGVTdGF0ZW1lbnQoYERST1AgVEFCTEUgJHt0YWJsZU5hbWV9YCwgY2x1c3RlclByb3BzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlVGFibGUoXG4gIHRhYmxlTmFtZTogc3RyaW5nLFxuICB0YWJsZU5hbWVQcmVmaXg6IHN0cmluZyxcbiAgdGFibGVOYW1lU3VmZml4OiBzdHJpbmcsXG4gIHRhYmxlQ29sdW1uczogQ29sdW1uW10sXG4gIHVzZUNvbHVtbklkczogYm9vbGVhbixcbiAgdGFibGVBbmRDbHVzdGVyUHJvcHM6IFRhYmxlQW5kQ2x1c3RlclByb3BzLFxuICBvbGRSZXNvdXJjZVByb3BlcnRpZXM6IFRhYmxlQW5kQ2x1c3RlclByb3BzLFxuICBpc1RhYmxlVjI6IGJvb2xlYW4sXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBhbHRlcmF0aW9uU3RhdGVtZW50czogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgbmV3VGFibGVOYW1lID0gdGFibGVOYW1lUHJlZml4ICsgdGFibGVOYW1lU3VmZml4O1xuXG4gIGNvbnN0IG9sZENsdXN0ZXJQcm9wcyA9IG9sZFJlc291cmNlUHJvcGVydGllcztcbiAgaWYgKHRhYmxlQW5kQ2x1c3RlclByb3BzLmNsdXN0ZXJOYW1lICE9PSBvbGRDbHVzdGVyUHJvcHMuY2x1c3Rlck5hbWUgfHwgdGFibGVBbmRDbHVzdGVyUHJvcHMuZGF0YWJhc2VOYW1lICE9PSBvbGRDbHVzdGVyUHJvcHMuZGF0YWJhc2VOYW1lKSB7XG4gICAgcmV0dXJuIGNyZWF0ZVRhYmxlKHRhYmxlTmFtZVByZWZpeCwgdGFibGVOYW1lU3VmZml4LCB0YWJsZUNvbHVtbnMsIHRhYmxlQW5kQ2x1c3RlclByb3BzKTtcbiAgfVxuXG4gIGNvbnN0IG9sZFRhYmxlQ29sdW1ucyA9IG9sZFJlc291cmNlUHJvcGVydGllcy50YWJsZUNvbHVtbnM7XG4gIGNvbnN0IGNvbHVtbkRlbGV0aW9ucyA9IG9sZFRhYmxlQ29sdW1ucy5maWx0ZXIob2xkQ29sdW1uID0+IChcbiAgICB0YWJsZUNvbHVtbnMuZXZlcnkoY29sdW1uID0+IHtcbiAgICAgIGlmICh1c2VDb2x1bW5JZHMpIHtcbiAgICAgICAgcmV0dXJuIG9sZENvbHVtbi5pZCA/IG9sZENvbHVtbi5pZCAhPT0gY29sdW1uLmlkIDogb2xkQ29sdW1uLm5hbWUgIT09IGNvbHVtbi5uYW1lO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9sZENvbHVtbi5uYW1lICE9PSBjb2x1bW4ubmFtZTtcbiAgICB9KVxuICApKTtcbiAgaWYgKGNvbHVtbkRlbGV0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgYWx0ZXJhdGlvblN0YXRlbWVudHMucHVzaCguLi5jb2x1bW5EZWxldGlvbnMubWFwKGNvbHVtbiA9PiBgQUxURVIgVEFCTEUgJHt0YWJsZU5hbWV9IERST1AgQ09MVU1OICR7Y29sdW1uLm5hbWV9YCkpO1xuICB9XG5cbiAgY29uc3QgY29sdW1uQWRkaXRpb25zID0gdGFibGVDb2x1bW5zLmZpbHRlcihjb2x1bW4gPT4ge1xuICAgIHJldHVybiAhb2xkVGFibGVDb2x1bW5zLnNvbWUob2xkQ29sdW1uID0+IHtcbiAgICAgIGlmICh1c2VDb2x1bW5JZHMpIHtcbiAgICAgICAgcmV0dXJuIG9sZENvbHVtbi5pZCA/IG9sZENvbHVtbi5pZCA9PT0gY29sdW1uLmlkIDogb2xkQ29sdW1uLm5hbWUgPT09IGNvbHVtbi5uYW1lO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9sZENvbHVtbi5uYW1lID09PSBjb2x1bW4ubmFtZTtcbiAgICB9KTtcbiAgfSkubWFwKGNvbHVtbiA9PiBgQUREICR7Y29sdW1uLm5hbWV9ICR7Y29sdW1uLmRhdGFUeXBlfWApO1xuICBpZiAoY29sdW1uQWRkaXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICBhbHRlcmF0aW9uU3RhdGVtZW50cy5wdXNoKC4uLmNvbHVtbkFkZGl0aW9ucy5tYXAoYWRkaXRpb24gPT4gYEFMVEVSIFRBQkxFICR7dGFibGVOYW1lfSAke2FkZGl0aW9ufWApKTtcbiAgfVxuXG4gIGNvbnN0IGNvbHVtbkVuY29kaW5nID0gdGFibGVDb2x1bW5zLmZpbHRlcihjb2x1bW4gPT4ge1xuICAgIHJldHVybiBvbGRUYWJsZUNvbHVtbnMuc29tZShvbGRDb2x1bW4gPT4gY29sdW1uLm5hbWUgPT09IG9sZENvbHVtbi5uYW1lICYmIGNvbHVtbi5lbmNvZGluZyAhPT0gb2xkQ29sdW1uLmVuY29kaW5nKTtcbiAgfSkubWFwKGNvbHVtbiA9PiBgQUxURVIgQ09MVU1OICR7Y29sdW1uLm5hbWV9IEVOQ09ERSAke2NvbHVtbi5lbmNvZGluZyB8fCAnQVVUTyd9YCk7XG4gIGlmIChjb2x1bW5FbmNvZGluZy5sZW5ndGggPiAwKSB7XG4gICAgYWx0ZXJhdGlvblN0YXRlbWVudHMucHVzaChgQUxURVIgVEFCTEUgJHt0YWJsZU5hbWV9ICR7Y29sdW1uRW5jb2Rpbmcuam9pbignLCAnKX1gKTtcbiAgfVxuXG4gIGNvbnN0IGNvbHVtbkNvbW1lbnRzID0gdGFibGVDb2x1bW5zLmZpbHRlcihjb2x1bW4gPT4ge1xuICAgIHJldHVybiBvbGRUYWJsZUNvbHVtbnMuc29tZShvbGRDb2x1bW4gPT4gY29sdW1uLm5hbWUgPT09IG9sZENvbHVtbi5uYW1lICYmIGNvbHVtbi5jb21tZW50ICE9PSBvbGRDb2x1bW4uY29tbWVudCk7XG4gIH0pLm1hcChjb2x1bW4gPT4gYENPTU1FTlQgT04gQ09MVU1OICR7dGFibGVOYW1lfS4ke2NvbHVtbi5uYW1lfSBJUyAke2NvbHVtbi5jb21tZW50ID8gYCcke2NvbHVtbi5jb21tZW50fSdgIDogJ05VTEwnfWApO1xuICBpZiAoY29sdW1uQ29tbWVudHMubGVuZ3RoID4gMCkge1xuICAgIGFsdGVyYXRpb25TdGF0ZW1lbnRzLnB1c2goLi4uY29sdW1uQ29tbWVudHMpO1xuICB9XG5cbiAgaWYgKHVzZUNvbHVtbklkcykge1xuICAgIGNvbnN0IGNvbHVtbk5hbWVVcGRhdGVzID0gdGFibGVDb2x1bW5zLnJlZHVjZSgodXBkYXRlcywgY29sdW1uKSA9PiB7XG4gICAgICBjb25zdCBvbGRDb2x1bW4gPSBvbGRUYWJsZUNvbHVtbnMuZmluZChvbGRDb2wgPT4gb2xkQ29sLmlkICYmIG9sZENvbC5pZCA9PT0gY29sdW1uLmlkKTtcbiAgICAgIGlmIChvbGRDb2x1bW4gJiYgb2xkQ29sdW1uLm5hbWUgIT09IGNvbHVtbi5uYW1lKSB7XG4gICAgICAgIHVwZGF0ZXNbb2xkQ29sdW1uLm5hbWVdID0gY29sdW1uLm5hbWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gdXBkYXRlcztcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTtcbiAgICBpZiAoT2JqZWN0LmtleXMoY29sdW1uTmFtZVVwZGF0ZXMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGFsdGVyYXRpb25TdGF0ZW1lbnRzLnB1c2goLi4uT2JqZWN0LmVudHJpZXMoY29sdW1uTmFtZVVwZGF0ZXMpLm1hcCgoW29sZE5hbWUsIG5ld05hbWVdKSA9PiAoXG4gICAgICAgIGBBTFRFUiBUQUJMRSAke3RhYmxlTmFtZX0gUkVOQU1FIENPTFVNTiAke29sZE5hbWV9IFRPICR7bmV3TmFtZX1gXG4gICAgICApKSk7XG4gICAgfVxuICB9XG5cbiAgY29uc3Qgb2xkRGlzdFN0eWxlID0gb2xkUmVzb3VyY2VQcm9wZXJ0aWVzLmRpc3RTdHlsZTtcbiAgaWYgKCghb2xkRGlzdFN0eWxlICYmIHRhYmxlQW5kQ2x1c3RlclByb3BzLmRpc3RTdHlsZSkgfHxcbiAgICAob2xkRGlzdFN0eWxlICYmICF0YWJsZUFuZENsdXN0ZXJQcm9wcy5kaXN0U3R5bGUpKSB7XG4gICAgcmV0dXJuIGNyZWF0ZVRhYmxlKHRhYmxlTmFtZVByZWZpeCwgdGFibGVOYW1lU3VmZml4LCB0YWJsZUNvbHVtbnMsIHRhYmxlQW5kQ2x1c3RlclByb3BzKTtcbiAgfSBlbHNlIGlmIChvbGREaXN0U3R5bGUgIT09IHRhYmxlQW5kQ2x1c3RlclByb3BzLmRpc3RTdHlsZSkge1xuICAgIGFsdGVyYXRpb25TdGF0ZW1lbnRzLnB1c2goYEFMVEVSIFRBQkxFICR7dGFibGVOYW1lfSBBTFRFUiBESVNUU1RZTEUgJHt0YWJsZUFuZENsdXN0ZXJQcm9wcy5kaXN0U3R5bGV9YCk7XG4gIH1cblxuICBjb25zdCBvbGREaXN0S2V5ID0gZ2V0RGlzdEtleUNvbHVtbihvbGRUYWJsZUNvbHVtbnMpPy5uYW1lO1xuICBjb25zdCBuZXdEaXN0S2V5ID0gZ2V0RGlzdEtleUNvbHVtbih0YWJsZUNvbHVtbnMpPy5uYW1lO1xuICBpZiAoIW9sZERpc3RLZXkgJiYgbmV3RGlzdEtleSkge1xuICAgIC8vIFRhYmxlIGhhcyBubyBleGlzdGluZyBkaXN0cmlidXRpb24ga2V5LCBhZGQgYSBuZXcgb25lXG4gICAgYWx0ZXJhdGlvblN0YXRlbWVudHMucHVzaChgQUxURVIgVEFCTEUgJHt0YWJsZU5hbWV9IEFMVEVSIERJU1RTVFlMRSBLRVkgRElTVEtFWSAke25ld0Rpc3RLZXl9YCk7XG4gIH0gZWxzZSBpZiAob2xkRGlzdEtleSAmJiAhbmV3RGlzdEtleSkge1xuICAgIC8vIFRhYmxlIGhhcyBhIGRpc3RyaWJ1dGlvbiBrZXksIHJlbW92ZSBhbmQgc2V0IHRvIEFVVE9cbiAgICBhbHRlcmF0aW9uU3RhdGVtZW50cy5wdXNoKGBBTFRFUiBUQUJMRSAke3RhYmxlTmFtZX0gQUxURVIgRElTVFNUWUxFIEFVVE9gKTtcbiAgfSBlbHNlIGlmIChvbGREaXN0S2V5ICE9PSBuZXdEaXN0S2V5KSB7XG4gICAgLy8gVGFibGUgaGFzIGFuIGV4aXN0aW5nIGRpc3RyaWJ1dGlvbiBrZXksIGNoYW5nZSBpdFxuICAgIGFsdGVyYXRpb25TdGF0ZW1lbnRzLnB1c2goYEFMVEVSIFRBQkxFICR7dGFibGVOYW1lfSBBTFRFUiBESVNUS0VZICR7bmV3RGlzdEtleX1gKTtcbiAgfVxuXG4gIGNvbnN0IG9sZFNvcnRLZXlDb2x1bW5zID0gZ2V0U29ydEtleUNvbHVtbnMob2xkVGFibGVDb2x1bW5zKTtcbiAgY29uc3QgbmV3U29ydEtleUNvbHVtbnMgPSBnZXRTb3J0S2V5Q29sdW1ucyh0YWJsZUNvbHVtbnMpO1xuICBjb25zdCBvbGRTb3J0U3R5bGUgPSBvbGRSZXNvdXJjZVByb3BlcnRpZXMuc29ydFN0eWxlO1xuICBjb25zdCBuZXdTb3J0U3R5bGUgPSB0YWJsZUFuZENsdXN0ZXJQcm9wcy5zb3J0U3R5bGU7XG4gIGlmICgob2xkU29ydFN0eWxlID09PSBuZXdTb3J0U3R5bGUgJiYgIWFyZUNvbHVtbnNFcXVhbChvbGRTb3J0S2V5Q29sdW1ucywgbmV3U29ydEtleUNvbHVtbnMpKVxuICAgIHx8IChvbGRTb3J0U3R5bGUgIT09IG5ld1NvcnRTdHlsZSkpIHtcbiAgICBzd2l0Y2ggKG5ld1NvcnRTdHlsZSkge1xuICAgICAgY2FzZSBUYWJsZVNvcnRTdHlsZS5JTlRFUkxFQVZFRDpcbiAgICAgICAgLy8gSU5URVJMRUFWRUQgc29ydCBrZXkgYWRkaXRpb24gcmVxdWlyZXMgcmVwbGFjZW1lbnQuXG4gICAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9yZWRzaGlmdC9sYXRlc3QvZGcvcl9BTFRFUl9UQUJMRS5odG1sXG4gICAgICAgIHJldHVybiBjcmVhdGVUYWJsZSh0YWJsZU5hbWVQcmVmaXgsIHRhYmxlTmFtZVN1ZmZpeCwgdGFibGVDb2x1bW5zLCB0YWJsZUFuZENsdXN0ZXJQcm9wcyk7XG5cbiAgICAgIGNhc2UgVGFibGVTb3J0U3R5bGUuQ09NUE9VTkQ6IHtcbiAgICAgICAgY29uc3Qgc29ydEtleUNvbHVtbnNTdHJpbmcgPSBnZXRTb3J0S2V5Q29sdW1uc1N0cmluZyhuZXdTb3J0S2V5Q29sdW1ucyk7XG4gICAgICAgIGFsdGVyYXRpb25TdGF0ZW1lbnRzLnB1c2goYEFMVEVSIFRBQkxFICR7dGFibGVOYW1lfSBBTFRFUiAke25ld1NvcnRTdHlsZX0gU09SVEtFWSgke3NvcnRLZXlDb2x1bW5zU3RyaW5nfSlgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNhc2UgVGFibGVTb3J0U3R5bGUuQVVUTzoge1xuICAgICAgICBhbHRlcmF0aW9uU3RhdGVtZW50cy5wdXNoKGBBTFRFUiBUQUJMRSAke3RhYmxlTmFtZX0gQUxURVIgU09SVEtFWSAke25ld1NvcnRTdHlsZX1gKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3Qgb2xkQ29tbWVudCA9IG9sZFJlc291cmNlUHJvcGVydGllcy50YWJsZUNvbW1lbnQ7XG4gIGNvbnN0IG5ld0NvbW1lbnQgPSB0YWJsZUFuZENsdXN0ZXJQcm9wcy50YWJsZUNvbW1lbnQ7XG4gIGlmIChvbGRDb21tZW50ICE9PSBuZXdDb21tZW50KSB7XG4gICAgYWx0ZXJhdGlvblN0YXRlbWVudHMucHVzaChgQ09NTUVOVCBPTiBUQUJMRSAke3RhYmxlTmFtZX0gSVMgJHtuZXdDb21tZW50ID8gYCcke25ld0NvbW1lbnR9J2AgOiAnTlVMTCd9YCk7XG4gIH1cblxuICAvLyBMaW1pdGVkIGJ5IGh1bWFuIGlucHV0XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAY2RrbGFicy9wcm9taXNlYWxsLW5vLXVuYm91bmRlZC1wYXJhbGxlbGlzbVxuICBhd2FpdCBQcm9taXNlLmFsbChhbHRlcmF0aW9uU3RhdGVtZW50cy5tYXAoc3RhdGVtZW50ID0+IGV4ZWN1dGVTdGF0ZW1lbnQoc3RhdGVtZW50LCB0YWJsZUFuZENsdXN0ZXJQcm9wcykpKTtcblxuICBpZiAoaXNUYWJsZVYyKSB7XG4gICAgY29uc3Qgb2xkVGFibGVOYW1lUHJlZml4ID0gb2xkUmVzb3VyY2VQcm9wZXJ0aWVzLnRhYmxlTmFtZS5wcmVmaXg7XG4gICAgaWYgKHRhYmxlTmFtZVByZWZpeCAhPT0gb2xkVGFibGVOYW1lUHJlZml4KSB7XG4gICAgICBhd2FpdCBleGVjdXRlU3RhdGVtZW50KGBBTFRFUiBUQUJMRSAke3RhYmxlTmFtZX0gUkVOQU1FIFRPICR7bmV3VGFibGVOYW1lfWAsIHRhYmxlQW5kQ2x1c3RlclByb3BzKTtcbiAgICAgIHJldHVybiB0YWJsZU5hbWVQcmVmaXggKyB0YWJsZU5hbWVTdWZmaXg7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhYmxlTmFtZTtcbn1cblxuZnVuY3Rpb24gZ2V0U29ydEtleUNvbHVtbnNTdHJpbmcoc29ydEtleUNvbHVtbnM6IENvbHVtbltdKSB7XG4gIHJldHVybiBzb3J0S2V5Q29sdW1ucy5tYXAoY29sdW1uID0+IGNvbHVtbi5uYW1lKS5qb2luKCk7XG59XG5cbmZ1bmN0aW9uIGdldEVuY29kaW5nQ29sdW1uU3RyaW5nKGNvbHVtbjogQ29sdW1uKTogc3RyaW5nIHtcbiAgaWYgKGNvbHVtbi5lbmNvZGluZykge1xuICAgIHJldHVybiBgIEVOQ09ERSAke2NvbHVtbi5lbmNvZGluZ31gO1xuICB9XG4gIHJldHVybiAnJztcbn1cbiJdfQ==