Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

vipera-npm-registry / motif-web-admin-core   js

Repository URL to install this package:

Version: 0.3.1 

/ esm2015 / lib / sections / Log / components / log-section-component.js

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
import * as tslib_1 from "tslib";
import { Component, ViewChild, ElementRef, Renderer2 } from '@angular/core';
import { PluginView } from 'web-console-core';
import { NGXLogger } from 'web-console-core';
import { LogService } from '@wa-motif-open-api/log-service';
import { ClipboardService } from 'ngx-clipboard';
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
import { faFileImport, faDownload, faCopy, faPaste } from '@fortawesome/free-solid-svg-icons';
import { WCNotificationCenter, NotificationType } from 'web-console-ui-kit';
import { saveAs } from '@progress/kendo-file-saver';
import { DatarecordsService } from '@wa-motif-open-api/datarecords-service';
import { WCSubscriptionHandler } from '../../../components/Commons/wc-subscription-handler';
import { formatDate } from '@angular/common';
import { WCSlidePanelComponent } from 'web-console-ui-kit';
import { DateRangePopupComponent } from '@progress/kendo-angular-dateinputs';
/** @type {?} */
const LOG_TAG = '[LogSection]';
let LogSectionComponent = class LogSectionComponent {
    /**
     * @param {?} logger
     * @param {?} notificationCenter
     * @param {?} logService
     * @param {?} renderer2
     * @param {?} clipboardService
     * @param {?} datarecordsService
     */
    constructor(logger, notificationCenter, logService, renderer2, clipboardService, datarecordsService) {
        this.logger = logger;
        this.notificationCenter = notificationCenter;
        this.logService = logService;
        this.renderer2 = renderer2;
        this.clipboardService = clipboardService;
        this.datarecordsService = datarecordsService;
        this.faFileImport = faFileImport;
        this.faDownload = faDownload;
        this.faExternalLinkSquareAlt = faExternalLinkSquareAlt;
        this.faCopy = faCopy;
        this.faPaste = faPaste;
        this.linesCount = 100;
        this.dataRecordTypes = [];
        this.range = { start: null, end: null };
        this._subHandler = new WCSubscriptionHandler();
        this.logger.debug(LOG_TAG, 'Opening...');
        this.logLevels = [];
        this.logLevels.push({ level: 'ERROR' });
        this.logLevels.push({ level: 'WARN' });
        this.logLevels.push({ level: 'INFO' });
        this.logLevels.push({ level: 'DEBUG' });
        this.logLevels.push({ level: 'TRACE' });
    }
    /**
     * Angular ngOnInit
     * @return {?}
     */
    ngOnInit() {
        this.logger.debug(LOG_TAG, 'Initializing...');
        this.tailLines = '';
        this.loadDatarecordsTypes();
        this.refreshData();
    }
    /**
     * @return {?}
     */
    ngOnDestroy() {
        this.logger.debug(LOG_TAG, 'ngOnDestroy ');
        this.freeMem();
    }
    /**
     * @return {?}
     */
    freeMem() {
        this.tailLines = null;
        this.logLevels = null;
        this.dataRecordTypes = null;
        this._subHandler.unsubscribe();
        this._subHandler = null;
    }
    /**
     * @return {?}
     */
    onRefreshClicked() {
        this.logger.debug(LOG_TAG, 'linesCount :', this.linesCount);
        this.loading = true;
        this._subHandler.add(this.logService.tailCurrentLog(this.linesCount).subscribe((/**
         * @param {?} logTail
         * @return {?}
         */
        (logTail) => {
            this.tailLines = logTail.data;
            this.currentTailLinesCount = logTail.lines;
            this.loading = false;
        }), (/**
         * @param {?} error
         * @return {?}
         */
        (error) => {
            this.logger.error(LOG_TAG, 'tailCurrentLog error:', error);
            this.notificationCenter.post({
                name: 'RefreshLogTailError',
                title: 'Tail Log',
                message: 'Error refreshing log:',
                type: NotificationType.Error,
                error: error,
                closable: true
            });
            this.loading = false;
        })));
    }
    /**
     * @return {?}
     */
    onCopyToClipboardClicked() {
        this.clipboardService.copyFromContent(this.tailLines);
        this.notificationCenter.post({
            name: 'LogTailCopy',
            title: 'Log tail Copy',
            message: 'The current displayed log has been copied to the clipboard.',
            type: NotificationType.Info
        });
    }
    /**
     * @param {?} logLevel
     * @return {?}
     */
    set rootLogLevel(logLevel) {
        if (logLevel) {
            this._rootLogLevel = logLevel;
            this.logger.debug(LOG_TAG, 'Changing ROOT log level :', logLevel);
            this._subHandler.add(this.logService.setRootLogLevel(this._rootLogLevel).subscribe((/**
             * @param {?} data
             * @return {?}
             */
            (data) => {
                this.logger.debug(LOG_TAG, 'Changed ROOT log level :', data);
                this.notificationCenter.post({
                    name: 'RootLogLevelChangeSuccess',
                    title: 'Log Management',
                    message: 'The ROOT Log Level has been changed to ' + logLevel.level,
                    type: NotificationType.Success
                });
            }), (/**
             * @param {?} error
             * @return {?}
             */
            (error) => {
                this.logger.error(LOG_TAG, 'Error changing ROOT Log Level:', error);
                this.notificationCenter.post({
                    name: 'RootLogLevelChangeError',
                    title: 'Log Management',
                    message: 'Error changing ROOT Log Level:',
                    type: NotificationType.Error,
                    error: error,
                    closable: true
                });
            })));
        }
    }
    /**
     * @return {?}
     */
    get rootLogLevel() {
        return this._rootLogLevel;
    }
    /**
     * @return {?}
     */
    refreshData() {
        this.logService.getRootLogLevel().subscribe((/**
         * @param {?} data
         * @return {?}
         */
        (data) => {
            this.logger.debug(LOG_TAG, 'Getting ROOT log level :', data);
            this._rootLogLevel = data;
        }), (/**
         * @param {?} error
         * @return {?}
         */
        (error) => {
            this.logger.error(LOG_TAG, 'Error Getting ROOT log level :', error);
        }));
    }
    /**
     * @return {?}
     */
    onDownloadClicked() {
        this.notificationCenter.post({
            name: 'LogDownload',
            title: 'Download Log',
            message: 'Downloading Log file...',
            type: NotificationType.Info
        });
        this._subHandler.add(this.logService.downloadCurrentLog().subscribe((/**
         * @param {?} data
         * @return {?}
         */
        (data) => {
            this.logger.debug(LOG_TAG, 'Export done.', data);
            /** @type {?} */
            const blob = new Blob([data], { type: 'application/zip' });
            /** @type {?} */
            const fileName = 'motif_log_' + new Date().getTime() + '.zip';
            this.logger.debug(LOG_TAG, 'Saving to: ', blob);
            saveAs(blob, fileName);
            // FileSaver.saveAs(blob, fileName);
            this.logger.debug(LOG_TAG, 'Log saved: ', fileName);
            this.notificationCenter.post({
                name: 'LogExportSuccess',
                title: 'Download Log',
                message: 'The Log file has been downloaded.',
                type: NotificationType.Success
            });
        }), (/**
         * @param {?} error
         * @return {?}
         */
        (error) => {
            this.logger.error(LOG_TAG, 'Log download error:', error);
            this.notificationCenter.post({
                name: 'LogExportError',
                title: 'Download Log',
                message: 'Error downloading the Log file:',
                type: NotificationType.Error,
                error: error,
                closable: true
            });
        })));
    }
    /**
     * @return {?}
     */
    onExportClicked() {
        this.exportSlideDownPanel.toggle();
    }
    /**
     * @return {?}
     */
    onExportConfirm() {
        if (this.exportDataRecords()) {
            this.exportSlideDownPanel.show(false);
        }
    }
    /**
     * @return {?}
     */
    onExportCancel() {
        this.exportSlideDownPanel.show(false);
    }
    /**
     * @return {?}
     */
    onSlidePanelClose() {
        this.range.start = null;
        this.range.end = null;
        this.dataRecordType = null;
    }
    /**
     * @private
     * @param {?} date
     * @return {?}
     */
    convertDate(date) {
        return formatDate(date, 'yyyy/MM/dd HH:mm:ss', 'en-US');
    }
    /**
     * @private
     * @return {?}
     */
    exportDataRecords() {
        this.logger.debug(LOG_TAG, 'exportDataRecords: ', this.dataRecordType, this.range.start, this.range.end);
        if ((this.dataRecordType == null) || (this.range.start == null) || (this.range.end == null)) {
            this.notificationCenter.post({
                name: 'ExportDataRecordsProgress',
                title: 'DataRecords Export',
                message: 'Ivalid export parameters.',
                type: NotificationType.Warning,
                closable: false
            });
            return false;
        }
        this.notificationCenter.post({
            name: 'ExportDataRecordsProgress',
            title: 'DataRecords Export',
            message: 'Exporting datarecords...',
            type: NotificationType.Info,
            closable: false
        });
        /** @type {?} */
        const startDate = this.range.start;
        /** @type {?} */
        const endDate = this.range.end;
        this.logger.debug(LOG_TAG, 'exportDataRecords: ', this.dataRecordType, startDate, endDate);
        this._subHandler.add(this.datarecordsService.exportDatarecords(this.dataRecordType, null, null, null, startDate, endDate).subscribe((/**
         * @param {?} data
         * @return {?}
         */
        (data) => {
            this.logger.debug(LOG_TAG, 'exportDataRecords done: ', data);
            /** @type {?} */
            const blob = new Blob([data], { type: 'application/zip' });
            /** @type {?} */
            const fileName = 'motif_datarecords_' + new Date().getTime() + '.zip';
            this.logger.debug(LOG_TAG, 'Saving to: ', blob);
            saveAs(blob, fileName);
            this.logger.debug(LOG_TAG, 'Log saved: ', fileName);
            this.notificationCenter.post({
                name: 'ExportDataRecordsSuccess',
                title: 'DataRecords Export',
                message: 'Datarecords exported successfully.',
                type: NotificationType.Success,
                closable: false
            });
        }), (/**
         * @param {?} error
         * @return {?}
         */
        (error) => {
            this.logger.error(LOG_TAG, 'exportDataRecords error: ', error);
            this.notificationCenter.post({
                name: 'ExportDataRecordsError',
                title: 'DataRecord Export',
                message: 'Error exporting datarecords:',
                type: NotificationType.Error,
                error: error,
                closable: true
            });
        })));
        return true;
    }
    /**
     * @private
     * @return {?}
     */
    loadDatarecordsTypes() {
        this._subHandler.add(this.datarecordsService.getDatarecordsTypes().subscribe((/**
         * @param {?} data
         * @return {?}
         */
        (data) => {
            this.logger.debug(LOG_TAG, 'loadDatarecordsTypes: ', data);
            this.dataRecordTypes = data;
        }), (/**
         * @param {?} error
         * @return {?}
         */
        (error) => {
            this.logger.error(LOG_TAG, 'loadDatarecordsTypes error: ', error);
            this.notificationCenter.post({
                name: 'GetDataRecordTypesError',
                title: 'Get DataRecord Types',
                message: 'Error getting the datarecord types:',
                type: NotificationType.Error,
                error: error,
                closable: true
            });
        })));
    }
    /**
     * @return {?}
     */
    onDateRangePopupOpen() {
    }
};
LogSectionComponent.decorators = [
    { type: Component, args: [{
                selector: 'wa-log-section',
                template: "<wc-loading-overlay [visible]='loading'></wc-loading-overlay>\n\n<wc-dashboard-header [title]=\"'Log'\"></wc-dashboard-header>\n\n<div class=\"row spread\">\n\n    <div class=\"flex-toolbar\" style=\"display:flex;align-items: center;\">\n        <div>\n            <label>Lines</label>\n            <input type=\"number\" [(ngModel)]=\"linesCount\">\n        </div>\n        <div>\n            <label>ROOT Log Level</label>\n            <kendo-dropdownlist \n                motif-acl=\"com.vipera.osgi.core.platform.api.rest.LogsApi:UPDATE:setRootLogLevel\"\n                [data]=\"logLevels\" [textField]=\"'level'\" [valueField]=\"'level'\" [(ngModel)]=\"rootLogLevel\" [popupSettings]=\"{ 'popupClass' : 'wa-kui-combobox-popup', 'animate' : false }\"\n                [valuePrimitive]=\"false\"></kendo-dropdownlist>\n        </div>\n    </div>\n\n    <div class=\"flex-cmd\">\n        <kendo-buttongroup look=\"flat\">\n            <button kendoButton \n                [motif-acl]=\"['com.vipera.osgi.foundation.datarecords.api.rest.DatarecordsApi:READ:exportDatarecords',\n                                'com.vipera.osgi.foundation.datarecords.api.rest.DatarecordsApi:READ:verifyDatarecordsExport',\n                                'com.vipera.osgi.foundation.datarecords.api.rest.DatarecordsApi:READ:getDatarecordsTypes']\"\n                [toggleable]=\"false\" (click)=\"onExportClicked()\">\n                <fa-icon [icon]=\"faExternalLinkSquareAlt\"></fa-icon>Export\n            </button>\n        </kendo-buttongroup>\n        <kendo-buttongroup look=\"flat\">\n            <button kendoButton \n                motif-acl=\"com.vipera.osgi.core.platform.api.rest.LogsApi:READ:downloadCurrentLog\"\n                [toggleable]=\"false\" (click)=\"onDownloadClicked()\">\n                <fa-icon [icon]=\"faDownload\"></fa-icon>Download\n            </button>\n        </kendo-buttongroup>\n        <kendo-buttongroup look=\"flat\">\n            <button kendoButton [toggleable]=\"false\" [icon]=\"'refresh'\" (click)=\"onRefreshClicked()\">Refresh</button>\n        </kendo-buttongroup>\n    </div>\n\n</div>\n\n<div class=\"row fill\">\n    <div>\n\n        <!-- Sliding Editor Panel for Export -->\n        <wc-slide-panel #exportSlideDownPanel (close)=\"onSlidePanelClose()\">\n            <div class=\"wc-slide-down-editor-pane\" style=\"display:flex;\">\n                <div>\n                    <label>Data Record Type</label>\n                    <kendo-dropdownlist [data]=\"dataRecordTypes\" [(ngModel)]=\"dataRecordType\" [valuePrimitive]=\"true\"  [popupSettings]=\"{ 'popupClass' : 'wa-kui-combobox-popup', 'animate' : false }\"></kendo-dropdownlist>\n                </div>\n                <div>\n                    <kendo-daterange style=\"display:flex;\">\n                        <div>\n                            <label>Start</label>\n                            <kendo-dateinput kendoDateRangeStartInput [(value)]=\"range.start\"></kendo-dateinput>\n                        </div>\n                        <div>\n                            <label>End</label>\n                            <kendo-dateinput kendoDateRangeEndInput [(value)]=\"range.end\"></kendo-dateinput>\n                        </div>\n                        <kendo-daterange-popup (open)=\"onDateRangePopupOpen()\" #dateRangePopup></kendo-daterange-popup>\n                    </kendo-daterange>\n                </div>\n            </div>\n            \n            <div class=\"cmd\" style=\"align-items: center;margin-top:.5rem;\">\n                    <label style=\"padding-bottom: 0px;padding-left: 10px;padding-right: 10px;\">Do Export ?</label>\n                    <a (click)=\"onExportConfirm()\">\n                        <i data-id=\"ok\" class=\"ok icon wa-ico-ok confirmation-icon\"></i>\n                    </a>\n                    <a (click)=\"onExportCancel()\" data-slideup=\"#exportSlideDownPanel\">\n                        <i data-id=\"ko\" class=\"ko icon wa-ico-ko confirmation-icon\"></i>\n                    </a>\n                </div>\n            \n        </wc-slide-panel>\n\n        <!-- Log Pane -->\n        <label>Log <div class=\"cmd\"><button class=\"small small-copy-button\" data-copy=\"#output\" (click)=\"onCopyToClipboardClicked()\">\n                    <fa-icon [icon]=\"faPaste\" style=\"font-size: 18px;padding-left: 4px;\"></fa-icon>\n                </button></div></label>\n        <textarea class=\"fill log-pane\" spellcheck=\"false\" id=\"output\" #logPane readonly>{{tailLines}}</textarea>\n    </div>\n</div>\n",
                styles: [":host{display:flex;flex:1;flex-direction:column}.log-pane{white-space:pre}.editor.slidedown>div>kendo-daterange>div>label,.editor.slidedown>div>label{padding-bottom:5px}.small-copy-button{height:2rem;width:2rem;border-radius:50px}.wc-slide-down-editor-pane label{margin-bottom:4px}.wc-slide-down-editor-pane div{margin-right:8px}"]
            }] }
];
/** @nocollapse */
LogSectionComponent.ctorParameters = () => [
    { type: NGXLogger },
    { type: WCNotificationCenter },
    { type: LogService },
    { type: Renderer2 },
    { type: ClipboardService },
    { type: DatarecordsService }
];
LogSectionComponent.propDecorators = {
    logPane: [{ type: ViewChild, args: ['logPane',] }],
    exportSlideDownPanel: [{ type: ViewChild, args: ['exportSlideDownPanel',] }],
    dateRangePopup: [{ type: ViewChild, args: ['dateRangePopup',] }]
};
LogSectionComponent = tslib_1.__decorate([
    PluginView('Log', {
        iconName: 'wa-ico-log',
        userData: {
            acl: {
                permissions: ['com.vipera.osgi.core.platform.api.rest.LogsApi:READ:tailCurrentLog',
                    'com.vipera.osgi.core.platform.api.rest.LogsApi:READ:getRootLogLevel']
            }
        }
    }),
    tslib_1.__metadata("design:paramtypes", [NGXLogger,
        WCNotificationCenter,
        LogService,
        Renderer2,
        ClipboardService,
        DatarecordsService])
], LogSectionComponent);
export { LogSectionComponent };
if (false) {
    /** @type {?} */
    LogSectionComponent.prototype.faFileImport;
    /** @type {?} */
    LogSectionComponent.prototype.faDownload;
    /** @type {?} */
    LogSectionComponent.prototype.faExternalLinkSquareAlt;
    /** @type {?} */
    LogSectionComponent.prototype.faCopy;
    /** @type {?} */
    LogSectionComponent.prototype.faPaste;
    /** @type {?} */
    LogSectionComponent.prototype.tailLines;
    /** @type {?} */
    LogSectionComponent.prototype.linesCount;
    /** @type {?} */
    LogSectionComponent.prototype.currentTailLinesCount;
    /** @type {?} */
    LogSectionComponent.prototype.logLevels;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype._rootLogLevel;
    /** @type {?} */
    LogSectionComponent.prototype.dataRecordTypes;
    /** @type {?} */
    LogSectionComponent.prototype.dataRecordType;
    /** @type {?} */
    LogSectionComponent.prototype.range;
    /** @type {?} */
    LogSectionComponent.prototype.loading;
    /** @type {?} */
    LogSectionComponent.prototype.logPane;
    /** @type {?} */
    LogSectionComponent.prototype.exportSlideDownPanel;
    /** @type {?} */
    LogSectionComponent.prototype.dateRangePopup;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype._subHandler;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype.logger;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype.notificationCenter;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype.logService;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype.renderer2;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype.clipboardService;
    /**
     * @type {?}
     * @private
     */
    LogSectionComponent.prototype.datarecordsService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nLXNlY3Rpb24tY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbW90aWYtd2ViLWFkbWluLWNvcmUvIiwic291cmNlcyI6WyJsaWIvc2VjdGlvbnMvTG9nL2NvbXBvbmVudHMvbG9nLXNlY3Rpb24tY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxTQUFTLEVBQWEsVUFBVSxFQUFFLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUM5RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFNBQVMsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxVQUFVLEVBQXFCLE1BQU0sZ0NBQWdDLENBQUM7QUFFL0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWpELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUM5RixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1RSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDNUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDNUYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzNELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDOztNQUV2RSxPQUFPLEdBQUcsY0FBYztJQWdCakIsbUJB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O0lBQzVCLCtDQUEwQzs7Ozs7SUFDMUMsaURBQThDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIFZpZXdDaGlsZCwgT25EZXN0cm95LCBFbGVtZW50UmVmLCBSZW5kZXJlcjJ9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUGx1Z2luVmlldyB9IGZyb20gJ3dlYi1jb25zb2xlLWNvcmUnO1xuaW1wb3J0IHsgTkdYTG9nZ2VyfSBmcm9tICd3ZWItY29uc29sZS1jb3JlJztcbmltcG9ydCB7IExvZ1NlcnZpY2UsIExvZ0xldmVsLCBMb2dUYWlsIH0gZnJvbSAnQHdhLW1vdGlmLW9wZW4tYXBpL2xvZy1zZXJ2aWNlJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IENsaXBib2FyZFNlcnZpY2UgfSBmcm9tICduZ3gtY2xpcGJvYXJkJztcbmltcG9ydCAqIGFzIEZpbGVTYXZlciBmcm9tICdmaWxlLXNhdmVyJztcbmltcG9ydCB7IGZhRXh0ZXJuYWxMaW5rU3F1YXJlQWx0IH0gZnJvbSAnQGZvcnRhd2Vzb21lL2ZyZWUtc29saWQtc3ZnLWljb25zJztcbmltcG9ydCB7IGZhRmlsZUltcG9ydCwgZmFEb3dubG9hZCwgZmFDb3B5LCBmYVBhc3RlIH0gZnJvbSAnQGZvcnRhd2Vzb21lL2ZyZWUtc29saWQtc3ZnLWljb25zJztcbmltcG9ydCB7IFdDTm90aWZpY2F0aW9uQ2VudGVyLCBOb3RpZmljYXRpb25UeXBlIH0gZnJvbSAnd2ViLWNvbnNvbGUtdWkta2l0JztcbmltcG9ydCB7IHNhdmVBcyB9IGZyb20gJ0Bwcm9ncmVzcy9rZW5kby1maWxlLXNhdmVyJztcbmltcG9ydCB7IERhdGFyZWNvcmRzU2VydmljZSB9IGZyb20gJ0B3YS1tb3RpZi1vcGVuLWFwaS9kYXRhcmVjb3Jkcy1zZXJ2aWNlJztcbmltcG9ydCB7IFdDU3Vic2NyaXB0aW9uSGFuZGxlciB9IGZyb20gJy4uLy4uLy4uL2NvbXBvbmVudHMvQ29tbW9ucy93Yy1zdWJzY3JpcHRpb24taGFuZGxlcic7XG5pbXBvcnQgeyBmb3JtYXREYXRlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFdDU2xpZGVQYW5lbENvbXBvbmVudCB9IGZyb20gJ3dlYi1jb25zb2xlLXVpLWtpdCc7XG5pbXBvcnQgeyBEYXRlUmFuZ2VQb3B1cENvbXBvbmVudCB9IGZyb20gJ0Bwcm9ncmVzcy9rZW5kby1hbmd1bGFyLWRhdGVpbnB1dHMnO1xuXG5jb25zdCBMT0dfVEFHID0gJ1tMb2dTZWN0aW9uXSc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnd2EtbG9nLXNlY3Rpb24nLFxuICAgIHN0eWxlVXJsczogWyAnLi9sb2ctc2VjdGlvbi1jb21wb25lbnQuc2NzcycgXSxcbiAgICB0ZW1wbGF0ZVVybDogJy4vbG9nLXNlY3Rpb24tY29tcG9uZW50Lmh0bWwnXG4gIH0pXG4gIEBQbHVnaW5WaWV3KCdMb2cnLCB7XG4gICAgaWNvbk5hbWU6ICd3YS1pY28tbG9nJyxcbiAgICB1c2VyRGF0YToge1xuICAgICAgICBhY2w6IHtcbiAgICAgICAgICAgIHBlcm1pc3Npb25zOiBbJ2NvbS52aXBlcmEub3NnaS5jb3JlLnBsYXRmb3JtLmFwaS5yZXN0LkxvZ3NBcGk6UkVBRDp0YWlsQ3VycmVudExvZycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbS52aXBlcmEub3NnaS5jb3JlLnBsYXRmb3JtLmFwaS5yZXN0LkxvZ3NBcGk6UkVBRDpnZXRSb290TG9nTGV2ZWwnXVxuICAgICAgICB9XG4gICAgfVxufSlcbmV4cG9ydCBjbGFzcyBMb2dTZWN0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gICAgZmFGaWxlSW1wb3J0ID0gZmFGaWxlSW1wb3J0O1xuICAgIGZhRG93bmxvYWQgPSBmYURvd25sb2FkO1xuICAgIGZhRXh0ZXJuYWxMaW5rU3F1YXJlQWx0ID0gZmFFeHRlcm5hbExpbmtTcXVhcmVBbHQ7XG4gICAgZmFDb3B5ID0gZmFDb3B5O1xuICAgIGZhUGFzdGUgPSBmYVBhc3RlO1xuXG4gICAgcHVibGljIHRhaWxMaW5lczogc3RyaW5nO1xuICAgIHB1YmxpYyBsaW5lc0NvdW50ID0gMTAwO1xuICAgIHB1YmxpYyBjdXJyZW50VGFpbExpbmVzQ291bnQ6IG51bWJlcjtcbiAgICBwdWJsaWMgbG9nTGV2ZWxzOiBMb2dMZXZlbFtdO1xuICAgIHByaXZhdGUgX3Jvb3RMb2dMZXZlbDogTG9nTGV2ZWw7XG4gICAgcHVibGljIGRhdGFSZWNvcmRUeXBlczogc3RyaW5nW10gPSBbIF07XG4gICAgcHVibGljIGRhdGFSZWNvcmRUeXBlOiBzdHJpbmc7XG4gICAgcHVibGljIHJhbmdlID0geyBzdGFydDogbnVsbCwgZW5kOiBudWxsIH07XG5cbiAgICBsb2FkaW5nOiBib29sZWFuO1xuXG4gICAgQFZpZXdDaGlsZCgnbG9nUGFuZScpIGxvZ1BhbmU6IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgnZXhwb3J0U2xpZGVEb3duUGFuZWwnKSBleHBvcnRTbGlkZURvd25QYW5lbDogV0NTbGlkZVBhbmVsQ29tcG9uZW50O1xuICAgIEBWaWV3Q2hpbGQoJ2RhdGVSYW5nZVBvcHVwJykgZGF0ZVJhbmdlUG9wdXA6IERhdGVSYW5nZVBvcHVwQ29tcG9uZW50O1xuICAgIFxuXG4gICAgcHJpdmF0ZSBfc3ViSGFuZGxlcjogV0NTdWJzY3JpcHRpb25IYW5kbGVyID0gbmV3IFdDU3Vic2NyaXB0aW9uSGFuZGxlcigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBsb2dnZXI6IE5HWExvZ2dlcixcbiAgICAgICAgcHJpdmF0ZSBub3RpZmljYXRpb25DZW50ZXI6IFdDTm90aWZpY2F0aW9uQ2VudGVyLFxuICAgICAgICBwcml2YXRlIGxvZ1NlcnZpY2U6IExvZ1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcmVuZGVyZXIyOiBSZW5kZXJlcjIsXG4gICAgICAgIHByaXZhdGUgY2xpcGJvYXJkU2VydmljZTogQ2xpcGJvYXJkU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBkYXRhcmVjb3Jkc1NlcnZpY2U6IERhdGFyZWNvcmRzU2VydmljZSkge1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ09wZW5pbmcuLi4nKTtcblxuICAgICAgICB0aGlzLmxvZ0xldmVscyA9IFtdO1xuICAgICAgICB0aGlzLmxvZ0xldmVscy5wdXNoKHtsZXZlbDogJ0VSUk9SJ30pO1xuICAgICAgICB0aGlzLmxvZ0xldmVscy5wdXNoKHtsZXZlbDogJ1dBUk4nfSk7XG4gICAgICAgIHRoaXMubG9nTGV2ZWxzLnB1c2goe2xldmVsOiAnSU5GTyd9KTtcbiAgICAgICAgdGhpcy5sb2dMZXZlbHMucHVzaCh7bGV2ZWw6ICdERUJVRyd9KTtcbiAgICAgICAgdGhpcy5sb2dMZXZlbHMucHVzaCh7bGV2ZWw6ICdUUkFDRSd9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmd1bGFyIG5nT25Jbml0XG4gICAgICovXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcgLCAnSW5pdGlhbGl6aW5nLi4uJyk7XG4gICAgICAgIHRoaXMudGFpbExpbmVzID0gJyc7XG4gICAgICAgIHRoaXMubG9hZERhdGFyZWNvcmRzVHlwZXMoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoRGF0YSgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ25nT25EZXN0cm95ICcpO1xuICAgICAgICB0aGlzLmZyZWVNZW0oKTtcbiAgICB9XG5cbiAgICBmcmVlTWVtKCkge1xuICAgICAgICB0aGlzLnRhaWxMaW5lcyA9IG51bGw7XG4gICAgICAgIHRoaXMubG9nTGV2ZWxzID0gbnVsbDtcbiAgICAgICAgdGhpcy5kYXRhUmVjb3JkVHlwZXMgPSBudWxsO1xuICAgICAgICB0aGlzLl9zdWJIYW5kbGVyLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIHRoaXMuX3N1YkhhbmRsZXIgPSBudWxsO1xuICAgIH1cblxuICAgIHB1YmxpYyBvblJlZnJlc2hDbGlja2VkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ2xpbmVzQ291bnQgOicsIHRoaXMubGluZXNDb3VudCk7XG4gICAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuX3N1YkhhbmRsZXIuYWRkKHRoaXMubG9nU2VydmljZS50YWlsQ3VycmVudExvZyh0aGlzLmxpbmVzQ291bnQpLnN1YnNjcmliZSgobG9nVGFpbDogTG9nVGFpbCkgPT4ge1xuICAgICAgICAgICAgdGhpcy50YWlsTGluZXMgPSBsb2dUYWlsLmRhdGE7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRUYWlsTGluZXNDb3VudCA9IGxvZ1RhaWwubGluZXM7XG4gICAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihMT0dfVEFHICwgJ3RhaWxDdXJyZW50TG9nIGVycm9yOicsIGVycm9yKTtcbiAgICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgICAgIG5hbWU6ICdSZWZyZXNoTG9nVGFpbEVycm9yJyxcbiAgICAgICAgICAgICAgICB0aXRsZTogJ1RhaWwgTG9nJyxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiAnRXJyb3IgcmVmcmVzaGluZyBsb2c6JyxcbiAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLkVycm9yLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgICAgICBjbG9zYWJsZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgfSkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBvbkNvcHlUb0NsaXBib2FyZENsaWNrZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2xpcGJvYXJkU2VydmljZS5jb3B5RnJvbUNvbnRlbnQodGhpcy50YWlsTGluZXMpO1xuXG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgbmFtZTogJ0xvZ1RhaWxDb3B5JyxcbiAgICAgICAgICAgIHRpdGxlOiAnTG9nIHRhaWwgQ29weScsXG4gICAgICAgICAgICBtZXNzYWdlOiAnVGhlIGN1cnJlbnQgZGlzcGxheWVkIGxvZyBoYXMgYmVlbiBjb3BpZWQgdG8gdGhlIGNsaXBib2FyZC4nLFxuICAgICAgICAgICAgdHlwZTogTm90aWZpY2F0aW9uVHlwZS5JbmZvXG4gICAgICAgIH0pO1xuXG4gICAgfVxuXG4gICAgcHVibGljIHNldCByb290TG9nTGV2ZWwobG9nTGV2ZWw6IExvZ0xldmVsKSB7XG4gICAgICAgIGlmIChsb2dMZXZlbCkge1xuICAgICAgICAgICAgdGhpcy5fcm9vdExvZ0xldmVsID0gbG9nTGV2ZWw7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ0NoYW5naW5nIFJPT1QgbG9nIGxldmVsIDonLCBsb2dMZXZlbCk7XG4gICAgICAgICAgICB0aGlzLl9zdWJIYW5kbGVyLmFkZCh0aGlzLmxvZ1NlcnZpY2Uuc2V0Um9vdExvZ0xldmVsKHRoaXMuX3Jvb3RMb2dMZXZlbCkuc3Vic2NyaWJlKChkYXRhKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRyAsICdDaGFuZ2VkIFJPT1QgbG9nIGxldmVsIDonLCBkYXRhKTtcblxuICAgICAgICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiAnUm9vdExvZ0xldmVsQ2hhbmdlU3VjY2VzcycsXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiAnTG9nIE1hbmFnZW1lbnQnLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiAnVGhlIFJPT1QgTG9nIExldmVsIGhhcyBiZWVuIGNoYW5nZWQgdG8gJyArIGxvZ0xldmVsLmxldmVsLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLlN1Y2Nlc3NcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoTE9HX1RBRyAsICdFcnJvciBjaGFuZ2luZyBST09UIExvZyBMZXZlbDonLCBlcnJvcik7XG5cbiAgICAgICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbkNlbnRlci5wb3N0KHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogJ1Jvb3RMb2dMZXZlbENoYW5nZUVycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6ICdMb2cgTWFuYWdlbWVudCcsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICdFcnJvciBjaGFuZ2luZyBST09UIExvZyBMZXZlbDonLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLkVycm9yLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogZXJyb3IsXG4gICAgICAgICAgICAgICAgICAgIGNsb3NhYmxlOiB0cnVlXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgcm9vdExvZ0xldmVsKCk6IExvZ0xldmVsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Jvb3RMb2dMZXZlbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaERhdGEoKSB7XG4gICAgICAgIHRoaXMubG9nU2VydmljZS5nZXRSb290TG9nTGV2ZWwoKS5zdWJzY3JpYmUoKGRhdGE6IExvZ0xldmVsKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ0dldHRpbmcgUk9PVCBsb2cgbGV2ZWwgOicsIGRhdGEpO1xuICAgICAgICAgICAgdGhpcy5fcm9vdExvZ0xldmVsID0gZGF0YTtcbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihMT0dfVEFHICwgJ0Vycm9yIEdldHRpbmcgUk9PVCBsb2cgbGV2ZWwgOicsIGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uRG93bmxvYWRDbGlja2VkKCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgbmFtZTogJ0xvZ0Rvd25sb2FkJyxcbiAgICAgICAgICAgIHRpdGxlOiAnRG93bmxvYWQgTG9nJyxcbiAgICAgICAgICAgIG1lc3NhZ2U6ICdEb3dubG9hZGluZyBMb2cgZmlsZS4uLicsXG4gICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLkluZm9cbiAgICAgICAgfSk7XG5cblxuICAgICAgICB0aGlzLl9zdWJIYW5kbGVyLmFkZCh0aGlzLmxvZ1NlcnZpY2UuZG93bmxvYWRDdXJyZW50TG9nKCkuc3Vic2NyaWJlKChkYXRhKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ0V4cG9ydCBkb25lLicsIGRhdGEpO1xuXG4gICAgICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2RhdGFdLCB7dHlwZTogJ2FwcGxpY2F0aW9uL3ppcCd9KTtcblxuICAgICAgICAgICAgY29uc3QgZmlsZU5hbWUgPSAnbW90aWZfbG9nXycgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKSArICcuemlwJztcblxuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoTE9HX1RBRyAsICdTYXZpbmcgdG86ICcsIGJsb2IpO1xuXG4gICAgICAgICAgICBzYXZlQXMoYmxvYiwgZmlsZU5hbWUpO1xuICAgICAgICAgICAgLy8gRmlsZVNhdmVyLnNhdmVBcyhibG9iLCBmaWxlTmFtZSk7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ0xvZyBzYXZlZDogJywgZmlsZU5hbWUpO1xuXG4gICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbkNlbnRlci5wb3N0KHtcbiAgICAgICAgICAgICAgICBuYW1lOiAnTG9nRXhwb3J0U3VjY2VzcycsXG4gICAgICAgICAgICAgICAgdGl0bGU6ICdEb3dubG9hZCBMb2cnLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICdUaGUgTG9nIGZpbGUgaGFzIGJlZW4gZG93bmxvYWRlZC4nLFxuICAgICAgICAgICAgICAgIHR5cGU6IE5vdGlmaWNhdGlvblR5cGUuU3VjY2Vzc1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihMT0dfVEFHICwgJ0xvZyBkb3dubG9hZCBlcnJvcjonLCBlcnJvcik7XG5cbiAgICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgICAgIG5hbWU6ICdMb2dFeHBvcnRFcnJvcicsXG4gICAgICAgICAgICAgICAgdGl0bGU6ICdEb3dubG9hZCBMb2cnLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICdFcnJvciBkb3dubG9hZGluZyB0aGUgTG9nIGZpbGU6JyxcbiAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLkVycm9yLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgICAgICBjbG9zYWJsZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBvbkV4cG9ydENsaWNrZWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZXhwb3J0U2xpZGVEb3duUGFuZWwudG9nZ2xlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uRXhwb3J0Q29uZmlybSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZXhwb3J0RGF0YVJlY29yZHMoKSkge1xuICAgICAgICAgICAgdGhpcy5leHBvcnRTbGlkZURvd25QYW5lbC5zaG93KGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBvbkV4cG9ydENhbmNlbCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5leHBvcnRTbGlkZURvd25QYW5lbC5zaG93KGZhbHNlKTtcbiAgICB9XG5cbiAgICBvblNsaWRlUGFuZWxDbG9zZSgpe1xuICAgICAgICB0aGlzLnJhbmdlLnN0YXJ0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5yYW5nZS5lbmQgPSBudWxsO1xuICAgICAgICB0aGlzLmRhdGFSZWNvcmRUeXBlID0gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbnZlcnREYXRlKGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gZm9ybWF0RGF0ZShkYXRlLCAneXl5eS9NTS9kZCBISDptbTpzcycsICdlbi1VUycpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZXhwb3J0RGF0YVJlY29yZHMoKTogYm9vbGVhbiB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcgLCAnZXhwb3J0RGF0YVJlY29yZHM6ICcsIHRoaXMuZGF0YVJlY29yZFR5cGUsIHRoaXMucmFuZ2Uuc3RhcnQsIHRoaXMucmFuZ2UuZW5kKTtcblxuICAgICAgICBpZiAoKHRoaXMuZGF0YVJlY29yZFR5cGU9PW51bGwpIHx8ICh0aGlzLnJhbmdlLnN0YXJ0PT1udWxsKSB8fCAodGhpcy5yYW5nZS5lbmQ9PW51bGwpKXtcbiAgICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgICAgIG5hbWU6ICdFeHBvcnREYXRhUmVjb3Jkc1Byb2dyZXNzJyxcbiAgICAgICAgICAgICAgICB0aXRsZTogJ0RhdGFSZWNvcmRzIEV4cG9ydCcsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ0l2YWxpZCBleHBvcnQgcGFyYW1ldGVycy4nLFxuICAgICAgICAgICAgICAgIHR5cGU6IE5vdGlmaWNhdGlvblR5cGUuV2FybmluZyxcbiAgICAgICAgICAgICAgICBjbG9zYWJsZTogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb25DZW50ZXIucG9zdCh7XG4gICAgICAgICAgICBuYW1lOiAnRXhwb3J0RGF0YVJlY29yZHNQcm9ncmVzcycsXG4gICAgICAgICAgICB0aXRsZTogJ0RhdGFSZWNvcmRzIEV4cG9ydCcsXG4gICAgICAgICAgICBtZXNzYWdlOiAnRXhwb3J0aW5nIGRhdGFyZWNvcmRzLi4uJyxcbiAgICAgICAgICAgIHR5cGU6IE5vdGlmaWNhdGlvblR5cGUuSW5mbyxcbiAgICAgICAgICAgIGNsb3NhYmxlOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgc3RhcnREYXRlID0gdGhpcy5yYW5nZS5zdGFydDtcbiAgICAgICAgY29uc3QgZW5kRGF0ZSA9IHRoaXMucmFuZ2UuZW5kO1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ2V4cG9ydERhdGFSZWNvcmRzOiAnLCB0aGlzLmRhdGFSZWNvcmRUeXBlLCBzdGFydERhdGUsIGVuZERhdGUpO1xuICAgICAgICB0aGlzLl9zdWJIYW5kbGVyLmFkZCh0aGlzLmRhdGFyZWNvcmRzU2VydmljZS5leHBvcnREYXRhcmVjb3Jkcyh0aGlzLmRhdGFSZWNvcmRUeXBlLCBudWxsLCBudWxsLCBudWxsLCBcbiAgICAgICAgICAgIHN0YXJ0RGF0ZSwgZW5kRGF0ZSApLnN1YnNjcmliZSggKGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ2V4cG9ydERhdGFSZWNvcmRzIGRvbmU6ICcsIGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtkYXRhXSwge3R5cGU6ICdhcHBsaWNhdGlvbi96aXAnfSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZU5hbWUgPSAnbW90aWZfZGF0YXJlY29yZHNfJyArIG5ldyBEYXRlKCkuZ2V0VGltZSgpICsgJy56aXAnO1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcgLCAnU2F2aW5nIHRvOiAnLCBibG9iKTtcbiAgICAgICAgICAgICAgICBzYXZlQXMoYmxvYiwgZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKExPR19UQUcgLCAnTG9nIHNhdmVkOiAnLCBmaWxlTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbkNlbnRlci5wb3N0KHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogJ0V4cG9ydERhdGFSZWNvcmRzU3VjY2VzcycsXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiAnRGF0YVJlY29yZHMgRXhwb3J0JyxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogJ0RhdGFyZWNvcmRzIGV4cG9ydGVkIHN1Y2Nlc3NmdWxseS4nLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLlN1Y2Nlc3MsXG4gICAgICAgICAgICAgICAgICAgIGNsb3NhYmxlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICBcbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKExPR19UQUcgLCAnZXhwb3J0RGF0YVJlY29yZHMgZXJyb3I6ICcsIGVycm9yKTtcblxuICAgICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25DZW50ZXIucG9zdCh7XG4gICAgICAgICAgICAgICAgbmFtZTogJ0V4cG9ydERhdGFSZWNvcmRzRXJyb3InLFxuICAgICAgICAgICAgICAgIHRpdGxlOiAnRGF0YVJlY29yZCBFeHBvcnQnLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICdFcnJvciBleHBvcnRpbmcgZGF0YXJlY29yZHM6JyxcbiAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLkVycm9yLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgICAgICBjbG9zYWJsZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSkpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWREYXRhcmVjb3Jkc1R5cGVzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9zdWJIYW5kbGVyLmFkZCh0aGlzLmRhdGFyZWNvcmRzU2VydmljZS5nZXREYXRhcmVjb3Jkc1R5cGVzKCkuc3Vic2NyaWJlKChkYXRhKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhMT0dfVEFHICwgJ2xvYWREYXRhcmVjb3Jkc1R5cGVzOiAnLCBkYXRhKTtcbiAgICAgICAgICAgIHRoaXMuZGF0YVJlY29yZFR5cGVzID0gZGF0YTtcbiAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihMT0dfVEFHICwgJ2xvYWREYXRhcmVjb3Jkc1R5cGVzIGVycm9yOiAnLCBlcnJvcik7XG5cbiAgICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uQ2VudGVyLnBvc3Qoe1xuICAgICAgICAgICAgICAgIG5hbWU6ICdHZXREYXRhUmVjb3JkVHlwZXNFcnJvcicsXG4gICAgICAgICAgICAgICAgdGl0bGU6ICdHZXQgRGF0YVJlY29yZCBUeXBlcycsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ0Vycm9yIGdldHRpbmcgdGhlIGRhdGFyZWNvcmQgdHlwZXM6JyxcbiAgICAgICAgICAgICAgICB0eXBlOiBOb3RpZmljYXRpb25UeXBlLkVycm9yLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgICAgICBjbG9zYWJsZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSkpO1xuICAgIH1cblxuICAgIG9uRGF0ZVJhbmdlUG9wdXBPcGVuKCkge1xuXG4gICAgfVxuXG59XG4iXX0=