aws-cdk 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +276 -0
- package/LICENSE +202 -0
- package/NOTICE +16 -0
- package/README.md +1274 -0
- package/THIRD_PARTY_LICENSES +26821 -0
- package/bin/cdk +6 -0
- package/build-info.json +4 -0
- package/db.json.gz +0 -0
- package/generate.sh +25 -0
- package/images/garbage-collection.png +0 -0
- package/lib/api/aws-auth/account-cache.d.ts +39 -0
- package/lib/api/aws-auth/account-cache.js +102 -0
- package/lib/api/aws-auth/awscli-compatible.d.ts +42 -0
- package/lib/api/aws-auth/awscli-compatible.js +264 -0
- package/lib/api/aws-auth/cached.d.ts +11 -0
- package/lib/api/aws-auth/cached.js +26 -0
- package/lib/api/aws-auth/credential-plugins.d.ts +36 -0
- package/lib/api/aws-auth/credential-plugins.js +153 -0
- package/lib/api/aws-auth/index.d.ts +3 -0
- package/lib/api/aws-auth/index.js +20 -0
- package/lib/api/aws-auth/provider-caching.d.ts +13 -0
- package/lib/api/aws-auth/provider-caching.js +24 -0
- package/lib/api/aws-auth/sdk-logger.d.ts +69 -0
- package/lib/api/aws-auth/sdk-logger.js +130 -0
- package/lib/api/aws-auth/sdk-provider.d.ts +207 -0
- package/lib/api/aws-auth/sdk-provider.js +359 -0
- package/lib/api/aws-auth/sdk.d.ts +223 -0
- package/lib/api/aws-auth/sdk.js +366 -0
- package/lib/api/aws-auth/tracing.d.ts +11 -0
- package/lib/api/aws-auth/tracing.js +61 -0
- package/lib/api/aws-auth/user-agent.d.ts +7 -0
- package/lib/api/aws-auth/user-agent.js +21 -0
- package/lib/api/aws-auth/util.d.ts +6 -0
- package/lib/api/aws-auth/util.js +23 -0
- package/lib/api/bootstrap/bootstrap-environment.d.ts +33 -0
- package/lib/api/bootstrap/bootstrap-environment.js +322 -0
- package/lib/api/bootstrap/bootstrap-props.d.ts +130 -0
- package/lib/api/bootstrap/bootstrap-props.js +14 -0
- package/lib/api/bootstrap/bootstrap-template.yaml +692 -0
- package/lib/api/bootstrap/deploy-bootstrap.d.ts +37 -0
- package/lib/api/bootstrap/deploy-bootstrap.js +143 -0
- package/lib/api/bootstrap/index.d.ts +2 -0
- package/lib/api/bootstrap/index.js +19 -0
- package/lib/api/bootstrap/legacy-template.d.ts +2 -0
- package/lib/api/bootstrap/legacy-template.js +82 -0
- package/lib/api/context.d.ts +40 -0
- package/lib/api/context.js +82 -0
- package/lib/api/cxapp/cloud-assembly.d.ts +150 -0
- package/lib/api/cxapp/cloud-assembly.js +305 -0
- package/lib/api/cxapp/cloud-executable.d.ts +44 -0
- package/lib/api/cxapp/cloud-executable.js +90 -0
- package/lib/api/cxapp/environments.d.ts +9 -0
- package/lib/api/cxapp/environments.js +66 -0
- package/lib/api/cxapp/exec.d.ts +56 -0
- package/lib/api/cxapp/exec.js +275 -0
- package/lib/api/deployments/asset-manifest-builder.d.ts +8 -0
- package/lib/api/deployments/asset-manifest-builder.js +35 -0
- package/lib/api/deployments/asset-publishing.d.ts +77 -0
- package/lib/api/deployments/asset-publishing.js +163 -0
- package/lib/api/deployments/assets.d.ts +10 -0
- package/lib/api/deployments/assets.js +111 -0
- package/lib/api/deployments/checks.d.ts +8 -0
- package/lib/api/deployments/checks.js +73 -0
- package/lib/api/deployments/cloudformation.d.ts +235 -0
- package/lib/api/deployments/cloudformation.js +598 -0
- package/lib/api/deployments/deploy-stack.d.ts +177 -0
- package/lib/api/deployments/deploy-stack.js +484 -0
- package/lib/api/deployments/deployment-method.d.ts +24 -0
- package/lib/api/deployments/deployment-method.js +3 -0
- package/lib/api/deployments/deployment-result.d.ts +21 -0
- package/lib/api/deployments/deployment-result.js +10 -0
- package/lib/api/deployments/deployments.d.ts +340 -0
- package/lib/api/deployments/deployments.js +369 -0
- package/lib/api/deployments/hotswap-deployments.d.ts +14 -0
- package/lib/api/deployments/hotswap-deployments.js +357 -0
- package/lib/api/deployments/index.d.ts +6 -0
- package/lib/api/deployments/index.js +23 -0
- package/lib/api/deployments/nested-stack-helpers.d.ts +25 -0
- package/lib/api/deployments/nested-stack-helpers.js +88 -0
- package/lib/api/environment-access.d.ts +138 -0
- package/lib/api/environment-access.js +203 -0
- package/lib/api/environment-resources.d.ts +73 -0
- package/lib/api/environment-resources.js +208 -0
- package/lib/api/evaluate-cloudformation-template.d.ts +84 -0
- package/lib/api/evaluate-cloudformation-template.js +443 -0
- package/lib/api/garbage-collection/garbage-collector.d.ts +152 -0
- package/lib/api/garbage-collection/garbage-collector.js +607 -0
- package/lib/api/garbage-collection/progress-printer.d.ts +21 -0
- package/lib/api/garbage-collection/progress-printer.js +69 -0
- package/lib/api/garbage-collection/stack-refresh.d.ts +44 -0
- package/lib/api/garbage-collection/stack-refresh.js +154 -0
- package/lib/api/hotswap/appsync-mapping-templates.d.ts +3 -0
- package/lib/api/hotswap/appsync-mapping-templates.js +157 -0
- package/lib/api/hotswap/code-build-projects.d.ts +3 -0
- package/lib/api/hotswap/code-build-projects.js +55 -0
- package/lib/api/hotswap/common.d.ts +126 -0
- package/lib/api/hotswap/common.js +170 -0
- package/lib/api/hotswap/ecs-services.d.ts +3 -0
- package/lib/api/hotswap/ecs-services.js +140 -0
- package/lib/api/hotswap/lambda-functions.d.ts +3 -0
- package/lib/api/hotswap/lambda-functions.js +309 -0
- package/lib/api/hotswap/s3-bucket-deployments.d.ts +9 -0
- package/lib/api/hotswap/s3-bucket-deployments.js +112 -0
- package/lib/api/hotswap/stepfunctions-state-machines.d.ts +3 -0
- package/lib/api/hotswap/stepfunctions-state-machines.js +42 -0
- package/lib/api/index.d.ts +5 -0
- package/lib/api/index.js +22 -0
- package/lib/api/logs/find-cloudwatch-logs.d.ts +24 -0
- package/lib/api/logs/find-cloudwatch-logs.js +97 -0
- package/lib/api/logs/logs-monitor.d.ts +53 -0
- package/lib/api/logs/logs-monitor.js +169 -0
- package/lib/api/plugin/context-provider-plugin.d.ts +6 -0
- package/lib/api/plugin/context-provider-plugin.js +7 -0
- package/lib/api/plugin/index.d.ts +3 -0
- package/lib/api/plugin/index.js +20 -0
- package/lib/api/plugin/mode.d.ts +4 -0
- package/lib/api/plugin/mode.js +9 -0
- package/lib/api/plugin/plugin.d.ts +63 -0
- package/lib/api/plugin/plugin.js +106 -0
- package/lib/api/settings.d.ts +29 -0
- package/lib/api/settings.js +141 -0
- package/lib/api/tags.d.ts +9 -0
- package/lib/api/tags.js +10 -0
- package/lib/api/toolkit-info.d.ts +51 -0
- package/lib/api/toolkit-info.js +156 -0
- package/lib/api/util/cloudformation/stack-activity-monitor.d.ts +237 -0
- package/lib/api/util/cloudformation/stack-activity-monitor.js +550 -0
- package/lib/api/util/cloudformation/stack-event-poller.d.ts +63 -0
- package/lib/api/util/cloudformation/stack-event-poller.js +129 -0
- package/lib/api/util/cloudformation/stack-status.d.ts +42 -0
- package/lib/api/util/cloudformation/stack-status.js +88 -0
- package/lib/api/util/display.d.ts +13 -0
- package/lib/api/util/display.js +80 -0
- package/lib/api/util/placeholders.d.ts +10 -0
- package/lib/api/util/placeholders.js +24 -0
- package/lib/api/util/rwlock.d.ts +65 -0
- package/lib/api/util/rwlock.js +179 -0
- package/lib/api/util/string-manipulation.d.ts +10 -0
- package/lib/api/util/string-manipulation.js +33 -0
- package/lib/api/util/template-body-parameter.d.ts +21 -0
- package/lib/api/util/template-body-parameter.js +104 -0
- package/lib/cli/cdk-toolkit.d.ts +594 -0
- package/lib/cli/cdk-toolkit.js +1019 -0
- package/lib/cli/cli-config.d.ts +10 -0
- package/lib/cli/cli-config.js +406 -0
- package/lib/cli/cli.d.ts +4 -0
- package/lib/cli/cli.js +538 -0
- package/lib/cli/convert-to-user-input.d.ts +3 -0
- package/lib/cli/convert-to-user-input.js +434 -0
- package/lib/cli/parse-command-line-arguments.d.ts +1 -0
- package/lib/cli/parse-command-line-arguments.js +806 -0
- package/lib/cli/platform-warnings.d.ts +2 -0
- package/lib/cli/platform-warnings.js +45 -0
- package/lib/cli/user-configuration.d.ts +90 -0
- package/lib/cli/user-configuration.js +272 -0
- package/lib/cli/user-input.d.ts +1163 -0
- package/lib/cli/user-input.js +3 -0
- package/lib/cli/util/console-formatters.d.ts +18 -0
- package/lib/cli/util/console-formatters.js +42 -0
- package/lib/cli/util/npm.d.ts +1 -0
- package/lib/cli/util/npm.js +22 -0
- package/lib/cli/util/yargs-helpers.d.ts +22 -0
- package/lib/cli/util/yargs-helpers.js +49 -0
- package/lib/cli/version.d.ts +13 -0
- package/lib/cli/version.js +120 -0
- package/lib/commands/context.d.ts +35 -0
- package/lib/commands/context.js +156 -0
- package/lib/commands/docs.d.ts +13 -0
- package/lib/commands/docs.js +32 -0
- package/lib/commands/doctor.d.ts +1 -0
- package/lib/commands/doctor.js +69 -0
- package/lib/commands/migrate.d.ts +327 -0
- package/lib/commands/migrate.js +804 -0
- package/lib/context-providers/ami.d.ts +11 -0
- package/lib/context-providers/ami.js +50 -0
- package/lib/context-providers/availability-zones.d.ts +11 -0
- package/lib/context-providers/availability-zones.js +27 -0
- package/lib/context-providers/endpoint-service-availability-zones.d.ts +11 -0
- package/lib/context-providers/endpoint-service-availability-zones.js +33 -0
- package/lib/context-providers/hosted-zones.d.ts +10 -0
- package/lib/context-providers/hosted-zones.js +67 -0
- package/lib/context-providers/index.d.ts +30 -0
- package/lib/context-providers/index.js +109 -0
- package/lib/context-providers/keys.d.ts +11 -0
- package/lib/context-providers/keys.js +52 -0
- package/lib/context-providers/load-balancers.d.ts +20 -0
- package/lib/context-providers/load-balancers.js +159 -0
- package/lib/context-providers/security-groups.d.ts +9 -0
- package/lib/context-providers/security-groups.js +70 -0
- package/lib/context-providers/ssm-parameters.d.ts +23 -0
- package/lib/context-providers/ssm-parameters.js +59 -0
- package/lib/context-providers/vpcs.d.ts +11 -0
- package/lib/context-providers/vpcs.js +288 -0
- package/lib/diff.d.ts +28 -0
- package/lib/diff.js +165 -0
- package/lib/import.d.ts +182 -0
- package/lib/import.js +335 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +348304 -0
- package/lib/index_bg.wasm +0 -0
- package/lib/init-hooks.d.ts +40 -0
- package/lib/init-hooks.js +64 -0
- package/lib/init-templates/.init-version.json +1 -0
- package/lib/init-templates/.no-packagejson-validator +0 -0
- package/lib/init-templates/.recommended-feature-flags.json +68 -0
- package/lib/init-templates/LICENSE +16 -0
- package/lib/init-templates/app/csharp/.template.gitignore +342 -0
- package/lib/init-templates/app/csharp/README.md +14 -0
- package/lib/init-templates/app/csharp/cdk.template.json +15 -0
- package/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj +20 -0
- package/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.cs +13 -0
- package/lib/init-templates/app/csharp/src/%name.PascalCased%/GlobalSuppressions.cs +1 -0
- package/lib/init-templates/app/csharp/src/%name.PascalCased%/Program.template.cs +44 -0
- package/lib/init-templates/app/csharp/src/%name.PascalCased%.template.sln +18 -0
- package/lib/init-templates/app/fsharp/.template.gitignore +342 -0
- package/lib/init-templates/app/fsharp/README.md +18 -0
- package/lib/init-templates/app/fsharp/cdk.template.json +14 -0
- package/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj +25 -0
- package/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.fs +8 -0
- package/lib/init-templates/app/fsharp/src/%name.PascalCased%/Program.template.fs +11 -0
- package/lib/init-templates/app/fsharp/src/%name.PascalCased%.template.sln +18 -0
- package/lib/init-templates/app/go/%name%.template.go +70 -0
- package/lib/init-templates/app/go/%name%_test.template.go +26 -0
- package/lib/init-templates/app/go/.template.gitignore +19 -0
- package/lib/init-templates/app/go/README.md +12 -0
- package/lib/init-templates/app/go/cdk.template.json +13 -0
- package/lib/init-templates/app/go/go.template.mod +9 -0
- package/lib/init-templates/app/info.json +4 -0
- package/lib/init-templates/app/java/.template.gitignore +13 -0
- package/lib/init-templates/app/java/README.md +18 -0
- package/lib/init-templates/app/java/cdk.json +13 -0
- package/lib/init-templates/app/java/pom.xml +60 -0
- package/lib/init-templates/app/java/src/main/java/com/myorg/%name.PascalCased%App.template.java +42 -0
- package/lib/init-templates/app/java/src/main/java/com/myorg/%name.PascalCased%Stack.template.java +24 -0
- package/lib/init-templates/app/java/src/test/java/com/myorg/%name.PascalCased%Test.template.java +26 -0
- package/lib/init-templates/app/javascript/.template.gitignore +5 -0
- package/lib/init-templates/app/javascript/.template.npmignore +3 -0
- package/lib/init-templates/app/javascript/README.md +12 -0
- package/lib/init-templates/app/javascript/bin/%name%.template.js +21 -0
- package/lib/init-templates/app/javascript/cdk.template.json +15 -0
- package/lib/init-templates/app/javascript/jest.config.js +3 -0
- package/lib/init-templates/app/javascript/lib/%name%-stack.template.js +23 -0
- package/lib/init-templates/app/javascript/package.json +20 -0
- package/lib/init-templates/app/javascript/test/%name%.test.template.js +17 -0
- package/lib/init-templates/app/python/%name.PythonModule%/%name.PythonModule%_stack.template.py +19 -0
- package/lib/init-templates/app/python/%name.PythonModule%/__init__.py +0 -0
- package/lib/init-templates/app/python/.template.gitignore +10 -0
- package/lib/init-templates/app/python/README.template.md +58 -0
- package/lib/init-templates/app/python/app.template.py +28 -0
- package/lib/init-templates/app/python/cdk.template.json +15 -0
- package/lib/init-templates/app/python/requirements-dev.txt +1 -0
- package/lib/init-templates/app/python/requirements.txt +2 -0
- package/lib/init-templates/app/python/source.bat +13 -0
- package/lib/init-templates/app/python/tests/__init__.py +0 -0
- package/lib/init-templates/app/python/tests/unit/__init__.py +0 -0
- package/lib/init-templates/app/python/tests/unit/test_%name.PythonModule%_stack.template.py +15 -0
- package/lib/init-templates/app/typescript/.template.gitignore +8 -0
- package/lib/init-templates/app/typescript/.template.npmignore +6 -0
- package/lib/init-templates/app/typescript/README.md +14 -0
- package/lib/init-templates/app/typescript/bin/%name%.template.ts +20 -0
- package/lib/init-templates/app/typescript/cdk.template.json +17 -0
- package/lib/init-templates/app/typescript/jest.config.js +8 -0
- package/lib/init-templates/app/typescript/lib/%name%-stack.template.ts +16 -0
- package/lib/init-templates/app/typescript/package.json +26 -0
- package/lib/init-templates/app/typescript/test/%name%.test.template.ts +17 -0
- package/lib/init-templates/app/typescript/tsconfig.json +31 -0
- package/lib/init-templates/lib/info.json +4 -0
- package/lib/init-templates/lib/typescript/.template.gitignore +8 -0
- package/lib/init-templates/lib/typescript/.template.npmignore +6 -0
- package/lib/init-templates/lib/typescript/README.template.md +12 -0
- package/lib/init-templates/lib/typescript/jest.config.js +8 -0
- package/lib/init-templates/lib/typescript/lib/index.template.ts +21 -0
- package/lib/init-templates/lib/typescript/package.json +24 -0
- package/lib/init-templates/lib/typescript/test/%name%.test.template.ts +18 -0
- package/lib/init-templates/lib/typescript/tsconfig.json +31 -0
- package/lib/init-templates/sample-app/csharp/.template.gitignore +342 -0
- package/lib/init-templates/sample-app/csharp/README.template.md +19 -0
- package/lib/init-templates/sample-app/csharp/cdk.template.json +15 -0
- package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj +20 -0
- package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.cs +24 -0
- package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/GlobalSuppressions.cs +1 -0
- package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/Program.template.cs +15 -0
- package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%.template.sln +18 -0
- package/lib/init-templates/sample-app/fsharp/.template.gitignore +342 -0
- package/lib/init-templates/sample-app/fsharp/README.template.md +20 -0
- package/lib/init-templates/sample-app/fsharp/cdk.template.json +14 -0
- package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj +25 -0
- package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.fs +14 -0
- package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/Program.template.fs +11 -0
- package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%.template.sln +18 -0
- package/lib/init-templates/sample-app/go/%name%.template.go +73 -0
- package/lib/init-templates/sample-app/go/%name%_test.template.go +25 -0
- package/lib/init-templates/sample-app/go/.template.gitignore +19 -0
- package/lib/init-templates/sample-app/go/README.md +12 -0
- package/lib/init-templates/sample-app/go/cdk.template.json +13 -0
- package/lib/init-templates/sample-app/go/go.template.mod +9 -0
- package/lib/init-templates/sample-app/info.json +4 -0
- package/lib/init-templates/sample-app/java/.template.gitignore +13 -0
- package/lib/init-templates/sample-app/java/README.template.md +19 -0
- package/lib/init-templates/sample-app/java/cdk.json +13 -0
- package/lib/init-templates/sample-app/java/pom.xml +55 -0
- package/lib/init-templates/sample-app/java/src/main/java/com/myorg/%name.PascalCased%App.template.java +13 -0
- package/lib/init-templates/sample-app/java/src/main/java/com/myorg/%name.PascalCased%Stack.template.java +29 -0
- package/lib/init-templates/sample-app/java/src/test/java/com/myorg/%name.PascalCased%StackTest.template.java +27 -0
- package/lib/init-templates/sample-app/javascript/.template.gitignore +5 -0
- package/lib/init-templates/sample-app/javascript/.template.npmignore +3 -0
- package/lib/init-templates/sample-app/javascript/README.template.md +13 -0
- package/lib/init-templates/sample-app/javascript/bin/%name%.template.js +6 -0
- package/lib/init-templates/sample-app/javascript/cdk.template.json +15 -0
- package/lib/init-templates/sample-app/javascript/jest.config.js +3 -0
- package/lib/init-templates/sample-app/javascript/lib/%name%-stack.template.js +25 -0
- package/lib/init-templates/sample-app/javascript/package.json +20 -0
- package/lib/init-templates/sample-app/javascript/test/%name%.test.template.js +16 -0
- package/lib/init-templates/sample-app/javascript/tsconfig.json +34 -0
- package/lib/init-templates/sample-app/python/%name.PythonModule%/%name.PythonModule%_stack.template.py +26 -0
- package/lib/init-templates/sample-app/python/%name.PythonModule%/__init__.py +0 -0
- package/lib/init-templates/sample-app/python/.template.gitignore +22 -0
- package/lib/init-templates/sample-app/python/README.template.md +65 -0
- package/lib/init-templates/sample-app/python/app.template.py +11 -0
- package/lib/init-templates/sample-app/python/cdk.template.json +15 -0
- package/lib/init-templates/sample-app/python/requirements-dev.txt +1 -0
- package/lib/init-templates/sample-app/python/requirements.txt +2 -0
- package/lib/init-templates/sample-app/python/source.bat +13 -0
- package/lib/init-templates/sample-app/python/tests/__init__.py +0 -0
- package/lib/init-templates/sample-app/python/tests/unit/__init__.py +0 -0
- package/lib/init-templates/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py +21 -0
- package/lib/init-templates/sample-app/typescript/.template.gitignore +8 -0
- package/lib/init-templates/sample-app/typescript/.template.npmignore +6 -0
- package/lib/init-templates/sample-app/typescript/README.template.md +15 -0
- package/lib/init-templates/sample-app/typescript/bin/%name%.template.ts +6 -0
- package/lib/init-templates/sample-app/typescript/cdk.template.json +17 -0
- package/lib/init-templates/sample-app/typescript/jest.config.js +8 -0
- package/lib/init-templates/sample-app/typescript/lib/%name%-stack.template.ts +19 -0
- package/lib/init-templates/sample-app/typescript/package.json +26 -0
- package/lib/init-templates/sample-app/typescript/test/%name%.test.template.ts +17 -0
- package/lib/init-templates/sample-app/typescript/tsconfig.json +31 -0
- package/lib/init.d.ts +52 -0
- package/lib/init.js +430 -0
- package/lib/legacy-exports-source.d.ts +27 -0
- package/lib/legacy-exports-source.js +88 -0
- package/lib/legacy-exports.d.ts +10 -0
- package/lib/legacy-exports.js +28 -0
- package/lib/legacy-logging-source.d.ts +32 -0
- package/lib/legacy-logging-source.js +107 -0
- package/lib/list-stacks.d.ts +22 -0
- package/lib/list-stacks.js +23 -0
- package/lib/logging.d.ts +109 -0
- package/lib/logging.js +159 -0
- package/lib/migrator.d.ts +25 -0
- package/lib/migrator.js +67 -0
- package/lib/notices.d.ts +156 -0
- package/lib/notices.js +373 -0
- package/lib/os.d.ts +7 -0
- package/lib/os.js +92 -0
- package/lib/serialize.d.ts +27 -0
- package/lib/serialize.js +86 -0
- package/lib/toolkit/cli-io-host.d.ts +208 -0
- package/lib/toolkit/cli-io-host.js +282 -0
- package/lib/toolkit/error.d.ts +44 -0
- package/lib/toolkit/error.js +78 -0
- package/lib/tree.d.ts +31 -0
- package/lib/tree.js +40 -0
- package/lib/util/archive.d.ts +1 -0
- package/lib/util/archive.js +86 -0
- package/lib/util/arrays.d.ts +14 -0
- package/lib/util/arrays.js +36 -0
- package/lib/util/bool.d.ts +7 -0
- package/lib/util/bool.js +13 -0
- package/lib/util/bytes.d.ts +8 -0
- package/lib/util/bytes.js +21 -0
- package/lib/util/content-hash.d.ts +5 -0
- package/lib/util/content-hash.js +43 -0
- package/lib/util/directories.d.ts +23 -0
- package/lib/util/directories.js +57 -0
- package/lib/util/error.d.ts +9 -0
- package/lib/util/error.js +22 -0
- package/lib/util/index.d.ts +5 -0
- package/lib/util/index.js +22 -0
- package/lib/util/objects.d.ts +52 -0
- package/lib/util/objects.js +183 -0
- package/lib/util/parallel.d.ts +6 -0
- package/lib/util/parallel.js +44 -0
- package/lib/util/tables.d.ts +1 -0
- package/lib/util/tables.js +10 -0
- package/lib/util/type-brands.d.ts +39 -0
- package/lib/util/type-brands.js +38 -0
- package/lib/util/types.d.ts +27 -0
- package/lib/util/types.js +25 -0
- package/lib/util/validate-notification-arn.d.ts +4 -0
- package/lib/util/validate-notification-arn.js +10 -0
- package/lib/util/version-range.d.ts +2 -0
- package/lib/util/version-range.js +36 -0
- package/lib/util/work-graph-builder.d.ts +32 -0
- package/lib/util/work-graph-builder.js +167 -0
- package/lib/util/work-graph-types.d.ts +50 -0
- package/lib/util/work-graph-types.js +14 -0
- package/lib/util/work-graph.d.ts +70 -0
- package/lib/util/work-graph.js +344 -0
- package/lib/util/yaml-cfn.d.ts +15 -0
- package/lib/util/yaml-cfn.js +56 -0
- package/package.json +197 -0
- package/scripts/user-input-gen +2 -0
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CurrentActivityPrinter = exports.HistoryActivityPrinter = exports.StackActivityMonitor = exports.StackActivityProgress = void 0;
|
|
4
|
+
const util = require("util");
|
|
5
|
+
const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema");
|
|
6
|
+
const chalk = require("chalk");
|
|
7
|
+
const stack_event_poller_1 = require("./stack-event-poller");
|
|
8
|
+
const logging_1 = require("../../../logging");
|
|
9
|
+
const cli_io_host_1 = require("../../../toolkit/cli-io-host");
|
|
10
|
+
const display_1 = require("../display");
|
|
11
|
+
/**
|
|
12
|
+
* Supported display modes for stack deployment activity
|
|
13
|
+
*/
|
|
14
|
+
var StackActivityProgress;
|
|
15
|
+
(function (StackActivityProgress) {
|
|
16
|
+
/**
|
|
17
|
+
* Displays a progress bar with only the events for the resource currently being deployed
|
|
18
|
+
*/
|
|
19
|
+
StackActivityProgress["BAR"] = "bar";
|
|
20
|
+
/**
|
|
21
|
+
* Displays complete history with all CloudFormation stack events
|
|
22
|
+
*/
|
|
23
|
+
StackActivityProgress["EVENTS"] = "events";
|
|
24
|
+
})(StackActivityProgress || (exports.StackActivityProgress = StackActivityProgress = {}));
|
|
25
|
+
class StackActivityMonitor {
|
|
26
|
+
/**
|
|
27
|
+
* Create a Stack Activity Monitor using a default printer, based on context clues
|
|
28
|
+
*/
|
|
29
|
+
static withDefaultPrinter(cfn, stackName, stackArtifact, options = {}) {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
const stream = options.ci ? process.stdout : process.stderr;
|
|
32
|
+
const props = {
|
|
33
|
+
resourceTypeColumnWidth: calcMaxResourceTypeLength(stackArtifact.template),
|
|
34
|
+
resourcesTotal: options.resourcesTotal,
|
|
35
|
+
stream,
|
|
36
|
+
};
|
|
37
|
+
const isWindows = process.platform === 'win32';
|
|
38
|
+
const verbose = (_a = options.logLevel) !== null && _a !== void 0 ? _a : 'info';
|
|
39
|
+
// On some CI systems (such as CircleCI) output still reports as a TTY so we also
|
|
40
|
+
// need an individual check for whether we're running on CI.
|
|
41
|
+
// see: https://discuss.circleci.com/t/circleci-terminal-is-a-tty-but-term-is-not-set/9965
|
|
42
|
+
const fancyOutputAvailable = !isWindows && stream.isTTY && !options.ci;
|
|
43
|
+
const progress = (_b = options.progress) !== null && _b !== void 0 ? _b : StackActivityProgress.BAR;
|
|
44
|
+
const printer = fancyOutputAvailable && !verbose && progress === StackActivityProgress.BAR
|
|
45
|
+
? new CurrentActivityPrinter(props)
|
|
46
|
+
: new HistoryActivityPrinter(props);
|
|
47
|
+
return new StackActivityMonitor(cfn, stackName, printer, stackArtifact, options.changeSetCreationTime);
|
|
48
|
+
}
|
|
49
|
+
constructor(cfn, stackName, printer, stack, changeSetCreationTime) {
|
|
50
|
+
var _a;
|
|
51
|
+
this.stackName = stackName;
|
|
52
|
+
this.printer = printer;
|
|
53
|
+
this.stack = stack;
|
|
54
|
+
this.errors = [];
|
|
55
|
+
this.active = false;
|
|
56
|
+
this.poller = new stack_event_poller_1.StackEventPoller(cfn, {
|
|
57
|
+
stackName,
|
|
58
|
+
startTime: (_a = changeSetCreationTime === null || changeSetCreationTime === void 0 ? void 0 : changeSetCreationTime.getTime()) !== null && _a !== void 0 ? _a : Date.now(),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
start() {
|
|
62
|
+
this.active = true;
|
|
63
|
+
this.printer.start();
|
|
64
|
+
this.scheduleNextTick();
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
async stop() {
|
|
68
|
+
this.active = false;
|
|
69
|
+
if (this.tickTimer) {
|
|
70
|
+
clearTimeout(this.tickTimer);
|
|
71
|
+
}
|
|
72
|
+
// Do a final poll for all events. This is to handle the situation where DescribeStackStatus
|
|
73
|
+
// already returned an error, but the monitor hasn't seen all the events yet and we'd end
|
|
74
|
+
// up not printing the failure reason to users.
|
|
75
|
+
await this.finalPollToEnd();
|
|
76
|
+
this.printer.stop();
|
|
77
|
+
}
|
|
78
|
+
scheduleNextTick() {
|
|
79
|
+
if (!this.active) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.tickTimer = setTimeout(() => void this.tick(), this.printer.updateSleep);
|
|
83
|
+
}
|
|
84
|
+
async tick() {
|
|
85
|
+
if (!this.active) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
this.readPromise = this.readNewEvents();
|
|
90
|
+
await this.readPromise;
|
|
91
|
+
this.readPromise = undefined;
|
|
92
|
+
// We might have been stop()ped while the network call was in progress.
|
|
93
|
+
if (!this.active) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this.printer.print();
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
(0, logging_1.error)('Error occurred while monitoring stack: %s', e);
|
|
100
|
+
}
|
|
101
|
+
this.scheduleNextTick();
|
|
102
|
+
}
|
|
103
|
+
findMetadataFor(logicalId) {
|
|
104
|
+
var _a, _b;
|
|
105
|
+
const metadata = (_b = (_a = this.stack) === null || _a === void 0 ? void 0 : _a.manifest) === null || _b === void 0 ? void 0 : _b.metadata;
|
|
106
|
+
if (!logicalId || !metadata) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
for (const path of Object.keys(metadata)) {
|
|
110
|
+
const entry = metadata[path]
|
|
111
|
+
.filter((e) => e.type === cloud_assembly_schema_1.ArtifactMetadataEntryType.LOGICAL_ID)
|
|
112
|
+
.find((e) => e.data === logicalId);
|
|
113
|
+
if (entry) {
|
|
114
|
+
return {
|
|
115
|
+
entry,
|
|
116
|
+
constructPath: this.simplifyConstructPath(path),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Reads all new events from the stack history
|
|
124
|
+
*
|
|
125
|
+
* The events are returned in reverse chronological order; we continue to the next page if we
|
|
126
|
+
* see a next page and the last event in the page is new to us (and within the time window).
|
|
127
|
+
* haven't seen the final event
|
|
128
|
+
*/
|
|
129
|
+
async readNewEvents() {
|
|
130
|
+
const pollEvents = await this.poller.poll();
|
|
131
|
+
const activities = pollEvents.map((event) => ({
|
|
132
|
+
...event,
|
|
133
|
+
metadata: this.findMetadataFor(event.event.LogicalResourceId),
|
|
134
|
+
}));
|
|
135
|
+
for (const activity of activities) {
|
|
136
|
+
this.checkForErrors(activity);
|
|
137
|
+
this.printer.addActivity(activity);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Perform a final poll to the end and flush out all events to the printer
|
|
142
|
+
*
|
|
143
|
+
* Finish any poll currently in progress, then do a final one until we've
|
|
144
|
+
* reached the last page.
|
|
145
|
+
*/
|
|
146
|
+
async finalPollToEnd() {
|
|
147
|
+
// If we were doing a poll, finish that first. It was started before
|
|
148
|
+
// the moment we were sure we weren't going to get any new events anymore
|
|
149
|
+
// so we need to do a new one anyway. Need to wait for this one though
|
|
150
|
+
// because our state is single-threaded.
|
|
151
|
+
if (this.readPromise) {
|
|
152
|
+
await this.readPromise;
|
|
153
|
+
}
|
|
154
|
+
await this.readNewEvents();
|
|
155
|
+
}
|
|
156
|
+
checkForErrors(activity) {
|
|
157
|
+
var _a, _b, _c;
|
|
158
|
+
if (hasErrorMessage((_a = activity.event.ResourceStatus) !== null && _a !== void 0 ? _a : '')) {
|
|
159
|
+
const isCancelled = ((_b = activity.event.ResourceStatusReason) !== null && _b !== void 0 ? _b : '').indexOf('cancelled') > -1;
|
|
160
|
+
// Cancelled is not an interesting failure reason, nor is the stack message (stack
|
|
161
|
+
// message will just say something like "stack failed to update")
|
|
162
|
+
if (!isCancelled && activity.event.StackName !== activity.event.LogicalResourceId) {
|
|
163
|
+
this.errors.push((_c = activity.event.ResourceStatusReason) !== null && _c !== void 0 ? _c : '');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
simplifyConstructPath(path) {
|
|
168
|
+
path = path.replace(/\/Resource$/, '');
|
|
169
|
+
path = path.replace(/^\//, ''); // remove "/" prefix
|
|
170
|
+
// remove "<stack-name>/" prefix
|
|
171
|
+
if (path.startsWith(this.stackName + '/')) {
|
|
172
|
+
path = path.slice(this.stackName.length + 1);
|
|
173
|
+
}
|
|
174
|
+
return path;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.StackActivityMonitor = StackActivityMonitor;
|
|
178
|
+
function padRight(n, x) {
|
|
179
|
+
return x + ' '.repeat(Math.max(0, n - x.length));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Infamous padLeft()
|
|
183
|
+
*/
|
|
184
|
+
function padLeft(n, x) {
|
|
185
|
+
return ' '.repeat(Math.max(0, n - x.length)) + x;
|
|
186
|
+
}
|
|
187
|
+
function calcMaxResourceTypeLength(template) {
|
|
188
|
+
const resources = (template && template.Resources) || {};
|
|
189
|
+
let maxWidth = 0;
|
|
190
|
+
for (const id of Object.keys(resources)) {
|
|
191
|
+
const type = resources[id].Type || '';
|
|
192
|
+
if (type.length > maxWidth) {
|
|
193
|
+
maxWidth = type.length;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return maxWidth;
|
|
197
|
+
}
|
|
198
|
+
class ActivityPrinterBase {
|
|
199
|
+
constructor(props) {
|
|
200
|
+
this.props = props;
|
|
201
|
+
/**
|
|
202
|
+
* Fetch new activity every 5 seconds
|
|
203
|
+
*/
|
|
204
|
+
this.updateSleep = 5000;
|
|
205
|
+
/**
|
|
206
|
+
* A list of resource IDs which are currently being processed
|
|
207
|
+
*/
|
|
208
|
+
this.resourcesInProgress = {};
|
|
209
|
+
/**
|
|
210
|
+
* Previous completion state observed by logical ID
|
|
211
|
+
*
|
|
212
|
+
* We use this to detect that if we see a DELETE_COMPLETE after a
|
|
213
|
+
* CREATE_COMPLETE, it's actually a rollback and we should DECREASE
|
|
214
|
+
* resourcesDone instead of increase it
|
|
215
|
+
*/
|
|
216
|
+
this.resourcesPrevCompleteState = {};
|
|
217
|
+
/**
|
|
218
|
+
* Count of resources that have reported a _COMPLETE status
|
|
219
|
+
*/
|
|
220
|
+
this.resourcesDone = 0;
|
|
221
|
+
/**
|
|
222
|
+
* How many digits we need to represent the total count (for lining up the status reporting)
|
|
223
|
+
*/
|
|
224
|
+
this.resourceDigits = 0;
|
|
225
|
+
this.rollingBack = false;
|
|
226
|
+
this.failures = new Array();
|
|
227
|
+
this.hookFailureMap = new Map();
|
|
228
|
+
// +1 because the stack also emits a "COMPLETE" event at the end, and that wasn't
|
|
229
|
+
// counted yet. This makes it line up with the amount of events we expect.
|
|
230
|
+
this.resourcesTotal = props.resourcesTotal ? props.resourcesTotal + 1 : undefined;
|
|
231
|
+
// How many digits does this number take to represent?
|
|
232
|
+
this.resourceDigits = this.resourcesTotal ? Math.ceil(Math.log10(this.resourcesTotal)) : 0;
|
|
233
|
+
}
|
|
234
|
+
failureReason(activity) {
|
|
235
|
+
var _a, _b;
|
|
236
|
+
const resourceStatusReason = (_a = activity.event.ResourceStatusReason) !== null && _a !== void 0 ? _a : '';
|
|
237
|
+
const logicalResourceId = (_b = activity.event.LogicalResourceId) !== null && _b !== void 0 ? _b : '';
|
|
238
|
+
const hookFailureReasonMap = this.hookFailureMap.get(logicalResourceId);
|
|
239
|
+
if (hookFailureReasonMap !== undefined) {
|
|
240
|
+
for (const hookType of hookFailureReasonMap.keys()) {
|
|
241
|
+
if (resourceStatusReason.includes(hookType)) {
|
|
242
|
+
return resourceStatusReason + ' : ' + hookFailureReasonMap.get(hookType);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return resourceStatusReason;
|
|
247
|
+
}
|
|
248
|
+
addActivity(activity) {
|
|
249
|
+
var _a, _b, _c, _d, _e;
|
|
250
|
+
const status = activity.event.ResourceStatus;
|
|
251
|
+
const hookStatus = activity.event.HookStatus;
|
|
252
|
+
const hookType = activity.event.HookType;
|
|
253
|
+
if (!status || !activity.event.LogicalResourceId) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (status === 'ROLLBACK_IN_PROGRESS' || status === 'UPDATE_ROLLBACK_IN_PROGRESS') {
|
|
257
|
+
// Only triggered on the stack once we've started doing a rollback
|
|
258
|
+
this.rollingBack = true;
|
|
259
|
+
}
|
|
260
|
+
if (status.endsWith('_IN_PROGRESS')) {
|
|
261
|
+
this.resourcesInProgress[activity.event.LogicalResourceId] = activity;
|
|
262
|
+
}
|
|
263
|
+
if (hasErrorMessage(status)) {
|
|
264
|
+
const isCancelled = ((_a = activity.event.ResourceStatusReason) !== null && _a !== void 0 ? _a : '').indexOf('cancelled') > -1;
|
|
265
|
+
// Cancelled is not an interesting failure reason
|
|
266
|
+
if (!isCancelled) {
|
|
267
|
+
this.failures.push(activity);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (status.endsWith('_COMPLETE') || status.endsWith('_FAILED')) {
|
|
271
|
+
delete this.resourcesInProgress[activity.event.LogicalResourceId];
|
|
272
|
+
}
|
|
273
|
+
if (status.endsWith('_COMPLETE_CLEANUP_IN_PROGRESS')) {
|
|
274
|
+
this.resourcesDone++;
|
|
275
|
+
}
|
|
276
|
+
if (status.endsWith('_COMPLETE')) {
|
|
277
|
+
const prevState = this.resourcesPrevCompleteState[activity.event.LogicalResourceId];
|
|
278
|
+
if (!prevState) {
|
|
279
|
+
this.resourcesDone++;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
// If we completed this before and we're completing it AGAIN, means we're rolling back.
|
|
283
|
+
// Protect against silly underflow.
|
|
284
|
+
this.resourcesDone--;
|
|
285
|
+
if (this.resourcesDone < 0) {
|
|
286
|
+
this.resourcesDone = 0;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
this.resourcesPrevCompleteState[activity.event.LogicalResourceId] = status;
|
|
290
|
+
}
|
|
291
|
+
if (hookStatus !== undefined &&
|
|
292
|
+
hookStatus.endsWith('_COMPLETE_FAILED') &&
|
|
293
|
+
activity.event.LogicalResourceId !== undefined &&
|
|
294
|
+
hookType !== undefined) {
|
|
295
|
+
if (this.hookFailureMap.has(activity.event.LogicalResourceId)) {
|
|
296
|
+
(_b = this.hookFailureMap.get(activity.event.LogicalResourceId)) === null || _b === void 0 ? void 0 : _b.set(hookType, (_c = activity.event.HookStatusReason) !== null && _c !== void 0 ? _c : '');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this.hookFailureMap.set(activity.event.LogicalResourceId, new Map());
|
|
300
|
+
(_d = this.hookFailureMap.get(activity.event.LogicalResourceId)) === null || _d === void 0 ? void 0 : _d.set(hookType, (_e = activity.event.HookStatusReason) !== null && _e !== void 0 ? _e : '');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
start() {
|
|
305
|
+
// Empty on purpose
|
|
306
|
+
}
|
|
307
|
+
stop() {
|
|
308
|
+
// Empty on purpose
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Activity Printer which shows a full log of all CloudFormation events
|
|
313
|
+
*
|
|
314
|
+
* When there hasn't been activity for a while, it will print the resources
|
|
315
|
+
* that are currently in progress, to show what's holding up the deployment.
|
|
316
|
+
*/
|
|
317
|
+
class HistoryActivityPrinter extends ActivityPrinterBase {
|
|
318
|
+
constructor(props) {
|
|
319
|
+
super(props);
|
|
320
|
+
/**
|
|
321
|
+
* Last time we printed something to the console.
|
|
322
|
+
*
|
|
323
|
+
* Used to measure timeout for progress reporting.
|
|
324
|
+
*/
|
|
325
|
+
this.lastPrintTime = Date.now();
|
|
326
|
+
/**
|
|
327
|
+
* Number of ms of change absence before we tell the user about the resources that are currently in progress.
|
|
328
|
+
*/
|
|
329
|
+
this.inProgressDelay = 30000;
|
|
330
|
+
this.printable = new Array();
|
|
331
|
+
}
|
|
332
|
+
addActivity(activity) {
|
|
333
|
+
super.addActivity(activity);
|
|
334
|
+
this.printable.push(activity);
|
|
335
|
+
this.print();
|
|
336
|
+
}
|
|
337
|
+
print() {
|
|
338
|
+
for (const activity of this.printable) {
|
|
339
|
+
this.printOne(activity);
|
|
340
|
+
}
|
|
341
|
+
this.printable.splice(0, this.printable.length);
|
|
342
|
+
this.printInProgress();
|
|
343
|
+
}
|
|
344
|
+
stop() {
|
|
345
|
+
// Print failures at the end
|
|
346
|
+
if (this.failures.length > 0) {
|
|
347
|
+
(0, logging_1.info)('\nFailed resources:');
|
|
348
|
+
for (const failure of this.failures) {
|
|
349
|
+
// Root stack failures are not interesting
|
|
350
|
+
if (failure.isStackEvent) {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
this.printOne(failure, false);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
printOne(activity, progress) {
|
|
358
|
+
const event = activity.event;
|
|
359
|
+
const color = colorFromStatusResult(event.ResourceStatus);
|
|
360
|
+
let reasonColor = chalk.cyan;
|
|
361
|
+
let stackTrace = '';
|
|
362
|
+
const metadata = activity.metadata;
|
|
363
|
+
if (event.ResourceStatus && event.ResourceStatus.indexOf('FAILED') !== -1) {
|
|
364
|
+
if (progress == undefined || progress) {
|
|
365
|
+
event.ResourceStatusReason = event.ResourceStatusReason ? this.failureReason(activity) : '';
|
|
366
|
+
}
|
|
367
|
+
if (metadata) {
|
|
368
|
+
stackTrace = metadata.entry.trace ? `\n\t${metadata.entry.trace.join('\n\t\\_ ')}` : '';
|
|
369
|
+
}
|
|
370
|
+
reasonColor = chalk.red;
|
|
371
|
+
}
|
|
372
|
+
const resourceName = metadata ? metadata.constructPath : event.LogicalResourceId || '';
|
|
373
|
+
const logicalId = resourceName !== event.LogicalResourceId ? `(${event.LogicalResourceId}) ` : '';
|
|
374
|
+
(0, logging_1.info)(util.format('%s | %s%s | %s | %s | %s %s%s%s', event.StackName, progress !== false ? `${this.progress()} | ` : '', new Date(event.Timestamp).toLocaleTimeString(), color(padRight(STATUS_WIDTH, (event.ResourceStatus || '').slice(0, STATUS_WIDTH))), // pad left and trim
|
|
375
|
+
padRight(this.props.resourceTypeColumnWidth, event.ResourceType || ''), color(chalk.bold(resourceName)), logicalId, reasonColor(chalk.bold(event.ResourceStatusReason ? event.ResourceStatusReason : '')), reasonColor(stackTrace)));
|
|
376
|
+
this.lastPrintTime = Date.now();
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Report the current progress as a [34/42] string, or just [34] if the total is unknown
|
|
380
|
+
*/
|
|
381
|
+
progress() {
|
|
382
|
+
if (this.resourcesTotal == null) {
|
|
383
|
+
// Don't have total, show simple count and hope the human knows
|
|
384
|
+
return padLeft(3, util.format('%s', this.resourcesDone)); // max 500 resources
|
|
385
|
+
}
|
|
386
|
+
return util.format('%s/%s', padLeft(this.resourceDigits, this.resourcesDone.toString()), padLeft(this.resourceDigits, this.resourcesTotal != null ? this.resourcesTotal.toString() : '?'));
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* If some resources are taking a while to create, notify the user about what's currently in progress
|
|
390
|
+
*/
|
|
391
|
+
printInProgress() {
|
|
392
|
+
if (Date.now() < this.lastPrintTime + this.inProgressDelay) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (Object.keys(this.resourcesInProgress).length > 0) {
|
|
396
|
+
(0, logging_1.info)(util.format('%s Currently in progress: %s', this.progress(), chalk.bold(Object.keys(this.resourcesInProgress).join(', '))));
|
|
397
|
+
}
|
|
398
|
+
// We cheat a bit here. To prevent printInProgress() from repeatedly triggering,
|
|
399
|
+
// we set the timestamp into the future. It will be reset whenever a regular print
|
|
400
|
+
// occurs, after which we can be triggered again.
|
|
401
|
+
this.lastPrintTime = +Infinity;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
exports.HistoryActivityPrinter = HistoryActivityPrinter;
|
|
405
|
+
/**
|
|
406
|
+
* Activity Printer which shows the resources currently being updated
|
|
407
|
+
*
|
|
408
|
+
* It will continuously reupdate the terminal and show only the resources
|
|
409
|
+
* that are currently being updated, in addition to a progress bar which
|
|
410
|
+
* shows how far along the deployment is.
|
|
411
|
+
*
|
|
412
|
+
* Resources that have failed will always be shown, and will be recapitulated
|
|
413
|
+
* along with their stack trace when the monitoring ends.
|
|
414
|
+
*
|
|
415
|
+
* Resources that failed deployment because they have been cancelled are
|
|
416
|
+
* not included.
|
|
417
|
+
*/
|
|
418
|
+
class CurrentActivityPrinter extends ActivityPrinterBase {
|
|
419
|
+
constructor(props) {
|
|
420
|
+
super(props);
|
|
421
|
+
/**
|
|
422
|
+
* This looks very disorienting sleeping for 5 seconds. Update quicker.
|
|
423
|
+
*/
|
|
424
|
+
this.updateSleep = 2000;
|
|
425
|
+
this.oldLogThreshold = cli_io_host_1.CliIoHost.instance().logLevel;
|
|
426
|
+
this.stream = props.stream;
|
|
427
|
+
this.block = new display_1.RewritableBlock(this.stream);
|
|
428
|
+
}
|
|
429
|
+
print() {
|
|
430
|
+
var _a;
|
|
431
|
+
const lines = [];
|
|
432
|
+
// Add a progress bar at the top
|
|
433
|
+
const progressWidth = Math.max(Math.min(((_a = this.block.width) !== null && _a !== void 0 ? _a : 80) - PROGRESSBAR_EXTRA_SPACE - 1, MAX_PROGRESSBAR_WIDTH), MIN_PROGRESSBAR_WIDTH);
|
|
434
|
+
const prog = this.progressBar(progressWidth);
|
|
435
|
+
if (prog) {
|
|
436
|
+
lines.push(' ' + prog, '');
|
|
437
|
+
}
|
|
438
|
+
// Normally we'd only print "resources in progress", but it's also useful
|
|
439
|
+
// to keep an eye on the failures and know about the specific errors asquickly
|
|
440
|
+
// as possible (while the stack is still rolling back), so add those in.
|
|
441
|
+
const toPrint = [...this.failures, ...Object.values(this.resourcesInProgress)];
|
|
442
|
+
toPrint.sort((a, b) => a.event.Timestamp.getTime() - b.event.Timestamp.getTime());
|
|
443
|
+
lines.push(...toPrint.map((res) => {
|
|
444
|
+
var _a, _b, _c;
|
|
445
|
+
const color = colorFromStatusActivity(res.event.ResourceStatus);
|
|
446
|
+
const resourceName = (_c = (_b = (_a = res.metadata) === null || _a === void 0 ? void 0 : _a.constructPath) !== null && _b !== void 0 ? _b : res.event.LogicalResourceId) !== null && _c !== void 0 ? _c : '';
|
|
447
|
+
return util.format('%s | %s | %s | %s%s', padLeft(TIMESTAMP_WIDTH, new Date(res.event.Timestamp).toLocaleTimeString()), color(padRight(STATUS_WIDTH, (res.event.ResourceStatus || '').slice(0, STATUS_WIDTH))), padRight(this.props.resourceTypeColumnWidth, res.event.ResourceType || ''), color(chalk.bold(shorten(40, resourceName))), this.failureReasonOnNextLine(res));
|
|
448
|
+
}));
|
|
449
|
+
this.block.displayLines(lines);
|
|
450
|
+
}
|
|
451
|
+
start() {
|
|
452
|
+
// Need to prevent the waiter from printing 'stack not stable' every 5 seconds, it messes
|
|
453
|
+
// with the output calculations.
|
|
454
|
+
this.oldLogThreshold = cli_io_host_1.CliIoHost.instance().logLevel;
|
|
455
|
+
cli_io_host_1.CliIoHost.instance().logLevel = 'info';
|
|
456
|
+
}
|
|
457
|
+
stop() {
|
|
458
|
+
var _a, _b, _c;
|
|
459
|
+
cli_io_host_1.CliIoHost.instance().logLevel = this.oldLogThreshold;
|
|
460
|
+
// Print failures at the end
|
|
461
|
+
const lines = new Array();
|
|
462
|
+
for (const failure of this.failures) {
|
|
463
|
+
// Root stack failures are not interesting
|
|
464
|
+
if (failure.isStackEvent) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
lines.push(util.format(chalk.red('%s | %s | %s | %s%s') + '\n', padLeft(TIMESTAMP_WIDTH, new Date(failure.event.Timestamp).toLocaleTimeString()), padRight(STATUS_WIDTH, (failure.event.ResourceStatus || '').slice(0, STATUS_WIDTH)), padRight(this.props.resourceTypeColumnWidth, failure.event.ResourceType || ''), shorten(40, (_a = failure.event.LogicalResourceId) !== null && _a !== void 0 ? _a : ''), this.failureReasonOnNextLine(failure)));
|
|
468
|
+
const trace = (_c = (_b = failure.metadata) === null || _b === void 0 ? void 0 : _b.entry) === null || _c === void 0 ? void 0 : _c.trace;
|
|
469
|
+
if (trace) {
|
|
470
|
+
lines.push(chalk.red(`\t${trace.join('\n\t\\_ ')}\n`));
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
// Display in the same block space, otherwise we're going to have silly empty lines.
|
|
474
|
+
this.block.displayLines(lines);
|
|
475
|
+
this.block.removeEmptyLines();
|
|
476
|
+
}
|
|
477
|
+
progressBar(width) {
|
|
478
|
+
if (!this.resourcesTotal) {
|
|
479
|
+
return '';
|
|
480
|
+
}
|
|
481
|
+
const fraction = Math.min(this.resourcesDone / this.resourcesTotal, 1);
|
|
482
|
+
const innerWidth = Math.max(1, width - 2);
|
|
483
|
+
const chars = innerWidth * fraction;
|
|
484
|
+
const remainder = chars - Math.floor(chars);
|
|
485
|
+
const fullChars = FULL_BLOCK.repeat(Math.floor(chars));
|
|
486
|
+
const partialChar = PARTIAL_BLOCK[Math.floor(remainder * PARTIAL_BLOCK.length)];
|
|
487
|
+
const filler = '·'.repeat(innerWidth - Math.floor(chars) - (partialChar ? 1 : 0));
|
|
488
|
+
const color = this.rollingBack ? chalk.yellow : chalk.green;
|
|
489
|
+
return '[' + color(fullChars + partialChar) + filler + `] (${this.resourcesDone}/${this.resourcesTotal})`;
|
|
490
|
+
}
|
|
491
|
+
failureReasonOnNextLine(activity) {
|
|
492
|
+
var _a, _b;
|
|
493
|
+
return hasErrorMessage((_a = activity.event.ResourceStatus) !== null && _a !== void 0 ? _a : '')
|
|
494
|
+
? `\n${' '.repeat(TIMESTAMP_WIDTH + STATUS_WIDTH + 6)}${chalk.red((_b = this.failureReason(activity)) !== null && _b !== void 0 ? _b : '')}`
|
|
495
|
+
: '';
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
exports.CurrentActivityPrinter = CurrentActivityPrinter;
|
|
499
|
+
const FULL_BLOCK = '█';
|
|
500
|
+
const PARTIAL_BLOCK = ['', '▏', '▎', '▍', '▌', '▋', '▊', '▉'];
|
|
501
|
+
const MAX_PROGRESSBAR_WIDTH = 60;
|
|
502
|
+
const MIN_PROGRESSBAR_WIDTH = 10;
|
|
503
|
+
const PROGRESSBAR_EXTRA_SPACE = 2 /* leading spaces */ + 2 /* brackets */ + 4 /* progress number decoration */ + 6; /* 2 progress numbers up to 999 */
|
|
504
|
+
function hasErrorMessage(status) {
|
|
505
|
+
return status.endsWith('_FAILED') || status === 'ROLLBACK_IN_PROGRESS' || status === 'UPDATE_ROLLBACK_IN_PROGRESS';
|
|
506
|
+
}
|
|
507
|
+
function colorFromStatusResult(status) {
|
|
508
|
+
if (!status) {
|
|
509
|
+
return chalk.reset;
|
|
510
|
+
}
|
|
511
|
+
if (status.indexOf('FAILED') !== -1) {
|
|
512
|
+
return chalk.red;
|
|
513
|
+
}
|
|
514
|
+
if (status.indexOf('ROLLBACK') !== -1) {
|
|
515
|
+
return chalk.yellow;
|
|
516
|
+
}
|
|
517
|
+
if (status.indexOf('COMPLETE') !== -1) {
|
|
518
|
+
return chalk.green;
|
|
519
|
+
}
|
|
520
|
+
return chalk.reset;
|
|
521
|
+
}
|
|
522
|
+
function colorFromStatusActivity(status) {
|
|
523
|
+
if (!status) {
|
|
524
|
+
return chalk.reset;
|
|
525
|
+
}
|
|
526
|
+
if (status.endsWith('_FAILED')) {
|
|
527
|
+
return chalk.red;
|
|
528
|
+
}
|
|
529
|
+
if (status.startsWith('CREATE_') || status.startsWith('UPDATE_') || status.startsWith('IMPORT_')) {
|
|
530
|
+
return chalk.green;
|
|
531
|
+
}
|
|
532
|
+
// For stacks, it may also be 'UPDDATE_ROLLBACK_IN_PROGRESS'
|
|
533
|
+
if (status.indexOf('ROLLBACK_') !== -1) {
|
|
534
|
+
return chalk.yellow;
|
|
535
|
+
}
|
|
536
|
+
if (status.startsWith('DELETE_')) {
|
|
537
|
+
return chalk.yellow;
|
|
538
|
+
}
|
|
539
|
+
return chalk.reset;
|
|
540
|
+
}
|
|
541
|
+
function shorten(maxWidth, p) {
|
|
542
|
+
if (p.length <= maxWidth) {
|
|
543
|
+
return p;
|
|
544
|
+
}
|
|
545
|
+
const half = Math.floor((maxWidth - 3) / 2);
|
|
546
|
+
return p.slice(0, half) + '...' + p.slice(-half);
|
|
547
|
+
}
|
|
548
|
+
const TIMESTAMP_WIDTH = 12;
|
|
549
|
+
const STATUS_WIDTH = 20;
|
|
550
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stYWN0aXZpdHktbW9uaXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInN0YWNrLWFjdGl2aXR5LW1vbml0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTZCO0FBQzdCLDBFQUErRjtBQUUvRiwrQkFBK0I7QUFDL0IsNkRBQXVFO0FBQ3ZFLDhDQUErQztBQUMvQyw4REFBeUU7QUFFekUsd0NBQTZDO0FBVzdDOztHQUVHO0FBQ0gsSUFBWSxxQkFVWDtBQVZELFdBQVkscUJBQXFCO0lBQy9COztPQUVHO0lBQ0gsb0NBQVcsQ0FBQTtJQUVYOztPQUVHO0lBQ0gsMENBQWlCLENBQUE7QUFDbkIsQ0FBQyxFQVZXLHFCQUFxQixxQ0FBckIscUJBQXFCLFFBVWhDO0FBc0RELE1BQWEsb0JBQW9CO0lBQy9COztPQUVHO0lBQ0ksTUFBTSxDQUFDLGtCQUFrQixDQUM5QixHQUEwQixFQUMxQixTQUFpQixFQUNqQixhQUEwQyxFQUMxQyxVQUFtQyxFQUFFOztRQUVyQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBRTVELE1BQU0sS0FBSyxHQUFpQjtZQUMxQix1QkFBdUIsRUFBRSx5QkFBeUIsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO1lBQzFFLGNBQWMsRUFBRSxPQUFPLENBQUMsY0FBYztZQUN0QyxNQUFNO1NBQ1AsQ0FBQztRQUVGLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxDQUFDO1FBQy9DLE1BQU0sT0FBTyxHQUFHLE1BQUEsT0FBTyxDQUFDLFFBQVEsbUNBQUksTUFBTSxDQUFDO1FBQzNDLGlGQUFpRjtRQUNqRiw0REFBNEQ7UUFDNUQsMEZBQTBGO1FBQzFGLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxD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QUFVLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUNqRyxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFDckIsQ0FBQztJQUNELDREQUE0RDtJQUM1RCxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN2QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDdEIsQ0FBQztJQUNELElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUN0QixDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDO0FBQ3JCLENBQUM7QUFFRCxTQUFTLE9BQU8sQ0FBQyxRQUFnQixFQUFFLENBQVM7SUFDMUMsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ3pCLE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUNELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCxNQUFNLGVBQWUsR0FBRyxFQUFFLENBQUM7QUFDM0IsTUFBTSxZQUFZLEdBQUcsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgdXRpbCBmcm9tICd1dGlsJztcbmltcG9ydCB7IEFydGlmYWN0TWV0YWRhdGFFbnRyeVR5cGUsIHR5cGUgTWV0YWRhdGFFbnRyeSB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgdHlwZSB7IENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgKiBhcyBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQgeyBSZXNvdXJjZUV2ZW50LCBTdGFja0V2ZW50UG9sbGVyIH0gZnJvbSAnLi9zdGFjay1ldmVudC1wb2xsZXInO1xuaW1wb3J0IHsgZXJyb3IsIGluZm8gfSBmcm9tICcuLi8uLi8uLi9sb2dnaW5nJztcbmltcG9ydCB7IENsaUlvSG9zdCwgSW9NZXNzYWdlTGV2ZWwgfSBmcm9tICcuLi8uLi8uLi90b29sa2l0L2NsaS1pby1ob3N0JztcbmltcG9ydCB0eXBlIHsgSUNsb3VkRm9ybWF0aW9uQ2xpZW50IH0gZnJvbSAnLi4vLi4vYXdzLWF1dGgnO1xuaW1wb3J0IHsgUmV3cml0YWJsZUJsb2NrIH0gZnJvbSAnLi4vZGlzcGxheSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2tBY3Rpdml0eSBleHRlbmRzIFJlc291cmNlRXZlbnQge1xuICByZWFkb25seSBtZXRhZGF0YT86IFJlc291cmNlTWV0YWRhdGE7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VNZXRhZGF0YSB7XG4gIGVudHJ5OiBNZXRhZGF0YUVudHJ5O1xuICBjb25zdHJ1Y3RQYXRoOiBzdHJpbmc7XG59XG5cbi8qKlxuICogU3VwcG9ydGVkIGRpc3BsYXkgbW9kZXMgZm9yIHN0YWNrIGRlcGxveW1lbnQgYWN0aXZpdHlcbiAqL1xuZXhwb3J0IGVudW0gU3RhY2tBY3Rpdml0eVByb2dyZXNzIHtcbiAgLyoqXG4gICAqIERpc3BsYXlzIGEgcHJvZ3Jlc3MgYmFyIHdpdGggb25seSB0aGUgZXZlbnRzIGZvciB0aGUgcmVzb3VyY2UgY3VycmVudGx5IGJlaW5nIGRlcGxveWVkXG4gICAqL1xuICBCQVIgPSAnYmFyJyxcblxuICAvKipcbiAgICogRGlzcGxheXMgY29tcGxldGUgaGlzdG9yeSB3aXRoIGFsbCBDbG91ZEZvcm1hdGlvbiBzdGFjayBldmVudHNcbiAgICovXG4gIEVWRU5UUyA9ICdldmVudHMnLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdpdGhEZWZhdWx0UHJpbnRlclByb3BzIHtcbiAgLyoqXG4gICAqIFRvdGFsIG51bWJlciBvZiByZXNvdXJjZXMgdG8gdXBkYXRlXG4gICAqXG4gICAqIFVzZWQgdG8gY2FsY3VsYXRlIGEgcHJvZ3Jlc3MgYmFyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHByb2dyZXNzIHJlcG9ydGluZy5cbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlc1RvdGFsPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbG9nIGxldmVsIHRoYXQgd2FzIHJlcXVlc3RlZCBpbiB0aGUgQ0xJXG4gICAqXG4gICAqIElmIHZlcmJvc2Ugb3IgdHJhY2UgaXMgcmVxdWVzdGVkLCB3ZSdsbCBhbHdheXMgdXNlIHRoZSBmdWxsIGhpc3RvcnkgcHJpbnRlci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBVc2UgdmFsdWUgZnJvbSBsb2dnaW5nLmxvZ0xldmVsXG4gICAqL1xuICByZWFkb25seSBsb2dMZXZlbD86IElvTWVzc2FnZUxldmVsO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGRpc3BsYXkgYWxsIHN0YWNrIGV2ZW50cyBvciB0byBkaXNwbGF5IG9ubHkgdGhlIGV2ZW50cyBmb3IgdGhlXG4gICAqIHJlc291cmNlIGN1cnJlbnRseSBiZWluZyBkZXBsb3llZFxuICAgKlxuICAgKiBJZiBub3Qgc2V0LCB0aGUgc3RhY2sgaGlzdG9yeSB3aXRoIGFsbCBzdGFjayBldmVudHMgd2lsbCBiZSBkaXNwbGF5ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHByb2dyZXNzPzogU3RhY2tBY3Rpdml0eVByb2dyZXNzO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHdlIGFyZSBvbiBhIENJIHN5c3RlbVxuICAgKlxuICAgKiBJZiBzbywgZGlzYWJsZSB0aGUgXCJvcHRpbWl6ZWRcIiBzdGFjayBtb25pdG9yLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgY2k/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDcmVhdGlvbiB0aW1lIG9mIHRoZSBjaGFuZ2Ugc2V0XG4gICAqXG4gICAqIFRoaXMgd2lsbCBiZSB1c2VkIHRvIGZpbHRlciBldmVudHMsIG9ubHkgc2hvd2luZyB0aG9zZSBmcm9tIGFmdGVyIHRoZSBjaGFuZ2VcbiAgICogc2V0IGNyZWF0aW9uIHRpbWUuXG4gICAqXG4gICAqIEl0IGlzIHJlY29tbWVuZGVkIHRvIHVzZSB0aGlzLCBvdGhlcndpc2UgdGhlIGZpbHRlcmluZyB3aWxsIGJlIHN1YmplY3RcbiAgICogdG8gY2xvY2sgZHJpZnQgYmV0d2VlbiBsb2NhbCBhbmQgY2xvdWQgbWFjaGluZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbG9jYWwgbWFjaGluZSdzIGN1cnJlbnQgdGltZVxuICAgKi9cbiAgcmVhZG9ubHkgY2hhbmdlU2V0Q3JlYXRpb25UaW1lPzogRGF0ZTtcbn1cblxuZXhwb3J0IGNsYXNzIFN0YWNrQWN0aXZpdHlNb25pdG9yIHtcbiAgLyoqXG4gICAqIENyZWF0ZSBhIFN0YWNrIEFjdGl2aXR5IE1vbml0b3IgdXNpbmcgYSBkZWZhdWx0IHByaW50ZXIsIGJhc2VkIG9uIGNvbnRleHQgY2x1ZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgd2l0aERlZmF1bHRQcmludGVyKFxuICAgIGNmbjogSUNsb3VkRm9ybWF0aW9uQ2xpZW50LFxuICAgIHN0YWNrTmFtZTogc3RyaW5nLFxuICAgIHN0YWNrQXJ0aWZhY3Q6IENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCxcbiAgICBvcHRpb25zOiBXaXRoRGVmYXVsdFByaW50ZXJQcm9wcyA9IHt9LFxuICApIHtcbiAgICBjb25zdCBzdHJlYW0gPSBvcHRpb25zLmNpID8gcHJvY2Vzcy5zdGRvdXQgOiBwcm9jZXNzLnN0ZGVycjtcblxuICAgIGNvbnN0IHByb3BzOiBQcmludGVyUHJvcHMgPSB7XG4gICAgICByZXNvdXJjZVR5cGVDb2x1bW5XaWR0aDogY2FsY01heFJlc291cmNlVHlwZUxlbmd0aChzdGFja0FydGlmYWN0LnRlbXBsYXRlKSxcbiAgICAgIHJlc291cmNlc1RvdGFsOiBvcHRpb25zLnJlc291cmNlc1RvdGFsLFxuICAgICAgc3RyZWFtLFxuICAgIH07XG5cbiAgICBjb25zdCBpc1dpbmRvd3MgPSBwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInO1xuICAgIGNvbnN0IHZlcmJvc2UgPSBvcHRpb25zLmxvZ0xldmVsID8/ICdpbmZvJztcbiAgICAvLyBPbiBzb21lIENJIHN5c3RlbXMgKHN1Y2ggYXMgQ2lyY2xlQ0kpIG91dHB1dCBzdGlsbCByZXBvcnRzIGFzIGEgVFRZIHNvIHdlIGFsc29cbiAgICAvLyBuZWVkIGFuIGluZGl2aWR1YWwgY2hlY2sgZm9yIHdoZXRoZXIgd2UncmUgcnVubmluZyBvbiBDSS5cbiAgICAvLyBzZWU6IGh0dHBzOi8vZGlzY3Vzcy5jaXJjbGVjaS5jb20vdC9jaXJjbGVjaS10ZXJtaW5hbC1pcy1hLXR0eS1idXQtdGVybS1pcy1ub3Qtc2V0Lzk5NjVcbiAgICBjb25zdCBmYW5jeU91dHB1dEF2YWlsYWJsZSA9ICFpc1dpbmRvd3MgJiYgc3RyZWFtLmlzVFRZICYmICFvcHRpb25zLmNpO1xuICAgIGNvbnN0IHByb2dyZXNzID0gb3B0aW9ucy5wcm9ncmVzcyA/PyBTdGFja0FjdGl2aXR5UHJvZ3Jlc3MuQkFSO1xuXG4gICAgY29uc3QgcHJpbnRlciA9XG4gICAgICBmYW5jeU91dHB1dEF2YWlsYWJsZSAmJiAhdmVyYm9zZSAmJiBwcm9ncmVzcyA9PT0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkJBUlxuICAgICAgICA/IG5ldyBDdXJyZW50QWN0aXZpdHlQcmludGVyKHByb3BzKVxuICAgICAgICA6IG5ldyBIaXN0b3J5QWN0aXZpdHlQcmludGVyKHByb3BzKTtcblxuICAgIHJldHVybiBuZXcgU3RhY2tBY3Rpdml0eU1vbml0b3IoY2ZuLCBzdGFja05hbWUsIHByaW50ZXIsIHN0YWNrQXJ0aWZhY3QsIG9wdGlvbnMuY2hhbmdlU2V0Q3JlYXRpb25UaW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcG9sbGVyIHVzZWQgdG8gcmVhZCBzdGFjayBldmVudHNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwb2xsZXI6IFN0YWNrRXZlbnRQb2xsZXI7XG5cbiAgcHVibGljIHJlYWRvbmx5IGVycm9yczogc3RyaW5nW10gPSBbXTtcblxuICBwcml2YXRlIGFjdGl2ZSA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBDdXJyZW50IHRpY2sgdGltZXJcbiAgICovXG4gIHByaXZhdGUgdGlja1RpbWVyPzogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD47XG5cbiAgLyoqXG4gICAqIFNldCB0byB0aGUgYWN0aXZpdHkgb2YgcmVhZGluZyB0aGUgY3VycmVudCBldmVudHNcbiAgICovXG4gIHByaXZhdGUgcmVhZFByb21pc2U/OiBQcm9taXNlPGFueT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgY2ZuOiBJQ2xvdWRGb3JtYXRpb25DbGllbnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdGFja05hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByaW50ZXI6IElBY3Rpdml0eVByaW50ZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdGFjaz86IENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCxcbiAgICBjaGFuZ2VTZXRDcmVhdGlvblRpbWU/OiBEYXRlLFxuICApIHtcbiAgICB0aGlzLnBvbGxlciA9IG5ldyBTdGFja0V2ZW50UG9sbGVyKGNmbiwge1xuICAgICAgc3RhY2tOYW1lLFxuICAgICAgc3RhcnRUaW1lOiBjaGFuZ2VTZXRDcmVhdGlvblRpbWU/LmdldFRpbWUoKSA/PyBEYXRlLm5vdygpLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXJ0KCkge1xuICAgIHRoaXMuYWN0aXZlID0gdHJ1ZTtcbiAgICB0aGlzLnByaW50ZXIuc3RhcnQoKTtcbiAgICB0aGlzLnNjaGVkdWxlTmV4dFRpY2soKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzdG9wKCkge1xuICAgIHRoaXMuYWN0aXZlID0gZmFsc2U7XG4gICAgaWYgKHRoaXMudGlja1RpbWVyKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy50aWNrVGltZXIpO1xuICAgIH1cblxuICAgIC8vIERvIGEgZmluYWwgcG9sbCBmb3IgYWxsIGV2ZW50cy4gVGhpcyBpcyB0byBoYW5kbGUgdGhlIHNpdHVhdGlvbiB3aGVyZSBEZXNjcmliZVN0YWNrU3RhdHVzXG4gICAgLy8gYWxyZWFkeSByZXR1cm5lZCBhbiBlcnJvciwgYnV0IHRoZSBtb25pdG9yIGhhc24ndCBzZWVuIGFsbCB0aGUgZXZlbnRzIHlldCBhbmQgd2UnZCBlbmRcbiAgICAvLyB1cCBub3QgcHJpbnRpbmcgdGhlIGZhaWx1cmUgcmVhc29uIHRvIHVzZXJzLlxuICAgIGF3YWl0IHRoaXMuZmluYWxQb2xsVG9FbmQoKTtcblxuICAgIHRoaXMucHJpbnRlci5zdG9wKCk7XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlTmV4dFRpY2soKSB7XG4gICAgaWYgKCF0aGlzLmFjdGl2ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudGlja1RpbWVyID0gc2V0VGltZW91dCgoKSA9PiB2b2lkIHRoaXMudGljaygpLCB0aGlzLnByaW50ZXIudXBkYXRlU2xlZXApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB0aWNrKCkge1xuICAgIGlmICghdGhpcy5hY3RpdmUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgdGhpcy5yZWFkUHJvbWlzZSA9IHRoaXMucmVhZE5ld0V2ZW50cygpO1xuICAgICAgYXdhaXQgdGhpcy5yZWFkUHJvbWlzZTtcbiAgICAgIHRoaXMucmVhZFByb21pc2UgPSB1bmRlZmluZWQ7XG5cbiAgICAgIC8vIFdlIG1pZ2h0IGhhdmUgYmVlbiBzdG9wKClwZWQgd2hpbGUgdGhlIG5ldHdvcmsgY2FsbCB3YXMgaW4gcHJvZ3Jlc3MuXG4gICAgICBpZiAoIXRoaXMuYWN0aXZlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wcmludGVyLnByaW50KCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZXJyb3IoJ0Vycm9yIG9jY3VycmVkIHdoaWxlIG1vbml0b3Jpbmcgc3RhY2s6ICVzJywgZSk7XG4gICAgfVxuICAgIHRoaXMuc2NoZWR1bGVOZXh0VGljaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kTWV0YWRhdGFGb3IobG9naWNhbElkOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBSZXNvdXJjZU1ldGFkYXRhIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBtZXRhZGF0YSA9IHRoaXMuc3RhY2s/Lm1hbmlmZXN0Py5tZXRhZGF0YTtcbiAgICBpZiAoIWxvZ2ljYWxJZCB8fCAhbWV0YWRhdGEpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGZvciAoY29uc3QgcGF0aCBvZiBPYmplY3Qua2V5cyhtZXRhZGF0YSkpIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gbWV0YWRhdGFbcGF0aF1cbiAgICAgICAgLmZpbHRlcigoZSkgPT4gZS50eXBlID09PSBBcnRpZmFjdE1ldGFkYXRhRW50cnlUeXBlLkxPR0lDQUxfSUQpXG4gICAgICAgIC5maW5kKChlKSA9PiBlLmRhdGEgPT09IGxvZ2ljYWxJZCk7XG4gICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlbnRyeSxcbiAgICAgICAgICBjb25zdHJ1Y3RQYXRoOiB0aGlzLnNpbXBsaWZ5Q29uc3RydWN0UGF0aChwYXRoKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkcyBhbGwgbmV3IGV2ZW50cyBmcm9tIHRoZSBzdGFjayBoaXN0b3J5XG4gICAqXG4gICAqIFRoZSBldmVudHMgYXJlIHJldHVybmVkIGluIHJldmVyc2UgY2hyb25vbG9naWNhbCBvcmRlcjsgd2UgY29udGludWUgdG8gdGhlIG5leHQgcGFnZSBpZiB3ZVxuICAgKiBzZWUgYSBuZXh0IHBhZ2UgYW5kIHRoZSBsYXN0IGV2ZW50IGluIHRoZSBwYWdlIGlzIG5ldyB0byB1cyAoYW5kIHdpdGhpbiB0aGUgdGltZSB3aW5kb3cpLlxuICAgKiBoYXZlbid0IHNlZW4gdGhlIGZpbmFsIGV2ZW50XG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlYWROZXdFdmVudHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcG9sbEV2ZW50cyA9IGF3YWl0IHRoaXMucG9sbGVyLnBvbGwoKTtcblxuICAgIGNvbnN0IGFjdGl2aXRpZXM6IFN0YWNrQWN0aXZpdHlbXSA9IHBvbGxFdmVudHMubWFwKChldmVudCkgPT4gKHtcbiAgICAgIC4uLmV2ZW50LFxuICAgICAgbWV0YWRhdGE6IHRoaXMuZmluZE1ldGFkYXRhRm9yKGV2ZW50LmV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkKSxcbiAgICB9KSk7XG5cbiAgICBmb3IgKGNvbnN0IGFjdGl2aXR5IG9mIGFjdGl2aXRpZXMpIHtcbiAgICAgIHRoaXMuY2hlY2tGb3JFcnJvcnMoYWN0aXZpdHkpO1xuICAgICAgdGhpcy5wcmludGVyLmFkZEFjdGl2aXR5KGFjdGl2aXR5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGZpbmFsIHBvbGwgdG8gdGhlIGVuZCBhbmQgZmx1c2ggb3V0IGFsbCBldmVudHMgdG8gdGhlIHByaW50ZXJcbiAgICpcbiAgICogRmluaXNoIGFueSBwb2xsIGN1cnJlbnRseSBpbiBwcm9ncmVzcywgdGhlbiBkbyBhIGZpbmFsIG9uZSB1bnRpbCB3ZSd2ZVxuICAgKiByZWFjaGVkIHRoZSBsYXN0IHBhZ2UuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZpbmFsUG9sbFRvRW5kKCkge1xuICAgIC8vIElmIHdlIHdlcmUgZG9pbmcgYSBwb2xsLCBmaW5pc2ggdGhhdCBmaXJzdC4gSXQgd2FzIHN0YXJ0ZWQgYmVmb3JlXG4gICAgLy8gdGhlIG1vbWVudCB3ZSB3ZXJlIHN1cmUgd2Ugd2VyZW4ndCBnb2luZyB0byBnZXQgYW55IG5ldyBldmVudHMgYW55bW9yZVxuICAgIC8vIHNvIHdlIG5lZWQgdG8gZG8gYSBuZXcgb25lIGFueXdheS4gTmVlZCB0byB3YWl0IGZvciB0aGlzIG9uZSB0aG91Z2hcbiAgICAvLyBiZWNhdXNlIG91ciBzdGF0ZSBpcyBzaW5nbGUtdGhyZWFkZWQuXG4gICAgaWYgKHRoaXMucmVhZFByb21pc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVhZFByb21pc2U7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5yZWFkTmV3RXZlbnRzKCk7XG4gIH1cblxuICBwcml2YXRlIGNoZWNrRm9yRXJyb3JzKGFjdGl2aXR5OiBTdGFja0FjdGl2aXR5KSB7XG4gICAgaWYgKGhhc0Vycm9yTWVzc2FnZShhY3Rpdml0eS5ldmVudC5SZXNvdXJjZVN0YXR1cyA/PyAnJykpIHtcbiAgICAgIGNvbnN0IGlzQ2FuY2VsbGVkID0gKGFjdGl2aXR5LmV2ZW50LlJlc291cmNlU3RhdHVzUmVhc29uID8/ICcnKS5pbmRleE9mKCdjYW5jZWxsZWQnKSA+IC0xO1xuXG4gICAgICAvLyBDYW5jZWxsZWQgaXMgbm90IGFuIGludGVyZXN0aW5nIGZhaWx1cmUgcmVhc29uLCBub3IgaXMgdGhlIHN0YWNrIG1lc3NhZ2UgKHN0YWNrXG4gICAgICAvLyBtZXNzYWdlIHdpbGwganVzdCBzYXkgc29tZXRoaW5nIGxpa2UgXCJzdGFjayBmYWlsZWQgdG8gdXBkYXRlXCIpXG4gICAgICBpZiAoIWlzQ2FuY2VsbGVkICYmIGFjdGl2aXR5LmV2ZW50LlN0YWNrTmFtZSAhPT0gYWN0aXZpdHkuZXZlbnQuTG9naWNhbFJlc291cmNlSWQpIHtcbiAgICAgICAgdGhpcy5lcnJvcnMucHVzaChhY3Rpdml0eS5ldmVudC5SZXNvdXJjZVN0YXR1c1JlYXNvbiA/PyAnJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzaW1wbGlmeUNvbnN0cnVjdFBhdGgocGF0aDogc3RyaW5nKSB7XG4gICAgcGF0aCA9IHBhdGgucmVwbGFjZSgvXFwvUmVzb3VyY2UkLywgJycpO1xuICAgIHBhdGggPSBwYXRoLnJlcGxhY2UoL15cXC8vLCAnJyk7IC8vIHJlbW92ZSBcIi9cIiBwcmVmaXhcblxuICAgIC8vIHJlbW92ZSBcIjxzdGFjay1uYW1lPi9cIiBwcmVmaXhcbiAgICBpZiAocGF0aC5zdGFydHNXaXRoKHRoaXMuc3RhY2tOYW1lICsgJy8nKSkge1xuICAgICAgcGF0aCA9IHBhdGguc2xpY2UodGhpcy5zdGFja05hbWUubGVuZ3RoICsgMSk7XG4gICAgfVxuICAgIHJldHVybiBwYXRoO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhZFJpZ2h0KG46IG51bWJlciwgeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHggKyAnICcucmVwZWF0KE1hdGgubWF4KDAsIG4gLSB4Lmxlbmd0aCkpO1xufVxuXG4vKipcbiAqIEluZmFtb3VzIHBhZExlZnQoKVxuICovXG5mdW5jdGlvbiBwYWRMZWZ0KG46IG51bWJlciwgeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuICcgJy5yZXBlYXQoTWF0aC5tYXgoMCwgbiAtIHgubGVuZ3RoKSkgKyB4O1xufVxuXG5mdW5jdGlvbiBjYWxjTWF4UmVzb3VyY2VUeXBlTGVuZ3RoKHRlbXBsYXRlOiBhbnkpIHtcbiAgY29uc3QgcmVzb3VyY2VzID0gKHRlbXBsYXRlICYmIHRlbXBsYXRlLlJlc291cmNlcykgfHwge307XG4gIGxldCBtYXhXaWR0aCA9IDA7XG4gIGZvciAoY29uc3QgaWQgb2YgT2JqZWN0LmtleXMocmVzb3VyY2VzKSkge1xuICAgIGNvbnN0IHR5cGUgPSByZXNvdXJjZXNbaWRdLlR5cGUgfHwgJyc7XG4gICAgaWYgKHR5cGUubGVuZ3RoID4gbWF4V2lkdGgpIHtcbiAgICAgIG1heFdpZHRoID0gdHlwZS5sZW5ndGg7XG4gICAgfVxuICB9XG4gIHJldHVybiBtYXhXaWR0aDtcbn1cblxuaW50ZXJmYWNlIFByaW50ZXJQcm9wcyB7XG4gIC8qKlxuICAgKiBUb3RhbCByZXNvdXJjZXMgdG8gZGVwbG95XG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZXNUb3RhbD86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIHdpdGggb2YgdGhlIFwicmVzb3VyY2UgdHlwZVwiIGNvbHVtbi5cbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlVHlwZUNvbHVtbldpZHRoOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFN0cmVhbSB0byB3cml0ZSB0b1xuICAgKi9cbiAgcmVhZG9ubHkgc3RyZWFtOiBOb2RlSlMuV3JpdGVTdHJlYW07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUFjdGl2aXR5UHJpbnRlciB7XG4gIHJlYWRvbmx5IHVwZGF0ZVNsZWVwOiBudW1iZXI7XG5cbiAgYWRkQWN0aXZpdHkoYWN0aXZpdHk6IFN0YWNrQWN0aXZpdHkpOiB2b2lkO1xuICBwcmludCgpOiB2b2lkO1xuICBzdGFydCgpOiB2b2lkO1xuICBzdG9wKCk6IHZvaWQ7XG59XG5cbmFic3RyYWN0IGNsYXNzIEFjdGl2aXR5UHJpbnRlckJhc2UgaW1wbGVtZW50cyBJQWN0aXZpdHlQcmludGVyIHtcbiAgLyoqXG4gICAqIEZldGNoIG5ldyBhY3Rpdml0eSBldmVyeSA1IHNlY29uZHNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB1cGRhdGVTbGVlcDogbnVtYmVyID0gNV8wMDA7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiByZXNvdXJjZSBJRHMgd2hpY2ggYXJlIGN1cnJlbnRseSBiZWluZyBwcm9jZXNzZWRcbiAgICovXG4gIHByb3RlY3RlZCByZXNvdXJjZXNJblByb2dyZXNzOiBSZWNvcmQ8c3RyaW5nLCBTdGFja0FjdGl2aXR5PiA9IHt9O1xuXG4gIC8qKlxuICAgKiBQcmV2aW91cyBjb21wbGV0aW9uIHN0YXRlIG9ic2VydmVkIGJ5IGxvZ2ljYWwgSURcbiAgICpcbiAgICogV2UgdXNlIHRoaXMgdG8gZGV0ZWN0IHRoYXQgaWYgd2Ugc2VlIGEgREVMRVRFX0NPTVBMRVRFIGFmdGVyIGFcbiAgICogQ1JFQVRFX0NPTVBMRVRFLCBpdCdzIGFjdHVhbGx5IGEgcm9sbGJhY2sgYW5kIHdlIHNob3VsZCBERUNSRUFTRVxuICAgKiByZXNvdXJjZXNEb25lIGluc3RlYWQgb2YgaW5jcmVhc2UgaXRcbiAgICovXG4gIHByb3RlY3RlZCByZXNvdXJjZXNQcmV2Q29tcGxldGVTdGF0ZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBDb3VudCBvZiByZXNvdXJjZXMgdGhhdCBoYXZlIHJlcG9ydGVkIGEgX0NPTVBMRVRFIHN0YXR1c1xuICAgKi9cbiAgcHJvdGVjdGVkIHJlc291cmNlc0RvbmU6IG51bWJlciA9IDA7XG5cbiAgLyoqXG4gICAqIEhvdyBtYW55IGRpZ2l0cyB3ZSBuZWVkIHRvIHJlcHJlc2VudCB0aGUgdG90YWwgY291bnQgKGZvciBsaW5pbmcgdXAgdGhlIHN0YXR1cyByZXBvcnRpbmcpXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVzb3VyY2VEaWdpdHM6IG51bWJlciA9IDA7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlc291cmNlc1RvdGFsPzogbnVtYmVyO1xuXG4gIHByb3RlY3RlZCByb2xsaW5nQmFjayA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBmYWlsdXJlcyA9IG5ldyBBcnJheTxTdGFja0FjdGl2aXR5PigpO1xuXG4gIHByb3RlY3RlZCBob29rRmFpbHVyZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PigpO1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBwcm9wczogUHJpbnRlclByb3BzKSB7XG4gICAgLy8gKzEgYmVjYXVzZSB0aGUgc3RhY2sgYWxzbyBlbWl0cyBhIFwiQ09NUExFVEVcIiBldmVudCBhdCB0aGUgZW5kLCBhbmQgdGhhdCB3YXNuJ3RcbiAgICAvLyBjb3VudGVkIHlldC4gVGhpcyBtYWtlcyBpdCBsaW5lIHVwIHdpdGggdGhlIGFtb3VudCBvZiBldmVudHMgd2UgZXhwZWN0LlxuICAgIHRoaXMucmVzb3VyY2VzVG90YWwgPSBwcm9wcy5yZXNvdXJjZXNUb3RhbCA/IHByb3BzLnJlc291cmNlc1RvdGFsICsgMSA6IHVuZGVmaW5lZDtcblxuICAgIC8vIEhvdyBtYW55IGRpZ2l0cyBkb2VzIHRoaXMgbnVtYmVyIHRha2UgdG8gcmVwcmVzZW50P1xuICAgIHRoaXMucmVzb3VyY2VEaWdpdHMgPSB0aGlzLnJlc291cmNlc1RvdGFsID8gTWF0aC5jZWlsKE1hdGgubG9nMTAodGhpcy5yZXNvdXJjZXNUb3RhbCkpIDogMDtcbiAgfVxuXG4gIHB1YmxpYyBmYWlsdXJlUmVhc29uKGFjdGl2aXR5OiBTdGFja0FjdGl2aXR5KSB7XG4gICAgY29uc3QgcmVzb3VyY2VTdGF0dXNSZWFzb24gPSBhY3Rpdml0eS5ldmVudC5SZXNvdXJjZVN0YXR1c1JlYXNvbiA/PyAnJztcbiAgICBjb25zdCBsb2dpY2FsUmVzb3VyY2VJZCA9IGFjdGl2aXR5LmV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkID8/ICcnO1xuICAgIGNvbnN0IGhvb2tGYWlsdXJlUmVhc29uTWFwID0gdGhpcy5ob29rRmFpbHVyZU1hcC5nZXQobG9naWNhbFJlc291cmNlSWQpO1xuXG4gICAgaWYgKGhvb2tGYWlsdXJlUmVhc29uTWFwICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAoY29uc3QgaG9va1R5cGUgb2YgaG9va0ZhaWx1cmVSZWFzb25NYXAua2V5cygpKSB7XG4gICAgICAgIGlmIChyZXNvdXJjZVN0YXR1c1JlYXNvbi5pbmNsdWRlcyhob29rVHlwZSkpIHtcbiAgICAgICAgICByZXR1cm4gcmVzb3VyY2VTdGF0dXNSZWFzb24gKyAnIDogJyArIGhvb2tGYWlsdXJlUmVhc29uTWFwLmdldChob29rVHlwZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc291cmNlU3RhdHVzUmVhc29uO1xuICB9XG5cbiAgcHVibGljIGFkZEFjdGl2aXR5KGFjdGl2aXR5OiBTdGFja0FjdGl2aXR5KSB7XG4gICAgY29uc3Qgc3RhdHVzID0gYWN0aXZpdHkuZXZlbnQuUmVzb3VyY2VTdGF0dXM7XG4gICAgY29uc3QgaG9va1N0YXR1cyA9IGFjdGl2aXR5LmV2ZW50Lkhvb2tTdGF0dXM7XG4gICAgY29uc3QgaG9va1R5cGUgPSBhY3Rpdml0eS5ldmVudC5Ib29rVHlwZTtcbiAgICBpZiAoIXN0YXR1cyB8fCAhYWN0aXZpdHkuZXZlbnQuTG9naWNhbFJlc291cmNlSWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoc3RhdHVzID09PSAnUk9MTEJBQ0tfSU5fUFJPR1JFU1MnIHx8IHN0YXR1cyA9PT0gJ1VQREFURV9ST0xMQkFDS19JTl9QUk9HUkVTUycpIHtcbiAgICAgIC8vIE9ubHkgdHJpZ2dlcmVkIG9uIHRoZSBzdGFjayBvbmNlIHdlJ3ZlIHN0YXJ0ZWQgZG9pbmcgYSByb2xsYmFja1xuICAgICAgdGhpcy5yb2xsaW5nQmFjayA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHN0YXR1cy5lbmRzV2l0aCgnX0lOX1BST0dSRVNTJykpIHtcbiAgICAgIHRoaXMucmVzb3VyY2VzSW5Qcm9ncmVzc1thY3Rpdml0eS5ldmVudC5Mb2dpY2FsUmVzb3VyY2VJZF0gPSBhY3Rpdml0eTtcbiAgICB9XG5cbiAgICBpZiAoaGFzRXJyb3JNZXNzYWdlKHN0YXR1cykpIHtcbiAgICAgIGNvbnN0IGlzQ2FuY2VsbGVkID0gKGFjdGl2aXR5LmV2ZW50LlJlc291cmNlU3RhdHVzUmVhc29uID8/ICcnKS5pbmRleE9mKCdjYW5jZWxsZWQnKSA+IC0xO1xuXG4gICAgICAvLyBDYW5jZWxsZWQgaXMgbm90IGFuIGludGVyZXN0aW5nIGZhaWx1cmUgcmVhc29uXG4gICAgICBpZiAoIWlzQ2FuY2VsbGVkKSB7XG4gICAgICAgIHRoaXMuZmFpbHVyZXMucHVzaChhY3Rpdml0eSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN0YXR1cy5lbmRzV2l0aCgnX0NPTVBMRVRFJykgfHwgc3RhdHVzLmVuZHNXaXRoKCdfRkFJTEVEJykpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnJlc291cmNlc0luUHJvZ3Jlc3NbYWN0aXZpdHkuZXZlbnQuTG9naWNhbFJlc291cmNlSWRdO1xuICAgIH1cblxuICAgIGlmIChzdGF0dXMuZW5kc1dpdGgoJ19DT01QTEVURV9DTEVBTlVQX0lOX1BST0dSRVNTJykpIHtcbiAgICAgIHRoaXMucmVzb3VyY2VzRG9uZSsrO1xuICAgIH1cblxuICAgIGlmIChzdGF0dXMuZW5kc1dpdGgoJ19DT01QTEVURScpKSB7XG4gICAgICBjb25zdCBwcmV2U3RhdGUgPSB0aGlzLnJlc291cmNlc1ByZXZDb21wbGV0ZVN0YXRlW2FjdGl2aXR5LmV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkXTtcbiAgICAgIGlmICghcHJldlN0YXRlKSB7XG4gICAgICAgIHRoaXMucmVzb3VyY2VzRG9uZSsrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgd2UgY29tcGxldGVkIHRoaXMgYmVmb3JlIGFuZCB3ZSdyZSBjb21wbGV0aW5nIGl0IEFHQUlOLCBtZWFucyB3ZSdyZSByb2xsaW5nIGJhY2suXG4gICAgICAgIC8vIFByb3RlY3QgYWdhaW5zdCBzaWxseSB1bmRlcmZsb3cuXG4gICAgICAgIHRoaXMucmVzb3VyY2VzRG9uZS0tO1xuICAgICAgICBpZiAodGhpcy5yZXNvdXJjZXNEb25lIDwgMCkge1xuICAgICAgICAgIHRoaXMucmVzb3VyY2VzRG9uZSA9IDA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMucmVzb3VyY2VzUHJldkNvbXBsZXRlU3RhdGVbYWN0aXZpdHkuZXZlbnQuTG9naWNhbFJlc291cmNlSWRdID0gc3RhdHVzO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGhvb2tTdGF0dXMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgaG9va1N0YXR1cy5lbmRzV2l0aCgnX0NPTVBMRVRFX0ZBSUxFRCcpICYmXG4gICAgICBhY3Rpdml0eS5ldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBob29rVHlwZSAhPT0gdW5kZWZpbmVkXG4gICAgKSB7XG4gICAgICBpZiAodGhpcy5ob29rRmFpbHVyZU1hcC5oYXMoYWN0aXZpdHkuZXZlbnQuTG9naWNhbFJlc291cmNlSWQpKSB7XG4gICAgICAgIHRoaXMuaG9va0ZhaWx1cmVNYXAuZ2V0KGFjdGl2aXR5LmV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkKT8uc2V0KGhvb2tUeXBlLCBhY3Rpdml0eS5ldmVudC5Ib29rU3RhdHVzUmVhc29uID8/ICcnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaG9va0ZhaWx1cmVNYXAuc2V0KGFjdGl2aXR5LmV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLCBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpKTtcbiAgICAgICAgdGhpcy5ob29rRmFpbHVyZU1hcC5nZXQoYWN0aXZpdHkuZXZlbnQuTG9naWNhbFJlc291cmNlSWQpPy5zZXQoaG9va1R5cGUsIGFjdGl2aXR5LmV2ZW50Lkhvb2tTdGF0dXNSZWFzb24gPz8gJycpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhYnN0cmFjdCBwcmludCgpOiB2b2lkO1xuXG4gIHB1YmxpYyBzdGFydCgpIHtcbiAgICAvLyBFbXB0eSBvbiBwdXJwb3NlXG4gIH1cblxuICBwdWJsaWMgc3RvcCgpIHtcbiAgICAvLyBFbXB0eSBvbiBwdXJwb3NlXG4gIH1cbn1cblxuLyoqXG4gKiBBY3Rpdml0eSBQcmludGVyIHdoaWNoIHNob3dzIGEgZnVsbCBsb2cgb2YgYWxsIENsb3VkRm9ybWF0aW9uIGV2ZW50c1xuICpcbiAqIFdoZW4gdGhlcmUgaGFzbid0IGJlZW4gYWN0aXZpdHkgZm9yIGEgd2hpbGUsIGl0IHdpbGwgcHJpbnQgdGhlIHJlc291cmNlc1xuICogdGhhdCBhcmUgY3VycmVudGx5IGluIHByb2dyZXNzLCB0byBzaG93IHdoYXQncyBob2xkaW5nIHVwIHRoZSBkZXBsb3ltZW50LlxuICovXG5leHBvcnQgY2xhc3MgSGlzdG9yeUFjdGl2aXR5UHJpbnRlciBleHRlbmRzIEFjdGl2aXR5UHJpbnRlckJhc2Uge1xuICAvKipcbiAgICogTGFzdCB0aW1lIHdlIHByaW50ZWQgc29tZXRoaW5nIHRvIHRoZSBjb25zb2xlLlxuICAgKlxuICAgKiBVc2VkIHRvIG1lYXN1cmUgdGltZW91dCBmb3IgcHJvZ3Jlc3MgcmVwb3J0aW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBsYXN0UHJpbnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIG1zIG9mIGNoYW5nZSBhYnNlbmNlIGJlZm9yZSB3ZSB0ZWxsIHRoZSB1c2VyIGFib3V0IHRoZSByZXNvdXJjZXMgdGhhdCBhcmUgY3VycmVudGx5IGluIHByb2dyZXNzLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBpblByb2dyZXNzRGVsYXkgPSAzMF8wMDA7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwcmludGFibGUgPSBuZXcgQXJyYXk8U3RhY2tBY3Rpdml0eT4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogUHJpbnRlclByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuICB9XG5cbiAgcHVibGljIGFkZEFjdGl2aXR5KGFjdGl2aXR5OiBTdGFja0FjdGl2aXR5KSB7XG4gICAgc3VwZXIuYWRkQWN0aXZpdHkoYWN0aXZpdHkpO1xuICAgIHRoaXMucHJpbnRhYmxlLnB1c2goYWN0aXZpdHkpO1xuICAgIHRoaXMucHJpbnQoKTtcbiAgfVxuXG4gIHB1YmxpYyBwcmludCgpIHtcbiAgICBmb3IgKGNvbnN0IGFjdGl2aXR5IG9mIHRoaXMucHJpbnRhYmxlKSB7XG4gICAgICB0aGlzLnByaW50T25lKGFjdGl2aXR5KTtcbiAgICB9XG4gICAgdGhpcy5wcmludGFibGUuc3BsaWNlKDAsIHRoaXMucHJpbnRhYmxlLmxlbmd0aCk7XG4gICAgdGhpcy5wcmludEluUHJvZ3Jlc3MoKTtcbiAgfVxuXG4gIHB1YmxpYyBzdG9wKCkge1xuICAgIC8vIFByaW50IGZhaWx1cmVzIGF0IHRoZSBlbmRcbiAgICBpZiAodGhpcy5mYWlsdXJlcy5sZW5ndGggPiAwKSB7XG4gICAgICBpbmZvKCdcXG5GYWlsZWQgcmVzb3VyY2VzOicpO1xuICAgICAgZm9yIChjb25zdCBmYWlsdXJlIG9mIHRoaXMuZmFpbHVyZXMpIHtcbiAgICAgICAgLy8gUm9vdCBzdGFjayBmYWlsdXJlcyBhcmUgbm90IGludGVyZXN0aW5nXG4gICAgICAgIGlmIChmYWlsdXJlLmlzU3RhY2tFdmVudCkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wcmludE9uZShmYWlsdXJlLCBmYWxzZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwcmludE9uZShhY3Rpdml0eTogU3RhY2tBY3Rpdml0eSwgcHJvZ3Jlc3M/OiBib29sZWFuKSB7XG4gICAgY29uc3QgZXZlbnQgPSBhY3Rpdml0eS5ldmVudDtcbiAgICBjb25zdCBjb2xvciA9IGNvbG9yRnJvbVN0YXR1c1Jlc3VsdChldmVudC5SZXNvdXJjZVN0YXR1cyk7XG4gICAgbGV0IHJlYXNvbkNvbG9yID0gY2hhbGsuY3lhbjtcblxuICAgIGxldCBzdGFja1RyYWNlID0gJyc7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBhY3Rpdml0eS5tZXRhZGF0YTtcblxuICAgIGlmIChldmVudC5SZXNvdXJjZVN0YXR1cyAmJiBldmVudC5SZXNvdXJjZVN0YXR1cy5pbmRleE9mKCdGQUlMRUQnKSAhPT0gLTEpIHtcbiAgICAgIGlmIChwcm9ncmVzcyA9PSB1bmRlZmluZWQgfHwgcHJvZ3Jlc3MpIHtcbiAgICAgICAgZXZlbnQuUmVzb3VyY2VTdGF0dXNSZWFzb24gPSBldmVudC5SZXNvdXJjZVN0YXR1c1JlYXNvbiA/IHRoaXMuZmFpbHVyZVJlYXNvbihhY3Rpdml0eSkgOiAnJztcbiAgICAgIH1cbiAgICAgIGlmIChtZXRhZGF0YSkge1xuICAgICAgICBzdGFja1RyYWNlID0gbWV0YWRhdGEuZW50cnkudHJhY2UgPyBgXFxuXFx0JHttZXRhZGF0YS5lbnRyeS50cmFjZS5qb2luKCdcXG5cXHRcXFxcXyAnKX1gIDogJyc7XG4gICAgICB9XG4gICAgICByZWFzb25Db2xvciA9IGNoYWxrLnJlZDtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZU5hbWUgPSBtZXRhZGF0YSA/IG1ldGFkYXRhLmNvbnN0cnVjdFBhdGggOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCB8fCAnJztcblxuICAgIGNvbnN0IGxvZ2ljYWxJZCA9IHJlc291cmNlTmFtZSAhPT0gZXZlbnQuTG9naWNhbFJlc291cmNlSWQgPyBgKCR7ZXZlbnQuTG9naWNhbFJlc291cmNlSWR9KSBgIDogJyc7XG5cbiAgICBpbmZvKFxuICAgICAgdXRpbC5mb3JtYXQoXG4gICAgICAgICclcyB8ICVzJXMgfCAlcyB8ICVzIHwgJXMgJXMlcyVzJyxcbiAgICAgICAgZXZlbnQuU3RhY2tOYW1lLFxuICAgICAgICBwcm9ncmVzcyAhPT0gZmFsc2UgPyBgJHt0aGlzLnByb2dyZXNzKCl9IHwgYCA6ICcnLFxuICAgICAgICBuZXcgRGF0ZShldmVudC5UaW1lc3RhbXAhKS50b0xvY2FsZVRpbWVTdHJpbmcoKSxcbiAgICAgICAgY29sb3IocGFkUmlnaHQoU1RBVFVTX1dJRFRILCAoZXZlbnQuUmVzb3VyY2VTdGF0dXMgfHwgJycpLnNsaWNlKDAsIFNUQVRVU19XSURUSCkpKSwgLy8gcGFkIGxlZnQgYW5kIHRyaW1cbiAgICAgICAgcGFkUmlnaHQodGhpcy5wcm9wcy5yZXNvdXJjZVR5cGVDb2x1bW5XaWR0aCwgZXZlbnQuUmVzb3VyY2VUeXBlIHx8ICcnKSxcbiAgICAgICAgY29sb3IoY2hhbGsuYm9sZChyZXNvdXJjZU5hbWUpKSxcbiAgICAgICAgbG9naWNhbElkLFxuICAgICAgICByZWFzb25Db2xvcihjaGFsay5ib2xkKGV2ZW50LlJlc291cmNlU3RhdHVzUmVhc29uID8gZXZlbnQuUmVzb3VyY2VTdGF0dXNSZWFzb24gOiAnJykpLFxuICAgICAgICByZWFzb25Db2xvcihzdGFja1RyYWNlKSxcbiAgICAgICksXG4gICAgKTtcblxuICAgIHRoaXMubGFzdFByaW50VGltZSA9IERhdGUubm93KCk7XG4gIH1cblxuICAvKipcbiAgICogUmVwb3J0IHRoZSBjdXJyZW50IHByb2dyZXNzIGFzIGEgWzM0LzQyXSBzdHJpbmcsIG9yIGp1c3QgWzM0XSBpZiB0aGUgdG90YWwgaXMgdW5rbm93blxuICAgKi9cbiAgcHJpdmF0ZSBwcm9ncmVzcygpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnJlc291cmNlc1RvdGFsID09IG51bGwpIHtcbiAgICAgIC8vIERvbid0IGhhdmUgdG90YWwsIHNob3cgc2ltcGxlIGNvdW50IGFuZCBob3BlIHRoZSBodW1hbiBrbm93c1xuICAgICAgcmV0dXJuIHBhZExlZnQoMywgdXRpbC5mb3JtYXQoJyVzJywgdGhpcy5yZXNvdXJjZXNEb25lKSk7IC8vIG1heCA1MDAgcmVzb3VyY2VzXG4gICAgfVxuXG4gICAgcmV0dXJuIHV0aWwuZm9ybWF0KFxuICAgICAgJyVzLyVzJyxcbiAgICAgIHBhZExlZnQodGhpcy5yZXNvdXJjZURpZ2l0cywgdGhpcy5yZXNvdXJjZXNEb25lLnRvU3RyaW5nKCkpLFxuICAgICAgcGFkTGVmdCh0aGlzLnJlc291cmNlRGlnaXRzLCB0aGlzLnJlc291cmNlc1RvdGFsICE9IG51bGwgPyB0aGlzLnJlc291cmNlc1RvdGFsLnRvU3RyaW5nKCkgOiAnPycpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSWYgc29tZSByZXNvdXJjZXMgYXJlIHRha2luZyBhIHdoaWxlIHRvIGNyZWF0ZSwgbm90aWZ5IHRoZSB1c2VyIGFib3V0IHdoYXQncyBjdXJyZW50bHkgaW4gcHJvZ3Jlc3NcbiAgICovXG4gIHByaXZhdGUgcHJpbnRJblByb2dyZXNzKCkge1xuICAgIGlmIChEYXRlLm5vdygpIDwgdGhpcy5sYXN0UHJpbnRUaW1lICsgdGhpcy5pblByb2dyZXNzRGVsYXkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5yZXNvdXJjZXNJblByb2dyZXNzKS5sZW5ndGggPiAwKSB7XG4gICAgICBpbmZvKFxuICAgICAgICB1dGlsLmZvcm1hdChcbiAgICAgICAgICAnJXMgQ3VycmVudGx5IGluIHByb2dyZXNzOiAlcycsXG4gICAgICAgICAgdGhpcy5wcm9ncmVzcygpLFxuICAgICAgICAgIGNoYWxrLmJvbGQoT2JqZWN0LmtleXModGhpcy5yZXNvdXJjZXNJblByb2dyZXNzKS5qb2luKCcsICcpKSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gV2UgY2hlYXQgYSBiaXQgaGVyZS4gVG8gcHJldmVudCBwcmludEluUHJvZ3Jlc3MoKSBmcm9tIHJlcGVhdGVkbHkgdHJpZ2dlcmluZyxcbiAgICAvLyB3ZSBzZXQgdGhlIHRpbWVzdGFtcCBpbnRvIHRoZSBmdXR1cmUuIEl0IHdpbGwgYmUgcmVzZXQgd2hlbmV2ZXIgYSByZWd1bGFyIHByaW50XG4gICAgLy8gb2NjdXJzLCBhZnRlciB3aGljaCB3ZSBjYW4gYmUgdHJpZ2dlcmVkIGFnYWluLlxuICAgIHRoaXMubGFzdFByaW50VGltZSA9ICtJbmZpbml0eTtcbiAgfVxufVxuXG4vKipcbiAqIEFjdGl2aXR5IFByaW50ZXIgd2hpY2ggc2hvd3MgdGhlIHJlc291cmNlcyBjdXJyZW50bHkgYmVpbmcgdXBkYXRlZFxuICpcbiAqIEl0IHdpbGwgY29udGludW91c2x5IHJldXBkYXRlIHRoZSB0ZXJtaW5hbCBhbmQgc2hvdyBvbmx5IHRoZSByZXNvdXJjZXNcbiAqIHRoYXQgYXJlIGN1cnJlbnRseSBiZWluZyB1cGRhdGVkLCBpbiBhZGRpdGlvbiB0byBhIHByb2dyZXNzIGJhciB3aGljaFxuICogc2hvd3MgaG93IGZhciBhbG9uZyB0aGUgZGVwbG95bWVudCBpcy5cbiAqXG4gKiBSZXNvdXJjZXMgdGhhdCBoYXZlIGZhaWxlZCB3aWxsIGFsd2F5cyBiZSBzaG93biwgYW5kIHdpbGwgYmUgcmVjYXBpdHVsYXRlZFxuICogYWxvbmcgd2l0aCB0aGVpciBzdGFjayB0cmFjZSB3aGVuIHRoZSBtb25pdG9yaW5nIGVuZHMuXG4gKlxuICogUmVzb3VyY2VzIHRoYXQgZmFpbGVkIGRlcGxveW1lbnQgYmVjYXVzZSB0aGV5IGhhdmUgYmVlbiBjYW5jZWxsZWQgYXJlXG4gKiBub3QgaW5jbHVkZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBDdXJyZW50QWN0aXZpdHlQcmludGVyIGV4dGVuZHMgQWN0aXZpdHlQcmludGVyQmFzZSB7XG4gIC8qKlxuICAgKiBUaGlzIGxvb2tzIHZlcnkgZGlzb3JpZW50aW5nIHNsZWVwaW5nIGZvciA1IHNlY29uZHMuIFVwZGF0ZSBxdWlja2VyLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHVwZGF0ZVNsZWVwOiBudW1iZXIgPSAyXzAwMDtcblxuICBwcml2YXRlIG9sZExvZ1RocmVzaG9sZDogSW9NZXNzYWdlTGV2ZWw7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RyZWFtOiBOb2RlSlMuV3JpdGVTdHJlYW07XG4gIHByaXZhdGUgYmxvY2s6IFJld3JpdGFibGVCbG9jaztcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogUHJpbnRlclByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuICAgIHRoaXMub2xkTG9nVGhyZXNob2xkID0gQ2xpSW9Ib3N0Lmluc3RhbmNlKCkubG9nTGV2ZWw7XG4gICAgdGhpcy5zdHJlYW0gPSBwcm9wcy5zdHJlYW07XG4gICAgdGhpcy5ibG9jayA9IG5ldyBSZXdyaXRhYmxlQmxvY2sodGhpcy5zdHJlYW0pO1xuICB9XG5cbiAgcHVibGljIHByaW50KCk6IHZvaWQge1xuICAgIGNvbnN0IGxpbmVzID0gW107XG5cbiAgICAvLyBBZGQgYSBwcm9ncmVzcyBiYXIgYXQgdGhlIHRvcFxuICAgIGNvbnN0IHByb2dyZXNzV2lkdGggPSBNYXRoLm1heChcbiAgICAgIE1hdGgubWluKCh0aGlzLmJsb2NrLndpZHRoID8/IDgwKSAtIFBST0dSRVNTQkFSX0VYVFJBX1NQQUNFIC0gMSwgTUFYX1BST0dSRVNTQkFSX1dJRFRIKSxcbiAgICAgIE1JTl9QUk9HUkVTU0JBUl9XSURUSCxcbiAgICApO1xuICAgIGNvbnN0IHByb2cgPSB0aGlzLnByb2dyZXNzQmFyKHByb2dyZXNzV2lkdGgpO1xuICAgIGlmIChwcm9nKSB7XG4gICAgICBsaW5lcy5wdXNoKCcgICcgKyBwcm9nLCAnJyk7XG4gICAgfVxuXG4gICAgLy8gTm9ybWFsbHkgd2UnZCBvbmx5IHByaW50IFwicmVzb3VyY2VzIGluIHByb2dyZXNzXCIsIGJ1dCBpdCdzIGFsc28gdXNlZnVsXG4gICAgLy8gdG8ga2VlcCBhbiBleWUgb24gdGhlIGZhaWx1cmVzIGFuZCBrbm93IGFib3V0IHRoZSBzcGVjaWZpYyBlcnJvcnMgYXNxdWlja2x5XG4gICAgLy8gYXMgcG9zc2libGUgKHdoaWxlIHRoZSBzdGFjayBpcyBzdGlsbCByb2xsaW5nIGJhY2spLCBzbyBhZGQgdGhvc2UgaW4uXG4gICAgY29uc3QgdG9QcmludDogU3RhY2tBY3Rpdml0eVtdID0gWy4uLnRoaXMuZmFpbHVyZXMsIC4uLk9iamVjdC52YWx1ZXModGhpcy5yZXNvdXJjZXNJblByb2dyZXNzKV07XG4gICAgdG9QcmludC5zb3J0KChhLCBiKSA9PiBhLmV2ZW50LlRpbWVzdGFtcCEuZ2V0VGltZSgpIC0gYi5ldmVudC5UaW1lc3RhbXAhLmdldFRpbWUoKSk7XG5cbiAgICBsaW5lcy5wdXNoKFxuICAgICAgLi4udG9QcmludC5tYXAoKHJlcykgPT4ge1xuICAgICAgICBjb25zdCBjb2xvciA9IGNvbG9yRnJvbVN0YXR1c0FjdGl2aXR5KHJlcy5ldmVudC5SZXNvdXJjZVN0YXR1cyk7XG4gICAgICAgIGNvbnN0IHJlc291cmNlTmFtZSA9IHJlcy5tZXRhZGF0YT8uY29uc3RydWN0UGF0aCA/PyByZXMuZXZlbnQuTG9naWNhbFJlc291cmNlSWQgPz8gJyc7XG5cbiAgICAgICAgcmV0dXJuIHV0aWwuZm9ybWF0KFxuICAgICAgICAgICclcyB8ICVzIHwgJXMgfCAlcyVzJyxcbiAgICAgICAgICBwYWRMZWZ0KFRJTUVTVEFNUF9XSURUSCwgbmV3IERhdGUocmVzLmV2ZW50LlRpbWVzdGFtcCEpLnRvTG9jYWxlVGltZVN0cmluZygpKSxcbiAgICAgICAgICBjb2xvcihwYWRSaWdodChTVEFUVVNfV0lEVEgsIChyZXMuZXZlbnQuUmVzb3VyY2VTdGF0dXMgfHwgJycpLnNsaWNlKDAsIFNUQVRVU19XSURUSCkpKSxcbiAgICAgICAgICBwYWRSaWdodCh0aGlzLnByb3BzLnJlc291cmNlVHlwZUNvbHVtbldpZHRoLCByZXMuZXZlbnQuUmVzb3VyY2VUeXBlIHx8ICcnKSxcbiAgICAgICAgICBjb2xvcihjaGFsay5ib2xkKHNob3J0ZW4oNDAsIHJlc291cmNlTmFtZSkpKSxcbiAgICAgICAgICB0aGlzLmZhaWx1cmVSZWFzb25Pbk5leHRMaW5lKHJlcyksXG4gICAgICAgICk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgdGhpcy5ibG9jay5kaXNwbGF5TGluZXMobGluZXMpO1xuICB9XG5cbiAgcHVibGljIHN0YXJ0KCkge1xuICAgIC8vIE5lZWQgdG8gcHJldmVudCB0aGUgd2FpdGVyIGZyb20gcHJpbnRpbmcgJ3N0YWNrIG5vdCBzdGFibGUnIGV2ZXJ5IDUgc2Vjb25kcywgaXQgbWVzc2VzXG4gICAgLy8gd2l0aCB0aGUgb3V0cHV0IGNhbGN1bGF0aW9ucy5cbiAgICB0aGlzLm9sZExvZ1RocmVzaG9sZCA9IENsaUlvSG9zdC5pbnN0YW5jZSgpLmxvZ0xldmVsO1xuICAgIENsaUlvSG9zdC5pbnN0YW5jZSgpLmxvZ0xldmVsID0gJ2luZm8nO1xuICB9XG5cbiAgcHVibGljIHN0b3AoKSB7XG4gICAgQ2xpSW9Ib3N0Lmluc3RhbmNlKCkubG9nTGV2ZWwgPSB0aGlzLm9sZExvZ1RocmVzaG9sZDtcblxuICAgIC8vIFByaW50IGZhaWx1cmVzIGF0IHRoZSBlbmRcbiAgICBjb25zdCBsaW5lcyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCBmYWlsdXJlIG9mIHRoaXMuZmFpbHVyZXMpIHtcbiAgICAgIC8vIFJvb3Qgc3RhY2sgZmFpbHVyZXMgYXJlIG5vdCBpbnRlcmVzdGluZ1xuICAgICAgaWYgKGZhaWx1cmUuaXNTdGFja0V2ZW50KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBsaW5lcy5wdXNoKFxuICAgICAgICB1dGlsLmZvcm1hdChcbiAgICAgICAgICBjaGFsay5yZWQoJyVzIHwgJXMgfCAlcyB8ICVzJXMnKSArICdcXG4nLFxuICAgICAgICAgIHBhZExlZnQoVElNRVNUQU1QX1dJRFRILCBuZXcgRGF0ZShmYWlsdXJlLmV2ZW50LlRpbWVzdGFtcCEpLnRvTG9jYWxlVGltZVN0cmluZygpKSxcbiAgICAgICAgICBwYWRSaWdodChTVEFUVVNfV0lEVEgsIChmYWlsdXJlLmV2ZW50LlJlc291cmNlU3RhdHVzIHx8ICcnKS5zbGljZSgwLCBTVEFUVVNfV0lEVEgpKSxcbiAgICAgICAgICBwYWRSaWdodCh0aGlzLnByb3BzLnJlc291cmNlVHlwZUNvbHVtbldpZHRoLCBmYWlsdXJlLmV2ZW50LlJlc291cmNlVHlwZSB8fCAnJyksXG4gICAgICAgICAgc2hvcnRlbig0MCwgZmFpbHVyZS5ldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCA/PyAnJyksXG4gICAgICAgICAgdGhpcy5mYWlsdXJlUmVhc29uT25OZXh0TGluZShmYWlsdXJlKSxcbiAgICAgICAgKSxcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHRyYWNlID0gZmFpbHVyZS5tZXRhZGF0YT8uZW50cnk/LnRyYWNlO1xuICAgICAgaWYgKHRyYWNlKSB7XG4gICAgICAgIGxpbmVzLnB1c2goY2hhbGsucmVkKGBcXHQke3RyYWNlLmpvaW4oJ1xcblxcdFxcXFxfICcpfVxcbmApKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXNwbGF5IGluIHRoZSBzYW1lIGJsb2NrIHNwYWNlLCBvdGhlcndpc2Ugd2UncmUgZ29pbmcgdG8gaGF2ZSBzaWxseSBlbXB0eSBsaW5lcy5cbiAgICB0aGlzLmJsb2NrLmRpc3BsYXlMaW5lcyhsaW5lcyk7XG4gICAgdGhpcy5ibG9jay5yZW1vdmVFbXB0eUxpbmVzKCk7XG4gIH1cblxuICBwcml2YXRlIHByb2dyZXNzQmFyKHdpZHRoOiBudW1iZXIpIHtcbiAgICBpZiAoIXRoaXMucmVzb3VyY2VzVG90YWwpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgY29uc3QgZnJhY3Rpb24gPSBNYXRoLm1pbih0aGlzLnJlc291cmNlc0RvbmUgLyB0aGlzLnJlc291cmNlc1RvdGFsLCAxKTtcbiAgICBjb25zdCBpbm5lcldpZHRoID0gTWF0aC5tYXgoMSwgd2lkdGggLSAyKTtcbiAgICBjb25zdCBjaGFycyA9IGlubmVyV2lkdGggKiBmcmFjdGlvbjtcbiAgICBjb25zdCByZW1haW5kZXIgPSBjaGFycyAtIE1hdGguZmxvb3IoY2hhcnMpO1xuXG4gICAgY29uc3QgZnVsbENoYXJzID0gRlVMTF9CTE9DSy5yZXBlYXQoTWF0aC5mbG9vcihjaGFycykpO1xuICAgIGNvbnN0IHBhcnRpYWxDaGFyID0gUEFSVElBTF9CTE9DS1tNYXRoLmZsb29yKHJlbWFpbmRlciAqIFBBUlRJQUxfQkxPQ0subGVuZ3RoKV07XG4gICAgY29uc3QgZmlsbGVyID0gJ8K3Jy5yZXBlYXQoaW5uZXJXaWR0aCAtIE1hdGguZmxvb3IoY2hhcnMpIC0gKHBhcnRpYWxDaGFyID8gMSA6IDApKTtcblxuICAgIGNvbnN0IGNvbG9yID0gdGhpcy5yb2xsaW5nQmFjayA/IGNoYWxrLnllbGxvdyA6IGNoYWxrLmdyZWVuO1xuXG4gICAgcmV0dXJuICdbJyArIGNvbG9yKGZ1bGxDaGFycyArIHBhcnRpYWxDaGFyKSArIGZpbGxlciArIGBdICgke3RoaXMucmVzb3VyY2VzRG9uZX0vJHt0aGlzLnJlc291cmNlc1RvdGFsfSlgO1xuICB9XG5cbiAgcHJpdmF0ZSBmYWlsdXJlUmVhc29uT25OZXh0TGluZShhY3Rpdml0eTogU3RhY2tBY3Rpdml0eSkge1xuICAgIHJldHVybiBoYXNFcnJvck1lc3NhZ2UoYWN0aXZpdHkuZXZlbnQuUmVzb3VyY2VTdGF0dXMgPz8gJycpXG4gICAgICA/IGBcXG4keycgJy5yZXBlYXQoVElNRVNUQU1QX1dJRFRIICsgU1RBVFVTX1dJRFRIICsgNil9JHtjaGFsay5yZWQodGhpcy5mYWlsdXJlUmVhc29uKGFjdGl2aXR5KSA/PyAnJyl9YFxuICAgICAgOiAnJztcbiAgfVxufVxuXG5jb25zdCBGVUxMX0JMT0NLID0gJ+KWiCc7XG5jb25zdCBQQVJUSUFMX0JMT0NLID0gWycnLCAn4paPJywgJ+KWjicsICfilo0nLCAn4paMJywgJ+KWiycsICfiloonLCAn4paJJ107XG5jb25zdCBNQVhfUFJPR1JFU1NCQVJfV0lEVEggPSA2MDtcbmNvbnN0IE1JTl9QUk9HUkVTU0JBUl9XSURUSCA9IDEwO1xuY29uc3QgUFJPR1JFU1NCQVJfRVhUUkFfU1BBQ0UgPVxuICAyIC8qIGxlYWRpbmcgc3BhY2VzICovICsgMiAvKiBicmFja2V0cyAqLyArIDQgLyogcHJvZ3Jlc3MgbnVtYmVyIGRlY29yYXRpb24gKi8gKyA2OyAvKiAyIHByb2dyZXNzIG51bWJlcnMgdXAgdG8gOTk5ICovXG5cbmZ1bmN0aW9uIGhhc0Vycm9yTWVzc2FnZShzdGF0dXM6IHN0cmluZykge1xuICByZXR1cm4gc3RhdHVzLmVuZHNXaXRoKCdfRkFJTEVEJykgfHwgc3RhdHVzID09PSAnUk9MTEJBQ0tfSU5fUFJPR1JFU1MnIHx8IHN0YXR1cyA9PT0gJ1VQREFURV9ST0xMQkFDS19JTl9QUk9HUkVTUyc7XG59XG5cbmZ1bmN0aW9uIGNvbG9yRnJvbVN0YXR1c1Jlc3VsdChzdGF0dXM/OiBzdHJpbmcpIHtcbiAgaWYgKCFzdGF0dXMpIHtcbiAgICByZXR1cm4gY2hhbGsucmVzZXQ7XG4gIH1cblxuICBpZiAoc3RhdHVzLmluZGV4T2YoJ0ZBSUxFRCcpICE9PSAtMSkge1xuICAgIHJldHVybiBjaGFsay5yZWQ7XG4gIH1cbiAgaWYgKHN0YXR1cy5pbmRleE9mKCdST0xMQkFDSycpICE9PSAtMSkge1xuICAgIHJldHVybiBjaGFsay55ZWxsb3c7XG4gIH1cbiAgaWYgKHN0YXR1cy5pbmRleE9mKCdDT01QTEVURScpICE9PSAtMSkge1xuICAgIHJldHVybiBjaGFsay5ncmVlbjtcbiAgfVxuXG4gIHJldHVybiBjaGFsay5yZXNldDtcbn1cblxuZnVuY3Rpb24gY29sb3JGcm9tU3RhdHVzQWN0aXZpdHkoc3RhdHVzPzogc3RyaW5nKSB7XG4gIGlmICghc3RhdHVzKSB7XG4gICAgcmV0dXJuIGNoYWxrLnJlc2V0O1xuICB9XG5cbiAgaWYgKHN0YXR1cy5lbmRzV2l0aCgnX0ZBSUxFRCcpKSB7XG4gICAgcmV0dXJuIGNoYWxrLnJlZDtcbiAgfVxuXG4gIGlmIChzdGF0dXMuc3RhcnRzV2l0aCgnQ1JFQVRFXycpIHx8IHN0YXR1cy5zdGFydHNXaXRoKCdVUERBVEVfJykgfHwgc3RhdHVzLnN0YXJ0c1dpdGgoJ0lNUE9SVF8nKSkge1xuICAgIHJldHVybiBjaGFsay5ncmVlbjtcbiAgfVxuICAvLyBGb3Igc3RhY2tzLCBpdCBtYXkgYWxzbyBiZSAnVVBEREFURV9ST0xMQkFDS19JTl9QUk9HUkVTUydcbiAgaWYgKHN0YXR1cy5pbmRleE9mKCdST0xMQkFDS18nKSAhPT0gLTEpIHtcbiAgICByZXR1cm4gY2hhbGsueWVsbG93O1xuICB9XG4gIGlmIChzdGF0dXMuc3RhcnRzV2l0aCgnREVMRVRFXycpKSB7XG4gICAgcmV0dXJuIGNoYWxrLnllbGxvdztcbiAgfVxuXG4gIHJldHVybiBjaGFsay5yZXNldDtcbn1cblxuZnVuY3Rpb24gc2hvcnRlbihtYXhXaWR0aDogbnVtYmVyLCBwOiBzdHJpbmcpIHtcbiAgaWYgKHAubGVuZ3RoIDw9IG1heFdpZHRoKSB7XG4gICAgcmV0dXJuIHA7XG4gIH1cbiAgY29uc3QgaGFsZiA9IE1hdGguZmxvb3IoKG1heFdpZHRoIC0gMykgLyAyKTtcbiAgcmV0dXJuIHAuc2xpY2UoMCwgaGFsZikgKyAnLi4uJyArIHAuc2xpY2UoLWhhbGYpO1xufVxuXG5jb25zdCBUSU1FU1RBTVBfV0lEVEggPSAxMjtcbmNvbnN0IFNUQVRVU19XSURUSCA9IDIwO1xuIl19
|