From 98ff399ee6089fa9313b35f93f4859479b3666f3 Mon Sep 17 00:00:00 2001 From: wm <569287825@qq.com> Date: Tue, 28 Jun 2016 10:22:53 +0800 Subject: [PATCH] =?UTF-8?q?=E2=80=9CV=5F1.0=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bowerrc | 3 + .gitignore | 9 + Dockerfile | 22 + LICENSE.txt | 202 + ReadMe.md | 61 + app/controllerHelp.js | 0 app/my.js | 37 + app/resumable-node.js | 213 + app/resumable.js | 1086 + app/style.css | 216 + app/xmloperation.js | 558 + bower.json | 63 + circle.yml | 29 + d.ts/developer/ts/FileMode.d.ts | 7 + d.ts/developer/ts/dataInfnModel.d.ts | 7 + d.ts/developer/ts/developerEnrichers.d.ts | 16 + d.ts/developer/ts/developerHelpers.d.ts | 25 + d.ts/developer/ts/developerNavigation.d.ts | 28 + d.ts/developer/ts/developerPlugin.d.ts | 10 + d.ts/developer/ts/environmentPanel.d.ts | 3 + d.ts/developer/ts/home.d.ts | 8 + d.ts/developer/ts/jenkinsJob.d.ts | 8 + d.ts/developer/ts/jenkinsJobs.d.ts | 8 + d.ts/developer/ts/jenkinsLog.d.ts | 12 + d.ts/developer/ts/jenkinsMetrics.d.ts | 8 + d.ts/developer/ts/navbar.d.ts | 8 + d.ts/developer/ts/pipeline.d.ts | 8 + d.ts/developer/ts/pipelineDirective.d.ts | 7 + d.ts/developer/ts/pipelines.d.ts | 9 + d.ts/developer/ts/project.d.ts | 8 + d.ts/developer/ts/projectSelector.d.ts | 3 + d.ts/developer/ts/projects.d.ts | 8 + d.ts/developer/ts/workspace.d.ts | 8 + d.ts/developer/ts/workspaces.d.ts | 8 + d.ts/includes.d.ts | 7 + d.ts/kubernetes/ts/apps.d.ts | 5 + d.ts/kubernetes/ts/breadcrumbs.d.ts | 5 + d.ts/kubernetes/ts/build.d.ts | 6 + d.ts/kubernetes/ts/buildConfig.d.ts | 6 + d.ts/kubernetes/ts/buildConfigEdit.d.ts | 6 + d.ts/kubernetes/ts/buildConfigs.d.ts | 5 + d.ts/kubernetes/ts/buildLogs.d.ts | 6 + d.ts/kubernetes/ts/builds.d.ts | 5 + d.ts/kubernetes/ts/connect.d.ts | 6 + d.ts/kubernetes/ts/dataInfnModel.d.ts | 33 + d.ts/kubernetes/ts/deployConfigs.d.ts | 5 + d.ts/kubernetes/ts/deploymentConfig.d.ts | 6 + d.ts/kubernetes/ts/deploymentConfigs.d.ts | 5 + d.ts/kubernetes/ts/editPod.d.ts | 6 + d.ts/kubernetes/ts/events.d.ts | 6 + d.ts/kubernetes/ts/host.d.ts | 7 + d.ts/kubernetes/ts/hosts.d.ts | 7 + d.ts/kubernetes/ts/imageRepositories.d.ts | 5 + d.ts/kubernetes/ts/kubernetesHelpers.d.ts | 208 + d.ts/kubernetes/ts/kubernetesInterfaces.d.ts | 98 + .../ts/kubernetesJsonDirective.d.ts | 6 + d.ts/kubernetes/ts/kubernetesModel.d.ts | 54 + d.ts/kubernetes/ts/kubernetesNavigation.d.ts | 5 + d.ts/kubernetes/ts/kubernetesPlugin.d.ts | 13 + d.ts/kubernetes/ts/kubernetesSchema.d.ts | 4 + d.ts/kubernetes/ts/kubernetesServices.d.ts | 3 + d.ts/kubernetes/ts/kubernetesTopLevel.d.ts | 9 + d.ts/kubernetes/ts/namespace.d.ts | 4 + d.ts/kubernetes/ts/oracleStatusModel.d.ts | 9 + d.ts/kubernetes/ts/overview.d.ts | 5 + d.ts/kubernetes/ts/pipelines.d.ts | 5 + d.ts/kubernetes/ts/pod.d.ts | 6 + d.ts/kubernetes/ts/podEdit.d.ts | 6 + d.ts/kubernetes/ts/podLogs.d.ts | 4 + d.ts/kubernetes/ts/pods.d.ts | 7 + d.ts/kubernetes/ts/replicationController.d.ts | 6 + .../ts/replicationControllerEdit.d.ts | 6 + .../kubernetes/ts/replicationControllers.d.ts | 6 + d.ts/kubernetes/ts/schema.d.ts | 6677 ++++++ d.ts/kubernetes/ts/schemaHelpers.d.ts | 5 + d.ts/kubernetes/ts/secret.d.ts | 6 + d.ts/kubernetes/ts/secrets.d.ts | 7 + d.ts/kubernetes/ts/service.d.ts | 6 + d.ts/kubernetes/ts/serviceEdit.d.ts | 6 + d.ts/kubernetes/ts/serviceRegistry.d.ts | 39 + d.ts/kubernetes/ts/services.d.ts | 7 + d.ts/kubernetes/ts/sharedControllers.d.ts | 8 + d.ts/kubernetes/ts/tabs.d.ts | 5 + d.ts/kubernetes/ts/templates.d.ts | 4 + d.ts/kubernetes/ts/term.d.ts | 5 + d.ts/kubernetes/ts/utilHelpers.d.ts | 56 + d.ts/kubernetes/ts/watcher.d.ts | 3 + d.ts/navigation/ts/navigationPlugin.d.ts | 6 + d.ts/service/ts/serviceHelpers.d.ts | 30 + d.ts/service/ts/servicePlugin.d.ts | 19 + defs.d.ts | 71 + dist/hawtio-console-assembly.css | 108 + dist/hawtio-kubernetes.css | 1025 + dist/hawtio-kubernetes.js | 17918 ++++++++++++++++ dist/img/host.svg | 316 + dist/img/kubernetes.svg | 451 + gulpfile.js | 703 + hawtio-kubernetes.iml | 9 + img/host.svg | 316 + img/icons1.gif | Bin 0 -> 62 bytes img/icons2.gif | Bin 0 -> 61 bytes img/kubernetes.svg | 451 + index.html | 168 + my.js | 24 + osconsole/config.js.tmpl | 7 + package.json | 41 + plugins/developer/html/addDataFile.html | 145 + plugins/developer/html/code.html | 51 + plugins/developer/html/environment.html | 1 + plugins/developer/html/environmentPanel.html | 87 + plugins/developer/html/environments.html | 100 + plugins/developer/html/home.html | 38 + .../developer/html/jenkinsApproveModal.html | 10 + plugins/developer/html/jenkinsJob.html | 79 + plugins/developer/html/jenkinsJobs.html | 97 + plugins/developer/html/jenkinsLog.html | 39 + plugins/developer/html/jenkinsMetrics.html | 27 + plugins/developer/html/logPanel.html | 7 + plugins/developer/html/overview | 0 plugins/developer/html/pipeline.html | 40 + plugins/developer/html/pipelineView.html | 77 + plugins/developer/html/pipelines.html | 44 + plugins/developer/html/projectDetail.html | 36 + plugins/developer/html/projectSelector.html | 13 + plugins/developer/html/projects.html | 126 + plugins/developer/html/tools.html | 51 + plugins/developer/html/workspace.html | 46 + plugins/developer/html/workspaces.html | 75 + plugins/developer/less/environmentPanel.less | 66 + plugins/developer/less/environments.less | 50 + plugins/developer/less/filterHeader.less | 8 + plugins/developer/less/jenkinsLog.less | 25 + plugins/developer/less/projectSelector.less | 14 + plugins/developer/less/style.less | 224 + plugins/developer/ts/FileMode.ts | 40 + plugins/developer/ts/developerEnrichers.ts | 247 + plugins/developer/ts/developerHelpers.ts | 294 + plugins/developer/ts/developerNavigation.ts | 616 + plugins/developer/ts/developerPlugin.ts | 78 + plugins/developer/ts/environmentPanel.ts | 22 + plugins/developer/ts/home.ts | 17 + plugins/developer/ts/jenkinsJob.ts | 94 + plugins/developer/ts/jenkinsJobs.ts | 101 + plugins/developer/ts/jenkinsLog.ts | 350 + plugins/developer/ts/jenkinsMetrics.ts | 181 + plugins/developer/ts/navbar.ts | 25 + plugins/developer/ts/pipeline.ts | 67 + plugins/developer/ts/pipelineDirective.ts | 13 + plugins/developer/ts/pipelines.ts | 165 + plugins/developer/ts/project.ts | 95 + plugins/developer/ts/projectSelector.ts | 19 + plugins/developer/ts/projects.ts | 171 + plugins/developer/ts/workspace.ts | 53 + plugins/developer/ts/workspaces.ts | 454 + plugins/includes.ts | 9 + .../kubernetes/html/appDeployedTemplate.html | 3 + .../kubernetes/html/appDetailTemplate.html | 149 + plugins/kubernetes/html/appIconTemplate.html | 10 + .../html/appPodCountsAndLinkTemplate.html | 9 + .../appReplicationControllerTemplate.html | 14 + .../kubernetes/html/appServicesTemplate.html | 8 + plugins/kubernetes/html/apps.html | 175 + plugins/kubernetes/html/breadcrumbs.html | 10 + plugins/kubernetes/html/build.html | 46 + plugins/kubernetes/html/buildConfig.html | 42 + plugins/kubernetes/html/buildConfigEdit.html | 62 + plugins/kubernetes/html/buildConfigs.html | 122 + plugins/kubernetes/html/buildLogs.html | 45 + plugins/kubernetes/html/builds.html | 111 + plugins/kubernetes/html/deploymentConfig.html | 21 + .../kubernetes/html/deploymentConfigs.html | 67 + plugins/kubernetes/html/events.html | 72 + plugins/kubernetes/html/host.html | 61 + plugins/kubernetes/html/hosts.html | 43 + .../kubernetes/html/imageRepositories.html | 51 + plugins/kubernetes/html/importProject.html | 58 + .../html/kubernetesJsonDirective.html | 32 + plugins/kubernetes/html/layoutKubernetes.html | 220 + plugins/kubernetes/html/logShell.html | 15 + plugins/kubernetes/html/overview.html | 117 + plugins/kubernetes/html/pendingPipelines.html | 20 + plugins/kubernetes/html/pipelines.html | 131 + plugins/kubernetes/html/pod.html | 88 + plugins/kubernetes/html/podCreate.html | 27 + plugins/kubernetes/html/podEdit.html | 27 + plugins/kubernetes/html/pods.html | 87 + .../html/replicationController.html | 89 + .../html/replicationControllerCreate.html | 27 + .../html/replicationControllerEdit.html | 27 + .../html/replicationControllers.html | 88 + plugins/kubernetes/html/secret.html | 157 + plugins/kubernetes/html/secrets.html | 52 + plugins/kubernetes/html/service.html | 68 + plugins/kubernetes/html/serviceApps.html | 16 + plugins/kubernetes/html/serviceCreate.html | 27 + plugins/kubernetes/html/serviceEdit.html | 27 + plugins/kubernetes/html/services.html | 93 + plugins/kubernetes/html/tabs.html | 13 + .../kubernetes/html/templateDescription.html | 9 + plugins/kubernetes/html/templates.html | 90 + plugins/kubernetes/html/termShell.html | 9 + plugins/kubernetes/less/appView.less | 108 + plugins/kubernetes/less/overview.less | 173 + plugins/kubernetes/less/podLog.less | 31 + plugins/kubernetes/less/terminalWindow.less | 84 + plugins/kubernetes/ts/apps.ts | 298 + plugins/kubernetes/ts/breadcrumbs.ts | 17 + plugins/kubernetes/ts/build.ts | 53 + plugins/kubernetes/ts/buildConfig.ts | 56 + plugins/kubernetes/ts/buildConfigEdit.ts | 429 + plugins/kubernetes/ts/buildConfigs.ts | 137 + plugins/kubernetes/ts/buildLogs.ts | 68 + plugins/kubernetes/ts/builds.ts | 131 + plugins/kubernetes/ts/connect.ts | 27 + plugins/kubernetes/ts/dataInfnModel.ts | 192 + plugins/kubernetes/ts/deploymentConfig.ts | 52 + plugins/kubernetes/ts/deploymentConfigs.ts | 124 + plugins/kubernetes/ts/events.ts | 64 + plugins/kubernetes/ts/host.ts | 61 + plugins/kubernetes/ts/hosts.ts | 58 + plugins/kubernetes/ts/imageRepositories.ts | 122 + plugins/kubernetes/ts/kubernetesHelpers.ts | 1792 ++ plugins/kubernetes/ts/kubernetesInterfaces.ts | 147 + plugins/kubernetes/ts/kubernetesModel.ts | 763 + plugins/kubernetes/ts/kubernetesNavigation.ts | 24 + plugins/kubernetes/ts/kubernetesPlugin.ts | 276 + plugins/kubernetes/ts/kubernetesSchema.ts | 77 + plugins/kubernetes/ts/kubernetesServices.ts | 49 + plugins/kubernetes/ts/kubernetesTopLevel.ts | 152 + plugins/kubernetes/ts/namespace.ts | 24 + plugins/kubernetes/ts/oracleStatusModel.ts | 28 + plugins/kubernetes/ts/overview.ts | 283 + plugins/kubernetes/ts/pipelines.ts | 174 + plugins/kubernetes/ts/pod.ts | 71 + plugins/kubernetes/ts/podEdit.ts | 41 + plugins/kubernetes/ts/podLogs.ts | 164 + plugins/kubernetes/ts/pods.ts | 162 + .../kubernetes/ts/replicationController.ts | 57 + .../ts/replicationControllerEdit.ts | 38 + .../kubernetes/ts/replicationControllers.ts | 199 + plugins/kubernetes/ts/schema.ts | 7020 ++++++ plugins/kubernetes/ts/schemaHelpers.ts | 26 + plugins/kubernetes/ts/secret.ts | 250 + plugins/kubernetes/ts/secrets.ts | 76 + plugins/kubernetes/ts/service.ts | 55 + plugins/kubernetes/ts/serviceEdit.ts | 37 + plugins/kubernetes/ts/serviceRegistry.ts | 91 + plugins/kubernetes/ts/services.ts | 102 + plugins/kubernetes/ts/sharedControllers.ts | 127 + plugins/kubernetes/ts/tabs.ts | 14 + plugins/kubernetes/ts/templates.ts | 330 + plugins/kubernetes/ts/term.ts | 288 + plugins/kubernetes/ts/utilHelpers.ts | 181 + plugins/kubernetes/ts/watcher.ts | 276 + plugins/main.less | 252 + plugins/navigation/ts/navigationPlugin.ts | 168 + resumable-node.js | 213 + 257 files changed, 55538 insertions(+) create mode 100644 .bowerrc create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.txt create mode 100644 ReadMe.md create mode 100644 app/controllerHelp.js create mode 100644 app/my.js create mode 100644 app/resumable-node.js create mode 100644 app/resumable.js create mode 100644 app/style.css create mode 100644 app/xmloperation.js create mode 100644 bower.json create mode 100644 circle.yml create mode 100644 d.ts/developer/ts/FileMode.d.ts create mode 100644 d.ts/developer/ts/dataInfnModel.d.ts create mode 100644 d.ts/developer/ts/developerEnrichers.d.ts create mode 100644 d.ts/developer/ts/developerHelpers.d.ts create mode 100644 d.ts/developer/ts/developerNavigation.d.ts create mode 100644 d.ts/developer/ts/developerPlugin.d.ts create mode 100644 d.ts/developer/ts/environmentPanel.d.ts create mode 100644 d.ts/developer/ts/home.d.ts create mode 100644 d.ts/developer/ts/jenkinsJob.d.ts create mode 100644 d.ts/developer/ts/jenkinsJobs.d.ts create mode 100644 d.ts/developer/ts/jenkinsLog.d.ts create mode 100644 d.ts/developer/ts/jenkinsMetrics.d.ts create mode 100644 d.ts/developer/ts/navbar.d.ts create mode 100644 d.ts/developer/ts/pipeline.d.ts create mode 100644 d.ts/developer/ts/pipelineDirective.d.ts create mode 100644 d.ts/developer/ts/pipelines.d.ts create mode 100644 d.ts/developer/ts/project.d.ts create mode 100644 d.ts/developer/ts/projectSelector.d.ts create mode 100644 d.ts/developer/ts/projects.d.ts create mode 100644 d.ts/developer/ts/workspace.d.ts create mode 100644 d.ts/developer/ts/workspaces.d.ts create mode 100644 d.ts/includes.d.ts create mode 100644 d.ts/kubernetes/ts/apps.d.ts create mode 100644 d.ts/kubernetes/ts/breadcrumbs.d.ts create mode 100644 d.ts/kubernetes/ts/build.d.ts create mode 100644 d.ts/kubernetes/ts/buildConfig.d.ts create mode 100644 d.ts/kubernetes/ts/buildConfigEdit.d.ts create mode 100644 d.ts/kubernetes/ts/buildConfigs.d.ts create mode 100644 d.ts/kubernetes/ts/buildLogs.d.ts create mode 100644 d.ts/kubernetes/ts/builds.d.ts create mode 100644 d.ts/kubernetes/ts/connect.d.ts create mode 100644 d.ts/kubernetes/ts/dataInfnModel.d.ts create mode 100644 d.ts/kubernetes/ts/deployConfigs.d.ts create mode 100644 d.ts/kubernetes/ts/deploymentConfig.d.ts create mode 100644 d.ts/kubernetes/ts/deploymentConfigs.d.ts create mode 100644 d.ts/kubernetes/ts/editPod.d.ts create mode 100644 d.ts/kubernetes/ts/events.d.ts create mode 100644 d.ts/kubernetes/ts/host.d.ts create mode 100644 d.ts/kubernetes/ts/hosts.d.ts create mode 100644 d.ts/kubernetes/ts/imageRepositories.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesHelpers.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesInterfaces.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesJsonDirective.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesModel.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesNavigation.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesPlugin.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesSchema.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesServices.d.ts create mode 100644 d.ts/kubernetes/ts/kubernetesTopLevel.d.ts create mode 100644 d.ts/kubernetes/ts/namespace.d.ts create mode 100644 d.ts/kubernetes/ts/oracleStatusModel.d.ts create mode 100644 d.ts/kubernetes/ts/overview.d.ts create mode 100644 d.ts/kubernetes/ts/pipelines.d.ts create mode 100644 d.ts/kubernetes/ts/pod.d.ts create mode 100644 d.ts/kubernetes/ts/podEdit.d.ts create mode 100644 d.ts/kubernetes/ts/podLogs.d.ts create mode 100644 d.ts/kubernetes/ts/pods.d.ts create mode 100644 d.ts/kubernetes/ts/replicationController.d.ts create mode 100644 d.ts/kubernetes/ts/replicationControllerEdit.d.ts create mode 100644 d.ts/kubernetes/ts/replicationControllers.d.ts create mode 100644 d.ts/kubernetes/ts/schema.d.ts create mode 100644 d.ts/kubernetes/ts/schemaHelpers.d.ts create mode 100644 d.ts/kubernetes/ts/secret.d.ts create mode 100644 d.ts/kubernetes/ts/secrets.d.ts create mode 100644 d.ts/kubernetes/ts/service.d.ts create mode 100644 d.ts/kubernetes/ts/serviceEdit.d.ts create mode 100644 d.ts/kubernetes/ts/serviceRegistry.d.ts create mode 100644 d.ts/kubernetes/ts/services.d.ts create mode 100644 d.ts/kubernetes/ts/sharedControllers.d.ts create mode 100644 d.ts/kubernetes/ts/tabs.d.ts create mode 100644 d.ts/kubernetes/ts/templates.d.ts create mode 100644 d.ts/kubernetes/ts/term.d.ts create mode 100644 d.ts/kubernetes/ts/utilHelpers.d.ts create mode 100644 d.ts/kubernetes/ts/watcher.d.ts create mode 100644 d.ts/navigation/ts/navigationPlugin.d.ts create mode 100644 d.ts/service/ts/serviceHelpers.d.ts create mode 100644 d.ts/service/ts/servicePlugin.d.ts create mode 100644 defs.d.ts create mode 100644 dist/hawtio-console-assembly.css create mode 100644 dist/hawtio-kubernetes.css create mode 100644 dist/hawtio-kubernetes.js create mode 100644 dist/img/host.svg create mode 100644 dist/img/kubernetes.svg create mode 100644 gulpfile.js create mode 100644 hawtio-kubernetes.iml create mode 100644 img/host.svg create mode 100644 img/icons1.gif create mode 100644 img/icons2.gif create mode 100644 img/kubernetes.svg create mode 100644 index.html create mode 100644 my.js create mode 100644 osconsole/config.js.tmpl create mode 100644 package.json create mode 100644 plugins/developer/html/addDataFile.html create mode 100644 plugins/developer/html/code.html create mode 100644 plugins/developer/html/environment.html create mode 100644 plugins/developer/html/environmentPanel.html create mode 100644 plugins/developer/html/environments.html create mode 100644 plugins/developer/html/home.html create mode 100644 plugins/developer/html/jenkinsApproveModal.html create mode 100644 plugins/developer/html/jenkinsJob.html create mode 100644 plugins/developer/html/jenkinsJobs.html create mode 100644 plugins/developer/html/jenkinsLog.html create mode 100644 plugins/developer/html/jenkinsMetrics.html create mode 100644 plugins/developer/html/logPanel.html create mode 100644 plugins/developer/html/overview create mode 100644 plugins/developer/html/pipeline.html create mode 100644 plugins/developer/html/pipelineView.html create mode 100644 plugins/developer/html/pipelines.html create mode 100644 plugins/developer/html/projectDetail.html create mode 100644 plugins/developer/html/projectSelector.html create mode 100644 plugins/developer/html/projects.html create mode 100644 plugins/developer/html/tools.html create mode 100644 plugins/developer/html/workspace.html create mode 100644 plugins/developer/html/workspaces.html create mode 100644 plugins/developer/less/environmentPanel.less create mode 100644 plugins/developer/less/environments.less create mode 100644 plugins/developer/less/filterHeader.less create mode 100644 plugins/developer/less/jenkinsLog.less create mode 100644 plugins/developer/less/projectSelector.less create mode 100644 plugins/developer/less/style.less create mode 100644 plugins/developer/ts/FileMode.ts create mode 100644 plugins/developer/ts/developerEnrichers.ts create mode 100644 plugins/developer/ts/developerHelpers.ts create mode 100644 plugins/developer/ts/developerNavigation.ts create mode 100644 plugins/developer/ts/developerPlugin.ts create mode 100644 plugins/developer/ts/environmentPanel.ts create mode 100644 plugins/developer/ts/home.ts create mode 100644 plugins/developer/ts/jenkinsJob.ts create mode 100644 plugins/developer/ts/jenkinsJobs.ts create mode 100644 plugins/developer/ts/jenkinsLog.ts create mode 100644 plugins/developer/ts/jenkinsMetrics.ts create mode 100644 plugins/developer/ts/navbar.ts create mode 100644 plugins/developer/ts/pipeline.ts create mode 100644 plugins/developer/ts/pipelineDirective.ts create mode 100644 plugins/developer/ts/pipelines.ts create mode 100644 plugins/developer/ts/project.ts create mode 100644 plugins/developer/ts/projectSelector.ts create mode 100644 plugins/developer/ts/projects.ts create mode 100644 plugins/developer/ts/workspace.ts create mode 100644 plugins/developer/ts/workspaces.ts create mode 100644 plugins/includes.ts create mode 100644 plugins/kubernetes/html/appDeployedTemplate.html create mode 100644 plugins/kubernetes/html/appDetailTemplate.html create mode 100644 plugins/kubernetes/html/appIconTemplate.html create mode 100644 plugins/kubernetes/html/appPodCountsAndLinkTemplate.html create mode 100644 plugins/kubernetes/html/appReplicationControllerTemplate.html create mode 100644 plugins/kubernetes/html/appServicesTemplate.html create mode 100644 plugins/kubernetes/html/apps.html create mode 100644 plugins/kubernetes/html/breadcrumbs.html create mode 100644 plugins/kubernetes/html/build.html create mode 100644 plugins/kubernetes/html/buildConfig.html create mode 100644 plugins/kubernetes/html/buildConfigEdit.html create mode 100644 plugins/kubernetes/html/buildConfigs.html create mode 100644 plugins/kubernetes/html/buildLogs.html create mode 100644 plugins/kubernetes/html/builds.html create mode 100644 plugins/kubernetes/html/deploymentConfig.html create mode 100644 plugins/kubernetes/html/deploymentConfigs.html create mode 100644 plugins/kubernetes/html/events.html create mode 100644 plugins/kubernetes/html/host.html create mode 100644 plugins/kubernetes/html/hosts.html create mode 100644 plugins/kubernetes/html/imageRepositories.html create mode 100644 plugins/kubernetes/html/importProject.html create mode 100644 plugins/kubernetes/html/kubernetesJsonDirective.html create mode 100644 plugins/kubernetes/html/layoutKubernetes.html create mode 100644 plugins/kubernetes/html/logShell.html create mode 100644 plugins/kubernetes/html/overview.html create mode 100644 plugins/kubernetes/html/pendingPipelines.html create mode 100644 plugins/kubernetes/html/pipelines.html create mode 100644 plugins/kubernetes/html/pod.html create mode 100644 plugins/kubernetes/html/podCreate.html create mode 100644 plugins/kubernetes/html/podEdit.html create mode 100644 plugins/kubernetes/html/pods.html create mode 100644 plugins/kubernetes/html/replicationController.html create mode 100644 plugins/kubernetes/html/replicationControllerCreate.html create mode 100644 plugins/kubernetes/html/replicationControllerEdit.html create mode 100644 plugins/kubernetes/html/replicationControllers.html create mode 100644 plugins/kubernetes/html/secret.html create mode 100644 plugins/kubernetes/html/secrets.html create mode 100644 plugins/kubernetes/html/service.html create mode 100644 plugins/kubernetes/html/serviceApps.html create mode 100644 plugins/kubernetes/html/serviceCreate.html create mode 100644 plugins/kubernetes/html/serviceEdit.html create mode 100644 plugins/kubernetes/html/services.html create mode 100644 plugins/kubernetes/html/tabs.html create mode 100644 plugins/kubernetes/html/templateDescription.html create mode 100644 plugins/kubernetes/html/templates.html create mode 100644 plugins/kubernetes/html/termShell.html create mode 100644 plugins/kubernetes/less/appView.less create mode 100644 plugins/kubernetes/less/overview.less create mode 100644 plugins/kubernetes/less/podLog.less create mode 100644 plugins/kubernetes/less/terminalWindow.less create mode 100644 plugins/kubernetes/ts/apps.ts create mode 100644 plugins/kubernetes/ts/breadcrumbs.ts create mode 100644 plugins/kubernetes/ts/build.ts create mode 100644 plugins/kubernetes/ts/buildConfig.ts create mode 100644 plugins/kubernetes/ts/buildConfigEdit.ts create mode 100644 plugins/kubernetes/ts/buildConfigs.ts create mode 100644 plugins/kubernetes/ts/buildLogs.ts create mode 100644 plugins/kubernetes/ts/builds.ts create mode 100644 plugins/kubernetes/ts/connect.ts create mode 100644 plugins/kubernetes/ts/dataInfnModel.ts create mode 100644 plugins/kubernetes/ts/deploymentConfig.ts create mode 100644 plugins/kubernetes/ts/deploymentConfigs.ts create mode 100644 plugins/kubernetes/ts/events.ts create mode 100644 plugins/kubernetes/ts/host.ts create mode 100644 plugins/kubernetes/ts/hosts.ts create mode 100644 plugins/kubernetes/ts/imageRepositories.ts create mode 100644 plugins/kubernetes/ts/kubernetesHelpers.ts create mode 100644 plugins/kubernetes/ts/kubernetesInterfaces.ts create mode 100644 plugins/kubernetes/ts/kubernetesModel.ts create mode 100644 plugins/kubernetes/ts/kubernetesNavigation.ts create mode 100644 plugins/kubernetes/ts/kubernetesPlugin.ts create mode 100644 plugins/kubernetes/ts/kubernetesSchema.ts create mode 100644 plugins/kubernetes/ts/kubernetesServices.ts create mode 100644 plugins/kubernetes/ts/kubernetesTopLevel.ts create mode 100644 plugins/kubernetes/ts/namespace.ts create mode 100644 plugins/kubernetes/ts/oracleStatusModel.ts create mode 100644 plugins/kubernetes/ts/overview.ts create mode 100644 plugins/kubernetes/ts/pipelines.ts create mode 100644 plugins/kubernetes/ts/pod.ts create mode 100644 plugins/kubernetes/ts/podEdit.ts create mode 100644 plugins/kubernetes/ts/podLogs.ts create mode 100644 plugins/kubernetes/ts/pods.ts create mode 100644 plugins/kubernetes/ts/replicationController.ts create mode 100644 plugins/kubernetes/ts/replicationControllerEdit.ts create mode 100644 plugins/kubernetes/ts/replicationControllers.ts create mode 100644 plugins/kubernetes/ts/schema.ts create mode 100644 plugins/kubernetes/ts/schemaHelpers.ts create mode 100644 plugins/kubernetes/ts/secret.ts create mode 100644 plugins/kubernetes/ts/secrets.ts create mode 100644 plugins/kubernetes/ts/service.ts create mode 100644 plugins/kubernetes/ts/serviceEdit.ts create mode 100644 plugins/kubernetes/ts/serviceRegistry.ts create mode 100644 plugins/kubernetes/ts/services.ts create mode 100644 plugins/kubernetes/ts/sharedControllers.ts create mode 100644 plugins/kubernetes/ts/tabs.ts create mode 100644 plugins/kubernetes/ts/templates.ts create mode 100644 plugins/kubernetes/ts/term.ts create mode 100644 plugins/kubernetes/ts/utilHelpers.ts create mode 100644 plugins/kubernetes/ts/watcher.ts create mode 100644 plugins/main.less create mode 100644 plugins/navigation/ts/navigationPlugin.ts create mode 100644 resumable-node.js diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..88ecdf0 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory" : "libs" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17d1aba --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +node_modules/ +libs/ +site/ +.idea +*.cer +*.req +*.key +serial +osconsole/config.js diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c918726 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM centos:centos7 +MAINTAINER Jimmi Dyson +ENTRYPOINT ["/kuisp"] +CMD [ "-p", "9090", \ + "-c", "/site/osconsole/config.js.tmpl=/site/osconsole/config.js", \ + "--default-page=/index.html", \ + "--max-age=24h", \ + "--compress" ] +EXPOSE 9090 + +ENV KUISP_VERSION 0.10 + +RUN yum install -y tar && \ + yum clean all && \ + curl -L https://github.com/jimmidyson/kuisp/releases/download/v${KUISP_VERSION}/kuisp-${KUISP_VERSION}-linux-amd64.tar.gz | \ + tar xzv + +COPY site /site/ +RUN chmod 777 /site/osconsole/ + +WORKDIR /site/ +USER nobody diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..85f4e53 --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,61 @@ +## hawtio-kubernetes [![Circle CI](https://circleci.com/gh/hawtio/hawtio-kubernetes.svg?style=svg)](https://circleci.com/gh/hawtio/hawtio-kubernetes) + +This plugin provides a [Kubernetes](http://kubernetes.io/) console for hawtio + +![controllers tab screenshot](http://fabric8.io/v2/images/controllers.png) + +### Running + +#### Running a release + +If you have a [Kubernetes](http://kubernetes.io/) or [OpenShift](http://www.openshift.org/) environment, the easiest way to try out this console is to just run the app directly in kubernetes via [these instructions](http://fabric8.io/v2/console.html#running-the-console-on-kubernetesopenshift) + +Or you can try running the [fabric8/hawtio-kubernetes docker image](https://registry.hub.docker.com/u/fabric8/hawtio-kubernetes/): + + docker pull fabric8/hawtio-kubernetes + docker run -it -p 9090:9090 -e KUBERNETES_SERVICE_HOST=$DOCKER_IP fabric8/hawtio-kubernetes + +Where **DOCKER_IP** is the IP address or host running the kubernetes master. + +#### Running this plugin locally + +First clone the source + + git clone https://github.com/hawtio/hawtio-kubernetes.git + cd hawtio-kubernetes + +Next you'll need to [install NodeJS](http://nodejs.org/download/) and then install the default global npm dependencies: + + npm install -g bower gulp slush slush-hawtio-javascript slush-hawtio-typescript typescript + +Then install all local nodejs packages and update bower dependencies via: + + npm install + bower update + +Next you need to setup the **KUBERNETES_MASTER** environment variable to point to the kubernetes master you want to run against. e.g. + + export KUBERNETES_MASTER=https://$DOCKER_IP:8443 + +Where **DOCKER_IP** is the IP address or host running the kubernetes master. + +If you need to disable OAUTH authentication in development try use **DISABLE_OAUTH**: + + export DISABLE_OAUTH=true + +Then to run the web application: + + gulp + +#### Install the bower package + +`bower install --save hawtio-kubernetes` + +#### Output build to a different directory + +When developing this plugin in a dependent console you can change the output directory where the compiled .js and .css go. Just use the 'out' flag to set a different output directory, for example: + +`gulp watch --out=../fabric8-console/libs/hawtio-kubernetes/dist/` + +Whenever the build completes the compiled .js file will be put into the target directory. Don't forget to first do a `gulp build` without this flag before committing changes! + diff --git a/app/controllerHelp.js b/app/controllerHelp.js new file mode 100644 index 0000000..e69de29 diff --git a/app/my.js b/app/my.js new file mode 100644 index 0000000..0fc0e5b --- /dev/null +++ b/app/my.js @@ -0,0 +1,37 @@ +function Recursion(node){ + var count=0; + for (var key in node) { + count++; + var value = node[key]; + delete node[key]; + //如果node为叶子节点 + if (key.toString() == '$') { + for (var attr in value) + node[attr] = value[attr]; + } else { + if (value instanceof Array) { + if (value.length > 0) { + node["children"] = value; + for (var obj in value) + Recursion(value[obj]); + } + } + } + } + if(count==1) + node["children"]=[]; +} + +function randomString(len) { + len = len || 32; + var $chars = 'abcdefhijkmnprstwxyz'; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1 + var maxPos = $chars.length; + var pwd = ''; + for (i = 0; i < len; i++) { + pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); + } + return pwd; +} + +exports.randomString=randomString; +exports.Recursion=Recursion; diff --git a/app/resumable-node.js b/app/resumable-node.js new file mode 100644 index 0000000..6389c7a --- /dev/null +++ b/app/resumable-node.js @@ -0,0 +1,213 @@ +var fs = require('fs'), path = require('path'), util = require('util'), Stream = require('stream').Stream; + + + +module.exports = resumable = function(temporaryFolder){ + var $ = this; + $.temporaryFolder = temporaryFolder; + $.maxFileSize = null; + $.fileParameterName = 'file'; + + try { + fs.mkdirSync($.temporaryFolder); + }catch(e){} + + + var cleanIdentifier = function(identifier){ + return identifier.replace(/^0-9A-Za-z_-/img, ''); + } + + var getChunkFilename = function(chunkNumber, identifier){ + // Clean up the identifier + identifier = cleanIdentifier(identifier); + // What would the file name be? + return path.join($.temporaryFolder, './resumable-'+identifier+'.'+chunkNumber); + } + + var validateRequest = function(chunkNumber, chunkSize, totalSize, identifier, filename, fileSize){ + // Clean up the identifier + identifier = cleanIdentifier(identifier); + + // Check if the request is sane + if (chunkNumber==0 || chunkSize==0 || totalSize==0 || identifier.length==0 || filename.length==0) { + return 'non_resumable_request'; + } + var numberOfChunks = Math.max(Math.floor(totalSize/(chunkSize*1.0)), 1); + if (chunkNumber>numberOfChunks) { + return 'invalid_resumable_request1'; + } + + // Is the file too big? + if($.maxFileSize && totalSize>$.maxFileSize) { + return 'invalid_resumable_request2'; + } + + if(typeof(fileSize)!='undefined') { + if(chunkNumber1 && chunkNumber==numberOfChunks && fileSize!=((totalSize%chunkSize)+chunkSize)) { + // The chunks in the POST is the last one, and the fil is not the correct size + return 'invalid_resumable_request4'; + } + if(numberOfChunks==1 && fileSize!=totalSize) { + // The file is only a single chunk, and the data size does not fit + return 'invalid_resumable_request5'; + } + } + + return 'valid'; + } + + //'found', filename, original_filename, identifier + //'not_found', null, null, null + $.get = function(req, callback){ + var chunkNumber = req.param('resumableChunkNumber', 0); + var chunkSize = req.param('resumableChunkSize', 0); + var totalSize = req.param('resumableTotalSize', 0); + var identifier = req.param('resumableIdentifier', ""); + var filename = req.param('resumableFilename', ""); + + if(validateRequest(chunkNumber, chunkSize, totalSize, identifier, filename)=='valid') { + var chunkFilename = getChunkFilename(chunkNumber, identifier); + fs.exists(chunkFilename, function(exists){ + if(exists){ + callback('found', chunkFilename, filename, identifier); + } else { + callback('not_found', chunkFilename, filename, identifier); + } + }); + } else { + callback('not_found2', chunkFilename, filename, identifier); + } + } + + //'partly_done', filename, original_filename, identifier + //'done', filename, original_filename, identifier + //'invalid_resumable_request', null, null, null + //'non_resumable_request', null, null, null + $.post = function(req, callback){ + + var fields = req.body; + var files = req.files; + + var chunkNumber = fields['resumableChunkNumber']; + var chunkSize = fields['resumableChunkSize']; + var totalSize = fields['resumableTotalSize']; + var identifier = cleanIdentifier(fields['resumableIdentifier']); + var filename = fields['resumableFilename']; + + var original_filename = fields['resumableIdentifier']; + + if(!files[$.fileParameterName] || !files[$.fileParameterName].size) { + callback('invalid_resumable_request', null, null, null); + return; + } + var validation = validateRequest(chunkNumber, chunkSize, totalSize, identifier, files[$.fileParameterName].size); + if(validation=='valid') { + var chunkFilename = getChunkFilename(chunkNumber, identifier); + + // Save the chunk (TODO: OVERWRITE) + fs.rename(files[$.fileParameterName].path, chunkFilename, function(){ + + // Do we have all the chunks? + var currentTestChunk = 1; + var numberOfChunks = Math.max(Math.floor(totalSize/(chunkSize*1.0)), 1); + var testChunkExists = function(){ + fs.exists(getChunkFilename(currentTestChunk, identifier), function(exists){ + if(exists){ + currentTestChunk++; + if(currentTestChunk>numberOfChunks) { + callback('done', filename, original_filename, identifier); + } else { + // Recursion + testChunkExists(); + } + } else { + callback('partly_done', filename, original_filename, identifier); + } + }); + } + testChunkExists(); + }); + } else { + callback(validation, filename, original_filename, identifier); + } + } + + + // Pipe chunks directly in to an existsing WritableStream + // r.write(identifier, response); + // r.write(identifier, response, {end:false}); + // + // var stream = fs.createWriteStream(filename); + // r.write(identifier, stream); + // stream.on('data', function(data){...}); + // stream.on('end', function(){...}); + $.write = function(identifier, writableStream, options) { + options = options || {}; + options.end = (typeof options['end'] == 'undefined' ? true : options['end']); + + // Iterate over each chunk + var pipeChunk = function(number) { + + var chunkFilename = getChunkFilename(number, identifier); + + fs.exists(chunkFilename, function(exists) { + + if (exists) { + // If the chunk with the current number exists, + // then create a ReadStream from the file + // and pipe it to the specified writableStream. + var sourceStream = fs.createReadStream(chunkFilename); + sourceStream.pipe(writableStream, { + end: false + }); + sourceStream.on('end', function() { + // When the chunk is fully streamed, + // jump to the next one + pipeChunk(number + 1); + }); + } else { + // When all the chunks have been piped, end the stream + if (options.end) writableStream.end(); + if (options.onDone) options.onDone(); + } + }); + } + pipeChunk(1); + } + + + $.clean = function(identifier, options) { + options = options || {}; + + // Iterate over each chunk + var pipeChunkRm = function(number) { + + var chunkFilename = getChunkFilename(number, identifier); + + //console.log('removing pipeChunkRm ', number, 'chunkFilename', chunkFilename); + fs.exists(chunkFilename, function(exists) { + if (exists) { + + console.log('exist removing ', chunkFilename); + fs.unlink(chunkFilename, function(err) { + if (err && options.onError) options.onError(err); + }); + + pipeChunkRm(number + 1); + + } else { + + if (options.onDone) options.onDone(); + + } + }); + } + pipeChunkRm(1); + } + + return $; +} diff --git a/app/resumable.js b/app/resumable.js new file mode 100644 index 0000000..67fffb2 --- /dev/null +++ b/app/resumable.js @@ -0,0 +1,1086 @@ +/* +* MIT Licensed +* http://www.23developer.com/opensource +* http://github.com/23/resumable.js +* Steffen Tiedemann Christensen, steffen@23company.com +*/ + +(function(){ +"use strict"; + var clientip=""; + var xmlversion=""; + var Resumable = function(opts){ + if ( !(this instanceof Resumable) ) { + return new Resumable(opts); + } + this.version = 1.0; + // SUPPORTED BY BROWSER? + // Check if these features are support by the browser: + // - File object type + // - Blob object type + // - FileList object type + // - slicing files + this.support = ( + (typeof(File)!=='undefined') + && + (typeof(Blob)!=='undefined') + && + (typeof(FileList)!=='undefined') + && + (!!Blob.prototype.webkitSlice||!!Blob.prototype.mozSlice||!!Blob.prototype.slice||false) + ); + if(!this.support) return(false); + var isnowcheck ="0" + var file_id = ""; + var rootPath = ""; + + // PROPERTIES + var $ = this; + $.files = []; + $.defaults = { + chunkSize:1*1024*1024, + forceChunkSize:false, + simultaneousUploads:3, + fileParameterName:'file', + chunkNumberParameterName: 'resumableChunkNumber', + chunkSizeParameterName: 'resumableChunkSize', + currentChunkSizeParameterName: 'resumableCurrentChunkSize', + totalSizeParameterName: 'resumableTotalSize', + typeParameterName: 'resumableType', + identifierParameterName: 'resumableIdentifier', + fileNameParameterName: 'resumableFilename', + relativePathParameterName: 'resumableRelativePath', + rootPathParameterName: 'resumableRootPath', + totalChunksParameterName: 'resumableTotalChunks', + throttleProgressCallbacks: 0.5, + query:{}, + headers:{}, + preprocess:null, + method:'multipart', + uploadMethod: 'POST', + testMethod: 'GET', + prioritizeFirstAndLastChunk:false, + target:'/', + parameterNamespace:'', + testChunks:true, + generateUniqueIdentifier:null, + getTarget:null, + maxChunkRetries:undefined, + chunkRetryInterval:undefined, + permanentErrors:[400, 404, 415, 500, 501], + maxFiles:undefined, + withCredentials:false, + xhrTimeout:0, + clearInput:true, + maxFilesErrorCallback:function (files, errorCount) { + var maxFiles = $.getOpt('maxFiles'); + alert('Please upload no more than ' + maxFiles + ' file' + (maxFiles === 1 ? '' : 's') + ' at a time.'); + }, + minFileSize:0, + minFileSizeErrorCallback:function(file, errorCount) { + alert(file.fileName||file.name +' is too small, please upload files larger than ' + $h.formatSize($.getOpt('minFileSize')) + '.'); + }, + maxFileSize:undefined, + maxFileSizeErrorCallback:function(file, errorCount) { + alert(file.fileName||file.name +' is too large, please upload files less than ' + $h.formatSize($.getOpt('maxFileSize')) + '.'); + }, + fileType: [], + fileTypeErrorCallback: function(file, errorCount) { + alert(file.fileName||file.name +' has type not allowed, please upload files of type ' + $.getOpt('fileType') + '.'); + } + }; + $.opts = opts||{}; + $.getOpt = function(o) { + var $opt = this; + // Get multiple option if passed an array + if(o instanceof Array) { + var options = {}; + $h.each(o, function(option){ + options[option] = $opt.getOpt(option); + }); + return options; + } + // Otherwise, just return a simple option + if ($opt instanceof ResumableChunk) { + if (typeof $opt.opts[o] !== 'undefined') { return $opt.opts[o]; } + else { $opt = $opt.fileObj; } + } + if ($opt instanceof ResumableFile) { + if (typeof $opt.opts[o] !== 'undefined') { return $opt.opts[o]; } + else { $opt = $opt.resumableObj; } + } + if ($opt instanceof Resumable) { + if (typeof $opt.opts[o] !== 'undefined') { return $opt.opts[o]; } + else { return $opt.defaults[o]; } + } + }; + + // EVENTS + // catchAll(event, ...) + // fileSuccess(file), fileProgress(file), fileAdded(file, event), fileRetry(file), fileError(file, message), + // complete(), progress(), error(message, file), pause() + $.events = []; + $.on = function(event,callback){ + $.events.push(event.toLowerCase(), callback); + + }; + $.fire = function(){ + // `arguments` is an object, not array, in FF, so: + var args = []; + for (var i=0; i0){ + //add these results to the array of all the new stuff + for (var i=0; i 0){ + var fileTypeFound = false; + for(var index in o.fileType){ + var extension = '.' + o.fileType[index]; + if(fileName.indexOf(extension, fileName.length - extension.length) !== -1){ + fileTypeFound = true; + break; + } + } + if (!fileTypeFound) { + o.fileTypeErrorCallback(file, errorCount++); + return false; + } + } + + if (typeof(o.minFileSize)!=='undefined' && file.sizeo.maxFileSize) { + o.maxFileSizeErrorCallback(file, errorCount++); + return false; + } + + function addFile(uniqueIdentifier){ + if (!$.getFromUniqueIdentifier(uniqueIdentifier)) {(function(){ + file.uniqueIdentifier = uniqueIdentifier; + var f = new ResumableFile($, file, uniqueIdentifier); + $.files.push(f); + files.push(f); + f.container = (typeof event != 'undefined' ? event.srcElement : null); + window.setTimeout(function(){ + $.fire('fileAdded', f, event) + },0); + })()}; + } + // directories have size == 0 + var uniqueIdentifier = $h.generateUniqueIdentifier(file) + if(uniqueIdentifier && typeof uniqueIdentifier.done === 'function' && typeof uniqueIdentifier.fail === 'function'){ + uniqueIdentifier + .done(function(uniqueIdentifier){ + addFile(uniqueIdentifier); + }) + .fail(function(){ + addFile(); + }); + }else{ + addFile(uniqueIdentifier); + } + + }); + window.setTimeout(function(){ + $.fire('filesAdded', files) + },0); + }; + + // INTERNAL OBJECT TYPES + function ResumableFile(resumableObj, file, uniqueIdentifier){ + var $ = this; + $.opts = {}; + $.getOpt = resumableObj.getOpt; + $._prevProgress = 0; + $.resumableObj = resumableObj; + $.file = file; + $.fileName = file.fileName||file.name; // Some confusion in different versions of Firefox + $.size = file.size; + $.relativePath = file.webkitRelativePath || file.relativePath || $.fileName; + $.uniqueIdentifier = uniqueIdentifier; + $._pause = false; + $.container = ''; + var _error = uniqueIdentifier !== undefined; + + // Callback when something happens within the chunk + var chunkEvent = function(event, message){ + // event can be 'progress', 'success', 'error' or 'retry' + switch(event){ + case 'progress': + $.resumableObj.fire('fileProgress', $); + break; + case 'error': + $.abort(); + _error = true; + $.chunks = []; + $.resumableObj.fire('fileError', $, message); + break; + case 'success': + if(_error) return; + $.resumableObj.fire('fileProgress', $); // it's at least progress + if($.isComplete()) { + $.resumableObj.fire('fileSuccess', $, message); + } + break; + case 'retry': + $.resumableObj.fire('fileRetry', $); + break; + } + }; + + // Main code to set up a file object with chunks, + // packaged to be able to handle retries if needed. + $.chunks = []; + $.abort = function(){ + // Stop current uploads + var abortCount = 0; + $h.each($.chunks, function(c){ + if(c.status()=='uploading') { + c.abort(); + abortCount++; + } + }); + if(abortCount>0) $.resumableObj.fire('fileProgress', $); + }; + $.cancel = function(){ + // Reset this file to be void + var _chunks = $.chunks; + $.chunks = []; + // Stop current uploads + $h.each(_chunks, function(c){ + if(c.status()=='uploading') { + c.abort(); + $.resumableObj.uploadNextChunk(); + } + }); + $.resumableObj.removeFile($); + $.resumableObj.fire('fileProgress', $); + }; + $.retry = function(){ + $.bootstrap(); + var firedRetry = false; + $.resumableObj.on('chunkingComplete', function(){ + if(!firedRetry) $.resumableObj.upload(); + firedRetry = true; + }); + }; + $.bootstrap = function(){ + $.abort(); + _error = false; + // Rebuild stack of chunks from file + $.chunks = []; + $._prevProgress = 0; + var round = $.getOpt('forceChunkSize') ? Math.ceil : Math.floor; + var maxOffset = Math.max(round($.file.size/$.getOpt('chunkSize')),1); + for (var offset=0; offset0.99999 ? 1 : ret)); + ret = Math.max($._prevProgress, ret); // We don't want to lose percentages when an upload is paused + if(isNaN(ret)){ + ret = $._prevProgress; + } + else{ + $._prevProgress = ret; + } + return(ret); + }; + $.isUploading = function(){ + var uploading = false; + $h.each($.chunks, function(chunk){ + if(chunk.status()=='uploading') { + uploading = true; + return(false); + } + }); + return(uploading); + }; + $.isComplete = function(){ + var outstanding = false; + $h.each($.chunks, function(chunk){ + var status = chunk.status(); + if(status=='pending' || status=='uploading' || chunk.preprocessState === 1) { + outstanding = true; + return(false); + } + }); + return(!outstanding); + }; + $.pause = function(pause){ + if(typeof(pause)==='undefined'){ + $._pause = ($._pause ? false : true); + }else{ + $._pause = pause; + } + }; + $.isPaused = function() { + return $._pause; + }; + + + // Bootstrap and return + $.resumableObj.fire('chunkingStart', $); + $.bootstrap(); + return(this); + } + + + function ResumableChunk(resumableObj, fileObj, offset, callback){ + var $ = this; + $.opts = {}; + $.getOpt = resumableObj.getOpt; + $.resumableObj = resumableObj; + $.fileObj = fileObj; + $.fileObjSize = fileObj.size; + $.fileObjType = fileObj.file.type; + $.offset = offset; + $.callback = callback; + $.lastProgressCallback = (new Date); + $.tested = false; + $.retries = 0; + $.pendingRetry = false; + $.preprocessState = 0; // 0 = unprocessed, 1 = processing, 2 = finished + + // Computed properties + var chunkSize = $.getOpt('chunkSize'); + $.loaded = 0; + $.startByte = $.offset*chunkSize; + $.endByte = Math.min($.fileObjSize, ($.offset+1)*chunkSize); + if ($.fileObjSize-$.endByte < chunkSize && !$.getOpt('forceChunkSize')) { + // The last chunk will be bigger than the chunk size, but less than 2*chunkSize + $.endByte = $.fileObjSize; + } + $.xhr = null; + + // test() makes a GET request without any data to see if the chunk has already been uploaded in a previous session + $.test = function(){ + // Set up request and listen for event + $.xhr = new XMLHttpRequest(); + + var testHandler = function(e){ + $.tested = true; + var status = $.status(); + if(status=='success') { + $.callback(status, $.message()); + $.resumableObj.uploadNextChunk(); + } else { + $.send(); + } + }; + $.xhr.addEventListener('load', testHandler, false); + $.xhr.addEventListener('error', testHandler, false); + $.xhr.addEventListener('timeout', testHandler, false); + + // Add data from the query options + var params = []; + var parameterNamespace = $.getOpt('parameterNamespace'); + var customQuery = $.getOpt('query'); + if(typeof customQuery == 'function') customQuery = customQuery($.fileObj, $); + $h.each(customQuery, function(k,v){ + params.push([encodeURIComponent(parameterNamespace+k), encodeURIComponent(v)].join('=')); + }); + // Add extra data to identify chunk + params.push([parameterNamespace + $.getOpt('chunkNumberParameterName'), encodeURIComponent($.offset + 1)].join('=')); + params.push([parameterNamespace + $.getOpt('chunkSizeParameterName'), encodeURIComponent($.getOpt('chunkSize'))].join('=')); + params.push([parameterNamespace + $.getOpt('currentChunkSizeParameterName'), encodeURIComponent($.endByte - $.startByte)].join('=')); + params.push([parameterNamespace + $.getOpt('totalSizeParameterName'), encodeURIComponent($.fileObjSize)].join('=')); + params.push([parameterNamespace + $.getOpt('typeParameterName'), encodeURIComponent($.fileObjType)].join('=')); + params.push([parameterNamespace + $.getOpt('identifierParameterName'), encodeURIComponent($.fileObj.uniqueIdentifier)].join('=')); + params.push([parameterNamespace + $.getOpt('fileNameParameterName'), encodeURIComponent($.fileObj.fileName+"("+clientip+$.fileObj.uniqueIdentifier+")")].join('=')); + params.push([parameterNamespace + $.getOpt('relativePathParameterName'), encodeURIComponent($.fileObj.relativePath)].join('=')); + params.push([parameterNamespace + $.getOpt('rootPathParameterName'), encodeURIComponent(rootPath)].join('=')); + params.push([parameterNamespace + $.getOpt('totalChunksParameterName'), encodeURIComponent($.fileObj.chunks.length)].join('=')); + // Append the relevant chunk and send it + $.xhr.open($.getOpt('testMethod'), $h.getTarget(params)); + $.xhr.timeout = $.getOpt('xhrTimeout'); + $.xhr.withCredentials = $.getOpt('withCredentials'); + // Add data from header options + var customHeaders = $.getOpt('headers'); + if(typeof customHeaders === 'function') { + customHeaders = customHeaders($.fileObj, $); + } + $h.each(customHeaders, function(k,v) { + $.xhr.setRequestHeader(k, v); + }); + $.xhr.send(null); + }; + + $.preprocessFinished = function(){ + $.preprocessState = 2; + $.send(); + }; + + // send() uploads the actual data in a POST call + $.send = function(){ + var preprocess = $.getOpt('preprocess'); + if(typeof preprocess === 'function') { + switch($.preprocessState) { + case 0: $.preprocessState = 1; preprocess($); return; + case 1: return; + case 2: break; + } + } + if($.getOpt('testChunks') && !$.tested) { + $.test(); + return; + } + + // Set up request and listen for event + $.xhr = new XMLHttpRequest(); + + // Progress + $.xhr.upload.addEventListener('progress', function(e){ + if( (new Date) - $.lastProgressCallback > $.getOpt('throttleProgressCallbacks') * 1000 ) { + $.callback('progress'); + $.lastProgressCallback = (new Date); + } + $.loaded=e.loaded||0; + }, false); + $.loaded = 0; + $.pendingRetry = false; + $.callback('progress'); + + // Done (either done, failed or retry) + var doneHandler = function(e){ + var status = $.status(); + if(status=='success'||status=='error') { + $.callback(status, $.message()); + $.resumableObj.uploadNextChunk(); + } else { + $.callback('retry', $.message()); + $.abort(); + $.retries++; + var retryInterval = $.getOpt('chunkRetryInterval'); + if(retryInterval !== undefined) { + $.pendingRetry = true; + setTimeout($.send, retryInterval); + } else { + $.send(); + } + } + }; + $.xhr.addEventListener('load', doneHandler, false); + $.xhr.addEventListener('error', doneHandler, false); + $.xhr.addEventListener('timeout', doneHandler, false); + + // Set up the basic query data from Resumable + var query = {}; + query[$.getOpt('chunkNumberParameterName')] = $.offset + 1; + query[$.getOpt('chunkSizeParameterName')] = $.getOpt('chunkSize'); + query[$.getOpt('currentChunkSizeParameterName')] = $.endByte - $.startByte; + query[$.getOpt('totalSizeParameterName')] = $.fileObjSize; + query[$.getOpt('typeParameterName')] = $.fileObjType; + query[$.getOpt('identifierParameterName')] = $.fileObj.uniqueIdentifier; + query[$.getOpt('fileNameParameterName')] = $.fileObj.fileName+"("+clientip+$.fileObj.uniqueIdentifier+")"; + query[$.getOpt('relativePathParameterName')] = $.fileObj.relativePath; + query[$.getOpt('rootPathParameterName')] = rootPath; + query[$.getOpt('totalChunksParameterName')] = $.fileObj.chunks.length; + // Mix in custom data + var customQuery = $.getOpt('query'); + if(typeof customQuery == 'function') customQuery = customQuery($.fileObj, $); + $h.each(customQuery, function(k,v){ + query[k] = v; + }); + + var func = ($.fileObj.file.slice ? 'slice' : ($.fileObj.file.mozSlice ? 'mozSlice' : ($.fileObj.file.webkitSlice ? 'webkitSlice' : 'slice'))), + bytes = $.fileObj.file[func]($.startByte,$.endByte), + data = null, + target = $.getOpt('target'); + + var parameterNamespace = $.getOpt('parameterNamespace'); + if ($.getOpt('method') === 'octet') { + // Add data from the query options + data = bytes; + var params = []; + $h.each(query, function(k,v){ + params.push([encodeURIComponent(parameterNamespace+k), encodeURIComponent(v)].join('=')); + }); + target = $h.getTarget(params); + } else { + // Add data from the query options + data = new FormData(); + $h.each(query, function(k,v){ + data.append(parameterNamespace+k,v); + }); + data.append(parameterNamespace+$.getOpt('fileParameterName'), bytes); + } + + var method = $.getOpt('uploadMethod'); + $.xhr.open(method, target); + if ($.getOpt('method') === 'octet') { + $.xhr.setRequestHeader('Content-Type', 'binary/octet-stream'); + } + $.xhr.timeout = $.getOpt('xhrTimeout'); + $.xhr.withCredentials = $.getOpt('withCredentials'); + // Add data from header options + var customHeaders = $.getOpt('headers'); + if(typeof customHeaders === 'function') { + customHeaders = customHeaders($.fileObj, $); + } + $h.each(customHeaders, function(k,v) { + $.xhr.setRequestHeader(k, v); + }); + $.xhr.send(data); + }; + $.abort = function(){ + // Abort and reset + if($.xhr) $.xhr.abort(); + $.xhr = null; + }; + $.status = function(){ + // Returns: 'pending', 'uploading', 'success', 'error' + if($.pendingRetry) { + // if pending retry then that's effectively the same as actively uploading, + // there might just be a slight delay before the retry starts + return('uploading'); + } else if(!$.xhr) { + return('pending'); + } else if($.xhr.readyState<4) { + // Status is really 'OPENED', 'HEADERS_RECEIVED' or 'LOADING' - meaning that stuff is happening + return('uploading'); + } else { + if($.xhr.status == 200 || $.xhr.status == 201) { + // HTTP 200, 201 (created) + return('success'); + } else if($h.contains($.getOpt('permanentErrors'), $.xhr.status) || $.retries >= $.getOpt('maxChunkRetries')) { + // HTTP 415/500/501, permanent error + return('error'); + } else { + // this should never happen, but we'll reset and queue a retry + // a likely case for this would be 503 service unavailable + $.abort(); + return('pending'); + } + } + }; + $.message = function(){ + return($.xhr ? $.xhr.responseText : ''); + }; + $.progress = function(relative){ + if(typeof(relative)==='undefined') relative = false; + var factor = (relative ? ($.endByte-$.startByte)/$.fileObjSize : 1); + if($.pendingRetry) return(0); + if(!$.xhr || !$.xhr.status) factor*=.95; + var s = $.status(); + switch(s){ + case 'success': + case 'error': + return(1*factor); + case 'pending': + return(0*factor); + default: + return($.loaded/($.endByte-$.startByte)*factor); + } + }; + return(this); + } + + // QUEUE + $.uploadNextChunk = function(){ + var found = false; + + // In some cases (such as videos) it's really handy to upload the first + // and last chunk of a file quickly; this let's the server check the file's + // metadata and determine if there's even a point in continuing. + if ($.getOpt('prioritizeFirstAndLastChunk')) { + $h.each($.files, function(file){ + if(file.chunks.length && file.chunks[0].status()=='pending' && file.chunks[0].preprocessState === 0) { + file.chunks[0].send(); + found = true; + return(false); + } + if(file.chunks.length>1 && file.chunks[file.chunks.length-1].status()=='pending' && file.chunks[file.chunks.length-1].preprocessState === 0) { + file.chunks[file.chunks.length-1].send(); + found = true; + return(false); + } + }); + if(found) return(true); + } + + // Now, simply look for the next, best thing to upload + $h.each($.files, function(file){ + if(file.isPaused()===false){ + $h.each(file.chunks, function(chunk){ + if(chunk.status()=='pending' && chunk.preprocessState === 0) { + chunk.send(); + found = true; + return(false); + } + }); + } + if(found) return(false); + }); + if(found) return(true); + + // The are no more outstanding chunks to upload, check is everything is done + var outstanding = false; + $h.each($.files, function(file){ + if(!file.isComplete()) { + outstanding = true; + return(false); + } + }); + if(!outstanding) { + // All chunks have been uploaded, complete + $.fire('complete'); + } + return(false); + }; + + + // PUBLIC METHODS FOR RESUMABLE.JS + $.assignBrowse = function(domNodes, isDirectory){ + if(typeof(domNodes.length)=='undefined') domNodes = [domNodes]; + + $h.each(domNodes, function(domNode) { + var input; + if(domNode.tagName==='INPUT' && domNode.type==='file'){ + input = domNode; + } else { + input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.style.display = 'none'; + domNode.addEventListener('click', function(){ + input.style.opacity = 0; + input.style.display='block'; + input.focus(); + input.click(); + input.style.display='none'; + }, false); + domNode.appendChild(input); + } + var maxFiles = $.getOpt('maxFiles'); + if (typeof(maxFiles)==='undefined'||maxFiles!=1){ + input.setAttribute('multiple', 'multiple'); + } else { + input.removeAttribute('multiple'); + } + if(isDirectory){ + input.setAttribute('webkitdirectory', 'webkitdirectory'); + } else { + input.removeAttribute('webkitdirectory'); + } + // When new files are added, simply append them to the overall list + input.addEventListener('change', function(e){ + appendFilesFromFileList(e.target.files,e); + var clearInput = $.getOpt('clearInput'); + if (clearInput) { + e.target.value = ''; + } + }, false); + }); + }; + $.assignDrop = function(domNodes){ + if(typeof(domNodes.length)=='undefined') domNodes = [domNodes]; + + $h.each(domNodes, function(domNode) { + domNode.addEventListener('dragover', preventDefault, false); + domNode.addEventListener('dragenter', preventDefault, false); + domNode.addEventListener('drop', onDrop, false); + }); + }; + $.unAssignDrop = function(domNodes) { + if (typeof(domNodes.length) == 'undefined') domNodes = [domNodes]; + + $h.each(domNodes, function(domNode) { + domNode.removeEventListener('dragover', preventDefault); + domNode.removeEventListener('dragenter', preventDefault); + domNode.removeEventListener('drop', onDrop); + }); + }; + $.isUploading = function(){ + var uploading = false; + $h.each($.files, function(file){ + if (file.isUploading()) { + uploading = true; + return(false); + } + }); + return(uploading); + }; + $.upload = function(){ + // Make sure we don't start too many uploads at once + if($.isUploading()) return; + // Kick off the queue + $.fire('uploadStart'); + for (var num=1; num<=$.getOpt('simultaneousUploads'); num++) { + $.uploadNextChunk(); + } + }; + $.pause = function(){ + // Resume all chunks currently being uploaded + $h.each($.files, function(file){ + file.abort(); + }); + $.fire('pause'); + }; + $.cancel = function(){ + $.fire('beforeCancel'); + for(var i = $.files.length - 1; i >= 0; i--) { + $.files[i].cancel(); + } + $.fire('cancel'); + }; + $.progress = function(){ + var totalDone = 0; + var totalSize = 0; + // Resume all chunks currently being uploaded + $h.each($.files, function(file){ + totalDone += file.progress()*file.size; + totalSize += file.size; + }); + return(totalSize>0 ? totalDone/totalSize : 0); + }; + $.addFile = function(file, event){ + appendFilesFromFileList([file], event); + }; + $.removeFile = function(file){ + for(var i = $.files.length - 1; i >= 0; i--) { + if($.files[i] === file) { + $.files.splice(i, 1); + } + } + }; + $.getFromUniqueIdentifier = function(uniqueIdentifier){ + var ret = false; + $h.each($.files, function(f){ + if(f.uniqueIdentifier==uniqueIdentifier) ret = f; + }); + return(ret); + }; + $.getSize = function(){ + var totalSize = 0; + $h.each($.files, function(file){ + totalSize += file.size; + }); + return(totalSize); + }; + $.handleDropEvent = function (e) { + onDrop(e); + }; + $.handleChangeEvent = function (e) { + appendFilesFromFileList(e.target.files, e); + e.target.value = ''; + }; + $.setRootPath = function (path) { + rootPath = path; + } + $.getrootPath = function () { + return rootPath; + } + $.setFileId = function (id) { + file_id = id; + } + $.getFileId = function () { + return file_id; + } + $.setisnowcheck = function (id) { + isnowcheck = id; + } + $.getisnowcheck = function () { + return isnowcheck; + } + + $.setip = function (ip) { + clientip = ip; + console.log(clientip); + }; + + $.setxmlversion = function (data) { + xmlversion = data; + } + $.getxmlversion = function () { + return xmlversion; + } + $.mkRetfileUploadSucceed = function() { + $.fire('fileuploadendsucceed', $); + } + + return(this); + }; + + + // Node.js-style export for Node and Component + if (typeof module != 'undefined') { + module.exports = Resumable; + } else if (typeof define === "function" && define.amd) { + // AMD/requirejs: Define the module + define(function(){ + return Resumable; + }); + } else { + // Browser: Expose to window + window.Resumable = Resumable; + } + +})(); diff --git a/app/style.css b/app/style.css new file mode 100644 index 0000000..e8fe905 --- /dev/null +++ b/app/style.css @@ -0,0 +1,216 @@ +/* 样式重置 */ +body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} +body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#fff;} +div,img,tr,td,table{ border:0;} +table,tr,td{border:0;cellspacing:0; cellpadding:0;} +ol,ul,li{ list-style-type:none} +a:link,a:visited{color:#7f7f7f;text-decoration:none;} +a:hover,a:active{color:#000;} +.fl{ float:left;} +.fr{ float:right;} +.cl{ clear:both; overflow:hidden;} + +/* 数据页面 */ +.data_container{ + width:100%; + margin:0 auto; +} +.data_heaer{ + height:66px; + width:100%; + background-color:#3499db; + text-align:center; +} +.data_heaer h2{ + font-size:30px; + font-weight:300; + color:#fff; + line-height:66px; +} +.data_content{ + width:1280px; + height:838px; + margin:0 auto; + background-color:#fff; + border:1px solid #e0dede; + border-top:none; +} +.data_leftside{ + width:612px; + border-right:1px solid #e0dede; +} +.data_h3{ + width:100%; + text-align:center; + height:50px; + font-size:18px; + color:#444; + line-height:50px; +} +.data_leftside_files{ + border-right:1px solid #e0dede; + border-bottom:1px solid #e0dede; + height:710px; + overflow :auto; +} +.data_leftside_files input{ + margin-top:15px; + width:15px; + height:15px; +} +.data_leftside_files li{ + height:40px; + line-height:40px; + border-bottom:1px solid #e0dede; + padding:0 10px; +} +.data_leftside_files li.data_title{ + width:210px; height:36px; + line-height:36px; + text-align:center; + background-color:#e9f3fb; + border:none; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; +} +.date_label{ + display:block; + width:168px; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; +} +.data_leftside_shu{ + border-right:none; +} +.data_leftside_shu li{ + border-bottom:none; +} +.data_conbar{ width:149px; + height:834px; + border-right:1px solid #e0dede; + border-left:1px solid #e0dede; +} +.date_btns{ + width:260px; + margin:20px auto; +} +.date_btns_w{ + width:390px; +} +.date_btns button{ + margin:10px 20px; +} +.data_btn{ + border:none; + width:108px; + height:35px; + line-height:35px; + text-align:center; + background-color:#3499db; + color:#fff; + font-size:14px; + -webkit-border-radius:5px; + -moz-border-radius:5px; + -o-border-radius:5px; + border-radius:5px; +} +.data_btn:hover{ + background-color:#2989da; +} +.data_rightside{ + width:667px; +} +.data_rightside_w{ + width:407px; +} +.data_leftside_files li.data_title_w{ + width:183px; +} +.date_label_w{ + width:150px; +} +.data_leftside_shu li{ + border-bottom:none; +} + +a.data_file_btn{ display:block; position:relative; width:108px; height:35px; margin:15px auto; line-height:35px; font-size:14px; color: #fff; text-align:center; + background-color: #79b4e7; + background-image: -webkit-linear-gradient(#79b4e7, #1377cf); + background-image: linear-gradient(#79b4e7, #1377cf); + border-color: #076bc2; + -webkit-border-radius:5px; + -moz-border-radius:5px; + -o-border-radius:5px; + border-radius:5px; + vertical-align: middle; + cursor: pointer; + margin:0 10px; +} +a:hover.data_file_btn{ + background-color: #076bc2; + background-image: -webkit-linear-gradient(#79b4e7, #076bc2); + background-image: linear-gradient(#79b4e7, #076bc2); + border-color: #076bc2;} +.data_file_btn input{ position:absolute; left:0px;opacity:0; filter:alpha(opacity=0); width:108px; height:35px;} + + +.data_conbox{ + width:407px; + height:709px; + border-top:1px solid #e0dede; + border-bottom:1px solid #e0dede; + overflow: auto; + } +.data_con_title{ + width:49.8%; + height:36px; + line-height:36px; + text-align:center; + background-color:#e9f3fb; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; + } + .data_con_line{ + border-right:1px solid #e0dede; + + } +.data_con_li{ + width:49.8%; + height:36px; + line-height:36px; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; + border-bottom:1px solid #e0dede; + } +.mt15{ margin-top:15px;} + + +/* 树形结构 */ +.data_rightside_tree{ + width:259px; + height:709px; + border-right:1px solid #e0dede; + border-top:1px solid #e0dede; + border-bottom:1px solid #e0dede; + overflow: auto; +} +.tree { min-height:20px;padding:15px;padding-left:30px;border-bottom:1px dashed #ccc;} +.tree li {list-style-type:none;margin:0; padding:10px 5px 0 20px; position:relative} +.tree li::before, .tree li::after { content:'';left:-30px;position:absolute; right:auto} +.tree li::before { border-left:1px solid #999; bottom:50px;height:100%; top:0; width:0px} +.tree li::after {border-top:1px solid #999;height:20px; top:25px; width:35px} +.tree li p {display:inline-block;padding:3px 10px;border:1px solid #fff; margin-left:-15px; width:150px; } +.tree li.parent_li>p {cursor:pointer} +.tree>ul>li::before, .tree>ul>li::after {border:0} +.tree li:last-child::before { height:30px} +.tree li.parent_li>p:hover, .tree li.parent_li>p:hover+ul li p { } +.icon-plus-sign{ margin-left:-15px; background:url(../img/icons1.gif) -5px 10px no-repeat; } +.icon-minus-sign{ margin-left:-15px; background:url(../img/icons2.gif) -6px 9px no-repeat;} \ No newline at end of file diff --git a/app/xmloperation.js b/app/xmloperation.js new file mode 100644 index 0000000..5efaf5f --- /dev/null +++ b/app/xmloperation.js @@ -0,0 +1,558 @@ + +var fs = require('fs'); +var dom = require("xmldom").DOMParser; +var select = require('xpath.js'); + +var dataDetailPath = "/home/server_data/data-detail.xml" +var dataPath = "/home/server_data/data.xml" +var versionPath = "/home/server_data/version.txt" + +//����fileId����ȡ�ļ���ŵ�λ�� +function getVersionPath(fileId){ + + fileId = fileId.replace(/\"/g, ""); + var item = "")[1].split("")[0]; + if(version.value < oldBigVersion){ + version.value = oldBigVersion; + } + } + } + version.value ++; + return version.value; +} + + + +function mkdataForPage(collecttime, realtype, realpath, realbatch, realid, realname, version){ +// var resultXmlData = ""; +// var realpath = "/uplaods/"; +// var realtype = "01"; +// var realbatch = "01_A"; +// var realid = "32550_111"; +// var realname = "�Ͼ���_������_��Ч����ϵͳ"; + //json���Եĸ�ʽ����@ + var type ="id=\""+realtype+"\""; + var batch = "id=\""+realtype+"_"+realbatch+"\""; + var id = realtype+"_"+realbatch+"_"+realid+"\""; + var versionid = realtype+"_"+realbatch + "_"+realid + "_" + version +"\""; + var name = "name=\""+realname+"\""; + var path = "path=\""+realpath+"\""; + var versionstrutf = fs.readFileSync(versionPath, "utf-8"); + console.log(typeof versionstrutf); + + console.log("------------- mkdataForPage --------------"); + fs.readFile(dataPath, "utf-8", function(err, data){ + if(err){ + console.log("��ȡ�ļ� "+dataDetailPath+" fail " + err); + } + else{ + var dataNodes = data.split("\n"; + isexist = "1"; + dataNodes[i] = dataNodes[i] + nodestr; + } + + } + + } + + + if(isexist.indexOf("1") == -1){ + var nodestr = ""; + for(var i=0; i < sizel; i++){ + if(dataNodes[i].indexOf(batch) != -1){ + var items = dataNodes[i].split("\n"; + nodestr = nodestr + "\n\n"; + isexist = "1"; + dataNodes[i] = dataNodes[i] + nodestr; + break; + } + else{ + var items = dataNodes[i].split("\n"; + nodestr = nodestr + "\n\n"; + isexist = "1"; + nodestr = items[0] +"\n" + nodestr +"\n\n"; + dataNodes[i] = nodestr; + break; + } + + } + } + + } + + var resultdatastr = ""; + for(var j=0; j < sizel-1; j++){ + resultdatastr = resultdatastr + dataNodes[j] + "\n"; + itemStr += "\t\t\t\t"+name+"\n"; + itemStr += "\t\t\t\t"+collecttime+"\n"; + itemStr += "\t\t\t\t\n"; + itemStr += "\t\t\t\t"+province+"\n"; + itemStr += "\t\t\t\t"+city+"\n"; + itemStr += "\t\t\t\t"+county+"\n"; + itemStr += "\t\t\t\t"+system+"\n"; + itemStr += "\t\t\t\t"+version+"\n"; + itemStr += "\t\t\t\t"+realpath+"\n"; + + itemStr += "\t\t\t\t"+areacode+"\n"; + itemStr += "\t\t\t\t"+systemcode+"\n"; + itemStr += "\t\t\t\t"+contacts+"\n"; + itemStr += "\t\t\t\t"+phone+"\n"; + itemStr += "\t\t\t\t"+type+"\n\t\t\t"+itemEnd+"\n\t\t"; + // ��� �� resultStr + // û�� item�� itemsize ==1 + if(itemsize ==1){ + var dataTimebeginstr = itemArray[0].split(dataTimeEndstr); + + resultStr += dataTimestr; + resultStr += dataTimebeginstr[0]; + resultStr += "\t" + itemStr; + resultStr += dataTimeEndstr; + for(var i = 1; i < dataTimebeginstr.length;i++){ + + resultStr += dataTimebeginstr[i]; + } + } + // �� item�� + else{ + resultStr += dataTimestr; + resultStr += itemArray[0]; + if(version == 1){ + for(var i=1; i < itemsize-1; i++){ + resultStr += item; + resultStr += itemArray[i]; + } + resultStr += itemStr + "\t"; + resultStr += item; + // itemArray[itemsize-1]: ������ + resultStr += itemArray[itemsize-1]; + } + else{ + var addtimes = 0; + var isadd = 0; + for(var i=1; i < itemsize-1; i++){ + isadd++; + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + resultStr += item; + resultStr += itemArray[i]; + } + if(isadd == 0){ + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + } + // itemArray[itemsize-1]: ������ + resultStr += item; + resultStr += itemArray[itemsize-1]; + } + } + + } + // ��1����ʱ + else{ + resultStr += datatype; + resultStr += timesArray[0]; + resultStr += dataTimestr; + // item Ԫ�� + var itemArray = timesArray[1].split(item); + var itemsize = itemArray.length; + + var nowDate = new Date(); + // itemԪ�� + var itemStr = "\n"; + itemStr += "\t\t\t\t"+name+"\n"; + itemStr += "\t\t\t\t"+collecttime+"\n"; + itemStr += "\t\t\t\t\n"; + itemStr += "\t\t\t\t"+province+"\n"; + itemStr += "\t\t\t\t"+city+"\n"; + itemStr += "\t\t\t\t"+county+"\n"; + itemStr += "\t\t\t\t"+system+"\n"; + itemStr += "\t\t\t\t"+version+"\n"; + itemStr += "\t\t\t\t"+realpath+"\n"; + + itemStr += "\t\t\t\t"+areacode+"\n"; + itemStr += "\t\t\t\t"+systemcode+"\n"; + itemStr += "\t\t\t\t"+contacts+"\n"; + itemStr += "\t\t\t\t"+phone+"\n"; + itemStr += "\t\t\t\t"+type+"\n\t\t\t"+itemEnd+"\n\t\t"; + // ��� �� resultStr + // û�� item�� itemsize ==1 + if(itemsize ==1){ + var dataTimebeginstr = itemArray[0].split(dataTimeEndstr); + resultStr += dataTimebeginstr[0]; + resultStr += "\t" + itemStr; + resultStr += dataTimeEndstr; + for(var i = 1; i < dataTimebeginstr.length;i++){ + resultStr += dataTimebeginstr[i]; + } + + } + // �� item�� + else{ + resultStr += itemArray[0]; + if(version == 1){ + for(var i=1; i < itemsize-1; i++){ + resultStr += item; + resultStr += itemArray[i]; + } + resultStr += itemStr + "\t"; + resultStr += item; + // itemArray[itemsize-1]: ������ + resultStr += itemArray[itemsize-1]; + } + else{ + var addtimes = 0; + var isadd = 0; + for(var i=1; i < itemsize-1; i++){ + isadd++; + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + resultStr += item; + resultStr += itemArray[i]; + } + if(isadd == 0){ + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + } + // itemArray[itemsize-1]: ������ + resultStr += item; + resultStr += itemArray[itemsize-1]; + } + } + + //Ȼ����ϵ�2���� + resultStr += dataTimestr; + resultStr += timesArray[2]; + } + + } + // ������籣 + else{ + resultStr += typeArray[0]; + + //�籣 ��typeArray[1] + var timesArray = typeArray[1].split(dataTimestr); + // �������:���ǵ�һ���εģ��ǵ�2����; {timesArray[0]:ͷ�� timesArray[1]:1���Σ� timesArray[2]:2����} + if(timesArray[1].indexOf(dataTimetemstr)== -1){ + resultStr += datatype; + resultStr += timesArray[0]; + // ���ϵ�1���� + resultStr += dataTimestr; + resultStr += timesArray[1]; + + var itemArray = timesArray[2].split(item); + var itemsize = itemArray.length; + + var nowDate = new Date(); + // itemԪ�� + var itemStr = "\n"; + itemStr += "\t\t\t\t"+name+"\n"; + itemStr += "\t\t\t\t"+collecttime+"\n"; + itemStr += "\t\t\t\t\n"; + itemStr += "\t\t\t\t"+province+"\n"; + itemStr += "\t\t\t\t"+city+"\n"; + itemStr += "\t\t\t\t"+county+"\n"; + itemStr += "\t\t\t\t"+system+"\n"; + itemStr += "\t\t\t\t"+version+"\n"; + itemStr += "\t\t\t\t"+realpath+"\n"; + + itemStr += "\t\t\t\t"+areacode+"\n"; + itemStr += "\t\t\t\t"+systemcode+"\n"; + itemStr += "\t\t\t\t"+contacts+"\n"; + itemStr += "\t\t\t\t"+phone+"\n"; + itemStr += "\t\t\t\t"+type+"\n\t\t\t"+itemEnd+"\n\t\t"; + // ��� �� resultStr + // û�� item�� itemsize ==1 + if(itemsize ==1){ + var dataTimebeginstr = itemArray[0].split(dataTimeEndstr); + resultStr += dataTimestr; + resultStr += dataTimebeginstr[0]; + resultStr = resultStr + "\t" + itemStr; + resultStr += dataTimeEndstr; + for(var i = 1; i < dataTimebeginstr.length;i++){ + resultStr += dataTimebeginstr[i]; + } + + } + // �� item�� + else{ + resultStr += dataTimestr; + resultStr += itemArray[0]; + if(version == 1){ + for(var i=1; i < itemsize-1; i++){ + resultStr += item; + resultStr += itemArray[i]; + } + resultStr += itemStr + "\t"; + resultStr += item; + // itemArray[itemsize-1]: ������ + resultStr += itemArray[itemsize-1]; + } + else{ + var addtimes = 0; + var isadd = 0; + for(var i=1; i < itemsize-1; i++){ + isadd++; + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + resultStr += item; + resultStr += itemArray[i]; + } + if(isadd == 0){ + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + } + // itemArray[itemsize-1]: ������ + resultStr += item; + resultStr += itemArray[itemsize-1]; + } + } + + } + // ��1����ʱ + else{ + resultStr += datatype; + resultStr += timesArray[0]; + resultStr += dataTimestr; + // item Ԫ�� + var itemArray = timesArray[1].split(item); + var itemsize = itemArray.length; + + var nowDate = new Date(); + // itemԪ�� + var itemStr = "\n"; + itemStr += "\t\t\t\t"+name+"\n"; + itemStr += "\t\t\t\t"+collecttime+"\n"; + itemStr += "\t\t\t\t\n"; + itemStr += "\t\t\t\t"+province+"\n"; + itemStr += "\t\t\t\t"+city+"\n"; + itemStr += "\t\t\t\t"+county+"\n"; + itemStr += "\t\t\t\t"+system+"\n"; + itemStr += "\t\t\t\t"+version+"\n"; + itemStr += "\t\t\t\t"+realpath+"\n"; + + itemStr += "\t\t\t\t"+areacode+"\n"; + itemStr += "\t\t\t\t"+systemcode+"\n"; + itemStr += "\t\t\t\t"+contacts+"\n"; + itemStr += "\t\t\t\t"+phone+"\n"; + itemStr += "\t\t\t\t"+type+"\n\t\t\t"+itemEnd+"\n\t\t"; + // ��� �� resultStr + // û�� item�� itemsize ==1 + if(itemsize ==1){ + var dataTimebeginstr = itemArray[0].split(dataTimeEndstr); + resultStr += dataTimebeginstr[0]; + resultStr = resultStr + "\t" + itemStr; + resultStr += dataTimeEndstr; + for(var i = 1; i < dataTimebeginstr.length;i++){ + resultStr += dataTimebeginstr[i]; + } + + } + // �� item�� + else{ + resultStr += itemArray[0]; + if(version == 1){ + for(var i=1; i < itemsize-1; i++){ + resultStr += item; + resultStr += itemArray[i]; + } + resultStr += itemStr+"\t"; + resultStr += item; + // itemArray[itemsize-1]: ������ + resultStr += itemArray[itemsize-1]; + } + else{ + var addtimes = 0; + var isadd = 0; + for(var i=1; i < itemsize-1; i++){ + isadd++; + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + resultStr += item; + resultStr += itemArray[i]; + } + if(isadd == 0){ + if(addtimes == 0){ + if(itemArray[i].indexOf(id)!= -1){ + resultStr += itemStr + "\t"; + addtimes = 1; + } + } + } + // itemArray[itemsize-1]: ������ + resultStr += item; + resultStr += itemArray[itemsize-1]; + } + } + + //Ȼ����ϵ�2���� + resultStr += dataTimestr; + resultStr += timesArray[2]; + } + + //���ϲ����� + resultStr += datatype; + resultStr += typeArray[2]; + } + + console.log("-----------------------------------------------"); + console.log(resultStr); + console.log(typeof resultStr); + // д���ļ� + fs.writeFile(dataDetailPath, resultStr, function(err){ + if(err) + console.log(err); + else + console.log('has finished'); + }); + + } + }); + +} + +exports.getVersionPath = getVersionPath; +exports.mkdataForPage = mkdataForPage +exports.saveByIdToXml = saveByIdToXml + + + + + diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..a73c758 --- /dev/null +++ b/bower.json @@ -0,0 +1,63 @@ +{ + "name": "hawtio-kubernetes", + "version": "2.1.179", + "keywords": [ + "hawtio" + ], + "main": [ + "dist/hawtio-kubernetes.css", + "dist/hawtio-kubernetes.js" + ], + "ignore": [ + ".*", + "**/.*", + "node_modules", + "bower_components", + "libs", + "test", + "tests", + "plugins" + ], + "dependencies": { + "angular-nvd3": "~1.0.2", + "angular": "~1.4.4", + "angular-resource": "~1.4.7", + "angular-ui-codemirror": "~0.3.0", + "angular-ui-validate": "~1.2.1", + "angularjs-scroll-glue": "~0.0.1", + "hawtio-core": "~2.0.16", + "hawtio-forms": "~2.0.15", + "hawtio-oauth": "~2.0.21", + "hawtio-template-cache": "*", + "hawtio-ui": "~2.0.67", + "hawtio-utilities": "~2.0.21", + "kubernetes-container-terminal": "~0.0.3", + "term.js": "~0.0.3", + "urijs": "~1.17.0", + "hawtio-kubernetes-api": "~2.0.0", + "human-date": "^1.3.2", + "js-yaml": "^3.5.4" + }, + "overrides": { + "term.js": { + "main": [ + "./src/term.js" + ] + } + }, + "devDependencies": { + "bootstrap": "~3.3.6", + "patternfly": "~2.7.0", + "hawtio-core-dts": "~2.0.0", + "angular-mocks": "~1.3.7", + "hawtio-preferences": "~2.0.1", + "hawtio-extension-service": "~2.0.1" + }, + "resolutions": { + "codemirror": "^5.0", + "angular": "~1.3.5", + "angular-resource": "~1.3.9", + "urijs": "~1.17.0", + "lodash": "3.10.1" + } +} diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..ef5137e --- /dev/null +++ b/circle.yml @@ -0,0 +1,29 @@ +machine: + node: + version: 0.10.33 + services: + - docker + +dependencies: + pre: + - npm install -g bower gulp slush slush-hawtio-javascript slush-hawtio-typescript typescript + - npm install + - bower update + - bower prune + override: + - gulp site + +test: + override: + - echo yes + +##deployment: +## hub: +## branch: master +## owner: hawtio +## commands: +## - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS +## - docker build -t fabric8/hawtio-kubernetes . +## - docker push fabric8/hawtio-kubernetes + + diff --git a/d.ts/developer/ts/FileMode.d.ts b/d.ts/developer/ts/FileMode.d.ts new file mode 100644 index 0000000..a48541a --- /dev/null +++ b/d.ts/developer/ts/FileMode.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +/// +/// +declare module Developer { +} diff --git a/d.ts/developer/ts/dataInfnModel.d.ts b/d.ts/developer/ts/dataInfnModel.d.ts new file mode 100644 index 0000000..06a29bc --- /dev/null +++ b/d.ts/developer/ts/dataInfnModel.d.ts @@ -0,0 +1,7 @@ +/// +declare module Developer { + class dataInfoModelService { + serverData: {}; + serverData: Object; + } +} diff --git a/d.ts/developer/ts/developerEnrichers.d.ts b/d.ts/developer/ts/developerEnrichers.d.ts new file mode 100644 index 0000000..cd7a782 --- /dev/null +++ b/d.ts/developer/ts/developerEnrichers.d.ts @@ -0,0 +1,16 @@ +/// +declare module Developer { + function enrichWorkspaces(projects: any): any; + function enrichWorkspace(build: any): any; + function asDate(value: any): Date; + function enrichJenkinsJobs(jobsData: any, projectId: any, jobName: any): any; + function enrichJenkinsJob(job: any, projectId: any, jobName: any): any; + function createBuildStatusIconClass(result: any): string; + function createBuildStatusBackgroundClass(result: any): string; + function enrichJenkinsBuild(job: any, build: any): any; + function jenkinsLink(): any; + function forgeReadyLink(): any; + function enrichJenkinsPipelineJob(job: any, projectId: any, jobId: any): void; + function enrichJenkinsStages(build: any, projectId: any, jobName: any): any; + function enrichJenkinsStage(stage: any, build?: any): void; +} diff --git a/d.ts/developer/ts/developerHelpers.d.ts b/d.ts/developer/ts/developerHelpers.d.ts new file mode 100644 index 0000000..ca216c3 --- /dev/null +++ b/d.ts/developer/ts/developerHelpers.d.ts @@ -0,0 +1,25 @@ +/// +declare module Developer { + var context: string; + var hash: string; + var pluginName: string; + var pluginPath: string; + var templatePath: string; + var log: Logging.Logger; + var jenkinsServiceName: string; + var jenkinsServiceNameAndPort: string; + var jenkinsHttpConfig: { + headers: { + Accept: string; + }; + }; + /** + * Returns true if the value hasn't changed from the last cached JSON version of this object + */ + function hasObjectChanged(value: any, state: any): boolean; + function projectForScope($scope: any): any; + /** + * Lets load the project versions for the given namespace + */ + function loadProjectVersions($scope: any, $element: any, project: any, env: any, ns: any, answer: any, caches: any): void; +} diff --git a/d.ts/developer/ts/developerNavigation.d.ts b/d.ts/developer/ts/developerNavigation.d.ts new file mode 100644 index 0000000..335dab8 --- /dev/null +++ b/d.ts/developer/ts/developerNavigation.d.ts @@ -0,0 +1,28 @@ +/// +declare module Developer { + function workspaceLink(): string; + function projectLink(projectId: any): string; + function createWorkspacesBreadcrumbs(developPerspective: any): any[]; + function createWorkspacesSubNavBars(developPerspective: any): any; + function createWorkspaceBreadcrumbs(children?: any, workspaceName?: any): any; + function createEnvironmentBreadcrumbs($scope: any, $location: any, $routeParams: any): any; + function createProjectBreadcrumbs(projectName?: any, children?: any, workspaceName?: any): any; + function createProjectSettingsBreadcrumbs(projectName: any, workspaceName?: any): any; + function createWorkspaceSubNavBars(): any; + function createProjectSubNavBars(projectName: any, jenkinsJobId?: any, $scope?: any): any; + function createProjectSettingsSubNavBars(projectName: any, jenkinsJobId?: any): any; + function forgeProjectHasBuilder(name: any): any; + function forgeProjectHasPerspective(name: any): any; + function editPipelineLinkScope($scope: any): string; + function createProjectLink(workspaceName?: any): string; + function editPipelineLink(workspaceName: any, projectName: any): string; + function editMavenBuildLink(workspaceName: any, projectName: any): string; + function projectSecretsLink(workspaceName: any, projectName: any): string; + function secretsNamespaceLink(workspaceName: any, projectName: any, secretsNamespace: any): string; + function projectWorkspaceLink(workspaceName: any, projectName: any, path: any, ignoreBlankProject?: boolean): string; + var customProjectSubTabFactories: any[]; + function createJenkinsBreadcrumbs(projectName: any, jobId: any, buildId: any): any; + function createJenkinsSubNavBars(projectName: any, jenkinsJobId: any, buildId: any, extraOption?: any): any; + function createEnvironmentSubNavBars($scope: any, $location: any, $routeParams: any): any; + function namespaceLink($scope: any, $routeParams: any, path?: any): string; +} diff --git a/d.ts/developer/ts/developerPlugin.d.ts b/d.ts/developer/ts/developerPlugin.d.ts new file mode 100644 index 0000000..c4ddffa --- /dev/null +++ b/d.ts/developer/ts/developerPlugin.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare module Developer { + var _module: ng.IModule; + var controller: (name: string, inlineAnnotatedConstructor: any[]) => ng.IModule; + var route: (templateName: string, reloadOnSearch?: boolean) => { + templateUrl: string; + reloadOnSearch: boolean; + }; +} diff --git a/d.ts/developer/ts/environmentPanel.d.ts b/d.ts/developer/ts/environmentPanel.d.ts new file mode 100644 index 0000000..5c97875 --- /dev/null +++ b/d.ts/developer/ts/environmentPanel.d.ts @@ -0,0 +1,3 @@ +/// +declare module Developer { +} diff --git a/d.ts/developer/ts/home.d.ts b/d.ts/developer/ts/home.d.ts new file mode 100644 index 0000000..a46cf5f --- /dev/null +++ b/d.ts/developer/ts/home.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var HomeController: ng.IModule; +} diff --git a/d.ts/developer/ts/jenkinsJob.d.ts b/d.ts/developer/ts/jenkinsJob.d.ts new file mode 100644 index 0000000..44dcb91 --- /dev/null +++ b/d.ts/developer/ts/jenkinsJob.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var JenkinsJobController: ng.IModule; +} diff --git a/d.ts/developer/ts/jenkinsJobs.d.ts b/d.ts/developer/ts/jenkinsJobs.d.ts new file mode 100644 index 0000000..2b19265 --- /dev/null +++ b/d.ts/developer/ts/jenkinsJobs.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var JenkinsJobsController: ng.IModule; +} diff --git a/d.ts/developer/ts/jenkinsLog.d.ts b/d.ts/developer/ts/jenkinsLog.d.ts new file mode 100644 index 0000000..a29004b --- /dev/null +++ b/d.ts/developer/ts/jenkinsLog.d.ts @@ -0,0 +1,12 @@ +/// +/// +/// +/// +/// +/// +/// +/// +declare module Developer { + function clickApprove(element: any, url: any): void; + var JenkinsLogController: ng.IModule; +} diff --git a/d.ts/developer/ts/jenkinsMetrics.d.ts b/d.ts/developer/ts/jenkinsMetrics.d.ts new file mode 100644 index 0000000..9ad98b9 --- /dev/null +++ b/d.ts/developer/ts/jenkinsMetrics.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var JenkinsMetricsController: ng.IModule; +} diff --git a/d.ts/developer/ts/navbar.d.ts b/d.ts/developer/ts/navbar.d.ts new file mode 100644 index 0000000..303b359 --- /dev/null +++ b/d.ts/developer/ts/navbar.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var NavBarController: ng.IModule; +} diff --git a/d.ts/developer/ts/pipeline.d.ts b/d.ts/developer/ts/pipeline.d.ts new file mode 100644 index 0000000..adac4b0 --- /dev/null +++ b/d.ts/developer/ts/pipeline.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var PipelineController: ng.IModule; +} diff --git a/d.ts/developer/ts/pipelineDirective.d.ts b/d.ts/developer/ts/pipelineDirective.d.ts new file mode 100644 index 0000000..a48541a --- /dev/null +++ b/d.ts/developer/ts/pipelineDirective.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +/// +/// +declare module Developer { +} diff --git a/d.ts/developer/ts/pipelines.d.ts b/d.ts/developer/ts/pipelines.d.ts new file mode 100644 index 0000000..954c5c8 --- /dev/null +++ b/d.ts/developer/ts/pipelines.d.ts @@ -0,0 +1,9 @@ +/// +/// +/// +/// +/// +/// +declare module Developer { + var PipelinesController: ng.IModule; +} diff --git a/d.ts/developer/ts/project.d.ts b/d.ts/developer/ts/project.d.ts new file mode 100644 index 0000000..7a36c46 --- /dev/null +++ b/d.ts/developer/ts/project.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var ProjectController: ng.IModule; +} diff --git a/d.ts/developer/ts/projectSelector.d.ts b/d.ts/developer/ts/projectSelector.d.ts new file mode 100644 index 0000000..5c97875 --- /dev/null +++ b/d.ts/developer/ts/projectSelector.d.ts @@ -0,0 +1,3 @@ +/// +declare module Developer { +} diff --git a/d.ts/developer/ts/projects.d.ts b/d.ts/developer/ts/projects.d.ts new file mode 100644 index 0000000..3ec7d0c --- /dev/null +++ b/d.ts/developer/ts/projects.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var ProjectsController: ng.IModule; +} diff --git a/d.ts/developer/ts/workspace.d.ts b/d.ts/developer/ts/workspace.d.ts new file mode 100644 index 0000000..7250703 --- /dev/null +++ b/d.ts/developer/ts/workspace.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var WorkspaceController: ng.IModule; +} diff --git a/d.ts/developer/ts/workspaces.d.ts b/d.ts/developer/ts/workspaces.d.ts new file mode 100644 index 0000000..270a545 --- /dev/null +++ b/d.ts/developer/ts/workspaces.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +/// +/// +declare module Developer { + var WorkspacesController: ng.IModule; +} diff --git a/d.ts/includes.d.ts b/d.ts/includes.d.ts new file mode 100644 index 0000000..648f162 --- /dev/null +++ b/d.ts/includes.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +/// +/// +declare var humandate: any; +declare var jsyaml: any; diff --git a/d.ts/kubernetes/ts/apps.d.ts b/d.ts/kubernetes/ts/apps.d.ts new file mode 100644 index 0000000..ea7bacb --- /dev/null +++ b/d.ts/kubernetes/ts/apps.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var Apps: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/breadcrumbs.d.ts b/d.ts/kubernetes/ts/breadcrumbs.d.ts new file mode 100644 index 0000000..c1db8db --- /dev/null +++ b/d.ts/kubernetes/ts/breadcrumbs.d.ts @@ -0,0 +1,5 @@ +/// +/// +/// +declare module Kubernetes { +} diff --git a/d.ts/kubernetes/ts/build.d.ts b/d.ts/kubernetes/ts/build.d.ts new file mode 100644 index 0000000..14737a8 --- /dev/null +++ b/d.ts/kubernetes/ts/build.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var BuildController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/buildConfig.d.ts b/d.ts/kubernetes/ts/buildConfig.d.ts new file mode 100644 index 0000000..d9eead5 --- /dev/null +++ b/d.ts/kubernetes/ts/buildConfig.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var BuildConfigController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/buildConfigEdit.d.ts b/d.ts/kubernetes/ts/buildConfigEdit.d.ts new file mode 100644 index 0000000..291fd57 --- /dev/null +++ b/d.ts/kubernetes/ts/buildConfigEdit.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var BuildConfigEditController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/buildConfigs.d.ts b/d.ts/kubernetes/ts/buildConfigs.d.ts new file mode 100644 index 0000000..7eddf76 --- /dev/null +++ b/d.ts/kubernetes/ts/buildConfigs.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var BuildConfigsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/buildLogs.d.ts b/d.ts/kubernetes/ts/buildLogs.d.ts new file mode 100644 index 0000000..02069aa --- /dev/null +++ b/d.ts/kubernetes/ts/buildLogs.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var BuildLogsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/builds.d.ts b/d.ts/kubernetes/ts/builds.d.ts new file mode 100644 index 0000000..a72ae26 --- /dev/null +++ b/d.ts/kubernetes/ts/builds.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var BuildsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/connect.d.ts b/d.ts/kubernetes/ts/connect.d.ts new file mode 100644 index 0000000..e39fd07 --- /dev/null +++ b/d.ts/kubernetes/ts/connect.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var ConnectController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/dataInfnModel.d.ts b/d.ts/kubernetes/ts/dataInfnModel.d.ts new file mode 100644 index 0000000..2a13b50 --- /dev/null +++ b/d.ts/kubernetes/ts/dataInfnModel.d.ts @@ -0,0 +1,33 @@ +/// +/// +declare module Kubernetes { + class dataInfoModelService { + serverdata: {}; + promiseobject: {}; + localdata: {}; + selectednodes: any[]; + resumablejs: any[]; + selecteditems: any[]; + serveritems: any[]; + uploadprocess: {}; + uploadedStatus: string; + uploadProcess: Object; + folderList: { + length: number; + }; + serverItems: Array; + resumableJs: Array; + selectedItems: Array; + selectedNodes: Array; + isContainsNodes(node: Object): boolean; + findNodes(node: any): string; + findItemIndex(item: any): number | string; + createFolderList(files: Object, rootPath: string): void; + updateNodeById(nodeId: any, key: any, value: any): void; + serverData: Object; + promiseObject: Object; + promise: Object; + localData: Object; + updataDataModel(): void; + } +} diff --git a/d.ts/kubernetes/ts/deployConfigs.d.ts b/d.ts/kubernetes/ts/deployConfigs.d.ts new file mode 100644 index 0000000..7eddf76 --- /dev/null +++ b/d.ts/kubernetes/ts/deployConfigs.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var BuildConfigsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/deploymentConfig.d.ts b/d.ts/kubernetes/ts/deploymentConfig.d.ts new file mode 100644 index 0000000..bc7fac6 --- /dev/null +++ b/d.ts/kubernetes/ts/deploymentConfig.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var DeploymentConfigController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/deploymentConfigs.d.ts b/d.ts/kubernetes/ts/deploymentConfigs.d.ts new file mode 100644 index 0000000..81cb0e1 --- /dev/null +++ b/d.ts/kubernetes/ts/deploymentConfigs.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var DeploymentConfigsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/editPod.d.ts b/d.ts/kubernetes/ts/editPod.d.ts new file mode 100644 index 0000000..0ed5f21 --- /dev/null +++ b/d.ts/kubernetes/ts/editPod.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var PodController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/events.d.ts b/d.ts/kubernetes/ts/events.d.ts new file mode 100644 index 0000000..5ab08e5 --- /dev/null +++ b/d.ts/kubernetes/ts/events.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var EventsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/host.d.ts b/d.ts/kubernetes/ts/host.d.ts new file mode 100644 index 0000000..5f8ff21 --- /dev/null +++ b/d.ts/kubernetes/ts/host.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +/// +declare module Kubernetes { + var HostController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/hosts.d.ts b/d.ts/kubernetes/ts/hosts.d.ts new file mode 100644 index 0000000..efba056 --- /dev/null +++ b/d.ts/kubernetes/ts/hosts.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +/// +declare module Kubernetes { + var HostsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/imageRepositories.d.ts b/d.ts/kubernetes/ts/imageRepositories.d.ts new file mode 100644 index 0000000..ddb4cb4 --- /dev/null +++ b/d.ts/kubernetes/ts/imageRepositories.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var ImageRepositoriesController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/kubernetesHelpers.d.ts b/d.ts/kubernetes/ts/kubernetesHelpers.d.ts new file mode 100644 index 0000000..26da9ae --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesHelpers.d.ts @@ -0,0 +1,208 @@ +/// +/// +declare module Kubernetes { + var context: string; + var hash: string; + var defaultRoute: string; + var pluginName: string; + var pluginPath: string; + var templatePath: string; + var log: Logging.Logger; + var keepPollingModel: boolean; + var defaultIconUrl: string; + var hostIconUrl: string; + var osConfig: KubernetesConfig; + var masterUrl: string; + var defaultApiVersion: string; + var defaultOSApiVersion: string; + var labelFilterTextSeparator: string; + var defaultNamespace: string; + var appSuffix: string; + var kibanaServiceName: string; + var fabric8ForgeServiceName: string; + var gogsServiceName: string; + var jenkinsServiceName: string; + var apimanServiceName: string; + var isOpenShift: boolean; + var sshSecretDataKeys: string[]; + var httpsSecretDataKeys: string[]; + function kubernetesNamespacePath(): string; + function apiPrefix(): string; + function osApiPrefix(): string; + function masterApiUrl(): string; + /** WARNING - this excludes the host name - you probably want to use: kubernetesApiUrl() instead!! */ + function kubernetesApiPrefix(): string; + function openshiftApiPrefix(): string; + function prefixForType(type: string): string; + function kubernetesApiUrl(): string; + function openshiftApiUrl(): string; + function resourcesUriForKind(type: any, ns?: any): string; + function uriTemplateForKubernetesKind(type: any): string; + function namespacePathForKind(type: any, ns: any): string; + /** + * Returns thevalue from the injector if its available or null + */ + function inject(name: any): T; + function createResource(thing: string, urlTemplate: string, $resource: ng.resource.IResourceService, KubernetesModel: any): ng.resource.IResourceClass>; + function imageRepositoriesRestURL(): string; + function deploymentConfigsRestURL(): string; + function buildsRestURL(): string; + function buildConfigHooksRestURL(): string; + function buildConfigsRestURL(): string; + function routesRestURL(): string; + function templatesRestURL(): string; + function getNamespace(entity: any): any; + function getLabels(entity: any): any; + function getName(entity: any): any; + function getKind(entity: any): any; + function getSelector(entity: any): any; + function getHost(pod: any): any; + function getStatus(pod: any): any; + function getPorts(service: any): any; + function getCreationTimestamp(entity: any): any; + var mbean: string; + var managerMBean: string; + var appViewMBean: string; + function isKubernetes(workspace?: any): boolean; + function isKubernetesTemplateManager(workspace?: any): boolean; + function isAppView(workspace?: any): boolean; + function getStrippedPathName(): string; + function linkContains(...words: String[]): boolean; + /** + * Returns true if the given link is active. The link can omit the leading # or / if necessary. + * The query parameters of the URL are ignored in the comparison. + * @method isLinkActive + * @param {String} href + * @return {Boolean} true if the given link is active + */ + function isLinkActive(href: string): boolean; + function setJson($scope: any, id: any, collection: any): void; + /** + * Returns the labels text string using the key1=value1,key2=value2,.... format + */ + function labelsToString(labels: any, seperatorText?: string): string; + function initShared($scope: any, $location: any, $http: any, $timeout: any, $routeParams: any, KubernetesModel: any, KubernetesState: any, KubernetesApiURL: any): void; + /** + * Returns the number of pods that are ready + */ + function readyPodCount(service: any): number; + /** + * Returns the service link URL for either the service name or the service object + */ + function serviceLinkUrl(service: any, httpOnly?: boolean): any; + /** + * Returns the total number of counters for the podCounters object + */ + function podCounterTotal($podCounters: any): number; + /** + * Given the list of pods lets iterate through them and find all pods matching the selector + * and return counters based on the status of the pod + */ + function createPodCounters(selector: any, pods: any, outputPods?: any[], podLinkQuery?: any, podLinkUrl?: any): { + podsLink: string; + ready: number; + valid: number; + waiting: number; + error: number; + }; + /** + * Converts the given json into an array of items. If the json contains a nested set of items then that is sorted; so that services + * are processed first; then turned into an array. Otherwise the json is put into an array so it can be processed polymorphically + */ + function convertKubernetesJsonToItems(json: any): any[]; + function isV1beta1Or2(): boolean; + /** + * Returns a link to the detail page for the given entity + */ + function entityPageLink(obj: any): any; + function resourceKindToUriPath(kind: any): string; + /** + * Returns the root URL for the kind + */ + function kubernetesUrlForKind(KubernetesApiURL: any, kind: any, namespace?: any, path?: any): string; + /** + * Returns the base URL for the kind of kubernetes resource or null if it cannot be found + */ + function kubernetesUrlForItemKind(KubernetesApiURL: any, json: any): string; + function kubernetesProxyUrlForService(KubernetesApiURL: any, service: any, path?: any): string; + function kubernetesProxyUrlForServiceCurrentNamespace(service: any, path?: any): string; + function buildConfigRestUrl(id: any): string; + function deploymentConfigRestUrl(id: any): string; + function imageRepositoryRestUrl(id: any): string; + function buildRestUrl(id: any): string; + function buildLogsRestUrl(id: any): string; + /** + * Runs the given application JSON + */ + function runApp($location: any, $scope: any, $http: any, KubernetesApiURL: any, json: any, name?: string, onSuccessFn?: any, namespace?: any, onCompleteFn?: any): void; + /** + * Returns true if the current status of the pod is running + */ + function isRunning(podCurrentState: any): any; + /** + * Returns true if the labels object has all of the key/value pairs from the selector + */ + function selectorMatches(selector: any, labels: any): boolean; + /** + * Returns the service registry + */ + function getServiceRegistry(): any; + /** + * Returns a link to the kibana logs web application + */ + function kibanaLogsLink(ServiceRegistry: any): string; + function openLogsForPods(ServiceRegistry: any, $window: any, namespace: any, pods: any): void; + function resizeController($http: any, KubernetesApiURL: any, replicationController: any, newReplicas: any, onCompleteFn?: any): void; + function statusTextToCssClass(text: any, ready?: boolean): string; + function podStatus(pod: any): any; + function isReady(pod: any): boolean; + function createAppViewPodCounters(appView: any): any[]; + function createAppViewServiceViews(appView: any): any[]; + /** + * converts a git path into an accessible URL for the browser + */ + function gitPathToUrl(iconPath: any, branch?: string): string; + function enrichBuildConfig(buildConfig: any, sortedBuilds: any): void; + function enrichBuildConfigs(buildConfigs: any, sortedBuilds?: any): any; + function enrichBuilds(builds: any): {}[]; + function enrichBuild(build: any): any; + function enrichDeploymentConfig(deploymentConfig: any): void; + function enrichDeploymentConfigs(deploymentConfigs: any): any; + function enrichEvent(event: any): void; + function enrichEvents(events: any, model?: any): any; + function enrichImageRepository(imageRepository: any): void; + function enrichImageRepositories(imageRepositories: any): any; + function containerLabelClass(labelType: string): string; + /** + * Returns true if the fabric8 forge plugin is enabled + */ + function isForgeEnabled(): boolean; + /** + * Returns the current kubernetes selected namespace or the default one + */ + function currentKubernetesNamespace(): any; + function setCurrentKubernetesNamespace(ns: any): void; + /** + * Configures the json schema + */ + function configureSchema(): void; + /** + * Lets remove any enriched data to leave the original json intact + */ + function unenrich(item: any): any; + /** + * Returns the unenriched JSON representation of an object + */ + function toRawJson(item: any): string; + /** + * Returns the unenriched YAML representation of an object + */ + function toRawYaml(item: any): any; + function watch($scope: any, $element: any, kind: any, ns: any, fn: any, labelSelector?: any): void; + function createKubernetesClient(kind: any, ns?: any): any; + function currentUserName(): any; + function createNamespace(ns: any, client?: any): void; + function createRC(obj: any, onCompleteFn?: any): void; + function updateReplicationControllerLabels($http: any, KubernetesApiURL: any, replicationController: any, newLabels: any, onCompleteFn?: any): void; + function connectOracle($http: any, $timeout: any, url: any, connectParam: any, rcName: any, delayTime: any): void; +} diff --git a/d.ts/kubernetes/ts/kubernetesInterfaces.d.ts b/d.ts/kubernetes/ts/kubernetesInterfaces.d.ts new file mode 100644 index 0000000..bd83b8e --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesInterfaces.d.ts @@ -0,0 +1,98 @@ +declare module Kubernetes { + class consts { + NAMESPACE_STORAGE_KEY: string; + } + var Constants: consts; + interface ApiLocation { + proto?: string; + hostPort: string; + prefix: string; + } + interface ApiLocations { + openshift?: ApiLocation; + k8s?: ApiLocation; + } + interface KubernetesConfig { + master_uri?: string; + api?: ApiLocations; + openshift?: OpenShiftOAuthConfig; + google?: GoogleOAuthConfig; + keycloak?: KeyCloakAuthConfig; + } + interface OpenShiftOAuthConfig { + oauth_authorize_uri: string; + oauth_client_id: string; + } + interface GoogleOAuthConfig { + authenticationURI: string; + authorizationURI: string; + clientId: string; + clientSecret: string; + redirectURI: string; + scope: string; + tokenURI?: string; + } + interface KeyCloakAuthConfig { + oauth_authorize_uri: string; + oauth_client_id: string; + } + interface KubernetesState { + namespaces: Array; + selectedNamespace: string; + } + class WatchTypes { + static ENDPOINTS: string; + static EVENTS: string; + static NAMESPACES: string; + static NODES: string; + static PERSISTENT_VOLUMES: string; + static PERSISTENT_VOLUME_CLAIMS: string; + static PODS: string; + static REPLICATION_CONTROLLERS: string; + static RESOURCE_QUOTAS: string; + static OAUTH_CLIENTS: string; + static SECRETS: string; + static SERVICES: string; + static SERVICE_ACCOUNTS: string; + static TEMPLATES: string; + static ROUTES: string; + static BUILD_CONFIGS: string; + static BUILDS: string; + static DEPLOYMENT_CONFIGS: string; + static IMAGE_STREAMS: string; + static POLICIES: string; + static POLICY_BINDINGS: string; + static PROJECTS: string; + static ROLE_BINDINGS: string; + static ROLES: string; + } + class NamespacedTypes { + static k8sTypes: Array; + static osTypes: Array; + } + class WatchActions { + static ANY: string; + static ADDED: string; + static MODIFIED: string; + static DELETED: string; + } + interface ObjectMap { + [uid: string]: any; + } + interface WatcherService { + hasWebSocket: boolean; + addCustomizer: (type: string, customizer: (obj: any) => void) => void; + getTypes: () => Array; + getNamespace: () => string; + setNamespace: (namespace: string) => void; + getObjects: (type: string) => Array; + getObjectMap: (type: string) => ObjectMap; + addAction: (type: string, action: string, fn: (obj: any) => void) => void; + registerListener: (fn: (objects: ObjectMap) => void) => void; + registerCustomUrlFunction: (kind: string, url: (kind: string) => string) => void; + } + interface KubePod { + id: string; + namespace: string; + } +} diff --git a/d.ts/kubernetes/ts/kubernetesJsonDirective.d.ts b/d.ts/kubernetes/ts/kubernetesJsonDirective.d.ts new file mode 100644 index 0000000..3c4889c --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesJsonDirective.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var KubernetesJsonDirective: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/kubernetesModel.d.ts b/d.ts/kubernetes/ts/kubernetesModel.d.ts new file mode 100644 index 0000000..1333b3e --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesModel.d.ts @@ -0,0 +1,54 @@ +/// +/// +declare module Kubernetes { + var FABRIC8_PROJECT_JSON: string; + /** + * The object which keeps track of all the pods, replication controllers, services and their associations + */ + class KubernetesModelService { + kubernetes: KubernetesState; + apps: any[]; + services: any[]; + replicationcontrollers: any[]; + replicationControllers: Array; + pods: any[]; + hosts: any[]; + namespaces: Array; + routes: any[]; + templates: any[]; + redraw: boolean; + resourceVersions: {}; + podsByHost: {}; + servicesByKey: {}; + replicationControllersByKey: {}; + podsByKey: {}; + appInfos: any[]; + appViews: any[]; + appFolders: any[]; + fetched: boolean; + showRunButton: boolean; + buildconfigs: any[]; + events: any[]; + workspaces: any[]; + projects: any[]; + project: any; + serviceApps: Array; + $keepPolling(): boolean; + orRedraw(flag: any): void; + getService(namespace: any, id: any): any; + getReplicationController(namespace: any, id: any): any; + getPod(namespace: any, id: any): any; + podsForNamespace(namespace?: any): any[]; + getBuildConfig(name: any): any; + getProject(name: any, ns?: any): any; + setProject(buildConfig: any): void; + /** + * Returns the current selected namespace or the default namespace + */ + currentNamespace(): any; + protected updateIconUrlAndAppInfo(entity: any, nameField: string): void; + maybeInit(): void; + protected updateApps(): void; + protected discoverPodConnections(entity: any): void; + } +} diff --git a/d.ts/kubernetes/ts/kubernetesNavigation.d.ts b/d.ts/kubernetes/ts/kubernetesNavigation.d.ts new file mode 100644 index 0000000..e6a9eb9 --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesNavigation.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + function selectSubNavBar($scope: any, tabName: any, newSubTabLabel: any): void; +} diff --git a/d.ts/kubernetes/ts/kubernetesPlugin.d.ts b/d.ts/kubernetes/ts/kubernetesPlugin.d.ts new file mode 100644 index 0000000..9ae5944 --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesPlugin.d.ts @@ -0,0 +1,13 @@ +/// +/// +declare var OSOAuthConfig: any; +declare var GoogleOAuthConfig: any; +declare var KeycloakConfig: any; +declare module Kubernetes { + var _module: ng.IModule; + var controller: (name: string, inlineAnnotatedConstructor: any[]) => ng.IModule; + var route: (templateName: string, reloadOnSearch?: boolean) => { + templateUrl: string; + reloadOnSearch: boolean; + }; +} diff --git a/d.ts/kubernetes/ts/kubernetesSchema.d.ts b/d.ts/kubernetes/ts/kubernetesSchema.d.ts new file mode 100644 index 0000000..98805f9 --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesSchema.d.ts @@ -0,0 +1,4 @@ +/// +/// +declare module Kubernetes { +} diff --git a/d.ts/kubernetes/ts/kubernetesServices.d.ts b/d.ts/kubernetes/ts/kubernetesServices.d.ts new file mode 100644 index 0000000..bab5421 --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesServices.d.ts @@ -0,0 +1,3 @@ +/// +declare module Kubernetes { +} diff --git a/d.ts/kubernetes/ts/kubernetesTopLevel.d.ts b/d.ts/kubernetes/ts/kubernetesTopLevel.d.ts new file mode 100644 index 0000000..dffd2d8 --- /dev/null +++ b/d.ts/kubernetes/ts/kubernetesTopLevel.d.ts @@ -0,0 +1,9 @@ +/// +/// +/// +/// +declare module Kubernetes { + var FileDropController: ng.IModule; + var NamespaceController: ng.IModule; + var TopLevel: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/namespace.d.ts b/d.ts/kubernetes/ts/namespace.d.ts new file mode 100644 index 0000000..ce20323 --- /dev/null +++ b/d.ts/kubernetes/ts/namespace.d.ts @@ -0,0 +1,4 @@ +/// +declare module Kubernetes { + var NamespaceController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/oracleStatusModel.d.ts b/d.ts/kubernetes/ts/oracleStatusModel.d.ts new file mode 100644 index 0000000..76445ad --- /dev/null +++ b/d.ts/kubernetes/ts/oracleStatusModel.d.ts @@ -0,0 +1,9 @@ +/// +/// +declare module Kubernetes { + class oracleModelService { + oraclecontrollers: any[]; + oracleControllers: Array; + findIndexOfOracleControllers(oracleControllers: Array, name: string): number; + } +} diff --git a/d.ts/kubernetes/ts/overview.d.ts b/d.ts/kubernetes/ts/overview.d.ts new file mode 100644 index 0000000..c1db8db --- /dev/null +++ b/d.ts/kubernetes/ts/overview.d.ts @@ -0,0 +1,5 @@ +/// +/// +/// +declare module Kubernetes { +} diff --git a/d.ts/kubernetes/ts/pipelines.d.ts b/d.ts/kubernetes/ts/pipelines.d.ts new file mode 100644 index 0000000..c58e19a --- /dev/null +++ b/d.ts/kubernetes/ts/pipelines.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + var PipelinesController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/pod.d.ts b/d.ts/kubernetes/ts/pod.d.ts new file mode 100644 index 0000000..0ed5f21 --- /dev/null +++ b/d.ts/kubernetes/ts/pod.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var PodController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/podEdit.d.ts b/d.ts/kubernetes/ts/podEdit.d.ts new file mode 100644 index 0000000..be89155 --- /dev/null +++ b/d.ts/kubernetes/ts/podEdit.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var PodEditController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/podLogs.d.ts b/d.ts/kubernetes/ts/podLogs.d.ts new file mode 100644 index 0000000..55ae2c5 --- /dev/null +++ b/d.ts/kubernetes/ts/podLogs.d.ts @@ -0,0 +1,4 @@ +/// +/// +declare module Kubernetes { +} diff --git a/d.ts/kubernetes/ts/pods.d.ts b/d.ts/kubernetes/ts/pods.d.ts new file mode 100644 index 0000000..9efc3e9 --- /dev/null +++ b/d.ts/kubernetes/ts/pods.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +declare module Kubernetes { + var EnvItem: ng.IModule; + var Pods: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/replicationController.d.ts b/d.ts/kubernetes/ts/replicationController.d.ts new file mode 100644 index 0000000..92f9731 --- /dev/null +++ b/d.ts/kubernetes/ts/replicationController.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var ReplicationControllerController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/replicationControllerEdit.d.ts b/d.ts/kubernetes/ts/replicationControllerEdit.d.ts new file mode 100644 index 0000000..8be9553 --- /dev/null +++ b/d.ts/kubernetes/ts/replicationControllerEdit.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var ReplicationControllerEditController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/replicationControllers.d.ts b/d.ts/kubernetes/ts/replicationControllers.d.ts new file mode 100644 index 0000000..9f818b0 --- /dev/null +++ b/d.ts/kubernetes/ts/replicationControllers.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var ReplicationControllers: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/schema.d.ts b/d.ts/kubernetes/ts/schema.d.ts new file mode 100644 index 0000000..083f850 --- /dev/null +++ b/d.ts/kubernetes/ts/schema.d.ts @@ -0,0 +1,6677 @@ +/// +declare module Kubernetes { + var schema: { + "id": string; + "$schema": string; + "definitions": { + "api_RootPaths": { + "type": string; + "description": string; + "properties": { + "paths": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_AWSElasticBlockStoreVolumeSource": { + "type": string; + "description": string; + "properties": { + "fsType": { + "type": string; + "description": string; + }; + "partition": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + "volumeID": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Capabilities": { + "type": string; + "description": string; + "properties": { + "add": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "drop": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_CephFSVolumeSource": { + "type": string; + "description": string; + "properties": { + "monitors": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "readOnly": { + "type": string; + "description": string; + }; + "secretFile": { + "type": string; + "description": string; + }; + "secretRef": { + "$ref": string; + "javaType": string; + }; + "user": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Container": { + "type": string; + "description": string; + "properties": { + "args": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "command": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "env": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "image": { + "type": string; + "description": string; + }; + "imagePullPolicy": { + "type": string; + "description": string; + }; + "lifecycle": { + "$ref": string; + "javaType": string; + }; + "livenessProbe": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "ports": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "readinessProbe": { + "$ref": string; + "javaType": string; + }; + "resources": { + "$ref": string; + "javaType": string; + }; + "securityContext": { + "$ref": string; + "javaType": string; + }; + "stdin": { + "type": string; + "description": string; + }; + "terminationMessagePath": { + "type": string; + "description": string; + }; + "tty": { + "type": string; + "description": string; + }; + "volumeMounts": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "workingDir": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ContainerPort": { + "type": string; + "description": string; + "properties": { + "containerPort": { + "type": string; + "description": string; + }; + "hostIP": { + "type": string; + "description": string; + }; + "hostPort": { + "type": string; + "description": string; + }; + "name": { + "type": string; + "description": string; + }; + "protocol": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ContainerState": { + "type": string; + "description": string; + "properties": { + "running": { + "$ref": string; + "javaType": string; + }; + "terminated": { + "$ref": string; + "javaType": string; + }; + "waiting": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ContainerStateRunning": { + "type": string; + "description": string; + "properties": { + "startedAt": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ContainerStateTerminated": { + "type": string; + "description": string; + "properties": { + "containerID": { + "type": string; + "description": string; + }; + "exitCode": { + "type": string; + "description": string; + }; + "finishedAt": { + "type": string; + "description": string; + }; + "message": { + "type": string; + "description": string; + }; + "reason": { + "type": string; + "description": string; + }; + "signal": { + "type": string; + "description": string; + }; + "startedAt": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ContainerStateWaiting": { + "type": string; + "description": string; + "properties": { + "reason": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ContainerStatus": { + "type": string; + "description": string; + "properties": { + "containerID": { + "type": string; + "description": string; + }; + "image": { + "type": string; + "description": string; + }; + "imageID": { + "type": string; + "description": string; + }; + "lastState": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "ready": { + "type": string; + "description": string; + }; + "restartCount": { + "type": string; + "description": string; + }; + "state": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_EmptyDirVolumeSource": { + "type": string; + "description": string; + "properties": { + "medium": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_EndpointAddress": { + "type": string; + "description": string; + "properties": { + "ip": { + "type": string; + "description": string; + }; + "targetRef": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_EndpointPort": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "port": { + "type": string; + "description": string; + }; + "protocol": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_EndpointSubset": { + "type": string; + "description": string; + "properties": { + "addresses": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "ports": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Endpoints": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "subsets": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_EndpointsList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_EnvVar": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + "pattern": string; + }; + "value": { + "type": string; + "description": string; + }; + "valueFrom": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_EnvVarSource": { + "type": string; + "description": string; + "properties": { + "fieldRef": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Event": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "count": { + "type": string; + "description": string; + }; + "firstTimestamp": { + "type": string; + "description": string; + }; + "involvedObject": { + "$ref": string; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "lastTimestamp": { + "type": string; + "description": string; + }; + "message": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "reason": { + "type": string; + "description": string; + }; + "source": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_EventList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_EventSource": { + "type": string; + "description": string; + "properties": { + "component": { + "type": string; + "description": string; + }; + "host": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ExecAction": { + "type": string; + "description": string; + "properties": { + "command": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_GCEPersistentDiskVolumeSource": { + "type": string; + "description": string; + "properties": { + "fsType": { + "type": string; + "description": string; + }; + "partition": { + "type": string; + "description": string; + }; + "pdName": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_GitRepoVolumeSource": { + "type": string; + "description": string; + "properties": { + "repository": { + "type": string; + "description": string; + }; + "revision": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_GlusterfsVolumeSource": { + "type": string; + "description": string; + "properties": { + "endpoints": { + "type": string; + "description": string; + }; + "path": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_HTTPGetAction": { + "type": string; + "description": string; + "properties": { + "host": { + "type": string; + "description": string; + }; + "path": { + "type": string; + "description": string; + }; + "port": { + "$ref": string; + "javaType": string; + }; + "scheme": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Handler": { + "type": string; + "description": string; + "properties": { + "exec": { + "$ref": string; + "javaType": string; + }; + "httpGet": { + "$ref": string; + "javaType": string; + }; + "tcpSocket": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_HostPathVolumeSource": { + "type": string; + "description": string; + "properties": { + "path": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ISCSIVolumeSource": { + "type": string; + "description": string; + "properties": { + "fsType": { + "type": string; + "description": string; + }; + "iqn": { + "type": string; + "description": string; + }; + "lun": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + "targetPortal": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Lifecycle": { + "type": string; + "description": string; + "properties": { + "postStart": { + "$ref": string; + "javaType": string; + }; + "preStop": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_List": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ListMeta": { + "type": string; + "description": string; + "properties": { + "resourceVersion": { + "type": string; + "description": string; + }; + "selfLink": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_LoadBalancerIngress": { + "type": string; + "description": string; + "properties": { + "hostname": { + "type": string; + "description": string; + }; + "ip": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_LoadBalancerStatus": { + "type": string; + "description": string; + "properties": { + "ingress": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_LocalObjectReference": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_MetadataFile": { + "type": string; + "description": string; + "properties": { + "fieldRef": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_MetadataVolumeSource": { + "type": string; + "description": string; + "properties": { + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_NFSVolumeSource": { + "type": string; + "description": string; + "properties": { + "path": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + "server": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Namespace": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_NamespaceList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_NamespaceSpec": { + "type": string; + "description": string; + "properties": { + "finalizers": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_NamespaceStatus": { + "type": string; + "description": string; + "properties": { + "phase": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Node": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_NodeAddress": { + "type": string; + "description": string; + "properties": { + "address": { + "type": string; + "description": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_NodeCondition": { + "type": string; + "description": string; + "properties": { + "lastHeartbeatTime": { + "type": string; + "description": string; + }; + "lastTransitionTime": { + "type": string; + "description": string; + }; + "message": { + "type": string; + "description": string; + }; + "reason": { + "type": string; + "description": string; + }; + "status": { + "type": string; + "description": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_NodeList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_NodeSpec": { + "type": string; + "description": string; + "properties": { + "externalID": { + "type": string; + "description": string; + }; + "podCIDR": { + "type": string; + "description": string; + }; + "providerID": { + "type": string; + "description": string; + }; + "unschedulable": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_NodeStatus": { + "type": string; + "description": string; + "properties": { + "addresses": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "capacity": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + "conditions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "nodeInfo": { + "$ref": string; + "javaType": string; + }; + "phase": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_NodeSystemInfo": { + "type": string; + "description": string; + "properties": { + "bootID": { + "type": string; + "description": string; + }; + "containerRuntimeVersion": { + "type": string; + "description": string; + }; + "kernelVersion": { + "type": string; + "description": string; + }; + "kubeProxyVersion": { + "type": string; + "description": string; + }; + "kubeletVersion": { + "type": string; + "description": string; + }; + "machineID": { + "type": string; + "description": string; + }; + "osImage": { + "type": string; + "description": string; + }; + "systemUUID": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ObjectFieldSelector": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + }; + "fieldPath": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ObjectMeta": { + "type": string; + "description": string; + "properties": { + "annotations": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "creationTimestamp": { + "type": string; + "description": string; + }; + "deletionTimestamp": { + "type": string; + "description": string; + }; + "generateName": { + "type": string; + "description": string; + }; + "generation": { + "type": string; + "description": string; + "javaType": string; + }; + "labels": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "namespace": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "resourceVersion": { + "type": string; + "description": string; + }; + "selfLink": { + "type": string; + "description": string; + }; + "uid": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ObjectReference": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + }; + "fieldPath": { + "type": string; + "description": string; + }; + "kind": { + "type": string; + "description": string; + }; + "name": { + "type": string; + "description": string; + }; + "namespace": { + "type": string; + "description": string; + }; + "resourceVersion": { + "type": string; + "description": string; + }; + "uid": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PersistentVolume": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_PersistentVolumeClaim": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_PersistentVolumeClaimList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_PersistentVolumeClaimSpec": { + "type": string; + "description": string; + "properties": { + "accessModes": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "resources": { + "$ref": string; + "javaType": string; + }; + "volumeName": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PersistentVolumeClaimStatus": { + "type": string; + "description": string; + "properties": { + "accessModes": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "capacity": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + "phase": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PersistentVolumeClaimVolumeSource": { + "type": string; + "description": string; + "properties": { + "claimName": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PersistentVolumeList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_PersistentVolumeSource": { + "type": string; + "description": string; + "properties": { + "awsElasticBlockStore": { + "$ref": string; + "javaType": string; + }; + "cephfs": { + "$ref": string; + "javaType": string; + }; + "gcePersistentDisk": { + "$ref": string; + "javaType": string; + }; + "glusterfs": { + "$ref": string; + "javaType": string; + }; + "hostPath": { + "$ref": string; + "javaType": string; + }; + "iscsi": { + "$ref": string; + "javaType": string; + }; + "nfs": { + "$ref": string; + "javaType": string; + }; + "rbd": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PersistentVolumeSpec": { + "type": string; + "description": string; + "properties": { + "accessModes": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "awsElasticBlockStore": { + "$ref": string; + "javaType": string; + }; + "capacity": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + "cephfs": { + "$ref": string; + "javaType": string; + }; + "claimRef": { + "$ref": string; + "javaType": string; + }; + "gcePersistentDisk": { + "$ref": string; + "javaType": string; + }; + "glusterfs": { + "$ref": string; + "javaType": string; + }; + "hostPath": { + "$ref": string; + "javaType": string; + }; + "iscsi": { + "$ref": string; + "javaType": string; + }; + "nfs": { + "$ref": string; + "javaType": string; + }; + "persistentVolumeReclaimPolicy": { + "type": string; + "description": string; + }; + "rbd": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PersistentVolumeStatus": { + "type": string; + "description": string; + "properties": { + "message": { + "type": string; + "description": string; + }; + "phase": { + "type": string; + "description": string; + }; + "reason": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Pod": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_PodCondition": { + "type": string; + "description": string; + "properties": { + "status": { + "type": string; + "description": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PodList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_PodSpec": { + "type": string; + "description": string; + "properties": { + "activeDeadlineSeconds": { + "type": string; + "description": string; + "javaType": string; + }; + "containers": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "dnsPolicy": { + "type": string; + "description": string; + }; + "host": { + "type": string; + "description": string; + }; + "hostNetwork": { + "type": string; + "description": string; + }; + "imagePullSecrets": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "nodeName": { + "type": string; + "description": string; + }; + "nodeSelector": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "restartPolicy": { + "type": string; + "description": string; + }; + "serviceAccount": { + "type": string; + "description": string; + }; + "serviceAccountName": { + "type": string; + "description": string; + }; + "terminationGracePeriodSeconds": { + "type": string; + "description": string; + "javaType": string; + }; + "volumes": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PodStatus": { + "type": string; + "description": string; + "properties": { + "conditions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "containerStatuses": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "hostIP": { + "type": string; + "description": string; + }; + "message": { + "type": string; + "description": string; + }; + "phase": { + "type": string; + "description": string; + }; + "podIP": { + "type": string; + "description": string; + }; + "reason": { + "type": string; + "description": string; + }; + "startTime": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_PodTemplateSpec": { + "type": string; + "description": string; + "properties": { + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Probe": { + "type": string; + "description": string; + "properties": { + "exec": { + "$ref": string; + "javaType": string; + }; + "httpGet": { + "$ref": string; + "javaType": string; + }; + "initialDelaySeconds": { + "type": string; + "description": string; + "javaType": string; + }; + "tcpSocket": { + "$ref": string; + "javaType": string; + }; + "timeoutSeconds": { + "type": string; + "description": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_RBDVolumeSource": { + "type": string; + "description": string; + "properties": { + "fsType": { + "type": string; + "description": string; + }; + "image": { + "type": string; + "description": string; + }; + "keyring": { + "type": string; + "description": string; + }; + "monitors": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "pool": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + "secretRef": { + "$ref": string; + "javaType": string; + }; + "user": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ReplicationController": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ReplicationControllerList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ReplicationControllerSpec": { + "type": string; + "description": string; + "properties": { + "replicas": { + "type": string; + "description": string; + }; + "selector": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "template": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ReplicationControllerStatus": { + "type": string; + "description": string; + "properties": { + "observedGeneration": { + "type": string; + "description": string; + "javaType": string; + }; + "replicas": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ResourceQuota": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ResourceQuotaList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ResourceQuotaSpec": { + "type": string; + "description": string; + "properties": { + "hard": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ResourceQuotaStatus": { + "type": string; + "description": string; + "properties": { + "hard": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + "used": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ResourceRequirements": { + "type": string; + "description": string; + "properties": { + "limits": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + "requests": { + "type": string; + "description": string; + "additionalProperties": { + "$ref": string; + "javaType": string; + }; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_RunAsUserStrategyOptions": { + "type": string; + "description": string; + "properties": { + "type": { + "type": string; + "description": string; + }; + "uid": { + "type": string; + "description": string; + "javaType": string; + }; + "uidRangeMax": { + "type": string; + "description": string; + "javaType": string; + }; + "uidRangeMin": { + "type": string; + "description": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_SELinuxContextStrategyOptions": { + "type": string; + "description": string; + "properties": { + "seLinuxOptions": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_SELinuxOptions": { + "type": string; + "description": string; + "properties": { + "level": { + "type": string; + "description": string; + }; + "role": { + "type": string; + "description": string; + }; + "type": { + "type": string; + "description": string; + }; + "user": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Secret": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "data": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_SecretList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_SecretVolumeSource": { + "type": string; + "description": string; + "properties": { + "secretName": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_SecurityContext": { + "type": string; + "description": string; + "properties": { + "capabilities": { + "$ref": string; + "javaType": string; + }; + "privileged": { + "type": string; + "description": string; + }; + "runAsNonRoot": { + "type": string; + "description": string; + }; + "runAsUser": { + "type": string; + "description": string; + "javaType": string; + }; + "seLinuxOptions": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_SecurityContextConstraints": { + "type": string; + "description": string; + "properties": { + "allowHostDirVolumePlugin": { + "type": string; + "description": string; + }; + "allowHostNetwork": { + "type": string; + "description": string; + }; + "allowHostPorts": { + "type": string; + "description": string; + }; + "allowPrivilegedContainer": { + "type": string; + "description": string; + }; + "allowedCapabilities": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "groups": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "runAsUser": { + "$ref": string; + "javaType": string; + }; + "seLinuxContext": { + "$ref": string; + "javaType": string; + }; + "users": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_SecurityContextConstraintsList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_Service": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ServiceAccount": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "imagePullSecrets": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "secrets": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ServiceAccountList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ServiceList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "kubernetes_ServicePort": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "nodePort": { + "type": string; + "description": string; + }; + "port": { + "type": string; + "description": string; + }; + "protocol": { + "type": string; + "description": string; + }; + "targetPort": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ServiceSpec": { + "type": string; + "description": string; + "properties": { + "clusterIP": { + "type": string; + "description": string; + }; + "deprecatedPublicIPs": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "portalIP": { + "type": string; + "description": string; + }; + "ports": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "selector": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "sessionAffinity": { + "type": string; + "description": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_ServiceStatus": { + "type": string; + "description": string; + "properties": { + "loadBalancer": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Status": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "code": { + "type": string; + "description": string; + }; + "details": { + "$ref": string; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "message": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "reason": { + "type": string; + "description": string; + }; + "status": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_StatusCause": { + "type": string; + "description": string; + "properties": { + "field": { + "type": string; + "description": string; + }; + "message": { + "type": string; + "description": string; + }; + "reason": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_StatusDetails": { + "type": string; + "description": string; + "properties": { + "causes": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + }; + "name": { + "type": string; + "description": string; + }; + "retryAfterSeconds": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_TCPSocketAction": { + "type": string; + "description": string; + "properties": { + "port": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_TypeMeta": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + }; + "kind": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_Volume": { + "type": string; + "description": string; + "properties": { + "awsElasticBlockStore": { + "$ref": string; + "javaType": string; + }; + "cephfs": { + "$ref": string; + "javaType": string; + }; + "emptyDir": { + "$ref": string; + "javaType": string; + }; + "gcePersistentDisk": { + "$ref": string; + "javaType": string; + }; + "gitRepo": { + "$ref": string; + "javaType": string; + }; + "glusterfs": { + "$ref": string; + "javaType": string; + }; + "hostPath": { + "$ref": string; + "javaType": string; + }; + "iscsi": { + "$ref": string; + "javaType": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + "maxLength": number; + "pattern": string; + }; + "nfs": { + "$ref": string; + "javaType": string; + }; + "persistentVolumeClaim": { + "$ref": string; + "javaType": string; + }; + "rbd": { + "$ref": string; + "javaType": string; + }; + "secret": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_VolumeMount": { + "type": string; + "description": string; + "properties": { + "mountPath": { + "type": string; + "description": string; + }; + "name": { + "type": string; + "description": string; + }; + "readOnly": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_VolumeSource": { + "type": string; + "description": string; + "properties": { + "awsElasticBlockStore": { + "$ref": string; + "javaType": string; + }; + "cephfs": { + "$ref": string; + "javaType": string; + }; + "emptyDir": { + "$ref": string; + "javaType": string; + }; + "gcePersistentDisk": { + "$ref": string; + "javaType": string; + }; + "gitRepo": { + "$ref": string; + "javaType": string; + }; + "glusterfs": { + "$ref": string; + "javaType": string; + }; + "hostPath": { + "$ref": string; + "javaType": string; + }; + "iscsi": { + "$ref": string; + "javaType": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "nfs": { + "$ref": string; + "javaType": string; + }; + "persistentVolumeClaim": { + "$ref": string; + "javaType": string; + }; + "rbd": { + "$ref": string; + "javaType": string; + }; + "secret": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_AuthInfo": { + "type": string; + "description": string; + "properties": { + "client-certificate": { + "type": string; + "description": string; + }; + "client-certificate-data": { + "type": string; + "description": string; + }; + "client-key": { + "type": string; + "description": string; + }; + "client-key-data": { + "type": string; + "description": string; + }; + "extensions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "password": { + "type": string; + "description": string; + }; + "token": { + "type": string; + "description": string; + }; + "username": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_Cluster": { + "type": string; + "description": string; + "properties": { + "api-version": { + "type": string; + "description": string; + }; + "certificate-authority": { + "type": string; + "description": string; + }; + "certificate-authority-data": { + "type": string; + "description": string; + }; + "extensions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "insecure-skip-tls-verify": { + "type": string; + "description": string; + }; + "server": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_Config": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + }; + "clusters": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "contexts": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "current-context": { + "type": string; + "description": string; + }; + "extensions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + }; + "preferences": { + "$ref": string; + "javaType": string; + }; + "users": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_Context": { + "type": string; + "description": string; + "properties": { + "cluster": { + "type": string; + "description": string; + }; + "extensions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "namespace": { + "type": string; + "description": string; + }; + "user": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_NamedAuthInfo": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + }; + "user": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_NamedCluster": { + "type": string; + "description": string; + "properties": { + "cluster": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_NamedContext": { + "type": string; + "description": string; + "properties": { + "context": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_NamedExtension": { + "type": string; + "description": string; + "properties": { + "extension": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_config_Preferences": { + "type": string; + "description": string; + "properties": { + "colors": { + "type": string; + "description": string; + }; + "extensions": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_resource_Quantity": { + "type": string; + "description": string; + "properties": { + "Amount": { + "$ref": string; + "javaType": string; + }; + "Format": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_runtime_RawExtension": { + "type": string; + "description": string; + "properties": { + "RawJSON": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_util_IntOrString": { + "type": string; + "description": string; + "properties": { + "IntVal": { + "type": string; + "description": string; + }; + "Kind": { + "type": string; + "description": string; + }; + "StrVal": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "kubernetes_watch_WatchEvent": { + "type": string; + "description": string; + "properties": { + "object": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_AuthorizationAttributes": { + "type": string; + "description": string; + "properties": { + "content": { + "$ref": string; + "javaType": string; + }; + "namespace": { + "type": string; + "description": string; + }; + "resource": { + "type": string; + "description": string; + }; + "resourceName": { + "type": string; + "description": string; + }; + "verb": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_ClusterPolicy": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "lastModified": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "roles": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_ClusterPolicyBinding": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "lastModified": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "policyRef": { + "$ref": string; + "javaType": string; + }; + "roleBindings": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_ClusterPolicyBindingList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_ClusterPolicyList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_ClusterRole": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "rules": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_ClusterRoleBinding": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "groupNames": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "roleRef": { + "$ref": string; + "javaType": string; + }; + "subjects": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "userNames": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_ClusterRoleBindingList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_LocalSubjectAccessReview": { + "type": string; + "description": string; + "properties": { + "TypeMeta": { + "$ref": string; + "javaType": string; + }; + "content": { + "$ref": string; + "javaType": string; + }; + "groups": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "namespace": { + "type": string; + "description": string; + }; + "resource": { + "type": string; + "description": string; + }; + "resourceName": { + "type": string; + "description": string; + }; + "user": { + "type": string; + "description": string; + }; + "verb": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_NamedClusterRole": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + }; + "role": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_NamedClusterRoleBinding": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + }; + "roleBinding": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_NamedRole": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + }; + "role": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_NamedRoleBinding": { + "type": string; + "description": string; + "properties": { + "name": { + "type": string; + "description": string; + }; + "roleBinding": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_Policy": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "lastModified": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "roles": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_PolicyBinding": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "lastModified": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "policyRef": { + "$ref": string; + "javaType": string; + }; + "roleBindings": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_PolicyBindingList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_PolicyList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_PolicyRule": { + "type": string; + "description": string; + "properties": { + "attributeRestrictions": { + "$ref": string; + "javaType": string; + }; + "nonResourceURLs": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "resourceNames": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "resources": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "verbs": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_Role": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "rules": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_RoleBinding": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "groupNames": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "roleRef": { + "$ref": string; + "javaType": string; + }; + "subjects": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "userNames": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_RoleBindingList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_RoleList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_authorization_SubjectAccessReview": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "content": { + "$ref": string; + "javaType": string; + }; + "groups": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "namespace": { + "type": string; + "description": string; + }; + "resource": { + "type": string; + "description": string; + }; + "resourceName": { + "type": string; + "description": string; + }; + "user": { + "type": string; + "description": string; + }; + "verb": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_authorization_SubjectAccessReviewResponse": { + "type": string; + "description": string; + "properties": { + "allowed": { + "type": string; + "description": string; + }; + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "namespace": { + "type": string; + "description": string; + }; + "reason": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_Build": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_build_BuildConfig": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_build_BuildConfigList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_build_BuildConfigSpec": { + "type": string; + "description": string; + "properties": { + "output": { + "$ref": string; + "javaType": string; + }; + "resources": { + "$ref": string; + "javaType": string; + }; + "revision": { + "$ref": string; + "javaType": string; + }; + "serviceAccount": { + "type": string; + "description": string; + }; + "source": { + "$ref": string; + "javaType": string; + }; + "strategy": { + "$ref": string; + "javaType": string; + }; + "triggers": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildConfigStatus": { + "type": string; + "description": string; + "properties": { + "lastVersion": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_build_BuildOutput": { + "type": string; + "description": string; + "properties": { + "pushSecret": { + "$ref": string; + "javaType": string; + }; + "to": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildRequest": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "from": { + "$ref": string; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "lastVersion": { + "type": string; + "description": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "revision": { + "$ref": string; + "javaType": string; + }; + "triggeredByImage": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_build_BuildSource": { + "type": string; + "description": string; + "properties": { + "contextDir": { + "type": string; + "description": string; + }; + "git": { + "$ref": string; + "javaType": string; + }; + "sourceSecret": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildSpec": { + "type": string; + "description": string; + "properties": { + "output": { + "$ref": string; + "javaType": string; + }; + "resources": { + "$ref": string; + "javaType": string; + }; + "revision": { + "$ref": string; + "javaType": string; + }; + "serviceAccount": { + "type": string; + "description": string; + }; + "source": { + "$ref": string; + "javaType": string; + }; + "strategy": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildStatus": { + "type": string; + "description": string; + "properties": { + "cancelled": { + "type": string; + "description": string; + }; + "completionTimestamp": { + "type": string; + "description": string; + }; + "config": { + "$ref": string; + "javaType": string; + }; + "duration": { + "type": string; + "description": string; + "javaType": string; + }; + "message": { + "type": string; + "description": string; + }; + "phase": { + "type": string; + "description": string; + }; + "startTimestamp": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildStrategy": { + "type": string; + "description": string; + "properties": { + "customStrategy": { + "$ref": string; + "javaType": string; + }; + "dockerStrategy": { + "$ref": string; + "javaType": string; + }; + "sourceStrategy": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_BuildTriggerPolicy": { + "type": string; + "description": string; + "properties": { + "generic": { + "$ref": string; + "javaType": string; + }; + "github": { + "$ref": string; + "javaType": string; + }; + "imageChange": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_CustomBuildStrategy": { + "type": string; + "description": string; + "properties": { + "env": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "exposeDockerSocket": { + "type": string; + "description": string; + }; + "forcePull": { + "type": string; + "description": string; + }; + "from": { + "$ref": string; + "javaType": string; + }; + "pullSecret": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_DockerBuildStrategy": { + "type": string; + "description": string; + "properties": { + "env": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "forcePull": { + "type": string; + "description": string; + }; + "from": { + "$ref": string; + "javaType": string; + }; + "noCache": { + "type": string; + "description": string; + }; + "pullSecret": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_GitBuildSource": { + "type": string; + "description": string; + "properties": { + "httpProxy": { + "type": string; + "description": string; + }; + "httpsProxy": { + "type": string; + "description": string; + }; + "ref": { + "type": string; + "description": string; + }; + "uri": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_GitSourceRevision": { + "type": string; + "description": string; + "properties": { + "author": { + "$ref": string; + "javaType": string; + }; + "commit": { + "type": string; + "description": string; + }; + "committer": { + "$ref": string; + "javaType": string; + }; + "message": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_ImageChangeTrigger": { + "type": string; + "description": string; + "properties": { + "from": { + "$ref": string; + "javaType": string; + }; + "lastTriggeredImageID": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_SourceBuildStrategy": { + "type": string; + "description": string; + "properties": { + "env": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "forcePull": { + "type": string; + "description": string; + }; + "from": { + "$ref": string; + "javaType": string; + }; + "incremental": { + "type": string; + "description": string; + }; + "pullSecret": { + "$ref": string; + "javaType": string; + }; + "scripts": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_SourceControlUser": { + "type": string; + "description": string; + "properties": { + "email": { + "type": string; + "description": string; + }; + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_SourceRevision": { + "type": string; + "description": string; + "properties": { + "git": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_build_WebHookTrigger": { + "type": string; + "description": string; + "properties": { + "secret": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_CustomDeploymentStrategyParams": { + "type": string; + "description": string; + "properties": { + "command": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "environment": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "image": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentCause": { + "type": string; + "description": string; + "properties": { + "imageTrigger": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentCauseImageTrigger": { + "type": string; + "description": string; + "properties": { + "from": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentConfig": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_deploy_DeploymentConfigList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_deploy_DeploymentConfigSpec": { + "type": string; + "description": string; + "properties": { + "replicas": { + "type": string; + "description": string; + }; + "selector": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "strategy": { + "$ref": string; + "javaType": string; + }; + "template": { + "$ref": string; + "javaType": string; + }; + "triggers": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentConfigStatus": { + "type": string; + "description": string; + "properties": { + "details": { + "$ref": string; + "javaType": string; + }; + "latestVersion": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentDetails": { + "type": string; + "description": string; + "properties": { + "causes": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "message": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentStrategy": { + "type": string; + "description": string; + "properties": { + "customParams": { + "$ref": string; + "javaType": string; + }; + "recreateParams": { + "$ref": string; + "javaType": string; + }; + "resources": { + "$ref": string; + "javaType": string; + }; + "rollingParams": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentTriggerImageChangeParams": { + "type": string; + "description": string; + "properties": { + "automatic": { + "type": string; + "description": string; + }; + "containerNames": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "from": { + "$ref": string; + "javaType": string; + }; + "lastTriggeredImage": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_DeploymentTriggerPolicy": { + "type": string; + "description": string; + "properties": { + "imageChangeParams": { + "$ref": string; + "javaType": string; + }; + "type": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_ExecNewPodHook": { + "type": string; + "description": string; + "properties": { + "command": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "containerName": { + "type": string; + "description": string; + }; + "env": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_LifecycleHook": { + "type": string; + "description": string; + "properties": { + "execNewPod": { + "$ref": string; + "javaType": string; + }; + "failurePolicy": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_RecreateDeploymentStrategyParams": { + "type": string; + "description": string; + "properties": { + "post": { + "$ref": string; + "javaType": string; + }; + "pre": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_deploy_RollingDeploymentStrategyParams": { + "type": string; + "description": string; + "properties": { + "intervalSeconds": { + "type": string; + "description": string; + "javaType": string; + }; + "post": { + "$ref": string; + "javaType": string; + }; + "pre": { + "$ref": string; + "javaType": string; + }; + "timeoutSeconds": { + "type": string; + "description": string; + "javaType": string; + }; + "updatePercent": { + "type": string; + "description": string; + }; + "updatePeriodSeconds": { + "type": string; + "description": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_image_Image": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "dockerImageManifest": { + "type": string; + "description": string; + }; + "dockerImageMetadata": { + "$ref": string; + "javaType": string; + }; + "dockerImageMetadataVersion": { + "type": string; + "description": string; + }; + "dockerImageReference": { + "type": string; + "description": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_image_ImageList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_image_ImageStream": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_image_ImageStreamList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_image_ImageStreamSpec": { + "type": string; + "description": string; + "properties": { + "dockerImageRepository": { + "type": string; + "description": string; + }; + "tags": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_image_ImageStreamStatus": { + "type": string; + "description": string; + "properties": { + "dockerImageRepository": { + "type": string; + "description": string; + }; + "tags": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_image_NamedTagEventList": { + "type": string; + "description": string; + "properties": { + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "tag": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_image_NamedTagReference": { + "type": string; + "description": string; + "properties": { + "annotations": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "from": { + "$ref": string; + "javaType": string; + }; + "name": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_image_TagEvent": { + "type": string; + "description": string; + "properties": { + "created": { + "type": string; + "description": string; + }; + "dockerImageReference": { + "type": string; + "description": string; + }; + "image": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_oauth_OAuthAccessToken": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "authorizeToken": { + "type": string; + "description": string; + }; + "clientName": { + "type": string; + "description": string; + }; + "expiresIn": { + "type": string; + "description": string; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "redirectURI": { + "type": string; + "description": string; + }; + "refreshToken": { + "type": string; + "description": string; + }; + "scopes": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "userName": { + "type": string; + "description": string; + }; + "userUID": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthAccessTokenList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthAuthorizeToken": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "clientName": { + "type": string; + "description": string; + }; + "expiresIn": { + "type": string; + "description": string; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "redirectURI": { + "type": string; + "description": string; + }; + "scopes": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "state": { + "type": string; + "description": string; + }; + "userName": { + "type": string; + "description": string; + }; + "userUID": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthAuthorizeTokenList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthClient": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "redirectURIs": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "respondWithChallenges": { + "type": string; + "description": string; + }; + "secret": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthClientAuthorization": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "clientName": { + "type": string; + "description": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "scopes": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "userName": { + "type": string; + "description": string; + }; + "userUID": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthClientAuthorizationList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_oauth_OAuthClientList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_project_Project": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_project_ProjectList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_project_ProjectRequest": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "description": { + "type": string; + "description": string; + }; + "displayName": { + "type": string; + "description": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_project_ProjectSpec": { + "type": string; + "description": string; + "properties": { + "finalizers": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_project_ProjectStatus": { + "type": string; + "description": string; + "properties": { + "phase": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_route_Route": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "spec": { + "$ref": string; + "javaType": string; + }; + "status": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_route_RouteList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_route_RouteSpec": { + "type": string; + "description": string; + "properties": { + "host": { + "type": string; + "description": string; + }; + "path": { + "type": string; + "description": string; + }; + "tls": { + "$ref": string; + "javaType": string; + }; + "to": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_route_RouteStatus": { + "type": string; + "description": string; + "additionalProperties": boolean; + "javaType": string; + }; + "os_route_TLSConfig": { + "type": string; + "description": string; + "properties": { + "caCertificate": { + "type": string; + "description": string; + }; + "certificate": { + "type": string; + "description": string; + }; + "destinationCACertificate": { + "type": string; + "description": string; + }; + "key": { + "type": string; + "description": string; + }; + "termination": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_template_Parameter": { + "type": string; + "description": string; + "properties": { + "description": { + "type": string; + "description": string; + }; + "from": { + "type": string; + "description": string; + }; + "generate": { + "type": string; + "description": string; + }; + "name": { + "type": string; + "description": string; + }; + "required": { + "type": string; + "description": string; + }; + "value": { + "type": string; + "description": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + }; + "os_template_Template": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "labels": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "objects": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "parameters": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_template_TemplateList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_user_Group": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "users": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_user_GroupList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_user_Identity": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "extra": { + "type": string; + "description": string; + "additionalProperties": { + "type": string; + "description": string; + }; + "javaType": string; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + "providerName": { + "type": string; + "description": string; + }; + "providerUserName": { + "type": string; + "description": string; + }; + "user": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_user_IdentityList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_user_User": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "fullName": { + "type": string; + "description": string; + }; + "groups": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "identities": { + "type": string; + "description": string; + "items": { + "type": string; + "description": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "os_user_UserList": { + "type": string; + "description": string; + "properties": { + "apiVersion": { + "type": string; + "description": string; + "default": string; + "required": boolean; + "enum": string[]; + }; + "items": { + "type": string; + "description": string; + "items": { + "$ref": string; + "javaType": string; + }; + }; + "kind": { + "type": string; + "description": string; + "default": string; + "required": boolean; + }; + "metadata": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + "javaType": string; + "javaInterfaces": string[]; + }; + "speter_inf_Dec": { + "type": string; + "description": string; + "additionalProperties": boolean; + "javaType": string; + }; + }; + "type": string; + "properties": { + "BaseKubernetesList": { + "$ref": string; + "javaType": string; + }; + "BuildConfigList": { + "$ref": string; + "javaType": string; + }; + "BuildList": { + "$ref": string; + "javaType": string; + }; + "BuildRequest": { + "$ref": string; + "javaType": string; + }; + "ClusterPolicy": { + "$ref": string; + "javaType": string; + }; + "ClusterPolicyBinding": { + "$ref": string; + "javaType": string; + }; + "ClusterPolicyBindingList": { + "$ref": string; + "javaType": string; + }; + "ClusterPolicyList": { + "$ref": string; + "javaType": string; + }; + "ClusterRoleBinding": { + "$ref": string; + "javaType": string; + }; + "ClusterRoleBindingList": { + "$ref": string; + "javaType": string; + }; + "Config": { + "$ref": string; + "javaType": string; + }; + "ContainerStatus": { + "$ref": string; + "javaType": string; + }; + "DeploymentConfigList": { + "$ref": string; + "javaType": string; + }; + "Endpoints": { + "$ref": string; + "javaType": string; + }; + "EndpointsList": { + "$ref": string; + "javaType": string; + }; + "EnvVar": { + "$ref": string; + "javaType": string; + }; + "EventList": { + "$ref": string; + "javaType": string; + }; + "Group": { + "$ref": string; + "javaType": string; + }; + "GroupList": { + "$ref": string; + "javaType": string; + }; + "Identity": { + "$ref": string; + "javaType": string; + }; + "IdentityList": { + "$ref": string; + "javaType": string; + }; + "ImageList": { + "$ref": string; + "javaType": string; + }; + "ImageStreamList": { + "$ref": string; + "javaType": string; + }; + "LocalSubjectAccessReview": { + "$ref": string; + "javaType": string; + }; + "Namespace": { + "$ref": string; + "javaType": string; + }; + "NamespaceList": { + "$ref": string; + "javaType": string; + }; + "Node": { + "$ref": string; + "javaType": string; + }; + "NodeList": { + "$ref": string; + "javaType": string; + }; + "OAuthAccessToken": { + "$ref": string; + "javaType": string; + }; + "OAuthAccessTokenList": { + "$ref": string; + "javaType": string; + }; + "OAuthAuthorizeToken": { + "$ref": string; + "javaType": string; + }; + "OAuthAuthorizeTokenList": { + "$ref": string; + "javaType": string; + }; + "OAuthClient": { + "$ref": string; + "javaType": string; + }; + "OAuthClientAuthorization": { + "$ref": string; + "javaType": string; + }; + "OAuthClientAuthorizationList": { + "$ref": string; + "javaType": string; + }; + "OAuthClientList": { + "$ref": string; + "javaType": string; + }; + "ObjectMeta": { + "$ref": string; + "javaType": string; + }; + "PersistentVolume": { + "$ref": string; + "javaType": string; + }; + "PersistentVolumeClaim": { + "$ref": string; + "javaType": string; + }; + "PersistentVolumeClaimList": { + "$ref": string; + "javaType": string; + }; + "PersistentVolumeList": { + "$ref": string; + "javaType": string; + }; + "PodList": { + "$ref": string; + "javaType": string; + }; + "Policy": { + "$ref": string; + "javaType": string; + }; + "PolicyBinding": { + "$ref": string; + "javaType": string; + }; + "PolicyBindingList": { + "$ref": string; + "javaType": string; + }; + "PolicyList": { + "$ref": string; + "javaType": string; + }; + "Project": { + "$ref": string; + "javaType": string; + }; + "ProjectList": { + "$ref": string; + "javaType": string; + }; + "ProjectRequest": { + "$ref": string; + "javaType": string; + }; + "Quantity": { + "$ref": string; + "javaType": string; + }; + "ReplicationControllerList": { + "$ref": string; + "javaType": string; + }; + "ResourceQuota": { + "$ref": string; + "javaType": string; + }; + "ResourceQuotaList": { + "$ref": string; + "javaType": string; + }; + "Role": { + "$ref": string; + "javaType": string; + }; + "RoleBinding": { + "$ref": string; + "javaType": string; + }; + "RoleBindingList": { + "$ref": string; + "javaType": string; + }; + "RoleList": { + "$ref": string; + "javaType": string; + }; + "RootPaths": { + "$ref": string; + "javaType": string; + }; + "RouteList": { + "$ref": string; + "javaType": string; + }; + "Secret": { + "$ref": string; + "javaType": string; + }; + "SecretList": { + "$ref": string; + "javaType": string; + }; + "SecurityContextConstraints": { + "$ref": string; + "javaType": string; + }; + "SecurityContextConstraintsList": { + "$ref": string; + "javaType": string; + }; + "ServiceAccount": { + "$ref": string; + "javaType": string; + }; + "ServiceAccountList": { + "$ref": string; + "javaType": string; + }; + "ServiceList": { + "$ref": string; + "javaType": string; + }; + "Status": { + "$ref": string; + "javaType": string; + }; + "SubjectAccessReview": { + "$ref": string; + "javaType": string; + }; + "SubjectAccessReviewResponse": { + "$ref": string; + "javaType": string; + }; + "TagEvent": { + "$ref": string; + "javaType": string; + }; + "Template": { + "$ref": string; + "javaType": string; + }; + "TemplateList": { + "$ref": string; + "javaType": string; + }; + "User": { + "$ref": string; + "javaType": string; + }; + "UserList": { + "$ref": string; + "javaType": string; + }; + "WatchEvent": { + "$ref": string; + "javaType": string; + }; + }; + "additionalProperties": boolean; + }; +} diff --git a/d.ts/kubernetes/ts/schemaHelpers.d.ts b/d.ts/kubernetes/ts/schemaHelpers.d.ts new file mode 100644 index 0000000..c7e3001 --- /dev/null +++ b/d.ts/kubernetes/ts/schemaHelpers.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + function schemaSetRequired(schema: any, propertyName: any, isRequired?: boolean): void; +} diff --git a/d.ts/kubernetes/ts/secret.d.ts b/d.ts/kubernetes/ts/secret.d.ts new file mode 100644 index 0000000..6751b02 --- /dev/null +++ b/d.ts/kubernetes/ts/secret.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var SecretController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/secrets.d.ts b/d.ts/kubernetes/ts/secrets.d.ts new file mode 100644 index 0000000..5b6b92d --- /dev/null +++ b/d.ts/kubernetes/ts/secrets.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +/// +declare module Kubernetes { + var SecretsController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/service.d.ts b/d.ts/kubernetes/ts/service.d.ts new file mode 100644 index 0000000..bd79902 --- /dev/null +++ b/d.ts/kubernetes/ts/service.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var ServiceController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/serviceEdit.d.ts b/d.ts/kubernetes/ts/serviceEdit.d.ts new file mode 100644 index 0000000..1714398 --- /dev/null +++ b/d.ts/kubernetes/ts/serviceEdit.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// +declare module Kubernetes { + var ServiceEditController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/serviceRegistry.d.ts b/d.ts/kubernetes/ts/serviceRegistry.d.ts new file mode 100644 index 0000000..8eb323e --- /dev/null +++ b/d.ts/kubernetes/ts/serviceRegistry.d.ts @@ -0,0 +1,39 @@ +/// +/// +/// +/// +declare module Kubernetes { + /** + * Represents a simple interface to service discovery that can be used early on in the application lifecycle before the + * underlying model has been created via dependency injection + */ + class ServiceRegistryService { + private model; + /** + * Returns true if there is a service available for the given ID or false + */ + hasService(serviceName: string): boolean; + /** + * Returns the service for the given service name (ID) or null if it cannot be found + * + * @param serviceName the name of the service to look for + * @return {null} + */ + findService(serviceName: string): any; + /** + * Returns the service link for the given service name + * + * @param serviceName the name of the service + * @return {null} + */ + serviceLink(serviceName: string): string; + /** + * Returns the service link for the given service name if its ready (has at least one ready pod) + * + * @param serviceName the name of the service + * @return {null} + */ + serviceReadyLink(serviceName: string): string; + private getModel(); + } +} diff --git a/d.ts/kubernetes/ts/services.d.ts b/d.ts/kubernetes/ts/services.d.ts new file mode 100644 index 0000000..6bd28fa --- /dev/null +++ b/d.ts/kubernetes/ts/services.d.ts @@ -0,0 +1,7 @@ +/// +/// +/// +declare module Kubernetes { + var ServiceApps: ng.IModule; + var Services: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/sharedControllers.d.ts b/d.ts/kubernetes/ts/sharedControllers.d.ts new file mode 100644 index 0000000..fa51b1e --- /dev/null +++ b/d.ts/kubernetes/ts/sharedControllers.d.ts @@ -0,0 +1,8 @@ +/// +/// +/// +declare module Kubernetes { + var PodStatus: ng.IModule; + var Labels: ng.IModule; + var Status: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/tabs.d.ts b/d.ts/kubernetes/ts/tabs.d.ts new file mode 100644 index 0000000..c1db8db --- /dev/null +++ b/d.ts/kubernetes/ts/tabs.d.ts @@ -0,0 +1,5 @@ +/// +/// +/// +declare module Kubernetes { +} diff --git a/d.ts/kubernetes/ts/templates.d.ts b/d.ts/kubernetes/ts/templates.d.ts new file mode 100644 index 0000000..34fc069 --- /dev/null +++ b/d.ts/kubernetes/ts/templates.d.ts @@ -0,0 +1,4 @@ +/// +declare module Kubernetes { + var TemplateController: ng.IModule; +} diff --git a/d.ts/kubernetes/ts/term.d.ts b/d.ts/kubernetes/ts/term.d.ts new file mode 100644 index 0000000..aac814d --- /dev/null +++ b/d.ts/kubernetes/ts/term.d.ts @@ -0,0 +1,5 @@ +/// +/// +declare module Kubernetes { + function addWindowActions(scope: any, element: any, TerminalService: any): void; +} diff --git a/d.ts/kubernetes/ts/utilHelpers.d.ts b/d.ts/kubernetes/ts/utilHelpers.d.ts new file mode 100644 index 0000000..2c2483f --- /dev/null +++ b/d.ts/kubernetes/ts/utilHelpers.d.ts @@ -0,0 +1,56 @@ +/// +declare module Kubernetes { + var hostPorts: any[]; + /** + * Sorts the the ip field + * + * @param ip the ip such as '10.1.2.13' + * @returns {any} + */ + function sortByPodIp(ip: any): any; + function ramdomPort(): number; + function getRandomString(len: number): string; + class resourceRCTemplate { + image: string; + names: string[]; + createRC(Obj: any): { + "apiVersion": string; + "kind": string; + "metadata": { + "name": any; + "labels": { + "style": string; + "status": string; + }; + }; + "spec": { + replicas: any; + "template": { + "metadata": { + "labels": any; + }; + "spec": { + "terminationGracePeriodSeconds": number; + "containers": any[]; + "volumes": any[]; + }; + }; + }; + }; + createVolumeMounts(): any[]; + createVolumes(rootPath: string): any[]; + createContainers(Obj: any): any[]; + createTemplate(Obj: any): { + "metadata": { + "labels": any; + }; + "spec": { + "terminationGracePeriodSeconds": number; + "containers": any[]; + "volumes": any[]; + }; + }; + } + function findLabelValue(value: string, key: string): string; + function labelToChinese(labels: any): {}; +} diff --git a/d.ts/kubernetes/ts/watcher.d.ts b/d.ts/kubernetes/ts/watcher.d.ts new file mode 100644 index 0000000..bab5421 --- /dev/null +++ b/d.ts/kubernetes/ts/watcher.d.ts @@ -0,0 +1,3 @@ +/// +declare module Kubernetes { +} diff --git a/d.ts/navigation/ts/navigationPlugin.d.ts b/d.ts/navigation/ts/navigationPlugin.d.ts new file mode 100644 index 0000000..ac0bced --- /dev/null +++ b/d.ts/navigation/ts/navigationPlugin.d.ts @@ -0,0 +1,6 @@ +/// +declare module Navigation { + var pluginName: string; + var log: Logging.Logger; + var _module: ng.IModule; +} diff --git a/d.ts/service/ts/serviceHelpers.d.ts b/d.ts/service/ts/serviceHelpers.d.ts new file mode 100644 index 0000000..3a0ec01 --- /dev/null +++ b/d.ts/service/ts/serviceHelpers.d.ts @@ -0,0 +1,30 @@ +/// +declare module Service { + var pluginName: string; + var log: Logging.Logger; + /** + * Used to specify whether the "service" URL should be polled for services using kubernetes or kubernetes-like service discover. + * For more details see: https://github.com/hawtio/hawtio/blob/master/docs/Services.md + */ + var pollServices: boolean; + /** + * Returns true if there is a service available for the given ID or false + */ + function hasService(ServiceRegistry: any, serviceName: string): boolean; + /** + * Returns the service for the given service name (ID) or null if it cannot be found + * + * @param ServiceRegistry + * @param serviceName + * @return {null} + */ + function findService(ServiceRegistry: any, serviceName: string): any; + /** + * Returns the service link for the given service name + * + * @param ServiceRegistry + * @param serviceName + * @return {null} + */ + function serviceLink(ServiceRegistry: any, serviceName: string): string; +} diff --git a/d.ts/service/ts/servicePlugin.d.ts b/d.ts/service/ts/servicePlugin.d.ts new file mode 100644 index 0000000..8e63849 --- /dev/null +++ b/d.ts/service/ts/servicePlugin.d.ts @@ -0,0 +1,19 @@ +/// +/// +declare module Service { + interface SelectorMap { + [name: string]: string; + } + interface Service { + kind: string; + id: string; + portalIP: string; + selector?: SelectorMap; + port: number; + containerPort: number; + } + interface ServiceResponse { + items: Array; + } + var _module: ng.IModule; +} diff --git a/defs.d.ts b/defs.d.ts new file mode 100644 index 0000000..361d143 --- /dev/null +++ b/defs.d.ts @@ -0,0 +1,71 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// diff --git a/dist/hawtio-console-assembly.css b/dist/hawtio-console-assembly.css new file mode 100644 index 0000000..cd5e0d5 --- /dev/null +++ b/dist/hawtio-console-assembly.css @@ -0,0 +1,108 @@ +/* console specific stuff here */ +body { + padding-top: 110px; +} +.pane { + top: 110px; +} +.navbar-brand > img { + height: 20px; + margin-top: -5px; + margin-bottom: -5px; +} + +.navbar-persistent { + background: #f6f6f6; + border-bottom: 1px solid #cecdcd; + padding: 0; + width: 100%; +} +.navbar-persistent > li.active:before, +.navbar-persistent > li.active:hover:before { + background: #0099d3; + bottom: -1px; + content: ''; + display: block; + height: 2px; + left: 20px; + position: absolute; + right: 20px; +} +.navbar-persistent > li.active > a, +.navbar-persistent > li.active > a:hover, +.navbar-persistent > li.active:hover > a { + background: transparent !important; + color: #0099d3 !important; +} +.navbar-persistent > li.active .active > a { + color: #f1f1f1; +} +.navbar-persistent > li.dropdown-submenu:hover > .dropdown-menu { + display: none; +} +.navbar-persistent > li.dropdown-submenu.open > .dropdown-menu { + display: block; + left: 20px; + margin-top: 1px; + top: 100%; +} +.navbar-persistent > li.dropdown-submenu.open > .dropdown-toggle { + color: #222222; +} +.navbar-persistent > li.dropdown-submenu.open > .dropdown-toggle:after { + border-top-color: #222222; +} +.navbar-persistent > li.dropdown-submenu > .dropdown-toggle { + padding-right: 35px !important; +} +.navbar-persistent > li.dropdown-submenu > .dropdown-toggle:after { + position: absolute; + right: 20px; + top: 10px; +} +.navbar-persistent > li:hover:before, +.navbar-persistent > li.open:before { + background: #aaaaaa; + bottom: -1px; + content: ''; + display: block; + height: 2px; + left: 20px; + position: absolute; + right: 20px; +} +.navbar-persistent > li:hover > a, +.navbar-persistent > li.open > a { + color: #222222; +} +.navbar-persistent > li:hover > a:after, +.navbar-persistent > li.open > a:after { + border-top-color: #222222; +} +.navbar-persistent > li > a { + background-color: transparent; + display: block; + line-height: 1; + padding: 9px 20px !important; +} +.navbar-persistent > li > a.dropdown-toggle { + padding-right: 35px; +} +.navbar-persistent > li > a.dropdown-toggle:after { + font-size: 15px; + position: absolute; + right: 20px; + top: 9px; +} +.navbar-persistent > li > a:hover { + color: #222222 !important; +} +.navbar-persistent > li a { + color: #4d5258 !important; +} +.navbar-pf .navbar-primary > li > a { + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; + position: relative; + margin: -1px 0 0; +} diff --git a/dist/hawtio-kubernetes.css b/dist/hawtio-kubernetes.css new file mode 100644 index 0000000..fca41fb --- /dev/null +++ b/dist/hawtio-kubernetes.css @@ -0,0 +1,1025 @@ +.nowrap { + white-space: nowrap; +} +.ngCellText .app-icon-small { + width: 24px; + vertical-align: middle; +} +.filter-header { + padding-bottom: 10px; +} +.app-name { + padding-left: 10px; +} +.profile-selector-name .app-name { + padding-left: 4px; +} +img.icon-small-app { + width: 24px; + height: 24px; + vertical-align: text-bottom; +} +.profile-selector-name { + line-height: 24px; +} +img.icon-selected-app { + width: 64px; + height: 64px; + vertical-align: middle; +} +.selected-app-name { + line-height: 36px; + padding-left: 5px; +} +.controller-pod-counts { + padding-right: 16px; + padding-top: 8px; +} +.pipeline-build-block { + background-color: #eeeeee; + display: inline-block; + width: 100%; +} +.pipeline-build { + background: white; + -moz-border-radius: 10px; + border-radius: 10px; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + margin-top: 10px; + margin-bottom: 10px; + margin-left: 20px; + margin-right: 20px; +} +.pipeline-deploy { + background: white; + border: 5px solid; + -moz-border-radius: 10px; + border-radius: 10px; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + margin-top: 10px; + margin-bottom: 10px; + margin-left: 20px; + margin-right: 20px; + color: black; +} +.widget-body > .pipeline-panel, +.widget-body > .pipeline-panel > *, +.widget-body > .pipeline-panel > * > *, +.widget-body > .pipeline-panel > * > * > *, +.widget-body > .pipeline-panel > * > * > * > * { + height: 100%; + vertical-align: middle; +} +.pipeline-block { + width: 100%; +} +.build-fail { + border-color: lightcoral; +} +.build-success { + border-color: lightgreen; +} +.build-pending { + border-color: khaki; +} +.build-aborted { + border-color: silver; +} +.build-not-started { + border-color: lightblue; +} +.pipeline-build a { + color: black; +} +.pipeline-deploy a { + color: black; +} +.pipeline-pod-counts { + padding-right: 16px; + padding-top: 8px; +} +.pipeline-row { + background: lightgrey; + height: 80px; + display: inline; + border-radius: 4px; + text-align: center; + vertical-align: middle; + border: 20px; + margin: 5px; +} +.pipeline-arrow { + font-size: 1.2em; +} +.icon-heading { + font-size: 24px; +} +.row-header { + padding-bottom: 20px; +} +.project-overview-title { + padding-left: 80px; + padding-top: 18px; +} +.project-overview-title a { + color: black; +} +/* + +.raw-json-view { + width: 90%; height: 700px; +} +*/ +.raw-json-view .CodeMirror { + height: 90%; +} +.k8sServiceApp-menu { + width: 260px; +} +.k8sServiceApp > a { + padding-top: 5px !important; + padding-bottom: 5px !important; + line-height: 32px !important; +} +.k8sServiceApp > a > img { + vertical-align: bottom; +} +.k8sServiceApp > a > span { + font-size: 14px; + line-height: 32px; +} +.breadcrumb-tabs { + padding-top: 5px; +} +tbody .ngCellText i { + margin-right: 5px; +} +.log-success { + color: green; +} +.log-warn { + color: orange; +} +.log-error { + color: red; +} +.form-warning.bg-danger { + padding: 8px; +} +legend { + border-bottom: none; +} +/* TODO lets work around some ui-bootstrap / patternfly css gremlins */ +.modal .modal-dialog { + margin-top: 0px; + margin-bottom: 0px; +} +/* lets set this to the same size as modal-dialog */ +.modal { + width: 600px; +} +.btn.btn-padding { + margin-left: 5px; + margin-right: 5px; +} +.k8s-badge-batch { + background-color: darkblue; +} +.k8s-badge-type { + background-color: darkgreen; +} +.k8s-badge-region { + background-color: darkred; +} +.k8s-badge-system { + background-color: darkmagenta; +} + +.environment-row a { + color: black; +} +.environment-row .panel { + min-width: 255px; + min-height: 160px; +} +.environment-row .panel-group { + margin-left: 10px; + margin-right: 10px; +} +.environment-row .panel-title > a:before { + display: none; +} +.environment-rows { + /* + background-color: rgb(238, 238, 238); + */ + padding-top: 5px; + vertical-align: top; +} +.environment-name-block { + width: 200px; +} +.environment-name-block, +.environment-deploy-block { + background: white; + -moz-border-radius: 10px; + border-radius: 10px; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + margin-top: 10px; + margin-bottom: 10px; + margin-left: 20px; + margin-right: 20px; +} +.environment-name-block { + padding-top: 0px; +} +.environment-block { + vertical-align: top; +} +.environment-deploy-block { + border: 1px dashed; + border-color: silver; +} +.environment-deploy-version-and-pods { + padding-bottom: 5px; +} + +.project-dashboard .page-header-row { + background: white; + margin-left: -20px; + margin-right: -20px; + margin-top: -20px; + border-bottom: 1px solid #d1d1d1; + margin-bottom: 13px; + padding-bottom: 7px; +} +.project-dashboard .card-pf-title { + margin-right: 1em; +} +.project-dashboard .no-border { + border: none; + margin-bottom: 0; +} +.project-dashboard .no-top-margin { + margin-top: 0; +} +.project-dashboard .full-card-width { + margin-left: -20px; + margin-right: -20px; +} +.project-dashboard .card-pf.pipeline .panel-group { + border-width: 0; +} +.project-dashboard .card-pf.pipeline .panel-group .panel { + box-shadow: none; +} +.project-dashboard .card-pf.pipeline .panel-group .panel.panel-default { + border-width: 0; + border-top-width: 1px; +} +.project-dashboard .card-pf.pipeline .panel-group .panel.panel-default .log-panel { + border: 1px solid #d4d4d4; +} + +.filter-header .btn, +.filter-header form { + margin-top: 1.05em; + margin-bottom: 1em; +} + +.log-window { + border-top: 1px solid #d4d4d4; + overflow: auto; +} +.log-window-inner * { + font-family: "DroidSansMonoRegular", monospace; + line-height: 13px; +} +.log-panel { + position: static; + height: 100%; + width: 100%; + overflow: auto; + border: none; + padding: 3px; +} +.log-panel-inner * { + font-family: "DroidSansMonoRegular", monospace; + line-height: 13px; +} + +.project-selector { + margin-top: 10px; + margin-bottom: 10px; + list-style-type: none; +} +.project-selector a, +.project-selector a:hover { + color: #fff; + text-decoration: none; + font-size: 13px; + line-height: 21px; +} + +/* 样式重置 */ +body, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +p, +blockquote, +dl, +dt, +dd, +ul, +ol, +li, +pre, +form, +fieldset, +legend, +button, +input, +textarea, +th, +td { + margin: 0; + padding: 0; +} +body, +table, +input, +textarea, +select, +button { + font-family: "微软雅黑", "宋体"; + font-size: 12px; + line-height: 1.5; + background: #fff; +} +div, +img, +tr, +td, +table { + border: 0; +} +table, +tr, +td { + border: 0; + cellspacing: 0; + cellpadding: 0; +} +ol, +ul, +li { + list-style-type: none; +} +a:link, +a:visited { + color: #7f7f7f; + text-decoration: none; +} +a:hover, +a:active { + color: #000; +} +.fl { + float: left; +} +.fr { + float: right; +} +.cl { + clear: both; + overflow: hidden; +} +/* 数据页面 */ +.data_container { + width: 100%; + margin: 0 auto; +} +.data_heaer { + height: 66px; + width: 100%; + background-color: #3499db; + text-align: center; +} +.data_heaer h2 { + font-size: 30px; + font-weight: 300; + color: #fff; + line-height: 66px; +} +.data_content { + width: 1280px; + height: 838px; + margin: 0 auto; + background-color: #fff; + border: 1px solid #e0dede; + border-top: none; +} +.data_leftside { + width: 611px; + border-right: 1px solid #e0dede; +} +.data_h3 { + width: 100%; + text-align: center; + height: 50px; + font-size: 18px; + color: #444; + line-height: 50px; +} +.data_leftside_files { + border-right: 1px solid #e0dede; + border-bottom: 1px solid #e0dede; + height: 710px; + overflow: auto; +} +.data_leftside_files input { + margin-top: 15px; + width: 15px; + height: 15px; +} +.data_leftside_files li { + height: 40px; + line-height: 40px; + border-bottom: 1px solid #e0dede; + padding: 0 10px; +} +.data_leftside_files li.data_title { + width: 210px; + height: 36px; + line-height: 36px; + text-align: center; + background-color: #e9f3fb; + border: none; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + white-space: nowrap; +} +.date_label { + display: block; + width: 168px; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + white-space: nowrap; +} +.data_leftside_shu { + border-right: none; +} +.data_leftside_shu li { + border-bottom: none; +} +.data_conbar { + width: 149px; + height: 834px; + border-right: 1px solid #e0dede; + border-left: 1px solid #e0dede; +} +.date_btns { + width: 260px; + margin: 20px auto; +} +.date_btns_w { + width: 390px; +} +.date_btns button { + margin: 10px 20px; +} +.data_btn { + border: none; + width: 108px; + height: 35px; + line-height: 35px; + text-align: center; + background-color: #3499db; + color: #fff; + font-size: 14px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} +.data_btn:hover { + background-color: #2989da; +} +.data_rightside { + width: 667px; +} +.data_rightside_w { + width: 407px; +} +.data_leftside_files li.data_title_w { + width: 184px; +} +.date_label_w { + width: 150px; +} +.data_leftside_shu li { + border-bottom: none; +} +a.data_file_btn { + display: block; + position: relative; + width: 108px; + height: 35px; + margin: 15px auto; + line-height: 35px; + font-size: 14px; + color: #fff; + text-align: center; + background-color: #79b4e7; + background-image: -webkit-linear-gradient(#79b4e7, #1377cf); + background-image: linear-gradient(#79b4e7, #1377cf); + border-color: #076bc2; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + vertical-align: middle; + cursor: pointer; + margin: 0 10px; +} +a:hover.data_file_btn { + background-color: #076bc2; + background-image: -webkit-linear-gradient(#79b4e7, #076bc2); + background-image: linear-gradient(#79b4e7, #076bc2); + border-color: #076bc2; +} +.data_file_btn input { + position: absolute; + left: 0px; + opacity: 0; + filter: alpha(opacity=0); + width: 108px; + height: 35px; +} +.data_conbox { + width: 407px; + height: 709px; + border-top: 1px solid #e0dede; + border-bottom: 1px solid #e0dede; + overflow: auto; +} +.data_con_title { + width: 49.8%; + height: 36px; + line-height: 36px; + text-align: center; + background-color: #e9f3fb; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + white-space: nowrap; +} +.data_con_line { + border-right: 1px solid #e0dede; +} +.data_con_li { + width: 49.8%; + height: 36px; + line-height: 36px; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + white-space: nowrap; + border-bottom: 1px solid #e0dede; +} +.mt15 { + margin-top: 15px; +} +#file-uploads { + opacity: 0; + position: absolute; + z-index: 10; + width: 118px; + height: 35px; +} +/* 树形结构 */ +.data_rightside_tree { + width: 259px; + height: 709px; + border-right: 1px solid #e0dede; + border-top: 1px solid #e0dede; + border-bottom: 1px solid #e0dede; + overflow: auto; +} +.tree { + min-height: 20px; + padding: 15px; + padding-left: 30px; + border-bottom: 1px dashed #ccc; +} +.tree li { + list-style-type: none; + margin: 0; + padding: 10px 5px 0 20px; + position: relative; +} +.tree li::before, +.tree li::after { + content: ''; + left: -30px; + position: absolute; + right: auto; +} +.tree li::before { + border-left: 1px solid #999; + bottom: 50px; + height: 100%; + top: 0; + width: 0px; +} +.tree li::after { + border-top: 1px solid #999; + height: 20px; + top: 25px; + width: 35px; +} +.tree li p { + display: inline-block; + padding: 3px 10px; + border: 1px solid #fff; + margin-left: -15px; + width: 150px; +} +.tree li.parent_li > p { + cursor: pointer; +} +.tree > ul > li::before, +.tree > ul > li::after { + border: 0; +} +.tree li:last-child::before { + height: 30px; +} +.icon-plus-sign { + margin-left: -15px; + background: url(../img/icons1.gif) -5px 10px no-repeat; +} +.icon-minus-sign { + margin-left: -15px; + background: url(../img/icons2.gif) -6px 9px no-repeat; +} + +/* This is for the 'Overview' page with all the rows of boxes */ +.service-view-rectangle { + position: relative; + margin-left: 0; + margin-right: 0px; + margin-bottom: 15px; + margin-top: 0; + background-color: #fafafa; + border-width: 1px; + border-style: solid; + border-color: #eeeeee; +} +.service-view-rectangle .service-view-header { + margin-top: 5px; + margin-bottom: 5px; + line-height: 20px; + vertical-align: middle; +} +.service-view-rectangle .service-view-detail-pod-box { + background-color: #eeeeee; + display: inline-block; + font-size: smaller; +} +.service-view-rectangle .service-view-header-delete .red { + opacity: 0.5; + transition: opacity 1s; + font-size: larger; +} +.service-view-rectangle .service-view-header-delete:hover .red { + opacity: 1; +} +.service-view-rectangle .service-view-icon img { + width: 32px; + height: 32px; + margin-right: 6px; +} +.service-view-rectangle .service-view-name { + font-size: larger; + font-weight: bold; +} +.service-view-rectangle .service-view-detail-header { + padding-top: 5px; + padding-bottom: 5px; + line-height: 20px; +} +.service-view-rectangle .service-view-detail-rectangle { + background-color: #eeeeee; + padding-left: 10px; + padding-right: 10px; +} +.service-view-rectangle .service-view-detail-rectangle .value { + font-weight: bold; +} +.service-view-rectangle .service-view-detail-pod-summary, +.service-view-rectangle .service-view-detail-pod-summary-expand { + display: inline-block; + padding-top: 2px; + padding-bottom: 2px; + padding-left: 20px; + padding-right: 20px; + margin-right: 8px; + margin-bottom: 8px; + background-color: #ffffff; +} +.service-view-rectangle .service-view-detail-pod-summary table td, +.service-view-rectangle .service-view-detail-pod-summary-expand table td { + padding-left: 10px; + padding-right: 10px; +} +.service-view-rectangle .service-view-detail-pod-status, +.service-view-rectangle .service-view-detail-pod-connect { + line-height: 36px; + padding-right: 20px; +} +.service-view-rectangle .service-view-detail-pod-status i, +.service-view-rectangle .service-view-detail-pod-connect i { + font-size: 36px; + display: inline-block; + vertical-align: middle; +} +.service-view-rectangle .service-view-detail-pod-expand { + color: #a0a0a0; + font-size: 18px; + padding-right: 0px; +} +.kubernetes-view .filter-header { + margin-bottom: 1em; +} + +/* This is all for the diagram, not the 'Overview' page */ +.kubernetes-overview { + width: 100%; + height: 100%; + display: table; + table-layout: fixed; +} +.kubernetes-overview-row { + display: table-row; +} +.kubernetes-overview-cell { + display: table-cell; + text-align: center; + vertical-align: middle; + padding: 0; +} +.service-wrapper { + display: block; + vertical-align: middle; +} +.kubernetes-node { + margin-left: auto; + margin-right: auto; + cursor: pointer; + text-align: center; + vertical-align: middle; + border: 1px solid #d4d4d4; + background: white; + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + border-radius: 4px; + transition: background 0.5s; + z-index: 1000; +} +.kubernetes-host-container { + margin-top: 5px; + margin-bottom: 5px; + margin-left: auto; + margin-right: auto; + text-align: center; + max-width: 600px; + min-width: 300px; + padding: 0; + border: 1px solid #d4d4d4; + background: white; + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + border-radius: 4px; +} +.kubernetes-pod-node { + display: block; + margin: 0; + padding: 0; + min-height: 48px; + line-height: 48px; + border-radius: 0; + border: 1px solid transparent; + border-top: 1px solid #d4d4d4; + box-shadow: none; + vertical-align: middle; +} +.css-table { + display: table; + width: 100%; + height: 100%; +} +.css-table-row { + display: table-row; +} +.css-table-row .pod-status-cell { + text-align: left; + padding-left: 5px; + padding-right: 5px; +} +.css-table-row .pod-status-cell i { + margin-left: 3px; + margin-right: 3px; +} +.css-table-row .pod-status-cell .clickable { + width: auto !important; +} +.css-table-cell { + display: table-cell; + vertical-align: middle; +} +.kubernetes-pod-node i { + font-size: 24px; +} +.kubernetes-overview-services { + width: 200px; +} +.kubernetes-service-node { + display: block; + margin-bottom: 10px; + width: 200px; + min-height: 66px; + padding: 0; + line-height: 48px; +} +.kubernetes-service-node .node-body { + display: inline; + padding-left: 10px; + line-height: 64px; + font-size: 20px; + float: left; +} +.kubernetes-service-node .node-header { + display: inline; + float: right; +} +.node-header { + padding-right: 10px; + white-space: nowrap; + line-height: 64px; + overflow: hidden; + text-overflow: ellipsis; +} +.kubernetes-replicationController-node { + border-radius: 64px; + display: block; + width: 64px; + height: 64px; + padding: 7px; + font-weight: bold; + vertical-align: middle; + overflow: hidden; + text-overflow: ellipsis; +} +.kubernetes-overview-cell .app-icon-medium { + width: 48px; + height: 48px; +} +.kubernetes-replicationController-node img { + width: 64px; +} +.kubernetes-node:hover, +.kubernetes-node.hovered { + background: #ddddff; +} +.pod-status-cell { + width: 80px; + line-height: 20px; +} +.pod-label-cell { + float: right; + text-align: right; + min-height: 48px; +} +.pod-label-cell .ngCellText { + white-space: normal; +} + +.pod-log-lines * { + padding-left: 5px; + padding-right: 5px; + font-family: monospace; + margin: 0; + line-height: 14px; +} +.pod-log-lines * .black { + color: #222; +} +.pod-log-lines * .red { + color: #f22; +} +.pod-log-lines * .green { + color: #2f2; +} +.pod-log-lines * .yellow { + color: #ff2; +} +.pod-log-lines * .blue { + color: #22f; +} +.pod-log-lines * .purple { + color: #f2f; +} +.pod-log-lines * .cyan { + color: #2dd; +} +.pod-log-lines * .white { + color: #ddd; +} + +.terminal-window { + position: fixed; + bottom: 0; + background: white; + border: 1px solid #d4d4d4; + overflow: hidden; + z-index: 1040; +} +.terminal-window .resize-dot { + width: 16px; + height: 16px; + border: 1px solid #d4d4d4; + background: white; + position: absolute; + bottom: 10px; + right: 10px; + cursor: nwse-resize; + border-radius: 8px; + z-index: 10000; +} +.terminal-window.minimized .resize-dot, +.terminal-window.maximized .resize-dot { + display: none; +} +.terminal-window.minimized .terminal-title, +.terminal-window.maximized .terminal-title { + cursor: inherit; +} +.terminal-window .terminal-body { + overflow: auto; +} +.terminal-window .terminal-body .terminal-wrapper > .terminal * { + font-family: 'DroidSansMonoRegular'; +} +.terminal-window .terminal-title { + cursor: move; + border-bottom: 1px solid #d4d4d4; +} +.terminal-window .terminal-title > h5 { + display: inline-block; + margin-left: 5px; +} +.terminal-window .terminal-title > i { + font-size: 16px; + margin-right: 5px; + margin-top: 7px; +} +kubernetes-container-terminal .terminal-wrapper { + display: block !important; +} +kubernetes-container-terminal .terminal-actions { + position: absolute !important; +} +.pod-log-window .scroll-indicator { + position: absolute; + bottom: 0; + line-height: 32px; + left: 20px; + right: 20px; + background-color: #ffffff; + border-top: 1px solid #d4d4d4; + border-left: 1px solid #d4d4d4; + border-right: 1px solid #d4d4d4; + border-radius: 4px 4px 0 0; + cursor: pointer; + z-index: 10000; + opacity: 0.7; +} +.pod-log-window .terminal-body { + overflow-y: auto; + overflow-x: hidden; +} diff --git a/dist/hawtio-kubernetes.js b/dist/hawtio-kubernetes.js new file mode 100644 index 0000000..6d57cc2 --- /dev/null +++ b/dist/hawtio-kubernetes.js @@ -0,0 +1,17918 @@ +/// +/// +/// +/// +/// + +var Kubernetes; +(function (Kubernetes) { + var consts = (function () { + function consts() { + } + Object.defineProperty(consts.prototype, "NAMESPACE_STORAGE_KEY", { + get: function () { return "k8sSelectedNamespace"; }, + enumerable: true, + configurable: true + }); + return consts; + }()); + Kubernetes.consts = consts; + Kubernetes.Constants = new consts(); + var WatchTypes = (function () { + function WatchTypes() { + } + Object.defineProperty(WatchTypes, "ENDPOINTS", { + get: function () { return "endpoints"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "EVENTS", { + get: function () { return "events"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "NAMESPACES", { + get: function () { return "namespaces"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "NODES", { + get: function () { return "nodes"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "PERSISTENT_VOLUMES", { + get: function () { return "persistentvolumes"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "PERSISTENT_VOLUME_CLAIMS", { + get: function () { return "persistentvolumeclaims"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "PODS", { + get: function () { return "pods"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "REPLICATION_CONTROLLERS", { + get: function () { return "replicationcontrollers"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "RESOURCE_QUOTAS", { + get: function () { return "resourcequotas"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "OAUTH_CLIENTS", { + get: function () { return "oauthclients"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "SECRETS", { + get: function () { return "secrets"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "SERVICES", { + get: function () { return "services"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "SERVICE_ACCOUNTS", { + get: function () { return "serviceaccounts"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "TEMPLATES", { + get: function () { return "templates"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "ROUTES", { + get: function () { return "routes"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "BUILD_CONFIGS", { + get: function () { return "buildconfigs"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "BUILDS", { + get: function () { return "builds"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "DEPLOYMENT_CONFIGS", { + get: function () { return "deploymentconfigs"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "IMAGE_STREAMS", { + get: function () { return "imagestreams"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "POLICIES", { + get: function () { return "policies"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "POLICY_BINDINGS", { + get: function () { return "policybindings"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "PROJECTS", { + get: function () { return "projects"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "ROLE_BINDINGS", { + get: function () { return "rolebindings"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchTypes, "ROLES", { + get: function () { return "roles"; }, + enumerable: true, + configurable: true + }); + return WatchTypes; + }()); + Kubernetes.WatchTypes = WatchTypes; + var NamespacedTypes = (function () { + function NamespacedTypes() { + } + Object.defineProperty(NamespacedTypes, "k8sTypes", { + get: function () { + return [ + WatchTypes.ENDPOINTS, + WatchTypes.EVENTS, + WatchTypes.NODES, + WatchTypes.PERSISTENT_VOLUMES, + WatchTypes.PERSISTENT_VOLUME_CLAIMS, + WatchTypes.PODS, + WatchTypes.REPLICATION_CONTROLLERS, + WatchTypes.RESOURCE_QUOTAS, + WatchTypes.PERSISTENT_VOLUMES, + WatchTypes.SECRETS, + WatchTypes.SERVICES, + WatchTypes.SERVICE_ACCOUNTS + ]; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(NamespacedTypes, "osTypes", { + get: function () { + return [ + WatchTypes.TEMPLATES, + WatchTypes.BUILD_CONFIGS, + WatchTypes.ROUTES, + WatchTypes.BUILDS, + WatchTypes.BUILD_CONFIGS, + WatchTypes.DEPLOYMENT_CONFIGS, + WatchTypes.IMAGE_STREAMS, + WatchTypes.OAUTH_CLIENTS, + WatchTypes.POLICIES, + WatchTypes.POLICY_BINDINGS, + WatchTypes.PROJECTS, + ]; + }, + enumerable: true, + configurable: true + }); + return NamespacedTypes; + }()); + Kubernetes.NamespacedTypes = NamespacedTypes; + var WatchActions = (function () { + function WatchActions() { + } + Object.defineProperty(WatchActions, "ANY", { + get: function () { return "*"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchActions, "ADDED", { + get: function () { return "ADDED"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchActions, "MODIFIED", { + get: function () { return "MODIFIED"; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WatchActions, "DELETED", { + get: function () { return "DELETED"; }, + enumerable: true, + configurable: true + }); + return WatchActions; + }()); + Kubernetes.WatchActions = WatchActions; +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.context = '/kubernetes'; + Kubernetes.hash = '#' + Kubernetes.context; + Kubernetes.defaultRoute = Kubernetes.hash + '/apps'; + Kubernetes.pluginName = 'Kubernetes'; + Kubernetes.pluginPath = 'plugins/kubernetes/'; + Kubernetes.templatePath = Kubernetes.pluginPath + 'html/'; + Kubernetes.log = Logger.get(Kubernetes.pluginName); + Kubernetes.keepPollingModel = true; + Kubernetes.defaultIconUrl = Core.url("/img/kubernetes.svg"); + Kubernetes.hostIconUrl = Core.url("/img/host.svg"); + // this gets set as a pre-bootstrap task + Kubernetes.osConfig = undefined; + Kubernetes.masterUrl = ""; + Kubernetes.defaultApiVersion = "v1"; + Kubernetes.defaultOSApiVersion = "v1"; + Kubernetes.labelFilterTextSeparator = ","; + Kubernetes.defaultNamespace = "default"; + Kubernetes.appSuffix = ".app"; + // kubernetes service names + Kubernetes.kibanaServiceName = "kibana"; + Kubernetes.fabric8ForgeServiceName = "fabric8-forge"; + Kubernetes.gogsServiceName = "gogs"; + Kubernetes.jenkinsServiceName = "jenkins"; + Kubernetes.apimanServiceName = 'apiman'; + Kubernetes.isOpenShift = true; + Kubernetes.sshSecretDataKeys = ["ssh-key", "ssh-key.pub"]; + Kubernetes.httpsSecretDataKeys = ["username", "password"]; + function kubernetesNamespacePath() { + var ns = currentKubernetesNamespace(); + if (ns) { + return "/namespaces/" + ns; + } + else { + return ""; + } + } + Kubernetes.kubernetesNamespacePath = kubernetesNamespacePath; + function apiPrefix() { + var prefix = Core.pathGet(Kubernetes.osConfig, ['api', 'k8s', 'prefix']); + if (!prefix) { + prefix = 'api'; + } + return Core.trimLeading(prefix, '/'); + } + Kubernetes.apiPrefix = apiPrefix; + function osApiPrefix() { + var prefix = Core.pathGet(Kubernetes.osConfig, ['api', 'openshift', 'prefix']); + if (!prefix) { + prefix = 'oapi'; + } + var answer = Core.trimLeading(prefix, '/'); + if (!Kubernetes.isOpenShift) { + return UrlHelpers.join(apiPrefix(), Kubernetes.defaultOSApiVersion, "proxy", kubernetesNamespacePath(), "services/templates", answer); + } + return answer; + } + Kubernetes.osApiPrefix = osApiPrefix; + function masterApiUrl() { + return Kubernetes.masterUrl || ""; + } + Kubernetes.masterApiUrl = masterApiUrl; + /** WARNING - this excludes the host name - you probably want to use: kubernetesApiUrl() instead!! */ + function kubernetesApiPrefix() { + return UrlHelpers.join(apiPrefix(), Kubernetes.defaultApiVersion); + } + Kubernetes.kubernetesApiPrefix = kubernetesApiPrefix; + function openshiftApiPrefix() { + return UrlHelpers.join(osApiPrefix(), Kubernetes.defaultOSApiVersion); + } + Kubernetes.openshiftApiPrefix = openshiftApiPrefix; + function prefixForType(type) { + if (type === Kubernetes.WatchTypes.NAMESPACES) { + return kubernetesApiPrefix(); + } + if (_.any(Kubernetes.NamespacedTypes.k8sTypes, function (t) { return t === type; })) { + return kubernetesApiPrefix(); + } + if (_.any(Kubernetes.NamespacedTypes.osTypes, function (t) { return t === type; })) { + return openshiftApiPrefix(); + } + // lets assume its an OpenShift extension type + return openshiftApiPrefix(); + } + Kubernetes.prefixForType = prefixForType; + function kubernetesApiUrl() { + return UrlHelpers.join(masterApiUrl(), kubernetesApiPrefix()); + } + Kubernetes.kubernetesApiUrl = kubernetesApiUrl; + function openshiftApiUrl() { + return UrlHelpers.join(masterApiUrl(), openshiftApiPrefix()); + } + Kubernetes.openshiftApiUrl = openshiftApiUrl; + function resourcesUriForKind(type, ns) { + if (ns === void 0) { ns = null; } + if (!ns) { + ns = currentKubernetesNamespace(); + } + return UrlHelpers.join(masterApiUrl(), prefixForType(type), namespacePathForKind(type, ns)); + } + Kubernetes.resourcesUriForKind = resourcesUriForKind; + function uriTemplateForKubernetesKind(type) { + var urlTemplate = ''; + switch (type) { + case Kubernetes.WatchTypes.NAMESPACES: + case "Namespaces": + urlTemplate = UrlHelpers.join('namespaces'); + break; + case Kubernetes.WatchTypes.OAUTH_CLIENTS: + case "OAuthClients": + case "OAuthClient": + return UrlHelpers.join('oauthclients'); + case Kubernetes.WatchTypes.PROJECTS: + case "Projects": + urlTemplate = UrlHelpers.join('projects'); + break; + default: + urlTemplate = UrlHelpers.join('namespaces/:namespace', type, ':id'); + } + return urlTemplate; + } + Kubernetes.uriTemplateForKubernetesKind = uriTemplateForKubernetesKind; + function namespacePathForKind(type, ns) { + var urlTemplate = ''; + switch (type) { + case Kubernetes.WatchTypes.NAMESPACES: + case "Namespaces": + case "Namespace": + return UrlHelpers.join('namespaces'); + case Kubernetes.WatchTypes.NODES: + case "Nodes": + case "node": + return UrlHelpers.join('nodes'); + case Kubernetes.WatchTypes.PROJECTS: + case "Projects": + case "Project": + return UrlHelpers.join('projects'); + case Kubernetes.WatchTypes.OAUTH_CLIENTS: + case "OAuthClients": + case "OAuthClient": + return UrlHelpers.join('oauthclients'); + case Kubernetes.WatchTypes.PERSISTENT_VOLUMES: + case "PersistentVolumes": + case "PersistentVolume": + return UrlHelpers.join('persistentvolumes'); + default: + return UrlHelpers.join('namespaces', ns, type); + } + } + Kubernetes.namespacePathForKind = namespacePathForKind; + /** + * Returns thevalue from the injector if its available or null + */ + function inject(name) { + var injector = HawtioCore.injector; + return injector ? injector.get(name) : null; + } + Kubernetes.inject = inject; + function createResource(thing, urlTemplate, $resource, KubernetesModel) { + var prefix = prefixForType(thing); + if (!prefix) { + Kubernetes.log.debug("Invalid type given: ", thing); + return null; + } + var params = { + namespace: currentKubernetesNamespace + }; + switch (thing) { + case Kubernetes.WatchTypes.NAMESPACES: + case Kubernetes.WatchTypes.OAUTH_CLIENTS: + case Kubernetes.WatchTypes.NODES: + case Kubernetes.WatchTypes.PROJECTS: + case Kubernetes.WatchTypes.OAUTH_CLIENTS: + case Kubernetes.WatchTypes.PERSISTENT_VOLUMES: + params = {}; + } + var url = UrlHelpers.join(masterApiUrl(), prefix, urlTemplate); + Kubernetes.log.debug("Url for ", thing, ": ", url); + var resource = $resource(url, null, { + query: { method: 'GET', isArray: false, params: params }, + create: { method: 'POST', params: params }, + save: { method: 'PUT', params: params }, + delete: { method: 'DELETE', params: _.extend({ + id: '@id' + }, params) } + }); + return resource; + } + Kubernetes.createResource = createResource; + function imageRepositoriesRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/imagestreams"); + } + Kubernetes.imageRepositoriesRestURL = imageRepositoriesRestURL; + function deploymentConfigsRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/deploymentconfigs"); + } + Kubernetes.deploymentConfigsRestURL = deploymentConfigsRestURL; + function buildsRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/builds"); + } + Kubernetes.buildsRestURL = buildsRestURL; + function buildConfigHooksRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/buildconfighooks"); + } + Kubernetes.buildConfigHooksRestURL = buildConfigHooksRestURL; + function buildConfigsRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/buildconfigs"); + } + Kubernetes.buildConfigsRestURL = buildConfigsRestURL; + function routesRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/routes"); + } + Kubernetes.routesRestURL = routesRestURL; + function templatesRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/templates"); + } + Kubernetes.templatesRestURL = templatesRestURL; + function getNamespace(entity) { + var answer = Core.pathGet(entity, ["metadata", "namespace"]); + return answer ? answer : currentKubernetesNamespace(); + } + Kubernetes.getNamespace = getNamespace; + function getLabels(entity) { + var answer = Core.pathGet(entity, ["metadata", "labels"]); + return answer ? answer : {}; + } + Kubernetes.getLabels = getLabels; + function getName(entity) { + if (angular.isString(entity)) { + return entity; + } + return Core.pathGet(entity, ["metadata", "name"]) || Core.pathGet(entity, "name") || Core.pathGet(entity, "id"); + } + Kubernetes.getName = getName; + function getKind(entity) { + return Core.pathGet(entity, ["metadata", "kind"]) || Core.pathGet(entity, "kind"); + } + Kubernetes.getKind = getKind; + function getSelector(entity) { + return Core.pathGet(entity, ["spec", "selector"]); + } + Kubernetes.getSelector = getSelector; + function getHost(pod) { + return Core.pathGet(pod, ["spec", "host"]) || Core.pathGet(pod, ["spec", "nodeName"]) || Core.pathGet(pod, ["status", "hostIP"]); + } + Kubernetes.getHost = getHost; + function getStatus(pod) { + return Core.pathGet(pod, ["status", "phase"]); + } + Kubernetes.getStatus = getStatus; + function getPorts(service) { + return Core.pathGet(service, ["spec", "ports"]); + } + Kubernetes.getPorts = getPorts; + function getCreationTimestamp(entity) { + return Core.pathGet(entity, ["metadata", "creationTimestamp"]); + } + Kubernetes.getCreationTimestamp = getCreationTimestamp; + ; + //var fabricDomain = Fabric.jmxDomain; + var fabricDomain = "io.fabric8"; + Kubernetes.mbean = fabricDomain + ":type=Kubernetes"; + Kubernetes.managerMBean = fabricDomain + ":type=KubernetesManager"; + Kubernetes.appViewMBean = fabricDomain + ":type=AppView"; + function isKubernetes(workspace) { + // return workspace.treeContainsDomainAndProperties(fabricDomain, {type: "Kubernetes"}); + return true; + } + Kubernetes.isKubernetes = isKubernetes; + function isKubernetesTemplateManager(workspace) { + // return workspace.treeContainsDomainAndProperties(fabricDomain, {type: "KubernetesTemplateManager"}); + return true; + } + Kubernetes.isKubernetesTemplateManager = isKubernetesTemplateManager; + function isAppView(workspace) { + // return workspace.treeContainsDomainAndProperties(fabricDomain, {type: "AppView"}); + return true; + } + Kubernetes.isAppView = isAppView; + function getStrippedPathName() { + var pathName = Core.trimLeading((this.$location.path() || '/'), "#"); + pathName = pathName.replace(/^\//, ''); + return pathName; + } + Kubernetes.getStrippedPathName = getStrippedPathName; + function linkContains() { + var words = []; + for (var _i = 0; _i < arguments.length; _i++) { + words[_i - 0] = arguments[_i]; + } + var pathName = this.getStrippedPathName(); + return _.every(words, function (word) { return pathName.indexOf(word) !== 0; }); + } + Kubernetes.linkContains = linkContains; + /** + * Returns true if the given link is active. The link can omit the leading # or / if necessary. + * The query parameters of the URL are ignored in the comparison. + * @method isLinkActive + * @param {String} href + * @return {Boolean} true if the given link is active + */ + function isLinkActive(href) { + // lets trim the leading slash + var pathName = getStrippedPathName(); + var link = Core.trimLeading(href, "#"); + link = link.replace(/^\//, ''); + // strip any query arguments + var idx = link.indexOf('?'); + if (idx >= 0) { + link = link.substring(0, idx); + } + if (!pathName.length) { + return link === pathName; + } + else { + return _.startsWith(pathName, link); + } + } + Kubernetes.isLinkActive = isLinkActive; + function setJson($scope, id, collection) { + $scope.id = id; + if (!$scope.fetched) { + return; + } + if (!id) { + $scope.json = ''; + return; + } + if (!collection) { + return; + } + var item = collection.find(function (item) { return getName(item) === id; }); + if (item) { + $scope.json = angular.toJson(item, true); + $scope.item = item; + } + else { + $scope.id = undefined; + $scope.json = ''; + $scope.item = undefined; + } + } + Kubernetes.setJson = setJson; + /** + * Returns the labels text string using the key1=value1,key2=value2,.... format + */ + function labelsToString(labels, seperatorText) { + if (seperatorText === void 0) { seperatorText = Kubernetes.labelFilterTextSeparator; } + var answer = ""; + angular.forEach(labels, function (value, key) { + var separator = answer ? seperatorText : ""; + answer += separator + key + "=" + value; + }); + return answer; + } + Kubernetes.labelsToString = labelsToString; + function initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL) { + $scope.baseUri = Core.trimTrailing(Core.url("/") || "", "/") || ""; + var injector = HawtioCore.injector; + function hasService(name) { + if (injector) { + var ServiceRegistry = injector.get("ServiceRegistry"); + if (ServiceRegistry) { + return ServiceRegistry.hasService(name); + } + } + return false; + } + $scope.hasServiceKibana = function () { return hasService(Kubernetes.kibanaServiceName); }; + $scope.hasServiceGogs = function () { return hasService(Kubernetes.gogsServiceName); }; + $scope.hasServiceForge = function () { return hasService(Kubernetes.fabric8ForgeServiceName); }; + $scope.hasServiceApiman = function () { return hasService(Kubernetes.apimanServiceName); }; + $scope.viewTemplates = function () { + var returnTo = $location.url(); + $location.path('/kubernetes/templates').search({ 'returnTo': returnTo }); + }; + $scope.namespace = $routeParams.namespace || $scope.namespace || KubernetesState.selectedNamespace || Kubernetes.defaultNamespace; + if ($scope.namespace != KubernetesState.selectedNamespace) { + KubernetesState.selectedNamespace = $scope.namespace; + // lets show page is going to reload + if ($scope.model) { + $scope.model.fetched = false; + } + } + Kubernetes.setCurrentKubernetesNamespace($scope.namespace); + $scope.forgeEnabled = isForgeEnabled(); + $scope.projectId = $routeParams["project"] || $scope.projectId || $scope.id; + var showProjectNavBars = false; + if ($scope.projectId && showProjectNavBars) { + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.projectId); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.projectId, null, $scope); + } + else { + $scope.breadcrumbConfig = Developer.createEnvironmentBreadcrumbs($scope, $location, $routeParams); + $scope.subTabConfig = Developer.createEnvironmentSubNavBars($scope, $location, $routeParams); + } + if ($scope.projectId) { + $scope.$projectLink = Developer.projectLink($scope.projectId); + } + $scope.link = function (href) { + if (!href) { + return href; + } + if ($scope.$projectLink) { + return Developer.namespaceLink($scope, $routeParams, href.replace(/^\/kubernetes/, '')); + } + else { + return href; + } + }; + $scope.codeMirrorOptions = { + lineWrapping: true, + lineNumbers: true, + readOnly: 'nocursor', + mode: { name: "javascript", json: true } + }; + $scope.resizeDialog = { + controller: null, + newReplicas: 0, + dialog: new UI.Dialog(), + onOk: function () { + var resizeDialog = $scope.resizeDialog; + resizeDialog.dialog.close(); + resizeController($http, KubernetesApiURL, resizeDialog.controller, resizeDialog.newReplicas, function () { Kubernetes.log.debug("updated number of replicas"); }); + }, + open: function (controller) { + var resizeDialog = $scope.resizeDialog; + resizeDialog.controller = controller; + resizeDialog.newReplicas = Core.pathGet(controller, ["status", "replicas"]); + resizeDialog.dialog.open(); + $timeout(function () { + $('#replicas').focus(); + }, 50); + }, + close: function () { + $scope.resizeDialog.dialog.close(); + } + }; + $scope.triggerBuild = function (buildConfig) { + var url = buildConfig.$triggerUrl; + console.log("triggering build at url: " + url); + if (url) { + //var data = {}; + var data = null; + var config = { + headers: { + 'Content-Type': "application/json" + } + }; + var name = Core.pathGet(buildConfig, ["metadata", "name"]); + Core.notification('info', "Triggering build " + name); + $http.post(url, data, config). + success(function (data, status, headers, config) { + console.log("trigger worked! got data " + angular.toJson(data, true)); + // TODO should we show some link to the build + Core.notification('info', "Building " + name); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + Core.notification('error', "Failed to trigger build for " + name + ". Returned code: " + status + " " + data); + }); + } + ; + }; + // update the URL if the filter is changed + $scope.$watch("tableConfig.filterOptions.filterText", function (text) { + //var filterText = Kubernetes.findValeOfLabels(text); + $location.search("q", text); + }); + $scope.$on("labelFilterUpdate", function ($event, text) { + var filterOptions = ($scope.tableConfig || {}).filterOptions || {}; + var currentFilter = filterOptions.filterText; + if (Core.isBlank(currentFilter)) { + filterOptions.filterText = text; + } + else { + var expressions = currentFilter.split(/\s+/); + if (expressions.indexOf(text) !== -1) { + // lets exclude this filter expression + expressions = expressions.remove(text); + filterOptions.filterText = expressions.join(" "); + } + else { + filterOptions.filterText = currentFilter + " " + text; + } + } + $scope.id = undefined; + }); + } + Kubernetes.initShared = initShared; + /** + * Returns the number of pods that are ready + */ + function readyPodCount(service) { + var count = 0; + angular.forEach((service || {}).$pods, function (pod) { + if (pod.$ready) { + count++; + } + }); + return count; + } + Kubernetes.readyPodCount = readyPodCount; + /** + * Returns the service link URL for either the service name or the service object + */ + function serviceLinkUrl(service, httpOnly) { + if (httpOnly === void 0) { httpOnly = false; } + if (angular.isObject(service)) { + var portalIP = service.$host; + // lets assume no custom port for now for external routes + var port = null; + var protocol = "http://"; + var spec = service.spec; + if (spec) { + if (!portalIP) { + portalIP = spec.portalIP; + } + var hasHttps = false; + var hasHttp = false; + angular.forEach(spec.ports, function (portSpec) { + var p = portSpec.port; + if (p) { + if (p === 443) { + hasHttps = true; + } + else if (p === 80) { + hasHttp = true; + } + if (!port) { + port = p; + } + } + }); + if (!hasHttps && !hasHttp && port) { + // lets treat 8080 as http which is a common service to export + if (port === 8080) { + hasHttp = true; + } + else if (port === 8443) { + hasHttps = true; + } + } + } + if (portalIP) { + if (hasHttps) { + return "https://" + portalIP; + } + else if (hasHttp) { + return "http://" + portalIP; + } + else if (!httpOnly) { + if (port) { + return protocol + portalIP + ":" + port + "/"; + } + else { + return protocol + portalIP; + } + } + } + } + else if (service) { + var serviceId = service.toString(); + if (serviceId) { + var ServiceRegistry = getServiceRegistry(); + if (ServiceRegistry) { + return ServiceRegistry.serviceLink(serviceId) || ""; + } + } + } + return ""; + } + Kubernetes.serviceLinkUrl = serviceLinkUrl; + /** + * Returns the total number of counters for the podCounters object + */ + function podCounterTotal($podCounters) { + var answer = 0; + if ($podCounters) { + angular.forEach(["ready", "valid", "waiting", "error"], function (name) { + var value = $podCounters[name] || 0; + answer += value; + }); + } + return answer; + } + Kubernetes.podCounterTotal = podCounterTotal; + /** + * Given the list of pods lets iterate through them and find all pods matching the selector + * and return counters based on the status of the pod + */ + function createPodCounters(selector, pods, outputPods, podLinkQuery, podLinkUrl) { + if (outputPods === void 0) { outputPods = []; } + if (podLinkQuery === void 0) { podLinkQuery = null; } + if (podLinkUrl === void 0) { podLinkUrl = null; } + if (!podLinkUrl) { + podLinkUrl = "/kubernetes/pods"; + } + var filterFn; + if (angular.isFunction(selector)) { + filterFn = selector; + } + else { + filterFn = function (pod) { return selectorMatches(selector, getLabels(pod)); }; + } + var answer = { + podsLink: "", + ready: 0, + valid: 0, + waiting: 0, + error: 0 + }; + if (selector) { + if (!podLinkQuery) { + podLinkQuery = Kubernetes.labelsToString(selector, " "); + } + answer.podsLink = podLinkUrl + "?q=" + encodeURIComponent(podLinkQuery); + angular.forEach(pods, function (pod) { + if (filterFn(pod)) { + outputPods.push(pod); + var status = getStatus(pod); + if (status) { + var lower = status.toLowerCase(); + if (lower.startsWith("run")) { + if (isReady(pod)) { + answer.ready += 1; + } + else { + answer.valid += 1; + } + } + else if (lower.startsWith("wait") || lower.startsWith("pend")) { + answer.waiting += 1; + } + else if (lower.startsWith("term") || lower.startsWith("error") || lower.startsWith("fail")) { + answer.error += 1; + } + } + else { + answer.error += 1; + } + } + }); + } + return answer; + } + Kubernetes.createPodCounters = createPodCounters; + /** + * Converts the given json into an array of items. If the json contains a nested set of items then that is sorted; so that services + * are processed first; then turned into an array. Otherwise the json is put into an array so it can be processed polymorphically + */ + function convertKubernetesJsonToItems(json) { + var items = json.items; + if (angular.isArray(items)) { + // TODO we could check for List or Config types here and warn if not + // sort the services first + var answer = []; + items.forEach(function (item) { + if (item.kind === "Service") { + answer.push(item); + } + }); + items.forEach(function (item) { + if (item.kind !== "Service") { + answer.push(item); + } + }); + return answer; + } + else { + return [json]; + } + } + Kubernetes.convertKubernetesJsonToItems = convertKubernetesJsonToItems; + function isV1beta1Or2() { + return Kubernetes.defaultApiVersion === "v1beta1" || Kubernetes.defaultApiVersion === "v1beta2"; + } + Kubernetes.isV1beta1Or2 = isV1beta1Or2; + /** + * Returns a link to the detail page for the given entity + */ + function entityPageLink(obj) { + if (obj) { + function getLink(entity) { + var viewLink = entity["$viewLink"]; + if (viewLink) { + return viewLink; + } + var id = getName(entity); + var kind = getKind(entity); + if (kind && id) { + var path = kind.substring(0, 1).toLowerCase() + kind.substring(1) + "s"; + var namespace = getNamespace(entity); + if (namespace && !isIgnoreNamespaceKind(kind)) { + return Core.url(UrlHelpers.join('/kubernetes/namespace', namespace, path, id)); + } + else { + return Core.url(UrlHelpers.join('/kubernetes', path, id)); + } + } + } + var baseLink = getLink(obj); + if (!HawtioCore.injector || !baseLink) { + return baseLink; + } + var $routeParams = HawtioCore.injector.get('$routeParams'); + var projectId = $routeParams['project'] || $routeParams['project']; + if (!projectId) { + return baseLink; + } + return UrlHelpers.join(Developer.projectLink(projectId), baseLink.replace(/^\/kubernetes\//, '')); + } + return null; + } + Kubernetes.entityPageLink = entityPageLink; + function resourceKindToUriPath(kind) { + var kindPath = kind.toLowerCase() + "s"; + if (kindPath === "replicationControllers" && !isV1beta1Or2()) { + kindPath = "replicationcontrollers"; + } + return kindPath; + } + Kubernetes.resourceKindToUriPath = resourceKindToUriPath; + function isIgnoreNamespaceKind(kind) { + return kind === "Host" || kind === "Minion"; + } + /** + * Returns the root URL for the kind + */ + function kubernetesUrlForKind(KubernetesApiURL, kind, namespace, path) { + if (namespace === void 0) { namespace = null; } + if (path === void 0) { path = null; } + var pathSegment = ""; + if (path) { + pathSegment = "/" + Core.trimLeading(path, "/"); + } + var kindPath = resourceKindToUriPath(kind); + var ignoreNamespace = isIgnoreNamespaceKind(kind); + if (isV1beta1Or2() || ignoreNamespace) { + var postfix = ""; + if (namespace && !ignoreNamespace) { + postfix = "?namespace=" + namespace; + } + return UrlHelpers.join(KubernetesApiURL, kindPath, pathSegment, postfix); + } + else { + return UrlHelpers.join(KubernetesApiURL, "/namespaces/", namespace, kindPath, pathSegment); + } + } + Kubernetes.kubernetesUrlForKind = kubernetesUrlForKind; + ; + /** + * Returns the base URL for the kind of kubernetes resource or null if it cannot be found + */ + function kubernetesUrlForItemKind(KubernetesApiURL, json) { + var kind = json.kind; + if (kind) { + return kubernetesUrlForKind(KubernetesApiURL, kind, json.namespace); + } + else { + Kubernetes.log.warn("Ignoring missing kind " + kind + " for kubernetes json: " + angular.toJson(json)); + return null; + } + } + Kubernetes.kubernetesUrlForItemKind = kubernetesUrlForItemKind; + function kubernetesProxyUrlForService(KubernetesApiURL, service, path) { + if (path === void 0) { path = null; } + var pathSegment = ""; + if (path) { + pathSegment = "/" + Core.trimLeading(path, "/"); + } + else { + pathSegment = "/"; + } + var namespace = getNamespace(service); + if (isV1beta1Or2()) { + var postfix = "?namespace=" + namespace; + return UrlHelpers.join(KubernetesApiURL, "/proxy", kubernetesNamespacePath(), "/services/" + getName(service) + pathSegment + postfix); + } + else { + return UrlHelpers.join(KubernetesApiURL, "/proxy/namespaces/", namespace, "/services/" + getName(service) + pathSegment); + } + } + Kubernetes.kubernetesProxyUrlForService = kubernetesProxyUrlForService; + function kubernetesProxyUrlForServiceCurrentNamespace(service, path) { + if (path === void 0) { path = null; } + var apiPrefix = UrlHelpers.join(kubernetesApiUrl()); + return kubernetesProxyUrlForService(apiPrefix, service, path); + } + Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace = kubernetesProxyUrlForServiceCurrentNamespace; + function buildConfigRestUrl(id) { + return UrlHelpers.join(buildConfigsRestURL(), id); + } + Kubernetes.buildConfigRestUrl = buildConfigRestUrl; + function deploymentConfigRestUrl(id) { + return UrlHelpers.join(deploymentConfigsRestURL(), id); + } + Kubernetes.deploymentConfigRestUrl = deploymentConfigRestUrl; + function imageRepositoryRestUrl(id) { + return UrlHelpers.join(imageRepositoriesRestURL(), id); + } + Kubernetes.imageRepositoryRestUrl = imageRepositoryRestUrl; + function buildRestUrl(id) { + return UrlHelpers.join(buildsRestURL(), id); + } + Kubernetes.buildRestUrl = buildRestUrl; + function buildLogsRestUrl(id) { + return UrlHelpers.join(buildsRestURL(), id, "log"); + } + Kubernetes.buildLogsRestUrl = buildLogsRestUrl; + /** + * Runs the given application JSON + */ + function runApp($location, $scope, $http, KubernetesApiURL, json, name, onSuccessFn, namespace, onCompleteFn) { + if (name === void 0) { name = "App"; } + if (onSuccessFn === void 0) { onSuccessFn = null; } + if (namespace === void 0) { namespace = null; } + if (onCompleteFn === void 0) { onCompleteFn = null; } + if (json) { + if (angular.isString(json)) { + json = angular.fromJson(json); + } + name = name || "App"; + var postfix = namespace ? " in namespace " + namespace : ""; + Core.notification('info', "Running " + name + postfix); + var items = convertKubernetesJsonToItems(json); + angular.forEach(items, function (item) { + var url = kubernetesUrlForItemKind(KubernetesApiURL, item); + if (url) { + $http.post(url, item). + success(function (data, status, headers, config) { + Kubernetes.log.debug("Got status: " + status + " on url: " + url + " data: " + data + " after posting: " + angular.toJson(item)); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(); + } + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + var message = null; + if (angular.isObject(data)) { + message = data.message; + var reason = data.reason; + if (reason === "AlreadyExists") { + // lets ignore duplicates + Kubernetes.log.debug("entity already exists at " + url); + return; + } + } + if (!message) { + message = "Failed to POST to " + url + " got status: " + status; + } + Kubernetes.log.warn("Failed to save " + url + " status: " + status + " response: " + angular.toJson(data, true)); + Core.notification('error', message); + }); + } + }); + } + } + Kubernetes.runApp = runApp; + /** + * Returns true if the current status of the pod is running + */ + function isRunning(podCurrentState) { + var status = (podCurrentState || {}).phase; + if (status) { + var lower = status.toLowerCase(); + return lower.startsWith("run"); + } + else { + return false; + } + } + Kubernetes.isRunning = isRunning; + /** + * Returns true if the labels object has all of the key/value pairs from the selector + */ + function selectorMatches(selector, labels) { + if (angular.isObject(labels)) { + var answer = true; + var count = 0; + angular.forEach(selector, function (value, key) { + count++; + if (answer && labels[key] !== value) { + answer = false; + } + }); + return answer && count > 0; + } + else { + return false; + } + } + Kubernetes.selectorMatches = selectorMatches; + /** + * Returns the service registry + */ + function getServiceRegistry() { + var injector = HawtioCore.injector; + return injector ? injector.get("ServiceRegistry") : null; + } + Kubernetes.getServiceRegistry = getServiceRegistry; + /** + * Returns a link to the kibana logs web application + */ + function kibanaLogsLink(ServiceRegistry) { + var link = ServiceRegistry.serviceLink(Kubernetes.kibanaServiceName); + if (link) { + if (!link.endsWith("/")) { + link += "/"; + } + return link + "#/dashboard/Fabric8"; + } + else { + return null; + } + } + Kubernetes.kibanaLogsLink = kibanaLogsLink; + function openLogsForPods(ServiceRegistry, $window, namespace, pods) { + var link = kibanaLogsLink(ServiceRegistry); + if (link) { + var query = ""; + var count = 0; + angular.forEach(pods, function (item) { + var id = getName(item); + if (id) { + var space = query ? " OR " : ""; + count++; + query += space + '"' + id + '"'; + } + }); + if (query) { + if (count > 1) { + query = "(" + query + ")"; + } + query = 'kubernetes.namespace_name:"' + namespace + '" AND kubernetes.pod_name:' + query; + link += "?_a=(query:(query_string:(query:'" + query + "')))"; + var newWindow = $window.open(link, "viewLogs"); + } + } + } + Kubernetes.openLogsForPods = openLogsForPods; + function resizeController($http, KubernetesApiURL, replicationController, newReplicas, onCompleteFn) { + if (onCompleteFn === void 0) { onCompleteFn = null; } + var id = getName(replicationController); + var namespace = getNamespace(replicationController) || ""; + var url = kubernetesUrlForKind(KubernetesApiURL, "ReplicationController", namespace, id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + var desiredState = data.spec; + if (!desiredState) { + desiredState = {}; + data.spec = desiredState; + } + desiredState.replicas = newReplicas; + $http.put(url, data). + success(function (data, status, headers, config) { + Kubernetes.log.debug("updated controller " + url); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to save " + url + " " + data + " " + status); + }); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + Kubernetes.resizeController = resizeController; + function statusTextToCssClass(text, ready) { + if (ready === void 0) { ready = false; } + if (text) { + var lower = text.toLowerCase(); + if (lower.startsWith("run") || lower.startsWith("ok")) { + if (!ready) { + return "fa fa-spinner fa-spin green"; + } + return 'fa fa-play-circle green'; + } + else if (lower.startsWith("wait") || lower.startsWith("pend")) { + return 'fa fa-download'; + } + else if (lower.startsWith("term") || lower.startsWith("error") || lower.startsWith("fail")) { + return 'fa fa-off orange'; + } + else if (lower.startsWith("succeeded")) { + return 'fa fa-check-circle-o green'; + } + } + return 'fa fa-question red'; + } + Kubernetes.statusTextToCssClass = statusTextToCssClass; + function podStatus(pod) { + return getStatus(pod); + } + Kubernetes.podStatus = podStatus; + function isReady(pod) { + var status = pod.status || {}; + var answer = false; + angular.forEach(status.conditions, function (condition) { + var t = condition.type; + if (t && t === "Ready") { + var status = condition.status; + if (status === "True") { + answer = true; + } + } + }); + return answer; + } + Kubernetes.isReady = isReady; + function createAppViewPodCounters(appView) { + var array = []; + var map = {}; + var pods = appView.pods; + var lowestDate = null; + angular.forEach(pods, function (pod) { + var selector = getLabels(pod); + var selectorText = Kubernetes.labelsToString(selector, " "); + var answer = map[selector]; + if (!answer) { + answer = { + labelText: selectorText, + podsLink: UrlHelpers.join("/kubernetes/namespace/", pod.metadata.namespace, "pods?q=" + encodeURIComponent(selectorText)), + valid: 0, + waiting: 0, + error: 0 + }; + map[selector] = answer; + array.push(answer); + } + var status = (podStatus(pod) || "Error").toLowerCase(); + if (status.startsWith("run") || status.startsWith("ok")) { + answer.valid += 1; + } + else if (status.startsWith("wait") || status.startsWith("pwnd")) { + answer.waiting += 1; + } + else { + answer.error += 1; + } + var creationTimestamp = getCreationTimestamp(pod); + if (creationTimestamp) { + var d = new Date(creationTimestamp); + if (!lowestDate || d < lowestDate) { + lowestDate = d; + } + } + }); + appView.$creationDate = lowestDate; + return array; + } + Kubernetes.createAppViewPodCounters = createAppViewPodCounters; + function createAppViewServiceViews(appView) { + var array = []; + var pods = appView.pods; + angular.forEach(pods, function (pod) { + var id = getName(pod); + if (id) { + var abbrev = id; + var idx = id.indexOf("-"); + if (idx > 1) { + abbrev = id.substring(0, idx); + } + pod.idAbbrev = abbrev; + } + pod.statusClass = statusTextToCssClass(podStatus(pod), isReady(pod)); + }); + var services = appView.services || []; + var replicationControllers = appView.replicationControllers || []; + var size = Math.max(services.length, replicationControllers.length, 1); + var appName = appView.$info.name; + for (var i = 0; i < size; i++) { + var service = services[i]; + var replicationController = replicationControllers[i]; + var controllerId = getName(replicationController); + var name = getName(service) || controllerId; + var address = Core.pathGet(service, ["spec", "portalIP"]); + if (!name && pods.length) { + name = pods[0].idAbbrev; + } + if (!appView.$info.name) { + appView.$info.name = name; + } + if (!appView.id && pods.length) { + appView.id = getName(pods[0]); + } + if (i > 0) { + appName = name; + } + var podCount = pods.length; + var podCountText = podCount + " pod" + (podCount > 1 ? "s" : ""); + var view = { + appName: appName || name, + name: name, + createdDate: appView.$creationDate, + podCount: podCount, + podCountText: podCountText, + address: address, + controllerId: controllerId, + service: service, + replicationController: replicationController, + pods: pods + }; + array.push(view); + } + return array; + } + Kubernetes.createAppViewServiceViews = createAppViewServiceViews; + /** + * converts a git path into an accessible URL for the browser + */ + function gitPathToUrl(iconPath, branch) { + if (branch === void 0) { branch = "master"; } + return (HawtioCore.injector.get('AppLibraryURL') || '') + "/git/" + branch + iconPath; + } + Kubernetes.gitPathToUrl = gitPathToUrl; + function asDate(value) { + return value ? new Date(value) : null; + } + function enrichBuildConfig(buildConfig, sortedBuilds) { + if (buildConfig) { + var triggerUrl = null; + var metadata = buildConfig.metadata || {}; + var name = metadata.name; + buildConfig.$name = name; + var projectLink = Developer.projectLink(name); + var ns = metadata.namespace || currentKubernetesNamespace(); + buildConfig.$namespace = ns; + buildConfig.environments = []; + buildConfig.$creationDate = asDate(Kubernetes.getCreationTimestamp(buildConfig)); + buildConfig.$labelsText = Kubernetes.labelsToString(getLabels(buildConfig)); + if (name) { + buildConfig.$viewLink = UrlHelpers.join("workspaces", ns, "projects", name, "environments"); + buildConfig.$editLink = UrlHelpers.join("workspaces", ns, "projects", name, "buildConfigEdit"); + angular.forEach([false, true], function (flag) { + angular.forEach(buildConfig.triggers, function (trigger) { + if (!triggerUrl) { + var type = trigger.type; + if (type === "generic" || flag) { + var generic = trigger[type]; + if (type && generic) { + var secret = generic.secret; + if (secret) { + triggerUrl = UrlHelpers.join(buildConfigHooksRestURL(), name, secret, type); + buildConfig.$triggerUrl = triggerUrl; + } + } + } + } + }); + }); + // lets find the latest build... + if (sortedBuilds) { + buildConfig.$lastBuild = _.find(sortedBuilds, { + metadata: { + labels: { + buildconfig: name + } + } + }); + } + } + var $fabric8Views = {}; + function defaultPropertiesIfNotExist(name, object, autoCreate) { + if (autoCreate === void 0) { autoCreate = false; } + var view = $fabric8Views[name]; + if (autoCreate && !view) { + view = {}; + $fabric8Views[name] = view; + } + if (view) { + angular.forEach(object, function (value, property) { + var current = view[property]; + if (!current) { + view[property] = value; + } + }); + } + } + function defaultPropertiesIfNotExistStartsWith(prefix, object, autoCreate) { + if (autoCreate === void 0) { autoCreate = false; } + angular.forEach($fabric8Views, function (view, name) { + if (view && name.startsWith(prefix)) { + angular.forEach(object, function (value, property) { + var current = view[property]; + if (!current) { + view[property] = value; + } + }); + } + }); + } + var labels = metadata.labels || {}; + var annotations = metadata.annotations || {}; + // lets default the repo and user + buildConfig.$user = annotations["fabric8.jenkins/user"] || labels["user"]; + buildConfig.$repo = annotations["fabric8.jenkins/repo"] || labels["repo"]; + angular.forEach(annotations, function (value, key) { + var parts = key.split('/', 2); + if (parts.length > 1) { + var linkId = parts[0]; + var property = parts[1]; + if (linkId && property && linkId.startsWith("fabric8.link")) { + var link = $fabric8Views[linkId]; + if (!link) { + link = { + class: linkId + }; + $fabric8Views[linkId] = link; + } + link[property] = value; + } + } + }); + if (buildConfig.$user && buildConfig.$repo) { + // browse gogs repo view + var gogsUrl = serviceLinkUrl(Kubernetes.gogsServiceName); + if (gogsUrl) { + defaultPropertiesIfNotExist("fabric8.link.browseGogs.view", { + label: "Browse...", + url: UrlHelpers.join(gogsUrl, buildConfig.$user, buildConfig.$repo), + description: "Browse the source code of this repository", + iconClass: "fa fa-external-link" + }, true); + } + // run forge commands view + defaultPropertiesIfNotExist("fabric8.link.forgeCommand.view", { + label: "Command...", + url: UrlHelpers.join(projectLink, "/forge/commands/user", buildConfig.$user, buildConfig.$repo), + description: "Perform an action on this project", + iconClass: "fa fa-play-circle" + }, true); + // configure devops view + defaultPropertiesIfNotExist("fabric8.link.forgeCommand.devops.settings", { + label: "Settings", + url: UrlHelpers.join(projectLink, "/forge/command/devops-edit/user", buildConfig.$user, buildConfig.$repo), + description: "Configure the DevOps settings for this project", + iconClass: "fa fa-pencil-square-o" + }, true); + } + // add some icons and descriptions + defaultPropertiesIfNotExist("fabric8.link.repository.browse", { + label: "Browse...", + description: "Browse the source code of this repository", + iconClass: "fa fa-external-link" + }); + defaultPropertiesIfNotExist("fabric8.link.jenkins.job", { + iconClass: "fa fa-tasks", + description: "View the Jenkins Job for this build" + }); + defaultPropertiesIfNotExist("fabric8.link.jenkins.monitor", { + iconClass: "fa fa-tachometer", + description: "View the Jenkins Monitor dashboard for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.jenkins.pipeline", { + iconClass: "fa fa-arrow-circle-o-right", + description: "View the Jenkins Pipeline for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.letschat.room", { + iconClass: "fa fa-comment", + description: "Chat room for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.letschat.room", { + iconClass: "fa fa-comment", + description: "Chat room for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.taiga", { + iconClass: "fa fa-check-square-o", + description: "Issue tracker for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.issues", { + iconClass: "fa fa-check-square-o", + description: "Issues for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.releases", { + iconClass: "fa fa-tag", + description: "Issues for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.taiga.team", { + iconClass: "fa fa-users", + description: "Team members for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.team", { + iconClass: "fa fa-users", + description: "Team members for this project" + }); + defaultPropertiesIfNotExistStartsWith("fabric8.link.environment.", { + iconClass: "fa fa-cloud", + description: "The kubernetes namespace for this environment" + }); + // lets put the views into sections... + var $fabric8CodeViews = {}; + var $fabric8BuildViews = {}; + var $fabric8TeamViews = {}; + var $fabric8EnvironmentViews = {}; + angular.forEach($fabric8Views, function (value, key) { + var view; + if (key.indexOf("taiga") > 0 || key.indexOf(".issue") > 0 || key.indexOf("letschat") > 0 || key.indexOf(".team") > 0) { + view = $fabric8TeamViews; + } + else if (key.indexOf("jenkins") > 0) { + view = $fabric8BuildViews; + } + else if (key.indexOf(".environment.") > 0) { + view = $fabric8EnvironmentViews; + } + else { + view = $fabric8CodeViews; + } + view[key] = value; + }); + buildConfig.$fabric8Views = $fabric8Views; + buildConfig.$fabric8CodeViews = $fabric8CodeViews; + buildConfig.$fabric8BuildViews = $fabric8BuildViews; + buildConfig.$fabric8EnvironmentViews = $fabric8EnvironmentViews; + buildConfig.$fabric8TeamViews = $fabric8TeamViews; + var $jenkinsJob = annotations["fabric8.io/jenkins-job"]; + if (!$jenkinsJob && $fabric8Views["fabric8.link.jenkins.job"]) { + $jenkinsJob = name; + } + buildConfig.$jenkinsJob = $jenkinsJob; + angular.forEach($fabric8EnvironmentViews, function (env) { + var c = env.class; + var prefix = "fabric8.link.environment."; + if (c && c.startsWith(prefix)) { + var ens = c.substring(prefix.length); + env.namespace = ens; + env.url = UrlHelpers.join("/workspaces", ns, "projects", name, "namespace", ens); + } + buildConfig.environments.push(env); + }); + if (!buildConfig.environments.length) { + // lets create a single environment + var ens = ns; + var env = { + namespace: ens, + label: "Current", + description: "The environemnt that this project is built and run inside", + iconClass: "fa fa-cloud", + url: UrlHelpers.join("/workspaces", ns, "projects", name, "namespace", ens) + }; + buildConfig.environments.push(env); + } + buildConfig.environments = buildConfig.environments.reverse(); + buildConfig.tools = []; + angular.forEach($fabric8CodeViews, function (env) { + buildConfig.tools.push(env); + }); + angular.forEach($fabric8TeamViews, function (env) { + buildConfig.tools.push(env); + }); + } + } + Kubernetes.enrichBuildConfig = enrichBuildConfig; + function enrichBuildConfigs(buildConfigs, sortedBuilds) { + if (sortedBuilds === void 0) { sortedBuilds = null; } + angular.forEach(buildConfigs, function (buildConfig) { + enrichBuildConfig(buildConfig, sortedBuilds); + }); + return buildConfigs; + } + Kubernetes.enrichBuildConfigs = enrichBuildConfigs; + function enrichBuilds(builds) { + angular.forEach(builds, function (build) { + enrichBuild(build); + }); + return _.sortBy(builds, "$creationDate").reverse(); + } + Kubernetes.enrichBuilds = enrichBuilds; + function enrichBuild(build) { + if (build) { + var metadata = build.metadata || {}; + var annotations = metadata.annotations || {}; + var name = getName(build); + var namespace = getNamespace(build); + build.$name = name; + build.$namespace = namespace; + var nameArray = name.split("-"); + var nameArrayLength = nameArray.length; + build.$shortName = (nameArrayLength > 4) ? nameArray.slice(0, nameArrayLength - 4).join("-") : name.substring(0, 30); + var labels = getLabels(build); + var configId = labels.buildconfig; + build.$configId = configId; + if (configId) { + //build.$configLink = UrlHelpers.join("kubernetes/buildConfigs", configId); + build.$configLink = UrlHelpers.join("workspaces", currentKubernetesNamespace(), "projects", configId); + } + var creationTimestamp = getCreationTimestamp(build); + if (creationTimestamp) { + var d = new Date(creationTimestamp); + build.$creationDate = d; + } + if (name) { + //build.$viewLink = UrlHelpers.join("kubernetes/builds", name); + var projectLink = UrlHelpers.join("workspaces", currentKubernetesNamespace(), "projects", configId); + build.$viewLink = UrlHelpers.join(projectLink, "builds", name); + //build.$logsLink = UrlHelpers.join("kubernetes/buildLogs", name); + build.$logsLink = UrlHelpers.join(projectLink, "buildLogs", name); + } + build.podName = build.podName || annotations["openshift.io/build.pod-name"]; + var podName = build.podName; + if (podName && namespace) { + var podNameArray = podName.split("-"); + var podNameArrayLength = podNameArray.length; + build.$podShortName = (podNameArrayLength > 5) ? podNameArray[podNameArrayLength - 5] : podName.substring(0, 30); + build.$podLink = UrlHelpers.join("kubernetes/namespace", namespace, "pods", podName); + } + } + return build; + } + Kubernetes.enrichBuild = enrichBuild; + function enrichDeploymentConfig(deploymentConfig) { + if (deploymentConfig) { + var triggerUrl = null; + var name = Core.pathGet(deploymentConfig, ["metadata", "name"]); + deploymentConfig.$name = name; + var found = false; + angular.forEach(deploymentConfig.triggers, function (trigger) { + var type = trigger.type; + if (!deploymentConfig.$imageChangeParams && type === "ImageChange") { + var imageChangeParams = trigger.imageChangeParams; + if (imageChangeParams) { + var containerNames = imageChangeParams.containerNames || []; + imageChangeParams.$containerNames = containerNames.join(" "); + deploymentConfig.$imageChangeParams = imageChangeParams; + } + } + }); + } + } + Kubernetes.enrichDeploymentConfig = enrichDeploymentConfig; + function enrichDeploymentConfigs(deploymentConfigs) { + angular.forEach(deploymentConfigs, function (deploymentConfig) { + enrichDeploymentConfig(deploymentConfig); + }); + return deploymentConfigs; + } + Kubernetes.enrichDeploymentConfigs = enrichDeploymentConfigs; + function enrichEvent(event) { + if (event) { + var metadata = event.metadata || {}; + var firstTimestamp = event.firstTimestamp; + if (firstTimestamp) { + var d = new Date(firstTimestamp); + event.$firstTimestamp = d; + } + var lastTimestamp = event.lastTimestamp; + if (lastTimestamp) { + var d = new Date(lastTimestamp); + event.$lastTimestamp = d; + } + var labels = angular.copy(event.source || {}); + var involvedObject = event.involvedObject || {}; + var name = involvedObject.name; + var kind = involvedObject.kind; + if (name) { + labels['name'] = name; + } + if (kind) { + labels['kind'] = kind; + } + event.$labelsText = Kubernetes.labelsToString(labels); + } + } + Kubernetes.enrichEvent = enrichEvent; + function enrichEvents(events, model) { + if (model === void 0) { model = null; } + angular.forEach(events, function (event) { + enrichEvent(event); + }); + // lets update links to the events for each pod and RC + if (model) { + function clearEvents(entity) { + entity.$events = []; + entity.$eventsLink = null; + entity.$eventCount = 0; + } + function updateEvent(entity, event) { + if (entity) { + entity.$events.push(event); + if (!entity.$eventsLink) { + entity.$eventsLink = UrlHelpers.join("/kubernetes/namespace/", currentKubernetesNamespace(), "events") + "?q=kind%3D" + entity.kind + "%20name%3D" + entity.metadata.name; + } + entity.$eventCount = entity.$events.length; + } + } + var pods = model.pods || []; + var rcs = model.replicationControllers || []; + angular.forEach(pods, clearEvents); + angular.forEach(rcs, clearEvents); + angular.forEach(events, function (event) { + var involvedObject = event.involvedObject || {}; + var name = involvedObject.name; + var kind = involvedObject.kind; + var ns = model.currentNamespace(); + if (name && kind && ns) { + var entity = null; + if (kind === "ReplicationController") { + entity = model.getReplicationController(ns, name); + } + else if (kind === "Pod") { + entity = model.getPod(ns, name); + } + if (entity) { + updateEvent(entity, event); + } + } + }); + } + return events; + } + Kubernetes.enrichEvents = enrichEvents; + function enrichImageRepository(imageRepository) { + if (imageRepository) { + var triggerUrl = null; + var name = Core.pathGet(imageRepository, ["metadata", "name"]); + imageRepository.$name = name; + } + } + Kubernetes.enrichImageRepository = enrichImageRepository; + function enrichImageRepositories(imageRepositories) { + angular.forEach(imageRepositories, function (imageRepository) { + enrichImageRepository(imageRepository); + }); + return imageRepositories; + } + Kubernetes.enrichImageRepositories = enrichImageRepositories; + var labelColors = { + 'batch': 'k8s-badge-batch', + 'region': 'k8s-badge-region', + 'type': 'k8s-badge-type', + 'system': 'k8s-badge-system' + }; + function containerLabelClass(labelType) { + if (!(labelType in labelColors)) { + return 'mouse-pointer'; + } + else + return labelColors[labelType] + ' mouse-pointer'; + } + Kubernetes.containerLabelClass = containerLabelClass; + /** + * Returns true if the fabric8 forge plugin is enabled + */ + function isForgeEnabled() { + // TODO should return true if the service "fabric8-forge" is valid + return true; + } + Kubernetes.isForgeEnabled = isForgeEnabled; + /** + * Returns the current kubernetes selected namespace or the default one + */ + function currentKubernetesNamespace() { + var injector = HawtioCore.injector; + if (injector) { + var KubernetesState = injector.get("KubernetesState") || {}; + return KubernetesState.selectedNamespace || Kubernetes.defaultNamespace; + } + return Kubernetes.defaultNamespace; + } + Kubernetes.currentKubernetesNamespace = currentKubernetesNamespace; + function setCurrentKubernetesNamespace(ns) { + if (ns) { + var KubernetesState = inject("KubernetesState") || {}; + KubernetesState.selectedNamespace = ns; + } + } + Kubernetes.setCurrentKubernetesNamespace = setCurrentKubernetesNamespace; + /** + * Configures the json schema + */ + function configureSchema() { + angular.forEach(Kubernetes.schema.definitions, function (definition, name) { + var properties = definition.properties; + if (properties) { + var hideProperties = ["creationTimestamp", "kind", "apiVersion", "annotations", "additionalProperties", "namespace", "resourceVersion", "selfLink", "uid"]; + angular.forEach(hideProperties, function (propertyName) { + var property = properties[propertyName]; + if (property) { + property["hidden"] = true; + } + }); + angular.forEach(properties, function (property, propertyName) { + var ref = property["$ref"]; + var type = property["type"]; + if (ref && (!type || type === "object")) { + property["type"] = ref; + } + if (type === "array") { + var items = property["items"]; + if (items) { + var ref = items["$ref"]; + var type = items["type"]; + if (ref && (!type || type === "object")) { + items["type"] = ref; + } + } + } + }); + } + Kubernetes.schema.definitions.os_build_WebHookTrigger.properties.secret.type = "password"; + }); + } + Kubernetes.configureSchema = configureSchema; + /** + * Lets remove any enriched data to leave the original json intact + */ + function unenrich(item) { + var o = _.cloneDeep(item); + angular.forEach(o, function (value, key) { + if (key.startsWith("$") || key.startsWith("_")) { + delete o[key]; + } + }); + delete o['connectTo']; + return o; + } + Kubernetes.unenrich = unenrich; + /** + * Returns the unenriched JSON representation of an object + */ + function toRawJson(item) { + var o = unenrich(item); + return JSON.stringify(o, null, 2); // spacing level = 2 + } + Kubernetes.toRawJson = toRawJson; + /** + * Returns the unenriched YAML representation of an object + */ + function toRawYaml(item) { + var o = unenrich(item); + return jsyaml.dump(o, { indent: 2 }); + } + Kubernetes.toRawYaml = toRawYaml; + function watch($scope, $element, kind, ns, fn, labelSelector) { + if (labelSelector === void 0) { labelSelector = null; } + var connection = KubernetesAPI.watch({ + kind: kind, + namespace: ns, + labelSelector: labelSelector, + success: function (objects) { + fn(objects); + Core.$apply($scope); + } + }); + $element.on('$destroy', function () { + console.log("Static controller[" + kind + ", " + ns + "] element destroyed"); + $scope.$destroy(); + }); + $scope.$on('$destroy', function () { + console.log("Static controller[" + kind + ", " + ns + "] scope destroyed"); + connection.disconnect(); + }); + var oldDeleteScopeFn = $scope.deleteScope; + $scope.deleteScope = function () { + $element.remove(); + if (angular.isFunction(oldDeleteScopeFn)) { + oldDeleteScopeFn(); + } + }; + } + Kubernetes.watch = watch; + function createKubernetesClient(kind, ns) { + if (ns === void 0) { ns = null; } + var K8SClientFactory = inject("K8SClientFactory"); + if (!K8SClientFactory) { + Kubernetes.log.warn("Could not find injected K8SClientFactory!"); + return null; + } + if (kind === "projects" || kind === "namespaces") { + ns = null; + } + else if (!ns) { + ns = Kubernetes.currentKubernetesNamespace(); + } + return K8SClientFactory.create(kind, ns); + } + Kubernetes.createKubernetesClient = createKubernetesClient; + function currentUserName() { + var userDetails = HawtioOAuth.getUserProfile(); + var answer = null; + if (userDetails) { + answer = getName(userDetails); + } + return answer || "admin"; + } + Kubernetes.currentUserName = currentUserName; + function createNamespace(ns, client) { + if (!client) { + client = Kubernetes.isOpenShift ? Kubernetes.createKubernetesClient('projects') : Kubernetes.createKubernetesClient('namespaces'); + } + if (ns && ns !== currentKubernetesNamespace()) { + var object = { + apiVersion: Kubernetes.defaultApiVersion, + kind: Kubernetes.isOpenShift ? 'Project' : 'Namespace', + metadata: { + name: ns, + labels: {} + } + }; + client.put(object, function (data) { + Kubernetes.log.info("Created namespace: " + ns); + }, function (err) { + Kubernetes.log.warn("Failed to create namespace: " + ns + ": " + angular.toJson(err)); + }); + } + } + Kubernetes.createNamespace = createNamespace; + function createRC(obj, onCompleteFn) { + if (onCompleteFn === void 0) { onCompleteFn = null; } + var client = Kubernetes.createKubernetesClient('replicationcontrollers', 'default'); + var RCTemplate = new Kubernetes.resourceRCTemplate(); + var rcTemplate = RCTemplate.createRC(obj); + client.put(rcTemplate, function (obj) { + console.log("Created: ", obj); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(obj); + } + }); + } + Kubernetes.createRC = createRC; + function updateReplicationControllerLabels($http, KubernetesApiURL, replicationController, newLabels, onCompleteFn) { + if (onCompleteFn === void 0) { onCompleteFn = null; } + var id = getName(replicationController); + var namespace = getNamespace(replicationController) || ""; + var url = kubernetesUrlForKind(KubernetesApiURL, "ReplicationController", namespace, id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + var desiredLabels = data.metadata; + if (!desiredLabels) { + desiredLabels = {}; + data.metadata = desiredLabels; + } + desiredLabels.labels = newLabels; + $http.put(url, data). + success(function (data, status, headers, config) { + Kubernetes.log.debug("updated controller " + url); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to save " + url + " " + data + " " + status); + }); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + Kubernetes.updateReplicationControllerLabels = updateReplicationControllerLabels; + function connectOracle($http, $timeout, url, connectParam, rcName, delayTime) { + $timeout(function () { + $http({ + url: url, + method: 'POST', + params: { oracleName: rcName, param: connectParam } + }).success(function (data, header, config, status) { + console.log("success"); + }).error(function (data, header, config, status) { + Kubernetes.log.warn("Failed to connect " + connectParam + " " + data + " " + status); + }); + }, delayTime); + } + Kubernetes.connectOracle = connectOracle; +})(Kubernetes || (Kubernetes = {})); + +/// +var Developer; +(function (Developer) { + function enrichWorkspaces(projects) { + angular.forEach(projects, function (project) { + enrichWorkspace(project); + }); + return projects; + } + Developer.enrichWorkspaces = enrichWorkspaces; + function enrichWorkspace(build) { + if (build) { + var name = Kubernetes.getName(build); + build.$name = name; + build.$sortOrder = 0 - build.number; + var nameArray = name.split("-"); + var nameArrayLength = nameArray.length; + build.$shortName = (nameArrayLength > 4) ? nameArray.slice(0, nameArrayLength - 4).join("-") : name.substring(0, 30); + var labels = Kubernetes.getLabels(build); + build.$creationDate = asDate(Kubernetes.getCreationTimestamp(build)); + build.$labelsText = Kubernetes.labelsToString(labels); + if (name) { + build.$projectsLink = UrlHelpers.join("workspaces", name); + build.$runtimeLink = UrlHelpers.join("kubernetes/namespace/", name, "/apps"); + build.$viewLink = build.$projectsLink; + } + } + return build; + } + Developer.enrichWorkspace = enrichWorkspace; + function asDate(value) { + return value ? new Date(value) : null; + } + Developer.asDate = asDate; + function enrichJenkinsJobs(jobsData, projectId, jobName) { + if (jobsData) { + angular.forEach(jobsData.jobs, function (job) { + enrichJenkinsJob(job, projectId, jobName); + }); + } + return jobsData; + } + Developer.enrichJenkinsJobs = enrichJenkinsJobs; + function enrichJenkinsJob(job, projectId, jobName) { + if (job) { + jobName = jobName || job.name || projectId; + job.$jobId = jobName; + job.$project = projectId || jobName; + var lastBuild = job.lastBuild; + var lastBuildResult = lastBuild ? lastBuild.result : "NOT_STARTED"; + var $iconClass = createBuildStatusIconClass(lastBuildResult); + job.$lastBuildNumber = enrichJenkinsBuild(job, lastBuild); + job.$lastSuccessfulBuildNumber = enrichJenkinsBuild(job, job.lastSuccessfulBuild); + job.$lastFailedlBuildNumber = enrichJenkinsBuild(job, job.lastFailedlBuild); + if (lastBuild) { + job.$duration = lastBuild.duration; + job.$timestamp = asDate(lastBuild.timestamp); + } + var jobUrl = (job || {}).url; + if (!jobUrl || !jobUrl.startsWith("http")) { + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + jobUrl = UrlHelpers.join(jenkinsUrl, "job", jobName); + } + } + if (jobUrl) { + job.$jobLink = jobUrl; + var workspaceName = Kubernetes.currentKubernetesNamespace(); + job.$pipelinesLink = UrlHelpers.join("/workspaces", workspaceName, "projects", job.$project, "jenkinsJob", jobName, "pipelines"); + job.$buildsLink = UrlHelpers.join("/workspaces", workspaceName, "projects", job.$project, "jenkinsJob", jobName); + } + job.$iconClass = $iconClass; + angular.forEach(job.builds, function (build) { + enrichJenkinsBuild(job, build); + }); + } + return job; + } + Developer.enrichJenkinsJob = enrichJenkinsJob; + function createBuildStatusIconClass(result) { + var $iconClass = "fa fa-spinner fa-spin"; + if (result) { + if (result === "FAILURE" || result === "FAILED") { + // TODO not available yet + $iconClass = "fa fa-exclamation-circle red"; + } + else if (result === "ABORTED" || result === "INTERUPTED") { + $iconClass = "fa fa-circle grey"; + } + else if (result === "SUCCESS" || result === "COMPLETE" || result === "COMPLETED") { + $iconClass = "fa fa-check-circle green"; + } + else if (result === "NOT_STARTED") { + $iconClass = "fa fa-circle-thin grey"; + } + } + return $iconClass; + } + Developer.createBuildStatusIconClass = createBuildStatusIconClass; + function createBuildStatusBackgroundClass(result) { + var $iconClass = "build-pending"; + if (result) { + if (result === "FAILURE" || result === "FAILED") { + $iconClass = "build-fail"; + } + else if (result === "ABORTED" || result === "INTERUPTED") { + $iconClass = "build-aborted"; + } + else if (result === "SUCCESS" || result === "COMPLETE" || result === "COMPLETED") { + $iconClass = "build-success"; + } + else if (result === "NOT_STARTED") { + $iconClass = "build-not-started"; + } + } + return $iconClass; + } + Developer.createBuildStatusBackgroundClass = createBuildStatusBackgroundClass; + function enrichJenkinsBuild(job, build) { + var number = null; + if (build) { + build.$duration = build.duration; + build.$timestamp = asDate(build.timestamp); + var projectId = job.$project; + var jobName = job.$jobId || projectId; + var buildId = build.id; + number = build.number; + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var $iconClass = createBuildStatusIconClass(build.result); + var jobUrl = (job || {}).url; + if (!jobUrl || !jobUrl.startsWith("http")) { + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + jobUrl = UrlHelpers.join(jenkinsUrl, "job", jobName); + } + } + if (jobUrl) { + build.$jobLink = jobUrl; + if (buildId) { + //build.$logsLink = UrlHelpers.join(build.$buildLink, "console"); + build.$logsLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "log", buildId); + build.$pipelineLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "pipeline", buildId); + build.$buildsLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName); + //build.$buildLink = UrlHelpers.join(jobUrl, build.id); + build.$buildLink = build.$logsLink; + } + } + build.$iconClass = $iconClass; + } + return number; + } + Developer.enrichJenkinsBuild = enrichJenkinsBuild; + function jenkinsLink() { + var ServiceRegistry = Kubernetes.inject("ServiceRegistry"); + if (ServiceRegistry) { + return ServiceRegistry.serviceLink(Developer.jenkinsServiceName); + } + return null; + } + Developer.jenkinsLink = jenkinsLink; + function forgeReadyLink() { + var ServiceRegistry = Kubernetes.inject("ServiceRegistry"); + if (ServiceRegistry) { + return ServiceRegistry.serviceReadyLink(Kubernetes.fabric8ForgeServiceName); + } + return null; + } + Developer.forgeReadyLink = forgeReadyLink; + function enrichJenkinsPipelineJob(job, projectId, jobId) { + if (job) { + job.$project = projectId; + job.$jobId = jobId; + angular.forEach(job.builds, function (build) { + enrichJenkinsStages(build, projectId, jobId); + }); + } + } + Developer.enrichJenkinsPipelineJob = enrichJenkinsPipelineJob; + function enrichJenkinsStages(build, projectId, jobName) { + if (build) { + build.$project = projectId; + build.$jobId = jobName; + build.$timestamp = asDate(build.timeInMillis); + build.$iconClass = createBuildStatusIconClass(build.result || "NOT_STARTED"); + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var parameters = build.parameters; + var $parameterCount = 0; + var $parameterText = "No parameters"; + if (parameters) { + $parameterCount = _.keys(parameters).length || 0; + $parameterText = Kubernetes.labelsToString(parameters, " "); + } + build.$parameterCount = $parameterCount; + build.$parameterText = $parameterText; + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + var url = build.url; + if (url) { + } + } + build.$logLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "log", build.id); + build.$viewLink = build.$logLink; + angular.forEach(build.stages, function (stage) { + enrichJenkinsStage(stage, build); + }); + } + return build; + } + Developer.enrichJenkinsStages = enrichJenkinsStages; + function enrichJenkinsStage(stage, build) { + if (build === void 0) { build = null; } + if (stage) { + if (build) { + stage.$buildId = build.id; + stage.$project = build.$project; + } + var projectId = build.$project; + var jobName = build.$jobId || projectId; + var buildId = build.id; + var workspaceName = Kubernetes.currentKubernetesNamespace(); + stage.$backgroundClass = createBuildStatusBackgroundClass(stage.status); + stage.$iconClass = createBuildStatusIconClass(stage.status); + stage.$startTime = asDate(stage.startTime); + if (!stage.duration) { + stage.duration = 0; + } + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + var url = stage.url; + if (url) { + stage.$viewLink = UrlHelpers.join(jenkinsUrl, url); + stage.$logLink = UrlHelpers.join(stage.$viewLink, "log"); + if (projectId && buildId) { + stage.$logLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "log", buildId); + } + } + } + } + } + Developer.enrichJenkinsStage = enrichJenkinsStage; +})(Developer || (Developer = {})); + +/// +var Developer; +(function (Developer) { + Developer.context = '/workspaces'; + Developer.hash = '#' + Developer.context; + Developer.pluginName = 'Developer'; + Developer.pluginPath = 'plugins/developer/'; + Developer.templatePath = Developer.pluginPath + 'html/'; + Developer.log = Logger.get(Developer.pluginName); + Developer.jenkinsServiceName = "jenkins"; + Developer.jenkinsServiceNameAndPort = Developer.jenkinsServiceName + ":http"; + Developer.jenkinsHttpConfig = { + headers: { + Accept: "application/json, text/x-json, text/plain" + } + }; + /** + * Returns true if the value hasn't changed from the last cached JSON version of this object + */ + function hasObjectChanged(value, state) { + var json = angular.toJson(value || ""); + var oldJson = state.json; + state.json = json; + return !oldJson || json !== oldJson; + } + Developer.hasObjectChanged = hasObjectChanged; + function projectForScope($scope) { + if ($scope) { + return $scope.buildConfig || $scope.entity || ($scope.model || {}).project; + } + return null; + } + Developer.projectForScope = projectForScope; + /** + * Lets load the project versions for the given namespace + */ + function loadProjectVersions($scope, $element, project, env, ns, answer, caches) { + var projectAnnotation = "project"; + var versionAnnotation = "version"; + var projectNamespace = project.$namespace; + var projectName = project.$name; + var cache = caches[ns]; + if (!cache) { + cache = {}; + caches[ns] = cache; + } + var status = { + rcs: [], + pods: [], + routes: [], + services: [] + }; + var imageStreamTags = []; + function updateModel() { + var projectInfos = {}; + var model = $scope.model || {}; + angular.forEach(status.rcs, function (item) { + var metadata = item.metadata || {}; + var name = metadata.name; + var labels = metadata.labels || {}; + var annotations = metadata.annotations || {}; + var spec = item.spec || {}; + var selector = spec.selector; + var project = labels[projectAnnotation]; + var version = labels[versionAnnotation]; + // lets try the S2I defaults... + if (!project) { + project = labels["app"]; + } + if (!version) { + version = annotations["openshift.io/deployment-config.latest-version"]; + } + if (project && version && project === projectName) { + var projects = projectInfos[project]; + if (!projects) { + projects = { + project: project, + versions: {} + }; + projectInfos[project] = projects; + } + var versionInfo = projects.versions[version]; + if (!versionInfo) { + versionInfo = { + replicationControllers: {} + }; + projects.versions[version] = versionInfo; + } + if (name) { + versionInfo.replicationControllers[name] = item; + item.$name = name; + if (projectNamespace && projectName) { + item.$viewLink = UrlHelpers.join("/workspaces/", projectNamespace, "projects", projectName, "namespace", ns, "replicationControllers", name); + } + else { + Developer.log.warn("Missing project data! " + projectNamespace + " name " + projectName); + } + item.$services = []; + var rcLink = null; + status.services.forEach(function (service) { + var repSelector = Kubernetes.getSelector(item); + var serviceSelector = Kubernetes.getSelector(service); + if (serviceSelector && repSelector && + Kubernetes.selectorMatches(serviceSelector, repSelector) && + Kubernetes.getNamespace(service) === Kubernetes.getNamespace(item)) { + status.routes.forEach(function (route) { + var serviceName = Kubernetes.getName(service); + if (serviceName === Kubernetes.getName(route)) { + service["$route"] = route; + service["$host"] = Core.pathGet(route, ["spec", "host"]); + item.$services.push(service); + if (!rcLink) { + var url = Kubernetes.serviceLinkUrl(service, true); + if (url) { + // TODO find icon etc? + rcLink = { + name: serviceName, + href: url + }; + } + } + } + }); + } + }); + item["$serviceLink"] = rcLink; + } + item.$buildId = annotations["fabric8.io/build-id"] || item.$buildId; + item.$buildUrl = annotations["fabric8.io/build-url"] || item.$buildUrl; + item.$gitCommit = annotations["fabric8.io/git-commit"] || item.$gitCommit; + item.$gitUrl = annotations["fabric8.io/git-url"] || item.$gitUrl; + item.$gitBranch = annotations["fabric8.io/git-branch"] || item.$gitBranch; + if (!item.$gitCommit) { + var image = getImage(item); + if (image) { + if (!$scope.$isWatchImages) { + $scope.$isWatchImages = true; + Kubernetes.watch($scope, $element, "images", null, function (data) { + imageStreamTags = data; + checkForMissingMetadata(); + }); + } + else { + checkForMissingMetadata(); + } + } + function getImage(item) { + var image = ""; + // lets see if we can find the commit id from a S2I image name + // TODO needs this issue fixed to find it via an OpenShift annotation: + // https://github.com/openshift/origin/issues/6241 + var containers = Core.pathGet(item, ["spec", "template", "spec", "containers"]); + if (containers && containers.length) { + var container = containers[0]; + if (container) { + image = container.image; + } + } + return image; + } + function checkForMissingMetadata() { + angular.forEach(projects.versions, function (vi) { + angular.forEach(vi.replicationControllers, function (item, name) { + if (!item.$gitCommit) { + var image = getImage(item); + if (image) { + angular.forEach(imageStreamTags, function (imageStreamTag) { + var imageName = imageStreamTag.dockerImageReference; + if (imageName && imageName === image) { + var foundISTag = imageStreamTag; + var manifestJSON = imageStreamTag.dockerImageManifest; + if (manifestJSON) { + var manifest = angular.fromJson(manifestJSON) || {}; + var history = manifest.history; + if (history && history.length) { + var v1 = history[0].v1Compatibility; + if (v1) { + var data = angular.fromJson(v1); + var env = Core.pathGet(data, ["config", "Env"]); + angular.forEach(env, function (envExp) { + if (envExp) { + var values = envExp.split("="); + if (values.length === 2 && values[0] == "OPENSHIFT_BUILD_NAME") { + var buildName = values[1]; + if (buildName) { + item.$buildId = buildName; + item.$buildUrl = Developer.projectWorkspaceLink(ns, projectName, "buildLogs/" + buildName); + } + } + } + }); + var labels = Core.pathGet(data, ["config", "Labels"]); + if (labels) { + item.$gitCommit = labels["io.openshift.build.commit.id"] || item.$gitCommit; + item.$gitCommitAuthor = labels["io.openshift.build.commit.author"] || item.$gitCommitAuthor; + item.$gitCommitDate = labels["io.openshift.build.commit.date"] || item.$gitCommitDate; + item.$gitCommitMessage = labels["io.openshift.build.commit.message"] || item.$gitCommitMessage; + item.$gitBranch = labels["io.openshift.build.commit.ref"] || item.$gitBranch; + if (!item.$gitUrl && item.$gitCommit) { + item.$gitUrl = Developer.projectWorkspaceLink(ns, projectName, "wiki/commitDetail///" + item.$gitCommit); + } + } + } + } + } + } + }); + } + } + }); + }); + } + } + if (selector) { + var selectorText = Kubernetes.labelsToString(selector, ","); + var podLinkUrl = UrlHelpers.join(Developer.projectLink(projectName), "namespace", ns, "pods"); + item.pods = []; + item.$podCounters = Kubernetes.createPodCounters(selector, status.pods, item.pods, selectorText, podLinkUrl); + } + } + }); + // lets check for a project name if we have lots of RCs with no pods, lets remove them! + angular.forEach(projectInfos, function (project, projectName) { + var rcsNoPods = []; + var rcsWithPods = []; + angular.forEach(project.versions, function (versionInfo) { + var rcs = versionInfo.replicationControllers; + angular.forEach(rcs, function (item, name) { + var count = Kubernetes.podCounterTotal(item.$podCounters); + if (count) { + rcsWithPods.push(name); + } + else { + rcsNoPods.push(function () { + delete rcs[name]; + }); + } + }); + }); + if (rcsWithPods.length) { + // lets remove all the empty RCs + angular.forEach(rcsNoPods, function (fn) { + fn(); + }); + } + }); + if (hasObjectChanged(projectInfos, cache)) { + Developer.log.debug("project versions has changed!"); + answer[ns] = projectInfos; + } + } + Kubernetes.watch($scope, $element, "replicationcontrollers", ns, function (data) { + if (data) { + status.rcs = data; + updateModel(); + } + }); + Kubernetes.watch($scope, $element, "services", ns, function (data) { + if (data) { + status.services = data; + updateModel(); + } + }); + Kubernetes.watch($scope, $element, "routes", ns, function (data) { + if (data) { + status.routes = data; + updateModel(); + } + }); + Kubernetes.watch($scope, $element, "pods", ns, function (data) { + if (data) { + status.pods = data; + updateModel(); + } + }); + } + Developer.loadProjectVersions = loadProjectVersions; +})(Developer || (Developer = {})); + +/// +var Developer; +(function (Developer) { + /* + function homeBreadcrumb() { + return { + href: "/home", + label: "Home", + title: "Go to the home page" + } + } + */ + function developBreadcrumb() { + return { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces"), + label: "Develop", + title: "View all the apps for a project" + }; + } + function operateBreadcrumb() { + return { + href: UrlHelpers.join(HawtioCore.documentBase(), "/namespaces"), + label: "Manage", + title: "Manage the projects and resources inside them" + }; + } + function workspaceLink() { + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", Kubernetes.currentKubernetesNamespace()); + } + Developer.workspaceLink = workspaceLink; + function projectLink(projectId) { + var link = workspaceLink(); + if (projectId) { + return UrlHelpers.join(link, "/projects", projectId); + } + else { + return link; + } + } + Developer.projectLink = projectLink; + function createWorkspacesBreadcrumbs(developPerspective) { + /* + if (developPerspective) { + return [ + //homeBreadcrumb(), + developBreadcrumb() + ]; + } else { + return [ + //homeBreadcrumb(), + operateBreadcrumb() + ]; + } + */ + return []; + } + Developer.createWorkspacesBreadcrumbs = createWorkspacesBreadcrumbs; + function createWorkspacesSubNavBars(developPerspective) { + return activateCurrent([ + developBreadcrumb(), + operateBreadcrumb() + ]); + } + Developer.createWorkspacesSubNavBars = createWorkspacesSubNavBars; + function createWorkspaceBreadcrumbs(children, workspaceName) { + if (children === void 0) { children = null; } + if (workspaceName === void 0) { workspaceName = null; } + var answer = [ + //homeBreadcrumb(), + developBreadcrumb() + ]; + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + if (workspaceName) { + answer.push({ + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces/", workspaceName), + label: workspaceName, + title: "View the project: " + workspaceName + }); + return processChildren(answer, children); + } + return answer; + } + Developer.createWorkspaceBreadcrumbs = createWorkspaceBreadcrumbs; + function createEnvironmentBreadcrumbs($scope, $location, $routeParams) { + var ns = Kubernetes.currentKubernetesNamespace(); + var namespacesLink = UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes/namespace"); + var workspaceName = $routeParams.workspace; + var project = $routeParams.project; + if (workspaceName && project) { + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", project); + $scope.$projectLink = projectLink; + $scope.$projectNamespaceLink = UrlHelpers.join(projectLink, "namespace", ns); + namespacesLink = UrlHelpers.join(projectLink, "namespace"); + // TODO use the logical name? + var envName = ns; + var buildConfig = null; + if ($scope.model) { + buildConfig = $scope.model.getProject(project, workspaceName); + if (buildConfig) { + // lets find the label for the namespace + var env = _.find(buildConfig.environments, { namespace: ns }); + if (env) { + envName = env['label'] || envName; + } + Developer.log.info("env found: " + env + " for nameppace " + ns + " on buildConfig: " + buildConfig); + } + } + var children = [ + { + href: UrlHelpers.join(projectLink, "environments"), + label: "Environments", + title: "View the environments for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "apps"), + label: envName, + title: "View the runtime of the workspace: " + ns + } + ]; + return createProjectBreadcrumbs(project, children, workspaceName); + } + else { + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + return activateCurrent([ + //homeBreadcrumb(), + operateBreadcrumb(), + { + href: UrlHelpers.join(namespacesLink, ns, "apps"), + label: workspaceName, + title: "View the runtime of the workspace: " + ns + } + ]); + } + } + Developer.createEnvironmentBreadcrumbs = createEnvironmentBreadcrumbs; + function createProjectBreadcrumbs(projectName, children, workspaceName) { + if (projectName === void 0) { projectName = null; } + if (children === void 0) { children = null; } + if (workspaceName === void 0) { workspaceName = null; } + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + var answer = createWorkspaceBreadcrumbs(null, workspaceName); + if (workspaceName) { + if (projectName) { + answer.push({ + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects"), + label: "Apps", + title: "View all the apps in this project" + }); + answer.push({ + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName), + label: projectName, + title: "View the project: " + projectName + }); + } + return processChildren(answer, children); + } + return answer; + } + Developer.createProjectBreadcrumbs = createProjectBreadcrumbs; + function createProjectSettingsBreadcrumbs(projectName, workspaceName) { + if (workspaceName === void 0) { workspaceName = null; } + var children = [{ + label: "Settings", + title: "View the settings of this app" + }]; + if (!projectName) { + var children = [{ + label: "New App", + title: "Lets make a new app" + }]; + } + return createProjectBreadcrumbs(projectName, children, workspaceName); + } + Developer.createProjectSettingsBreadcrumbs = createProjectSettingsBreadcrumbs; + function createWorkspaceSubNavBars() { + var workspaceName = Kubernetes.currentKubernetesNamespace(); + return activateCurrent([ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName), + label: "Apps", + class: "fa fa-rocket", + title: "View the apps in this project" + }, + { + isValid: function () { return Developer.jenkinsLink(); }, + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "jenkinsJob"), + label: "Builds", + class: "fa fa-code", + title: "View the builds in this project" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes/namespace", workspaceName, "apps"), + label: "Runtime", + class: "fa fa-gears", + title: "View the runtime resources in this project" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "detail"), + label: "Details", + class: "fa fa-gear", + title: "View the project details" + } + ]); + } + Developer.createWorkspaceSubNavBars = createWorkspaceSubNavBars; + function createBuildsLink(workspaceName, projectName, jenkinsJobId) { + workspaceName = workspaceName || Kubernetes.currentKubernetesNamespace(); + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "jenkinsJob", jenkinsJobId); + } + function createProjectSubNavBars(projectName, jenkinsJobId, $scope) { + if (jenkinsJobId === void 0) { jenkinsJobId = null; } + if ($scope === void 0) { $scope = null; } + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName); + var buildsLink = UrlHelpers.join(projectLink, "builds"); + if (!jenkinsJobId) { + jenkinsJobId = projectName; + } + var jenkinsBuildLink = null; + var pipelinesLink = null; + if (projectName && jenkinsJobId) { + jenkinsBuildLink = createBuildsLink(workspaceName, projectName, jenkinsJobId); + pipelinesLink = UrlHelpers.join(jenkinsBuildLink, "pipelines"); + } + function isJenkinsBuild() { + var answer = Developer.jenkinsLink() && jenkinsBuildLink; + if (answer && $scope) { + var entity = Developer.projectForScope($scope); + if (entity) { + return answer && entity.$jenkinsJob; + } + } + return answer; + } + var answer = [ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName), + label: "All Apps", + class: 'fa fa-angle-double-left', + title: "View the apps in this project" + }, + { + template: "
" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "environments"), + isActive: function (subTab, path) { + //console.log("subTab: ", subTab, " path: ", path); + if (path === subTab.href) { + return true; + } + var rootPath = subTab.href.replace(/\/environments/, ''); + if (path === rootPath) { + return true; + } + return false; + }, + //href: UrlHelpers.join("/workspaces", workspaceName, "projects", projectName), + label: "Dashboard", + class: "fa fa-tachometer", + title: "View the app dashboard for the activity, environments and pipelines" + }, + { + isValid: function () { return isJenkinsBuild() && pipelinesLink; }, + id: "pipelines", + href: pipelinesLink, + label: "Pipelines", + class: "fa fa-ellipsis-h", + title: "View the pipeline builds for this app" + }, + { + isValid: function () { return !isJenkinsBuild(); }, + href: buildsLink, + label: "Builds", + class: "fa fa-bars", + title: "View the builds for this app" + }, + { + isValid: function () { return isJenkinsBuild(); }, + id: "builds", + href: jenkinsBuildLink, + label: "Builds", + class: "fa fa-bars", + title: "View the Jenkins builds for this app" + }, + { + isValid: function () { return isJenkinsBuild(); }, + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "jenkinsJob", jenkinsJobId, "metrics"), + label: "Metrics", + class: "fa fa-bar-chart", + title: "View the metrics for this project" + }, + /* + { + href: UrlHelpers.join("/workspaces", workspaceName, "projects", projectName, "tools"), + label: "Tools", + title: "View the tools for this project" + }, + */ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "buildConfigEdit"), + label: "Settings", + class: "fa fa-cog", + title: "View the app configuration", + isActive: function (subTab, path) { + if (_.endsWith(path, '/buildConfigEdit')) { + return true; + } + if (_.endsWith(path, '/forge/secrets')) { + return true; + } + if (_.endsWith(path, '/forge/command/devops-edit')) { + return true; + } + return false; + } + } + ]; + var context = { + workspaceName: workspaceName, + projectName: projectName, + projectLink: projectLink, + jenkinsJobId: jenkinsJobId, + $scope: $scope + }; + angular.forEach(Developer.customProjectSubTabFactories, function (fn) { + if (angular.isFunction(fn)) { + var subtab = fn(context); + if (subtab) { + if (angular.isArray(subtab)) { + angular.forEach(subtab, function (t) { + answer.push(t); + }); + } + else { + answer.push(subtab); + } + } + } + }); + return activateCurrent(answer); + } + Developer.createProjectSubNavBars = createProjectSubNavBars; + function createProjectSettingsSubNavBars(projectName, jenkinsJobId) { + if (jenkinsJobId === void 0) { jenkinsJobId = null; } + if (!projectName) { + return []; + } + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName); + if (!jenkinsJobId) { + jenkinsJobId = projectName; + } + var answer = [ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "buildConfigEdit"), + label: "Core", + title: "View the core build configuration" + }, + { + href: projectSecretsLink(workspaceName, projectName), + label: "Secrets", + title: "View or change the secrets used to edit source code in the source control system" + }, + { + href: editPipelineLink(workspaceName, projectName), + label: "Pipeline", + title: "View the DevOps and pipeline configuration" + }, + { + isValid: function () { return forgeProjectHasBuilder("maven"); }, + href: editMavenBuildLink(workspaceName, projectName), + label: "Maven", + title: "View the Maven build configuration" + } + ]; + return activateCurrent(answer); + } + Developer.createProjectSettingsSubNavBars = createProjectSettingsSubNavBars; + function forgeProjectHasBuilder(name) { + var forgeProject = Kubernetes.inject("ForgeProject"); + if (forgeProject) { + return forgeProject.hasBuilder(name); + } + return false; + } + Developer.forgeProjectHasBuilder = forgeProjectHasBuilder; + function forgeProjectHasPerspective(name) { + var forgeProject = Kubernetes.inject("ForgeProject"); + if (forgeProject) { + return forgeProject.hasPerspective(name); + } + return false; + } + Developer.forgeProjectHasPerspective = forgeProjectHasPerspective; + function editPipelineLinkScope($scope) { + return editPipelineLink($scope.namespace, $scope.projectId || $scope.projectName || $scope.project); + } + Developer.editPipelineLinkScope = editPipelineLinkScope; + function createProjectLink(workspaceName) { + if (workspaceName === void 0) { workspaceName = null; } + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "/forge/createProject"); + } + Developer.createProjectLink = createProjectLink; + function editPipelineLink(workspaceName, projectName) { + return projectWorkspaceLink(workspaceName, projectName, "forge/command/devops-edit"); + } + Developer.editPipelineLink = editPipelineLink; + function editMavenBuildLink(workspaceName, projectName) { + return projectWorkspaceLink(workspaceName, projectName, "forge/command/fabric8-setup"); + } + Developer.editMavenBuildLink = editMavenBuildLink; + function projectSecretsLink(workspaceName, projectName) { + return projectWorkspaceLink(workspaceName, projectName, "forge/secrets", false); + } + Developer.projectSecretsLink = projectSecretsLink; + function secretsNamespaceLink(workspaceName, projectName, secretsNamespace) { + var prefix = projectWorkspaceLink(workspaceName, projectName, "") || "kubernetes"; + return UrlHelpers.join(prefix, "namespace", secretsNamespace, "secrets"); + } + Developer.secretsNamespaceLink = secretsNamespaceLink; + function projectWorkspaceLink(workspaceName, projectName, path, ignoreBlankProject) { + if (ignoreBlankProject === void 0) { ignoreBlankProject = true; } + if (ignoreBlankProject && !projectName) { + return ""; + } + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, path); + } + Developer.projectWorkspaceLink = projectWorkspaceLink; + Developer.customProjectSubTabFactories = []; + function createJenkinsBreadcrumbs(projectName, jobId, buildId) { + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var children = [ + { + id: "builds", + href: createBuildsLink(workspaceName, projectName, jobId), + label: "Builds", + title: "View the builds for this app" + } + ]; + if (buildId) { + children.push({ + id: "", + href: "", + label: "#" + buildId, + title: "Build #" + buildId + }); + } + return createProjectBreadcrumbs(projectName, children); + } + Developer.createJenkinsBreadcrumbs = createJenkinsBreadcrumbs; + function createJenkinsSubNavBars(projectName, jenkinsJobId, buildId, extraOption) { + if (extraOption === void 0) { extraOption = null; } + var answer = createProjectSubNavBars(projectName, jenkinsJobId); + if (extraOption) { + extraOption.active = true; + answer.push(extraOption); + } + return answer; + } + Developer.createJenkinsSubNavBars = createJenkinsSubNavBars; + function createEnvironmentSubNavBars($scope, $location, $routeParams) { + var ns = Kubernetes.currentKubernetesNamespace(); + var workspaceName = $routeParams.workspace; + var project = $routeParams.project; + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes"); + if (workspaceName && project) { + projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", project); + } + var namespacesLink = UrlHelpers.join(projectLink, "namespace"); + return activateCurrent([ + { + href: UrlHelpers.join(projectLink, "environments"), + label: "<< Back To App", + title: "Go back to the Dashboard for this App", + isValid: function () { return project; } + }, + { + href: UrlHelpers.join(namespacesLink, ns, "apps"), + label: "Overview", + class: "fa fa-list", + title: "Overview of all the apps for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "services"), + label: "Services", + class: "fa fa-plug", + title: "View the apps for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "replicationControllers"), + label: "Controllers", + class: "fa fa-clone", + title: "View the Replication Controllers for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "pods"), + label: "Pods", + class: "fa fa-puzzle-piece", + title: "View the pods for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "events"), + label: "Events", + class: "fa fa-newspaper-o", + title: "View the events for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "secrets"), + label: "Secrets", + class: "fa fa-key", + title: "View the secrets for this project" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes/hosts"), + label: "Nodes", + class: "fa fa-server", + title: "View the nodes for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "overview"), + label: "Diagram", + class: "fa fa-sitemap", + title: "View all the objects in this project and their relationship" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "angryPods"), + label: "Angry Pods", + class: "fa fa-gamepad", + title: "Try the Angry Pods game!" + }, + ]); + } + Developer.createEnvironmentSubNavBars = createEnvironmentSubNavBars; + function namespaceLink($scope, $routeParams, path) { + if (path === void 0) { path = null; } + var ns = Kubernetes.currentKubernetesNamespace(); + var workspaceName = $routeParams.workspace; + var project = $routeParams.project; + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes"); + if (workspaceName && project) { + projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", project); + } + return UrlHelpers.join(projectLink, "namespace", ns, path); + } + Developer.namespaceLink = namespaceLink; + /** + * Removes the URL query string if its inside the given text + */ + function trimQuery(text) { + if (text) { + var idx = text.indexOf("?"); + if (idx >= 0) { + return text.substring(0, idx); + } + } + return text; + } + function activateCurrent(navBarItems) { + navBarItems = _.compact(navBarItems); + var injector = HawtioCore.injector; + var $location = injector ? injector.get("$location") : null; + if ($location) { + var path = trimQuery($location.path()); + var found = false; + function makeActive(item) { + item.active = true; + found = true; + } + angular.forEach(navBarItems, function (item) { + if (item) { + if (angular.isFunction(item.isActive)) { + if (!found && item.isActive(item, path)) { + makeActive(item); + } + } + else { + var href = item.href; + var trimHref = trimQuery(href); + if (!found && trimHref && trimHref === path) { + makeActive(item); + } + } + } + }); + } + return navBarItems; + } + function processChildren(answer, children) { + if (children) { + if (angular.isArray(children)) { + answer = answer.concat(children); + } + else { + answer.push(children); + } + } + activateCurrent(answer); + return answer; + } +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// + +/// +/// +var Developer; +(function (Developer) { + Developer._module = angular.module(Developer.pluginName, ['hawtio-core', 'hawtio-ui', 'ui.codemirror', 'nvd3', 'treeControl']); + Developer.controller = PluginHelpers.createControllerFunction(Developer._module, Developer.pluginName); + Developer.route = PluginHelpers.createRoutingFunction(Developer.templatePath); + Developer._module.config(['$routeProvider', function ($routeProvider) { + $routeProvider.when(Developer.context, Developer.route('workspaces.html', false)) + .when("/namespaces", Developer.route('workspaces.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace'), Developer.route('projects.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/detail'), Developer.route('workspace.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/jenkinsJob'), Developer.route('jenkinsJobs.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects'), Developer.route('projects.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id'), Developer.route('environments.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/detail'), Kubernetes.route('buildConfig.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/builds'), Kubernetes.route('builds.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/environments'), Developer.route('environments.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/jenkinsJob/:job'), Developer.route('jenkinsJob.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/jenkinsJob/:job/log/:build'), Developer.route('jenkinsLog.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/jenkinsJob/:job/pipelines'), Developer.route('pipelines.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/jenkinsJob/:job/pipeline/:build'), Developer.route('pipeline.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/jenkinsJob/:job/metrics'), Developer.route('jenkinsMetrics.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/jenkinsMetrics'), Developer.route('jenkinsMetrics.html', false)) + .when(UrlHelpers.join(Developer.context, '/:namespace/projects/:id/tools'), Developer.route('tools.html', false)) + .when(UrlHelpers.join(Developer.context, '/:workspace/projects/:project/environments/:namespace'), Developer.route('environment.html', false)) + .when(UrlHelpers.join(Developer.context, '/:workspace/projects/:project/environments/:namespace'), Developer.route('environment.html', false)) + .when(UrlHelpers.join(Developer.context, '/Aggregate/overview'), Developer.route('addDataFile.html', false)) + .otherwise("/workspaces"); + }]); + Developer._module.run(['viewRegistry', 'ServiceRegistry', 'HawtioNav', 'KubernetesModel', '$templateCache', 'DataInfoModel', function (viewRegistry, ServiceRegistry, HawtioNav, KubernetesModel, $templateCache, DataInfoModel) { + Developer.log.debug("Running"); + viewRegistry['workspaces'] = Kubernetes.templatePath + 'layoutKubernetes.html'; + viewRegistry['namespaces'] = Kubernetes.templatePath + 'layoutKubernetes.html'; + var builder = HawtioNav.builder(); + var workspaces = builder.id('workspaces') + .href(function () { return Developer.context; }) + .title(function () { return '查看'; }) + .build(); + /* + var workspaceOverview = builder.id('workspaces') + .href(() => UrlHelpers.join(context, 'overview')) + .title(() => 'Workspace') + .build(); + */ + /* var dataadd = builder.id('dataadd') + .href(() => context) + .title(() => '汇总') + .build(); + */ + var Aggregate = builder.id('Aggregate;') + .rank(200) + .href(function () { return Developer.context; }) + .title(function () { return '数据汇总'; }) + .tabs(workspaces) + .build(); + HawtioNav.add(Aggregate); + }]); + Developer._module.filter('asTrustedHtml', ['$sce', function ($sce) { + return function (text) { + return $sce.trustAsHtml(text); + }; + }]); + hawtioPluginLoader.addModule(Developer.pluginName); + // for scroll-glue directive + hawtioPluginLoader.addModule('luegg.directives'); +})(Developer || (Developer = {})); + +/// +var Developer; +(function (Developer) { + Developer._module.controller('Developer.EnvironmentPanelController', ["$scope", "$element", "$location", "$routeParams", "KubernetesModel", "$http", "$timeout", "KubernetesState", "KubernetesApiURL", function ($scope, $element, $location, $routeParams, KubernetesModel, $http, $timeout, KubernetesState, KubernetesApiURL) { + $scope.envVersions = {}; + $scope.model = KubernetesModel; + $scope.env = $scope.$eval('env'); + $scope.buildConfig = $scope.$eval('entity'); + $scope.open = true; + $scope.toggle = function () { return $scope.open = !$scope.open; }; + var caches = {}; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + Developer.loadProjectVersions($scope, $element, $scope.buildConfig, $scope.env, $scope.env.namespace, $scope.envVersions, caches); + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.HomeController = Developer.controller("HomeController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.namespace = Kubernetes.currentKubernetesNamespace(); + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.JenkinsJobController = Developer.controller("JenkinsJobController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $routeParams["job"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.tableConfig = { + data: 'job.builds', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '$sortOrder', + displayName: 'Name', + cellTemplate: $templateCache.get("jenkinsBuildIdTemplate.html") + }, + { + field: '$buildLink', + displayName: 'Views', + cellTemplate: $templateCache.get("jenkinsBuildButtonsTemplate.html") + }, + { + field: '$duration', + displayName: 'Duration', + cellTemplate: $templateCache.get("jenkinsBuildDurationTemplate.html") + }, + { + field: '$timestamp', + displayName: 'Time Started', + cellTemplate: $templateCache.get("jenkinsBuildTimestampTemplate.html") + } + ] + }; + updateData(); + function updateData() { + if ($scope.jobId) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, UrlHelpers.join("job", $scope.jobId, "api/json?depth=1")); + if (url && (!$scope.job || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + Developer.enrichJenkinsJob(data, $scope.id, $scope.jobId); + if (Developer.hasObjectChanged(data, $scope.entityChangedCache)) { + Developer.log.info("entity has changed!"); + $scope.job = data; + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + else { + $scope.model.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.JenkinsJobsController = Developer.controller("JenkinsJobsController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.jenkins = null; + $scope.entityChangedCache = {}; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs(); + $scope.subTabConfig = Developer.createWorkspaceSubNavBars(); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.tableConfig = { + data: 'jenkins.jobs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'name', + displayName: 'Name', + cellTemplate: $templateCache.get("jenkinsJobNameTemplate.html") + }, + { + field: '$buildLink', + displayName: 'Views', + cellTemplate: $templateCache.get("jenkinsJobButtonsTemplate.html") + }, + { + field: '$lastSuccessfulBuildNumber', + displayName: 'Last Success', + cellTemplate: $templateCache.get("jenkinsLastSuccessTemplate.html") + }, + { + field: '$lastFailedlBuildNumber', + displayName: 'Last Failure', + cellTemplate: $templateCache.get("jenkinsLastFailureTemplate.html") + }, + { + field: '$duration', + displayName: 'Last Duration', + cellTemplate: $templateCache.get("jenkinsBuildDurationTemplate.html") + }, + { + field: '$timestamp', + displayName: 'Time Started', + cellTemplate: $templateCache.get("jenkinsBuildTimestampTemplate.html") + } + ] + }; + updateData(); + function updateData() { + // TODO only need depth 2 to be able to fetch the lastBuild + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, "api/json?depth=2"); + Developer.log.info(""); + if (url && (!$scope.jenkins || Kubernetes.keepPollingModel)) { + $http.get(url, Developer.jenkinsHttpConfig). + success(function (data, status, headers, config) { + if (data) { + Developer.enrichJenkinsJobs(data, $scope.id, $scope.id); + if (Developer.hasObjectChanged(data, $scope.entityChangedCache)) { + Developer.log.info("entity has changed!"); + $scope.jenkins = data; + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + }]); +})(Developer || (Developer = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes._module = angular.module(Kubernetes.pluginName, ['hawtio-core', 'hawtio-ui', 'ui.codemirror', 'ui.validate', 'kubernetesUI']); + Kubernetes.controller = PluginHelpers.createControllerFunction(Kubernetes._module, Kubernetes.pluginName); + Kubernetes.route = PluginHelpers.createRoutingFunction(Kubernetes.templatePath); + Kubernetes._module.config(['$routeProvider', function ($routeProvider) { + $routeProvider + .when(UrlHelpers.join(Kubernetes.context, '/pods'), Kubernetes.route('pods.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'replicationControllers'), Kubernetes.route('replicationControllers.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'services'), Kubernetes.route('services.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'events'), Kubernetes.route('events.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'apps'), Kubernetes.route('apps.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'apps/:namespace'), Kubernetes.route('apps.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'templates'), Kubernetes.route('templates.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'hosts'), Kubernetes.route('hosts.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'hosts/:id'), Kubernetes.route('host.html', true)) + .when(UrlHelpers.join(Kubernetes.context, 'pipelines'), Kubernetes.route('pipelines.html', false)) + .when(UrlHelpers.join(Kubernetes.context, 'overview'), Kubernetes.route('overview.html', true)) + .when(Kubernetes.context, { redirectTo: UrlHelpers.join(Kubernetes.context, 'replicationControllers') }); + angular.forEach([Kubernetes.context, "/workspaces/:workspace/projects/:project"], function (context) { + $routeProvider + .when(UrlHelpers.join(context, '/namespace/:namespace/podCreate'), Kubernetes.route('podCreate.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/podEdit/:id'), Kubernetes.route('podEdit.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/pods'), Kubernetes.route('pods.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/pods/:id'), Kubernetes.route('pod.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllers'), Kubernetes.route('replicationControllers.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllers/:id'), Kubernetes.route('replicationController.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllerCreate'), Kubernetes.route('replicationControllerCreate.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllerEdit/:id'), Kubernetes.route('replicationControllerEdit.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/secrets'), Kubernetes.route('secrets.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/secrets/:id'), Kubernetes.route('secret.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/secretCreate'), Kubernetes.route('secret.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/services'), Kubernetes.route('services.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/services/:id'), Kubernetes.route('service.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/serviceCreate'), Kubernetes.route('serviceCreate.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/serviceEdit/:id'), Kubernetes.route('serviceEdit.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/events'), Kubernetes.route('events.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/apps'), Kubernetes.route('apps.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/overview'), Kubernetes.route('overview.html', true)) + .when(UrlHelpers.join(context, '/namespace/:namespace/templates/:targetNamespace'), Kubernetes.route('templates.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace'), Kubernetes.route('apps.html', false)) + .when(UrlHelpers.join(context, 'builds'), Kubernetes.route('builds.html', false)) + .when(UrlHelpers.join(context, 'builds/:id'), Kubernetes.route('build.html', true)) + .when(UrlHelpers.join(context, 'buildLogs/:id'), Kubernetes.route('buildLogs.html', true)) + .when(UrlHelpers.join(context, 'buildConfigs'), Kubernetes.route('buildConfigs.html', false)) + .when(UrlHelpers.join(context, 'buildConfigs/:id'), Kubernetes.route('buildConfig.html', true)) + .when(UrlHelpers.join(context, 'buildConfigEdit/:id'), Kubernetes.route('buildConfigEdit.html', true)) + .when(UrlHelpers.join(context, 'deploymentConfigs'), Kubernetes.route('deploymentConfigs.html', false)) + .when(UrlHelpers.join(context, 'deploymentConfigs/:id'), Kubernetes.route('deploymentConfig.html', true)) + .when(UrlHelpers.join(context, 'imageRepositories'), Kubernetes.route('imageRepositories.html', false)); + }); + angular.forEach([Kubernetes.context, "/workspaces/:workspace", "/workspaces/:workspace/projects/:project"], function (context) { + $routeProvider + .when(UrlHelpers.join(context, 'buildConfigEdit'), Kubernetes.route('buildConfigEdit.html', true)) + .when(UrlHelpers.join(context, 'buildConfigEdit/:id'), Kubernetes.route('buildConfigEdit.html', true)) + .when(UrlHelpers.join(context, 'importProject'), Kubernetes.route('importProject.html', true)); + }); + }]); + Kubernetes._module.factory('AppLibraryURL', ['$rootScope', function ($rootScope) { + return UrlHelpers.join(Kubernetes.kubernetesApiUrl(), "/proxy", Kubernetes.kubernetesNamespacePath(), "/services/app-library"); + }]); + Kubernetes._module.factory('WikiGitUrlPrefix', function () { + return UrlHelpers.join(Kubernetes.kubernetesApiUrl(), "/proxy", Kubernetes.kubernetesNamespacePath(), "services/app-library"); + }); + Kubernetes._module.factory('wikiRepository', ["$location", "localStorage", function ($location, localStorage) { + return false; + }]); + Kubernetes._module.factory('ConnectDialogService', ['$rootScope', function ($rootScope) { + return { + dialog: new UI.Dialog(), + saveCredentials: false, + userName: null, + password: null, + jolokiaUrl: null, + containerName: null, + view: null + }; + }]); + Kubernetes._module.filter('kubernetesPageLink', function () { return Kubernetes.entityPageLink; }); + Kubernetes._module.filter('relativeTime', function () { + return function (date) { + return humandate.relativeTime(date); + }; + }); + Kubernetes._module.run(['viewRegistry', 'ServiceRegistry', 'HawtioNav', 'KubernetesModel', '$templateCache', function (viewRegistry, ServiceRegistry, HawtioNav, KubernetesModel, $templateCache) { + Kubernetes.log.debug("Running"); + viewRegistry['kubernetes'] = Kubernetes.templatePath + 'layoutKubernetes.html'; + var builder = HawtioNav.builder(); + var apps = builder.id('kube-apps') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'apps'); }) + .title(function () { return 'Apps'; }) + .build(); + var services = builder.id('kube-services') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'services'); }) + .title(function () { return 'Services'; }) + .build(); + var controllers = builder.id('kube-controllers') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'replicationControllers'); }) + .title(function () { return 'oracle服务'; }) + .build(); + var pods = builder.id('kube-pods') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'pods'); }) + .title(function () { return '测试页面'; }) + .build(); + var events = builder.id('kube-events') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'events'); }) + .title(function () { return '服务启动日志'; }) + .build(); + var hosts = builder.id('kube-hosts') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'hosts'); }) + .title(function () { return '集群节点'; }) + .build(); + var overview = builder.id('kube-overview') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'overview'); }) + .title(function () { return 'Diagram'; }) + .build(); + var builds = builder.id('kube-builds') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'builds'); }) + .title(function () { return 'Builds'; }) + .build(); + var buildConfigs = builder.id('kube-buildConfigs') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'buildConfigs'); }) + .title(function () { return 'Build Configs'; }) + .build(); + var deploys = builder.id('kube-deploys') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'deploymentConfigs'); }) + .title(function () { return 'Deploys'; }) + .build(); + var imageRepositories = builder.id('kube-imageRepositories') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'imageRepositories'); }) + .title(function () { return 'Registries'; }) + .build(); + var pipelines = builder.id('kube-pipelines') + .href(function () { return UrlHelpers.join(Kubernetes.context, 'pipelines'); }) + .title(function () { return 'Pipelines'; }) + .build(); + var repos = builder.id('kube-repos') + .href(function () { return "/forge/repos"; }) + .isValid(function () { return ServiceRegistry.hasService(Kubernetes.fabric8ForgeServiceName) && ServiceRegistry.hasService(Kubernetes.gogsServiceName); }) + .title(function () { return 'Repositories'; }) + .build(); + var mainTab = builder.id('kubernetes') + .rank(100) + .defaultPage({ + rank: 20, + isValid: function (yes, no) { + yes(); + } + }) + .href(function () { return Kubernetes.context; }) + .title(function () { return '服务集群'; }) + .tabs(controllers, events) + .build(); + HawtioNav.add(mainTab); + /* testKubernetesModel + HawtioNav.add({ + id: 'k8sAppSwitcher', + title: () => '', // not used as 'template' below overrides this + isValid: () => KubernetesModel.serviceApps.length > 0, + context: true, + template: () => $templateCache.get(UrlHelpers.join(templatePath, 'serviceApps.html')) + }); + */ + var projectsTab = builder.id('openshift') + .rank(100) + .href(function () { return UrlHelpers.join(Kubernetes.context, 'buildConfigs') + '?sub-tab=kube-buildConfigs'; }) + .title(function () { return 'Projects'; }) + .tabs(repos, buildConfigs, builds, deploys, imageRepositories) + .build(); + //HawtioNav.add(projectsTab); + }]); + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'KubernetesInit', + task: function (next) { + $.getScript('osconsole/config.js') + .done(function (script, textStatus) { + var config = Kubernetes.osConfig = window['OPENSHIFT_CONFIG']; + Kubernetes.log.debug("Fetched OAuth config: ", config); + var master = config.master_uri; + if (!master && config.api && config.api.k8s) { + var masterUri = new URI().host(config.api.k8s.hostPort).path("").query(""); + if (config.api.k8s.proto) { + masterUri.protocol(config.api.k8s.proto); + } + master = masterUri.toString(); + } + OSOAuthConfig = config.openshift; + GoogleOAuthConfig = config.google; + KeycloakConfig = config.keycloak; + if (OSOAuthConfig && !master) { + // TODO auth.master_uri no longer used right? + // master = OSOAuthConfig.master_uri; + if (!master) { + var oauth_authorize_uri = OSOAuthConfig.oauth_authorize_uri; + if (oauth_authorize_uri) { + var text = oauth_authorize_uri; + var idx = text.indexOf("://"); + if (idx > 0) { + idx += 3; + idx = text.indexOf("/", idx); + if (idx > 0) { + master = text.substring(0, ++idx); + } + } + } + } + } + if ((!Kubernetes.masterUrl || Kubernetes.masterUrl === "/") && (!master || master === "/")) { + // lets default the master to the current protocol and host/port + // in case the master url is "/" and we are + // serving up static content from inside /api/v1/namespaces/default/services/fabric8 or something like that + var href = location.href; + if (href) { + master = new URI(href).query("").path("").toString(); + } + } + if (master) { + Kubernetes.masterUrl = master; + next(); + return; + } + }) + .fail(function (response) { + Kubernetes.log.debug("Error fetching OAUTH config: ", response); + }) + .always(function () { + next(); + }); + } + }, true); + hawtioPluginLoader.addModule('ngResource'); + hawtioPluginLoader.addModule(Kubernetes.pluginName); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.FABRIC8_PROJECT_JSON = "fabric8ProjectJson"; + function byId(thing) { + return thing.id; + } + function createKey(namespace, id, kind) { + return (namespace || "") + "-" + (kind || 'undefined').toLowerCase() + '-' + (id || 'undefined').replace(/\./g, '-'); + } + function populateKey(item) { + var result = item; + result['_key'] = createKey(Kubernetes.getNamespace(item), Kubernetes.getName(item), Kubernetes.getKind(item)); + return result; + } + function populateKeys(items) { + var result = []; + angular.forEach(items, function (item) { + result.push(populateKey(item)); + }); + return result; + } + function selectPods(pods, namespace, labels) { + return pods.filter(function (pod) { + return Kubernetes.getNamespace(pod) === namespace && Kubernetes.selectorMatches(labels, Kubernetes.getLabels(pod)); + }); + } + /** + * The object which keeps track of all the pods, replication controllers, services and their associations + */ + var KubernetesModelService = (function () { + function KubernetesModelService() { + this.kubernetes = null; + this.apps = []; + this.services = []; + this.replicationcontrollers = []; + this.pods = []; + this.hosts = []; + //public namespaces = []; + this.routes = []; + this.templates = []; + this.redraw = false; + this.resourceVersions = {}; + // various views on the data + this.podsByHost = {}; + this.servicesByKey = {}; + this.replicationControllersByKey = {}; + this.podsByKey = {}; + this.appInfos = []; + this.appViews = []; + this.appFolders = []; + this.fetched = false; + this.buildconfigs = []; + this.events = []; + this.workspaces = []; + this.projects = []; + this.project = null; + } + Object.defineProperty(KubernetesModelService.prototype, "replicationControllers", { + get: function () { + return this.replicationcontrollers; + }, + set: function (replicationControllers) { + this.replicationcontrollers = replicationControllers; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(KubernetesModelService.prototype, "namespaces", { + get: function () { + return this.kubernetes.namespaces; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(KubernetesModelService.prototype, "showRunButton", { + get: function () { + if (Kubernetes.isOpenShift) { + return true; + } + return _.any(this.services, function (service) { + var name = Kubernetes.getName(service); + if (name === "templates") { + var podCounters = service.$podCounters; + return podCounters && (podCounters.valid || podCounters.ready); + } + else { + return false; + } + }); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(KubernetesModelService.prototype, "serviceApps", { + get: function () { + return _.filter(this.services, function (s) { + return s.$host && s.$serviceUrl && s.$podCount; + }); + }, + enumerable: true, + configurable: true + }); + KubernetesModelService.prototype.$keepPolling = function () { + return Kubernetes.keepPollingModel; + }; + KubernetesModelService.prototype.orRedraw = function (flag) { + this.redraw = this.redraw || flag; + }; + KubernetesModelService.prototype.getService = function (namespace, id) { + return this.servicesByKey[createKey(namespace, id, 'service')]; + }; + KubernetesModelService.prototype.getReplicationController = function (namespace, id) { + return this.replicationControllersByKey[createKey(namespace, id, 'replicationController')]; + }; + KubernetesModelService.prototype.getPod = function (namespace, id) { + return this.podsByKey[createKey(namespace, id, 'pod')]; + }; + KubernetesModelService.prototype.podsForNamespace = function (namespace) { + if (namespace === void 0) { namespace = this.currentNamespace(); } + return _.filter(this.pods, { namespace: namespace }); + }; + KubernetesModelService.prototype.getBuildConfig = function (name) { + return _.find(this.buildconfigs, { $name: name }); + }; + KubernetesModelService.prototype.getProject = function (name, ns) { + if (ns === void 0) { ns = this.currentNamespace(); } + var buildConfig = this.project; + if (!buildConfig) { + var text = localStorage[Kubernetes.FABRIC8_PROJECT_JSON]; + if (text) { + try { + buildConfig = angular.fromJson(text); + } + catch (e) { + Kubernetes.log.warn("Could not parse json for " + Kubernetes.FABRIC8_PROJECT_JSON + ". Was: " + text + ". " + e, e); + } + } + } + if (buildConfig && ns != Kubernetes.getNamespace(buildConfig) && name != buildConfig.$name) { + buildConfig = this.getBuildConfig(name); + } + return buildConfig; + }; + KubernetesModelService.prototype.setProject = function (buildConfig) { + this.project = buildConfig; + if (buildConfig) { + // lets store in local storage + var localStorage = Kubernetes.inject("localStorage"); + if (localStorage) { + localStorage[Kubernetes.FABRIC8_PROJECT_JSON] = angular.toJson(buildConfig); + } + } + }; + /** + * Returns the current selected namespace or the default namespace + */ + KubernetesModelService.prototype.currentNamespace = function () { + var answer = null; + if (this.kubernetes) { + answer = this.kubernetes.selectedNamespace; + } + return answer || Kubernetes.defaultNamespace; + }; + KubernetesModelService.prototype.updateIconUrlAndAppInfo = function (entity, nameField) { + var answer = null; + var id = Kubernetes.getName(entity); + entity.$iconUrl = Core.pathGet(entity, ['metadata', 'annotations', 'fabric8.' + id + '/iconUrl']); + entity.$info = Core.pathGet(entity, ['metadata', 'annotations', 'fabric8.' + id + '/summary']); + if (entity.$iconUrl) { + return; + } + if (id && nameField) { + (this.templates || []).forEach(function (template) { + var metadata = template.metadata; + if (metadata) { + var annotations = metadata.annotations || {}; + var iconUrl = annotations["fabric8." + id + "/iconUrl"] || annotations["fabric8/iconUrl"]; + if (iconUrl) { + (template.objects || []).forEach(function (item) { + var entityName = Kubernetes.getName(item); + if (id === entityName) { + entity.$iconUrl = iconUrl; + } + }); + } + } + }); + (this.appInfos || []).forEach(function (appInfo) { + var iconPath = appInfo.iconPath; + if (iconPath && !answer && iconPath !== "null") { + var iconUrl = Kubernetes.gitPathToUrl(iconPath); + var ids = Core.pathGet(appInfo, ["names", nameField]); + angular.forEach(ids, function (appId) { + if (appId === id) { + entity.$iconUrl = iconUrl; + entity.appPath = appInfo.appPath; + entity.$info = appInfo; + } + }); + } + }); + } + if (!entity.$iconUrl) { + entity.$iconUrl = Kubernetes.defaultIconUrl; + } + }; + KubernetesModelService.prototype.maybeInit = function () { + var _this = this; + this.fetched = true; + this.servicesByKey = {}; + this.podsByKey = {}; + this.replicationControllersByKey = {}; + this.pods.forEach(function (pod) { + if (!pod.kind) + pod.kind = "Pod"; + _this.podsByKey[pod._key] = pod; + var host = Kubernetes.getHost(pod); + pod.$labelsText = Kubernetes.labelsToString(Kubernetes.getLabels(pod)); + if (host) { + pod.$labelsText += Kubernetes.labelFilterTextSeparator + "host=" + host; + } + pod.$iconUrl = Kubernetes.defaultIconUrl; + _this.discoverPodConnections(pod); + pod.$containerPorts = []; + var podStatus = pod.status || {}; + var startTime = podStatus.startTime; + pod.$startTime = null; + if (startTime) { + pod.$startTime = new Date(startTime); + } + var createdTime = Kubernetes.getCreationTimestamp(pod); + pod.$createdTime = null; + pod.$age = null; + if (createdTime) { + pod.$createdTime = new Date(createdTime); + pod.$age = humandate.relativeTime(pod.$createdTime); + } + var ready = Kubernetes.isReady(pod); + pod.$ready = ready; + pod.$statusCss = Kubernetes.statusTextToCssClass(podStatus.phase, ready); + var maxRestartCount = 0; + angular.forEach(Core.pathGet(pod, ["status", "containerStatuses"]), function (status) { + var restartCount = status.restartCount; + if (restartCount) { + if (restartCount > maxRestartCount) { + maxRestartCount = restartCount; + } + } + }); + if (maxRestartCount) { + pod.$restartCount = maxRestartCount; + } + var imageNames = ""; + angular.forEach(Core.pathGet(pod, ["spec", "containers"]), function (container) { + var image = container.image; + if (image) { + if (!imageNames) { + imageNames = image; + } + else { + imageNames = imageNames + " " + image; + } + var idx = image.lastIndexOf(":"); + if (idx > 0) { + image = image.substring(0, idx); + } + var paths = image.split("/", 3); + if (paths.length) { + var answer = null; + if (paths.length == 3) { + answer = paths[1] + "/" + paths[2]; + } + else if (paths.length == 2) { + answer = paths[0] + "/" + paths[1]; + } + else { + answer = paths[0] + "/" + paths[1]; + } + container.$imageLink = UrlHelpers.join("https://registry.hub.docker.com/u/", answer); + } + } + angular.forEach(container.ports, function (port) { + var containerPort = port.containerPort; + if (containerPort) { + pod.$containerPorts.push(containerPort); + } + }); + }); + pod.$imageNames = imageNames; + var podStatus = podStatus; + var podSpec = (pod.spec || {}); + pod.$podIP = podStatus.podIP; + pod.$host = podSpec.host || podSpec.nodeName || podStatus.hostIP; + }); + this.services.forEach(function (service) { + if (!service.kind) + service.kind = "Service"; + _this.servicesByKey[service._key] = service; + var selector = Kubernetes.getSelector(service); + service.$pods = []; + if (!service.$podCounters) { + service.$podCounters = {}; + } + var podLinkUrl = UrlHelpers.join("/kubernetes/namespace", service.metadata.namespace, "pods"); + _.assign(service.$podCounters, selector ? Kubernetes.createPodCounters(selector, _this.pods, service.$pods, Kubernetes.labelsToString(selector, ","), podLinkUrl) : {}); + service.$podCount = service.$pods.length; + var selectedPods = service.$pods; + service.connectTo = selectedPods.map(function (pod) { + return pod._key; + }).join(','); + service.$labelsText = Kubernetes.labelsToString(Kubernetes.getLabels(service)); + _this.updateIconUrlAndAppInfo(service, "serviceNames"); + var spec = service.spec || {}; + service.$portalIP = spec.portalIP; + service.$selectorText = Kubernetes.labelsToString(spec.selector); + var ports = _.map(spec.ports || [], "port"); + service.$ports = ports; + service.$portsText = ports.join(", "); + var iconUrl = service.$iconUrl; + if (iconUrl && selectedPods) { + selectedPods.forEach(function (pod) { + pod.$iconUrl = iconUrl; + }); + } + service.$serviceUrl = Kubernetes.serviceLinkUrl(service); + }); + this.replicationControllers.forEach(function (replicationController) { + if (!replicationController.kind) + replicationController.kind = "ReplicationController"; + _this.replicationControllersByKey[replicationController._key] = replicationController; + var selector = Kubernetes.getSelector(replicationController); + replicationController.$pods = []; + replicationController.$podCounters = selector ? Kubernetes.createPodCounters(selector, _this.pods, replicationController.$pods) : null; + replicationController.$podCount = replicationController.$pods.length; + replicationController.$replicas = (replicationController.spec || {}).replicas; + var selectedPods = replicationController.$pods; + replicationController.connectTo = selectedPods.map(function (pod) { + return pod._key; + }).join(','); + replicationController.$labelsText = Kubernetes.labelsToString(Kubernetes.getLabels(replicationController)); + replicationController.metadata.labels = Kubernetes.labelToChinese(Kubernetes.getLabels(replicationController)); + _this.updateIconUrlAndAppInfo(replicationController, "replicationControllerNames"); + var iconUrl = replicationController.$iconUrl; + if (iconUrl && selectedPods) { + selectedPods.forEach(function (pod) { + pod.$iconUrl = iconUrl; + }); + } + }); + // services may not map to an icon but their pods may do via the RC + // so lets default it... + this.services.forEach(function (service) { + var iconUrl = service.$iconUrl; + var selectedPods = service.$pods; + if (selectedPods) { + if (!iconUrl || iconUrl === Kubernetes.defaultIconUrl) { + iconUrl = null; + selectedPods.forEach(function (pod) { + if (!iconUrl) { + iconUrl = pod.$iconUrl; + if (iconUrl) { + service.$iconUrl = iconUrl; + } + } + }); + } + } + }); + this.updateApps(); + var podsByHost = {}; + this.pods.forEach(function (pod) { + var host = Kubernetes.getHost(pod); + var podsForHost = podsByHost[host]; + if (!podsForHost) { + podsForHost = []; + podsByHost[host] = podsForHost; + } + podsForHost.push(pod); + }); + this.podsByHost = podsByHost; + var tmpHosts = []; + for (var hostKey in podsByHost) { + var hostPods = []; + var podCounters = Kubernetes.createPodCounters(function (pod) { return Kubernetes.getHost(pod) === hostKey; }, this.pods, hostPods, "host=" + hostKey); + var hostIP = null; + if (hostPods.length) { + var pod = hostPods[0]; + var currentState = pod.status; + if (currentState) { + hostIP = currentState.hostIP; + } + } + var hostDetails = { + name: hostKey, + id: hostKey, + elementId: hostKey.replace(/\./g, '_'), + hostIP: hostIP, + pods: hostPods, + kind: "Host", + $podCounters: podCounters, + $iconUrl: Kubernetes.hostIconUrl + }; + tmpHosts.push(hostDetails); + } + this.hosts = tmpHosts; + Kubernetes.enrichBuildConfigs(this.buildconfigs); + Kubernetes.enrichEvents(this.events, this); + }; + KubernetesModelService.prototype.updateApps = function () { + var _this = this; + try { + // lets create the app views by trying to join controllers / services / pods that are related + var appViews = []; + this.replicationControllers.forEach(function (replicationController) { + var name = Kubernetes.getName(replicationController); + var $iconUrl = replicationController.$iconUrl; + appViews.push({ + appPath: "/dummyPath/" + name, + $name: name, + $info: { + $iconUrl: $iconUrl + }, + $iconUrl: $iconUrl, + replicationControllers: [replicationController], + pods: replicationController.$pods || [], + services: [] + }); + }); + var noMatches = []; + this.services.forEach(function (service) { + // now lets see if we can find an app with an RC of the same selector + var matchesApp = null; + appViews.forEach(function (appView) { + appView.replicationControllers.forEach(function (replicationController) { + var repSelector = Kubernetes.getSelector(replicationController); + if (repSelector && + Kubernetes.selectorMatches(repSelector, Kubernetes.getSelector(service)) && + Kubernetes.getNamespace(service) === Kubernetes.getNamespace(replicationController)) { + matchesApp = appView; + } + }); + }); + if (matchesApp) { + matchesApp.services.push(service); + } + else { + noMatches.push(service); + } + }); + Kubernetes.log.debug("no matches: ", noMatches); + noMatches.forEach(function (service) { + var appView = _.find(appViews, function (appView) { + return _.any(appView.replicationControllers, function (rc) { + return _.startsWith(Kubernetes.getName(rc), Kubernetes.getName(service)); + }); + }); + if (appView) { + appView.services.push(service); + } + else { + var $iconUrl = service.$iconUrl; + appViews.push({ + appPath: "/dummyPath/" + name, + $name: name, + $info: { + $iconUrl: $iconUrl + }, + $iconUrl: $iconUrl, + replicationControllers: [], + pods: service.$pods || [], + services: [service] + }); + } + }); + angular.forEach(this.routes, function (route) { + var metadata = route.metadata || {}; + var spec = route.spec || {}; + var serviceName = Core.pathGet(spec, ["to", "name"]); + var host = spec.host; + var namespace = Kubernetes.getNamespace(route); + if (serviceName && host) { + var service = _this.getService(namespace, serviceName); + if (service) { + service.$host = host; + // TODO we could use some annotations / metadata to deduce what URL we should use to open this + // service in the console. For now just assume its http: + if (host) { + var hostUrl = host; + if (hostUrl.indexOf("://") < 0) { + hostUrl = "http://" + host; + } + service.$connectUrl = UrlHelpers.join(hostUrl, "/"); + } + // TODO definitely need that annotation, temp hack for apiman link + if (Kubernetes.getName(service) === 'apiman' && host) { + service.$connectUrl = new URI().host(service.$host) + .path('apimanui/index.html') + .query({}) + .hash(URI.encode(angular.toJson({ + backTo: new URI().toString(), + token: HawtioOAuth.getOAuthToken() + }))).toString(); + } + } + else { + Kubernetes.log.debug("Could not find service " + serviceName + " namespace " + namespace + " for route: " + metadata.name); + } + } + }); + appViews = _.sortBy(populateKeys(appViews), function (appView) { return appView._key; }); + ArrayHelpers.sync(this.appViews, appViews, '$name'); + if (this.appInfos && this.appViews) { + var folderMap = {}; + var folders = []; + var appMap = {}; + angular.forEach(this.appInfos, function (appInfo) { + if (!appInfo.$iconUrl && appInfo.iconPath && appInfo.iconPath !== "null") { + appInfo.$iconUrl = Kubernetes.gitPathToUrl(appInfo.iconPath); + } + var appPath = appInfo.appPath; + if (appPath) { + appMap[appPath] = appInfo; + var idx = appPath.lastIndexOf("/"); + var folderPath = ""; + if (idx >= 0) { + folderPath = appPath.substring(0, idx); + } + folderPath = Core.trimLeading(folderPath, "/"); + var folder = folderMap[folderPath]; + if (!folder) { + folder = { + path: folderPath, + expanded: true, + apps: [] + }; + folders.push(folder); + folderMap[folderPath] = folder; + } + folder.apps.push(appInfo); + } + }); + this.appFolders = _.sortBy(folders, "path"); + var apps = []; + var defaultInfo = { + $iconUrl: Kubernetes.defaultIconUrl + }; + angular.forEach(this.appViews, function (appView) { + try { + var appPath = appView.appPath; + /* + TODO + appView.$select = () => { + Kubernetes.setJson($scope, appView.id, $scope.model.apps); + }; + */ + var appInfo = angular.copy(defaultInfo); + if (appPath) { + appInfo = appMap[appPath] || appInfo; + } + if (!appView.$info) { + appView.$info = defaultInfo; + appView.$info = appInfo; + } + appView.id = appPath; + if (!appView.$name) { + appView.$name = appInfo.name || appView.$name; + } + if (!appView.$iconUrl) { + appView.$iconUrl = appInfo.$iconUrl; + } + apps.push(appView); + appView.$podCounters = Kubernetes.createAppViewPodCounters(appView); + appView.$podCount = (appView.pods || []).length; + appView.$replicationControllersText = (appView.replicationControllers || []).map(function (i) { return i["_key"]; }).join(" "); + appView.$servicesText = (appView.services || []).map(function (i) { return i["_key"]; }).join(" "); + appView.$serviceViews = Kubernetes.createAppViewServiceViews(appView); + } + catch (e) { + Kubernetes.log.warn("Failed to update appViews: " + e); + } + }); + //this.apps = apps; + this.apps = this.appViews; + } + } + catch (e) { + Kubernetes.log.warn("Caught error: " + e); + } + }; + KubernetesModelService.prototype.discoverPodConnections = function (entity) { + var info = Core.pathGet(entity, ["status", "info"]); + var hostPort = null; + var currentState = entity.status || {}; + var desiredState = entity.spec || {}; + var podId = Kubernetes.getName(entity); + var host = currentState["hostIP"]; + var podIP = currentState["podIP"]; + var hasDocker = false; + var foundContainerPort = null; + if (desiredState) { + var containers = desiredState.containers; + angular.forEach(containers, function (container) { + if (!hostPort) { + var ports = container.ports; + angular.forEach(ports, function (port) { + if (!hostPort) { + var containerPort = port.containerPort; + var portName = port.name; + var containerHostPort = port.hostPort; + if (containerPort === 8778 || "jolokia" === portName) { + if (containerPort) { + if (podIP) { + foundContainerPort = containerPort; + } + if (containerHostPort) { + hostPort = containerHostPort; + } + } + } + } + }); + } + }); + } + if (foundContainerPort && podId && Kubernetes.isRunning(currentState)) { + if (!Kubernetes.isOpenShift) { + // TODO temp workaround for k8s on GKE https://github.com/kubernetes/kubernetes/issues/17172 + entity.$jolokiaUrl = UrlHelpers.join(Kubernetes.masterApiUrl(), "api", Kubernetes.defaultApiVersion, "proxy", "namespaces", entity.metadata.namespace, "pods", + //"https:" + podId + ":" + foundContainerPort, + podId + ":" + foundContainerPort, "jolokia/"); + } + else { + entity.$jolokiaUrl = UrlHelpers.join(Kubernetes.masterApiUrl(), "api", Kubernetes.defaultApiVersion, "namespaces", entity.metadata.namespace, "pods", "https:" + podId + ":" + foundContainerPort, "proxy/jolokia/"); + } + } + }; + return KubernetesModelService; + }()); + Kubernetes.KubernetesModelService = KubernetesModelService; + function getTemplateService(model) { + var key = createKey('default', 'templates', 'service'); + var answer = model.servicesByKey[key]; + Kubernetes.log.debug("found template service: ", answer); + return answer; + } + /** + * Creates a model service which keeps track of all the pods, replication controllers and services along + * with their associations and status + */ + Kubernetes._module.factory('KubernetesModel', ['$rootScope', '$http', 'KubernetesApiURL', 'KubernetesState', 'WatcherService', '$location', '$resource', function ($rootScope, $http, AppLibraryURL, KubernetesState, watcher, $location, $resource) { + var $scope = new KubernetesModelService(); + $scope.kubernetes = KubernetesState; + // create all of our resource classes + var typeNames = watcher.getTypes(); + _.forEach(typeNames, function (type) { + var urlTemplate = Kubernetes.uriTemplateForKubernetesKind(type); + $scope[type + 'Resource'] = Kubernetes.createResource(type, urlTemplate, $resource, $scope); + }); + if (!Kubernetes.isOpenShift) { + // register custom URL factories for templates/projects + watcher.registerCustomUrlFunction(KubernetesAPI.WatchTypes.BUILD_CONFIGS, function (options) { + var templateService = getTemplateService($scope); + if (templateService) { + return UrlHelpers.join(templateService.proxyUrl, '/oapi/v1/namespaces/default/buildconfigs/'); + } + return null; + }); + // register custom URL factories for templates/projects + watcher.registerCustomUrlFunction(KubernetesAPI.WatchTypes.TEMPLATES, function (options) { + var templateService = getTemplateService($scope); + if (templateService) { + return UrlHelpers.join(templateService.proxyUrl, '/oapi/v1/namespaces/default/templates/'); + } + return null; + }); + } + // register for all updates on objects + watcher.registerListener(function (objects) { + var types = watcher.getTypes(); + _.forEach(types, function (type) { + switch (type) { + case Kubernetes.WatchTypes.SERVICES: + var items = populateKeys(objects[type]); + angular.forEach(items, function (item) { + item.proxyUrl = Kubernetes.kubernetesProxyUrlForService(Kubernetes.kubernetesApiUrl(), item); + }); + $scope[type] = items; + break; + case Kubernetes.WatchTypes.TEMPLATES: + case Kubernetes.WatchTypes.ROUTES: + case Kubernetes.WatchTypes.BUILDS: + case Kubernetes.WatchTypes.BUILD_CONFIGS: + case Kubernetes.WatchTypes.IMAGE_STREAMS: + // don't put a break here :-) + default: + $scope[type] = populateKeys(objects[type]); + } + Kubernetes.log.debug("Type: ", type, " object: ", $scope[type]); + }); + $scope.maybeInit(); + $rootScope.$broadcast('kubernetesModelUpdated', $scope); + Core.$apply($rootScope); + }); + // set the selected namespace if set in the location bar + // otherwise use whatever previously selected namespace is + // available + var search = $location.search(); + if ('namespace' in search) { + watcher.setNamespace(search['namespace']); + } + function selectPods(pods, namespace, labels) { + return pods.filter(function (pod) { + return Kubernetes.getNamespace(pod) === namespace && Kubernetes.selectorMatches(labels, Kubernetes.getLabels(pod)); + }); + } + return $scope; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + function clickApprove(element, url) { + var $scope = angular.element(element).scope(); + if ($scope) { + $scope.approve(url, element.text); + } + } + Developer.clickApprove = clickApprove; + Developer.JenkinsLogController = Developer._module.controller("Developer.JenkinsLogController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "$modal", "KubernetesApiURL", "ServiceRegistry", "$element", function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, $modal, KubernetesApiURL, ServiceRegistry, $element) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.selectedBuild = $scope.$eval('build') || $scope.$eval('selectedBuild'); + $scope.id = $scope.$eval('build.id') || $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + $element.on('$destroy', function () { + $scope.$destroy(); + }); + $scope.log = { + html: "", + start: 0, + firstIdx: null + }; + $scope.$on('kubernetesModelUpdated', function () { + updateJenkinsLink(); + Core.$apply($scope); + }); + $scope.$on('jenkinsSelectedBuild', function (event, build) { + Developer.log.info("==== jenkins build selected! " + build.id + " " + build.$jobId); + $scope.selectedBuild = build; + }); + $scope.$watch('selectedBuild', function (selectedBuild) { + Developer.log.info("Selected build updated: ", selectedBuild); + $scope.fetch(); + }); + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createJenkinsBreadcrumbs($scope.id, getJobId(), getBuildId()); + $scope.subTabConfig = Developer.createJenkinsSubNavBars($scope.id, getJobId(), getBuildId(), { + label: "Log", + title: "Views the logs of this build" + }); + function getJobId() { + // lets allow the parent scope to be used too for when this is used as a panel + return $routeParams["job"] || ($scope.selectedBuild || {}).$jobId; + } + $scope.getJobId = getJobId; + function getBuildId() { + // lets allow the parent scope to be used too for when this is used as a panel + return $routeParams["build"] || ($scope.selectedBuild || {}).id; + } + $scope.getBuildId = getBuildId; + function updateJenkinsLink() { + var jenkinsUrl = Developer.jenkinsLink(); + if (jenkinsUrl) { + $scope.$viewJenkinsBuildLink = UrlHelpers.join(jenkinsUrl, "job", getJobId(), getBuildId()); + $scope.$viewJenkinsLogLink = UrlHelpers.join($scope.$viewJenkinsBuildLink, "console"); + } + } + var querySize = 50000; + $scope.approve = function (url, operation) { + var modal = $modal.open({ + templateUrl: UrlHelpers.join(Developer.templatePath, 'jenkinsApproveModal.html'), + controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) { + $scope.operation = operation; + $scope.header = operation + "?"; + $scope.ok = function () { + modal.close(); + postToJenkins(url, operation); + }; + $scope.cancel = function () { + modal.dismiss(); + }; + }] + }); + }; + function postToJenkins(uri, operation) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, uri); + if (url) { + var body = null; + var config = { + headers: {} + }; + Developer.log.info("posting to jenkinsUrl: " + url); + $http.post(url, body, config). + success(function (data, status, headers, config) { + Developer.log.info("Managed to " + operation + " at " + url); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed " + operation + " job at " + url + " " + data + " " + status); + }); + } + else { + Developer.log.warn("Cannot post to jenkins URI: " + uri + " as no jenkins found!"); + } + } + $scope.$keepPolling = function () { return Kubernetes.keepPollingModel; }; + $scope.fetch = PollHelpers.setupPolling($scope, function (next) { + if ($scope.$eval('hideLogs && !build.building')) { + Developer.log.debug("Log hidden, not fetching logs"); + return; + } + else { + Developer.log.debug("Fetching logs for build: ", $scope.$eval('build')); + } + var buildId = getBuildId(); + var jobId = getJobId(); + //log.info("=== jenkins log querying job " + jobId + " build " + buildId + " selected build " + $scope.selectedBuild); + if (jobId && buildId) { + if ($scope.buildId !== buildId || $scope.jobId !== jobId) { + // lets clear the query + $scope.log = { + html: "", + start: 0, + firstIdx: null + }; + } + $scope.buildId = buildId; + $scope.jobId = jobId; + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, UrlHelpers.join("job", jobId, buildId, "fabric8/logHtml?tail=1&start=" + $scope.log.start + "&size=" + querySize)); + if ($scope.log.firstIdx !== null) { + url += "&first=" + $scope.log.firstIdx; + } + if (url && (!$scope.log.fetched || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + var replaceClusterIPsInHtml = replaceClusterIpFunction(); + if (!$scope.log.logs) { + $scope.log.logs = []; + } + var lines = data.lines; + var returnedLength = data.returnedLength; + var logLength = data.logLength; + var returnedStart = data.start; + var earlierLog = false; + if (angular.isDefined(returnedStart)) { + earlierLog = returnedStart < $scope.log.start; + } + var lineSplit = data.lineSplit; + // log.info("start was: " + $scope.log.start + " first: " + $scope.log.firstIdx + " => returnedLength: " + returnedLength + " logLength: " + logLength + " returnedStart: " + returnedStart + " earlierLog: " + earlierLog + " lineSplit: " + lineSplit); + if (lines) { + var currentLogs = $scope.log.logs; + // lets re-join split lines + if (lineSplit && currentLogs.length) { + var lastIndex; + var restOfLine; + if (earlierLog) { + lastIndex = 0; + restOfLine = lines.pop(); + if (restOfLine) { + currentLogs[lastIndex] = replaceClusterIPsInHtml(restOfLine + currentLogs[lastIndex]); + } + } + else { + lastIndex = currentLogs.length - 1; + restOfLine = lines.shift(); + if (restOfLine) { + currentLogs[lastIndex] = replaceClusterIPsInHtml(currentLogs[lastIndex] + restOfLine); + } + } + } + for (var i = 0; i < lines.length; i++) { + lines[i] = replaceClusterIPsInHtml(lines[i]); + } + if (earlierLog) { + $scope.log.logs = lines.concat(currentLogs); + } + else { + $scope.log.logs = currentLogs.concat(lines); + } + } + var moveForward = true; + if (angular.isDefined(returnedStart)) { + if (returnedStart > $scope.log.start && $scope.log.start === 0) { + // we've jumped to the end of the file to read the tail of it + $scope.log.start = returnedStart; + $scope.log.firstIdx = returnedStart; + } + else if ($scope.log.firstIdx === null) { + // lets remember where the first request started + $scope.log.firstIdx = returnedStart; + } + else if (returnedStart < $scope.log.firstIdx) { + // we've got an earlier bit of the log + // after starting at the tail + // so lets move firstIdx backwards and leave start as it is (at the end of the file) + $scope.log.firstIdx = returnedStart; + moveForward = false; + } + } + if (moveForward && returnedLength && !earlierLog) { + $scope.log.start += returnedLength; + if (logLength && $scope.log.start > logLength) { + $scope.log.start = logLength; + } + } + updateJenkinsLink(); + } + $scope.log.fetched = true; + // Core.$apply($scope); + next(); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + next(); + }); + } + } + else { + $scope.log.fetched = true; + Core.$apply($scope); + next(); + } + }); + if (angular.isFunction($scope.fetch)) { + $scope.fetch(); + } + function replaceClusterIpFunction() { + function createReplaceFunction(from, to) { + return function (text) { return replaceText(text, from, to); }; + } + var replacements = []; + angular.forEach($scope.model.services, function (service) { + var $portalIP = service.$portalIP; + var $serviceUrl = service.$serviceUrl; + var $portsText = service.$portsText; + if ($portalIP && $serviceUrl) { + var idx = $serviceUrl.indexOf("://"); + if (idx > 0) { + var replaceWith = $serviceUrl.substring(idx, $serviceUrl.length); + if (!replaceWith.endsWith("/")) { + replaceWith += "/"; + } + if (replaceWith.length > 4) { + replacements.push(createReplaceFunction("://" + $portalIP + "/", replaceWith)); + if ($portsText) { + var suffix = ":" + $portsText; + var serviceWithPort = replaceWith.substring(0, replaceWith.length - 1); + if (!serviceWithPort.endsWith(suffix)) { + serviceWithPort += suffix; + } + serviceWithPort += "/"; + replacements.push(createReplaceFunction("://" + $portalIP + ":" + $portsText + "/", serviceWithPort)); + } + } + } + } + }); + function addReplaceFn(from, to) { + replacements.push(function (text) { + return replaceText(text, from, to); + }); + } + addReplaceFn("[INFO]", "[INFO]"); + addReplaceFn("[WARN]", "[WARN]"); + addReplaceFn("[WARNING]", "[WARNING]"); + addReplaceFn("[ERROR]", "[ERROR]"); + addReplaceFn("FAILURE", "FAILURE"); + addReplaceFn("SUCCESS", "SUCCESS"); + // lets try convert the Proceed / Abort links + replacements.push(function (text) { + var prefix = "= 0) { + idx = text.indexOf(prefix, idx); + if (idx >= 0) { + var start = idx + prefix.length; + var endQuote = text.indexOf("'", start + 1); + if (endQuote <= 0) { + break; + } + var endDoubleQuote = text.indexOf('"', endQuote + 1); + if (endDoubleQuote <= 0) { + break; + } + var url = text.substring(start, endQuote); + // TODO using $compile is a tad complex, for now lets cheat with a little onclick ;) + //text = text.substring(0, idx) + " '" + to + "'"); + var idx = 0; + while (true) { + idx = text.indexOf(from, idx); + if (idx >= 0) { + text = text.substring(0, idx) + to + text.substring(idx + from.length); + idx += to.length; + } + else { + break; + } + } + } + return text; + } + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.JenkinsMetricsController = Developer.controller("JenkinsMetricsController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $routeParams["job"]; + $scope.schema = KubernetesSchema; + $scope.jenkins = null; + $scope.entityChangedCache = {}; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.options = { + chart: { + type: 'discreteBarChart', + autorefresh: false, + height: 450, + margin: { + top: 20, + right: 20, + bottom: 60, + left: 45 + }, + clipEdge: true, + staggerLabels: false, + transitionDuration: 500, + stacked: false, + interactive: true, + tooltip: { + enabled: true, + contentGenerator: function (args) { + var data = args.data || {}; + return data.tooltip; + }, + }, + color: function (d, i) { + return d.color; + }, + xAxis: { + axisLabel: 'Builds', + showMaxMin: false, + tickFormat: function (d) { + return "#" + d; + } + }, + yAxis: { + axisLabel: 'Build Duration (seconds)', + tickFormat: function (d) { + return d3.format(',.1f')(d); + } + } + } + }; + $scope.data = []; + updateData(); + function barColourForBuildResult(result) { + if (result) { + if (result === "FAILURE" || result === "FAILED") { + return "red"; + } + else if (result === "ABORTED" || result === "INTERUPTED") { + return "tan"; + } + else if (result === "SUCCESS") { + return "green"; + } + else if (result === "NOT_STARTED") { + return "lightgrey"; + } + } + return "darkgrey"; + } + function updateChartData() { + var useSingleSet = true; + var buildsSucceeded = []; + var buildsFailed = []; + var successBuildKey = "Succeeded builds"; + var failedBuildKey = "Failed builds"; + if (useSingleSet) { + successBuildKey = "Builds"; + } + var count = 0; + var builds = _.sortBy($scope.metrics.builds || [], "number"); + angular.forEach(builds, function (build) { + var x = build.number; + var y = build.duration / 1000; + var date = Developer.asDate(build.timeInMillis); + var result = build.result || "NOT_STARTED"; + var color = barColourForBuildResult(result); + var iconClass = Developer.createBuildStatusIconClass(result); + var tooltip = '

' + build.displayName + '

' + + '

duration: ' + y + ' seconds

'; + if (date) { + tooltip += '

started: ' + date + '

'; + } + if (result) { + tooltip += '

result: ' + result + '

'; + } + if (x) { + var data = buildsSucceeded; + var key = successBuildKey; + if (!successBuildKey && (!result || !result.startsWith("SUCC"))) { + data = buildsFailed; + key = failedBuildKey; + } + data.push({ + tooltip: tooltip, + color: color, + x: x, y: y }); + } + }); + $scope.data = []; + if (buildsSucceeded.length) { + $scope.data.push({ + key: successBuildKey, + values: buildsSucceeded + }); + } + if (buildsFailed.length) { + $scope.data.push({ + key: failedBuildKey, + values: buildsFailed + }); + } + $scope.api.updateWithData($scope.data); + $timeout(function () { + $scope.api.update(); + }, 50); + } + function updateData() { + var metricsPath = $scope.jobId ? UrlHelpers.join("job", $scope.jobId, "fabric8/metrics") : "fabric8/metrics"; + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, metricsPath); + Developer.log.info(""); + if (url && (!$scope.jenkins || Kubernetes.keepPollingModel)) { + $http.get(url, Developer.jenkinsHttpConfig). + success(function (data, status, headers, config) { + if (data) { + if (Developer.hasObjectChanged(data, $scope.entityChangedCache)) { + Developer.log.info("entity has changed!"); + $scope.metrics = data; + updateChartData(); + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.NavBarController = Developer.controller("NavBarController", ["$scope", "$location", "$routeParams", "$timeout", "KubernetesApiURL", + function ($scope, $location, $routeParams, $timeout) { + $scope.isValid = function (item) { + if (item) { + var value = item.isValid; + if (angular.isFunction(value)) { + return value(item); + } + else { + return angular.isUndefined(value) || value; + } + } + return false; + }; + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.PipelineController = Developer.controller("PipelineController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) { + $scope.kubernetes = KubernetesState; + $scope.kubeModel = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $routeParams["job"]; + $scope.buildId = $routeParams["build"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + $scope.model = { + stages: null + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + if ($scope.jobId) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, UrlHelpers.join("job", $scope.jobId, $scope.buildId, "fabric8/stages/")); + if (url && (!$scope.model.stages || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + Developer.enrichJenkinsStages(data, $scope.id, $scope.jobId); + if (Developer.hasObjectChanged(data, $scope.entityChangedCache)) { + Developer.log.info("entity has changed!"); + $scope.build = data; + $scope.model.stages = data.stages; + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + $scope.model.fetched = true; + }); + } + } + else { + $scope.model.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer._module.directive("pipelineView", function () { + return { + templateUrl: Developer.templatePath + 'pipelineView.html' + }; + }); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.PipelinesController = Developer._module.controller("Developer.PipelinesController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", "$element", function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry, $element) { + $scope.kubernetes = KubernetesState; + $scope.kubeModel = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $scope.jobId || $routeParams["job"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + $element.on('$destroy', function () { + $scope.$destroy(); + }); + $scope.model = { + job: null, + pendingOnly: $scope.pendingPipelinesOnly + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.$watch('model.pendingOnly', function ($event) { + updateData(); + }); + $scope.selectBuild = function (build) { + var id = build.id; + if (id) { + if (id !== $scope.selectedBuildId) { + $scope.selectedBuildId = id; + $scope.$broadcast("jenkinsSelectedBuild", build); + } + } + }; + var updateData = _.debounce(function () { + var entity = $scope.entity; + if ($scope.jobId) { + if ((!entity || entity.$jenkinsJob)) { + var queryPath = "fabric8/stages/"; + if ($scope.model.pendingOnly) { + queryPath = "fabric8/pendingStages/"; + } + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, UrlHelpers.join("job", $scope.jobId, queryPath)); + if (url && (!$scope.model.job || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + Developer.enrichJenkinsPipelineJob(data, $scope.id, $scope.jobId); + if (Developer.hasObjectChanged(data, $scope.entityChangedCache)) { + Developer.log.info("entity has changed!"); + $scope.model.job = data; + var builds = data.builds; + if (builds && builds.length) { + $scope.selectBuild(builds[0]); + } + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + $scope.model.fetched = true; + }); + } + } + else { + if ($scope.model) { + Kubernetes.enrichBuilds($scope.kubeModel.builds); + var builds = []; + angular.forEach($scope.kubeModel.builds, function (build) { + var labels = Kubernetes.getLabels(build); + var app = labels["app"]; + if (app === $scope.projectId) { + builds.push(build); + } + }); + builds = _.sortBy(builds, "$creationDate").reverse(); + var allBuilds = builds; + if (allBuilds.length > 1) { + builds = _.filter(allBuilds, function (b) { return !b.$creationDate; }); + if (!builds.length) { + builds = [allBuilds[0]]; + } + } + var pipelines = []; + angular.forEach(builds, function (build) { + var buildStatus = build.status || {}; + var result = buildStatus.phase || ""; + var resultUpperCase = result.toUpperCase(); + var description = ""; + var $viewLink = build.$viewLink; + var $logLink = build.$logsLink; + var $timestamp = build.$creationDate; + var duration = buildStatus.duration; + if (duration) { + // 17s = 17,000,000,000 on openshift + duration = duration / 1000000; + } + var displayName = Kubernetes.getName(build); + var $iconClass = Developer.createBuildStatusIconClass(resultUpperCase); + var $backgroundClass = Developer.createBuildStatusBackgroundClass(resultUpperCase); + var stage = { + stageName: "OpenShift Build", + $viewLink: $viewLink, + $logLink: $logLink, + $startTime: $timestamp, + duration: duration, + status: result, + $iconClass: $iconClass, + $backgroundClass: $backgroundClass + }; + var pipeline = { + description: description, + displayName: displayName, + $viewLink: $viewLink, + $logLink: $logLink, + $timestamp: $timestamp, + duration: duration, + stages: [stage] + }; + pipelines.push(pipeline); + }); + // lets filter the OpenShift builds and make a pipeline from that + $scope.model.job = { + $jobId: $scope.jobId, + $project: $scope.projectId, + builds: pipelines + }; + } + $scope.model.fetched = true; + Core.$apply($scope); + } + } + else { + $scope.model.fetched = true; + Core.$apply($scope); + } + }, 50); + updateData(); + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.ProjectController = Developer.controller("ProjectController", ["$scope", "$element", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, $element, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_BuildConfig; + $scope.entityChangedCache = {}; + $scope.envVersionsCache = {}; + $scope.envNSCaches = {}; + $scope.envVersions = {}; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = []; //Developer.createProjectBreadcrumbs($scope.id); + updateTabs(); + // this is used for the pendingPipelines view + $scope.jobId = $scope.id; + $scope.pendingPipelinesOnly = true; + $scope.$on('jenkinsSelectedBuild', function (event, build) { + $scope.selectedBuild = build; + }); + // TODO this should be unnecessary but seems sometiems this watch doesn't always trigger unless you hit reload on this page + if ($scope.model.buildconfigs) { + onBuildConfigs($scope.model.buildconfigs); + } + Kubernetes.watch($scope, $element, "buildconfigs", $scope.namespace, onBuildConfigs); + function onBuildConfigs(buildConfigs) { + angular.forEach(buildConfigs, function (data) { + var name = Kubernetes.getName(data); + if (name === $scope.id) { + var sortedBuilds = null; + Kubernetes.enrichBuildConfig(data, sortedBuilds); + if (Developer.hasObjectChanged(data, $scope.entityChangedCache)) { + Developer.log.info("entity has changed!"); + $scope.entity = data; + $scope.entity.$build = (data.$fabric8CodeViews || {})['fabric8.link.browseGogs.view']; + $scope.model.setProject($scope.entity); + } + updateEnvironmentWatch(); + updateTabs(); + } + }); + $scope.model.fetched = true; + Core.$apply($scope); + } + /** + * We have updated the entity so lets make sure we are watching all the environments to find + * the project versions for each namespace + */ + function updateEnvironmentWatch() { + var project = $scope.entity; + if (project) { + var jenkinsJob = project.$jenkinsJob; + if (jenkinsJob) { + var buildsTab = _.find($scope.subTabConfig, { id: "builds" }); + if (buildsTab) { + buildsTab["href"] = UrlHelpers.join("/workspaces", Kubernetes.currentKubernetesNamespace(), "projects", $scope.id, "jenkinsJob", jenkinsJob); + } + } + angular.forEach(project.environments, function (env) { + var ns = env.namespace; + var caches = $scope.envNSCaches[ns]; + if (!caches) { + caches = {}; + $scope.envNSCaches[ns] = caches; + Developer.loadProjectVersions($scope, $element, project, env, ns, $scope.envVersions, caches); + } + }); + } + } + function updateTabs() { + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, null, $scope); + } + }]); +})(Developer || (Developer = {})); + +/// +var Developer; +(function (Developer) { + Developer._module.controller('Developer.ProjectSelector', ['$scope', '$routeParams', 'KubernetesModel', function ($scope, $routeParams, KubernetesModel) { + var projectId = $routeParams['projectId'] || $routeParams['project'] || $routeParams['id']; + if (projectId) { + $scope.projectId = projectId; + $scope.model = KubernetesModel; + $scope.$watch('model.buildconfigs', function (buildconfigs) { + $scope.projects = buildconfigs; + }); + } + else { + Developer.log.info("no project ID in routeParams: ", $routeParams); + } + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.ProjectsController = Developer.controller("ProjectsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.tableConfig = { + data: 'model.buildconfigs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '$name', + displayName: 'Name', + cellTemplate: $templateCache.get("idTemplate.html") + }, + /* + { + field: 'spec.source.type', + displayName: 'Source' + }, + */ + { + field: 'spec.source.git.uri', + displayName: 'Repository' + }, + /* + { + field: 'spec.strategy.type', + displayName: 'Strategy' + }, + { + field: 'spec.strategy.stiStrategy.image', + displayName: 'Source Image' + }, + { + field: 'spec.output.imageTag', + displayName: 'Output Image' + }, + */ + { + field: 'metadata.description', + displayName: 'Description' + }, + { + field: '$creationDate', + displayName: 'Created', + cellTemplate: $templateCache.get("creationTimeTemplate.html") + }, + { + field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs(); + $scope.subTabConfig = Developer.createWorkspaceSubNavBars(); + // TODO + //$scope.isLoggedIntoGogs = Forge.isLoggedIntoGogs; + $scope.deletePrompt = function (selected) { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, function () { + deleteSelected(selected, selected.shift()); + }); + } + else { + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Apps', + action: 'The following Apps will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + var jenkinsJob = selection.$jenkinsJob; + var publicJenkinsUrl = Developer.jenkinsLink(); + //var jenkinsUrl = Core.pathGet(selection, ["$fabric8Views", "fabric8.link.jenkins.job", "url"]); + if (name) { + console.log("About to delete build config: " + name); + var url = Kubernetes.buildConfigRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to delete build config on " + url + " " + data + " " + status); + nextCallback(); + }); + } + else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + if (jenkinsJob && publicJenkinsUrl) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(Developer.jenkinsServiceNameAndPort, UrlHelpers.join("job", jenkinsJob, "doDelete")); + var body = ""; + var config = { + headers: { + 'Content-Type': "text/plain" + } + }; + Developer.log.info("posting to jenkinsUrl: " + url); + $http.post(url, body, config). + success(function (data, status, headers, config) { + Developer.log.info("Managed to delete " + url); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to delete jenkins job at " + url + " " + data + " " + status); + }); + } + } + /* + $scope.$keepPolling = () => Kubernetes.keepPollingModel; + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + var url = Kubernetes.buildConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + var sortedBuilds = null; + $scope.buildConfigs = Kubernetes.enrichBuildConfigs(data.items, sortedBuilds); + $scope.model.fetched = true; + Core.$apply($scope); + next(); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + next(); + }); + }); + + $scope.fetch(); + */ + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.WorkspaceController = Developer.controller("WorkspaceController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["namespace"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.kubernetes_Namespace; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createWorkspaceBreadcrumbs(); + $scope.subTabConfig = Developer.createWorkspaceSubNavBars(); + $scope.$keepPolling = function () { return Kubernetes.keepPollingModel; }; + $scope.fetch = PollHelpers.setupPolling($scope, function (next) { + $scope.item = null; + if ($scope.id) { + var url = UrlHelpers.join(Kubernetes.resourcesUriForKind("Projects"), $scope.id); + Developer.log.info("Loading url: " + url); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = Developer.enrichWorkspace(data); + } + $scope.model.fetched = true; + Core.$apply($scope); + next(); + }). + error(function (data, status, headers, config) { + Developer.log.warn("Failed to load " + url + " " + data + " " + status); + next(); + }); + } + else { + $scope.model.fetched = true; + Core.$apply($scope); + next(); + } + }); + $scope.fetch(); + }]); +})(Developer || (Developer = {})); + +/// +/// +/// +/// +/// +var Developer; +(function (Developer) { + Developer.WorkspacesController = Developer.controller("WorkspacesController", ["$scope", "OracleStatusModel", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "DataInfoModel", "$interval", + function ($scope, OracleStatusModel, KubernetesModel, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, DataInfoModel, $interval) { + $scope.model = DataInfoModel; + $scope.items = []; + $scope.localitems = []; + var rootPath = ""; + var FilterList = { + length: 0 + }; + update(); + $scope.treeOptions = { + nodeChildren: "children", + dirSelectable: true, + multiSelection: false, + injectClasses: { + ul: "a1", + li: "a2", + liSelected: "a7", + iExpanded: "a3", + iCollapsed: "a4", + iLeaf: "a5", + label: "a6", + labelSelected: "a8" + } + }; + $scope.treeOptionss = { + nodeChildren: "children", + dirSelectable: true, + multiSelection: true, + injectClasses: { + ul: "a1", + li: "a2", + liSelected: "a7", + iExpanded: "a3", + iCollapsed: "a4", + iLeaf: "a5", + label: "a6", + labelSelected: "a8" + } + }; + $scope.showSelected = function (node, selected) { + $scope.model.serveritems = []; + var array = new Array(); + if (selected) { + if (node.children.length > 0) { + array.unshift(node); + while (array.length > 0) { + var childNode = array.pop(); + if (childNode.children.length > 0) { + for (var i = 0; i < childNode.children.length; i++) + array.unshift(childNode.children[i]); + } + else { + if (childNode.hasOwnProperty("path")) + $scope.model.serveritems.push(childNode); + } + } + } + else { + if (node.hasOwnProperty("path")) + $scope.model.serveritems.push(node); + } + } + }; + $scope.dataForTheTree = $scope.model.serverdata; + $scope.dataForTheTreeLocal = $scope.model.localdata; + $scope.$watch('model.serverdata', function (newValue, oldValue) { + if (newValue) { + $scope.dataForTheTree = $scope.model.serverdata; + } + }); + $scope.$watch('model.localdata', function (newValue, oldValue) { + if (newValue) { + $scope.dataForTheTreeLocal = $scope.model.localdata; + } + }); + $scope.upLoadXMLFile = function (files) { + FilterList.length = 0; + if (files.length > 0) { + var j = 0; + for (var i = 0; i < files.length; i++) { + if (files[i].name.indexOf("data.xml") != -1) { + //console.log(files[i]); + rootPath = files[i].webkitRelativePath.replace(/\/data.xml$/, ""); + var reader = new FileReader(); + var resultString = "{\"name\": \"数据\", \"children\":["; + reader.onload = function () { + var str = event.target.result; + // alert(str); + var item = ""; + var itemEnd = ""; + // ´ý·µ»ØµÄ½á¹û£º + if (str != undefined) { + // Õû¸öxml ÍêÕûÊý¾Ý£ºxmldata + var xmldata = str.toString(); + // °´¶ÔÏó·ÖµÄÊý¾Ý£º + var itemArray = xmldata.split(item); + var itemsize = itemArray.length; + for (var k = 1; k < itemsize; k++) { + var itemvalue = itemArray[k].split(itemEnd); + // province + var provinceValueTemp = itemvalue[0].split(""); + var provinceValue = provinceValueTemp[provinceValueTemp.length - 1].split("")[0]; + //city + var cityValueTemp = itemvalue[0].split(""); + var cityValue = cityValueTemp[cityValueTemp.length - 1].split("")[0]; + // county + var countyValueTemp = itemvalue[0].split(""); + var countyValue = countyValueTemp[countyValueTemp.length - 1].split("")[0]; + // + var codeValueTemp = itemvalue[0].split(""); + var codeValue = codeValueTemp[codeValueTemp.length - 1].split("")[0]; + // + var sys_nameValueTemp = itemvalue[0].split(""); + var sys_nameValue = sys_nameValueTemp[sys_nameValueTemp.length - 1].split("")[0]; + // + var character_setValueTemp = itemvalue[0].split(""); + var character_setValue = character_setValueTemp[character_setValueTemp.length - 1].split("")[0]; + // + var sys_name_codeValueTemp = itemvalue[0].split(""); + var sys_name_codeValue = sys_name_codeValueTemp[sys_name_codeValueTemp.length - 1].split("")[0]; + // + var contactValueTemp = itemvalue[0].split(""); + var contactValue = contactValueTemp[contactValueTemp.length - 1].split("")[0]; + // + var phoneValueTemp = itemvalue[0].split(""); + var phoneValue = phoneValueTemp[phoneValueTemp.length - 1].split("")[0]; + // + var dateValueTemp = itemvalue[0].split(""); + var dateValue = dateValueTemp[dateValueTemp.length - 1].split("")[0]; + //id : + var itemId = codeValue + "_" + sys_name_codeValue; + // http get version + var rid = itemId; //.replace(/\"/g, ""); + // TODO typeValue 通过前端页面获取或者??,财政01或社保02 + var typeValue = "01"; + // TODO batchValue 通过前端页面获取或者??,批次A :大写的A,批次B :大写的B, + var batchValue = "A"; + var itemname = cityValue + countyValue + sys_nameValue; + var versionid = 1; + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + versionid = xhr.responseText; + } + } + }; + xhr.open("get", "/getversion?id=" + rid, false); + xhr.send(null); + var jsobj = JSON.parse(versionid); + var xmlversion = jsobj.id; + var properValue = "{\"id\":\"" + itemId + "\", \"name\":\"" + itemname + "\", \"city\":\"" + + cityValue + "\", \"county\":\"" + countyValue + "\", \"system\":\"" + + sys_nameValue + "\", \"type\":\"" + typeValue + "\",\"batch\":\"" + + batchValue + "\",\"version\":\"" + xmlversion + "\", \"province\":\"" + + provinceValue + "\", \"code\":\"" + + codeValue + "\", \"character_set\":\"" + + character_setValue + "\", \"sys_name_code\":\"" + + sys_name_codeValue + "\", \"contact\":\"" + + contactValue + "\", \"phone\":\"" + + phoneValue + "\", \"date\":\"" + + dateValue + "\"}"; + resultString = resultString + properValue; + if (k < itemsize - 1) { + resultString = resultString + ", "; + } + } + resultString = resultString + "]}"; + } + $scope.$apply(function () { + $scope.model.localdata = JSON.parse(resultString.toString()); + }); + }; + reader.readAsText(files[i], "utf-8"); + } + else { + FilterList.length += 1; + var file_id = files[i].name.replace(/\.\w*$/, ''); + // var file_id=file[i].webkitRelativePath.replace(/^[a-z]*\/$/,''); + // file_id = file_id.replace(/\/\w+$/,''); + FilterList[j++] = files[i]; + } + } + } + $scope.model.uploadprocess = {}; + }; + $scope.upLoadFiles = function () { + if ($scope.model.uploadedStatus == "once") { + return; + } + $scope.model.uploadedStatus = "once"; + $scope.model.createFolderList(FilterList, rootPath); + if ($scope.model.folderList.length > 0 && $scope.model.selectednodes.length > 0) { + var isNotExited = []; + var isExited = []; + for (var node in $scope.model.selectednodes) { + if (!$scope.model.folderList.hasOwnProperty($scope.model.selectednodes[node].id)) { + isNotExited.push($scope.model.selectednodes[node]); + } + else { + if ($scope.model.uploadprocess[$scope.model.selectednodes[node].id] === 'undefined' || $scope.model.uploadprocess[$scope.model.selectednodes[node].id] === 0) + isExited.push($scope.model.selectednodes[node]); + } + } + if (isNotExited.length > 0) { + var str = "以下数据文件不存在:\n\r文件名:\n"; + for (var item in isNotExited) + str += isNotExited[item].id + "\n"; + alert(str); + } + if (isExited.length <= 0) { + alert("数据文件中没有可用上传的文件!"); + } + else { + var isuploaad = 1, i = 0; + var timerForUpload = setInterval(function () { + if (i >= isExited.length) { + clearInterval(timerForUpload); + } + if (isuploaad == 1) { + var r = new Resumable({ + target: '/uploadfiles', + chunkSize: 50 * 1024 * 1024, + simultaneousUploads: 400, + testChunks: true, + throttleProgressCallbacks: 1 + }); + var xhr = new XMLHttpRequest(); + xhr.open("GET", "/getclientip", true); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + r.setip(xhr.responseText); + } + } + }; + xhr.send(null); + r.on('fileAdded', function (file) { + r.upload(); + }); + $scope.model.resumablejs.push({ + dirname: isExited[i].id, + resumable: r + }); + r.setRootPath(isExited[i].type + "/" + isExited[i].batch + "/" + isExited[i].id + "/" + isExited[i].version + "/"); + r.myLoadFiles($scope.model.folderList[isExited[i].id]); + r.upload(); + r.on('fileProgress', function (file) { + var file_id = file.relativePath.replace(/^[a-z]*\/$/, ''); + var filestr = ""; + var reg = /\/[0-9]*_*[0-9]*\//g; + var resultstr; + while ((resultstr = reg.exec(file_id)) != null) { + filestr = resultstr[0]; + } + file_id = filestr.replace(/\/*/g, ''); + r.setFileId(file_id); + //$scope.$apply(function(){ + $scope.model.uploadprocess[file_id] = Math.floor(r.progress() * 98); + //}); + }); + r.on('complete', function () { + var timerForchmod = setInterval(function () { + var pathjson = "\"path\":\"" + r.getrootPath() + "\""; + var datamessage = { "path": r.getrootPath(), "filenum": $scope.model.folderList[isExited[i - 1].id].length }; + $scope.model.uploadprocess[r.getFileId()] = Math.round(r.progress() * 99); + $http({ + url: '/setchmod2dir', + method: 'GET', + params: datamessage + }).success(function (data, header, config, status) { + if (data) { + //console.log(data); + var clientdata = data; + if (clientdata == "chmod") { + sendDateMessage(isExited[i - 1]); + r.setisnowcheck("1"); + r.mkRetfileUploadSucceed(); + clearInterval(timerForchmod); + } + } + }).error(function (data, header, config, status) { + console.log("-----sendDateMessage-------------" + status); + }); + }, 5000); + }); + i++; + isuploaad = 0; + r.on('fileuploadendsucceed', function () { + $scope.model.uploadprocess[r.getFileId()] = Math.floor(r.progress() * 100); + $timeout(function () { + $http({ + url: '/xmlformserver', + method: 'Post' + }).success(function (data, header, config, status) { + if (data) { + $scope.model.serverdata = data; + } + }).error(function (data, header, config, status) { + console.log("error"); + }); + }, 2000); + isuploaad = 1; + }); + } + }, 2000); + } + } + else { + alert("您没有选择需要上传的数据文件,或你选择的文件中不存在指定格式的数据文件!"); + } + }; + function sendDateMessage(datamessage) { + $http({ + url: '/sendDateMessage', + method: 'GET', + params: datamessage + }).success(function (data, header, config, status) { + if (data) + var clientdata = data; + }).error(function (data, header, config, status) { + }); + } + $scope.downLoadFiles = function () { + Kubernetes.connectOracle($http, $timeout, "192.168.0.103:64182", "320614-54-1", 500); + }; + $scope.isSelected = function (node) { + var index = $scope.model.findItemIndex(node); + if (index !== -1) { + $scope.model.selecteditems.splice(index, 1); + } + else { + $scope.model.selecteditems.push(node); + } + }; + $scope.showSelectedLocal = function (node, selected) { + var index = $scope.model.findNodes(node); + if (index !== "-1") { + if ($scope.model.uploadprocess[node.id] === 0) + $scope.model.selectednodes.splice(index, 1); + } + else { + $scope.model.uploadprocess[node.id] = 0; + $scope.model.selectednodes.push(node); + } + }; + $scope.startOracle = function () { + if ($scope.model.selecteditems.length > 0) { + for (var id in $scope.model.selecteditems) { + var Obj = createRCObj($scope.model.selecteditems[id]); + if (!checkIsRunning(KubernetesModel.replicationControllers, Obj)) { + Kubernetes.createRC(Obj, function (rc) { + console.log(rc.metadata.name); + Kubernetes.connectOracle($http, $timeout, "/connectToOracle", "", rc.metadata.name, 0); + }); + } + } + } + }; + function checkIsRunning(replicationControllers, item) { + for (var rc in replicationControllers) { + if (item.name === replicationControllers[rc].metadata.name) + return true; + } + return false; + } + function createRCObj(item) { + var array = item.id.split("_"); + return { + "name": array[2] + "-" + array[3] + "-" + array[4], + "labels": { + "type": array[0], + "batch": array[1], + "region": array[2], + "system": array[3], + "version": array[4] + }, + "path": item.path + "app/" + }; + } + function setchmod2dir(datamessage) { + $http({ + url: '/setchmod2dir', + method: 'GET', + params: datamessage + }).success(function (data, header, config, status) { + if (data) + var clientdata = data; + }).error(function (data, header, config, status) { + console.log("-----sendDateMessage-------------" + status); + }); + } + function update() { + for (var i = 0; i < $scope.model.resumablejs.length; i++) { + var dirId = $scope.model.resumablejs[i].dirname; + var r = $scope.model.resumablejs[i].resumable; + r.on('fileProgress', function (file) { + $scope.$apply(function () { + $scope.model.uploadprocess[dirId] = Math.floor(r.progress() * 100); + console.log(dirId + ":" + Math.floor(r.progress() * 100)); + }); + }); + } + } + }]); +})(Developer || (Developer = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.Apps = Kubernetes.controller("Apps", ["$scope", "KubernetesModel", "KubernetesServices", "KubernetesReplicationControllers", "KubernetesPods", "KubernetesState", "KubernetesApiURL", "$templateCache", "$location", "$routeParams", "$http", "$dialog", "$timeout", + function ($scope, KubernetesModel, KubernetesServices, KubernetesReplicationControllers, KubernetesPods, KubernetesState, KubernetesApiURL, $templateCache, $location, $routeParams, $http, $dialog, $timeout) { + $scope.model = KubernetesModel; + $scope.apps = []; + $scope.allApps = []; + $scope.kubernetes = KubernetesState; + $scope.fetched = false; + $scope.json = ''; + ControllerHelpers.bindModelToSearchParam($scope, $location, 'id', '_id', undefined); + ControllerHelpers.bindModelToSearchParam($scope, $location, 'appSelectorShow', 'openApp', undefined); + ControllerHelpers.bindModelToSearchParam($scope, $location, 'mode', 'mode', 'detail'); + var branch = $scope.branch || "master"; + var namespace = null; + function appMatches(app) { + var filterText = $scope.appSelector.filterText; + if (filterText) { + return Core.matchFilterIgnoreCase(app.groupId, filterText) || + Core.matchFilterIgnoreCase(app.artifactId, filterText) || + Core.matchFilterIgnoreCase(app.name, filterText) || + Core.matchFilterIgnoreCase(app.description, filterText); + } + else { + return true; + } + } + function appRunning(app) { + return $scope.model.apps.any(function (running) { return running.appPath === app.appPath; }); + } + $scope.tableConfig = { + data: 'model.apps', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '$name', displayName: 'App', cellTemplate: $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, "appIconTemlate.html")) }, + { field: '$servicesText', displayName: 'Services', cellTemplate: $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, "appServicesTemplate.html")) }, + { field: '$replicationControllersText', displayName: 'Controllers', cellTemplate: $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, "appReplicationControllerTemplate.html")) }, + { field: '$podCount', displayName: 'Pods', cellTemplate: $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, "appPodCountsAndLinkTemplate.html")) }, + { field: '$creationDate', displayName: 'Deployed', cellTemplate: $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, "appDeployedTemplate.html")) } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.expandedPods = []; + $scope.$on('do-resize', function ($event, controller) { + $scope.resizeDialog.open(controller); + }); + $scope.podExpanded = function (pod) { + var id = Kubernetes.getName(pod); + return id && ($scope.expandedPods || []).indexOf(id) >= 0; + }; + $scope.expandPod = function (pod) { + var id = Kubernetes.getName(pod); + if (id) { + $scope.expandedPods.push(id); + } + }; + $scope.collapsePod = function (pod) { + var id = Kubernetes.getName(pod); + if (id) { + _.remove($scope.expandedPods, function (v) { return id === v; }); + } + }; + $scope.$on('$routeUpdate', function ($event) { + Kubernetes.setJson($scope, $location.search()['_id'], $scope.model.apps); + }); + function deleteApp(app, onCompleteFn) { + function deleteServices(services, service, onCompletedFn) { + if (!service || !services) { + return onCompletedFn(); + } + var id = Kubernetes.getName(service); + if (!id) { + Kubernetes.log.warn("No ID for service " + angular.toJson(service)); + } + else { + KubernetesServices.delete({ + id: id + }, undefined, function () { + Kubernetes.log.debug("Deleted service: ", id); + deleteServices(services, services.shift(), onCompletedFn); + }, function (error) { + Kubernetes.log.debug("Error deleting service: ", error); + deleteServices(services, services.shift(), onCompletedFn); + }); + } + } + function deleteReplicationControllers(replicationControllers, replicationController, onCompletedFn) { + if (!replicationController || !replicationControllers) { + return onCompletedFn(); + } + var id = Kubernetes.getName(replicationController); + if (!id) { + Kubernetes.log.warn("No ID for replicationController " + angular.toJson(replicationController)); + } + else { + KubernetesReplicationControllers.delete({ + id: id + }, undefined, function () { + Kubernetes.log.debug("Deleted replicationController: ", id); + deleteReplicationControllers(replicationControllers, replicationControllers.shift(), onCompletedFn); + }, function (error) { + Kubernetes.log.debug("Error deleting replicationController: ", error); + deleteReplicationControllers(replicationControllers, replicationControllers.shift(), onCompletedFn); + }); + } + } + function deletePods(pods, pod, onCompletedFn) { + if (!pod || !pods) { + return onCompletedFn(); + } + var id = Kubernetes.getName(pod); + if (!id) { + Kubernetes.log.warn("No ID for pod " + angular.toJson(pod)); + } + else { + KubernetesPods.delete({ + id: id + }, undefined, function () { + Kubernetes.log.debug("Deleted pod: ", id); + deletePods(pods, pods.shift(), onCompletedFn); + }, function (error) { + Kubernetes.log.debug("Error deleting pod: ", error); + deletePods(pods, pods.shift(), onCompletedFn); + }); + } + } + var services = [].concat(app.services); + deleteServices(services, services.shift(), function () { + var replicationControllers = [].concat(app.replicationControllers); + deleteReplicationControllers(replicationControllers, replicationControllers.shift(), function () { + var pods = [].concat(app.pods); + deletePods(pods, pods.shift(), onCompleteFn); + }); + }); + } + $scope.deleteSingleApp = function (app) { + $scope.deletePrompt([app]); + }; + $scope.deletePrompt = function (selected) { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + var id = next.name; + Kubernetes.log.debug("deleting: ", id); + deleteApp(next, function () { + Kubernetes.log.debug("deleted: ", id); + deleteSelected(selected, selected.shift()); + }); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Apps?', + action: 'The following Apps will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + $scope.appSelector = { + filterText: "", + folders: [], + selectedApps: [], + isOpen: function (folder) { + if ($scope.appSelector.filterText !== '' || folder.expanded) { + return "opened"; + } + return "closed"; + }, + getSelectedClass: function (app) { + if (app.abstract) { + return "abstract"; + } + if (app.selected) { + return "selected"; + } + return ""; + }, + showApp: function (app) { + return appMatches(app) && !appRunning(app); + }, + showFolder: function (folder) { + return !$scope.appSelector.filterText || folder.apps.some(function (app) { return appMatches(app) && !appRunning(app); }); + }, + clearSelected: function () { + angular.forEach($scope.model.appFolders, function (folder) { + angular.forEach(folder.apps, function (app) { + app.selected = false; + }); + }); + $scope.appSelector.selectedApps = []; + Core.$apply($scope); + }, + updateSelected: function () { + // lets update the selected apps + var selectedApps = []; + angular.forEach($scope.model.appFolders, function (folder) { + var apps = folder.apps.filter(function (app) { return app.selected; }); + if (apps) { + selectedApps = selectedApps.concat(apps); + } + }); + $scope.appSelector.selectedApps = _.sortBy(selectedApps, "name"); + }, + select: function (app, flag) { + app.selected = flag; + $scope.appSelector.updateSelected(); + }, + hasSelection: function () { + return $scope.model.appFolders.any(function (folder) { return folder.apps.any(function (app) { return app.selected; }); }); + }, + runSelectedApps: function () { + // lets run all the selected apps + angular.forEach($scope.appSelector.selectedApps, function (app) { + var name = app.name; + var metadataPath = app.metadataPath; + if (metadataPath) { + // lets load the json/yaml + //var url = gitPathToUrl(Wiki.gitRelativeURL(branch, metadataPath)); + var url = Kubernetes.gitPathToUrl(metadataPath, branch); + if (url) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + // lets convert the json object structure into a string + var json = angular.toJson(data); + var fn = function () { }; + Kubernetes.runApp($location, $scope, $http, KubernetesApiURL, json, name, fn, namespace); + } + }). + error(function (data, status, headers, config) { + $scope.summaryHtml = null; + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + }); + // lets go back to the apps view + $scope.appSelector.clearSelected(); + $scope.appSelectorShow = false; + } + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes._module.directive("hawtioBreadcrumbs", ['HawtioBreadcrumbs', function (HawtioBreadcrumbs) { + return { + /* + templateUrl: Kubernetes.templatePath + 'breadcrumbs.html' + */ + link: function (scope, element, attrs) { + HawtioBreadcrumbs.apply(scope.$eval('breadcrumbConfig')); + } + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.BuildController = Kubernetes.controller("BuildController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_Build; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, null, $scope); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = Kubernetes.buildRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = Kubernetes.enrichBuild(data); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.BuildConfigController = Kubernetes.controller("BuildConfigController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_BuildConfig; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = Kubernetes.buildConfigRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = data; + var sortedBuilds = null; + Kubernetes.enrichBuildConfig(data, sortedBuilds); + $scope.model.setProject($scope.entity); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.BuildConfigEditController = Kubernetes._module.controller("Kubernetes.BuildConfigEditController", ["$scope", "$element", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "K8SClientFactory", "SchemaRegistry", function ($scope, $element, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, K8SClientFactory, SchemaRegistry) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["project"] || $routeParams["id"]; + $scope.schema = KubernetesSchema; + var mode = $scope.$eval('mode') || 'edit'; + Kubernetes.log.debug("Mode: ", mode); + var specConfig = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildConfigSpec'); + var gitBuildSource = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.GitBuildSource'); + var buildSource = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildSource'); + var buildOutput = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildOutput'); + var resources = SchemaRegistry.getSchema('io.fabric8.kubernetes.api.model.ResourceRequirements'); + var revision = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.SourceRevision'); + var strategy = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildStrategy'); + var customStrategy = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.CustomBuildStrategy'); + var buildTriggerPolicy = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildTriggerPolicy'); + var getSecrets = function () { + return $scope.secrets; + }; + var secretSchemaType = "fabric8_SecretReference"; + var secretSchemaRef = "#/definitions/" + secretSchemaType; + var secretSchemaJavaType = "io.fabric8.console.SecretReference"; + var secretNameElement = { + "type": "string", + "enum": getSecrets, + required: true + }; + var secretSchema = { + "type": "object", + properties: { + "name": secretNameElement + }, + javaType: secretSchemaJavaType + }; + SchemaRegistry.addSchema(secretSchemaType, secretSchema); + // lets switch to the new secrets types: + var sourceSecretProperty = Core.pathGet(buildSource, ["properties", "sourceSecret"]); + angular.forEach([ + Core.pathGet(customStrategy, ["properties", "pullSecret"]), + sourceSecretProperty, + ], function (schemaType) { + if (schemaType) { + schemaType["type"] = secretSchemaType; + schemaType["$ref"] = secretSchemaRef; + schemaType["javaType"] = secretSchemaJavaType; + } + }); + // lets try make the buildSource's sourceSecret mandatory + //schemaSetRequired(customStrategy, 'pullSecret'); + Kubernetes.schemaSetRequired(buildSource, 'sourceSecret'); + if (sourceSecretProperty) { + Core.pathSet(sourceSecretProperty, ['properties', 'required'], true); + Core.pathSet(sourceSecretProperty, ['properties', 'input-attributes', 'required'], true); + } + $scope.customStrategy = customStrategy; + $scope.buildSource = buildSource; + $scope.secrets = []; + // $scope.config = KubernetesSchema.definitions.os_build_BuildConfig; + //$scope.specConfig = KubernetesSchema.definitions.os_build_BuildConfigSpec; + // + specConfig.style = HawtioForms.FormStyle.STANDARD; + specConfig.properties['triggers']['label-attributes'] = { + style: 'display: none;' + }; + gitBuildSource.controls = ['uri', 'ref', '*']; + buildSource.properties['type'].type = 'hidden'; + buildSource.properties['type']['default'] = 'Git'; + buildSource.controls = ['git', 'contextDir', 'sourceSecret', '*']; + gitBuildSource['hideLegend'] = true; + buildSource['hideLegend'] = true; + buildOutput['hideLegend'] = true; + resources['hideLegend'] = true; + revision['hideLegend'] = true; + strategy['hideLegend'] = true; + strategy.controls = ['type', '*']; + strategy.properties['type'] = { + type: 'text', + enum: [{ + 'value': 'Custom', + 'label': 'Custom' + }, { + 'value': 'Docker', + 'label': 'Docker' + }, { + 'value': 'Source', + 'label': 'Source' + }] + }; + customStrategy['control-group-attributes'] = { + 'ng-show': "entity.type == 'Custom'" + }; + strategy.properties['dockerStrategy']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Docker'" + }; + strategy.properties['sourceStrategy']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Source'" + }; + buildTriggerPolicy.controls = ['type', '*']; + buildTriggerPolicy.properties['type'] = { + type: 'string', + enum: [{ + 'value': 'Github', + 'label': 'Github' + }, { + 'value': 'ImageChange', + 'label': 'Image Change' + }, { + 'value': 'Generic', + 'label': 'Generic' + }] + }; + buildTriggerPolicy.properties['generic']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Generic'" + }; + buildTriggerPolicy.properties['github']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Github'" + }; + buildTriggerPolicy.properties['imageChange']['control-group-attributes'] = { + 'ng-show': "entity.type == 'ImageChange'" + }; + // re-arranging the controls + //specConfig.controls = ['source', '*']; + // tabs + specConfig.tabs = { + "Source": ["source"], + "Revision": ["revision"], + "Output": ["output"], + "Resources": ["resources"], + "Strategy": ["strategy"], + "Triggers": ["triggers"], + "Service Account": ["serviceAccount"] + }; + /* + * wizard, needs an 'onFinish' function in the scope + specConfig.wizard = { + pages: { + Source: { + controls: ["source"] + }, + Revision: { + controls: ["revision"] + }, + Output: { + controls: ["output"] + }, + Resources: { + controls: ["resources"] + }, + Strategy: { + controls: ["strategy"] + }, + Triggers: { + controls: ["triggers"] + }, + "Service Account": { + controls: ["serviceAccount"] + } + } + }; + */ + $scope.entity = { + "apiVersion": "v1", + "kind": "BuildConfig", + "metadata": { + "name": "", + "labels": {} + }, + "spec": { + "source": { + "type": "Git" + }, + "strategy": { + "type": "Custom", + "customStrategy": { + "from": { + "kind": "DockerImage", + "name": "fabric8/openshift-s2i-jenkins-trigger" + }, + "env": [ + { + "name": "BASE_URI", + "value": jenkinsUrl + }, + { + "name": "JOB_NAME", + "value": jobName + } + ] + } + } + } + }; + $scope.$watch('entity.spec.source.git.uri', function (val) { + if (!val) { + return; + } + var lastBit = val.match(/[^\/]+$/)[0]; + if (lastBit) { + var name = lastBit.replace(/\.git$/, ''); + Kubernetes.log.debug("name: ", name); + if (!Core.isBlank(name) + && Core.isBlank(Core.pathGet($scope.entity, ['metadata', 'name']))) { + Core.pathSet($scope.entity, ['metadata', 'name'], name); + } + } + }); + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectSettingsBreadcrumbs($scope.projectId); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.projectId); + $scope.tabs = Developer.createProjectSettingsSubNavBars($scope.projectId); + Kubernetes.watch($scope, $element, "secrets", $scope.namespace, onSecrets); + $scope.buildConfigClient = K8SClientFactory.create("buildconfigs", $scope.namespace); + $element.on('$destroy', function () { + $scope.$destroy(); + }); + $scope.$on('$destroy', function () { + K8SClientFactory.destroy($scope.buildConfigClient); + }); + /* + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + */ + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.save = function () { + Kubernetes.log.info("Saving!"); + var entity = $scope.entity; + var spec = (entity || {}).spec || {}; + // TODO update the jenkins job name! + // lets delete lots of cruft + var strategy = spec.strategy || {}; + delete strategy["dockerStrategy"]; + delete strategy["sourceStrategy"]; + delete spec["revision"]; + delete spec["output"]; + delete spec["resources"]; + var strategyPullSecretName = Core.pathGet(spec, ["strategy", "customStrategy", "pullSecret", "name"]); + var sourceSecretName = Core.pathGet(spec, ["source", "sourceSecret", "name"]); + Kubernetes.log.info("sourceSecretName: " + sourceSecretName); + Kubernetes.log.info("strategyPullSecretName: " + strategyPullSecretName); + if (!strategyPullSecretName && sourceSecretName) { + Core.pathSet(spec, ["strategy", "customStrategy", "pullSecret", "name"], sourceSecretName); + } + /* + // TODO hack until the put deals with updates + var metadata = entity.metadata; + if (metadata) { + delete metadata["resourceVersion"]; + } + */ + Kubernetes.log.info(angular.toJson(entity, true)); + $scope.buildConfigClient.put(entity, function (obj) { + Kubernetes.log.info("build config created!"); + var link = Developer.projectSecretsLink($scope.namespace, Kubernetes.getName(entity)); + if (link) { + Kubernetes.log.info("Navigating to: " + link); + $location.path(link); + } + else { + Kubernetes.log.warn("Could not find the edit pipeline link!"); + } + }); + }; + updateData(); + var jenkinsUrl = Developer.jenkinsLink(); + var jobName = ""; + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = Kubernetes.buildConfigRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = data; + var buildConfig = angular.copy(data); + var sortedBuilds = null; + Kubernetes.enrichBuildConfig(buildConfig, sortedBuilds); + $scope.buildConfig = buildConfig; + } + $scope.spec = ($scope.entity || {}).spec || {}; + $scope.fetched = true; + // lets update the tabs + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.projectId, null, $scope); + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + else { + $scope.fetched = true; + $scope.spec = $scope.entity.spec; + Core.$apply($scope); + } + } + function onSecrets(secrets) { + var array = []; + angular.forEach(secrets, function (secret) { + var name = Kubernetes.getName(secret); + if (name) { + array.push({ + label: name, + value: name, + "attributes": { + "title": name + }, + $secret: secret + }); + } + }); + $scope.secrets = _.sortBy(array, "label"); + var specSourceSecretNamePath = ['spec', 'source', 'sourceSecret', 'name']; + if ($scope.entity && !Core.pathGet($scope.entity, specSourceSecretNamePath)) { + var defaultSecretName = findDefaultImportSecretName(secrets); + Core.pathSet($scope.entity, specSourceSecretNamePath, defaultSecretName); + } + } + function findDefaultImportSecretName(secrets) { + var answer = null; + angular.forEach(secrets, function (secret) { + var name = Kubernetes.getName(secret); + if (!answer && name && name.startsWith("jenkins-login")) { + answer = name; + } + }); + if (!answer) { + angular.forEach(secrets, function (secret) { + var name = Kubernetes.getName(secret); + if (!answer && name && name.startsWith("jenkins-token")) { + answer = name; + } + }); + } + return answer; + } + switch (mode) { + case 'create': + delete specConfig.tabs; + _.forIn(buildSource.properties, function (property, name) { + if (name !== 'git') { + Kubernetes.log.info("Hiding property: ", name); + property.hidden = true; + } + }); + _.forIn(gitBuildSource.properties, function (property, name) { + if (name !== 'uri') { + Kubernetes.log.info("Hiding property: ", name); + property.hidden = true; + } + else { + property.label = "Git URL"; + property['input-attributes'] = { + 'required': true + }; + } + }); + _.forIn(specConfig.properties, function (property, name) { + if (name !== 'source') { + Kubernetes.log.info("Hiding property: ", name); + property.hidden = true; + } + }); + break; + case 'edit': + default: + } + $scope.specConfig = specConfig; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.BuildConfigsController = Kubernetes.controller("BuildConfigsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.tableConfig = { + data: 'model.buildconfigs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name', + cellTemplate: $templateCache.get("buildConfigLinkTemplate.html") + }, + /* + { + field: 'spec.source.type', + displayName: 'Source' + }, + */ + { + field: 'spec.source.git.uri', + displayName: 'Repository' + }, + /* + { + field: 'spec.strategy.type', + displayName: 'Strategy' + }, + { + field: 'spec.strategy.stiStrategy.image', + displayName: 'Source Image' + }, + { + field: 'spec.output.imageTag', + displayName: 'Output Image' + }, + */ + { + field: '$fabric8CodeViews', + displayName: 'Code', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigCodeViewsTemplate.html") + }, + { + field: '$fabric8BuildViews', + displayName: 'Builds', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigBuildViewsTemplate.html") + }, + { + field: '$fabric8EnvironmentViews', + displayName: 'Environments', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigEnvironmentViewsTemplate.html") + }, + { + field: '$fabric8TeamViews', + displayName: 'People', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigTeamViewsTemplate.html") + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + // TODO + // $scope.isLoggedIntoGogs = Forge.isLoggedIntoGogs; + $scope.deletePrompt = function (selected) { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, function () { + deleteSelected(selected, selected.shift()); + }); + } + else { + updateData(); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Build Configs?', + action: 'The following Build Configs will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + if (name) { + console.log("About to delete build config: " + name); + var url = Kubernetes.buildConfigRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to delete build config on " + url + " " + data + " " + status); + }); + } + else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + } + function updateData() { + } + updateData(); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.BuildLogsController = Kubernetes.controller("BuildLogsController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_Build; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.logsText = "Loading logs..."; + updateData(); + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = Kubernetes.buildRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = Kubernetes.enrichBuild(data); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + url = Kubernetes.buildLogsRestUrl($scope.id); + $http.get(url). + success(function (data, status) { + $scope.logsText = data; + Core.$apply($scope); + }). + error(function (data, status) { + $scope.logsText = "Failed to load logs from: " + url + " " + data + " status: " + status; + Core.$apply($scope); + }). + catch(function (error) { + $scope.logsText = "Failed to load logs: " + angular.toJson(error, true); + Core.$apply($scope); + }); + } + else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.BuildsController = Kubernetes.controller("BuildsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.buildConfigId = $routeParams["id"]; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.tableConfig = { + data: 'model.builds', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name', + cellTemplate: $templateCache.get("buildLinkTemplate.html") + }, + { + field: '$creationDate', + displayName: 'Time', + defaultSort: true, + cellTemplate: $templateCache.get("buildTimeTemplate.html") + }, + { + field: 'status', + displayName: 'Status', + cellTemplate: $templateCache.get("buildStatusTemplate.html") + }, + { + field: '$logsLink', + displayName: 'Logs', + cellTemplate: $templateCache.get("buildLogsTemplate.html") + }, + { + field: '$podLink', + displayName: 'Build Pod', + cellTemplate: $templateCache.get("buildPodTemplate.html") + }, + /* + { + field: 'parameters.source.type', + displayName: 'Source' + }, + */ + { + field: 'spec.source.git.uri', + displayName: 'Repository', + cellTemplate: $templateCache.get("buildRepositoryTemplate.html") + }, + { + field: 'spec.strategy.type', + displayName: 'Strategy' + }, + { + field: 'spec.strategy.sourceStrategy.from.name', + displayName: 'Source Image' + }, + { + field: 'spec.output.to.name', + displayName: 'Output Image' + }] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.buildConfigId); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.buildConfigId, null, $scope); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + function updateData() { + if ($scope.model) { + var builds = $scope.model.builds; + var buildConfigId = $scope.buildConfigId; + Kubernetes.enrichBuilds(builds); + $scope.fetched = true; + if (buildConfigId) { + $scope.buildConfig = $scope.model.getBuildConfig(buildConfigId); + } + } + } + updateData(); + /* + $scope.$keepPolling = () => keepPollingModel; + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + var url = buildsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + $scope.builds = enrichBuilds(data.items); + $scope.fetched = true; + + if ($scope.model) { + $scope.buildConfig = $scope.model.getBuildConfig($scope.buildConfigId); + } + } + Core.$apply($scope); + next(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + Core.$apply($scope); + next(); + }); + }); + + $scope.fetch(); + */ + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + // controller for connecting to a remote container via jolokia + Kubernetes.ConnectController = Kubernetes.controller("ConnectController", [ + "$scope", "localStorage", "userDetails", "ConnectDialogService", "$browser", + function ($scope, localStorage, userDetails, ConnectDialogService, $browser) { + $scope.doConnect = function (entity) { + var connectUrl = new URI().path(UrlHelpers.join(HawtioCore.documentBase(), '/java/index.html')); + var returnTo = new URI().toString(); + var title = entity.metadata.name || 'Untitled Container'; + var token = userDetails.token || ''; + connectUrl.hash(token).query({ + jolokiaUrl: entity.$jolokiaUrl, + title: title, + returnTo: returnTo + }); + Kubernetes.log.debug("Connect URI: ", connectUrl.toString()); + window.open(connectUrl.toString()); + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + var dataInfoModelService = (function () { + function dataInfoModelService() { + this.serverdata = {}; + this.promiseobject = {}; + this.localdata = {}; + this.selectednodes = []; + this.resumablejs = []; + this.selecteditems = []; + this.serveritems = []; + this.uploadprocess = {}; + this.uploadedStatus = ""; + this.folderList = { + length: 0 + }; + } + Object.defineProperty(dataInfoModelService.prototype, "uploadProcess", { + get: function () { + return this.uploadprocess; + }, + set: function (uploadProcess) { + this.uploadprocess = uploadProcess; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "serverItems", { + get: function () { + return this.serveritems; + }, + set: function (serverItems) { + this.serveritems = serverItems; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "resumableJs", { + get: function () { + return this.resumableJs; + }, + set: function (resumableJs) { + this.resumablejs = resumableJs; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "selectedItems", { + get: function () { + return this.selecteditems; + }, + set: function (selectedItems) { + this.selecteditems = selectedItems; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "selectedNodes", { + get: function () { + return this.selectednodes; + }, + set: function (selectedNodes) { + this.selectednodes = selectedNodes; + }, + enumerable: true, + configurable: true + }); + dataInfoModelService.prototype.isContainsNodes = function (node) { + for (var item in this.selectednodes) { + if (this.selectednodes[item].id === node.id) + return true; + } + return false; + }; + dataInfoModelService.prototype.findNodes = function (node) { + var id = "-1"; + if (typeof (node) === "object") { + id = node.id; + } + else if (typeof (node) === "number") { + id = node.toString(); + } + else if (typeof (node) === "string") { + id = node; + } + else { + return "-1"; + } + for (var item in this.selectednodes) { + if (this.selectednodes[item].id === id) + return item; + } + return "-1"; + }; + dataInfoModelService.prototype.findItemIndex = function (item) { + var id = -1; + if (typeof (item) === "object") { + id = item.id; + } + else if (typeof (item) === "number") { + id = item.toString(); + } + else if (typeof (item) === "string") { + id = item; + } + else { + return -1; + } + for (var it in this.selecteditems) { + if (this.selecteditems[it].id === id) + return it; + } + return -1; + }; + dataInfoModelService.prototype.createFolderList = function (files, rootPath) { + for (var i = 0; i < files.length; i++) { + var relativePath = files[i].webkitRelativePath.replace(RegExp("^" + rootPath + "/"), ""); + var paths = relativePath.split("/"); + if (!this.folderList.hasOwnProperty(paths[0])) { + this.folderList[paths[0]] = { + length: 0 + }; + this.folderList.length++; + } + var Obj = this.folderList[paths[0]]; + Obj[Obj.length] = files[i]; + Obj.length++; + this.folderList[paths[0]] = Obj; + } + }; + dataInfoModelService.prototype.updateNodeById = function (nodeId, key, value) { + for (var item in this.selectednodes) { + var node = this.selectednodes[item]; + if (node.id === nodeId) { + node[key] = value; + break; + } + } + }; + Object.defineProperty(dataInfoModelService.prototype, "serverData", { + get: function () { + return this.serverData; + }, + set: function (serverData) { + this.serverdata = serverData; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "promiseObject", { + get: function () { + return this.promiseobject; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "promise", { + set: function (promiseObject) { + this.promiseobject = promiseObject; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(dataInfoModelService.prototype, "localData", { + get: function () { + return this.localdata; + }, + set: function (localData) { + this.localdata = localData; + }, + enumerable: true, + configurable: true + }); + dataInfoModelService.prototype.updataDataModel = function () { + this.promiseobject.success(function (data, header, config, status) { + this.serverdata = data; + }); + this.promiseobject.error(function (data, status, hedaers, config) { + this.serverdata = {}; + }); + }; + return dataInfoModelService; + }()); + Kubernetes.dataInfoModelService = dataInfoModelService; + Kubernetes._module.factory('DataInfoModel', ['$http', function ($http) { + var $scope = new dataInfoModelService(); + $scope.promiseobject = $http({ + url: '/xmlformserver', + method: 'POST' + }); + updateDataFromServer($scope.serverdata, function (data, header, config, status) { + $scope.serverdata = data; + }); + function updateDataFromServer(data, callback) { + $http({ + url: '/xmlformserver', + method: 'POST' + }).success(function (data, header, config, status) { + if (data) + callback(data, header, config, status); + }).error(function (data, header, config, status) { + console.log("error"); + }); + } + ; + return $scope; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.DeploymentConfigController = Kubernetes.controller("DeploymentConfigController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_deploy_DeploymentConfig; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = Kubernetes.deploymentConfigRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = data; + Kubernetes.enrichDeploymentConfig(data); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.DeploymentConfigsController = Kubernetes.controller("DeploymentConfigsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.labelClass = Kubernetes.containerLabelClass; + $scope.tableConfig = { + data: 'deploymentConfigs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name', + cellTemplate: $templateCache.get("deploymentConfigLinkTemplate.html") + }, + { + field: 'metadata.namespace', + displayName: 'Namespace' + }, + { + field: '$imageChangeParams.automatic', + displayName: 'Automatic' + }, + { + field: '$imageChangeParams.$containerNames', + displayName: 'Container Names' + }, + { + field: '$imageChangeParams.from.name', + displayName: 'From image' + }, + { + field: '$imageChangeParams.tag', + displayName: 'Tag' + }, + { + field: 'template.controllerTemplate.podTemplate.tags', + displayName: 'Labels', + cellTemplate: $templateCache.get("deploymentConfigLabelTemplate.html") + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.deletePrompt = function (selected) { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, function () { + deleteSelected(selected, selected.shift()); + }); + } + else { + updateData(); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Deployment?', + action: 'The following Deployments will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + if (name) { + console.log("About to delete deployment config: " + name); + var url = Kubernetes.deploymentConfigRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to delete deployment config on " + url + " " + data + " " + status); + }); + } + else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + } + function updateData() { + var url = Kubernetes.deploymentConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + $scope.deploymentConfigs = Kubernetes.enrichDeploymentConfigs(data.items); + $scope.fetched = true; + Core.$apply($scope); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + updateData(); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.EventsController = Kubernetes.controller("EventsController", ["$scope", "KubernetesModel", "KubernetesServices", "KubernetesPods", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesServices, KubernetesPods, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + ControllerHelpers.bindModelToSearchParam($scope, $location, 'mode', 'mode', 'list'); + $scope.tableConfig = { + data: 'model.events', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '$firstTimestamp', + displayName: 'First Seen', + cellTemplate: $templateCache.get("firstTimestampTemplate.html") + }, + { field: '$lastTimestamp', + displayName: 'Last Seen', + cellTemplate: $templateCache.get("lastTimestampTemplate.html") + }, + { field: 'count', + displayName: 'Count' + }, + { field: 'involvedObject.name', + displayName: 'Name', + cellTemplate: $templateCache.get("eventNameTemplate.html") + }, + { field: 'involvedObject.kind', + displayName: 'Kind', + cellTemplate: $templateCache.get("eventKindTemplate.html") + }, + { field: 'involvedObject.fieldPath', + displayName: 'Subject' + }, + { field: 'reason', + displayName: 'Reason' + }, + { field: 'source', + displayName: 'Source', + cellTemplate: $templateCache.get("eventSourceTemplate.html") + }, + { field: 'message', + displayName: 'Message' + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.HostController = Kubernetes.controller("HostController", ["$scope", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + $scope.itemConfig = { + properties: {} + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.flipRaw = function () { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + updateData(); + function updateData() { + $scope.id = $routeParams["id"]; + $scope.item = null; + if ($scope.id) { + var url = UrlHelpers.join(KubernetesApiURL, "nodes", $scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.item = data; + } + if ($scope.item) { + $scope.rawModel = Kubernetes.toRawYaml($scope.item); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + else { + $scope.rawModel = null; + Core.$apply($scope); + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.hostPorts = []; + /** + * Sorts the the ip field + * + * @param ip the ip such as '10.1.2.13' + * @returns {any} + */ + function sortByPodIp(ip) { + // i guess there is maybe nicer ways of sort this without parsing and slicing + var regex = /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; + var groups = regex.exec(ip); + if (angular.isDefined(groups)) { + var g1 = ("00" + groups[1]).slice(-3); + var g2 = ("00" + groups[2]).slice(-3); + var g3 = ("00" + groups[3]).slice(-3); + var g4 = ("00" + groups[4]).slice(-3); + var answer = g1 + g2 + g3 + g4; + return answer; + } + else { + return 0; + } + } + Kubernetes.sortByPodIp = sortByPodIp; + function ramdomPort() { + var hostPort = Math.floor(30000 + Math.random() * (65535 - 30000)); + while (Kubernetes.hostPorts.indexOf(hostPort) === 0) { + hostPort = Math.floor(30000 + Math.random() * (65535 - 30000)); + } + Kubernetes.hostPorts.push(hostPort); + return hostPort; + } + Kubernetes.ramdomPort = ramdomPort; + function getRandomString(len) { + len = len || 32; + var $chars = 'abcdefhijkmnprstwxyz'; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1 + var maxPos = $chars.length; + var pwd = ''; + for (var i = 0; i < len; i++) { + pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); + } + return pwd; + } + Kubernetes.getRandomString = getRandomString; + var resourceRCTemplate = (function () { + function resourceRCTemplate() { + this.image = "s1:latest"; + this.names = ["admin", "cfgtoollogs", "checkpoints", "diag", "flash-recovery-area", "oradata"]; + } + resourceRCTemplate.prototype.createRC = function (Obj) { + var labels = { + "style": "oracle", + "status": "created" + }; + for (var item in Obj.labels) + labels[item] = Obj.labels[item]; + return { + "apiVersion": Kubernetes.defaultApiVersion, + "kind": "ReplicationController", + "metadata": { + "name": Obj.name, + "labels": labels + }, + "spec": { + replicas: Obj.replicas || 1, + "template": this.createTemplate(Obj) + } + }; + }; + resourceRCTemplate.prototype.createVolumeMounts = function () { + var volumeMounts = []; + for (var item in this.names) { + if (this.names[item] === 'flash-recovery-area') + volumeMounts.push({ + "name": this.names[item], + "mountPath": "/opt/oracle/app/flash_recovery_area" + }); + else + volumeMounts.push({ + "name": this.names[item], + "mountPath": "/opt/oracle/app/" + this.names[item] + }); + } + return volumeMounts; + }; + resourceRCTemplate.prototype.createVolumes = function (rootPath) { + var volumes = []; + for (var item in this.names) { + if (this.names[item] === 'flash-recovery-area') + volumes.push({ + "name": this.names[item], + "hostPath": { + "path": rootPath + "flash_recovery_area" + } + }); + else + volumes.push({ + "name": this.names[item], + "hostPath": { + "path": rootPath + this.names[item] + } + }); + } + return volumes; + }; + resourceRCTemplate.prototype.createContainers = function (Obj) { + var containers = []; + containers.push({ + "name": "oracle", + "image": this.image, + "imagePullPolicy": "IfNotPresent", + "command": ["/assets/entrypoint.sh"], + "ports": [ + { + "containerPort": 1521, + "hostPort": Obj.port || ramdomPort() + }], + "volumeMounts": this.createVolumeMounts() + }); + return containers; + }; + resourceRCTemplate.prototype.createTemplate = function (Obj) { + return { + "metadata": { + //"name": Obj.name, + "labels": Obj.labels + }, + "spec": { + "terminationGracePeriodSeconds": 0, + "containers": this.createContainers(Obj), + "volumes": this.createVolumes(Obj.path) + } + }; + }; + return resourceRCTemplate; + }()); + Kubernetes.resourceRCTemplate = resourceRCTemplate; + function findLabelValue(value, key) { + var trueValue = ''; + switch (value) { + case '01': + trueValue = '财政'; + break; + case '02': + trueValue = '社保'; + break; + case 'A': + trueValue = '批次A'; + break; + case 'B': + trueValue = '批次B'; + break; + default: + if (key === "version") { + var reg = new RegExp('^[0-9]$').exec(value); + if (reg) + trueValue = '版本' + reg[0]; + else + trueValue = value; + } + else + trueValue = value; + } + return trueValue; + } + Kubernetes.findLabelValue = findLabelValue; + function labelToChinese(labels) { + var answer = {}; + angular.forEach(labels, function (value, key) { + answer[key] = findLabelValue(value, key); + }); + return answer; + } + Kubernetes.labelToChinese = labelToChinese; +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.HostsController = Kubernetes.controller("HostsController", ["$scope", "KubernetesModel", "KubernetesPods", "KubernetesState", "ServiceRegistry", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesPods, KubernetesState, ServiceRegistry, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.tableConfig = { + data: 'model.hosts', + showSelectionCheckbox: false, + enableRowClickSelection: false, + multiSelect: false, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'id', + displayName: 'Name', + defaultSort: true, + cellTemplate: $templateCache.get("idTemplate.html") + }, + { + field: 'hostIP', + displayName: 'IP', + customSortField: function (field) { + // use a custom sort to sort ip address + return Kubernetes.sortByPodIp(field.hostIP); + } + }, + { field: '$podsLink', + displayName: 'Pods', + cellTemplate: $templateCache.get("podCountsAndLinkTemplate.html"), + customSortField: function (field) { + // need to concat all the pod counters + var ready = field.$podCounters.ready || 0; + var valid = field.$podCounters.valid || 0; + var waiting = field.$podCounters.waiting || 0; + var error = field.$podCounters.error || 0; + return ready + valid + waiting + error; + } + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ImageRepositoriesController = Kubernetes.controller("ImageRepositoriesController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.tableConfig = { + data: 'imageRepositories', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name' + }, + { + field: 'metadata.namespace', + displayName: 'Namespace' + }, + { + field: 'status.dockerImageRepository', + displayName: 'Docker Registry' + }, + { + field: 'tags', + displayName: 'Tags', + cellTemplate: $templateCache.get('imageRegistryLabelTemplate.html') + } + ] + }; + var labelColors = { + 'prod': 'background-blue', + 'valid': 'background-light-green', + 'test': 'background-light-grey' + }; + $scope.labelClass = function (labelType) { + if (!(labelType in labelColors)) { + return 'mouse-pointer'; + } + else + return labelColors[labelType] + ' mouse-pointer'; + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.deletePrompt = function (selected) { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, function () { + deleteSelected(selected, selected.shift()); + }); + } + else { + updateData(); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Image Repository?', + action: 'The following Image Repositories will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + if (name) { + console.log("About to delete image repository: " + name); + var url = Kubernetes.imageRepositoryRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to delete image repository on " + url + " " + data + " " + status); + }); + } + else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + } + function updateData() { + var url = Kubernetes.imageRepositoriesRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + $scope.imageRepositories = Kubernetes.enrichImageRepositories(data.items); + $scope.fetched = true; + Core.$apply($scope); + } + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + updateData(); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + function selectSubNavBar($scope, tabName, newSubTabLabel) { + var foundTab = null; + angular.forEach($scope.subTabConfig, function (tab) { + if (tabName === tab.label || tabName === tab.id) { + foundTab = tab; + } + }); + var breadcrumbConfig = $scope.breadcrumbConfig; + if (foundTab && breadcrumbConfig) { + breadcrumbConfig.push(foundTab); + $scope.subTabConfig = [ + { + label: newSubTabLabel + } + ]; + } + } + Kubernetes.selectSubNavBar = selectSubNavBar; +})(Kubernetes || (Kubernetes = {})); + +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.schema = { + "id": "http://fabric8.io/fabric8/v2/Schema#", + "$schema": "http://json-schema.org/schema#", + "definitions": { + "api_RootPaths": { + "type": "object", + "description": "", + "properties": { + "paths": { + "type": "array", + "description": "", + "items": { + "type": "string", + "description": "" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.RootPaths" + }, + "kubernetes_AWSElasticBlockStoreVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "partition": { + "type": "integer", + "description": "partition on the disk to mount (e.g." + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true" + }, + "volumeID": { + "type": "string", + "description": "unique id of the PD resource in AWS; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#awselasticblockstore" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "kubernetes_Capabilities": { + "type": "object", + "description": "", + "properties": { + "add": { + "type": "array", + "description": "added capabilities", + "items": { + "type": "string", + "description": "added capabilities" + } + }, + "drop": { + "type": "array", + "description": "droped capabilities", + "items": { + "type": "string", + "description": "droped capabilities" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Capabilities" + }, + "kubernetes_CephFSVolumeSource": { + "type": "object", + "description": "", + "properties": { + "monitors": { + "type": "array", + "description": "a collection of Ceph monitors", + "items": { + "type": "string", + "description": "a collection of Ceph monitors" + } + }, + "readOnly": { + "type": "boolean", + "description": "Ceph fs to be mounted with read-only permissions" + }, + "secretFile": { + "type": "string", + "description": "path to secret for rados user; default is /etc/ceph/user.secret; optional" + }, + "secretRef": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "user": { + "type": "string", + "description": "rados user name; default is admin; optional" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "kubernetes_Container": { + "type": "object", + "description": "", + "properties": { + "args": { + "type": "array", + "description": "command array; the docker image's cmd is used if this is not provided; arguments to the entrypoint; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved", + "items": { + "type": "string", + "description": "command array; the docker image's cmd is used if this is not provided; arguments to the entrypoint; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved" + } + }, + "command": { + "type": "array", + "description": "entrypoint array; not executed within a shell; the docker image's entrypoint is used if this is not provided; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved", + "items": { + "type": "string", + "description": "entrypoint array; not executed within a shell; the docker image's entrypoint is used if this is not provided; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved" + } + }, + "env": { + "type": "array", + "description": "list of environment variables to set in the container; cannot be updated", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "image": { + "type": "string", + "description": "Docker image name; see http://releases.k8s.io/HEAD/docs/user-guide/images.md" + }, + "imagePullPolicy": { + "type": "string", + "description": "image pull policy; one of Always" + }, + "lifecycle": { + "$ref": "#/definitions/kubernetes_Lifecycle", + "javaType": "io.fabric8.kubernetes.api.model.Lifecycle" + }, + "livenessProbe": { + "$ref": "#/definitions/kubernetes_Probe", + "javaType": "io.fabric8.kubernetes.api.model.Probe" + }, + "name": { + "type": "string", + "description": "name of the container; must be a DNS_LABEL and unique within the pod; cannot be updated", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "ports": { + "type": "array", + "description": "list of ports to expose from the container; cannot be updated", + "items": { + "$ref": "#/definitions/kubernetes_ContainerPort", + "javaType": "io.fabric8.kubernetes.api.model.ContainerPort" + } + }, + "readinessProbe": { + "$ref": "#/definitions/kubernetes_Probe", + "javaType": "io.fabric8.kubernetes.api.model.Probe" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "securityContext": { + "$ref": "#/definitions/kubernetes_SecurityContext", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContext" + }, + "stdin": { + "type": "boolean", + "description": "Whether this container should allocate a buffer for stdin in the container runtime; default is false" + }, + "terminationMessagePath": { + "type": "string", + "description": "path at which the file to which the container's termination message will be written is mounted into the container's filesystem; message written is intended to be brief final status" + }, + "tty": { + "type": "boolean", + "description": "Whether this container should allocate a TTY for itself" + }, + "volumeMounts": { + "type": "array", + "description": "pod volumes to mount into the container's filesyste; cannot be updated", + "items": { + "$ref": "#/definitions/kubernetes_VolumeMount", + "javaType": "io.fabric8.kubernetes.api.model.VolumeMount" + } + }, + "workingDir": { + "type": "string", + "description": "container's working directory; defaults to image's default; cannot be updated" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Container" + }, + "kubernetes_ContainerPort": { + "type": "object", + "description": "", + "properties": { + "containerPort": { + "type": "integer", + "description": "number of port to expose on the pod's IP address" + }, + "hostIP": { + "type": "string", + "description": "host IP to bind the port to" + }, + "hostPort": { + "type": "integer", + "description": "number of port to expose on the host; most containers do not need this" + }, + "name": { + "type": "string", + "description": "name for the port that can be referred to by services; must be an IANA_SVC_NAME and unique within the pod" + }, + "protocol": { + "type": "string", + "description": "protocol for port; must be UDP or TCP; TCP if unspecified" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerPort" + }, + "kubernetes_ContainerState": { + "type": "object", + "description": "", + "properties": { + "running": { + "$ref": "#/definitions/kubernetes_ContainerStateRunning", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateRunning" + }, + "terminated": { + "$ref": "#/definitions/kubernetes_ContainerStateTerminated", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateTerminated" + }, + "waiting": { + "$ref": "#/definitions/kubernetes_ContainerStateWaiting", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateWaiting" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerState" + }, + "kubernetes_ContainerStateRunning": { + "type": "object", + "description": "", + "properties": { + "startedAt": { + "type": "string", + "description": "time at which the container was last (re-)started" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateRunning" + }, + "kubernetes_ContainerStateTerminated": { + "type": "object", + "description": "", + "properties": { + "containerID": { + "type": "string", + "description": "container's ID in the format 'docker://\u003ccontainer_id\u003e'" + }, + "exitCode": { + "type": "integer", + "description": "exit status from the last termination of the container" + }, + "finishedAt": { + "type": "string", + "description": "time at which the container last terminated" + }, + "message": { + "type": "string", + "description": "message regarding the last termination of the container" + }, + "reason": { + "type": "string", + "description": "(brief) reason from the last termination of the container" + }, + "signal": { + "type": "integer", + "description": "signal from the last termination of the container" + }, + "startedAt": { + "type": "string", + "description": "time at which previous execution of the container started" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateTerminated" + }, + "kubernetes_ContainerStateWaiting": { + "type": "object", + "description": "", + "properties": { + "reason": { + "type": "string", + "description": "(brief) reason the container is not yet running" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateWaiting" + }, + "kubernetes_ContainerStatus": { + "type": "object", + "description": "", + "properties": { + "containerID": { + "type": "string", + "description": "container's ID in the format 'docker://\u003ccontainer_id\u003e'; see http://releases.k8s.io/HEAD/docs/user-guide/container-environment.md#container-information" + }, + "image": { + "type": "string", + "description": "image of the container; see http://releases.k8s.io/HEAD/docs/user-guide/images.md" + }, + "imageID": { + "type": "string", + "description": "ID of the container's image" + }, + "lastState": { + "$ref": "#/definitions/kubernetes_ContainerState", + "javaType": "io.fabric8.kubernetes.api.model.ContainerState" + }, + "name": { + "type": "string", + "description": "name of the container; must be a DNS_LABEL and unique within the pod; cannot be updated", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "ready": { + "type": "boolean", + "description": "specifies whether the container has passed its readiness probe" + }, + "restartCount": { + "type": "integer", + "description": "the number of times the container has been restarted" + }, + "state": { + "$ref": "#/definitions/kubernetes_ContainerState", + "javaType": "io.fabric8.kubernetes.api.model.ContainerState" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStatus" + }, + "kubernetes_EmptyDirVolumeSource": { + "type": "object", + "description": "", + "properties": { + "medium": { + "type": "string", + "description": "type of storage used to back the volume; must be an empty string (default) or Memory; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#emptydir" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EmptyDirVolumeSource" + }, + "kubernetes_EndpointAddress": { + "type": "object", + "description": "", + "properties": { + "ip": { + "type": "string", + "description": "IP address of the endpoint" + }, + "targetRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointAddress" + }, + "kubernetes_EndpointPort": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of this port", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "port": { + "type": "integer", + "description": "port number of the endpoint" + }, + "protocol": { + "type": "string", + "description": "protocol for this port; must be UDP or TCP; TCP if unspecified" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointPort" + }, + "kubernetes_EndpointSubset": { + "type": "object", + "description": "", + "properties": { + "addresses": { + "type": "array", + "description": "IP addresses which offer the related ports", + "items": { + "$ref": "#/definitions/kubernetes_EndpointAddress", + "javaType": "io.fabric8.kubernetes.api.model.EndpointAddress" + } + }, + "ports": { + "type": "array", + "description": "port numbers available on the related IP addresses", + "items": { + "$ref": "#/definitions/kubernetes_EndpointPort", + "javaType": "io.fabric8.kubernetes.api.model.EndpointPort" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointSubset" + }, + "kubernetes_Endpoints": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Endpoints", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "subsets": { + "type": "array", + "description": "sets of addresses and ports that comprise a service", + "items": { + "$ref": "#/definitions/kubernetes_EndpointSubset", + "javaType": "io.fabric8.kubernetes.api.model.EndpointSubset" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Endpoints", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_EndpointsList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of endpoints", + "items": { + "$ref": "#/definitions/kubernetes_Endpoints", + "javaType": "io.fabric8.kubernetes.api.model.Endpoints" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "EndpointsList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointsList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_EnvVar": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the environment variable; must be a C_IDENTIFIER", + "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" + }, + "value": { + "type": "string", + "description": "value of the environment variable; defaults to empty string; variable references $(VAR_NAME) are expanded using the previously defined environment varibles in the container and any service environment variables; if a variable cannot be resolved" + }, + "valueFrom": { + "$ref": "#/definitions/kubernetes_EnvVarSource", + "javaType": "io.fabric8.kubernetes.api.model.EnvVarSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + }, + "kubernetes_EnvVarSource": { + "type": "object", + "description": "", + "properties": { + "fieldRef": { + "$ref": "#/definitions/kubernetes_ObjectFieldSelector", + "javaType": "io.fabric8.kubernetes.api.model.ObjectFieldSelector" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EnvVarSource" + }, + "kubernetes_Event": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "count": { + "type": "integer", + "description": "the number of times this event has occurred" + }, + "firstTimestamp": { + "type": "string", + "description": "the time at which the event was first recorded" + }, + "involvedObject": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "kind": { + "type": "string", + "description": "", + "default": "Event", + "required": true + }, + "lastTimestamp": { + "type": "string", + "description": "the time at which the most recent occurrence of this event was recorded" + }, + "message": { + "type": "string", + "description": "human-readable description of the status of this operation" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "reason": { + "type": "string", + "description": "short" + }, + "source": { + "$ref": "#/definitions/kubernetes_EventSource", + "javaType": "io.fabric8.kubernetes.api.model.EventSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Event", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_EventList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of events", + "items": { + "$ref": "#/definitions/kubernetes_Event", + "javaType": "io.fabric8.kubernetes.api.model.Event" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "EventList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EventList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_EventSource": { + "type": "object", + "description": "", + "properties": { + "component": { + "type": "string", + "description": "component that generated the event" + }, + "host": { + "type": "string", + "description": "name of the host where the event is generated" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EventSource" + }, + "kubernetes_ExecAction": { + "type": "object", + "description": "", + "properties": { + "command": { + "type": "array", + "description": "command line to execute inside the container; working directory for the command is root ('/') in the container's file system; the command is exec'd", + "items": { + "type": "string", + "description": "command line to execute inside the container; working directory for the command is root ('/') in the container's file system; the command is exec'd" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ExecAction" + }, + "kubernetes_GCEPersistentDiskVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "partition": { + "type": "integer", + "description": "partition on the disk to mount (e.g." + }, + "pdName": { + "type": "string", + "description": "unique name of the PD resource in GCE; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#gcepersistentdisk" + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "kubernetes_GitRepoVolumeSource": { + "type": "object", + "description": "", + "properties": { + "repository": { + "type": "string", + "description": "repository URL" + }, + "revision": { + "type": "string", + "description": "commit hash for the specified revision" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.GitRepoVolumeSource" + }, + "kubernetes_GlusterfsVolumeSource": { + "type": "object", + "description": "", + "properties": { + "endpoints": { + "type": "string", + "description": "gluster hosts endpoints name; see http://releases.k8s.io/HEAD/examples/glusterfs/README.md#create-a-pod" + }, + "path": { + "type": "string", + "description": "path to gluster volume; see http://releases.k8s.io/HEAD/examples/glusterfs/README.md#create-a-pod" + }, + "readOnly": { + "type": "boolean", + "description": "glusterfs volume to be mounted with read-only permissions; see http://releases.k8s.io/HEAD/examples/glusterfs/README.md#create-a-pod" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "kubernetes_HTTPGetAction": { + "type": "object", + "description": "", + "properties": { + "host": { + "type": "string", + "description": "hostname to connect to; defaults to pod IP" + }, + "path": { + "type": "string", + "description": "path to access on the HTTP server" + }, + "port": { + "$ref": "#/definitions/kubernetes_util_IntOrString", + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + }, + "scheme": { + "type": "string", + "description": "scheme to connect with" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.HTTPGetAction" + }, + "kubernetes_Handler": { + "type": "object", + "description": "", + "properties": { + "exec": { + "$ref": "#/definitions/kubernetes_ExecAction", + "javaType": "io.fabric8.kubernetes.api.model.ExecAction" + }, + "httpGet": { + "$ref": "#/definitions/kubernetes_HTTPGetAction", + "javaType": "io.fabric8.kubernetes.api.model.HTTPGetAction" + }, + "tcpSocket": { + "$ref": "#/definitions/kubernetes_TCPSocketAction", + "javaType": "io.fabric8.kubernetes.api.model.TCPSocketAction" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Handler" + }, + "kubernetes_HostPathVolumeSource": { + "type": "object", + "description": "", + "properties": { + "path": { + "type": "string", + "description": "path of the directory on the host; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#hostpath" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "kubernetes_ISCSIVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "iqn": { + "type": "string", + "description": "iSCSI Qualified Name" + }, + "lun": { + "type": "integer", + "description": "iscsi target lun number" + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true" + }, + "targetPortal": { + "type": "string", + "description": "iSCSI target portal" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "kubernetes_Lifecycle": { + "type": "object", + "description": "", + "properties": { + "postStart": { + "$ref": "#/definitions/kubernetes_Handler", + "javaType": "io.fabric8.kubernetes.api.model.Handler" + }, + "preStop": { + "$ref": "#/definitions/kubernetes_Handler", + "javaType": "io.fabric8.kubernetes.api.model.Handler" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Lifecycle" + }, + "kubernetes_List": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of objects", + "items": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "List", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.BaseKubernetesList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ListMeta": { + "type": "object", + "description": "", + "properties": { + "resourceVersion": { + "type": "string", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system" + }, + "selfLink": { + "type": "string", + "description": "URL for the object; populated by the system" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + }, + "kubernetes_LoadBalancerIngress": { + "type": "object", + "description": "", + "properties": { + "hostname": { + "type": "string", + "description": "hostname of ingress point" + }, + "ip": { + "type": "string", + "description": "IP address of ingress point" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerIngress" + }, + "kubernetes_LoadBalancerStatus": { + "type": "object", + "description": "", + "properties": { + "ingress": { + "type": "array", + "description": "load-balancer ingress points", + "items": { + "$ref": "#/definitions/kubernetes_LoadBalancerIngress", + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerIngress" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerStatus" + }, + "kubernetes_LocalObjectReference": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "kubernetes_MetadataFile": { + "type": "object", + "description": "", + "properties": { + "fieldRef": { + "$ref": "#/definitions/kubernetes_ObjectFieldSelector", + "javaType": "io.fabric8.kubernetes.api.model.ObjectFieldSelector" + }, + "name": { + "type": "string", + "description": "the name of the file to be created" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.MetadataFile" + }, + "kubernetes_MetadataVolumeSource": { + "type": "object", + "description": "", + "properties": { + "items": { + "type": "array", + "description": "list of metadata files", + "items": { + "$ref": "#/definitions/kubernetes_MetadataFile", + "javaType": "io.fabric8.kubernetes.api.model.MetadataFile" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.MetadataVolumeSource" + }, + "kubernetes_NFSVolumeSource": { + "type": "object", + "description": "", + "properties": { + "path": { + "type": "string", + "description": "the path that is exported by the NFS server; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs" + }, + "readOnly": { + "type": "boolean", + "description": "forces the NFS export to be mounted with read-only permissions; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs" + }, + "server": { + "type": "string", + "description": "the hostname or IP address of the NFS server; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "kubernetes_Namespace": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Namespace", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_NamespaceSpec", + "javaType": "io.fabric8.kubernetes.api.model.NamespaceSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_NamespaceStatus", + "javaType": "io.fabric8.kubernetes.api.model.NamespaceStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Namespace", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_NamespaceList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "items is the list of Namespace objects in the list; see http://releases.k8s.io/HEAD/docs/user-guide/namespaces.md", + "items": { + "$ref": "#/definitions/kubernetes_Namespace", + "javaType": "io.fabric8.kubernetes.api.model.Namespace" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "NamespaceList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamespaceList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_NamespaceSpec": { + "type": "object", + "description": "", + "properties": { + "finalizers": { + "type": "array", + "description": "an opaque list of values that must be empty to permanently remove object from storage; see http://releases.k8s.io/HEAD/docs/design/namespaces.md#finalizers", + "items": { + "type": "string", + "description": "an opaque list of values that must be empty to permanently remove object from storage; see http://releases.k8s.io/HEAD/docs/design/namespaces.md#finalizers" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamespaceSpec" + }, + "kubernetes_NamespaceStatus": { + "type": "object", + "description": "", + "properties": { + "phase": { + "type": "string", + "description": "phase is the current lifecycle phase of the namespace; see http://releases.k8s.io/HEAD/docs/design/namespaces.md#phases" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamespaceStatus" + }, + "kubernetes_Node": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Node", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_NodeSpec", + "javaType": "io.fabric8.kubernetes.api.model.NodeSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_NodeStatus", + "javaType": "io.fabric8.kubernetes.api.model.NodeStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Node", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_NodeAddress": { + "type": "object", + "description": "", + "properties": { + "address": { + "type": "string", + "description": "the node address" + }, + "type": { + "type": "string", + "description": "node address type" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeAddress" + }, + "kubernetes_NodeCondition": { + "type": "object", + "description": "", + "properties": { + "lastHeartbeatTime": { + "type": "string", + "description": "last time we got an update on a given condition" + }, + "lastTransitionTime": { + "type": "string", + "description": "last time the condition transit from one status to another" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about last transition" + }, + "reason": { + "type": "string", + "description": "(brief) reason for the condition's last transition" + }, + "status": { + "type": "string", + "description": "status of the condition" + }, + "type": { + "type": "string", + "description": "type of node condition" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeCondition" + }, + "kubernetes_NodeList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of nodes", + "items": { + "$ref": "#/definitions/kubernetes_Node", + "javaType": "io.fabric8.kubernetes.api.model.Node" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "NodeList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_NodeSpec": { + "type": "object", + "description": "", + "properties": { + "externalID": { + "type": "string", + "description": "deprecated. External ID assigned to the node by some machine database (e.g. a cloud provider). Defaults to node name when empty." + }, + "podCIDR": { + "type": "string", + "description": "pod IP range assigned to the node" + }, + "providerID": { + "type": "string", + "description": "ID of the node assigned by the cloud provider in the format: \u003cProviderName\u003e://\u003cProviderSpecificNodeID\u003e" + }, + "unschedulable": { + "type": "boolean", + "description": "disable pod scheduling on the node; see http://releases.k8s.io/HEAD/docs/admin/node.md#manual-node-administration" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeSpec" + }, + "kubernetes_NodeStatus": { + "type": "object", + "description": "", + "properties": { + "addresses": { + "type": "array", + "description": "list of addresses reachable to the node; see http://releases.k8s.io/HEAD/docs/admin/node.md#node-addresses", + "items": { + "$ref": "#/definitions/kubernetes_NodeAddress", + "javaType": "io.fabric8.kubernetes.api.model.NodeAddress" + } + }, + "capacity": { + "type": "object", + "description": "compute resource capacity of the node; see http://releases.k8s.io/HEAD/docs/user-guide/compute-resources.md", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "conditions": { + "type": "array", + "description": "list of node conditions observed; see http://releases.k8s.io/HEAD/docs/admin/node.md#node-condition", + "items": { + "$ref": "#/definitions/kubernetes_NodeCondition", + "javaType": "io.fabric8.kubernetes.api.model.NodeCondition" + } + }, + "nodeInfo": { + "$ref": "#/definitions/kubernetes_NodeSystemInfo", + "javaType": "io.fabric8.kubernetes.api.model.NodeSystemInfo" + }, + "phase": { + "type": "string", + "description": "most recently observed lifecycle phase of the node; see http://releases.k8s.io/HEAD/docs/admin/node.md#node-phase" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeStatus" + }, + "kubernetes_NodeSystemInfo": { + "type": "object", + "description": "", + "properties": { + "bootID": { + "type": "string", + "description": "boot id is the boot-id reported by the node" + }, + "containerRuntimeVersion": { + "type": "string", + "description": "Container runtime version reported by the node through runtime remote API (e.g. docker://1.5.0)" + }, + "kernelVersion": { + "type": "string", + "description": "Kernel version reported by the node from 'uname -r' (e.g. 3.16.0-0.bpo.4-amd64)" + }, + "kubeProxyVersion": { + "type": "string", + "description": "Kube-proxy version reported by the node" + }, + "kubeletVersion": { + "type": "string", + "description": "Kubelet version reported by the node" + }, + "machineID": { + "type": "string", + "description": "machine-id reported by the node" + }, + "osImage": { + "type": "string", + "description": "OS image used reported by the node from /etc/os-release (e.g. Debian GNU/Linux 7 (wheezy))" + }, + "systemUUID": { + "type": "string", + "description": "system-uuid reported by the node" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeSystemInfo" + }, + "kubernetes_ObjectFieldSelector": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "version of the schema that fieldPath is written in terms of; defaults to v1" + }, + "fieldPath": { + "type": "string", + "description": "path of the field to select in the specified API version" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ObjectFieldSelector" + }, + "kubernetes_ObjectMeta": { + "type": "object", + "description": "", + "properties": { + "annotations": { + "type": "object", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about objects; see http://releases.k8s.io/HEAD/docs/user-guide/annotations.md", + "additionalProperties": { + "type": "string", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about objects; see http://releases.k8s.io/HEAD/docs/user-guide/annotations.md" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; populated by the system" + }, + "deletionTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object will be deleted; populated by the system when a graceful deletion is requested" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional" + }, + "generation": { + "type": "integer", + "description": "a sequence number representing a specific generation of the desired state; populated by the system; read-only", + "javaType": "Long" + }, + "labels": { + "type": "object", + "description": "map of string keys and values that can be used to organize and categorize objects; may match selectors of replication controllers and services; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md", + "additionalProperties": { + "type": "string", + "description": "map of string keys and values that can be used to organize and categorize objects; may match selectors of replication controllers and services; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "name": { + "type": "string", + "description": "string that identifies an object. Must be unique within a namespace; cannot be updated; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "namespace": { + "type": "string", + "description": "namespace of the object; must be a DNS_LABEL; cannot be updated; see http://releases.k8s.io/HEAD/docs/user-guide/namespaces.md", + "maxLength": 253, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" + }, + "resourceVersion": { + "type": "string", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system" + }, + "selfLink": { + "type": "string", + "description": "URL for the object; populated by the system" + }, + "uid": { + "type": "string", + "description": "unique UUID across space and time; populated by the system; read-only; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#uids" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "kubernetes_ObjectReference": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "API version of the referent" + }, + "fieldPath": { + "type": "string", + "description": "if referring to a piece of an object instead of an entire object" + }, + "kind": { + "type": "string", + "description": "kind of the referent; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds" + }, + "name": { + "type": "string", + "description": "name of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names" + }, + "namespace": { + "type": "string", + "description": "namespace of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/namespaces.md" + }, + "resourceVersion": { + "type": "string", + "description": "specific resourceVersion to which this reference is made" + }, + "uid": { + "type": "string", + "description": "uid of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#uids" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "kubernetes_PersistentVolume": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolume", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PersistentVolumeSpec", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_PersistentVolumeStatus", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolume", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_PersistentVolumeClaim": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolumeClaim", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimSpec", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimStatus", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaim", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_PersistentVolumeClaimList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "a list of persistent volume claims; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#persistentvolumeclaims", + "items": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaim", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaim" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolumeClaimList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_PersistentVolumeClaimSpec": { + "type": "object", + "description": "", + "properties": { + "accessModes": { + "type": "array", + "description": "the desired access modes the volume should have; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1", + "items": { + "type": "string", + "description": "the desired access modes the volume should have; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1" + } + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "volumeName": { + "type": "string", + "description": "the binding reference to the persistent volume backing this claim" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimSpec" + }, + "kubernetes_PersistentVolumeClaimStatus": { + "type": "object", + "description": "", + "properties": { + "accessModes": { + "type": "array", + "description": "the actual access modes the volume has; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1", + "items": { + "type": "string", + "description": "the actual access modes the volume has; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1" + } + }, + "capacity": { + "type": "object", + "description": "the actual resources the volume has", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "phase": { + "type": "string", + "description": "the current phase of the claim" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimStatus" + }, + "kubernetes_PersistentVolumeClaimVolumeSource": { + "type": "object", + "description": "", + "properties": { + "claimName": { + "type": "string", + "description": "the name of the claim in the same namespace to be mounted as a volume; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#persistentvolumeclaims" + }, + "readOnly": { + "type": "boolean", + "description": "mount volume as read-only when true; default false" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource" + }, + "kubernetes_PersistentVolumeList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of persistent volumes; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md", + "items": { + "$ref": "#/definitions/kubernetes_PersistentVolume", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolume" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolumeList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_PersistentVolumeSource": { + "type": "object", + "description": "", + "properties": { + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeSource" + }, + "kubernetes_PersistentVolumeSpec": { + "type": "object", + "description": "", + "properties": { + "accessModes": { + "type": "array", + "description": "all ways the volume can be mounted; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes", + "items": { + "type": "string", + "description": "all ways the volume can be mounted; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes" + } + }, + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "capacity": { + "type": "object", + "description": "a description of the persistent volume's resources and capacityr; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#capacity", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "claimRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "persistentVolumeReclaimPolicy": { + "type": "string", + "description": "what happens to a volume when released from its claim; Valid options are Retain (default) and Recycle. Recyling must be supported by the volume plugin underlying this persistent volume. See http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#recycling-policy" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeSpec" + }, + "kubernetes_PersistentVolumeStatus": { + "type": "object", + "description": "", + "properties": { + "message": { + "type": "string", + "description": "human-readable message indicating details about why the volume is in this state" + }, + "phase": { + "type": "string", + "description": "the current phase of a persistent volume; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#phase" + }, + "reason": { + "type": "string", + "description": "(brief) reason the volume is not is not available" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeStatus" + }, + "kubernetes_Pod": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Pod", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PodSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_PodStatus", + "javaType": "io.fabric8.kubernetes.api.model.PodStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Pod", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_PodCondition": { + "type": "object", + "description": "", + "properties": { + "status": { + "type": "string", + "description": "status of the condition" + }, + "type": { + "type": "string", + "description": "kind of the condition" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodCondition" + }, + "kubernetes_PodList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of pods; see http://releases.k8s.io/HEAD/docs/user-guide/pods.md", + "items": { + "$ref": "#/definitions/kubernetes_Pod", + "javaType": "io.fabric8.kubernetes.api.model.Pod" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PodList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_PodSpec": { + "type": "object", + "description": "", + "properties": { + "activeDeadlineSeconds": { + "type": "integer", + "description": "", + "javaType": "Long" + }, + "containers": { + "type": "array", + "description": "list of containers belonging to the pod; cannot be updated; containers cannot currently be added or removed; there must be at least one container in a Pod; see http://releases.k8s.io/HEAD/docs/user-guide/containers.md", + "items": { + "$ref": "#/definitions/kubernetes_Container", + "javaType": "io.fabric8.kubernetes.api.model.Container" + } + }, + "dnsPolicy": { + "type": "string", + "description": "DNS policy for containers within the pod; one of 'ClusterFirst' or 'Default'" + }, + "host": { + "type": "string", + "description": "deprecated" + }, + "hostNetwork": { + "type": "boolean", + "description": "host networking requested for this pod" + }, + "imagePullSecrets": { + "type": "array", + "description": "list of references to secrets in the same namespace available for pulling the container images; see http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod", + "items": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "nodeName": { + "type": "string", + "description": "node requested for this pod" + }, + "nodeSelector": { + "type": "object", + "description": "selector which must match a node's labels for the pod to be scheduled on that node; see http://releases.k8s.io/HEAD/docs/user-guide/node-selection/README.md", + "additionalProperties": { + "type": "string", + "description": "selector which must match a node's labels for the pod to be scheduled on that node; see http://releases.k8s.io/HEAD/docs/user-guide/node-selection/README.md" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "restartPolicy": { + "type": "string", + "description": "restart policy for all containers within the pod; one of Always" + }, + "serviceAccount": { + "type": "string", + "description": "deprecated; use serviceAccountName instead" + }, + "serviceAccountName": { + "type": "string", + "description": "name of the ServiceAccount to use to run this pod; see http://releases.k8s.io/HEAD/docs/design/service_accounts.md" + }, + "terminationGracePeriodSeconds": { + "type": "integer", + "description": "optional duration in seconds the pod needs to terminate gracefully; may be decreased in delete request; value must be non-negative integer; the value zero indicates delete immediately; if this value is not set", + "javaType": "Long" + }, + "volumes": { + "type": "array", + "description": "list of volumes that can be mounted by containers belonging to the pod; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md", + "items": { + "$ref": "#/definitions/kubernetes_Volume", + "javaType": "io.fabric8.kubernetes.api.model.Volume" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodSpec" + }, + "kubernetes_PodStatus": { + "type": "object", + "description": "", + "properties": { + "conditions": { + "type": "array", + "description": "current service state of pod; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#pod-conditions", + "items": { + "$ref": "#/definitions/kubernetes_PodCondition", + "javaType": "io.fabric8.kubernetes.api.model.PodCondition" + } + }, + "containerStatuses": { + "type": "array", + "description": "list of container statuses; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-statuses", + "items": { + "$ref": "#/definitions/kubernetes_ContainerStatus", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStatus" + } + }, + "hostIP": { + "type": "string", + "description": "IP address of the host to which the pod is assigned; empty if not yet scheduled" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about why the pod is in this condition" + }, + "phase": { + "type": "string", + "description": "current condition of the pod; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#pod-phase" + }, + "podIP": { + "type": "string", + "description": "IP address allocated to the pod; routable at least within the cluster; empty if not yet allocated" + }, + "reason": { + "type": "string", + "description": "(brief-CamelCase) reason indicating details about why the pod is in this condition" + }, + "startTime": { + "type": "string", + "description": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod." + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodStatus" + }, + "kubernetes_PodTemplateSpec": { + "type": "object", + "description": "", + "properties": { + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PodSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodSpec" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodTemplateSpec" + }, + "kubernetes_Probe": { + "type": "object", + "description": "", + "properties": { + "exec": { + "$ref": "#/definitions/kubernetes_ExecAction", + "javaType": "io.fabric8.kubernetes.api.model.ExecAction" + }, + "httpGet": { + "$ref": "#/definitions/kubernetes_HTTPGetAction", + "javaType": "io.fabric8.kubernetes.api.model.HTTPGetAction" + }, + "initialDelaySeconds": { + "type": "integer", + "description": "number of seconds after the container has started before liveness probes are initiated; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes", + "javaType": "Long" + }, + "tcpSocket": { + "$ref": "#/definitions/kubernetes_TCPSocketAction", + "javaType": "io.fabric8.kubernetes.api.model.TCPSocketAction" + }, + "timeoutSeconds": { + "type": "integer", + "description": "number of seconds after which liveness probes timeout; defaults to 1 second; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes", + "javaType": "Long" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Probe" + }, + "kubernetes_RBDVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "image": { + "type": "string", + "description": "rados image name; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "keyring": { + "type": "string", + "description": "keyring is the path to key ring for rados user; default is /etc/ceph/keyring; optional; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "monitors": { + "type": "array", + "description": "a collection of Ceph monitors; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it", + "items": { + "type": "string", + "description": "a collection of Ceph monitors; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + } + }, + "pool": { + "type": "string", + "description": "rados pool name; default is rbd; optional; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "readOnly": { + "type": "boolean", + "description": "rbd volume to be mounted with read-only permissions; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "secretRef": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "user": { + "type": "string", + "description": "rados user name; default is admin; optional; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + }, + "kubernetes_ReplicationController": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ReplicationController", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_ReplicationControllerSpec", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_ReplicationControllerStatus", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationController", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ReplicationControllerList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of replication controllers; see http://releases.k8s.io/HEAD/docs/user-guide/replication-controller.md", + "items": { + "$ref": "#/definitions/kubernetes_ReplicationController", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationController" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ReplicationControllerList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ReplicationControllerSpec": { + "type": "object", + "description": "", + "properties": { + "replicas": { + "type": "integer", + "description": "number of replicas desired; defaults to 1; see http://releases.k8s.io/HEAD/docs/user-guide/replication-controller.md#what-is-a-replication-controller" + }, + "selector": { + "type": "object", + "description": "label keys and values that must match in order to be controlled by this replication controller", + "additionalProperties": { + "type": "string", + "description": "label keys and values that must match in order to be controlled by this replication controller" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "template": { + "$ref": "#/definitions/kubernetes_PodTemplateSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodTemplateSpec" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerSpec" + }, + "kubernetes_ReplicationControllerStatus": { + "type": "object", + "description": "", + "properties": { + "observedGeneration": { + "type": "integer", + "description": "reflects the generation of the most recently observed replication controller", + "javaType": "Long" + }, + "replicas": { + "type": "integer", + "description": "most recently oberved number of replicas; see http://releases.k8s.io/HEAD/docs/user-guide/replication-controller.md#what-is-a-replication-controller" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerStatus" + }, + "kubernetes_ResourceQuota": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ResourceQuota", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_ResourceQuotaSpec", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_ResourceQuotaStatus", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuota", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ResourceQuotaList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "items is a list of ResourceQuota objects; see http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", + "items": { + "$ref": "#/definitions/kubernetes_ResourceQuota", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuota" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ResourceQuotaList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ResourceQuotaSpec": { + "type": "object", + "description": "", + "properties": { + "hard": { + "type": "object", + "description": "hard is the set of desired hard limits for each named resource; see http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaSpec" + }, + "kubernetes_ResourceQuotaStatus": { + "type": "object", + "description": "", + "properties": { + "hard": { + "type": "object", + "description": "hard is the set of enforced hard limits for each named resource; see http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "used": { + "type": "object", + "description": "used is the current observed total usage of the resource in the namespace", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaStatus" + }, + "kubernetes_ResourceRequirements": { + "type": "object", + "description": "", + "properties": { + "limits": { + "type": "object", + "description": "Maximum amount of compute resources allowed; see http://releases.k8s.io/HEAD/docs/design/resources.md#resource-specifications", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "requests": { + "type": "object", + "description": "Minimum amount of resources requested; if Requests is omitted for a container", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "kubernetes_RunAsUserStrategyOptions": { + "type": "object", + "description": "", + "properties": { + "type": { + "type": "string", + "description": "strategy used to generate RunAsUser" + }, + "uid": { + "type": "integer", + "description": "the uid to always run as; required for MustRunAs", + "javaType": "Long" + }, + "uidRangeMax": { + "type": "integer", + "description": "max value for range based allocators", + "javaType": "Long" + }, + "uidRangeMin": { + "type": "integer", + "description": "min value for range based allocators", + "javaType": "Long" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.RunAsUserStrategyOptions" + }, + "kubernetes_SELinuxContextStrategyOptions": { + "type": "object", + "description": "", + "properties": { + "seLinuxOptions": { + "$ref": "#/definitions/kubernetes_SELinuxOptions", + "javaType": "io.fabric8.kubernetes.api.model.SELinuxOptions" + }, + "type": { + "type": "string", + "description": "strategy used to generate the SELinux context" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SELinuxContextStrategyOptions" + }, + "kubernetes_SELinuxOptions": { + "type": "object", + "description": "", + "properties": { + "level": { + "type": "string", + "description": "the level label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "role": { + "type": "string", + "description": "the role label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "type": { + "type": "string", + "description": "the type label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "user": { + "type": "string", + "description": "the user label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SELinuxOptions" + }, + "kubernetes_Secret": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "data": { + "type": "object", + "description": "data contains the secret data. Each key must be a valid DNS_SUBDOMAIN or leading dot followed by valid DNS_SUBDOMAIN. Each value must be a base64 encoded string as described in https://tools.ietf.org/html/rfc4648#section-4", + "additionalProperties": { + "type": "string", + "description": "data contains the secret data. Each key must be a valid DNS_SUBDOMAIN or leading dot followed by valid DNS_SUBDOMAIN. Each value must be a base64 encoded string as described in https://tools.ietf.org/html/rfc4648#section-4" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "kind": { + "type": "string", + "description": "", + "default": "Secret", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "type": { + "type": "string", + "description": "type facilitates programmatic handling of secret data" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Secret", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_SecretList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "items is a list of secret objects; see http://releases.k8s.io/HEAD/docs/user-guide/secrets.md", + "items": { + "$ref": "#/definitions/kubernetes_Secret", + "javaType": "io.fabric8.kubernetes.api.model.Secret" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SecretList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecretList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_SecretVolumeSource": { + "type": "object", + "description": "", + "properties": { + "secretName": { + "type": "string", + "description": "secretName is the name of a secret in the pod's namespace; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#secrets" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource" + }, + "kubernetes_SecurityContext": { + "type": "object", + "description": "", + "properties": { + "capabilities": { + "$ref": "#/definitions/kubernetes_Capabilities", + "javaType": "io.fabric8.kubernetes.api.model.Capabilities" + }, + "privileged": { + "type": "boolean", + "description": "run the container in privileged mode; see http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context" + }, + "runAsNonRoot": { + "type": "boolean", + "description": "indicates the container must be run as a non-root user either by specifying the runAsUser or in the image specification" + }, + "runAsUser": { + "type": "integer", + "description": "the user id that runs the first process in the container; see http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context", + "javaType": "Long" + }, + "seLinuxOptions": { + "$ref": "#/definitions/kubernetes_SELinuxOptions", + "javaType": "io.fabric8.kubernetes.api.model.SELinuxOptions" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecurityContext" + }, + "kubernetes_SecurityContextConstraints": { + "type": "object", + "description": "", + "properties": { + "allowHostDirVolumePlugin": { + "type": "boolean", + "description": "allow the use of the host dir volume plugin" + }, + "allowHostNetwork": { + "type": "boolean", + "description": "allow the use of the hostNetwork in the pod spec" + }, + "allowHostPorts": { + "type": "boolean", + "description": "allow the use of the host ports in the containers" + }, + "allowPrivilegedContainer": { + "type": "boolean", + "description": "allow containers to run as privileged" + }, + "allowedCapabilities": { + "type": "array", + "description": "capabilities that are allowed to be added", + "items": { + "type": "string", + "description": "capabilities that are allowed to be added" + } + }, + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "groups": { + "type": "array", + "description": "groups allowed to use this SecurityContextConstraints", + "items": { + "type": "string", + "description": "groups allowed to use this SecurityContextConstraints" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SecurityContextConstraints", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "runAsUser": { + "$ref": "#/definitions/kubernetes_RunAsUserStrategyOptions", + "javaType": "io.fabric8.kubernetes.api.model.RunAsUserStrategyOptions" + }, + "seLinuxContext": { + "$ref": "#/definitions/kubernetes_SELinuxContextStrategyOptions", + "javaType": "io.fabric8.kubernetes.api.model.SELinuxContextStrategyOptions" + }, + "users": { + "type": "array", + "description": "users allowed to use this SecurityContextConstraints", + "items": { + "type": "string", + "description": "users allowed to use this SecurityContextConstraints" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraints", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_SecurityContextConstraintsList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_SecurityContextConstraints", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraints" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SecurityContextConstraintsList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraintsList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_Service": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Service", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_ServiceSpec", + "javaType": "io.fabric8.kubernetes.api.model.ServiceSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_ServiceStatus", + "javaType": "io.fabric8.kubernetes.api.model.ServiceStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Service", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ServiceAccount": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "imagePullSecrets": { + "type": "array", + "description": "list of references to secrets in the same namespace available for pulling container images; see http://releases.k8s.io/HEAD/docs/user-guide/secrets.md#manually-specifying-an-imagepullsecret", + "items": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ServiceAccount", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "secrets": { + "type": "array", + "description": "list of secrets that can be used by pods running as this service account; see http://releases.k8s.io/HEAD/docs/user-guide/secrets.md", + "items": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccount", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ServiceAccountList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of ServiceAccounts; see http://releases.k8s.io/HEAD/docs/design/service_accounts.md#service-accounts", + "items": { + "$ref": "#/definitions/kubernetes_ServiceAccount", + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccount" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ServiceAccountList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccountList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ServiceList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of services", + "items": { + "$ref": "#/definitions/kubernetes_Service", + "javaType": "io.fabric8.kubernetes.api.model.Service" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ServiceList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ServicePort": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "the name of this port; optional if only one port is defined", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "nodePort": { + "type": "integer", + "description": "the port on each node on which this service is exposed when type=NodePort or LoadBalancer; usually assigned by the system; if specified" + }, + "port": { + "type": "integer", + "description": "the port number that is exposed" + }, + "protocol": { + "type": "string", + "description": "the protocol used by this port; must be UDP or TCP; TCP if unspecified" + }, + "targetPort": { + "$ref": "#/definitions/kubernetes_util_IntOrString", + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServicePort" + }, + "kubernetes_ServiceSpec": { + "type": "object", + "description": "", + "properties": { + "clusterIP": { + "type": "string", + "description": "IP address of the service; usually assigned by the system; if specified" + }, + "deprecatedPublicIPs": { + "type": "array", + "description": "deprecated. externally visible IPs (e.g. load balancers) that should be proxied to this service", + "items": { + "type": "string", + "description": "deprecated. externally visible IPs (e.g. load balancers) that should be proxied to this service" + } + }, + "portalIP": { + "type": "string", + "description": "deprecated" + }, + "ports": { + "type": "array", + "description": "ports exposed by the service; see http://releases.k8s.io/HEAD/docs/user-guide/services.md#virtual-ips-and-service-proxies", + "items": { + "$ref": "#/definitions/kubernetes_ServicePort", + "javaType": "io.fabric8.kubernetes.api.model.ServicePort" + } + }, + "selector": { + "type": "object", + "description": "label keys and values that must match in order to receive traffic for this service; if empty", + "additionalProperties": { + "type": "string", + "description": "label keys and values that must match in order to receive traffic for this service; if empty" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "sessionAffinity": { + "type": "string", + "description": "enable client IP based session affinity; must be ClientIP or None; defaults to None; see http://releases.k8s.io/HEAD/docs/user-guide/services.md#virtual-ips-and-service-proxies" + }, + "type": { + "type": "string", + "description": "type of this service; must be ClusterIP" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceSpec" + }, + "kubernetes_ServiceStatus": { + "type": "object", + "description": "", + "properties": { + "loadBalancer": { + "$ref": "#/definitions/kubernetes_LoadBalancerStatus", + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceStatus" + }, + "kubernetes_Status": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "code": { + "type": "integer", + "description": "suggested HTTP return code for this status; 0 if not set" + }, + "details": { + "$ref": "#/definitions/kubernetes_StatusDetails", + "javaType": "io.fabric8.kubernetes.api.model.StatusDetails" + }, + "kind": { + "type": "string", + "description": "", + "default": "Status", + "required": true + }, + "message": { + "type": "string", + "description": "human-readable description of the status of this operation" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + }, + "reason": { + "type": "string", + "description": "machine-readable description of why this operation is in the 'Failure' status; if this value is empty there is no information available; a reason clarifies an HTTP status code but does not override it" + }, + "status": { + "type": "string", + "description": "status of the operation; either Success" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Status" + }, + "kubernetes_StatusCause": { + "type": "object", + "description": "", + "properties": { + "field": { + "type": "string", + "description": "field of the resource that has caused this error" + }, + "message": { + "type": "string", + "description": "human-readable description of the cause of the error; this field may be presented as-is to a reader" + }, + "reason": { + "type": "string", + "description": "machine-readable description of the cause of the error; if this value is empty there is no information available" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.StatusCause" + }, + "kubernetes_StatusDetails": { + "type": "object", + "description": "", + "properties": { + "causes": { + "type": "array", + "description": "the Causes array includes more details associated with the StatusReason failure; not all StatusReasons may provide detailed causes", + "items": { + "$ref": "#/definitions/kubernetes_StatusCause", + "javaType": "io.fabric8.kubernetes.api.model.StatusCause" + } + }, + "kind": { + "type": "string", + "description": "the kind attribute of the resource associated with the status StatusReason; on some operations may differ from the requested resource Kind; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds" + }, + "name": { + "type": "string", + "description": "the name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)" + }, + "retryAfterSeconds": { + "type": "integer", + "description": "the number of seconds before the client should attempt to retry this operation" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.StatusDetails" + }, + "kubernetes_TCPSocketAction": { + "type": "object", + "description": "", + "properties": { + "port": { + "$ref": "#/definitions/kubernetes_util_IntOrString", + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.TCPSocketAction" + }, + "kubernetes_TypeMeta": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources" + }, + "kind": { + "type": "string", + "description": "kind of object" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.TypeMeta" + }, + "kubernetes_Volume": { + "type": "object", + "description": "", + "properties": { + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "emptyDir": { + "$ref": "#/definitions/kubernetes_EmptyDirVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.EmptyDirVolumeSource" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "gitRepo": { + "$ref": "#/definitions/kubernetes_GitRepoVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GitRepoVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_MetadataVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.MetadataVolumeSource" + }, + "name": { + "type": "string", + "description": "volume name; must be a DNS_LABEL and unique within the pod; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "persistentVolumeClaim": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + }, + "secret": { + "$ref": "#/definitions/kubernetes_SecretVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Volume" + }, + "kubernetes_VolumeMount": { + "type": "object", + "description": "", + "properties": { + "mountPath": { + "type": "string", + "description": "path within the container at which the volume should be mounted" + }, + "name": { + "type": "string", + "description": "name of the volume to mount" + }, + "readOnly": { + "type": "boolean", + "description": "mounted read-only if true" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.VolumeMount" + }, + "kubernetes_VolumeSource": { + "type": "object", + "description": "", + "properties": { + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "emptyDir": { + "$ref": "#/definitions/kubernetes_EmptyDirVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.EmptyDirVolumeSource" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "gitRepo": { + "$ref": "#/definitions/kubernetes_GitRepoVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GitRepoVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_MetadataVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.MetadataVolumeSource" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "persistentVolumeClaim": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + }, + "secret": { + "$ref": "#/definitions/kubernetes_SecretVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.VolumeSource" + }, + "kubernetes_config_AuthInfo": { + "type": "object", + "description": "", + "properties": { + "client-certificate": { + "type": "string", + "description": "" + }, + "client-certificate-data": { + "type": "string", + "description": "" + }, + "client-key": { + "type": "string", + "description": "" + }, + "client-key-data": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "password": { + "type": "string", + "description": "" + }, + "token": { + "type": "string", + "description": "" + }, + "username": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.AuthInfo" + }, + "kubernetes_config_Cluster": { + "type": "object", + "description": "", + "properties": { + "api-version": { + "type": "string", + "description": "" + }, + "certificate-authority": { + "type": "string", + "description": "" + }, + "certificate-authority-data": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "insecure-skip-tls-verify": { + "type": "boolean", + "description": "" + }, + "server": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Cluster" + }, + "kubernetes_config_Config": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "" + }, + "clusters": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedCluster", + "javaType": "io.fabric8.kubernetes.api.model.NamedCluster" + } + }, + "contexts": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedContext", + "javaType": "io.fabric8.kubernetes.api.model.NamedContext" + } + }, + "current-context": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "kind": { + "type": "string", + "description": "" + }, + "preferences": { + "$ref": "#/definitions/kubernetes_config_Preferences", + "javaType": "io.fabric8.kubernetes.api.model.Preferences" + }, + "users": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedAuthInfo", + "javaType": "io.fabric8.kubernetes.api.model.NamedAuthInfo" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Config" + }, + "kubernetes_config_Context": { + "type": "object", + "description": "", + "properties": { + "cluster": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "namespace": { + "type": "string", + "description": "" + }, + "user": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Context" + }, + "kubernetes_config_NamedAuthInfo": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "" + }, + "user": { + "$ref": "#/definitions/kubernetes_config_AuthInfo", + "javaType": "io.fabric8.kubernetes.api.model.AuthInfo" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedAuthInfo" + }, + "kubernetes_config_NamedCluster": { + "type": "object", + "description": "", + "properties": { + "cluster": { + "$ref": "#/definitions/kubernetes_config_Cluster", + "javaType": "io.fabric8.kubernetes.api.model.Cluster" + }, + "name": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedCluster" + }, + "kubernetes_config_NamedContext": { + "type": "object", + "description": "", + "properties": { + "context": { + "$ref": "#/definitions/kubernetes_config_Context", + "javaType": "io.fabric8.kubernetes.api.model.Context" + }, + "name": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedContext" + }, + "kubernetes_config_NamedExtension": { + "type": "object", + "description": "", + "properties": { + "extension": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "name": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + }, + "kubernetes_config_Preferences": { + "type": "object", + "description": "", + "properties": { + "colors": { + "type": "boolean", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Preferences" + }, + "kubernetes_resource_Quantity": { + "type": "object", + "description": "", + "properties": { + "Amount": { + "$ref": "#/definitions/speter_inf_Dec", + "javaType": "io.fabric8.openshift.api.model.Dec" + }, + "Format": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "kubernetes_runtime_RawExtension": { + "type": "object", + "description": "", + "properties": { + "RawJSON": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "kubernetes_util_IntOrString": { + "type": "object", + "description": "", + "properties": { + "IntVal": { + "type": "integer", + "description": "" + }, + "Kind": { + "type": "integer", + "description": "" + }, + "StrVal": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + }, + "kubernetes_watch_WatchEvent": { + "type": "object", + "description": "", + "properties": { + "object": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "type": { + "type": "string", + "description": "the type of watch event; may be ADDED" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.WatchEvent" + }, + "os_authorization_AuthorizationAttributes": { + "type": "object", + "description": "", + "properties": { + "content": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "namespace": { + "type": "string", + "description": "namespace of the action being requested" + }, + "resource": { + "type": "string", + "description": "one of the existing resource types" + }, + "resourceName": { + "type": "string", + "description": "name of the resource being requested for a get or delete" + }, + "verb": { + "type": "string", + "description": "one of get" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.AuthorizationAttributes" + }, + "os_authorization_ClusterPolicy": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicy", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time any part of the object was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roles": { + "type": "array", + "description": "all the roles held by this policy", + "items": { + "$ref": "#/definitions/os_authorization_NamedClusterRole", + "javaType": "io.fabric8.openshift.api.model.NamedClusterRole" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicy", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterPolicyBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicyBinding", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time any part of the object was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "policyRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "roleBindings": { + "type": "array", + "description": "all the role bindings held by this policy", + "items": { + "$ref": "#/definitions/os_authorization_NamedClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.NamedClusterRoleBinding" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterPolicyBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of cluster policy bindings", + "items": { + "$ref": "#/definitions/os_authorization_ClusterPolicyBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicyBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_ClusterPolicyList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of cluster policies", + "items": { + "$ref": "#/definitions/os_authorization_ClusterPolicy", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicy" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicyList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_ClusterRole": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterRole", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "rules": { + "type": "array", + "description": "list of policy rules", + "items": { + "$ref": "#/definitions/os_authorization_PolicyRule", + "javaType": "io.fabric8.openshift.api.model.PolicyRule" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterRole", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterRoleBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "groupNames": { + "type": "array", + "description": "all the groups directly bound to the role", + "items": { + "type": "string", + "description": "all the groups directly bound to the role" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterRoleBinding", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roleRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "subjects": { + "type": "array", + "description": "references to subjects bound to the role. Only User", + "items": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "userNames": { + "type": "array", + "description": "all user names directly bound to the role", + "items": { + "type": "string", + "description": "all user names directly bound to the role" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterRoleBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of cluster role bindings", + "items": { + "$ref": "#/definitions/os_authorization_ClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterRoleBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_LocalSubjectAccessReview": { + "type": "object", + "description": "", + "properties": { + "TypeMeta": { + "$ref": "#/definitions/kubernetes_TypeMeta", + "javaType": "io.fabric8.kubernetes.api.model.TypeMeta" + }, + "content": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "groups": { + "type": "array", + "description": "optional", + "items": { + "type": "string", + "description": "optional" + } + }, + "namespace": { + "type": "string", + "description": "namespace of the action being requested" + }, + "resource": { + "type": "string", + "description": "one of the existing resource types" + }, + "resourceName": { + "type": "string", + "description": "name of the resource being requested for a get or delete" + }, + "user": { + "type": "string", + "description": "optional" + }, + "verb": { + "type": "string", + "description": "one of get" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.LocalSubjectAccessReview" + }, + "os_authorization_NamedClusterRole": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the cluster role" + }, + "role": { + "$ref": "#/definitions/os_authorization_ClusterRole", + "javaType": "io.fabric8.openshift.api.model.ClusterRole" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedClusterRole" + }, + "os_authorization_NamedClusterRoleBinding": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the cluster role binding" + }, + "roleBinding": { + "$ref": "#/definitions/os_authorization_ClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedClusterRoleBinding" + }, + "os_authorization_NamedRole": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the role" + }, + "role": { + "$ref": "#/definitions/os_authorization_Role", + "javaType": "io.fabric8.openshift.api.model.Role" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedRole" + }, + "os_authorization_NamedRoleBinding": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the roleBinding" + }, + "roleBinding": { + "$ref": "#/definitions/os_authorization_RoleBinding", + "javaType": "io.fabric8.openshift.api.model.RoleBinding" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedRoleBinding" + }, + "os_authorization_Policy": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Policy", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time that any part of the policy was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roles": { + "type": "array", + "description": "roles held by this policy", + "items": { + "$ref": "#/definitions/os_authorization_NamedRole", + "javaType": "io.fabric8.openshift.api.model.NamedRole" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Policy", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_PolicyBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "PolicyBinding", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time that any part of the object was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "policyRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "roleBindings": { + "type": "array", + "description": "all roleBindings held by this policyBinding", + "items": { + "$ref": "#/definitions/os_authorization_NamedRoleBinding", + "javaType": "io.fabric8.openshift.api.model.NamedRoleBinding" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_PolicyBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of policy bindings", + "items": { + "$ref": "#/definitions/os_authorization_PolicyBinding", + "javaType": "io.fabric8.openshift.api.model.PolicyBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PolicyBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_PolicyList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of policies", + "items": { + "$ref": "#/definitions/os_authorization_Policy", + "javaType": "io.fabric8.openshift.api.model.Policy" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PolicyList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_PolicyRule": { + "type": "object", + "description": "", + "properties": { + "attributeRestrictions": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "nonResourceURLs": { + "type": "array", + "description": "set of partial urls that a user should have access to. *s are allowed", + "items": { + "type": "string", + "description": "set of partial urls that a user should have access to. *s are allowed" + } + }, + "resourceNames": { + "type": "array", + "description": "optional white list of names that the rule applies to. An empty set means that everything is allowed.", + "items": { + "type": "string", + "description": "optional white list of names that the rule applies to. An empty set means that everything is allowed." + } + }, + "resources": { + "type": "array", + "description": "list of resources this rule applies to. * represents all resources.", + "items": { + "type": "string", + "description": "list of resources this rule applies to. * represents all resources." + } + }, + "verbs": { + "type": "array", + "description": "list of verbs that apply to ALL the resourceKinds and attributeRestrictions contained in this rule. The verb * represents all kinds.", + "items": { + "type": "string", + "description": "list of verbs that apply to ALL the resourceKinds and attributeRestrictions contained in this rule. The verb * represents all kinds." + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyRule" + }, + "os_authorization_Role": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Role", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "rules": { + "type": "array", + "description": "all the rules for this role", + "items": { + "$ref": "#/definitions/os_authorization_PolicyRule", + "javaType": "io.fabric8.openshift.api.model.PolicyRule" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Role", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_RoleBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "groupNames": { + "type": "array", + "description": "all the groups directly bound to the role", + "items": { + "type": "string", + "description": "all the groups directly bound to the role" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RoleBinding", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roleRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "subjects": { + "type": "array", + "description": "references to subjects bound to the role. Only User", + "items": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "userNames": { + "type": "array", + "description": "all the usernames directly bound to the role", + "items": { + "type": "string", + "description": "all the usernames directly bound to the role" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RoleBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_RoleBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of role bindings", + "items": { + "$ref": "#/definitions/os_authorization_RoleBinding", + "javaType": "io.fabric8.openshift.api.model.RoleBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RoleBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RoleBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_RoleList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of roles", + "items": { + "$ref": "#/definitions/os_authorization_Role", + "javaType": "io.fabric8.openshift.api.model.Role" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RoleList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RoleList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_SubjectAccessReview": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "content": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "groups": { + "type": "array", + "description": "optional", + "items": { + "type": "string", + "description": "optional" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SubjectAccessReview", + "required": true + }, + "namespace": { + "type": "string", + "description": "namespace of the action being requested" + }, + "resource": { + "type": "string", + "description": "one of the existing resource types" + }, + "resourceName": { + "type": "string", + "description": "name of the resource being requested for a get or delete" + }, + "user": { + "type": "string", + "description": "optional" + }, + "verb": { + "type": "string", + "description": "one of get" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReview" + }, + "os_authorization_SubjectAccessReviewResponse": { + "type": "object", + "description": "", + "properties": { + "allowed": { + "type": "boolean", + "description": "true if the action would be allowed" + }, + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "SubjectAccessReviewResponse", + "required": true + }, + "namespace": { + "type": "string", + "description": "the namespace used for the access review" + }, + "reason": { + "type": "string", + "description": "reason is optional" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReviewResponse" + }, + "os_build_Build": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Build", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_build_BuildSpec", + "javaType": "io.fabric8.openshift.api.model.BuildSpec" + }, + "status": { + "$ref": "#/definitions/os_build_BuildStatus", + "javaType": "io.fabric8.openshift.api.model.BuildStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Build", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_build_BuildConfig": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildConfig", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_build_BuildConfigSpec", + "javaType": "io.fabric8.openshift.api.model.BuildConfigSpec" + }, + "status": { + "$ref": "#/definitions/os_build_BuildConfigStatus", + "javaType": "io.fabric8.openshift.api.model.BuildConfigStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfig", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_build_BuildConfigList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of build configs", + "items": { + "$ref": "#/definitions/os_build_BuildConfig", + "javaType": "io.fabric8.openshift.api.model.BuildConfig" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildConfigList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfigList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_build_BuildConfigSpec": { + "type": "object", + "description": "", + "properties": { + "output": { + "$ref": "#/definitions/os_build_BuildOutput", + "javaType": "io.fabric8.openshift.api.model.BuildOutput" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "revision": { + "$ref": "#/definitions/os_build_SourceRevision", + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "serviceAccount": { + "type": "string", + "description": "the name of the service account to use to run pods created by the build" + }, + "source": { + "$ref": "#/definitions/os_build_BuildSource", + "javaType": "io.fabric8.openshift.api.model.BuildSource" + }, + "strategy": { + "$ref": "#/definitions/os_build_BuildStrategy", + "javaType": "io.fabric8.openshift.api.model.BuildStrategy" + }, + "triggers": { + "type": "array", + "description": "determines how new builds can be launched from a build config. if no triggers are defined", + "items": { + "$ref": "#/definitions/os_build_BuildTriggerPolicy", + "javaType": "io.fabric8.openshift.api.model.BuildTriggerPolicy" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfigSpec" + }, + "os_build_BuildConfigStatus": { + "type": "object", + "description": "", + "properties": { + "lastVersion": { + "type": "integer", + "description": "used to inform about number of last triggered build" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfigStatus" + }, + "os_build_BuildList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of builds", + "items": { + "$ref": "#/definitions/os_build_Build", + "javaType": "io.fabric8.openshift.api.model.Build" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_build_BuildOutput": { + "type": "object", + "description": "", + "properties": { + "pushSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "to": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildOutput" + }, + "os_build_BuildRequest": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildRequest", + "required": true + }, + "lastVersion": { + "type": "integer", + "description": "LastVersion of the BuildConfig that triggered this build" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "revision": { + "$ref": "#/definitions/os_build_SourceRevision", + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "triggeredByImage": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildRequest", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_build_BuildSource": { + "type": "object", + "description": "", + "properties": { + "contextDir": { + "type": "string", + "description": "specifies sub-directory where the source code for the application exists" + }, + "git": { + "$ref": "#/definitions/os_build_GitBuildSource", + "javaType": "io.fabric8.openshift.api.model.GitBuildSource" + }, + "sourceSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "type": { + "type": "string", + "description": "type of source control management system" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildSource" + }, + "os_build_BuildSpec": { + "type": "object", + "description": "", + "properties": { + "output": { + "$ref": "#/definitions/os_build_BuildOutput", + "javaType": "io.fabric8.openshift.api.model.BuildOutput" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "revision": { + "$ref": "#/definitions/os_build_SourceRevision", + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "serviceAccount": { + "type": "string", + "description": "the name of the service account to use to run pods created by the build" + }, + "source": { + "$ref": "#/definitions/os_build_BuildSource", + "javaType": "io.fabric8.openshift.api.model.BuildSource" + }, + "strategy": { + "$ref": "#/definitions/os_build_BuildStrategy", + "javaType": "io.fabric8.openshift.api.model.BuildStrategy" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildSpec" + }, + "os_build_BuildStatus": { + "type": "object", + "description": "", + "properties": { + "cancelled": { + "type": "boolean", + "description": "describes if a canceling event was triggered for the build" + }, + "completionTimestamp": { + "type": "string", + "description": "server time when the pod running this build stopped running" + }, + "config": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "duration": { + "type": "integer", + "description": "amount of time the build has been running", + "javaType": "Long" + }, + "message": { + "type": "string", + "description": "human-readable message indicating details about why the build has this status" + }, + "phase": { + "type": "string", + "description": "observed point in the build lifecycle" + }, + "startTimestamp": { + "type": "string", + "description": "server time when this build started running in a pod" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildStatus" + }, + "os_build_BuildStrategy": { + "type": "object", + "description": "", + "properties": { + "customStrategy": { + "$ref": "#/definitions/os_build_CustomBuildStrategy", + "javaType": "io.fabric8.openshift.api.model.CustomBuildStrategy" + }, + "dockerStrategy": { + "$ref": "#/definitions/os_build_DockerBuildStrategy", + "javaType": "io.fabric8.openshift.api.model.DockerBuildStrategy" + }, + "sourceStrategy": { + "$ref": "#/definitions/os_build_SourceBuildStrategy", + "javaType": "io.fabric8.openshift.api.model.SourceBuildStrategy" + }, + "type": { + "type": "string", + "description": "identifies the type of build strategy" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildStrategy" + }, + "os_build_BuildTriggerPolicy": { + "type": "object", + "description": "", + "properties": { + "generic": { + "$ref": "#/definitions/os_build_WebHookTrigger", + "javaType": "io.fabric8.openshift.api.model.WebHookTrigger" + }, + "github": { + "$ref": "#/definitions/os_build_WebHookTrigger", + "javaType": "io.fabric8.openshift.api.model.WebHookTrigger" + }, + "imageChange": { + "$ref": "#/definitions/os_build_ImageChangeTrigger", + "javaType": "io.fabric8.openshift.api.model.ImageChangeTrigger" + }, + "type": { + "type": "string", + "description": "type of build trigger" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildTriggerPolicy" + }, + "os_build_CustomBuildStrategy": { + "type": "object", + "description": "", + "properties": { + "env": { + "type": "array", + "description": "additional environment variables you want to pass into a builder container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "exposeDockerSocket": { + "type": "boolean", + "description": "allow running Docker commands (and build Docker images) from inside the container" + }, + "forcePull": { + "type": "boolean", + "description": "forces pulling of builder image from remote registry if true" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "pullSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.CustomBuildStrategy" + }, + "os_build_DockerBuildStrategy": { + "type": "object", + "description": "", + "properties": { + "env": { + "type": "array", + "description": "additional environment variables you want to pass into a builder container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "forcePull": { + "type": "boolean", + "description": "forces the source build to pull the image if true" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "noCache": { + "type": "boolean", + "description": "if true" + }, + "pullSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DockerBuildStrategy" + }, + "os_build_GitBuildSource": { + "type": "object", + "description": "", + "properties": { + "httpProxy": { + "type": "string", + "description": "specifies a http proxy to be used during git clone operations" + }, + "httpsProxy": { + "type": "string", + "description": "specifies a https proxy to be used during git clone operations" + }, + "ref": { + "type": "string", + "description": "identifies the branch/tag/ref to build" + }, + "uri": { + "type": "string", + "description": "points to the source that will be built" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.GitBuildSource" + }, + "os_build_GitSourceRevision": { + "type": "object", + "description": "", + "properties": { + "author": { + "$ref": "#/definitions/os_build_SourceControlUser", + "javaType": "io.fabric8.openshift.api.model.SourceControlUser" + }, + "commit": { + "type": "string", + "description": "hash identifying a specific commit" + }, + "committer": { + "$ref": "#/definitions/os_build_SourceControlUser", + "javaType": "io.fabric8.openshift.api.model.SourceControlUser" + }, + "message": { + "type": "string", + "description": "description of a specific commit" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.GitSourceRevision" + }, + "os_build_ImageChangeTrigger": { + "type": "object", + "description": "", + "properties": { + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "lastTriggeredImageID": { + "type": "string", + "description": "used internally to save last used image ID for build" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageChangeTrigger" + }, + "os_build_SourceBuildStrategy": { + "type": "object", + "description": "", + "properties": { + "env": { + "type": "array", + "description": "additional environment variables you want to pass into a builder container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "forcePull": { + "type": "boolean", + "description": "forces the source build to pull the image if true" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "incremental": { + "type": "boolean", + "description": "forces the source build to do incremental builds if true" + }, + "pullSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "scripts": { + "type": "string", + "description": "location of the source scripts" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SourceBuildStrategy" + }, + "os_build_SourceControlUser": { + "type": "object", + "description": "", + "properties": { + "email": { + "type": "string", + "description": "e-mail of the source control user" + }, + "name": { + "type": "string", + "description": "name of the source control user" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SourceControlUser" + }, + "os_build_SourceRevision": { + "type": "object", + "description": "", + "properties": { + "git": { + "$ref": "#/definitions/os_build_GitSourceRevision", + "javaType": "io.fabric8.openshift.api.model.GitSourceRevision" + }, + "type": { + "type": "string", + "description": "type of the build source" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "os_build_WebHookTrigger": { + "type": "object", + "description": "", + "properties": { + "secret": { + "type": "string", + "description": "secret used to validate requests" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.WebHookTrigger" + }, + "os_deploy_CustomDeploymentStrategyParams": { + "type": "object", + "description": "", + "properties": { + "command": { + "type": "array", + "description": "optionally overrides the container command (default is specified by the image)", + "items": { + "type": "string", + "description": "optionally overrides the container command (default is specified by the image)" + } + }, + "environment": { + "type": "array", + "description": "environment variables provided to the deployment process container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "image": { + "type": "string", + "description": "a Docker image which can carry out a deployment" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.CustomDeploymentStrategyParams" + }, + "os_deploy_DeploymentCause": { + "type": "object", + "description": "", + "properties": { + "imageTrigger": { + "$ref": "#/definitions/os_deploy_DeploymentCauseImageTrigger", + "javaType": "io.fabric8.openshift.api.model.DeploymentCauseImageTrigger" + }, + "type": { + "type": "string", + "description": "the type of trigger that resulted in a new deployment" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentCause" + }, + "os_deploy_DeploymentCauseImageTrigger": { + "type": "object", + "description": "", + "properties": { + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentCauseImageTrigger" + }, + "os_deploy_DeploymentConfig": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "DeploymentConfig", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_deploy_DeploymentConfigSpec", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigSpec" + }, + "status": { + "$ref": "#/definitions/os_deploy_DeploymentConfigStatus", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfig", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_deploy_DeploymentConfigList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "a list of deployment configs", + "items": { + "$ref": "#/definitions/os_deploy_DeploymentConfig", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfig" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "DeploymentConfigList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_deploy_DeploymentConfigSpec": { + "type": "object", + "description": "", + "properties": { + "replicas": { + "type": "integer", + "description": "the desired number of replicas" + }, + "selector": { + "type": "object", + "description": "a label query over pods that should match the replicas count", + "additionalProperties": { + "type": "string", + "description": "a label query over pods that should match the replicas count" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "strategy": { + "$ref": "#/definitions/os_deploy_DeploymentStrategy", + "javaType": "io.fabric8.openshift.api.model.DeploymentStrategy" + }, + "template": { + "$ref": "#/definitions/kubernetes_PodTemplateSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodTemplateSpec" + }, + "triggers": { + "type": "array", + "description": "how new deployments are triggered", + "items": { + "$ref": "#/definitions/os_deploy_DeploymentTriggerPolicy", + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerPolicy" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigSpec" + }, + "os_deploy_DeploymentConfigStatus": { + "type": "object", + "description": "", + "properties": { + "details": { + "$ref": "#/definitions/os_deploy_DeploymentDetails", + "javaType": "io.fabric8.openshift.api.model.DeploymentDetails" + }, + "latestVersion": { + "type": "integer", + "description": "used to determine whether the current deployment is out of sync" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigStatus" + }, + "os_deploy_DeploymentDetails": { + "type": "object", + "description": "", + "properties": { + "causes": { + "type": "array", + "description": "extended data associated with all the causes for creating a new deployment", + "items": { + "$ref": "#/definitions/os_deploy_DeploymentCause", + "javaType": "io.fabric8.openshift.api.model.DeploymentCause" + } + }, + "message": { + "type": "string", + "description": "a user specified change message" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentDetails" + }, + "os_deploy_DeploymentStrategy": { + "type": "object", + "description": "", + "properties": { + "customParams": { + "$ref": "#/definitions/os_deploy_CustomDeploymentStrategyParams", + "javaType": "io.fabric8.openshift.api.model.CustomDeploymentStrategyParams" + }, + "recreateParams": { + "$ref": "#/definitions/os_deploy_RecreateDeploymentStrategyParams", + "javaType": "io.fabric8.openshift.api.model.RecreateDeploymentStrategyParams" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "rollingParams": { + "$ref": "#/definitions/os_deploy_RollingDeploymentStrategyParams", + "javaType": "io.fabric8.openshift.api.model.RollingDeploymentStrategyParams" + }, + "type": { + "type": "string", + "description": "the name of a deployment strategy" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentStrategy" + }, + "os_deploy_DeploymentTriggerImageChangeParams": { + "type": "object", + "description": "", + "properties": { + "automatic": { + "type": "boolean", + "description": "whether detection of a new tag value should trigger a deployment" + }, + "containerNames": { + "type": "array", + "description": "restricts tag updates to a set of container names in the pod", + "items": { + "type": "string", + "description": "restricts tag updates to a set of container names in the pod" + } + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "lastTriggeredImage": { + "type": "string", + "description": "the last image to be triggered" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerImageChangeParams" + }, + "os_deploy_DeploymentTriggerPolicy": { + "type": "object", + "description": "", + "properties": { + "imageChangeParams": { + "$ref": "#/definitions/os_deploy_DeploymentTriggerImageChangeParams", + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerImageChangeParams" + }, + "type": { + "type": "string", + "description": "the type of the trigger" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerPolicy" + }, + "os_deploy_ExecNewPodHook": { + "type": "object", + "description": "", + "properties": { + "command": { + "type": "array", + "description": "the hook command and its arguments", + "items": { + "type": "string", + "description": "the hook command and its arguments" + } + }, + "containerName": { + "type": "string", + "description": "the name of a container from the pod template whose image will be used for the hook container" + }, + "env": { + "type": "array", + "description": "environment variables provided to the hook container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ExecNewPodHook" + }, + "os_deploy_LifecycleHook": { + "type": "object", + "description": "", + "properties": { + "execNewPod": { + "$ref": "#/definitions/os_deploy_ExecNewPodHook", + "javaType": "io.fabric8.openshift.api.model.ExecNewPodHook" + }, + "failurePolicy": { + "type": "string", + "description": "what action to take if the hook fails" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "os_deploy_RecreateDeploymentStrategyParams": { + "type": "object", + "description": "", + "properties": { + "post": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "pre": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RecreateDeploymentStrategyParams" + }, + "os_deploy_RollingDeploymentStrategyParams": { + "type": "object", + "description": "", + "properties": { + "intervalSeconds": { + "type": "integer", + "description": "the time to wait between polling deployment status after update", + "javaType": "Long" + }, + "post": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "pre": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "timeoutSeconds": { + "type": "integer", + "description": "the time to wait for updates before giving up", + "javaType": "Long" + }, + "updatePercent": { + "type": "integer", + "description": "the percentage of replicas to scale up or down each interval (negative value switches scale order to down/up instead of up/down)" + }, + "updatePeriodSeconds": { + "type": "integer", + "description": "the time to wait between individual pod updates", + "javaType": "Long" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RollingDeploymentStrategyParams" + }, + "os_image_Image": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "dockerImageManifest": { + "type": "string", + "description": "raw JSON of the manifest" + }, + "dockerImageMetadata": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "dockerImageMetadataVersion": { + "type": "string", + "description": "conveys version of the object" + }, + "dockerImageReference": { + "type": "string", + "description": "string that can be used to pull this image" + }, + "kind": { + "type": "string", + "description": "", + "default": "Image", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Image", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_image_ImageList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of image objects", + "items": { + "$ref": "#/definitions/os_image_Image", + "javaType": "io.fabric8.openshift.api.model.Image" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ImageList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_image_ImageStream": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ImageStream", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_image_ImageStreamSpec", + "javaType": "io.fabric8.openshift.api.model.ImageStreamSpec" + }, + "status": { + "$ref": "#/definitions/os_image_ImageStreamStatus", + "javaType": "io.fabric8.openshift.api.model.ImageStreamStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStream", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_image_ImageStreamList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of image stream objects", + "items": { + "$ref": "#/definitions/os_image_ImageStream", + "javaType": "io.fabric8.openshift.api.model.ImageStream" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ImageStreamList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStreamList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_image_ImageStreamSpec": { + "type": "object", + "description": "", + "properties": { + "dockerImageRepository": { + "type": "string", + "description": "optional field if specified this stream is backed by a Docker repository on this server" + }, + "tags": { + "type": "array", + "description": "map arbitrary string values to specific image locators", + "items": { + "$ref": "#/definitions/os_image_NamedTagReference", + "javaType": "io.fabric8.openshift.api.model.NamedTagReference" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStreamSpec" + }, + "os_image_ImageStreamStatus": { + "type": "object", + "description": "", + "properties": { + "dockerImageRepository": { + "type": "string", + "description": "represents the effective location this stream may be accessed at" + }, + "tags": { + "type": "array", + "description": "historical record of images associated with each tag", + "items": { + "$ref": "#/definitions/os_image_NamedTagEventList", + "javaType": "io.fabric8.openshift.api.model.NamedTagEventList" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStreamStatus" + }, + "os_image_NamedTagEventList": { + "type": "object", + "description": "", + "properties": { + "items": { + "type": "array", + "description": "list of tag events related to the tag", + "items": { + "$ref": "#/definitions/os_image_TagEvent", + "javaType": "io.fabric8.openshift.api.model.TagEvent" + } + }, + "tag": { + "type": "string", + "description": "the tag" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedTagEventList" + }, + "os_image_NamedTagReference": { + "type": "object", + "description": "", + "properties": { + "annotations": { + "type": "object", + "description": "annotations associated with images using this tag", + "additionalProperties": { + "type": "string", + "description": "annotations associated with images using this tag" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "name": { + "type": "string", + "description": "name of tag" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedTagReference" + }, + "os_image_TagEvent": { + "type": "object", + "description": "", + "properties": { + "created": { + "type": "string", + "description": "when the event was created" + }, + "dockerImageReference": { + "type": "string", + "description": "the string that can be used to pull this image" + }, + "image": { + "type": "string", + "description": "the image" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.TagEvent" + }, + "os_oauth_OAuthAccessToken": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "authorizeToken": { + "type": "string", + "description": "contains the token that authorized this token" + }, + "clientName": { + "type": "string", + "description": "references the client that created this token" + }, + "expiresIn": { + "type": "integer", + "description": "is the seconds from creation time before this token expires", + "javaType": "Long" + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAccessToken", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "redirectURI": { + "type": "string", + "description": "redirection URI associated with the token" + }, + "refreshToken": { + "type": "string", + "description": "optional value by which this token can be renewed" + }, + "scopes": { + "type": "array", + "description": "list of requested scopes", + "items": { + "type": "string", + "description": "list of requested scopes" + } + }, + "userName": { + "type": "string", + "description": "user name associated with this token" + }, + "userUID": { + "type": "string", + "description": "unique UID associated with this token" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAccessToken", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthAccessTokenList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth access tokens", + "items": { + "$ref": "#/definitions/os_oauth_OAuthAccessToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAccessToken" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAccessTokenList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAccessTokenList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_oauth_OAuthAuthorizeToken": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "clientName": { + "type": "string", + "description": "references the client that created this token" + }, + "expiresIn": { + "type": "integer", + "description": "seconds from creation time before this token expires", + "javaType": "Long" + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAuthorizeToken", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "redirectURI": { + "type": "string", + "description": "redirection URI associated with the token" + }, + "scopes": { + "type": "array", + "description": "list of requested scopes", + "items": { + "type": "string", + "description": "list of requested scopes" + } + }, + "state": { + "type": "string", + "description": "state data from request" + }, + "userName": { + "type": "string", + "description": "user name associated with this token" + }, + "userUID": { + "type": "string", + "description": "unique UID associated with this token. userUID and userName must both match for this token to be valid" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeToken", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthAuthorizeTokenList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth authorization tokens", + "items": { + "$ref": "#/definitions/os_oauth_OAuthAuthorizeToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeToken" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAuthorizeTokenList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeTokenList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_oauth_OAuthClient": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClient", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "redirectURIs": { + "type": "array", + "description": "valid redirection URIs associated with a client", + "items": { + "type": "string", + "description": "valid redirection URIs associated with a client" + } + }, + "respondWithChallenges": { + "type": "boolean", + "description": "indicates whether the client wants authentication needed responses made in the form of challenges instead of redirects" + }, + "secret": { + "type": "string", + "description": "unique secret associated with a client" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClient", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthClientAuthorization": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "clientName": { + "type": "string", + "description": "references the client that created this authorization" + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClientAuthorization", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "scopes": { + "type": "array", + "description": "list of granted scopes", + "items": { + "type": "string", + "description": "list of granted scopes" + } + }, + "userName": { + "type": "string", + "description": "user name that authorized this client" + }, + "userUID": { + "type": "string", + "description": "unique UID associated with this authorization. userUID and userName must both match for this authorization to be valid" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorization", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthClientAuthorizationList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth client authorizations", + "items": { + "$ref": "#/definitions/os_oauth_OAuthClientAuthorization", + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorization" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClientAuthorizationList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorizationList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_oauth_OAuthClientList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth clients", + "items": { + "$ref": "#/definitions/os_oauth_OAuthClient", + "javaType": "io.fabric8.openshift.api.model.OAuthClient" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClientList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClientList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_project_Project": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Project", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_project_ProjectSpec", + "javaType": "io.fabric8.openshift.api.model.ProjectSpec" + }, + "status": { + "$ref": "#/definitions/os_project_ProjectStatus", + "javaType": "io.fabric8.openshift.api.model.ProjectStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Project", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_project_ProjectList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of projects", + "items": { + "$ref": "#/definitions/os_project_Project", + "javaType": "io.fabric8.openshift.api.model.Project" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ProjectList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_project_ProjectRequest": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "description": { + "type": "string", + "description": "description to apply to a project" + }, + "displayName": { + "type": "string", + "description": "display name to apply to a project" + }, + "kind": { + "type": "string", + "description": "", + "default": "ProjectRequest", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectRequest", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_project_ProjectSpec": { + "type": "object", + "description": "", + "properties": { + "finalizers": { + "type": "array", + "description": "an opaque list of values that must be empty to permanently remove object from storage", + "items": { + "type": "string", + "description": "an opaque list of values that must be empty to permanently remove object from storage" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectSpec" + }, + "os_project_ProjectStatus": { + "type": "object", + "description": "", + "properties": { + "phase": { + "type": "string", + "description": "phase is the current lifecycle phase of the project" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectStatus" + }, + "os_route_Route": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Route", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_route_RouteSpec", + "javaType": "io.fabric8.openshift.api.model.RouteSpec" + }, + "status": { + "$ref": "#/definitions/os_route_RouteStatus", + "javaType": "io.fabric8.openshift.api.model.RouteStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Route", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_route_RouteList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of routes", + "items": { + "$ref": "#/definitions/os_route_Route", + "javaType": "io.fabric8.openshift.api.model.Route" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RouteList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RouteList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_route_RouteSpec": { + "type": "object", + "description": "", + "properties": { + "host": { + "type": "string", + "description": "optional: alias/dns that points to the service" + }, + "path": { + "type": "string", + "description": "optional: path that the router watches to route traffic to the service" + }, + "tls": { + "$ref": "#/definitions/os_route_TLSConfig", + "javaType": "io.fabric8.openshift.api.model.TLSConfig" + }, + "to": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RouteSpec" + }, + "os_route_RouteStatus": { + "type": "object", + "description": "", + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RouteStatus" + }, + "os_route_TLSConfig": { + "type": "object", + "description": "", + "properties": { + "caCertificate": { + "type": "string", + "description": "provides the cert authority certificate contents" + }, + "certificate": { + "type": "string", + "description": "provides certificate contents" + }, + "destinationCACertificate": { + "type": "string", + "description": "provides the contents of the ca certificate of the final destination. When using re-encrypt termination this file should be provided in order to have routers use it for health checks on the secure connection" + }, + "key": { + "type": "string", + "description": "provides key file contents" + }, + "termination": { + "type": "string", + "description": "indicates termination type. if not set" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.TLSConfig" + }, + "os_template_Parameter": { + "type": "object", + "description": "", + "properties": { + "description": { + "type": "string", + "description": "optional: describes the parameter" + }, + "from": { + "type": "string", + "description": "input value for the generator" + }, + "generate": { + "type": "string", + "description": "optional: generate specifies the generator to be used to generate random string from an input value specified by the from field. the result string is stored in the value field. if not specified" + }, + "name": { + "type": "string", + "description": "name of the parameter" + }, + "required": { + "type": "boolean", + "description": "indicates the parameter must have a non-empty value or be generated" + }, + "value": { + "type": "string", + "description": "optional: holds the parameter data. if specified" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Parameter" + }, + "os_template_Template": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Template", + "required": true + }, + "labels": { + "type": "object", + "description": "optional: list of lables that are applied to every object during the template to config transformation", + "additionalProperties": { + "type": "string", + "description": "optional: list of lables that are applied to every object during the template to config transformation" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "objects": { + "type": "array", + "description": "list of objects to include in the template", + "items": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + } + }, + "parameters": { + "type": "array", + "description": "optional: list of parameters used during template to config transformation", + "items": { + "$ref": "#/definitions/os_template_Parameter", + "javaType": "io.fabric8.openshift.api.model.Parameter" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Template", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_template_TemplateList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of templates", + "items": { + "$ref": "#/definitions/os_template_Template", + "javaType": "io.fabric8.openshift.api.model.Template" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "TemplateList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.TemplateList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_user_Group": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Group", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "users": { + "type": "array", + "description": "list of users in this group", + "items": { + "type": "string", + "description": "list of users in this group" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Group", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_user_GroupList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of groups", + "items": { + "$ref": "#/definitions/os_user_Group", + "javaType": "io.fabric8.openshift.api.model.Group" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "GroupList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.GroupList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_user_Identity": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "extra": { + "type": "object", + "description": "extra information for this identity", + "additionalProperties": { + "type": "string", + "description": "extra information for this identity" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "kind": { + "type": "string", + "description": "", + "default": "Identity", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "providerName": { + "type": "string", + "description": "source of identity information" + }, + "providerUserName": { + "type": "string", + "description": "uniquely represents this identity in the scope of the provider" + }, + "user": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Identity", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_user_IdentityList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of identities", + "items": { + "$ref": "#/definitions/os_user_Identity", + "javaType": "io.fabric8.openshift.api.model.Identity" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "IdentityList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.IdentityList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_user_User": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "fullName": { + "type": "string", + "description": "full name of user" + }, + "groups": { + "type": "array", + "description": "list of groups", + "items": { + "type": "string", + "description": "list of groups" + } + }, + "identities": { + "type": "array", + "description": "list of identities", + "items": { + "type": "string", + "description": "list of identities" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "User", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.User", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_user_UserList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of users", + "items": { + "$ref": "#/definitions/os_user_User", + "javaType": "io.fabric8.openshift.api.model.User" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "UserList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.UserList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "speter_inf_Dec": { + "type": "object", + "description": "", + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Dec" + } + }, + "type": "object", + "properties": { + "BaseKubernetesList": { + "$ref": "#/definitions/kubernetes_List", + "javaType": "io.fabric8.kubernetes.api.model.BaseKubernetesList" + }, + "BuildConfigList": { + "$ref": "#/definitions/os_build_BuildConfigList", + "javaType": "io.fabric8.openshift.api.model.BuildConfigList" + }, + "BuildList": { + "$ref": "#/definitions/os_build_BuildList", + "javaType": "io.fabric8.openshift.api.model.BuildList" + }, + "BuildRequest": { + "$ref": "#/definitions/os_build_BuildRequest", + "javaType": "io.fabric8.openshift.api.model.BuildRequest" + }, + "ClusterPolicy": { + "$ref": "#/definitions/os_authorization_ClusterPolicy", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicy" + }, + "ClusterPolicyBinding": { + "$ref": "#/definitions/os_authorization_ClusterPolicyBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBinding" + }, + "ClusterPolicyBindingList": { + "$ref": "#/definitions/os_authorization_ClusterPolicyBindingList", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBindingList" + }, + "ClusterPolicyList": { + "$ref": "#/definitions/os_authorization_ClusterPolicyList", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyList" + }, + "ClusterRoleBinding": { + "$ref": "#/definitions/os_authorization_ClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding" + }, + "ClusterRoleBindingList": { + "$ref": "#/definitions/os_authorization_ClusterRoleBindingList", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBindingList" + }, + "Config": { + "$ref": "#/definitions/kubernetes_config_Config", + "javaType": "io.fabric8.kubernetes.api.model.Config" + }, + "ContainerStatus": { + "$ref": "#/definitions/kubernetes_ContainerStatus", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStatus" + }, + "DeploymentConfigList": { + "$ref": "#/definitions/os_deploy_DeploymentConfigList", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigList" + }, + "Endpoints": { + "$ref": "#/definitions/kubernetes_Endpoints", + "javaType": "io.fabric8.kubernetes.api.model.Endpoints" + }, + "EndpointsList": { + "$ref": "#/definitions/kubernetes_EndpointsList", + "javaType": "io.fabric8.kubernetes.api.model.EndpointsList" + }, + "EnvVar": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + }, + "EventList": { + "$ref": "#/definitions/kubernetes_EventList", + "javaType": "io.fabric8.kubernetes.api.model.EventList" + }, + "Group": { + "$ref": "#/definitions/os_user_Group", + "javaType": "io.fabric8.openshift.api.model.Group" + }, + "GroupList": { + "$ref": "#/definitions/os_user_GroupList", + "javaType": "io.fabric8.openshift.api.model.GroupList" + }, + "Identity": { + "$ref": "#/definitions/os_user_Identity", + "javaType": "io.fabric8.openshift.api.model.Identity" + }, + "IdentityList": { + "$ref": "#/definitions/os_user_IdentityList", + "javaType": "io.fabric8.openshift.api.model.IdentityList" + }, + "ImageList": { + "$ref": "#/definitions/os_image_ImageList", + "javaType": "io.fabric8.openshift.api.model.ImageList" + }, + "ImageStreamList": { + "$ref": "#/definitions/os_image_ImageStreamList", + "javaType": "io.fabric8.openshift.api.model.ImageStreamList" + }, + "LocalSubjectAccessReview": { + "$ref": "#/definitions/os_authorization_LocalSubjectAccessReview", + "javaType": "io.fabric8.openshift.api.model.LocalSubjectAccessReview" + }, + "Namespace": { + "$ref": "#/definitions/kubernetes_Namespace", + "javaType": "io.fabric8.kubernetes.api.model.Namespace" + }, + "NamespaceList": { + "$ref": "#/definitions/kubernetes_NamespaceList", + "javaType": "io.fabric8.kubernetes.api.model.NamespaceList" + }, + "Node": { + "$ref": "#/definitions/kubernetes_Node", + "javaType": "io.fabric8.kubernetes.api.model.Node" + }, + "NodeList": { + "$ref": "#/definitions/kubernetes_NodeList", + "javaType": "io.fabric8.kubernetes.api.model.NodeList" + }, + "OAuthAccessToken": { + "$ref": "#/definitions/os_oauth_OAuthAccessToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAccessToken" + }, + "OAuthAccessTokenList": { + "$ref": "#/definitions/os_oauth_OAuthAccessTokenList", + "javaType": "io.fabric8.openshift.api.model.OAuthAccessTokenList" + }, + "OAuthAuthorizeToken": { + "$ref": "#/definitions/os_oauth_OAuthAuthorizeToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeToken" + }, + "OAuthAuthorizeTokenList": { + "$ref": "#/definitions/os_oauth_OAuthAuthorizeTokenList", + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeTokenList" + }, + "OAuthClient": { + "$ref": "#/definitions/os_oauth_OAuthClient", + "javaType": "io.fabric8.openshift.api.model.OAuthClient" + }, + "OAuthClientAuthorization": { + "$ref": "#/definitions/os_oauth_OAuthClientAuthorization", + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorization" + }, + "OAuthClientAuthorizationList": { + "$ref": "#/definitions/os_oauth_OAuthClientAuthorizationList", + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorizationList" + }, + "OAuthClientList": { + "$ref": "#/definitions/os_oauth_OAuthClientList", + "javaType": "io.fabric8.openshift.api.model.OAuthClientList" + }, + "ObjectMeta": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "PersistentVolume": { + "$ref": "#/definitions/kubernetes_PersistentVolume", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolume" + }, + "PersistentVolumeClaim": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaim", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaim" + }, + "PersistentVolumeClaimList": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimList", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimList" + }, + "PersistentVolumeList": { + "$ref": "#/definitions/kubernetes_PersistentVolumeList", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeList" + }, + "PodList": { + "$ref": "#/definitions/kubernetes_PodList", + "javaType": "io.fabric8.kubernetes.api.model.PodList" + }, + "Policy": { + "$ref": "#/definitions/os_authorization_Policy", + "javaType": "io.fabric8.openshift.api.model.Policy" + }, + "PolicyBinding": { + "$ref": "#/definitions/os_authorization_PolicyBinding", + "javaType": "io.fabric8.openshift.api.model.PolicyBinding" + }, + "PolicyBindingList": { + "$ref": "#/definitions/os_authorization_PolicyBindingList", + "javaType": "io.fabric8.openshift.api.model.PolicyBindingList" + }, + "PolicyList": { + "$ref": "#/definitions/os_authorization_PolicyList", + "javaType": "io.fabric8.openshift.api.model.PolicyList" + }, + "Project": { + "$ref": "#/definitions/os_project_Project", + "javaType": "io.fabric8.openshift.api.model.Project" + }, + "ProjectList": { + "$ref": "#/definitions/os_project_ProjectList", + "javaType": "io.fabric8.openshift.api.model.ProjectList" + }, + "ProjectRequest": { + "$ref": "#/definitions/os_project_ProjectRequest", + "javaType": "io.fabric8.openshift.api.model.ProjectRequest" + }, + "Quantity": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "ReplicationControllerList": { + "$ref": "#/definitions/kubernetes_ReplicationControllerList", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerList" + }, + "ResourceQuota": { + "$ref": "#/definitions/kubernetes_ResourceQuota", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuota" + }, + "ResourceQuotaList": { + "$ref": "#/definitions/kubernetes_ResourceQuotaList", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaList" + }, + "Role": { + "$ref": "#/definitions/os_authorization_Role", + "javaType": "io.fabric8.openshift.api.model.Role" + }, + "RoleBinding": { + "$ref": "#/definitions/os_authorization_RoleBinding", + "javaType": "io.fabric8.openshift.api.model.RoleBinding" + }, + "RoleBindingList": { + "$ref": "#/definitions/os_authorization_RoleBindingList", + "javaType": "io.fabric8.openshift.api.model.RoleBindingList" + }, + "RoleList": { + "$ref": "#/definitions/os_authorization_RoleList", + "javaType": "io.fabric8.openshift.api.model.RoleList" + }, + "RootPaths": { + "$ref": "#/definitions/api_RootPaths", + "javaType": "io.fabric8.kubernetes.api.model.RootPaths" + }, + "RouteList": { + "$ref": "#/definitions/os_route_RouteList", + "javaType": "io.fabric8.openshift.api.model.RouteList" + }, + "Secret": { + "$ref": "#/definitions/kubernetes_Secret", + "javaType": "io.fabric8.kubernetes.api.model.Secret" + }, + "SecretList": { + "$ref": "#/definitions/kubernetes_SecretList", + "javaType": "io.fabric8.kubernetes.api.model.SecretList" + }, + "SecurityContextConstraints": { + "$ref": "#/definitions/kubernetes_SecurityContextConstraints", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraints" + }, + "SecurityContextConstraintsList": { + "$ref": "#/definitions/kubernetes_SecurityContextConstraintsList", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraintsList" + }, + "ServiceAccount": { + "$ref": "#/definitions/kubernetes_ServiceAccount", + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccount" + }, + "ServiceAccountList": { + "$ref": "#/definitions/kubernetes_ServiceAccountList", + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccountList" + }, + "ServiceList": { + "$ref": "#/definitions/kubernetes_ServiceList", + "javaType": "io.fabric8.kubernetes.api.model.ServiceList" + }, + "Status": { + "$ref": "#/definitions/kubernetes_Status", + "javaType": "io.fabric8.kubernetes.api.model.Status" + }, + "SubjectAccessReview": { + "$ref": "#/definitions/os_authorization_SubjectAccessReview", + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReview" + }, + "SubjectAccessReviewResponse": { + "$ref": "#/definitions/os_authorization_SubjectAccessReviewResponse", + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReviewResponse" + }, + "TagEvent": { + "$ref": "#/definitions/os_image_TagEvent", + "javaType": "io.fabric8.openshift.api.model.TagEvent" + }, + "Template": { + "$ref": "#/definitions/os_template_Template", + "javaType": "io.fabric8.openshift.api.model.Template" + }, + "TemplateList": { + "$ref": "#/definitions/os_template_TemplateList", + "javaType": "io.fabric8.openshift.api.model.TemplateList" + }, + "User": { + "$ref": "#/definitions/os_user_User", + "javaType": "io.fabric8.openshift.api.model.User" + }, + "UserList": { + "$ref": "#/definitions/os_user_UserList", + "javaType": "io.fabric8.openshift.api.model.UserList" + }, + "WatchEvent": { + "$ref": "#/definitions/kubernetes_watch_WatchEvent", + "javaType": "io.fabric8.kubernetes.api.model.WatchEvent" + } + }, + "additionalProperties": true + }; +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + var hiddenProperties = ['status', 'deletionTimestamp']; + function withProperty(schema, name, action) { + if (schema.properties[name]) { + action(schema.properties[name]); + } + } + function hideProperties(schema) { + _.forEach(hiddenProperties, function (property) { + withProperty(schema, property, function (property) { + property.hidden = true; + }); + }); + } + Kubernetes._module.factory('KubernetesSchema', ['SchemaRegistry', function (schemas) { + Kubernetes.configureSchema(); + schemas.addListener("k8s schema customizer", function (name, schema) { + if (schema.properties) { + if (schema.properties.name) { + schema.controls = ['name', '*']; + } + withProperty(schema, 'portalIP', function (property) { + property.label = "Portal IP"; + }); + withProperty(schema, 'publicIPs', function (property) { + property.label = "Public IPs"; + }); + withProperty(schema, 'Spec', function (property) { + property.label = 'false'; + }); + withProperty(schema, 'Metadata', function (property) { + property.label = 'false'; + }); + hideProperties(schema); + } + if (_.endsWith(name, "ServiceSpec")) { + schema.controls = ["portalIP", "createExternalLoadBalancer", "sessionAffinity", "publicIPs", "ports", "selector", "*"]; + withProperty(schema, 'sessionAffinity', function (property) { + Kubernetes.log.debug("Schema: ", schema); + property.enum = ['None', 'ClientIP']; + property.default = 'None'; + }); + } + if (_.endsWith(name, "Service")) { + schema.controls = undefined; + schema.tabs = { + 'Basic Information': ['metadata'], + 'Details': ['*'] + }; + Kubernetes.log.debug("Name: ", name, " Schema: ", schema); + } + }); + schemas.addSchema('kubernetes', Kubernetes.schema); + // now lets iterate and add all the definitions too + angular.forEach(Kubernetes.schema.definitions, function (definition, typeName) { + //schemas.addSchema(typeName, definition); + schemas.addSchema("#/definitions/" + typeName, definition); + }); + return Kubernetes.schema; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +var Kubernetes; +(function (Kubernetes) { + // facade this to the watcher service + var KubernetesStateImpl = (function () { + function KubernetesStateImpl(watcher) { + this.watcher = watcher; + } + Object.defineProperty(KubernetesStateImpl.prototype, "namespaces", { + get: function () { + return _.map(this.watcher.getObjects(Kubernetes.WatchTypes.NAMESPACES), function (namespace) { + return namespace.metadata.name; + }); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(KubernetesStateImpl.prototype, "selectedNamespace", { + get: function () { + return this.watcher.getNamespace(); + }, + set: function (namespace) { + this.watcher.setNamespace(namespace); + }, + enumerable: true, + configurable: true + }); + return KubernetesStateImpl; + }()); + Kubernetes._module.factory('KubernetesState', ['WatcherService', function (watcher) { + return new KubernetesStateImpl(watcher); + }]); + // TODO this doesn't need to be a service really + Kubernetes._module.factory('KubernetesApiURL', function () { return Kubernetes.kubernetesApiUrl(); }); + // TODO we'll get rid of this... + Kubernetes._module.factory('KubernetesVersion', [function () { + return { + query: function () { return null; } + }; + }]); + // TODO let's move these into KubernetesModel so controllers don't have to inject them separately + Kubernetes._module.factory('KubernetesPods', ['KubernetesModel', function (KubernetesModel) { + return KubernetesModel['podsResource']; + }]); + Kubernetes._module.factory('KubernetesReplicationControllers', ['KubernetesModel', function (KubernetesModel) { + return KubernetesModel['replicationcontrollersResource']; + }]); + Kubernetes._module.factory('KubernetesServices', ['KubernetesModel', function (KubernetesModel) { + return KubernetesModel['servicesResource']; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.FileDropController = Kubernetes.controller("FileDropController", ["$scope", "KubernetesModel", "FileUploader", '$http', function ($scope, model, FileUploader, $http) { + var log = Logger.get('kubernetes-file-uploader'); + var uploader = $scope.uploader = new FileUploader({ + autoUpload: false, + removeAfterUpload: true, + url: Kubernetes.kubernetesApiUrl() + }); + $scope.uploader.onAfterAddingFile = function (file) { + var reader = new FileReader(); + reader.onload = function () { + if (reader.readyState === 2) { + log.debug("File added: ", file); + var data = reader.result; + var obj = null; + if (_.endsWith(file._file.name, '.json')) { + log.debug("Parsing JSON file"); + try { + obj = angular.fromJson(data); + } + catch (err) { + log.debug("Failed to read dropped file ", file._file.name, ": ", err); + return; + } + } + else if (_.endsWith(file._file.name, '.yaml')) { + log.debug("Parsing YAML file"); + try { + obj = jsyaml.load(data); + } + catch (err) { + log.debug("Failed to read dropped file ", file._file.name, ": ", err); + return; + } + } + else { + log.debug("Unknown file type for file: ", file._file.name); + return; + } + log.debug("Dropped object: ", obj); + if (!KubernetesAPI.getNamespace(obj)) { + obj.metadata.namespace = model.currentNamespace(); + } + KubernetesAPI.put({ + object: obj, + success: function (data) { + Core.notification("success", "Applied " + file._file.name); + }, + error: function (err) { + log.info("Got error applying", file._file.name, ": ", err); + Core.notification("warning", "Failed to apply " + file._file.name + ", error: " + err.message); + } + }); + } + }; + reader.readAsText(file._file); + }; + $scope.uploader.onBeforeUploadItem = function (item) { + log.debug("Uploading: ", item); + //Core.notification('info', 'Uploading ' + item); + }; + $scope.uploader.onSuccessItem = function (item) { + log.debug("onSuccessItem: ", item); + }; + $scope.uploader.onErrorItem = function (item, response, status) { + log.debug("Failed to apply, response: ", response, " status: ", status); + }; + }]); + Kubernetes.NamespaceController = Kubernetes.controller('NamespaceController', ['$scope', 'WatcherService', function ($scope, watcher) { + $scope.namespaces = watcher.getObjects('namespaces'); + $scope.$watchCollection('namespaces', function (newValue, oldValue) { + if (newValue !== oldValue) { + $scope.namespace = watcher.getNamespace(); + } + }); + $scope.$watch('namespace', function (newValue, oldValue) { + if (newValue !== oldValue) { + if (newValue !== oldValue) { + watcher.setNamespace(newValue); + } + } + }); + }]); + Kubernetes.TopLevel = Kubernetes.controller("TopLevel", ["$scope", "KubernetesVersion", "KubernetesState", function ($scope, KubernetesVersion, KubernetesState) { + $scope.version = undefined; + $scope.showAppView = Kubernetes.isAppView(); + $scope.isActive = function (href) { + return Kubernetes.isLinkActive(href); + }; + $scope.mode = 'yaml'; + $scope.rawMode = true; + $scope.dirty = false; + $scope.readOnly = true; + $scope.rawModel = null; + $scope.$on('hawtioEditor_default_dirty', function ($event, dirty) { + $scope.dirty = dirty; + }); + $scope.save = function (rawModel) { + var obj = null; + var str = rawModel.replace(/\t/g, " "); + try { + obj = jsyaml.load(str); + } + catch (err) { + Core.notification("warning", "Failed to save object, error: \"" + err + "\""); + } + if (!obj) { + return; + } + $scope.readOnly = true; + KubernetesAPI.put({ + object: obj, + success: function (data) { + $scope.dirty = false; + Core.notification("success", "Saved object " + Kubernetes.getName(obj)); + Core.$apply($scope); + }, + error: function (err) { + console.log("Got error: ", err); + Core.notification("warning", "Failed to save object, error: \"" + err.message + "\""); + $scope.dirty = false; + Core.$apply($scope); + } + }); + }; + $scope.kubernetes = KubernetesState; + KubernetesVersion.query(function (response) { + $scope.version = response; + }); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.NamespaceController = Kubernetes.controller("NamespaceController", ["$scope", "WatcherService", function ($scope, watcher) { + $scope.watcher = watcher; + $scope.namespaceObjects = watcher.getObjects('namespaces'); + $scope.namespace = watcher.getNamespace(); + $scope.namespaces = []; + $scope.$watch('namespace', function (newValue, oldValue) { + if (newValue !== oldValue) { + watcher.setNamespace(newValue); + } + }); + $scope.$watch('watcher.getNamespace()', function (newValue, oldValue) { + if (newValue !== oldValue) { + $scope.namespace = newValue; + } + }); + $scope.$watchCollection('namespaceObjects', function (namespaceObjects) { + $scope.namespaces = _.map(namespaceObjects, function (namespace) { return namespace.metadata.name; }); + }); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + var oracleModelService = (function () { + function oracleModelService() { + this.oraclecontrollers = []; + } + Object.defineProperty(oracleModelService.prototype, "oracleControllers", { + get: function () { + return this.oraclecontrollers; + }, + set: function (oracleControllers) { + this.oraclecontrollers = oracleControllers; + }, + enumerable: true, + configurable: true + }); + oracleModelService.prototype.findIndexOfOracleControllers = function (oracleControllers, name) { + for (var index in oracleControllers) + if (oracleControllers[index].name === name) + return index; + return -1; + }; + return oracleModelService; + }()); + Kubernetes.oracleModelService = oracleModelService; + Kubernetes._module.factory('OracleStatusModel', [function () { + return new oracleModelService(); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + var OverviewDirective = Kubernetes._module.directive("kubernetesOverview", ["$templateCache", "$compile", "$interpolate", "$timeout", "$window", "KubernetesState", 'KubernetesModel', function ($templateCache, $compile, $interpolate, $timeout, $window, KubernetesState, KubernetesModel) { + var log = Logger.get('kubernetes-overview'); + var model = KubernetesModel; + var state = KubernetesState; + return { + restrict: 'E', + replace: true, + link: function (scope, element, attr) { + scope.model = model; + element.css({ visibility: 'hidden' }); + scope.getEntity = function (type, key) { + switch (type) { + case 'host': + return model.podsByHost[key]; + case 'pod': + return model.podsByKey[key]; + case 'replicationController': + return model.replicationControllersByKey[key]; + case 'service': + return model.servicesByKey[key]; + default: + return undefined; + } + }; + scope.kubernetes = state; + scope.customizeDefaultOptions = function (options) { + options.Endpoint = ['Blank', {}]; + }; + scope.mouseEnter = function ($event) { + if (scope.jsPlumb) { + angular.element($event.currentTarget).addClass("hovered"); + scope.jsPlumb.getEndpoints($event.currentTarget).forEach(function (endpoint) { + endpoint.connections.forEach(function (connection) { + if (!connection.isHover()) { + connection.setHover(true); + connection.endpoints.forEach(function (e) { + scope.mouseEnter({ + currentTarget: e.element + }); + }); + } + }); + }); + } + }; + scope.mouseLeave = function ($event) { + if (scope.jsPlumb) { + angular.element($event.currentTarget).removeClass("hovered"); + scope.jsPlumb.getEndpoints($event.currentTarget).forEach(function (endpoint) { + endpoint.connections.forEach(function (connection) { + if (connection.isHover()) { + connection.setHover(false); + connection.endpoints.forEach(function (e) { + scope.mouseLeave({ + currentTarget: e.element + }); + }); + } + }); + }); + } + }; + /* + scope.customizeEndpointOptions = (jsPlumb, node, options) => { + var type = node.el.attr('data-type'); + // log.debug("endpoint type: ", type); + switch (type) { + case 'pod': + break; + case 'service': + break; + case 'replicationController': + break; + } + }; + */ + scope.customizeConnectionOptions = function (jsPlumb, edge, params, options) { + var type = edge.source.el.attr('data-type'); + options.connector = ["Bezier", { curviness: 50, stub: 25, alwaysRespectStubs: true }]; + params.paintStyle = { + lineWidth: 2, + strokeStyle: '#5555cc' + }; + switch (type) { + case 'pod': + break; + case 'service': + params.anchors = [ + ["Continuous", { faces: ["right"] }], + ["Continuous", { faces: ["left"] }] + ]; + break; + case 'replicationController': + params.anchors = [ + ["Perimeter", { shape: "Circle" }], + ["Continuous", { faces: ["right"] }] + ]; + break; + } + //log.debug("connection source type: ", type); + return options; + }; + function interpolate(template, config) { + return $interpolate(template)(config); + } + function createElement(template, thingName, thing) { + var config = {}; + config[thingName] = thing; + return interpolate(template, config); + } + function createElements(template, thingName, things) { + return things.map(function (thing) { + return createElement(template, thingName, thing); + }); + } + function appendNewElements(parentEl, template, thingName, things) { + things.forEach(function (thing) { + var key = thing['_key'] || thing['elementId'] || thing['id']; + var existing = parentEl.find("#" + key); + if (!existing.length) { + log.debug("existing: ", existing, " key: ", key); + parentEl.append($compile(createElement(template, thingName, thing))(scope)); + } + }); + } + function namespaceFilter(item) { + return Kubernetes.getNamespace(item) === scope.kubernetes.selectedNamespace; + } + function firstDraw() { + log.debug("First draw"); + element.empty(); + var services = model.services; + var replicationControllers = model.replicationControllers; + var pods = model.pods; + var hosts = model.hosts; + // log.debug("hosts: ", model.hosts); + var parentEl = angular.element($templateCache.get("overviewTemplate.html")); + var servicesEl = parentEl.find(".services"); + var hostsEl = parentEl.find(".hosts"); + var replicationControllersEl = parentEl.find(".replicationControllers"); + servicesEl.append(createElements($templateCache.get("serviceTemplate.html"), 'service', services.filter(namespaceFilter))); + replicationControllersEl.append(createElements($templateCache.get("replicationControllerTemplate.html"), 'replicationController', replicationControllers.filter(namespaceFilter))); + hosts.forEach(function (host) { + var hostEl = angular.element(createElement($templateCache.get("overviewHostTemplate.html"), 'host', host)); + var podContainer = angular.element(hostEl.find('.pod-container')); + podContainer.append(createElements($templateCache.get("podTemplate.html"), "pod", host.pods)); + hostsEl.append(hostEl); + }); + //parentEl.append(createElements($templateCache.get("podTemplate.html"), 'pod', pods)); + element.append($compile(parentEl)(scope)); + $timeout(function () { element.css({ visibility: 'visible' }); }, 250); + } + function update() { + scope.$emit('jsplumbDoWhileSuspended', function () { + log.debug("Update"); + var services = model.services; + var replicationControllers = model.replicationControllers; + var pods = model.pods; + var hosts = model.hosts; + var parentEl = element.find('[hawtio-jsplumb]'); + var children = parentEl.find('.jsplumb-node'); + children.each(function (index, c) { + var child = angular.element(c); + var key = child.attr('id'); + log.debug('key: ', key); + if (Core.isBlank(key)) { + return; + } + var type = child.attr('data-type'); + switch (type) { + case 'host': + if (key in model.podsByHost) { + return; + } + break; + case 'service': + if (key in model.servicesByKey && Kubernetes.getNamespace(model.servicesByKey[key]) == scope.kubernetes.selectedNamespace) { + var service = model.servicesByKey[key]; + child.attr('connect-to', service.connectTo); + return; + } + break; + case 'pod': + /* + if (hasId(pods, id)) { + return; + } + */ + if (key in model.podsByKey) { + return; + } + break; + case 'replicationController': + if (key in model.replicationControllersByKey) { + var replicationController = model.replicationControllersByKey[key]; + child.attr('connect-to', replicationController.connectTo); + return; + } + break; + default: + log.debug("Ignoring element with unknown type"); + return; + } + log.debug("Removing: ", key); + child.remove(); + }); + var servicesEl = element.find(".services"); + var replicationControllersEl = element.find(".replicationControllers"); + var hostsEl = element.find(".hosts"); + appendNewElements(servicesEl, $templateCache.get("serviceTemplate.html"), "service", services); + appendNewElements(replicationControllersEl, $templateCache.get("replicationControllerTemplate.html"), "replicationController", replicationControllers); + appendNewElements(hostsEl, $templateCache.get("overviewHostTemplate.html"), "host", hosts); + hosts.forEach(function (host) { + var hostEl = angular.element(hostsEl.find("#" + host.elementId)); + var podContainer = angular.element(hostEl.find('.pod-container')); + appendNewElements(podContainer, $templateCache.get("podTemplate.html"), "pod", host.pods); + }); + }); + } + function refreshDrawing() { + log.debug("Refreshing drawing"); + if (element.children().length === 0) { + firstDraw(); + } + else { + update(); + } + Core.$apply(scope); + } + scope.$on('kubernetesModelUpdated', _.debounce(refreshDrawing, 500, { trailing: true })); + setTimeout(refreshDrawing, 100); + } + }; + }]); + var OverviewBoxController = Kubernetes.controller("OverviewBoxController", ["$scope", "$location", function ($scope, $location) { + $scope.viewDetails = function (entity, path) { + if (entity) { + var namespace = Kubernetes.getNamespace(entity); + var id = Kubernetes.getName(entity); + $location.path(UrlHelpers.join('/kubernetes/namespace', namespace, path, id)); + } + else { + Kubernetes.log.warn("No entity for viewDetails!"); + } + }; + }]); + var scopeName = "OverviewController"; + var OverviewController = Kubernetes.controller(scopeName, ["$scope", "$location", "$http", "$timeout", "$routeParams", "KubernetesModel", "KubernetesState", "KubernetesApiURL", function ($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL) { + $scope.name = scopeName; + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + //$scope.subTabConfig = []; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.PipelinesController = Kubernetes.controller("PipelinesController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + /** + * Lets update the various data to join them together to a pipeline model + */ + function updateData() { + var pipelineSteps = {}; + if ($scope.buildConfigs && $scope.builds && $scope.deploymentConfigs) { + Kubernetes.enrichBuildConfigs($scope.buildConfigs, $scope.builds); + $scope.fetched = true; + angular.forEach($scope.buildConfigs, function (buildConfig) { + var pipelineKey = createPipelineKey(buildConfig); + if (pipelineKey) { + pipelineSteps[pipelineKey] = { + buildConfig: buildConfig, + builds: [], + triggeredBy: null, + triggersSteps: [], + $class: 'pipeline-build' + }; + } + }); + angular.forEach($scope.builds, function (build) { + var pipelineKey = createPipelineKey(build); + if (pipelineKey) { + var pipeline = pipelineSteps[pipelineKey]; + if (!pipeline) { + //console.log("warning no pipeline generated for buildConfig for key " + pipelineKey + " for build " + angular.toJson(build, true)); + console.log("warning no pipeline generated for buildConfig for key " + pipelineKey + " for build " + build.$name); + } + else { + pipeline.builds.push(build); + } + } + }); + // TODO now we need to look at the triggers to figure out which pipelineSteps triggers each pipelineStep + // now lets create an array of all pipelines, starting from the first known step with a list of the steps + var pipelines = []; + angular.forEach(pipelineSteps, function (pipelineStep, key) { + if (!pipelineStep.triggeredBy) { + // we are a root step.... + pipelines.push(pipelineStep); + // now lets add all the steps for this key... + pipelineStep.triggersSteps.push(pipelineStep); + angular.forEach(pipelineSteps, function (step) { + if (step.triggeredBy === key) { + pipelineStep.triggersSteps.push(step); + } + }); + } + }); + angular.forEach($scope.deploymentConfigs, function (deploymentConfig) { + if (!deploymentConfig.kind) { + deploymentConfig.kind = "DeploymentConfig"; + } + angular.forEach(deploymentConfig.triggers, function (trigger) { + var type = trigger.type; + var imageChangeParams = trigger.imageChangeParams; + if (imageChangeParams && type === "ImageChange") { + var from = imageChangeParams.from; + if (from) { + var name = from.name; + if (from.kind === "ImageRepository") { + var tag = imageChangeParams.tag || "latest"; + if (name) { + // now lets find a pipeline step which fires from this + angular.forEach(pipelineSteps, function (pipelineStep, key) { + var to = Core.pathGet(pipelineStep, ["buildConfig", "parameters", "output", "to"]); + if (to && (to.kind === "ImageRepository" || to.kind === "ImageStream")) { + var toName = to.name; + if (toName === name) { + var selector = Core.pathGet(deploymentConfig, ["template", "controllerTemplate", "selector"]); + var pods = []; + var $podCounters = selector ? Kubernetes.createPodCounters(selector, KubernetesModel.podsForNamespace(), pods) : null; + var deployPipelineStep = { + buildConfig: deploymentConfig, + $class: 'pipeline-deploy', + $podCounters: $podCounters, + $pods: pods + }; + pipelineStep.triggersSteps.push(deployPipelineStep); + } + } + }); + } + } + } + } + }); + }); + $scope.pipelines = pipelines; + } + } + /** + * Lets create a unique key for build / config we can use to do linking of builds / configs / triggers + */ + function createPipelineKey(buildConfig) { + return Core.pathGet(buildConfig, ["parameters", "source", "git", "uri"]); + } + $scope.$keepPolling = function () { return Kubernetes.keepPollingModel; }; + $scope.fetch = PollHelpers.setupPolling($scope, function (next) { + var ready = 0; + var numServices = 3; + function maybeNext() { + if (++ready >= numServices) { + next(); + } + } + var url = Kubernetes.buildsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.builds = Kubernetes.enrichBuilds(data.items); + updateData(); + } + maybeNext(); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + maybeNext(); + }); + url = Kubernetes.buildConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.buildConfigs = data.items; + updateData(); + } + maybeNext(); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + maybeNext(); + }); + url = Kubernetes.deploymentConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.deploymentConfigs = data.items; + updateData(); + } + maybeNext(); + }). + error(function (data, status, headers, config) { + Kubernetes.log.warn("Failed to load " + url + " " + data + " " + status); + maybeNext(); + }); + }); + $scope.fetch(); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.PodController = Kubernetes.controller("PodController", ["$scope", "KubernetesModel", "KubernetesState", "ServiceRegistry", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "$window", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, ServiceRegistry, $templateCache, $location, $routeParams, $http, $timeout, $window, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + $scope.itemConfig = { + properties: { + 'containers/image$': { + template: $templateCache.get('imageTemplate.html') + }, + 'status/phase': { + template: $templateCache.get('statusTemplate.html') + }, + '\\/Env\\/': { + template: $templateCache.get('envItemTemplate.html') + }, + '^\\/labels$': { + template: $templateCache.get('labelTemplate.html') + }, + '\\/env\\/key$': { + hidden: true + } + } + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.$watch('model.pods', function (newValue, oldValue) { + updateData(); + }, true); + $scope.flipRaw = function () { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + $scope.openLogs = function () { + var pods = [$scope.item]; + Kubernetes.openLogsForPods(ServiceRegistry, $window, KubernetesModel.currentNamespace(), pods); + }; + updateData(); + function updateData() { + $scope.id = $routeParams["id"]; + $scope.item = $scope.model.getPod(KubernetesState.selectedNamespace, $scope.id); + if ($scope.item) { + $scope.rawModel = Kubernetes.toRawYaml($scope.item); + } + Core.$apply($scope); + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.PodEditController = Kubernetes.controller("PodEditController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "SchemaRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, schemas) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = schemas.cloneSchema("io.fabric8.kubernetes.api.model.Pod"); + //$scope.config = KubernetesSchema.definitions.kubernetes_v1beta2_Pod; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + if ($scope.id) { + $scope.entity = $scope.model.getPod(KubernetesState.selectedNamespace, $scope.id); + Core.$apply($scope); + $scope.fetched = true; + } + else { + $scope.fetched = true; + } + } + $scope.save = function () { + console.log($scope.entity); + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +var Kubernetes; +(function (Kubernetes) { + var log = Logger.get('kubernetes-watcher'); + var k8sTypes = KubernetesAPI.NamespacedTypes.k8sTypes; + var osTypes = KubernetesAPI.NamespacedTypes.osTypes; + var self = {}; + var updateFunction = function () { + log.debug("Objects changed, firing listeners"); + var objects = {}; + _.forEach(self.getTypes(), function (type) { + objects[type] = self.getObjects(type); + }); + _.forEach(self.listeners, function (listener) { + listener(objects); + }); + }; + var debouncedUpdate = _.debounce(updateFunction, 75, { trailing: true }); + var namespaceWatch = { + selected: undefined, + watch: undefined, + objects: [], + objectMap: {}, + watches: {} + }; + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'KubernetesWatcherInit', + depends: ['KubernetesApiDiscovery'], + task: function (next) { + var booted = false; + if (Kubernetes.isOpenShift) { + log.info("Backend is an Openshift instance"); + } + else { + log.info("Backend is a vanilla Kubernetes instance"); + } + namespaceWatch.watch = KubernetesAPI.watch({ + kind: KubernetesAPI.WatchTypes.NAMESPACES, + success: function (objects) { + namespaceWatch.objects = objects; + if (!booted) { + booted = true; + self.setNamespace(localStorage[Kubernetes.Constants.NAMESPACE_STORAGE_KEY] || Kubernetes.defaultNamespace); + next(); + } + log.debug("Got namespaces: ", namespaceWatch.objects); + }, error: function (error) { + log.warn("Error fetching namespaces: ", error); + // TODO is this necessary? + //HawtioOAuth.doLogout(); + if (!booted) { + booted = true; + next(); + } + } + }); + } + }); + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'KubernetesApiDiscovery', + depends: ['hawtio-oauth'], + task: function (next) { + Kubernetes.isOpenShift = false; + var userProfile = HawtioOAuth.getUserProfile(); + log.debug("User profile: ", userProfile); + if (userProfile && userProfile.provider === "hawtio-google-oauth") { + log.debug("Possibly running on GCE"); + // api master is on GCE + $.ajax({ + url: UrlHelpers.join(Kubernetes.masterApiUrl(), 'api', 'v1', 'namespaces'), + complete: function (jqXHR, textStatus) { + if (textStatus === "success") { + log.debug("jqXHR: ", jqXHR); + userProfile.oldToken = userProfile.token; + userProfile.token = undefined; + $.ajaxSetup({ + beforeSend: function (request) { + } + }); + } + next(); + }, + beforeSend: function (request) { + } + }); + } + else { + log.debug("Not running on GCE"); + // double-check if we're on vanilla k8s or openshift + var rootUri = new URI(Kubernetes.masterApiUrl()).path("/oapi").query("").toString(); + log.debug("Checking for an openshift backend"); + HawtioOAuth.authenticatedHttpRequest({ + url: rootUri, + success: function (data) { + if (data) { + Kubernetes.isOpenShift = true; + } + next(); + }, + error: function (jqXHR, textStatus, errorThrown) { + var error = KubernetesAPI.getErrorObject(jqXHR); + if (!error) { + log.debug("Failed to find root paths: ", textStatus, ": ", errorThrown); + } + else { + log.debug("Failed to find root paths: ", error); + } + Kubernetes.isOpenShift = false; + next(); + } + }); + } + } + }); + var customUrlHandlers = {}; + self.setNamespace = function (namespace) { + if (namespace === namespaceWatch.selected) { + return; + } + if (namespaceWatch.selected) { + log.debug("Stopping current watches"); + _.forOwn(namespaceWatch.watches, function (watch, key) { + if (!KubernetesAPI.namespaced(key)) { + return; + } + log.debug("Disconnecting watch: ", key); + watch.disconnect(); + }); + _.forEach(_.keys(namespaceWatch.watches), function (key) { + if (!KubernetesAPI.namespaced(key)) { + return; + } + log.debug("Deleting kind: ", key); + delete namespaceWatch.watches[key]; + }); + } + namespaceWatch.selected = namespace; + if (namespace) { + _.forEach(self.getTypes(), function (kind) { + if (kind === KubernetesAPI.WatchTypes.NAMESPACES) { + return; + } + if (!namespaceWatch.watches[kind]) { + log.debug("Creating watch for kind: ", kind); + var config = { + kind: kind, + namespace: KubernetesAPI.namespaced(kind) ? namespace : undefined, + success: function (objects) { + watch.objects = objects; + debouncedUpdate(); + } + }; + if (kind in customUrlHandlers) { + config.urlFunction = customUrlHandlers[kind]; + } + var watch = KubernetesAPI.watch(config); + watch.config = config; + namespaceWatch.watches[kind] = watch; + } + }); + } + }; + self.hasWebSocket = true; + self.getNamespace = function () { return namespaceWatch.selected; }; + self.registerCustomUrlFunction = function (kind, url) { + customUrlHandlers[kind] = url; + if (kind in namespaceWatch.watches) { + var watch = namespaceWatch.watches[kind]; + var config = watch.config; + config.urlFunction = url; + watch.disconnect(); + delete namespaceWatch.watches[kind]; + config.success = function (objects) { + watch.objects = objects; + debouncedUpdate(); + }; + watch = KubernetesAPI.watch(config); + watch.config = config; + namespaceWatch.watches[kind] = watch; + } + }; + self.getTypes = function () { + var filter = function (kind) { + // filter out stuff we don't care about yet + switch (kind) { + case KubernetesAPI.WatchTypes.OAUTH_CLIENTS: + case KubernetesAPI.WatchTypes.IMAGE_STREAMS: + case KubernetesAPI.WatchTypes.POLICIES: + case KubernetesAPI.WatchTypes.ROLES: + case KubernetesAPI.WatchTypes.ROLE_BINDINGS: + case KubernetesAPI.WatchTypes.POLICY_BINDINGS: + case KubernetesAPI.WatchTypes.PERSISTENT_VOLUME_CLAIMS: + case KubernetesAPI.WatchTypes.PERSISTENT_VOLUMES: + case KubernetesAPI.WatchTypes.ENDPOINTS: + case KubernetesAPI.WatchTypes.RESOURCE_QUOTAS: + case KubernetesAPI.WatchTypes.SERVICE_ACCOUNTS: + return false; + default: + return true; + } + }; + var answer = k8sTypes.concat([Kubernetes.WatchTypes.NAMESPACES]); + if (Kubernetes.isOpenShift) { + answer = answer.concat(osTypes); + } + else { + answer = answer.concat(KubernetesAPI.WatchTypes.TEMPLATES); + answer = answer.concat(KubernetesAPI.WatchTypes.BUILD_CONFIGS); + } + return _.filter(answer, filter); + }; + self.getObjects = function (kind) { + if (kind === Kubernetes.WatchTypes.NAMESPACES) { + return namespaceWatch.objects; + } + if (kind in namespaceWatch.watches) { + return namespaceWatch.watches[kind].objects; + } + else { + return undefined; + } + }; + self.listeners = []; + // listener gets notified after a bunch of changes have occurred + self.registerListener = function (fn) { + self.listeners.push(fn); + }; + var projectsHandle = undefined; + // kick off the project watcher a bit sooner also + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'ProjectsWatcher', + depends: ['KubernetesApiDiscovery'], + task: function (next) { + if (Kubernetes.isOpenShift) { + projectsHandle = KubernetesAPI.watch({ + kind: KubernetesAPI.WatchTypes.PROJECTS, + namespace: undefined, + success: function (objects) { + if (self.listeners && self.listeners.length) { + log.debug("got projects: ", objects); + _.forEach(self.listeners, function (listener) { + listener({ + projects: objects + }); + }); + } + } + }); + } + next(); + } + }); + Kubernetes._module.service('WatcherService', ['userDetails', '$rootScope', '$timeout', function (userDetails, $rootScope, $timeout) { + return self; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + var log = Logger.get("kubernetes-term-windows"); + Kubernetes._module.config(["kubernetesContainerSocketProvider", function (kubernetesContainerSocketProvider) { + kubernetesContainerSocketProvider.WebSocketFactory = "CustomWebSockets"; + }]); + Kubernetes._module.factory('CustomWebSockets', ["userDetails", function (userDetails) { + return function CustomWebSocket(url, protocols) { + var paths = url.split('?'); + if (!_.startsWith(paths[0], Kubernetes.masterApiUrl())) { + paths[0] = UrlHelpers.join(Kubernetes.masterApiUrl(), paths[0]); + } + url = KubernetesAPI.wsUrl(paths[0]); + url.search(paths[1] + '&access_token=' + userDetails.token); + log.debug("Using ws url: ", url.toString()); + return new WebSocket(url.toString(), protocols); + }; + }]); + Kubernetes._module.service('TerminalService', ["$rootScope", "$document", "$compile", "$templateCache", function ($rootScope, $document, $compile, $templateCache) { + var body = $document.find('body'); + function positionTerminals(terminals) { + var total = _.keys(terminals).length; + var dist = (body.width() - 225) / total; + var position = 5; + angular.forEach(terminals, function (value, key) { + if (!value.scope.docked) { + return; + } + value.el.css('left', position + 'px'); + position = position + dist; + }); + } + var defaultTemplate = $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, 'termShell.html')); + var self = { + positionTerminals: function () { + positionTerminals(self.terminals); + }, + terminals: {}, + newTerminal: function (podLink, containerName, template) { + if (template === void 0) { template = defaultTemplate; } + var terminalId = UrlHelpers.join(podLink, containerName); + if (terminalId in self.terminals) { + log.debug("Already a terminal with id: ", terminalId); + self.raiseTerminal(terminalId); + return terminalId; + } + var scope = $rootScope.$new(); + scope.podLink = podLink; + scope.containerName = containerName; + scope.id = terminalId; + scope.docked = true; + var el = $($compile(template)(scope)); + var term = { + scope: scope, + el: el + }; + body.append(el); + self.terminals[terminalId] = term; + positionTerminals(self.terminals); + return terminalId; + }, + closeTerminal: function (id) { + var term = self.terminals[id]; + if (term) { + term.el.remove(); + delete self.terminals[id]; + positionTerminals(self.terminals); + } + }, + raiseTerminal: function (id) { + angular.forEach(self.terminals, function (value, key) { + if (key === id) { + value.el.css('z-index', '4000'); + value.el.find('.terminal').focus(); + } + else { + value.el.css('z-index', '3000'); + } + }); + } + }; + return self; + }]); + function addWindowActions(scope, element, TerminalService) { + var moved = false; + var lastX = 0; + var lastY = 0; + var header = element.find('.terminal-title'); + var body = element.find('.terminal-body'); + element.on('$destroy', function () { + $('#main').css({ display: 'inherit' }); + }); + var HEIGHT = 348; + var WIDTH = 600; + var TITLE_HEIGHT = 35; + var NAV_OFFSET = 46; + element.css({ + height: HEIGHT, + width: WIDTH + }); + header.css({ + height: TITLE_HEIGHT + }); + body.css({ + position: 'absolute', + top: 35, + left: 0, + right: 0, + bottom: 0 + }); + scope.close = function () { + TerminalService.closeTerminal(scope.id); + }; + scope.raise = function () { + TerminalService.raiseTerminal(scope.id); + }; + scope.$watch('docked', function (docked) { + if (docked) { + element.width(WIDTH); + if (!element.hasClass('minimized')) { + element.height(HEIGHT); + } + } + }); + scope.startResize = function (e) { + e.preventDefault(); + log.debug("Start resize"); + scope.resizing = true; + element.on('mouseup', scope.stopResize); + $(document).on('mousemove', scope.doResize); + $(document).on('mouseleave', scope.stopResize); + }; + scope.doResize = function (e) { + if (scope.resizing) { + log.debug("Resizing, e: ", e); + if (!moved) { + lastX = e.clientX; + lastY = e.clientY; + moved = true; + return; + } + var height = element.height(); + var width = element.width(); + var deltaX = e.clientX - lastX; + var deltaY = e.clientY - lastY; + var newHeight = height + deltaY; + var newWidth = width + deltaX; + if (newHeight > 35 && newWidth > 80) { + element.height(height + deltaY); + element.width(width + deltaX); + } + lastX = e.clientX; + lastY = e.clientY; + } + }; + scope.stopResize = function (e) { + scope.resizing = false; + moved = false; + element.off('mouseup', scope.stopResize); + $(document).off('mousemove', scope.doResize); + $(document).off('mouseleave', scope.stopResize); + }; + scope.mouseDown = function (e) { + e.preventDefault(); + if (element.hasClass('minimized') || element.hasClass('maximized')) { + return; + } + scope.dragging = true; + element.on('mouseup', scope.mouseUp); + $(document).on('mousemove', scope.mouseMove); + $(document).on('mouseleave', scope.mouseUp); + }; + scope.mouseUp = function (e) { + e.preventDefault(); + scope.dragging = false; + moved = false; + var height = element.height(); + var offset = element.offset(); + var winHeight = $(window).height(); + if (offset.top > (winHeight - height - 20)) { + element.css({ top: "inherit", left: "inherit" }); + scope.docked = true; + TerminalService.positionTerminals(); + } + else { + scope.docked = false; + } + element.off('mouseup', scope.mouseUp); + $(document).off('mousemove', scope.mouseMove); + $(document).off('mouseleave', scope.mouseUp); + }; + scope.mouseMove = function (e) { + if (scope.dragging) { + if (!moved) { + lastX = e.clientX; + lastY = e.clientY; + moved = true; + return; + } + var deltaX = e.clientX - lastX; + var deltaY = e.clientY - lastY; + var elOffset = element.offset(); + element.offset({ top: elOffset.top + deltaY, left: elOffset.left + deltaX }); + lastX = e.clientX; + lastY = e.clientY; + } + }; + function restoreWindow(scope, element) { + if (scope.offset) { + element.offset(scope.offset); + scope.docked = false; + } + if (scope.height) { + element.height(scope.height); + } + if (scope.width) { + element.width(scope.width); + } + } + function saveWindow(scope, element) { + scope.offset = element.offset(); + scope.height = element.height(); + scope.width = element.width(); + } + scope.maximized = function () { + return element.hasClass('maximized'); + }; + scope.maximize = function ($e) { + $e.preventDefault(); + if (element.hasClass('minimized')) { + scope.minimize(); + } + if (element.hasClass('maximized')) { + restoreWindow(scope, element); + $('#main').css({ display: 'inherit' }); + } + else { + saveWindow(scope, element); + $('#main').css({ display: 'none' }); + element.css({ + height: 'inherit', + bottom: 0, + width: '100%', + top: NAV_OFFSET, + left: 0 + }); + } + element.toggleClass('maximized'); + }; + scope.minimize = function ($e) { + $e.preventDefault(); + if (element.hasClass('maximized')) { + scope.maximize(); + } + if (element.hasClass('minimized')) { + restoreWindow(scope, element); + } + else { + saveWindow(scope, element); + scope.docked = true; + element.css({ height: TITLE_HEIGHT, top: "inherit", left: "inherit" }); + TerminalService.positionTerminals(); + } + element.toggleClass('minimized'); + }; + } + Kubernetes.addWindowActions = addWindowActions; + Kubernetes._module.directive('terminalWindow', ["$compile", "TerminalService", function ($compile, TerminalService) { + return { + restrict: 'A', + scope: false, + link: function (scope, element, attr) { + addWindowActions(scope, element, TerminalService); + var body = element.find('.terminal-body'); + body.append($compile('')(scope)); + } + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + var log = Logger.get("kubernetes-pod-logs"); + Kubernetes._module.service("PodLogReplacements", function () { + return []; + }); + Kubernetes._module.run(["PodLogReplacements", function (PodLogReplacements) { + var log = Logger.get("pod-log-replacers"); + // Add ANSI escape character replacer + // adapted from https://github.com/mmalecki/ansispan + var colors = { + '30': 'black', + '31': 'red', + '32': 'green', + '33': 'yellow', + '34': 'blue', + '35': 'purple', + '36': 'cyan', + '37': 'white' + }; + PodLogReplacements.push(function (msg) { + if (!msg) { + return msg; + } + var end = ""; + _.forOwn(colors, function (color, code) { + var start = ""; + msg = msg.replace(new RegExp('\033\\[' + code + 'm', 'g'), start); + msg = msg.replace(new RegExp('\033\\[0;' + code + 'm', 'g'), start); + }); + msg = msg.replace(/\033\[1m/g, '').replace(/\033\[22m/g, ''); + msg = msg.replace(/\033\[3m/g, '').replace(/\033\[23m/g, ''); + msg = msg.replace(/\033\[m/g, end); + msg = msg.replace(/\033\[0m/g, end); + msg = msg.replace(/\033\[39m/g, end); + msg = msg.replace(/\033\[2m/g, ''); + msg = msg.replace(/\033\[0;39m/g, end); + log.debug("Running replacement on message: ", msg); + return msg; + }); + }]); + Kubernetes._module.controller("Kubernetes.PodLogLinkController", ["$scope", "TerminalService", "$templateCache", function ($scope, TerminalService, $templateCache) { + $scope.openLogs = function (entity) { + log.debug("Open logs: ", entity); + TerminalService.newTerminal(entity.metadata.selfLink, entity.metadata.name, $templateCache.get(UrlHelpers.join(Kubernetes.templatePath, 'logShell.html'))); + }; + }]); + Kubernetes._module.directive('podLogDisplay', ["userDetails", "PodLogReplacements", function (userDetails, PodLogReplacements) { + return { + restrict: 'E', + template: "\n \n ", + link: function (scope, element, attr) { + var link = scope.$eval('podLink'); + var name = scope.$eval('containerName'); + if (!link) { + return; + } + scope.fetched = false; + scope.previous = false; + scope.messages = []; + link = UrlHelpers.join(Kubernetes.masterApiUrl(), link, 'log'); + link = KubernetesAPI.wsUrl(link); + link.search({ + follow: true, + tailLines: 1000, + access_token: userDetails.token + }); + var messages = []; + var pullMessages = _.debounce(function () { + scope.messages = scope.messages.concat(_.remove(messages, function () { return true; }).map(function (msg) { + PodLogReplacements.forEach(function (replFunc) { + if (angular.isFunction(replFunc)) { + msg = replFunc(msg); + } + }); + return msg; + })); + if (!scope.fetched) { + scope.fetched = true; + } + Core.$apply(scope); + }, 1000); + function initSocket(link) { + scope.fetched = false; + messages.length = 0; + scope.messages.length = 0; + var ws = new WebSocket(link.toString(), 'base64.binary.k8s.io'); + ws.onmessage = function (event) { + try { + var message = window.atob(event.data); + messages.push(message); + pullMessages(); + } + catch (err) { + } + }; + return ws; + } + var ws = initSocket(link); + scope.$watch('previous', function (value, old) { + if (value !== old) { + if (link.hasSearch('previous')) { + link.removeSearch('previous').addSearch('previous', scope.previous); + } + else { + link.addSearch('previous', scope.previous); + } + ws.close(); + ws = initSocket(link); + } + }); + element.on('$destroy', function () { + if (ws) { + try { + ws.close(); + } + catch (err) { + } + delete ws; + } + }); + } + }; + }]); + Kubernetes._module.directive('podLogWindow', ["$compile", "TerminalService", function ($compile, TerminalService) { + return { + restrict: 'A', + scope: false, + link: function (scope, element, attr) { + Kubernetes.addWindowActions(scope, element, TerminalService); + scope.atBottom = true; + scope.$watch('atBottom', function (val) { + console.log("atBottom: ", val); + }); + } + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.EnvItem = Kubernetes.controller("EnvItem", ["$scope", function ($scope) { + var parts = $scope.data.split('='); + $scope.key = parts.shift(); + $scope.value = parts.join('='); + }]); + // main controller for the page + Kubernetes.Pods = Kubernetes.controller("Pods", ["$scope", "KubernetesModel", "KubernetesPods", "KubernetesState", "ServiceRegistry", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesPods, KubernetesState, ServiceRegistry, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.itemSchema = Forms.createFormConfiguration(); + $scope.tableConfig = { + data: 'model.pods', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '_key', + displayName: 'Name', + defaultSort: true, + cellTemplate: $templateCache.get("idTemplate.html") + }, + { + field: '$statusCss', + displayName: 'Status', + cellTemplate: $templateCache.get("statusTemplate.html") + }, + { field: '$eventCount', + displayName: 'Events', + cellTemplate: $templateCache.get("eventSummaryTemplate.html") + }, + { + field: '$restartCount', + displayName: 'Restarts' + }, + { + field: '$createdTime', + displayName: 'Age', + cellTemplate: $templateCache.get("ageTemplate.html") + }, + { + field: '$imageNames', + displayName: 'Images', + cellTemplate: $templateCache.get("imageTemplate.html") + }, + { + field: '$host', + displayName: 'Host', + cellTemplate: $templateCache.get("hostTemplate.html") + }, + { + field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + }, + { + field: '$podIP', + displayName: 'Pod IP', + customSortField: function (field) { + return Kubernetes.sortByPodIp(field.$podIP); + } + } + ] + }; + $scope.openLogs = function () { + var pods = $scope.tableConfig.selectedItems; + if (!pods || !pods.length) { + if ($scope.id) { + var item = $scope.item; + if (item) { + pods = [item]; + } + } + } + Kubernetes.openLogsForPods(ServiceRegistry, $window, KubernetesModel.currentNamespace(), pods); + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.deletePrompt = function (selected) { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + Kubernetes.log.debug("deleting: ", Kubernetes.getName(next)); + KubernetesPods.delete({ + id: Kubernetes.getName(next) + }, undefined, function () { + Kubernetes.log.debug("deleted: ", Kubernetes.getName(next)); + deleteSelected(selected, selected.shift()); + }, function (error) { + Kubernetes.log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + }); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete pods?', + action: 'The following pods will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + $scope.createPods = function () { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + var obj = JSON.parse(xhr.responseText); + var object = { + "name": "newpod", + "labels": { + "aim": "test", + "app": "oracle" + }, + "path": '/home/', + "port": 1525 + }; + Kubernetes.createRC(object); + } + else { + } + } + }; + xhr.open("POST", "/oracleAppPath", false); //与服务器连接并发送 + xhr.send(null); + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ReplicationControllerController = Kubernetes.controller("ReplicationControllerController", ["$scope", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.itemConfig = { + properties: { + '^\\/labels$': { + template: $templateCache.get('labelTemplate.html') + } + } + }; + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.$watch('model.pods', function (newValue, oldValue) { + updateData(); + }, true); + $scope.flipRaw = function () { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + updateData(); + function updateData() { + if ($scope.dirty) { + return; + } + $scope.id = $routeParams["id"]; + $scope.item = $scope.model.getReplicationController(KubernetesState.selectedNamespace, $scope.id); + if ($scope.item) { + $scope.rawModel = Kubernetes.toRawYaml($scope.item); + } + Core.$apply($scope); + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ReplicationControllerEditController = Kubernetes.controller("ReplicationControllerEditController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "SchemaRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, schemas) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + Kubernetes.log.debug("Schema: ", $scope.schema); + $scope.config = schemas.cloneSchema("io.fabric8.kubernetes.api.model.ReplicationController"); + //$$scope.config = KubernetesSchema.definitions.kubernetes_v1beta3_ReplicationController; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + if ($scope.id) { + $scope.entity = $scope.model.getReplicationController(KubernetesState.selectedNamespace, $scope.id); + Core.$apply($scope); + $scope.fetched = true; + } + else { + $scope.fetched = true; + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ReplicationControllers = Kubernetes.controller("ReplicationControllers", ["$scope", "OracleStatusModel", "KubernetesModel", "KubernetesReplicationControllers", "KubernetesPods", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, OracleStatusModel, KubernetesModel, KubernetesReplicationControllers, KubernetesPods, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.tableConfig = { + data: 'model.replicationControllers', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '_key', + displayName: '服务名称', + cellTemplate: $templateCache.get("idTemplate.html") + }, + //{ field: '$replicas', + // displayName: 'Scale', + // cellTemplate:$templateCache.get("desiredReplicas.html") + //}, + { field: '$pods.age', + displayName: '启动时间', + cellTemplate: $templateCache.get("ageTemplate.html") + }, + { field: '$labelsText', + displayName: '数据标签', + cellTemplate: $templateCache.get("labelTemplate.html") + }, + { field: '$pods', + displayName: '连接参数', + cellTemplate: $templateCache.get("connectParamTemplate.html") + }, + { field: '$pods[0].$eventCount', + displayName: '服务启动日志', + cellTemplate: $templateCache.get("eventSummaryTemplate.html") + }, + { field: '$podCounters', + displayName: '服务状态', + cellTemplate: $templateCache.get("podCountsAndLinkTemplate.html"), + customSortField: function (field) { + if (field.$podCounters.ready) { + return 3; + } + else if (field.$podCounters.valid || field.$podCounters.waiting) { + return 2; + } + else if (field.$podCounters.error) { + return 0; + } + else { + return 1; + } + } + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.deletePrompt = function (selected) { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + Kubernetes.log.debug("deleting: ", Kubernetes.getName(next)); + Kubernetes.resizeController($http, KubernetesApiURL, next, 0, function () { + Kubernetes.log.debug("updated number of replicas"); + KubernetesReplicationControllers.delete({ + id: Kubernetes.getName(next) + }, undefined, function () { + Kubernetes.log.debug("deleted: ", Kubernetes.getName(next)); + if (next.metadata.labels.style === "oracle") + Kubernetes.connectOracle($http, $timeout, "/cancelOracleConection", "", Kubernetes.getName(next), 0); + deleteSelected(selected, selected.shift()); + }, function (error) { + Kubernetes.log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + }); + }); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: '是否需要删除oracle服务?', + action: '以下的oracle服务将会被删除:', + okText: '删除', + okClass: 'btn-danger', + custom: "该服务删除后将会清除oracle对应服务的端口等资源占用,但不删除数据文件,是否删除,请确认!", + customClass: "alert alert-warning", + cancelText: "取消" + }).open(); + }; + $scope.createRCs = function () { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + var obj = JSON.parse(xhr.responseText); + console.log(obj.path); + var name = Kubernetes.getRandomString(8); + //console.log(name + "=====" +port); + var object = { + "name": name, + "labels": { + "name": name + }, + "path": obj.path, + }; + Kubernetes.createRC(object, function (rc) { + Kubernetes.connectOracle($http, $timeout, "/connectToOracle", "", Kubernetes.getName(rc), 0); + }); + } + else if (xhr.status == 403) { + alert("两次创建oracle服务时间间隔需要超过1分钟!"); + } + else { + } + } + }; + xhr.open("POST", "/oracleAppPath", false); //与服务器连接并发送 + xhr.send(null); + }; + $scope.stopPrompt = function (selected) { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: function (result) { + if (result) { + function stopSelected(selected, next) { + if (next) { + Kubernetes.resizeController($http, KubernetesApiURL, next, 0, function () { + if (next.metadata.labels.style === "oracle") + Kubernetes.connectOracle($http, $timeout, "/cancelOracleConection", "", Kubernetes.getName(next), 0); + stopSelected(selected, selected.shift()); + }); + } + } + stopSelected(selected, selected.shift()); + } + }, + title: '是否需要停止oracle服务?', + action: '以下的oracle服务将会被停止:', + okText: '停止', + okClass: 'btn-danger', + custom: "该服务停止后将无法继续提供连接访问服务,但可通过启动按钮重新启动该服务以进行访问。是否停止,请确认", + customClass: "alert alert-warning", + cancelText: "取消" + }).open(); + }; + $scope.reStartPrompt = function (selected) { + function startSelected(selected, next) { + if (next) { + if (next.$replicas === 0) + Kubernetes.resizeController($http, KubernetesApiURL, next, 1, function () { + Kubernetes.connectOracle($http, $timeout, "/connectToOracle", "", Kubernetes.getName(next), 0); + startSelected(selected, selected.shift()); + }); + } + } + startSelected(selected, selected.shift()); + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +var Kubernetes; +(function (Kubernetes) { + function schemaSetRequired(schema, propertyName, isRequired) { + if (isRequired === void 0) { isRequired = true; } + if (schema && propertyName) { + var required = schema.required; + if (isRequired) { + if (!required) { + required = []; + schema.required = required; + } + if (!_.contains(required, propertyName)) { + required.push(propertyName); + } + } + else { + if (required) { + var idx = required.indexOf(propertyName); + if (idx >= 0) { + required.splice(idx, 1); + } + } + } + } + } + Kubernetes.schemaSetRequired = schemaSetRequired; +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.SecretController = Kubernetes.controller("SecretController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "K8SClientFactory", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, K8SClientFactory) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + Kubernetes.selectSubNavBar($scope, "Secrets", $scope.id ? "Edit Secret: " + $scope.id : "Create Secret"); + var kubeClient = Kubernetes.createKubernetesClient("secrets"); + var onSaveUrl = $location.search()["savedUrl"]; + var createKind = $location.search()["kind"]; + $scope.sshKeys = Kubernetes.sshSecretDataKeys; + $scope.httpsKeys = Kubernetes.httpsSecretDataKeys; + var secretLabels = { + "ssh-key": "SSH private key", + "ssh-key.pub": "SSH public key", + "ca.crt": "CA Certificate", + ".dockercfg": "Docker config", + "username": "User name" + }; + var secretTooltips = { + "ssh-key": "SSH private key text contents", + "ca.crt": "Certificate Authority (CA) Certificate", + ".dockercfg": "Docker configuration token" + }; + $scope.$on('kubernetesModelUpdated', function () { + if ($scope.id && !$scope.secret) { + updateData(); + } + }); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.propertyKeys = function () { + return _.keys(secretLabels); + }; + $scope.checkNameUnique = function (value) { + var answer = true; + angular.forEach($scope.model.secrets, function (secret) { + var name = Kubernetes.getName(secret); + if (value === name) { + answer = false; + } + }); + return answer; + }; + $scope.checkFieldUnique = function (key) { + return $scope.entity.properties[key] ? false : true; + }; + $scope.hasAllKeys = function (keys) { + var answer = keys && keys.length; + angular.forEach(keys, function (key) { + if (!$scope.entity.properties[key]) { + answer = false; + } + }); + return answer; + }; + $scope.addFieldDialog = { + controller: null, + newReplicas: 0, + dialog: new UI.Dialog(), + onOk: function () { + $scope.addFieldDialog.dialog.close(); + $scope.addDataField(); + }, + open: function (controller) { + var addFieldDialog = $scope.addFieldDialog; + addFieldDialog.dialog.open(); + $timeout(function () { + $('#newDataName').focus(); + }, 50); + }, + close: function () { + $scope.addFieldDialog.dialog.close(); + } + }; + $scope.entityChanged = function () { + $scope.changed = true; + }; + $scope.addFields = function (keys) { + angular.forEach(keys, function (key) { return addField(key); }); + Core.$apply($scope); + }; + function addField(key) { + var property = createProperty(key, ""); + $scope.entity.properties[key] = property; + $scope.entity.newDataKey = ""; + $scope.showAddDataFieldForm = false; + $scope.entityChanged(); + } + $scope.addDataField = function () { + var key = $scope.entity.newDataKey; + if (key) { + addField(key); + Core.$apply($scope); + } + }; + $scope.deleteProperty = function (key) { + if (key) { + delete $scope.entity.properties[key]; + $scope.entityChanged(); + Core.$apply($scope); + } + }; + $scope.cancel = function () { + updateData(); + }; + $scope.save = function () { + var entity = $scope.entity || {}; + var name = entity.name; + if (name) { + if (!$scope.secret) { + $scope.secret = { + apiVersion: Kubernetes.defaultApiVersion, + kind: "Secret", + metadata: { + name: "" + }, + data: {} + }; + } + var data = {}; + angular.forEach(entity.properties, function (property) { + var key = property.key; + var value = property.value || ""; + if (key) { + data[key] = window.btoa(value); + } + }); + $scope.secret.metadata.name = name; + $scope.secret.data = data; + Core.notification('info', "Saving secret " + name); + kubeClient.put($scope.secret, function (data) { + var secretsLink = onSaveUrl || Developer.namespaceLink($scope, $routeParams, "secrets"); + var params = {}; + if (onSaveUrl) { + params['secret'] = name; + } + $location.path(secretsLink); + $location.search(params); + Kubernetes.log.info("navigating to URL: " + secretsLink + " with params " + angular.toJson($location.search())); + }, function (err) { + Core.notification('error', "Failed to secret " + name + "\n" + err); + }); + } + }; + updateData(); + function createProperty(key, text) { + var label = secretLabels[key] || Core.humanizeValue(key); + var tooltip = secretTooltips[key] || "Value of the " + label; + var rows = 5; + var lines = text.split("\n").length + 1; + if (lines > rows) { + rows = lines; + } + var type = "textarea"; + if (key === "username") { + type = "text"; + if (!text) { + text = Kubernetes.currentUserName(); + } + } + else if (key === "password") { + type = "password"; + } + var property = { + key: key, + label: label, + tooltip: tooltip, + rows: rows, + value: text, + type: type + }; + return property; + } + function updateData() { + $scope.item = null; + $scope.changed = false; + $scope.entity = { + name: $scope.id, + properties: {} + }; + if ($scope.id) { + angular.forEach($scope.model.secrets, function (secret) { + var name = Kubernetes.getName(secret); + if (name === $scope.id) { + $scope.secret = secret; + angular.forEach(secret.data, function (value, key) { + var text = ""; + if (angular.isString(value) && value) { + text = window.atob(value); + } + var property = createProperty(key, text); + $scope.entity.properties[key] = property; + }); + $scope.fetched = true; + Core.$apply($scope); + } + }); + } + else { + if (createKind === "ssh") { + $scope.addFields($scope.sshKeys); + } + else if (createKind === "https") { + $scope.addFields($scope.httpsKeys); + } + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.SecretsController = Kubernetes.controller("SecretsController", ["$scope", "KubernetesModel", "KubernetesState", "ServiceRegistry", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, ServiceRegistry, $dialog, $window, $templateCache, $routeParams, $location, localStorage, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.$createSecretLink = Developer.namespaceLink($scope, $routeParams, "secretCreate"); + var kubeClient = Kubernetes.createKubernetesClient("secrets"); + $scope.tableConfig = { + data: 'model.secrets', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '_key', + displayName: 'Name', + defaultSort: true, + cellTemplate: $templateCache.get("idTemplate.html") + }, + { + field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + }, + ] + }; + $scope.deletePrompt = function (selected) { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + kubeClient.delete(next, function () { + deleteSelected(selected, selected.shift()); + }); + } + else { + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Secrets', + action: 'The following Secrets will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ServiceController = Kubernetes.controller("ServiceController", ["$scope", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.itemConfig = { + properties: { + '^\\/labels$': { + template: $templateCache.get('labelTemplate.html') + } + } + }; + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + $scope.$watch('model.services', function (newValue, oldValue) { + updateData(); + }, true); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + $scope.flipRaw = function () { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + updateData(); + function updateData() { + $scope.id = $routeParams["id"]; + $scope.namespace = $routeParams["namespace"] || KubernetesState.selectedNamespace; + $scope.item = $scope.model.getService($scope.namespace, $scope.id); + if ($scope.item) { + $scope.rawModel = Kubernetes.toRawYaml($scope.item); + } + Core.$apply($scope); + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ServiceEditController = Kubernetes.controller("ServiceEditController", ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "SchemaRegistry", + function ($scope, KubernetesModel, KubernetesState, KubernetesSchema, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL, schemas) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = schemas.cloneSchema("io.fabric8.kubernetes.api.model.Service"); + //$scope.config = KubernetesSchema.definitions.kubernetes_v1beta2_Service; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$on('$routeUpdate', function ($event) { + updateData(); + }); + updateData(); + function updateData() { + if ($scope.id) { + $scope.entity = $scope.model.getService(KubernetesState.selectedNamespace, $scope.id); + Core.$apply($scope); + $scope.fetched = true; + } + else { + $scope.fetched = true; + } + } + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes._module.factory('ServiceRegistry', [function () { + return new ServiceRegistryService(); + }]); + /** + * Represents a simple interface to service discovery that can be used early on in the application lifecycle before the + * underlying model has been created via dependency injection + */ + var ServiceRegistryService = (function () { + function ServiceRegistryService() { + this.model = null; + } + /** + * Returns true if there is a service available for the given ID or false + */ + ServiceRegistryService.prototype.hasService = function (serviceName) { + return this.findService(serviceName) ? true : false; + }; + /** + * Returns the service for the given service name (ID) or null if it cannot be found + * + * @param serviceName the name of the service to look for + * @return {null} + */ + ServiceRegistryService.prototype.findService = function (serviceName) { + var answer = null; + if (serviceName) { + var model = this.getModel(); + if (model) { + var namespace = model.currentNamespace(); + return model.getService(namespace, serviceName); + } + } + return answer; + }; + /** + * Returns the service link for the given service name + * + * @param serviceName the name of the service + * @return {null} + */ + ServiceRegistryService.prototype.serviceLink = function (serviceName) { + var service = this.findService(serviceName); + return Kubernetes.serviceLinkUrl(service); + }; + /** + * Returns the service link for the given service name if its ready (has at least one ready pod) + * + * @param serviceName the name of the service + * @return {null} + */ + ServiceRegistryService.prototype.serviceReadyLink = function (serviceName) { + var service = this.findService(serviceName); + if (Kubernetes.readyPodCount(service)) { + return Kubernetes.serviceLinkUrl(service); + } + else { + return null; + } + }; + ServiceRegistryService.prototype.getModel = function () { + var answer = this.model; + // lets allow lazy load so we can be invoked before the injector has been created + if (!answer) { + var injector = HawtioCore.injector; + if (injector) { + this.model = injector.get('KubernetesModel'); + } + } + answer = this.model; + return answer; + }; + return ServiceRegistryService; + }()); + Kubernetes.ServiceRegistryService = ServiceRegistryService; +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.ServiceApps = Kubernetes._module.controller('Kubernetes.ServiceApps', ["$scope", "KubernetesModel", function ($scope, KubernetesModel) { + $scope.model = KubernetesModel; + }]); + Kubernetes.Services = Kubernetes.controller("Services", ["$scope", "KubernetesModel", "KubernetesServices", "KubernetesPods", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + function ($scope, KubernetesModel, KubernetesServices, KubernetesPods, KubernetesState, $templateCache, $location, $routeParams, $http, $timeout, KubernetesApiURL) { + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + ControllerHelpers.bindModelToSearchParam($scope, $location, 'mode', 'mode', 'list'); + $scope.tableConfig = { + data: 'model.services', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '_key', + displayName: 'Name', + cellTemplate: $templateCache.get("idTemplate.html") + }, + { field: '$serviceUrl', + displayName: 'Address', + cellTemplate: $templateCache.get("portalAddress.html") + }, + { field: '$podCount', + displayName: 'Pods', + cellTemplate: $templateCache.get("podCountsAndLinkTemplate.html"), + customSortField: function (field) { + // need to concat all the pod counters + var ready = field.$podCounters.ready || 0; + var valid = field.$podCounters.valid || 0; + var waiting = field.$podCounters.waiting || 0; + var error = field.$podCounters.error || 0; + return ready + valid + waiting + error; + } + }, + { field: '$selectorText', + displayName: 'Selector', + cellTemplate: $templateCache.get("selectorTemplate.html") + }, + { field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + } + ] + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.deletePrompt = function (selected) { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: function (result) { + if (result) { + function deleteSelected(selected, next) { + if (next) { + Kubernetes.log.debug("deleting: ", Kubernetes.getName(next)); + KubernetesServices.delete({ + id: Kubernetes.getName(next) + }, undefined, function () { + Kubernetes.log.debug("deleted: ", Kubernetes.getName(next)); + deleteSelected(selected, selected.shift()); + }, function (error) { + Kubernetes.log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + }); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete services?', + action: 'The following services will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + // controller for the status icon cell + Kubernetes.PodStatus = Kubernetes.controller("PodStatus", ["$scope", function ($scope) { + $scope.statusMapping = function (text) { + return Kubernetes.statusTextToCssClass(text); + }; + }]); + Kubernetes._module.controller("Kubernetes.TermController", ["$scope", "TerminalService", function ($scope, TerminalService) { + $scope.canConnectTo = function (container) { + if (container.securityContext && container.securityContext.privileged) { + return false; + } + return true; + }; + $scope.openTerminal = function (selfLink, containerName) { + var id = TerminalService.newTerminal(selfLink, containerName); + Kubernetes.log.debug("Created terminal, id: ", id); + }; + }]); + // controller that deals with the labels per pod + Kubernetes.Labels = Kubernetes.controller("Labels", ["$scope", "$location", function ($scope, $location) { + $scope.labels = []; + var labelKeyWeights = { + "name": 1, + "replicationController": 2, + "group": 3 + }; + $scope.$watch('entity', function (newValue, oldValue) { + if (newValue) { + // log.debug("labels: ", newValue); + // massage the labels a bit + $scope.labels = []; + angular.forEach(Core.pathGet($scope.entity, ["metadata", "labels"]), function (value, key) { + if (key === 'fabric8' || key === 'style' || key === 'status') { + // TODO not sure what this is for, the container type? + return; + } + $scope.labels.push({ + key: key, + title: value + }); + }); + // lets sort by key but lets make sure that we weight certain labels so they are first + $scope.labels = $scope.labels.sort(function (a, b) { + function getWeight(key) { + return labelKeyWeights[key] || 1000; + } + var n1 = a["key"]; + var n2 = b["key"]; + var w1 = getWeight(n1); + var w2 = getWeight(n2); + var diff = w1 - w2; + if (diff < 0) { + return -1; + } + else if (diff > 0) { + return 1; + } + if (n1 && n2) { + if (n1 > n2) { + return 1; + } + else if (n1 < n2) { + return -1; + } + else { + return 0; + } + } + else { + if (n1 === n2) { + return 0; + } + else if (n1) { + return 1; + } + else { + return -1; + } + } + }); + } + }); + $scope.handleClick = function (entity, labelType, value) { + // log.debug("handleClick, entity: ", entity, " key: ", labelType, " value: ", value); + $scope.$emit('labelFilterUpdate', value.title); + }; + $scope.labelClass = Kubernetes.containerLabelClass; + }]); + //服务状态过滤 + Kubernetes.Status = Kubernetes.controller('Status', ["$scope", "$http", "$interval", "$location", "KubernetesApiURL", function ($scope, $http, $interval, $location, KubernetesApiURL) { + $scope.$watch('entity', function (newValue, oldValue) { + if (newValue) { + //console.log($scope.entity.metadata.labels); + if ($scope.entity.metadata.labels.status === "0" && $scope.entity.metadata.labels.lock === "0") { + var labels = Kubernetes.updateReplicationControllerLabels($http, KubernetesApiURL, $scope.entity, { "style": "oracle", "status": "0", "lock": "1" }); + var ip = $scope.entity.$pods[0].$host + ":" + $scope.entity.$pods[0].spec.containers[0].ports[0].hostPort; + var timer = $interval(function () { + $http({ + url: '/connectToOracle', + method: 'POST', + params: { param: ip } + }).success(function (data, header, config, status) { + if (header === 200) { + console.log(data); + $interval.cancel(timer); + } + }).error(function (data, header, config, status) { + }); + }, 60000, 10); + timer.then(function () { + console.log("All Connect Done!"); + }); + } + } + }, true); + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +/// +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes._module.directive("hawtioTabs", ['HawtioSubTabs', function (HawtioSubTabs) { + return { + link: function (scope, element, attrs) { + HawtioSubTabs.apply(scope.$eval('subTabConfig')); + } + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +var Kubernetes; +(function (Kubernetes) { + Kubernetes.TemplateController = Kubernetes.controller("TemplateController", [ + "$scope", "$location", "$http", "$timeout", "$routeParams", "marked", "$templateCache", "$modal", "KubernetesModel", "KubernetesState", "KubernetesApiURL", + function ($scope, $location, $http, $timeout, $routeParams, marked, $templateCache, $modal, KubernetesModel, KubernetesState, KubernetesApiURL) { + var model = $scope.model = KubernetesModel; + $scope.filterText = $location.search()["q"]; + $scope.targetNamespace = $routeParams.targetNamespace; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.$watchCollection('model.namespaces', function () { + if (!$scope.targetNamespace) { + $scope.targetNamespace = model.currentNamespace(); + } + }); + var returnTo = new URI($location.search()['returnTo'] || '/kubernetes/apps'); + function goBack() { + $location.path(returnTo.path()).search(returnTo.query(true)); + } + function getAnnotations(obj) { + return Core.pathGet(obj, ['metadata', 'annotations']); + } + function getValueFor(obj, key) { + var annotations = getAnnotations(obj); + if (!annotations) { + return ""; + } + var name = Kubernetes.getName(obj); + if (name) { + var fullKey = "fabric8." + name + "/" + key; + var answer = annotations[fullKey]; + if (answer) { + return answer; + } + } + var key = _.find(_.keys(annotations), function (k) { return _.endsWith(k, key); }); + if (key) { + return annotations[key]; + } + else { + return ""; + } + } + $scope.cancel = function () { + if ($scope.formConfig) { + delete $scope.formConfig; + delete $scope.entity; + $scope.objects = undefined; + return; + } + goBack(); + }; + /* + $scope.$watch('model.templates.length', (newValue) => { + if (newValue === 0) { + goBack(); + } + }); + */ + $scope.filterTemplates = function (template) { + if (Core.isBlank($scope.filterText)) { + return true; + } + return _.contains(angular.toJson(template), $scope.filterText.toLowerCase()); + }; + $scope.openFullDescription = function (template) { + var text = marked(getValueFor(template, 'description') || 'No description'); + var modal = $modal.open({ + templateUrl: UrlHelpers.join(Kubernetes.templatePath, 'templateDescription.html'), + controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) { + $scope.text = text, + $scope.ok = function () { + modal.close(); + }; + }] + }); + }; + $scope.getDescription = function (template) { + var answer = $(marked(getValueFor(template, 'description') || 'No description')); + var textDefault = answer.html(); + var maxLength = 200; + if (textDefault.length > maxLength) { + var truncated = $.trim(textDefault).substring(0, maxLength).split(' ').slice(0, -1).join(' '); + answer.html(truncated + '...'); + answer.append($templateCache.get('truncatedDescriptionTag.html')); + } + return answer.html(); + }; + $scope.getIconUrl = function (template) { + return getValueFor(template, 'iconUrl') || Kubernetes.defaultIconUrl; + }; + $scope.deployTemplate = function (template) { + Kubernetes.log.debug("Template parameters: ", template.parameters); + Kubernetes.log.debug("Template objects: ", template.objects); + Kubernetes.log.debug("Template annotations: ", template.metadata.annotations); + var templateAnnotations = template.metadata.annotations; + if (templateAnnotations) { + _.forEach(template.objects, function (object) { + var annotations = object.metadata.annotations || {}; + var name = Kubernetes.getName(object); + var matches = _.filter(_.keys(templateAnnotations), function (key) { return key.match('.' + name + '/'); }); + matches.forEach(function (match) { + if (!(match in annotations)) { + annotations[match] = templateAnnotations[match]; + } + }); + object.metadata.annotations = annotations; + }); + } + var routeServiceName = undefined; + var service = _.find(template.objects, function (obj) { + if (Kubernetes.getKind(obj) === "Service") { + var ports = Kubernetes.getPorts(obj); + if (ports && ports.length === 1) { + return true; + } + } + else { + return false; + } + }); + if (service) { + routeServiceName = Kubernetes.getName(service); + } + Kubernetes.log.debug("Service: ", service); + if ((!routeServiceName || !Kubernetes.isOpenShift) && (!template.parameters || template.parameters.length === 0)) { + Kubernetes.log.debug("No parameters required, deploying objects"); + applyObjects(template.objects); + return; + } + var formConfig = { + style: HawtioForms.FormStyle.STANDARD, + hideLegend: true, + properties: {} + }; + var params = template.parameters; + _.forEach(params, function (param) { + var property = {}; + property.label = _.startCase(param.name); + property.description = param.description; + property.default = param.value; + // TODO, do parameters support types? + property.type = 'string'; + formConfig.properties[param.name] = property; + }); + if (routeServiceName && Kubernetes.isOpenShift) { + formConfig.properties.createRoute = { + type: 'boolean', + default: true, + label: "Create Route" + }; + /* + formConfig.properties.routeName = { + type: 'string', + label: 'Route Name', + default: routeServiceName, + 'control-group-attributes': { + 'ng-show': 'entity.createRoute' + } + }; + */ + formConfig.properties.routeServiceName = { + type: 'hidden', + default: routeServiceName + }; + var namespace = Kubernetes.currentKubernetesNamespace(); + // TODO store this in localStorage! + var domain = "vagrant.f8"; + var defaultRouteHostSuffix = '.' + (namespace === "default" ? "" : namespace + ".") + domain; + formConfig.properties.routeHostname = { + type: 'string', + default: defaultRouteHostSuffix, + label: "Route host name suffix", + 'control-group-attributes': { + 'ng-show': 'entity.createRoute' + } + }; + } + $scope.entity = {}; + $scope.formConfig = formConfig; + $scope.objects = template.objects; + Kubernetes.log.debug("Form config: ", formConfig); + }; + function substitute(str, data) { + return str.replace(/\${\w*}/g, function (match) { + var key = match.replace(/\${/, '').replace(/}/, '').trim(); + return data[key] || match; + }); + } + ; + $scope.substituteAndDeployTemplate = function () { + var objects = $scope.objects; + var objectsText = angular.toJson(objects, true); + // pull these out of the entity object so they're not used in substitutions + var createRoute = $scope.entity.createRoute; + var routeHostnameSuffix = $scope.entity.routeHostname || ""; + var routeName = $scope.entity.routeName; + var routeServiceName = $scope.entity.routeServiceName; + delete $scope.entity.createRoute; + delete $scope.entity.routeHostname; + delete $scope.entity.routeName; + delete $scope.entity.routeServiceName; + objectsText = substitute(objectsText, $scope.entity); + objects = angular.fromJson(objectsText); + if (createRoute) { + var routes = []; + angular.forEach(objects, function (object) { + var kind = object.kind; + var name = Kubernetes.getName(object); + if (name && "Service" === kind) { + var routeHostname = name + routeHostnameSuffix; + var route = { + kind: "Route", + apiVersion: Kubernetes.defaultOSApiVersion, + metadata: { + name: name, + }, + spec: { + host: routeHostname, + to: { + kind: "Service", + name: name + } + } + }; + routes.push(route); + } + }); + objects = objects.concat(routes); + } + if ($scope.targetNamespace !== model.currentNamespace()) { + $scope.$on('WatcherNamespaceChanged', function () { + Kubernetes.log.debug("Namespace changed"); + setTimeout(function () { + applyObjects(objects); + Core.$apply($scope); + }, 500); + }); + Core.notification('info', "Switching to namespace " + $scope.targetNamespace + " and deploying template"); + model.kubernetes.selectedNamespace = $scope.targetNamespace; + } + else { + applyObjects(objects); + } + }; + function applyObjects(objects) { + var projectClient = Kubernetes.createKubernetesClient("projects"); + _.forEach(objects, function (object) { + Kubernetes.log.debug("Object: ", object); + var kind = Kubernetes.getKind(object); + var name = Kubernetes.getName(object); + var ns = Kubernetes.getNamespace(object); + if (kind && name) { + if (ns && ns !== Kubernetes.currentKubernetesNamespace()) { + var project = { + apiVersion: Kubernetes.defaultApiVersion, + kind: "Project", + metadata: { + name: ns, + labels: {} + } + }; + projectClient.put(project, function (data) { + Kubernetes.log.info("Created namespace: " + ns); + }, function (err) { + Kubernetes.log.warn("Failed to create namespace: " + ns + ": " + angular.toJson(err)); + }); + } + var pluralKind = kind.toLowerCase() + "s"; + var kubeClient = Kubernetes.createKubernetesClient(pluralKind, ns); + kubeClient.put(object, function (data) { + Kubernetes.log.info("updated " + kind + " name: " + name + (ns ? " ns: " + ns : "")); + }, function (err) { + Kubernetes.log.warn("Failed to update " + kind + " name: " + name + (ns ? " ns: " + ns : "") + " error: " + angular.toJson(err)); + }); + } + }); + goBack(); + } + $scope.deleteTemplate = function (template) { + UI.multiItemConfirmActionDialog({ + collection: [template], + index: 'metadata.name', + onClose: function (result) { + if (result) { + KubernetesModel['templatesResource'].delete({ + id: template.metadata.name + }, undefined, function () { + KubernetesModel['templatesResource'].query(function (data) { + KubernetesModel.templates = data.items; + }); + }, function (error) { + Kubernetes.log.debug("Error deleting template: ", error); + }); + } + }, + title: 'Delete Template?', + action: 'The following template will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + }]); +})(Kubernetes || (Kubernetes = {})); + +/// +var Navigation; +(function (Navigation) { + Navigation.pluginName = 'hawtio-navigation'; + Navigation.log = Logger.get(Navigation.pluginName); + Navigation._module = angular.module(Navigation.pluginName, []); + Navigation._module.run(function () { + }); + Navigation._module.service('HawtioBreadcrumbs', function () { + var _config = []; + var self = { + apply: function (config) { + _config.length = 0; + _.forEach(config, function (crumb) { + _config.push(crumb); + }); + }, + get: function () { + return _config; + } + }; + return self; + }); + Navigation._module.service('HawtioSubTabs', function () { + var _config = []; + var self = { + apply: function (config) { + _config.length = 0; + _.forEach(config, function (crumb) { + _config.push(crumb); + }); + }, + get: function () { + return _config; + } + }; + return self; + }); + Navigation._module.directive('viewportHeight', ['$window', '$document', function ($window, $document) { + return { + restrict: 'A', + link: function (scope, element, attr) { + // log.debug("Window: ", $window); + // log.debug("element: ", element); + var win = $($window); + var resizeFunc = function () { + var viewportHeight = win.innerHeight(); + // log.debug("Viewport height: ", viewportHeight); + var elTop = element.offset().top; + // log.debug("Element top: ", elTop); + var height = viewportHeight - elTop; + element.css('height', height); + }; + win.on('resize', resizeFunc); + element.on('$destroy', function () { + win.off('resize', resizeFunc); + }); + setTimeout(resizeFunc, 50); + } + }; + }]); + Navigation._module.directive('hawtioMainOutlet', ['HawtioSubTabs', function (HawtioSubTabs) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + scope.HawtioSubTabs = HawtioSubTabs; + scope.$watchCollection('HawtioSubTabs.get()', function (subTabConfig) { + // log.debug("subTabConfig: ", subTabConfig); + if (subTabConfig && subTabConfig.length > 0) { + element.removeClass('hidden-nav'); + } + else { + element.addClass('hidden-nav'); + } + }); + } + }; + }]); + Navigation._module.directive('hawtioTabsOutlet', ['HawtioSubTabs', function (HawtioSubTabs) { + var initialized = false; + return { + restrict: 'AE', + replace: true, + template: "\n
\n \n
\n ", + link: function (scope, element, attrs) { + if (!initialized) { + try { + $().setupVerticalNavigation(false); + } + catch (err) { + } + initialized = true; + } + scope.HawtioSubTabs = HawtioSubTabs; + var collapsed = false; + scope.getClass = function () { + //log.debug("My class: ", element.attr('class')); + if (!scope.subTabConfig || !scope.subTabConfig.length) { + return 'hidden'; + } + if (collapsed) { + return 'collapsed'; + } + return ''; + }; + scope.$on('hawtioCollapseNav', function () { + collapsed = !collapsed; + }); + scope.$watch('HawtioSubTabs.get()', function (subTabConfig) { + scope.subTabConfig = subTabConfig; + }); + } + }; + }]); + Navigation._module.directive('hawtioBreadcrumbsOutlet', ['HawtioBreadcrumbs', function (HawtioBreadcrumbs) { + return { + restrict: 'E', + scope: {}, + template: "\n
\n
    \n

    \n
  1. \n {{breadcrumb.label}}\n {{breadcrumb.label}}\n
\n
\n ", + link: function (scope, element, attrs) { + scope.breadcrumbs = HawtioBreadcrumbs; + scope.$watchCollection('breadcrumbs.get()', function (breadcrumbConfig) { + scope.breadcrumbConfig = breadcrumbConfig; + }); + } + }; + }]); + //hawtioPluginLoader.addModule('patternfly'); + hawtioPluginLoader.addModule(Navigation.pluginName); +})(Navigation || (Navigation = {})); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluY2x1ZGVzLnRzIiwia3ViZXJuZXRlcy90cy9rdWJlcm5ldGVzSW50ZXJmYWNlcy50cyIsImt1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHMiLCJkZXZlbG9wZXIvdHMvZGV2ZWxvcGVyRW5yaWNoZXJzLnRzIiwiZGV2ZWxvcGVyL3RzL2RldmVsb3BlckhlbHBlcnMudHMiLCJkZXZlbG9wZXIvdHMvZGV2ZWxvcGVyTmF2aWdhdGlvbi50cyIsImRldmVsb3Blci90cy9GaWxlTW9kZS50cyIsImRldmVsb3Blci90cy9kZXZlbG9wZXJQbHVnaW4udHMiLCJkZXZlbG9wZXIvdHMvZW52aXJvbm1lbnRQYW5lbC50cyIsImRldmVsb3Blci90cy9ob21lLnRzIiwiZGV2ZWxvcGVyL3RzL2plbmtpbnNKb2IudHMiLCJkZXZlbG9wZXIvdHMvamVua2luc0pvYnMudHMiLCJrdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNQbHVnaW4udHMiLCJrdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNNb2RlbC50cyIsImRldmVsb3Blci90cy9qZW5raW5zTG9nLnRzIiwiZGV2ZWxvcGVyL3RzL2plbmtpbnNNZXRyaWNzLnRzIiwiZGV2ZWxvcGVyL3RzL25hdmJhci50cyIsImRldmVsb3Blci90cy9waXBlbGluZS50cyIsImRldmVsb3Blci90cy9waXBlbGluZURpcmVjdGl2ZS50cyIsImRldmVsb3Blci90cy9waXBlbGluZXMudHMiLCJkZXZlbG9wZXIvdHMvcHJvamVjdC50cyIsImRldmVsb3Blci90cy9wcm9qZWN0U2VsZWN0b3IudHMiLCJkZXZlbG9wZXIvdHMvcHJvamVjdHMudHMiLCJkZXZlbG9wZXIvdHMvd29ya3NwYWNlLnRzIiwiZGV2ZWxvcGVyL3RzL3dvcmtzcGFjZXMudHMiLCJrdWJlcm5ldGVzL3RzL2FwcHMudHMiLCJrdWJlcm5ldGVzL3RzL2JyZWFkY3J1bWJzLnRzIiwia3ViZXJuZXRlcy90cy9idWlsZC50cyIsImt1YmVybmV0ZXMvdHMvYnVpbGRDb25maWcudHMiLCJrdWJlcm5ldGVzL3RzL2J1aWxkQ29uZmlnRWRpdC50cyIsImt1YmVybmV0ZXMvdHMvYnVpbGRDb25maWdzLnRzIiwia3ViZXJuZXRlcy90cy9idWlsZExvZ3MudHMiLCJrdWJlcm5ldGVzL3RzL2J1aWxkcy50cyIsImt1YmVybmV0ZXMvdHMvY29ubmVjdC50cyIsImt1YmVybmV0ZXMvdHMvZGF0YUluZm5Nb2RlbC50cyIsImt1YmVybmV0ZXMvdHMvZGVwbG95bWVudENvbmZpZy50cyIsImt1YmVybmV0ZXMvdHMvZGVwbG95bWVudENvbmZpZ3MudHMiLCJrdWJlcm5ldGVzL3RzL2V2ZW50cy50cyIsImt1YmVybmV0ZXMvdHMvaG9zdC50cyIsImt1YmVybmV0ZXMvdHMvdXRpbEhlbHBlcnMudHMiLCJrdWJlcm5ldGVzL3RzL2hvc3RzLnRzIiwia3ViZXJuZXRlcy90cy9pbWFnZVJlcG9zaXRvcmllcy50cyIsImt1YmVybmV0ZXMvdHMva3ViZXJuZXRlc05hdmlnYXRpb24udHMiLCJrdWJlcm5ldGVzL3RzL3NjaGVtYS50cyIsImt1YmVybmV0ZXMvdHMva3ViZXJuZXRlc1NjaGVtYS50cyIsImt1YmVybmV0ZXMvdHMva3ViZXJuZXRlc1NlcnZpY2VzLnRzIiwia3ViZXJuZXRlcy90cy9rdWJlcm5ldGVzVG9wTGV2ZWwudHMiLCJrdWJlcm5ldGVzL3RzL25hbWVzcGFjZS50cyIsImt1YmVybmV0ZXMvdHMvb3JhY2xlU3RhdHVzTW9kZWwudHMiLCJrdWJlcm5ldGVzL3RzL292ZXJ2aWV3LnRzIiwia3ViZXJuZXRlcy90cy9waXBlbGluZXMudHMiLCJrdWJlcm5ldGVzL3RzL3BvZC50cyIsImt1YmVybmV0ZXMvdHMvcG9kRWRpdC50cyIsImt1YmVybmV0ZXMvdHMvd2F0Y2hlci50cyIsImt1YmVybmV0ZXMvdHMvdGVybS50cyIsImt1YmVybmV0ZXMvdHMvcG9kTG9ncy50cyIsImt1YmVybmV0ZXMvdHMvcG9kcy50cyIsImt1YmVybmV0ZXMvdHMvcmVwbGljYXRpb25Db250cm9sbGVyLnRzIiwia3ViZXJuZXRlcy90cy9yZXBsaWNhdGlvbkNvbnRyb2xsZXJFZGl0LnRzIiwia3ViZXJuZXRlcy90cy9yZXBsaWNhdGlvbkNvbnRyb2xsZXJzLnRzIiwia3ViZXJuZXRlcy90cy9zY2hlbWFIZWxwZXJzLnRzIiwia3ViZXJuZXRlcy90cy9zZWNyZXQudHMiLCJrdWJlcm5ldGVzL3RzL3NlY3JldHMudHMiLCJrdWJlcm5ldGVzL3RzL3NlcnZpY2UudHMiLCJrdWJlcm5ldGVzL3RzL3NlcnZpY2VFZGl0LnRzIiwia3ViZXJuZXRlcy90cy9zZXJ2aWNlUmVnaXN0cnkudHMiLCJrdWJlcm5ldGVzL3RzL3NlcnZpY2VzLnRzIiwia3ViZXJuZXRlcy90cy9zaGFyZWRDb250cm9sbGVycy50cyIsImt1YmVybmV0ZXMvdHMvdGFicy50cyIsImt1YmVybmV0ZXMvdHMvdGVtcGxhdGVzLnRzIiwibmF2aWdhdGlvbi90cy9uYXZpZ2F0aW9uUGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHNEQUFzRDtBQUN0RCwrREFBK0Q7QUFDL0Qsc0RBQXNEO0FBQ3RELG1EQUFtRDtBQUNuRCwwREFBMEQ7O0FDSjFELElBQU8sVUFBVSxDQWtKaEI7QUFsSkQsV0FBTyxVQUFVLEVBQUMsQ0FBQztJQUVqQjtRQUFBO1FBRUEsQ0FBQztRQURDLHNCQUFJLHlDQUFxQjtpQkFBekIsY0FBcUMsTUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQzs7O1dBQUE7UUFDdkUsYUFBQztJQUFELENBRkEsQUFFQyxJQUFBO0lBRlksaUJBQU0sU0FFbEIsQ0FBQTtJQUVVLG9CQUFTLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQztJQThDckM7UUFBQTtRQTBCQSxDQUFDO1FBekJBLHNCQUFrQix1QkFBUztpQkFBM0IsY0FBdUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7OztXQUFBO1FBQzVELHNCQUFrQixvQkFBTTtpQkFBeEIsY0FBb0MsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7OztXQUFBO1FB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LENBQUMsQ0FBQzs0QkFDZCxNQUFNLENBQUMsV0FBVyxDQUFDO3dCQUNyQixDQUFDO3dCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQ1osQ0FBQyxDQUFBO29CQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUU7d0JBQzdCLFNBQVMsR0FBRyxDQUFDLFNBQVMsQ0FBQztvQkFDekIsQ0FBQyxDQUFDLENBQUM7b0JBQ0gsS0FBSyxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSxVQUFDLFlBQVk7d0JBQy9DLEtBQUssQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO29CQUNwQyxDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDO2FBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFSixrQkFBTyxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsRUFBRSxDQUFDLG1CQUFtQixFQUFFLFVBQUMsaUJBQWlCO1lBQ25GLE1BQU0sQ0FBQztnQkFDTCxRQUFRLEVBQUUsR0FBRztnQkFDYixLQUFLLEVBQUUsRUFBRTtnQkFDVCxRQUFRLEVBQUUsZ29CQVdUO2dCQUNELElBQUksRUFBRSxVQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSztvQkFDMUIsS0FBSyxDQUFDLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQztvQkFDdEMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQixFQUFFLFVBQUMsZ0JBQWdCO3dCQUMzRCxLQUFLLENBQUMsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7b0JBQzVDLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUM7YUFDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVKLDZDQUE2QztJQUM3QyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMscUJBQVUsQ0FBQyxDQUFDO0FBRTNDLENBQUMsRUFyS00sVUFBVSxLQUFWLFVBQVUsUUFxS2hCIiwiZmlsZSI6ImNvbXBpbGVkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uL2xpYnMvaGF3dGlvLWZvcm1zL2RlZnMuZC50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9saWJzL2hhd3Rpby1rdWJlcm5ldGVzLWFwaS9kZWZzLmQudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vbGlicy9oYXd0aW8tb2F1dGgvZGVmcy5kLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uL2xpYnMvaGF3dGlvLXVpL2RlZnMuZC50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi9saWJzL2hhd3Rpby11dGlsaXRpZXMvZGVmcy5kLnRzXCIvPlxuXG5kZWNsYXJlIHZhciBodW1hbmRhdGU7XG5kZWNsYXJlIHZhciBqc3lhbWw6YW55O1xuXG4iLCJtb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IGNsYXNzIGNvbnN0cyB7XG4gICAgZ2V0IE5BTUVTUEFDRV9TVE9SQUdFX0tFWSgpOnN0cmluZyB7IHJldHVybiBcIms4c1NlbGVjdGVkTmFtZXNwYWNlXCI7IH1cbiAgfVxuXG4gIGV4cG9ydCB2YXIgQ29uc3RhbnRzID0gbmV3IGNvbnN0cygpO1xuXHRcbiAgZXhwb3J0IGludGVyZmFjZSBBcGlMb2NhdGlvbiB7XG4gICAgcHJvdG8/OnN0cmluZztcbiAgICBob3N0UG9ydDpzdHJpbmc7XG4gICAgcHJlZml4OnN0cmluZztcbiAgfVxuICBcbiAgZXhwb3J0IGludGVyZmFjZSBBcGlMb2NhdGlvbnMge1xuICAgIG9wZW5zaGlmdD86IEFwaUxvY2F0aW9uO1xuICAgIGs4cz86IEFwaUxvY2F0aW9uO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBLdWJlcm5ldGVzQ29uZmlnIHtcbiAgICBtYXN0ZXJfdXJpPzogc3RyaW5nO1xuICAgIGFwaT86IEFwaUxvY2F0aW9ucztcbiAgICBvcGVuc2hpZnQ/OiBPcGVuU2hpZnRPQXV0aENvbmZpZztcbiAgICBnb29nbGU/OiBHb29nbGVPQXV0aENvbmZpZztcbiAgICBrZXljbG9haz86IEtleUNsb2FrQXV0aENvbmZpZztcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgT3BlblNoaWZ0T0F1dGhDb25maWcge1xuICAgIG9hdXRoX2F1dGhvcml6ZV91cmk6c3RyaW5nO1xuICAgIG9hdXRoX2NsaWVudF9pZDpzdHJpbmc7XG4gIH1cblxuICBleHBvcnQgaW50ZXJmYWNlIEdvb2dsZU9BdXRoQ29uZmlnIHtcbiAgICBhdXRoZW50aWNhdGlvblVSSTpzdHJpbmc7XG4gICAgYXV0aG9yaXphdGlvblVSSTpzdHJpbmc7XG4gICAgY2xpZW50SWQ6c3RyaW5nO1xuICAgIGNsaWVudFNlY3JldDpzdHJpbmc7XG4gICAgcmVkaXJlY3RVUkk6c3RyaW5nO1xuICAgIHNjb3BlOnN0cmluZztcbiAgICB0b2tlblVSST86c3RyaW5nO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBLZXlDbG9ha0F1dGhDb25maWcge1xuICAgIG9hdXRoX2F1dGhvcml6ZV91cmk6c3RyaW5nO1xuICAgIG9hdXRoX2NsaWVudF9pZDpzdHJpbmc7XG4gIH1cblxuICBleHBvcnQgaW50ZXJmYWNlIEt1YmVybmV0ZXNTdGF0ZSB7XG4gICAgbmFtZXNwYWNlczogQXJyYXk8c3RyaW5nPjtcbiAgICBzZWxlY3RlZE5hbWVzcGFjZTogc3RyaW5nO1xuICB9XG5cblx0ZXhwb3J0IGNsYXNzIFdhdGNoVHlwZXMge1xuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IEVORFBPSU5UUygpOnN0cmluZyB7IHJldHVybiBcImVuZHBvaW50c1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgRVZFTlRTKCk6c3RyaW5nIHsgcmV0dXJuIFwiZXZlbnRzXCI7IH1cbiAgICBwdWJsaWMgc3RhdGljIGdldCBOQU1FU1BBQ0VTKCk6c3RyaW5nIHsgcmV0dXJuIFwibmFtZXNwYWNlc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgTk9ERVMoKTpzdHJpbmcgeyByZXR1cm4gXCJub2Rlc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgUEVSU0lTVEVOVF9WT0xVTUVTKCk6c3RyaW5nIHsgcmV0dXJuIFwicGVyc2lzdGVudHZvbHVtZXNcIjsgfVxuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IFBFUlNJU1RFTlRfVk9MVU1FX0NMQUlNUygpOnN0cmluZyB7IHJldHVybiBcInBlcnNpc3RlbnR2b2x1bWVjbGFpbXNcIjsgfVxuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IFBPRFMoKTpzdHJpbmcgeyByZXR1cm4gXCJwb2RzXCI7IH1cblx0XHRwdWJsaWMgc3RhdGljIGdldCBSRVBMSUNBVElPTl9DT05UUk9MTEVSUygpOnN0cmluZyB7IHJldHVybiBcInJlcGxpY2F0aW9uY29udHJvbGxlcnNcIjsgfVxuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IFJFU09VUkNFX1FVT1RBUygpOnN0cmluZyB7IHJldHVybiBcInJlc291cmNlcXVvdGFzXCI7IH1cblx0XHRwdWJsaWMgc3RhdGljIGdldCBPQVVUSF9DTElFTlRTKCk6c3RyaW5nIHsgcmV0dXJuIFwib2F1dGhjbGllbnRzXCI7IH1cblx0XHRwdWJsaWMgc3RhdGljIGdldCBTRUNSRVRTKCk6c3RyaW5nIHsgcmV0dXJuIFwic2VjcmV0c1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgU0VSVklDRVMoKTpzdHJpbmcgeyByZXR1cm4gXCJzZXJ2aWNlc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgU0VSVklDRV9BQ0NPVU5UUygpOnN0cmluZyB7IHJldHVybiBcInNlcnZpY2VhY2NvdW50c1wiOyB9XG5cblx0XHRwdWJsaWMgc3RhdGljIGdldCBURU1QTEFURVMoKTpzdHJpbmcgeyByZXR1cm4gXCJ0ZW1wbGF0ZXNcIjsgfVxuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IFJPVVRFUygpOnN0cmluZyB7IHJldHVybiBcInJvdXRlc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgQlVJTERfQ09ORklHUygpOnN0cmluZyB7IHJldHVybiBcImJ1aWxkY29uZmlnc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgQlVJTERTKCk6c3RyaW5nIHsgcmV0dXJuIFwiYnVpbGRzXCI7IH1cblx0XHRwdWJsaWMgc3RhdGljIGdldCBERVBMT1lNRU5UX0NPTkZJR1MoKTpzdHJpbmcgeyByZXR1cm4gXCJkZXBsb3ltZW50Y29uZmlnc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgSU1BR0VfU1RSRUFNUygpOnN0cmluZyB7IHJldHVybiBcImltYWdlc3RyZWFtc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgUE9MSUNJRVMoKTpzdHJpbmcgeyByZXR1cm4gXCJwb2xpY2llc1wiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgUE9MSUNZX0JJTkRJTkdTKCk6c3RyaW5nIHsgcmV0dXJuIFwicG9saWN5YmluZGluZ3NcIjsgfVxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0IFBST0pFQ1RTKCk6c3RyaW5nIHsgcmV0dXJuIFwicHJvamVjdHNcIjsgfVxuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IFJPTEVfQklORElOR1MoKTpzdHJpbmcgeyByZXR1cm4gXCJyb2xlYmluZGluZ3NcIjsgfVxuXHRcdHB1YmxpYyBzdGF0aWMgZ2V0IFJPTEVTKCk6c3RyaW5nIHsgcmV0dXJuIFwicm9sZXNcIjsgfVxuXHR9XG5cbiAgZXhwb3J0IGNsYXNzIE5hbWVzcGFjZWRUeXBlcyB7XG4gICAgcHVibGljIHN0YXRpYyBnZXQgazhzVHlwZXMoKTpBcnJheTxzdHJpbmc+IHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIFdhdGNoVHlwZXMuRU5EUE9JTlRTLFxuICAgICAgICBXYXRjaFR5cGVzLkVWRU5UUyxcbiAgICAgICAgV2F0Y2hUeXBlcy5OT0RFUyxcbiAgICAgICAgV2F0Y2hUeXBlcy5QRVJTSVNURU5UX1ZPTFVNRVMsXG4gICAgICAgIFdhdGNoVHlwZXMuUEVSU0lTVEVOVF9WT0xVTUVfQ0xBSU1TLFxuICAgICAgICBXYXRjaFR5cGVzLlBPRFMsXG4gICAgICAgIFdhdGNoVHlwZXMuUkVQTElDQVRJT05fQ09OVFJPTExFUlMsXG4gICAgICAgIFdhdGNoVHlwZXMuUkVTT1VSQ0VfUVVPVEFTLFxuICAgICAgICBXYXRjaFR5cGVzLlBFUlNJU1RFTlRfVk9MVU1FUyxcbiAgICAgICAgV2F0Y2hUeXBlcy5TRUNSRVRTLFxuICAgICAgICBXYXRjaFR5cGVzLlNFUlZJQ0VTLFxuICAgICAgICBXYXRjaFR5cGVzLlNFUlZJQ0VfQUNDT1VOVFNcbiAgICAgIF07XG4gICAgfVxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0IG9zVHlwZXMoKTpBcnJheTxzdHJpbmc+IHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIFdhdGNoVHlwZXMuVEVNUExBVEVTLFxuICAgICAgICBXYXRjaFR5cGVzLkJVSUxEX0NPTkZJR1MsXG4gICAgICAgIFdhdGNoVHlwZXMuUk9VVEVTLFxuICAgICAgICBXYXRjaFR5cGVzLkJVSUxEUyxcbiAgICAgICAgV2F0Y2hUeXBlcy5CVUlMRF9DT05GSUdTLFxuICAgICAgICBXYXRjaFR5cGVzLkRFUExPWU1FTlRfQ09ORklHUyxcbiAgICAgICAgV2F0Y2hUeXBlcy5JTUFHRV9TVFJFQU1TLFxuICAgICAgICBXYXRjaFR5cGVzLk9BVVRIX0NMSUVOVFMsXG4gICAgICAgIFdhdGNoVHlwZXMuUE9MSUNJRVMsXG4gICAgICAgIFdhdGNoVHlwZXMuUE9MSUNZX0JJTkRJTkdTLFxuICAgICAgICBXYXRjaFR5cGVzLlBST0pFQ1RTLFxuICAgICAgICAvL1dhdGNoVHlwZXMuUk9MRV9CSU5ESU5HUyxcbiAgICAgICAgLy9XYXRjaFR5cGVzLlJPTEVTXG4gICAgICBdO1xuICAgIH1cbiAgfVxuXHRcblx0ZXhwb3J0IGNsYXNzIFdhdGNoQWN0aW9ucyB7XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgQU5ZKCk6c3RyaW5nIHsgcmV0dXJuIFwiKlwiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgQURERUQoKTpzdHJpbmcgeyByZXR1cm4gXCJBRERFRFwiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgTU9ESUZJRUQoKTpzdHJpbmcgeyByZXR1cm4gXCJNT0RJRklFRFwiOyB9XG5cdFx0cHVibGljIHN0YXRpYyBnZXQgREVMRVRFRCgpOnN0cmluZyB7IHJldHVybiBcIkRFTEVURURcIjsgfVxuXHR9XG5cdFxuXHRleHBvcnQgaW50ZXJmYWNlIE9iamVjdE1hcCB7XG5cdFx0W3VpZDpzdHJpbmddOiBhbnk7XHRcdFxuXHR9XG5cdFxuXHRleHBvcnQgaW50ZXJmYWNlIFdhdGNoZXJTZXJ2aWNlIHtcblx0XHRoYXNXZWJTb2NrZXQ6IGJvb2xlYW47XG5cdFx0YWRkQ3VzdG9taXplcjogKHR5cGU6IHN0cmluZywgY3VzdG9taXplcjogKG9iajphbnkpID0+IHZvaWQpID0+IHZvaWQ7XG5cdFx0Z2V0VHlwZXM6ICgpID0+IEFycmF5PHN0cmluZz47XG5cdFx0Z2V0TmFtZXNwYWNlOiAoKSA9PiBzdHJpbmc7XG5cdFx0c2V0TmFtZXNwYWNlOiAobmFtZXNwYWNlOiBzdHJpbmcpID0+IHZvaWQ7XG5cdFx0Z2V0T2JqZWN0czogKHR5cGU6IHN0cmluZykgPT4gQXJyYXk8YW55Pjtcblx0XHRnZXRPYmplY3RNYXA6ICh0eXBlOiBzdHJpbmcpID0+IE9iamVjdE1hcDtcblx0XHRhZGRBY3Rpb246ICh0eXBlOiBzdHJpbmcsIGFjdGlvbjogc3RyaW5nLCBmbjogKG9iajphbnkpID0+IHZvaWQpID0+IHZvaWQ7XG5cdFx0cmVnaXN0ZXJMaXN0ZW5lcjogKGZuOihvYmplY3RzOk9iamVjdE1hcCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgICByZWdpc3RlckN1c3RvbVVybEZ1bmN0aW9uOiAoa2luZDpzdHJpbmcsIHVybDooa2luZDpzdHJpbmcpID0+IHN0cmluZykgPT4gdm9pZDtcblx0fVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgS3ViZVBvZCB7XG4gICAgaWQ6c3RyaW5nO1xuICAgIG5hbWVzcGFjZTpzdHJpbmc7XG4gIH1cblxuXHRcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSW50ZXJmYWNlcy50c1wiLz5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIGNvbnRleHQgPSAnL2t1YmVybmV0ZXMnO1xuICBleHBvcnQgdmFyIGhhc2ggPSAnIycgKyBjb250ZXh0O1xuICBleHBvcnQgdmFyIGRlZmF1bHRSb3V0ZSA9IGhhc2ggKyAnL2FwcHMnO1xuICBleHBvcnQgdmFyIHBsdWdpbk5hbWUgPSAnS3ViZXJuZXRlcyc7XG4gIGV4cG9ydCB2YXIgcGx1Z2luUGF0aCA9ICdwbHVnaW5zL2t1YmVybmV0ZXMvJztcbiAgZXhwb3J0IHZhciB0ZW1wbGF0ZVBhdGggPSBwbHVnaW5QYXRoICsgJ2h0bWwvJztcbiAgZXhwb3J0IHZhciBsb2c6TG9nZ2luZy5Mb2dnZXIgPSBMb2dnZXIuZ2V0KHBsdWdpbk5hbWUpO1xuXG4gIGV4cG9ydCB2YXIga2VlcFBvbGxpbmdNb2RlbCA9IHRydWU7XG5cbiAgZXhwb3J0IHZhciBkZWZhdWx0SWNvblVybCA9IENvcmUudXJsKFwiL2ltZy9rdWJlcm5ldGVzLnN2Z1wiKTtcbiAgZXhwb3J0IHZhciBob3N0SWNvblVybCA9IENvcmUudXJsKFwiL2ltZy9ob3N0LnN2Z1wiKTtcblxuICAvLyB0aGlzIGdldHMgc2V0IGFzIGEgcHJlLWJvb3RzdHJhcCB0YXNrXG4gIGV4cG9ydCB2YXIgb3NDb25maWc6S3ViZXJuZXRlc0NvbmZpZyA9IHVuZGVmaW5lZDtcbiAgZXhwb3J0IHZhciBtYXN0ZXJVcmwgPSBcIlwiO1xuXG4gIGV4cG9ydCB2YXIgZGVmYXVsdEFwaVZlcnNpb24gPSBcInYxXCI7XG4gIGV4cG9ydCB2YXIgZGVmYXVsdE9TQXBpVmVyc2lvbiA9IFwidjFcIjtcbiAgZXhwb3J0IHZhciBsYWJlbEZpbHRlclRleHRTZXBhcmF0b3IgPSBcIixcIjtcblxuICBleHBvcnQgdmFyIGRlZmF1bHROYW1lc3BhY2UgPSBcImRlZmF1bHRcIjtcblxuICBleHBvcnQgdmFyIGFwcFN1ZmZpeCA9IFwiLmFwcFwiO1xuXG4gIC8vIGt1YmVybmV0ZXMgc2VydmljZSBuYW1lc1xuICBleHBvcnQgdmFyIGtpYmFuYVNlcnZpY2VOYW1lID0gXCJraWJhbmFcIjtcbiAgZXhwb3J0IHZhciBmYWJyaWM4Rm9yZ2VTZXJ2aWNlTmFtZSA9IFwiZmFicmljOC1mb3JnZVwiO1xuICBleHBvcnQgdmFyIGdvZ3NTZXJ2aWNlTmFtZSA9IFwiZ29nc1wiO1xuICBleHBvcnQgdmFyIGplbmtpbnNTZXJ2aWNlTmFtZSA9IFwiamVua2luc1wiO1xuICBleHBvcnQgdmFyIGFwaW1hblNlcnZpY2VOYW1lID0gJ2FwaW1hbic7XG4gIGV4cG9ydCB2YXIgaXNPcGVuU2hpZnQgPSB0cnVlO1xuXG4gIGV4cG9ydCB2YXIgc3NoU2VjcmV0RGF0YUtleXMgPSBbXCJzc2gta2V5XCIsIFwic3NoLWtleS5wdWJcIl07XG4gIGV4cG9ydCB2YXIgaHR0cHNTZWNyZXREYXRhS2V5cyA9IFtcInVzZXJuYW1lXCIsIFwicGFzc3dvcmRcIl07XG5cblxuICBleHBvcnQgZnVuY3Rpb24ga3ViZXJuZXRlc05hbWVzcGFjZVBhdGgoKSB7XG4gICAgdmFyIG5zID0gY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcbiAgICBpZiAobnMpIHtcbiAgICAgIHJldHVybiBcIi9uYW1lc3BhY2VzL1wiICsgbnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBhcGlQcmVmaXgoKSB7XG4gICAgdmFyIHByZWZpeCA9IENvcmUucGF0aEdldChvc0NvbmZpZywgWydhcGknLCAnazhzJywgJ3ByZWZpeCddKTtcbiAgICBpZiAoIXByZWZpeCkge1xuICAgICAgcHJlZml4ID0gJ2FwaSc7XG4gICAgfVxuICAgIHJldHVybiBDb3JlLnRyaW1MZWFkaW5nKHByZWZpeCwgJy8nKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBvc0FwaVByZWZpeCgpIHtcbiAgICB2YXIgcHJlZml4ID0gQ29yZS5wYXRoR2V0KG9zQ29uZmlnLCBbJ2FwaScsICdvcGVuc2hpZnQnLCAncHJlZml4J10pO1xuICAgIGlmICghcHJlZml4KSB7XG4gICAgICBwcmVmaXggPSAnb2FwaSc7XG4gICAgfVxuICAgIHZhciBhbnN3ZXIgPSBDb3JlLnRyaW1MZWFkaW5nKHByZWZpeCwgJy8nKTtcbiAgICBpZiAoIWlzT3BlblNoaWZ0KSB7XG4gICAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKGFwaVByZWZpeCgpLCBkZWZhdWx0T1NBcGlWZXJzaW9uLCBcInByb3h5XCIsIGt1YmVybmV0ZXNOYW1lc3BhY2VQYXRoKCksIFwic2VydmljZXMvdGVtcGxhdGVzXCIsIGFuc3dlcik7XG4gICAgfVxuICAgIHJldHVybiBhbnN3ZXI7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gbWFzdGVyQXBpVXJsKCkge1xuICAgIHJldHVybiBtYXN0ZXJVcmwgfHwgXCJcIjtcbiAgfVxuXG4gIC8qKiBXQVJOSU5HIC0gdGhpcyBleGNsdWRlcyB0aGUgaG9zdCBuYW1lIC0geW91IHByb2JhYmx5IHdhbnQgdG8gdXNlOiBrdWJlcm5ldGVzQXBpVXJsKCkgaW5zdGVhZCEhICovXG4gIGV4cG9ydCBmdW5jdGlvbiBrdWJlcm5ldGVzQXBpUHJlZml4KCkge1xuICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oYXBpUHJlZml4KCksIGRlZmF1bHRBcGlWZXJzaW9uKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBvcGVuc2hpZnRBcGlQcmVmaXgoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihvc0FwaVByZWZpeCgpLCBkZWZhdWx0T1NBcGlWZXJzaW9uKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBwcmVmaXhGb3JUeXBlKHR5cGU6c3RyaW5nKSB7XG4gICAgaWYgKHR5cGUgPT09IFdhdGNoVHlwZXMuTkFNRVNQQUNFUykge1xuICAgICAgcmV0dXJuIGt1YmVybmV0ZXNBcGlQcmVmaXgoKTtcbiAgICB9XG4gICAgaWYgKF8uYW55KE5hbWVzcGFjZWRUeXBlcy5rOHNUeXBlcywgKHQpID0+IHQgPT09IHR5cGUpKSB7XG4gICAgICByZXR1cm4ga3ViZXJuZXRlc0FwaVByZWZpeCgpO1xuICAgIH1cbiAgICBpZiAoXy5hbnkoTmFtZXNwYWNlZFR5cGVzLm9zVHlwZXMsICh0KSA9PiB0ID09PSB0eXBlKSkge1xuICAgICAgcmV0dXJuIG9wZW5zaGlmdEFwaVByZWZpeCgpO1xuICAgIH1cbiAgICAvLyBsZXRzIGFzc3VtZSBpdHMgYW4gT3BlblNoaWZ0IGV4dGVuc2lvbiB0eXBlXG4gICAgcmV0dXJuIG9wZW5zaGlmdEFwaVByZWZpeCgpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGt1YmVybmV0ZXNBcGlVcmwoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihtYXN0ZXJBcGlVcmwoKSwga3ViZXJuZXRlc0FwaVByZWZpeCgpKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBvcGVuc2hpZnRBcGlVcmwoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihtYXN0ZXJBcGlVcmwoKSwgb3BlbnNoaWZ0QXBpUHJlZml4KCkpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHJlc291cmNlc1VyaUZvcktpbmQodHlwZSwgbnMgPSBudWxsKSB7XG4gICAgaWYgKCFucykge1xuICAgICAgbnMgPSBjdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgIH1cbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKG1hc3RlckFwaVVybCgpLCBwcmVmaXhGb3JUeXBlKHR5cGUpLCBuYW1lc3BhY2VQYXRoRm9yS2luZCh0eXBlLCBucykpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHVyaVRlbXBsYXRlRm9yS3ViZXJuZXRlc0tpbmQodHlwZSkge1xuICAgIHZhciB1cmxUZW1wbGF0ZSA9ICcnO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBXYXRjaFR5cGVzLk5BTUVTUEFDRVM6XG4gICAgICBjYXNlIFwiTmFtZXNwYWNlc1wiOlxuICAgICAgICB1cmxUZW1wbGF0ZSA9IFVybEhlbHBlcnMuam9pbignbmFtZXNwYWNlcycpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgV2F0Y2hUeXBlcy5PQVVUSF9DTElFTlRTOlxuICAgICAgY2FzZSBcIk9BdXRoQ2xpZW50c1wiOlxuICAgICAgY2FzZSBcIk9BdXRoQ2xpZW50XCI6XG4gICAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oJ29hdXRoY2xpZW50cycpO1xuICAgICAgY2FzZSBXYXRjaFR5cGVzLlBST0pFQ1RTOlxuICAgICAgY2FzZSBcIlByb2plY3RzXCI6XG4gICAgICAgIHVybFRlbXBsYXRlID0gVXJsSGVscGVycy5qb2luKCdwcm9qZWN0cycpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHVybFRlbXBsYXRlID0gVXJsSGVscGVycy5qb2luKCduYW1lc3BhY2VzLzpuYW1lc3BhY2UnLCB0eXBlLCAnOmlkJyk7XG4gICAgfVxuICAgIHJldHVybiB1cmxUZW1wbGF0ZTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBuYW1lc3BhY2VQYXRoRm9yS2luZCh0eXBlLCBucykge1xuICAgIHZhciB1cmxUZW1wbGF0ZSA9ICcnO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBXYXRjaFR5cGVzLk5BTUVTUEFDRVM6XG4gICAgICBjYXNlIFwiTmFtZXNwYWNlc1wiOlxuICAgICAgY2FzZSBcIk5hbWVzcGFjZVwiOlxuICAgICAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKCduYW1lc3BhY2VzJyk7XG4gICAgICBjYXNlIFdhdGNoVHlwZXMuTk9ERVM6XG4gICAgICBjYXNlIFwiTm9kZXNcIjpcbiAgICAgIGNhc2UgXCJub2RlXCI6XG4gICAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oJ25vZGVzJyk7XG4gICAgICBjYXNlIFdhdGNoVHlwZXMuUFJPSkVDVFM6XG4gICAgICBjYXNlIFwiUHJvamVjdHNcIjpcbiAgICAgIGNhc2UgXCJQcm9qZWN0XCI6XG4gICAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oJ3Byb2plY3RzJyk7XG4gICAgICBjYXNlIFdhdGNoVHlwZXMuT0FVVEhfQ0xJRU5UUzpcbiAgICAgIGNhc2UgXCJPQXV0aENsaWVudHNcIjpcbiAgICAgIGNhc2UgXCJPQXV0aENsaWVudFwiOlxuICAgICAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKCdvYXV0aGNsaWVudHMnKTtcbiAgICAgIGNhc2UgV2F0Y2hUeXBlcy5QRVJTSVNURU5UX1ZPTFVNRVM6XG4gICAgICBjYXNlIFwiUGVyc2lzdGVudFZvbHVtZXNcIjpcbiAgICAgIGNhc2UgXCJQZXJzaXN0ZW50Vm9sdW1lXCI6XG4gICAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oJ3BlcnNpc3RlbnR2b2x1bWVzJyk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKCduYW1lc3BhY2VzJywgbnMsIHR5cGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZXZhbHVlIGZyb20gdGhlIGluamVjdG9yIGlmIGl0cyBhdmFpbGFibGUgb3IgbnVsbFxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGluamVjdDxUPihuYW1lKTpUIHtcbiAgICB2YXIgaW5qZWN0b3IgPSBIYXd0aW9Db3JlLmluamVjdG9yO1xuICAgIHJldHVybiBpbmplY3RvciA/IGluamVjdG9yLmdldDxUPihuYW1lKSA6IG51bGw7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVzb3VyY2UodGhpbmc6c3RyaW5nLCB1cmxUZW1wbGF0ZTpzdHJpbmcsICRyZXNvdXJjZTogbmcucmVzb3VyY2UuSVJlc291cmNlU2VydmljZSwgS3ViZXJuZXRlc01vZGVsKSB7XG4gICAgdmFyIHByZWZpeCA9IHByZWZpeEZvclR5cGUodGhpbmcpO1xuICAgIGlmICghcHJlZml4KSB7XG4gICAgICBsb2cuZGVidWcoXCJJbnZhbGlkIHR5cGUgZ2l2ZW46IFwiLCB0aGluZyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgcGFyYW1zID0gPGFueT4ge1xuICAgICAgbmFtZXNwYWNlOiBjdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZVxuICAgIH1cbiAgICBzd2l0Y2ggKHRoaW5nKSB7XG4gICAgICBjYXNlIFdhdGNoVHlwZXMuTkFNRVNQQUNFUzpcbiAgICAgIGNhc2UgV2F0Y2hUeXBlcy5PQVVUSF9DTElFTlRTOlxuICAgICAgY2FzZSBXYXRjaFR5cGVzLk5PREVTOlxuICAgICAgY2FzZSBXYXRjaFR5cGVzLlBST0pFQ1RTOlxuICAgICAgY2FzZSBXYXRjaFR5cGVzLk9BVVRIX0NMSUVOVFM6XG4gICAgICBjYXNlIFdhdGNoVHlwZXMuUEVSU0lTVEVOVF9WT0xVTUVTOlxuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuXG4gICAgdmFyIHVybCA9IFVybEhlbHBlcnMuam9pbihtYXN0ZXJBcGlVcmwoKSwgcHJlZml4LCB1cmxUZW1wbGF0ZSk7XG4gICAgbG9nLmRlYnVnKFwiVXJsIGZvciBcIiwgdGhpbmcsIFwiOiBcIiwgdXJsKTtcbiAgICB2YXIgcmVzb3VyY2UgPSAkcmVzb3VyY2UodXJsLCBudWxsLCB7XG4gICAgICBxdWVyeTogeyBtZXRob2Q6ICdHRVQnLCBpc0FycmF5OiBmYWxzZSwgcGFyYW1zOiBwYXJhbXN9LFxuICAgICAgY3JlYXRlOiB7IG1ldGhvZDogJ1BPU1QnLCBwYXJhbXM6IHBhcmFtc30sXG4gICAgICBzYXZlOiB7IG1ldGhvZDogJ1BVVCcsIHBhcmFtczogcGFyYW1zfSxcbiAgICAgIGRlbGV0ZTogeyBtZXRob2Q6ICdERUxFVEUnLCBwYXJhbXM6IF8uZXh0ZW5kKHtcbiAgICAgICAgaWQ6ICdAaWQnXG4gICAgICB9LCBwYXJhbXMpfVxuICAgIH0pO1xuICAgIHJldHVybiByZXNvdXJjZTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBpbWFnZVJlcG9zaXRvcmllc1Jlc3RVUkwoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihvcGVuc2hpZnRBcGlVcmwoKSwga3ViZXJuZXRlc05hbWVzcGFjZVBhdGgoKSwgXCIvaW1hZ2VzdHJlYW1zXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGRlcGxveW1lbnRDb25maWdzUmVzdFVSTCgpIHtcbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKG9wZW5zaGlmdEFwaVVybCgpLCBrdWJlcm5ldGVzTmFtZXNwYWNlUGF0aCgpLCBcIi9kZXBsb3ltZW50Y29uZmlnc1wiKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBidWlsZHNSZXN0VVJMKCkge1xuICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4ob3BlbnNoaWZ0QXBpVXJsKCksIGt1YmVybmV0ZXNOYW1lc3BhY2VQYXRoKCksIFwiL2J1aWxkc1wiKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBidWlsZENvbmZpZ0hvb2tzUmVzdFVSTCgpIHtcbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKG9wZW5zaGlmdEFwaVVybCgpLCBrdWJlcm5ldGVzTmFtZXNwYWNlUGF0aCgpLCBcIi9idWlsZGNvbmZpZ2hvb2tzXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQ29uZmlnc1Jlc3RVUkwoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihvcGVuc2hpZnRBcGlVcmwoKSwga3ViZXJuZXRlc05hbWVzcGFjZVBhdGgoKSwgXCIvYnVpbGRjb25maWdzXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHJvdXRlc1Jlc3RVUkwoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihvcGVuc2hpZnRBcGlVcmwoKSwga3ViZXJuZXRlc05hbWVzcGFjZVBhdGgoKSwgXCIvcm91dGVzXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHRlbXBsYXRlc1Jlc3RVUkwoKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihvcGVuc2hpZnRBcGlVcmwoKSwga3ViZXJuZXRlc05hbWVzcGFjZVBhdGgoKSwgXCIvdGVtcGxhdGVzXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldE5hbWVzcGFjZShlbnRpdHkpIHtcbiAgICB2YXIgYW5zd2VyID0gQ29yZS5wYXRoR2V0KGVudGl0eSwgW1wibWV0YWRhdGFcIiwgXCJuYW1lc3BhY2VcIl0pO1xuICAgIHJldHVybiBhbnN3ZXIgPyBhbnN3ZXIgOiBjdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldExhYmVscyhlbnRpdHkpIHtcbiAgICB2YXIgYW5zd2VyID0gQ29yZS5wYXRoR2V0KGVudGl0eSwgW1wibWV0YWRhdGFcIiwgXCJsYWJlbHNcIl0pO1xuICAgIHJldHVybiBhbnN3ZXIgPyBhbnN3ZXIgOiB7fTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBnZXROYW1lKGVudGl0eSkge1xuICAgIGlmIChhbmd1bGFyLmlzU3RyaW5nKGVudGl0eSkpIHtcbiAgICAgIHJldHVybiBlbnRpdHk7XG4gICAgfVxuICAgIHJldHVybiBDb3JlLnBhdGhHZXQoZW50aXR5LCBbXCJtZXRhZGF0YVwiLCBcIm5hbWVcIl0pIHx8IENvcmUucGF0aEdldChlbnRpdHksIFwibmFtZVwiKSB8fCBDb3JlLnBhdGhHZXQoZW50aXR5LCBcImlkXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldEtpbmQoZW50aXR5KSB7XG4gICAgcmV0dXJuIENvcmUucGF0aEdldChlbnRpdHksIFtcIm1ldGFkYXRhXCIsIFwia2luZFwiXSkgfHwgQ29yZS5wYXRoR2V0KGVudGl0eSwgXCJraW5kXCIpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldFNlbGVjdG9yKGVudGl0eSkge1xuICAgIHJldHVybiBDb3JlLnBhdGhHZXQoZW50aXR5LCBbXCJzcGVjXCIsIFwic2VsZWN0b3JcIl0pO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldEhvc3QocG9kKSB7XG4gICAgcmV0dXJuIENvcmUucGF0aEdldChwb2QsIFtcInNwZWNcIiwgXCJob3N0XCJdKSB8fCBDb3JlLnBhdGhHZXQocG9kLCBbXCJzcGVjXCIsIFwibm9kZU5hbWVcIl0pIHx8IENvcmUucGF0aEdldChwb2QsIFtcInN0YXR1c1wiLCBcImhvc3RJUFwiXSk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZ2V0U3RhdHVzKHBvZCkge1xuICAgIHJldHVybiBDb3JlLnBhdGhHZXQocG9kLCBbXCJzdGF0dXNcIiwgXCJwaGFzZVwiXSk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZ2V0UG9ydHMoc2VydmljZSkge1xuICAgIHJldHVybiBDb3JlLnBhdGhHZXQoc2VydmljZSwgW1wic3BlY1wiLCBcInBvcnRzXCJdKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBnZXRDcmVhdGlvblRpbWVzdGFtcChlbnRpdHkpIHtcbiAgICByZXR1cm4gQ29yZS5wYXRoR2V0KGVudGl0eSwgW1wibWV0YWRhdGFcIiwgXCJjcmVhdGlvblRpbWVzdGFtcFwiXSk7XG4gIH07XG5cbiAgLy92YXIgZmFicmljRG9tYWluID0gRmFicmljLmpteERvbWFpbjtcbiAgdmFyIGZhYnJpY0RvbWFpbiA9IFwiaW8uZmFicmljOFwiO1xuICBleHBvcnQgdmFyIG1iZWFuID0gZmFicmljRG9tYWluICsgXCI6dHlwZT1LdWJlcm5ldGVzXCI7XG4gIGV4cG9ydCB2YXIgbWFuYWdlck1CZWFuID0gZmFicmljRG9tYWluICsgXCI6dHlwZT1LdWJlcm5ldGVzTWFuYWdlclwiO1xuICBleHBvcnQgdmFyIGFwcFZpZXdNQmVhbiA9IGZhYnJpY0RvbWFpbiArIFwiOnR5cGU9QXBwVmlld1wiO1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBpc0t1YmVybmV0ZXMod29ya3NwYWNlPykge1xuICAgIC8vIHJldHVybiB3b3Jrc3BhY2UudHJlZUNvbnRhaW5zRG9tYWluQW5kUHJvcGVydGllcyhmYWJyaWNEb21haW4sIHt0eXBlOiBcIkt1YmVybmV0ZXNcIn0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGlzS3ViZXJuZXRlc1RlbXBsYXRlTWFuYWdlcih3b3Jrc3BhY2U/KSB7XG4gICAgLy8gcmV0dXJuIHdvcmtzcGFjZS50cmVlQ29udGFpbnNEb21haW5BbmRQcm9wZXJ0aWVzKGZhYnJpY0RvbWFpbiwge3R5cGU6IFwiS3ViZXJuZXRlc1RlbXBsYXRlTWFuYWdlclwifSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gaXNBcHBWaWV3KHdvcmtzcGFjZT8pIHtcbiAgICAvLyByZXR1cm4gd29ya3NwYWNlLnRyZWVDb250YWluc0RvbWFpbkFuZFByb3BlcnRpZXMoZmFicmljRG9tYWluLCB7dHlwZTogXCJBcHBWaWV3XCJ9KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBnZXRTdHJpcHBlZFBhdGhOYW1lKCk6c3RyaW5nIHtcbiAgICB2YXIgcGF0aE5hbWUgPSBDb3JlLnRyaW1MZWFkaW5nKCh0aGlzLiRsb2NhdGlvbi5wYXRoKCkgfHwgJy8nKSwgXCIjXCIpO1xuICAgIHBhdGhOYW1lID0gcGF0aE5hbWUucmVwbGFjZSgvXlxcLy8sICcnKTtcbiAgICByZXR1cm4gcGF0aE5hbWU7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gbGlua0NvbnRhaW5zKC4uLndvcmRzOlN0cmluZ1tdKTpib29sZWFuIHtcbiAgICB2YXIgcGF0aE5hbWUgPSB0aGlzLmdldFN0cmlwcGVkUGF0aE5hbWUoKTtcbiAgICByZXR1cm4gXy5ldmVyeSh3b3JkcywgKHdvcmQ6c3RyaW5nKSA9PiBwYXRoTmFtZS5pbmRleE9mKHdvcmQpICE9PSAwKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgZ2l2ZW4gbGluayBpcyBhY3RpdmUuIFRoZSBsaW5rIGNhbiBvbWl0IHRoZSBsZWFkaW5nICMgb3IgLyBpZiBuZWNlc3NhcnkuXG4gICAqIFRoZSBxdWVyeSBwYXJhbWV0ZXJzIG9mIHRoZSBVUkwgYXJlIGlnbm9yZWQgaW4gdGhlIGNvbXBhcmlzb24uXG4gICAqIEBtZXRob2QgaXNMaW5rQWN0aXZlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBocmVmXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgdGhlIGdpdmVuIGxpbmsgaXMgYWN0aXZlXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gaXNMaW5rQWN0aXZlKGhyZWY6c3RyaW5nKTpib29sZWFuIHtcbiAgICAvLyBsZXRzIHRyaW0gdGhlIGxlYWRpbmcgc2xhc2hcbiAgICB2YXIgcGF0aE5hbWUgPSBnZXRTdHJpcHBlZFBhdGhOYW1lKCk7XG5cbiAgICB2YXIgbGluayA9IENvcmUudHJpbUxlYWRpbmcoaHJlZiwgXCIjXCIpO1xuICAgIGxpbmsgPSBsaW5rLnJlcGxhY2UoL15cXC8vLCAnJyk7XG4gICAgLy8gc3RyaXAgYW55IHF1ZXJ5IGFyZ3VtZW50c1xuICAgIHZhciBpZHggPSBsaW5rLmluZGV4T2YoJz8nKTtcbiAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgIGxpbmsgPSBsaW5rLnN1YnN0cmluZygwLCBpZHgpO1xuICAgIH1cbiAgICBpZiAoIXBhdGhOYW1lLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGxpbmsgPT09IHBhdGhOYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gXy5zdGFydHNXaXRoKHBhdGhOYW1lLCBsaW5rKTtcbiAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gc2V0SnNvbigkc2NvcGUsIGlkLCBjb2xsZWN0aW9uKSB7XG4gICAgJHNjb3BlLmlkID0gaWQ7XG4gICAgaWYgKCEkc2NvcGUuZmV0Y2hlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWlkKSB7XG4gICAgICAkc2NvcGUuanNvbiA9ICcnO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWNvbGxlY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGl0ZW0gPSBjb2xsZWN0aW9uLmZpbmQoKGl0ZW0pID0+IHsgcmV0dXJuIGdldE5hbWUoaXRlbSkgPT09IGlkOyB9KTtcbiAgICBpZiAoaXRlbSkge1xuICAgICAgJHNjb3BlLmpzb24gPSBhbmd1bGFyLnRvSnNvbihpdGVtLCB0cnVlKTtcbiAgICAgICRzY29wZS5pdGVtID0gaXRlbTtcbiAgICB9IGVsc2Uge1xuICAgICAgJHNjb3BlLmlkID0gdW5kZWZpbmVkO1xuICAgICAgJHNjb3BlLmpzb24gPSAnJztcbiAgICAgICRzY29wZS5pdGVtID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsYWJlbHMgdGV4dCBzdHJpbmcgdXNpbmcgdGhlIDxjb2RlPmtleTE9dmFsdWUxLGtleTI9dmFsdWUyLC4uLi48L2NvZGU+IGZvcm1hdFxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGxhYmVsc1RvU3RyaW5nKGxhYmVscywgc2VwZXJhdG9yVGV4dCA9IGxhYmVsRmlsdGVyVGV4dFNlcGFyYXRvcikge1xuICAgIHZhciBhbnN3ZXIgPSBcIlwiO1xuICAgIGFuZ3VsYXIuZm9yRWFjaChsYWJlbHMsICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICB2YXIgc2VwYXJhdG9yID0gYW5zd2VyID8gc2VwZXJhdG9yVGV4dCA6IFwiXCI7XG5cbiAgICAgIGFuc3dlciArPSBzZXBhcmF0b3IgKyBrZXkgKyBcIj1cIiArIHZhbHVlO1xuICAgIH0pO1xuICAgIHJldHVybiBhbnN3ZXI7XG4gIH1cblxuXG4gIGV4cG9ydCBmdW5jdGlvbiBpbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpIHtcbiAgICAkc2NvcGUuYmFzZVVyaSA9IENvcmUudHJpbVRyYWlsaW5nKENvcmUudXJsKFwiL1wiKSB8fCBcIlwiLCBcIi9cIikgfHwgXCJcIjtcblxuICAgIHZhciBpbmplY3RvciA9IEhhd3Rpb0NvcmUuaW5qZWN0b3I7XG5cbiAgICBmdW5jdGlvbiBoYXNTZXJ2aWNlKG5hbWUpIHtcbiAgICAgIGlmIChpbmplY3Rvcikge1xuICAgICAgICB2YXIgU2VydmljZVJlZ2lzdHJ5ID0gaW5qZWN0b3IuZ2V0PGFueT4oXCJTZXJ2aWNlUmVnaXN0cnlcIik7XG4gICAgICAgIGlmIChTZXJ2aWNlUmVnaXN0cnkpIHtcbiAgICAgICAgICByZXR1cm4gU2VydmljZVJlZ2lzdHJ5Lmhhc1NlcnZpY2UobmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAkc2NvcGUuaGFzU2VydmljZUtpYmFuYSA9ICgpID0+IGhhc1NlcnZpY2Uoa2liYW5hU2VydmljZU5hbWUpO1xuICAgICRzY29wZS5oYXNTZXJ2aWNlR29ncyA9ICgpID0+IGhhc1NlcnZpY2UoZ29nc1NlcnZpY2VOYW1lKTtcbiAgICAkc2NvcGUuaGFzU2VydmljZUZvcmdlID0gKCkgPT4gaGFzU2VydmljZShmYWJyaWM4Rm9yZ2VTZXJ2aWNlTmFtZSk7XG4gICAgJHNjb3BlLmhhc1NlcnZpY2VBcGltYW4gPSAoKSA9PiBoYXNTZXJ2aWNlKGFwaW1hblNlcnZpY2VOYW1lKTtcblxuICAgICRzY29wZS52aWV3VGVtcGxhdGVzID0gKCkgPT4ge1xuICAgICAgdmFyIHJldHVyblRvID0gJGxvY2F0aW9uLnVybCgpO1xuICAgICAgJGxvY2F0aW9uLnBhdGgoJy9rdWJlcm5ldGVzL3RlbXBsYXRlcycpLnNlYXJjaCh7J3JldHVyblRvJzogcmV0dXJuVG99KTtcbiAgICB9O1xuXG4gICAgJHNjb3BlLm5hbWVzcGFjZSA9ICRyb3V0ZVBhcmFtcy5uYW1lc3BhY2UgfHwgJHNjb3BlLm5hbWVzcGFjZSB8fCBLdWJlcm5ldGVzU3RhdGUuc2VsZWN0ZWROYW1lc3BhY2UgfHwgZGVmYXVsdE5hbWVzcGFjZTtcbiAgICBpZiAoJHNjb3BlLm5hbWVzcGFjZSAhPSBLdWJlcm5ldGVzU3RhdGUuc2VsZWN0ZWROYW1lc3BhY2UpIHtcbiAgICAgIEt1YmVybmV0ZXNTdGF0ZS5zZWxlY3RlZE5hbWVzcGFjZSA9ICRzY29wZS5uYW1lc3BhY2U7XG5cbiAgICAgIC8vIGxldHMgc2hvdyBwYWdlIGlzIGdvaW5nIHRvIHJlbG9hZFxuICAgICAgaWYgKCRzY29wZS5tb2RlbCkge1xuICAgICAgICAkc2NvcGUubW9kZWwuZmV0Y2hlZCA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBLdWJlcm5ldGVzLnNldEN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCRzY29wZS5uYW1lc3BhY2UpO1xuXG4gICAgJHNjb3BlLmZvcmdlRW5hYmxlZCA9IGlzRm9yZ2VFbmFibGVkKCk7XG5cbiAgICAkc2NvcGUucHJvamVjdElkID0gJHJvdXRlUGFyYW1zW1wicHJvamVjdFwiXSB8fCAkc2NvcGUucHJvamVjdElkIHx8ICRzY29wZS5pZDtcbiAgICB2YXIgc2hvd1Byb2plY3ROYXZCYXJzID0gZmFsc2U7XG4gICAgaWYgKCRzY29wZS5wcm9qZWN0SWQgJiYgc2hvd1Byb2plY3ROYXZCYXJzKSB7XG4gICAgICAkc2NvcGUuYnJlYWRjcnVtYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0QnJlYWRjcnVtYnMoJHNjb3BlLnByb2plY3RJZCk7XG4gICAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RTdWJOYXZCYXJzKCRzY29wZS5wcm9qZWN0SWQsIG51bGwsICRzY29wZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZUVudmlyb25tZW50QnJlYWRjcnVtYnMoJHNjb3BlLCAkbG9jYXRpb24sICRyb3V0ZVBhcmFtcyk7XG4gICAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZUVudmlyb25tZW50U3ViTmF2QmFycygkc2NvcGUsICRsb2NhdGlvbiwgJHJvdXRlUGFyYW1zKTtcbiAgICB9XG5cbiAgICBpZiAoJHNjb3BlLnByb2plY3RJZCkge1xuICAgICAgJHNjb3BlLiRwcm9qZWN0TGluayA9IERldmVsb3Blci5wcm9qZWN0TGluaygkc2NvcGUucHJvamVjdElkKTtcbiAgICB9XG5cbiAgICAkc2NvcGUubGluayA9IChocmVmKSA9PiB7XG4gICAgICBpZiAoIWhyZWYpIHtcbiAgICAgICAgcmV0dXJuIGhyZWY7XG4gICAgICB9XG4gICAgICBpZiAoJHNjb3BlLiRwcm9qZWN0TGluaykge1xuICAgICAgICByZXR1cm4gRGV2ZWxvcGVyLm5hbWVzcGFjZUxpbmsoJHNjb3BlLCAkcm91dGVQYXJhbXMsIGhyZWYucmVwbGFjZSgvXlxcL2t1YmVybmV0ZXMvLCAnJykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGhyZWY7XG4gICAgICB9XG4gICAgfVxuXG4gICAgJHNjb3BlLmNvZGVNaXJyb3JPcHRpb25zID0ge1xuICAgICAgbGluZVdyYXBwaW5nIDogdHJ1ZSxcbiAgICAgIGxpbmVOdW1iZXJzOiB0cnVlLFxuICAgICAgcmVhZE9ubHk6ICdub2N1cnNvcicsXG4gICAgICBtb2RlOiB7bmFtZTogXCJqYXZhc2NyaXB0XCIsIGpzb246IHRydWV9XG4gICAgfTtcblxuICAgICRzY29wZS5yZXNpemVEaWFsb2cgPSB7XG4gICAgICBjb250cm9sbGVyOiBudWxsLFxuICAgICAgbmV3UmVwbGljYXM6IDAsXG4gICAgICBkaWFsb2c6IG5ldyBVSS5EaWFsb2coKSxcbiAgICAgIG9uT2s6ICgpID0+IHtcbiAgICAgICAgdmFyIHJlc2l6ZURpYWxvZyA9ICRzY29wZS5yZXNpemVEaWFsb2c7XG4gICAgICAgIHJlc2l6ZURpYWxvZy5kaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgcmVzaXplQ29udHJvbGxlcigkaHR0cCwgS3ViZXJuZXRlc0FwaVVSTCwgcmVzaXplRGlhbG9nLmNvbnRyb2xsZXIsIHJlc2l6ZURpYWxvZy5uZXdSZXBsaWNhcywgKCkgPT4geyBsb2cuZGVidWcoXCJ1cGRhdGVkIG51bWJlciBvZiByZXBsaWNhc1wiKTsgfSlcbiAgICAgIH0sXG4gICAgICBvcGVuOiAoY29udHJvbGxlcikgPT4ge1xuICAgICAgICB2YXIgcmVzaXplRGlhbG9nID0gJHNjb3BlLnJlc2l6ZURpYWxvZztcbiAgICAgICAgcmVzaXplRGlhbG9nLmNvbnRyb2xsZXIgPSBjb250cm9sbGVyO1xuICAgICAgICByZXNpemVEaWFsb2cubmV3UmVwbGljYXMgPSBDb3JlLnBhdGhHZXQoY29udHJvbGxlciwgW1wic3RhdHVzXCIsIFwicmVwbGljYXNcIl0pO1xuICAgICAgICByZXNpemVEaWFsb2cuZGlhbG9nLm9wZW4oKTtcblxuICAgICAgICAkdGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgJCgnI3JlcGxpY2FzJykuZm9jdXMoKTtcbiAgICAgICAgfSwgNTApO1xuICAgICAgfSxcbiAgICAgIGNsb3NlOiAoKSA9PiB7XG4gICAgICAgICRzY29wZS5yZXNpemVEaWFsb2cuZGlhbG9nLmNsb3NlKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgICRzY29wZS50cmlnZ2VyQnVpbGQgPSAoYnVpbGRDb25maWcpID0+IHtcbiAgICAgIHZhciB1cmwgPSBidWlsZENvbmZpZy4kdHJpZ2dlclVybDtcbiAgICAgIGNvbnNvbGUubG9nKFwidHJpZ2dlcmluZyBidWlsZCBhdCB1cmw6IFwiICsgdXJsKTtcbiAgICAgIGlmICh1cmwpIHtcbiAgICAgICAgLy92YXIgZGF0YSA9IHt9O1xuICAgICAgICB2YXIgZGF0YSA9IG51bGw7XG4gICAgICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6IFwiYXBwbGljYXRpb24vanNvblwiXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgbmFtZSA9IENvcmUucGF0aEdldChidWlsZENvbmZpZywgW1wibWV0YWRhdGFcIiwgXCJuYW1lXCJdKTtcbiAgICAgICAgQ29yZS5ub3RpZmljYXRpb24oJ2luZm8nLCBcIlRyaWdnZXJpbmcgYnVpbGQgXCIgKyBuYW1lKTtcbiAgICAgICAgJGh0dHAucG9zdCh1cmwsIGRhdGEsIGNvbmZpZykuXG4gICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidHJpZ2dlciB3b3JrZWQhIGdvdCBkYXRhIFwiICsgYW5ndWxhci50b0pzb24oZGF0YSwgdHJ1ZSkpO1xuICAgICAgICAgICAgLy8gVE9ETyBzaG91bGQgd2Ugc2hvdyBzb21lIGxpbmsgdG8gdGhlIGJ1aWxkXG4gICAgICAgICAgICBDb3JlLm5vdGlmaWNhdGlvbignaW5mbycsIFwiQnVpbGRpbmcgXCIgKyBuYW1lKTtcbiAgICAgICAgICB9KS5cbiAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICBDb3JlLm5vdGlmaWNhdGlvbignZXJyb3InLCBcIkZhaWxlZCB0byB0cmlnZ2VyIGJ1aWxkIGZvciBcIiArIG5hbWUgKyBcIi4gUmV0dXJuZWQgY29kZTogXCIgKyBzdGF0dXMgKyBcIiBcIiArIGRhdGEpO1xuICAgICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyB1cGRhdGUgdGhlIFVSTCBpZiB0aGUgZmlsdGVyIGlzIGNoYW5nZWRcbiAgICAkc2NvcGUuJHdhdGNoKFwidGFibGVDb25maWcuZmlsdGVyT3B0aW9ucy5maWx0ZXJUZXh0XCIsICh0ZXh0KSA9PiB7XG4gICAgICAvL3ZhciBmaWx0ZXJUZXh0ID0gS3ViZXJuZXRlcy5maW5kVmFsZU9mTGFiZWxzKHRleHQpO1xuICAgICAgJGxvY2F0aW9uLnNlYXJjaChcInFcIiwgdGV4dCk7XG4gICAgfSk7XG5cbiAgICAkc2NvcGUuJG9uKFwibGFiZWxGaWx0ZXJVcGRhdGVcIiwgKCRldmVudCwgdGV4dCkgPT4ge1xuICAgICAgdmFyIGZpbHRlck9wdGlvbnMgPSAoJHNjb3BlLnRhYmxlQ29uZmlnIHx8IHt9KS5maWx0ZXJPcHRpb25zIHx8IHt9O1xuICAgICAgdmFyIGN1cnJlbnRGaWx0ZXIgPSBmaWx0ZXJPcHRpb25zLmZpbHRlclRleHQ7XG4gICAgICBpZiAoQ29yZS5pc0JsYW5rKGN1cnJlbnRGaWx0ZXIpKSB7XG4gICAgICAgIGZpbHRlck9wdGlvbnMuZmlsdGVyVGV4dCA9IHRleHQ7XG4gICAgICB9ZWxzZXtcbiAgICAgICAgdmFyIGV4cHJlc3Npb25zID0gY3VycmVudEZpbHRlci5zcGxpdCgvXFxzKy8pO1xuICAgICAgICBpZiAoZXhwcmVzc2lvbnMuaW5kZXhPZih0ZXh0KSAhPT0gLTEpIHtcbiAgICAgICAgICAvLyBsZXRzIGV4Y2x1ZGUgdGhpcyBmaWx0ZXIgZXhwcmVzc2lvblxuICAgICAgICAgIGV4cHJlc3Npb25zID0gZXhwcmVzc2lvbnMucmVtb3ZlKHRleHQpO1xuICAgICAgICAgIGZpbHRlck9wdGlvbnMuZmlsdGVyVGV4dCA9IGV4cHJlc3Npb25zLmpvaW4oXCIgXCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZpbHRlck9wdGlvbnMuZmlsdGVyVGV4dCA9IGN1cnJlbnRGaWx0ZXIgKyBcIiBcIiArIHRleHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgICRzY29wZS5pZCA9IHVuZGVmaW5lZDtcbiAgICB9KTtcblxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBwb2RzIHRoYXQgYXJlIHJlYWR5XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gcmVhZHlQb2RDb3VudChzZXJ2aWNlKSB7XG4gICAgdmFyIGNvdW50ID0gMDtcbiAgICBhbmd1bGFyLmZvckVhY2goKHNlcnZpY2UgfHwge30pLiRwb2RzLCAocG9kKT0+IHtcbiAgICAgIGlmIChwb2QuJHJlYWR5KSB7XG4gICAgICAgIGNvdW50Kys7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvdW50O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNlcnZpY2UgbGluayBVUkwgZm9yIGVpdGhlciB0aGUgc2VydmljZSBuYW1lIG9yIHRoZSBzZXJ2aWNlIG9iamVjdFxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIHNlcnZpY2VMaW5rVXJsKHNlcnZpY2UsIGh0dHBPbmx5ID0gZmFsc2UpIHtcbiAgICBpZiAoYW5ndWxhci5pc09iamVjdChzZXJ2aWNlKSkge1xuICAgICAgdmFyIHBvcnRhbElQID0gc2VydmljZS4kaG9zdDtcbiAgICAgIC8vIGxldHMgYXNzdW1lIG5vIGN1c3RvbSBwb3J0IGZvciBub3cgZm9yIGV4dGVybmFsIHJvdXRlc1xuICAgICAgdmFyIHBvcnQgPSBudWxsO1xuICAgICAgdmFyIHByb3RvY29sID0gXCJodHRwOi8vXCI7XG4gICAgICB2YXIgc3BlYyA9IHNlcnZpY2Uuc3BlYztcbiAgICAgIGlmIChzcGVjKSB7XG4gICAgICAgIGlmICghcG9ydGFsSVApIHtcbiAgICAgICAgICBwb3J0YWxJUCA9IHNwZWMucG9ydGFsSVA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhhc0h0dHBzID0gZmFsc2U7XG4gICAgICAgIHZhciBoYXNIdHRwID0gZmFsc2U7XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChzcGVjLnBvcnRzLCAocG9ydFNwZWMpID0+IHtcbiAgICAgICAgICB2YXIgcCA9IHBvcnRTcGVjLnBvcnQ7XG4gICAgICAgICAgaWYgKHApIHtcbiAgICAgICAgICAgIGlmIChwID09PSA0NDMpIHtcbiAgICAgICAgICAgICAgaGFzSHR0cHMgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwID09PSA4MCkge1xuICAgICAgICAgICAgICBoYXNIdHRwID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcG9ydCkge1xuICAgICAgICAgICAgICBwb3J0ID0gcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWhhc0h0dHBzICYmICFoYXNIdHRwICYmIHBvcnQpIHtcbiAgICAgICAgICAvLyBsZXRzIHRyZWF0IDgwODAgYXMgaHR0cCB3aGljaCBpcyBhIGNvbW1vbiBzZXJ2aWNlIHRvIGV4cG9ydFxuICAgICAgICAgIGlmIChwb3J0ID09PSA4MDgwKSB7XG4gICAgICAgICAgICBoYXNIdHRwID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHBvcnQgPT09IDg0NDMpIHtcbiAgICAgICAgICAgIGhhc0h0dHBzID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChwb3J0YWxJUCkge1xuICAgICAgICBpZiAoaGFzSHR0cHMpIHtcbiAgICAgICAgICByZXR1cm4gXCJodHRwczovL1wiICsgcG9ydGFsSVA7XG4gICAgICAgIH0gZWxzZSBpZiAoaGFzSHR0cCkge1xuICAgICAgICAgIHJldHVybiBcImh0dHA6Ly9cIiArIHBvcnRhbElQO1xuICAgICAgICB9IGVsc2UgaWYgKCFodHRwT25seSkge1xuICAgICAgICAgIGlmIChwb3J0KSB7XG4gICAgICAgICAgICByZXR1cm4gcHJvdG9jb2wgKyBwb3J0YWxJUCArIFwiOlwiICsgcG9ydCArIFwiL1wiO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcHJvdG9jb2wgKyBwb3J0YWxJUDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHNlcnZpY2UpIHtcbiAgICAgIHZhciBzZXJ2aWNlSWQgPSBzZXJ2aWNlLnRvU3RyaW5nKCk7XG4gICAgICBpZiAoc2VydmljZUlkKSB7XG4gICAgICAgIHZhciBTZXJ2aWNlUmVnaXN0cnkgPSBnZXRTZXJ2aWNlUmVnaXN0cnkoKTtcbiAgICAgICAgaWYgKFNlcnZpY2VSZWdpc3RyeSkge1xuICAgICAgICAgIHJldHVybiBTZXJ2aWNlUmVnaXN0cnkuc2VydmljZUxpbmsoc2VydmljZUlkKSB8fCBcIlwiO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBcIlwiO1xuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdG90YWwgbnVtYmVyIG9mIGNvdW50ZXJzIGZvciB0aGUgcG9kQ291bnRlcnMgb2JqZWN0XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gcG9kQ291bnRlclRvdGFsKCRwb2RDb3VudGVycykge1xuICAgIHZhciBhbnN3ZXIgPSAwO1xuICAgIGlmICgkcG9kQ291bnRlcnMpIHtcbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChbXCJyZWFkeVwiLCBcInZhbGlkXCIsIFwid2FpdGluZ1wiLCBcImVycm9yXCJdLCAobmFtZSkgPT4ge1xuICAgICAgICB2YXIgdmFsdWUgPSAkcG9kQ291bnRlcnNbbmFtZV0gfHwgMDtcbiAgICAgICAgYW5zd2VyICs9IHZhbHVlO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBhbnN3ZXI7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gdGhlIGxpc3Qgb2YgcG9kcyBsZXRzIGl0ZXJhdGUgdGhyb3VnaCB0aGVtIGFuZCBmaW5kIGFsbCBwb2RzIG1hdGNoaW5nIHRoZSBzZWxlY3RvclxuICAgKiBhbmQgcmV0dXJuIGNvdW50ZXJzIGJhc2VkIG9uIHRoZSBzdGF0dXMgb2YgdGhlIHBvZFxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVBvZENvdW50ZXJzKHNlbGVjdG9yLCBwb2RzLCBvdXRwdXRQb2RzID0gW10sIHBvZExpbmtRdWVyeSA9IG51bGwsIHBvZExpbmtVcmwgPSBudWxsKSB7XG4gICAgaWYgKCFwb2RMaW5rVXJsKSB7XG4gICAgICBwb2RMaW5rVXJsID0gXCIva3ViZXJuZXRlcy9wb2RzXCI7XG4gICAgfVxuICAgIHZhciBmaWx0ZXJGbjtcbiAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKHNlbGVjdG9yKSkge1xuICAgICAgZmlsdGVyRm4gPSBzZWxlY3RvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgZmlsdGVyRm4gPSAocG9kKSA9PiBzZWxlY3Rvck1hdGNoZXMoc2VsZWN0b3IsIGdldExhYmVscyhwb2QpKTtcbiAgICB9XG4gICAgdmFyIGFuc3dlciA9IHtcbiAgICAgIHBvZHNMaW5rOiBcIlwiLFxuICAgICAgcmVhZHk6IDAsXG4gICAgICB2YWxpZDogMCxcbiAgICAgIHdhaXRpbmc6IDAsXG4gICAgICBlcnJvcjogMFxuICAgIH07XG4gICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICBpZiAoIXBvZExpbmtRdWVyeSkge1xuICAgICAgICBwb2RMaW5rUXVlcnkgPSBLdWJlcm5ldGVzLmxhYmVsc1RvU3RyaW5nKHNlbGVjdG9yLCBcIiBcIik7XG4gICAgICB9XG4gICAgICBhbnN3ZXIucG9kc0xpbmsgPSBwb2RMaW5rVXJsICsgXCI/cT1cIiArIGVuY29kZVVSSUNvbXBvbmVudChwb2RMaW5rUXVlcnkpO1xuICAgICAgYW5ndWxhci5mb3JFYWNoKHBvZHMsIHBvZCA9PiB7XG4gICAgICAgIGlmIChmaWx0ZXJGbihwb2QpKSB7XG4gICAgICAgICAgb3V0cHV0UG9kcy5wdXNoKHBvZCk7XG4gICAgICAgICAgdmFyIHN0YXR1cyA9IGdldFN0YXR1cyhwb2QpO1xuICAgICAgICAgIGlmIChzdGF0dXMpIHtcbiAgICAgICAgICAgIHZhciBsb3dlciA9IHN0YXR1cy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgaWYgKGxvd2VyLnN0YXJ0c1dpdGgoXCJydW5cIikpIHtcbiAgICAgICAgICAgICAgaWYgKGlzUmVhZHkocG9kKSkge1xuICAgICAgICAgICAgICAgIGFuc3dlci5yZWFkeSArPSAxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuc3dlci52YWxpZCArPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxvd2VyLnN0YXJ0c1dpdGgoXCJ3YWl0XCIpIHx8IGxvd2VyLnN0YXJ0c1dpdGgoXCJwZW5kXCIpKSB7XG4gICAgICAgICAgICAgIGFuc3dlci53YWl0aW5nICs9IDE7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxvd2VyLnN0YXJ0c1dpdGgoXCJ0ZXJtXCIpIHx8IGxvd2VyLnN0YXJ0c1dpdGgoXCJlcnJvclwiKSB8fCBsb3dlci5zdGFydHNXaXRoKFwiZmFpbFwiKSkge1xuICAgICAgICAgICAgICBhbnN3ZXIuZXJyb3IgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYW5zd2VyLmVycm9yICs9IDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFuc3dlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyB0aGUgZ2l2ZW4ganNvbiBpbnRvIGFuIGFycmF5IG9mIGl0ZW1zLiBJZiB0aGUganNvbiBjb250YWlucyBhIG5lc3RlZCBzZXQgb2YgaXRlbXMgdGhlbiB0aGF0IGlzIHNvcnRlZDsgc28gdGhhdCBzZXJ2aWNlc1xuICAgKiBhcmUgcHJvY2Vzc2VkIGZpcnN0OyB0aGVuIHR1cm5lZCBpbnRvIGFuIGFycmF5LiBPdGhlcndpc2UgdGhlIGpzb24gaXMgcHV0IGludG8gYW4gYXJyYXkgc28gaXQgY2FuIGJlIHByb2Nlc3NlZCBwb2x5bW9ycGhpY2FsbHlcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBjb252ZXJ0S3ViZXJuZXRlc0pzb25Ub0l0ZW1zKGpzb24pIHtcbiAgICB2YXIgaXRlbXMgPSBqc29uLml0ZW1zO1xuICAgIGlmIChhbmd1bGFyLmlzQXJyYXkoaXRlbXMpKSB7XG4gICAgICAvLyBUT0RPIHdlIGNvdWxkIGNoZWNrIGZvciBMaXN0IG9yIENvbmZpZyB0eXBlcyBoZXJlIGFuZCB3YXJuIGlmIG5vdFxuXG4gICAgICAvLyBzb3J0IHRoZSBzZXJ2aWNlcyBmaXJzdFxuICAgICAgdmFyIGFuc3dlciA9IFtdO1xuICAgICAgaXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICBpZiAoaXRlbS5raW5kID09PSBcIlNlcnZpY2VcIikge1xuICAgICAgICAgIGFuc3dlci5wdXNoKGl0ZW0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGl0ZW1zLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgaWYgKGl0ZW0ua2luZCAhPT0gXCJTZXJ2aWNlXCIpIHtcbiAgICAgICAgICBhbnN3ZXIucHVzaChpdGVtKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gYW5zd2VyO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW2pzb25dO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBpc1YxYmV0YTFPcjIoKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRBcGlWZXJzaW9uID09PSBcInYxYmV0YTFcIiB8fCBkZWZhdWx0QXBpVmVyc2lvbiA9PT0gXCJ2MWJldGEyXCI7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpbmsgdG8gdGhlIGRldGFpbCBwYWdlIGZvciB0aGUgZ2l2ZW4gZW50aXR5XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gZW50aXR5UGFnZUxpbmsob2JqKSB7XG4gICAgaWYgKG9iaikge1xuICAgICAgZnVuY3Rpb24gZ2V0TGluayhlbnRpdHkpIHtcbiAgICAgICAgdmFyIHZpZXdMaW5rID0gZW50aXR5W1wiJHZpZXdMaW5rXCJdO1xuICAgICAgICBpZiAodmlld0xpbmspIHtcbiAgICAgICAgICByZXR1cm4gdmlld0xpbms7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGlkID0gZ2V0TmFtZShlbnRpdHkpO1xuICAgICAgICB2YXIga2luZCA9IGdldEtpbmQoZW50aXR5KTtcbiAgICAgICAgaWYgKGtpbmQgJiYgaWQpIHtcbiAgICAgICAgICB2YXIgcGF0aCA9IGtpbmQuc3Vic3RyaW5nKDAsIDEpLnRvTG93ZXJDYXNlKCkgKyBraW5kLnN1YnN0cmluZygxKSArIFwic1wiO1xuICAgICAgICAgIHZhciBuYW1lc3BhY2UgPSBnZXROYW1lc3BhY2UoZW50aXR5KTtcbiAgICAgICAgICBpZiAobmFtZXNwYWNlICYmICFpc0lnbm9yZU5hbWVzcGFjZUtpbmQoa2luZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBDb3JlLnVybChVcmxIZWxwZXJzLmpvaW4oJy9rdWJlcm5ldGVzL25hbWVzcGFjZScsIG5hbWVzcGFjZSwgcGF0aCwgaWQpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIENvcmUudXJsKFVybEhlbHBlcnMuam9pbignL2t1YmVybmV0ZXMnLCBwYXRoLCBpZCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIGJhc2VMaW5rID0gZ2V0TGluayhvYmopO1xuICAgICAgaWYgKCFIYXd0aW9Db3JlLmluamVjdG9yIHx8ICFiYXNlTGluaykge1xuICAgICAgICByZXR1cm4gYmFzZUxpbms7XG4gICAgICB9XG4gICAgICB2YXIgJHJvdXRlUGFyYW1zID0gSGF3dGlvQ29yZS5pbmplY3Rvci5nZXQ8bmcucm91dGUuSVJvdXRlUGFyYW1zU2VydmljZT4oJyRyb3V0ZVBhcmFtcycpO1xuICAgICAgdmFyIHByb2plY3RJZCA9ICRyb3V0ZVBhcmFtc1sncHJvamVjdCddIHx8ICRyb3V0ZVBhcmFtc1sncHJvamVjdCddO1xuICAgICAgaWYgKCFwcm9qZWN0SWQpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VMaW5rO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihEZXZlbG9wZXIucHJvamVjdExpbmsocHJvamVjdElkKSwgYmFzZUxpbmsucmVwbGFjZSgvXlxcL2t1YmVybmV0ZXNcXC8vLCAnJykpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHJlc291cmNlS2luZFRvVXJpUGF0aChraW5kKSB7XG4gICAgdmFyIGtpbmRQYXRoID0ga2luZC50b0xvd2VyQ2FzZSgpICsgXCJzXCI7XG4gICAgaWYgKGtpbmRQYXRoID09PSBcInJlcGxpY2F0aW9uQ29udHJvbGxlcnNcIiAmJiAhaXNWMWJldGExT3IyKCkpIHtcbiAgICAgIGtpbmRQYXRoID0gXCJyZXBsaWNhdGlvbmNvbnRyb2xsZXJzXCI7XG4gICAgfVxuICAgIHJldHVybiBraW5kUGF0aDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzSWdub3JlTmFtZXNwYWNlS2luZChraW5kKSB7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwiSG9zdFwiIHx8IGtpbmQgPT09IFwiTWluaW9uXCI7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgcm9vdCBVUkwgZm9yIHRoZSBraW5kXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24ga3ViZXJuZXRlc1VybEZvcktpbmQoS3ViZXJuZXRlc0FwaVVSTCwga2luZCwgbmFtZXNwYWNlID0gbnVsbCwgcGF0aCA9IG51bGwpIHtcbiAgICB2YXIgcGF0aFNlZ21lbnQgPSBcIlwiO1xuICAgIGlmIChwYXRoKSB7XG4gICAgICBwYXRoU2VnbWVudCA9IFwiL1wiICsgQ29yZS50cmltTGVhZGluZyhwYXRoLCBcIi9cIik7XG4gICAgfVxuICAgIHZhciBraW5kUGF0aCA9IHJlc291cmNlS2luZFRvVXJpUGF0aChraW5kKTtcbiAgICB2YXIgaWdub3JlTmFtZXNwYWNlID0gaXNJZ25vcmVOYW1lc3BhY2VLaW5kKGtpbmQpO1xuICAgIGlmIChpc1YxYmV0YTFPcjIoKSB8fCBpZ25vcmVOYW1lc3BhY2UpIHtcbiAgICAgIHZhciBwb3N0Zml4ID0gXCJcIjtcbiAgICAgIGlmIChuYW1lc3BhY2UgJiYgIWlnbm9yZU5hbWVzcGFjZSkge1xuICAgICAgICBwb3N0Zml4ID0gXCI/bmFtZXNwYWNlPVwiICsgbmFtZXNwYWNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihLdWJlcm5ldGVzQXBpVVJMLCBraW5kUGF0aCwgcGF0aFNlZ21lbnQsIHBvc3RmaXgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKEt1YmVybmV0ZXNBcGlVUkwsIFwiL25hbWVzcGFjZXMvXCIsIG5hbWVzcGFjZSAsIGtpbmRQYXRoLCBwYXRoU2VnbWVudCk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBiYXNlIFVSTCBmb3IgdGhlIGtpbmQgb2Yga3ViZXJuZXRlcyByZXNvdXJjZSBvciBudWxsIGlmIGl0IGNhbm5vdCBiZSBmb3VuZFxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGt1YmVybmV0ZXNVcmxGb3JJdGVtS2luZChLdWJlcm5ldGVzQXBpVVJMLCBqc29uKSB7XG4gICAgdmFyIGtpbmQgPSBqc29uLmtpbmQ7XG4gICAgaWYgKGtpbmQpIHtcbiAgICAgIHJldHVybiBrdWJlcm5ldGVzVXJsRm9yS2luZChLdWJlcm5ldGVzQXBpVVJMLCBraW5kLCBqc29uLm5hbWVzcGFjZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy53YXJuKFwiSWdub3JpbmcgbWlzc2luZyBraW5kIFwiICsga2luZCArIFwiIGZvciBrdWJlcm5ldGVzIGpzb246IFwiICsgYW5ndWxhci50b0pzb24oanNvbikpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGt1YmVybmV0ZXNQcm94eVVybEZvclNlcnZpY2UoS3ViZXJuZXRlc0FwaVVSTCwgc2VydmljZSwgcGF0aCA9IG51bGwpIHtcbiAgICB2YXIgcGF0aFNlZ21lbnQgPSBcIlwiO1xuICAgIGlmIChwYXRoKSB7XG4gICAgICBwYXRoU2VnbWVudCA9IFwiL1wiICsgQ29yZS50cmltTGVhZGluZyhwYXRoLCBcIi9cIik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhdGhTZWdtZW50ID0gXCIvXCI7XG4gICAgfVxuICAgIHZhciBuYW1lc3BhY2UgPSBnZXROYW1lc3BhY2Uoc2VydmljZSk7XG4gICAgaWYgKGlzVjFiZXRhMU9yMigpKSB7XG4gICAgICB2YXIgcG9zdGZpeCA9IFwiP25hbWVzcGFjZT1cIiArIG5hbWVzcGFjZTtcbiAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oS3ViZXJuZXRlc0FwaVVSTCwgXCIvcHJveHlcIiwgIGt1YmVybmV0ZXNOYW1lc3BhY2VQYXRoKCksIFwiL3NlcnZpY2VzL1wiICsgZ2V0TmFtZShzZXJ2aWNlKSArIHBhdGhTZWdtZW50ICsgcG9zdGZpeCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oS3ViZXJuZXRlc0FwaVVSTCwgXCIvcHJveHkvbmFtZXNwYWNlcy9cIiwgbmFtZXNwYWNlLCBcIi9zZXJ2aWNlcy9cIiArIGdldE5hbWUoc2VydmljZSkgKyBwYXRoU2VnbWVudCk7XG4gICAgfVxuICB9XG5cblxuICBleHBvcnQgZnVuY3Rpb24ga3ViZXJuZXRlc1Byb3h5VXJsRm9yU2VydmljZUN1cnJlbnROYW1lc3BhY2Uoc2VydmljZSwgcGF0aCA9IG51bGwpIHtcbiAgICB2YXIgYXBpUHJlZml4ID0gVXJsSGVscGVycy5qb2luKGt1YmVybmV0ZXNBcGlVcmwoKSk7XG4gICAgcmV0dXJuIGt1YmVybmV0ZXNQcm94eVVybEZvclNlcnZpY2UoYXBpUHJlZml4LCBzZXJ2aWNlLCBwYXRoKTtcblxuICB9XG4gIGV4cG9ydCBmdW5jdGlvbiBidWlsZENvbmZpZ1Jlc3RVcmwoaWQpIHtcbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKGJ1aWxkQ29uZmlnc1Jlc3RVUkwoKSwgaWQpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGRlcGxveW1lbnRDb25maWdSZXN0VXJsKGlkKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihkZXBsb3ltZW50Q29uZmlnc1Jlc3RVUkwoKSwgaWQpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGltYWdlUmVwb3NpdG9yeVJlc3RVcmwoaWQpIHtcbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKGltYWdlUmVwb3NpdG9yaWVzUmVzdFVSTCgpLCBpZCk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gYnVpbGRSZXN0VXJsKGlkKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihidWlsZHNSZXN0VVJMKCksIGlkKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBidWlsZExvZ3NSZXN0VXJsKGlkKSB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihidWlsZHNSZXN0VVJMKCksIGlkLCBcImxvZ1wiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHRoZSBnaXZlbiBhcHBsaWNhdGlvbiBKU09OXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gcnVuQXBwKCRsb2NhdGlvbiwgJHNjb3BlLCAkaHR0cCwgS3ViZXJuZXRlc0FwaVVSTCwganNvbiwgbmFtZSA9IFwiQXBwXCIsIG9uU3VjY2Vzc0ZuID0gbnVsbCwgbmFtZXNwYWNlID0gbnVsbCwgb25Db21wbGV0ZUZuID0gbnVsbCkge1xuICAgIGlmIChqc29uKSB7XG4gICAgICBpZiAoYW5ndWxhci5pc1N0cmluZyhqc29uKSkge1xuICAgICAgICBqc29uID0gYW5ndWxhci5mcm9tSnNvbihqc29uKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSBuYW1lIHx8IFwiQXBwXCI7XG4gICAgICB2YXIgcG9zdGZpeCA9IG5hbWVzcGFjZSA/IFwiIGluIG5hbWVzcGFjZSBcIiArIG5hbWVzcGFjZSA6IFwiXCI7XG4gICAgICBDb3JlLm5vdGlmaWNhdGlvbignaW5mbycsIFwiUnVubmluZyBcIiArIG5hbWUgKyBwb3N0Zml4KTtcblxuICAgICAgdmFyIGl0ZW1zID0gY29udmVydEt1YmVybmV0ZXNKc29uVG9JdGVtcyhqc29uKTtcbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChpdGVtcywgKGl0ZW0pID0+IHtcbiAgICAgICAgdmFyIHVybCA9IGt1YmVybmV0ZXNVcmxGb3JJdGVtS2luZChLdWJlcm5ldGVzQXBpVVJMLCBpdGVtKTtcbiAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgICRodHRwLnBvc3QodXJsLCBpdGVtKS5cbiAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkdvdCBzdGF0dXM6IFwiICsgc3RhdHVzICsgXCIgb24gdXJsOiBcIiArIHVybCArIFwiIGRhdGE6IFwiICsgZGF0YSArIFwiIGFmdGVyIHBvc3Rpbmc6IFwiICsgYW5ndWxhci50b0pzb24oaXRlbSkpO1xuICAgICAgICAgICAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKG9uQ29tcGxldGVGbikpIHtcbiAgICAgICAgICAgICAgICBvbkNvbXBsZXRlRm4oKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgfSkuXG4gICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG51bGw7XG4gICAgICAgICAgICBpZiAoYW5ndWxhci5pc09iamVjdChkYXRhKSkge1xuICAgICAgICAgICAgICBtZXNzYWdlID0gZGF0YS5tZXNzYWdlO1xuICAgICAgICAgICAgICB2YXIgcmVhc29uID0gZGF0YS5yZWFzb247XG4gICAgICAgICAgICAgIGlmIChyZWFzb24gPT09IFwiQWxyZWFkeUV4aXN0c1wiKSB7XG4gICAgICAgICAgICAgICAgLy8gbGV0cyBpZ25vcmUgZHVwbGljYXRlc1xuICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcImVudGl0eSBhbHJlYWR5IGV4aXN0cyBhdCBcIiArIHVybCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSA9IFwiRmFpbGVkIHRvIFBPU1QgdG8gXCIgKyB1cmwgKyBcIiBnb3Qgc3RhdHVzOiBcIiArIHN0YXR1cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIHNhdmUgXCIgKyB1cmwgKyBcIiBzdGF0dXM6IFwiICsgc3RhdHVzICsgXCIgcmVzcG9uc2U6IFwiICsgYW5ndWxhci50b0pzb24oZGF0YSwgdHJ1ZSkpO1xuICAgICAgICAgICAgQ29yZS5ub3RpZmljYXRpb24oJ2Vycm9yJywgbWVzc2FnZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIHBvZCBpcyBydW5uaW5nXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gaXNSdW5uaW5nKHBvZEN1cnJlbnRTdGF0ZSkge1xuICAgIHZhciBzdGF0dXMgPSAocG9kQ3VycmVudFN0YXRlIHx8IHt9KS5waGFzZTtcbiAgICBpZiAoc3RhdHVzKSB7XG4gICAgICB2YXIgbG93ZXIgPSBzdGF0dXMudG9Mb3dlckNhc2UoKTtcbiAgICAgIHJldHVybiBsb3dlci5zdGFydHNXaXRoKFwicnVuXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgbGFiZWxzIG9iamVjdCBoYXMgYWxsIG9mIHRoZSBrZXkvdmFsdWUgcGFpcnMgZnJvbSB0aGUgc2VsZWN0b3JcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBzZWxlY3Rvck1hdGNoZXMoc2VsZWN0b3IsIGxhYmVscykge1xuICAgIGlmIChhbmd1bGFyLmlzT2JqZWN0KGxhYmVscykpIHtcbiAgICAgIHZhciBhbnN3ZXIgPSB0cnVlO1xuICAgICAgdmFyIGNvdW50ID0gMDtcbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChzZWxlY3RvciwgKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgY291bnQrKztcbiAgICAgICAgaWYgKGFuc3dlciAmJiBsYWJlbHNba2V5XSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICBhbnN3ZXIgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gYW5zd2VyICYmIGNvdW50ID4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzZXJ2aWNlIHJlZ2lzdHJ5XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gZ2V0U2VydmljZVJlZ2lzdHJ5KCkge1xuICAgIHZhciBpbmplY3RvciA9IEhhd3Rpb0NvcmUuaW5qZWN0b3I7XG4gICAgcmV0dXJuIGluamVjdG9yID8gaW5qZWN0b3IuZ2V0PGFueT4oXCJTZXJ2aWNlUmVnaXN0cnlcIikgOiBudWxsO1xuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpbmsgdG8gdGhlIGtpYmFuYSBsb2dzIHdlYiBhcHBsaWNhdGlvblxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGtpYmFuYUxvZ3NMaW5rKFNlcnZpY2VSZWdpc3RyeSkge1xuICAgIHZhciBsaW5rID0gU2VydmljZVJlZ2lzdHJ5LnNlcnZpY2VMaW5rKGtpYmFuYVNlcnZpY2VOYW1lKTtcbiAgICBpZiAobGluaykge1xuICAgICAgaWYgKCFsaW5rLmVuZHNXaXRoKFwiL1wiKSkge1xuICAgICAgICBsaW5rICs9IFwiL1wiO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxpbmsgKyBcIiMvZGFzaGJvYXJkL0ZhYnJpYzhcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIG9wZW5Mb2dzRm9yUG9kcyhTZXJ2aWNlUmVnaXN0cnksICR3aW5kb3csIG5hbWVzcGFjZSwgcG9kcykge1xuICAgIHZhciBsaW5rID0ga2liYW5hTG9nc0xpbmsoU2VydmljZVJlZ2lzdHJ5KTtcbiAgICBpZiAobGluaykge1xuICAgICAgdmFyIHF1ZXJ5ID0gXCJcIjtcbiAgICAgIHZhciBjb3VudCA9IDA7XG4gICAgICBhbmd1bGFyLmZvckVhY2gocG9kcywgKGl0ZW0pID0+IHtcbiAgICAgICAgdmFyIGlkID0gZ2V0TmFtZShpdGVtKTtcbiAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgdmFyIHNwYWNlID0gcXVlcnkgPyBcIiBPUiBcIiA6IFwiXCI7XG4gICAgICAgICAgY291bnQrKztcbiAgICAgICAgICBxdWVyeSArPSBzcGFjZSArICdcIicgKyBpZCArICdcIic7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgaWYgKHF1ZXJ5KSB7XG4gICAgICAgIGlmIChjb3VudCA+IDEpIHtcbiAgICAgICAgICBxdWVyeSA9IFwiKFwiICsgcXVlcnkgKyBcIilcIjtcbiAgICAgICAgfVxuICAgICAgICBxdWVyeSA9ICdrdWJlcm5ldGVzLm5hbWVzcGFjZV9uYW1lOlwiJyArIG5hbWVzcGFjZSArICdcIiBBTkQga3ViZXJuZXRlcy5wb2RfbmFtZTonICsgcXVlcnk7XG4gICAgICAgIGxpbmsgKz0gXCI/X2E9KHF1ZXJ5OihxdWVyeV9zdHJpbmc6KHF1ZXJ5OidcIiArIHF1ZXJ5ICsgXCInKSkpXCI7XG4gICAgICAgIHZhciBuZXdXaW5kb3cgPSAkd2luZG93Lm9wZW4obGluaywgXCJ2aWV3TG9nc1wiKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gcmVzaXplQ29udHJvbGxlcigkaHR0cCwgS3ViZXJuZXRlc0FwaVVSTCwgcmVwbGljYXRpb25Db250cm9sbGVyLCBuZXdSZXBsaWNhcywgb25Db21wbGV0ZUZuID0gbnVsbCkge1xuICAgIHZhciBpZCA9IGdldE5hbWUocmVwbGljYXRpb25Db250cm9sbGVyKTtcbiAgICB2YXIgbmFtZXNwYWNlID0gZ2V0TmFtZXNwYWNlKHJlcGxpY2F0aW9uQ29udHJvbGxlcikgfHwgXCJcIjtcbiAgICB2YXIgdXJsID0ga3ViZXJuZXRlc1VybEZvcktpbmQoS3ViZXJuZXRlc0FwaVVSTCwgXCJSZXBsaWNhdGlvbkNvbnRyb2xsZXJcIiwgbmFtZXNwYWNlLCBpZCk7XG4gICAgJGh0dHAuZ2V0KHVybCkuXG4gICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgIHZhciBkZXNpcmVkU3RhdGUgPSBkYXRhLnNwZWM7XG4gICAgICAgICAgaWYgKCFkZXNpcmVkU3RhdGUpIHtcbiAgICAgICAgICAgIGRlc2lyZWRTdGF0ZSA9IHt9O1xuICAgICAgICAgICAgZGF0YS5zcGVjID0gZGVzaXJlZFN0YXRlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZXNpcmVkU3RhdGUucmVwbGljYXMgPSBuZXdSZXBsaWNhcztcbiAgICAgICAgICAkaHR0cC5wdXQodXJsLCBkYXRhKS5cbiAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcInVwZGF0ZWQgY29udHJvbGxlciBcIiArIHVybCk7XG4gICAgICAgICAgICAgIGlmIChhbmd1bGFyLmlzRnVuY3Rpb24ob25Db21wbGV0ZUZuKSkge1xuICAgICAgICAgICAgICAgIG9uQ29tcGxldGVGbigpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5cbiAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIHNhdmUgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pLlxuICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBzdGF0dXNUZXh0VG9Dc3NDbGFzcyh0ZXh0LCByZWFkeSA9IGZhbHNlKSB7XG4gICAgaWYgKHRleHQpIHtcbiAgICAgIHZhciBsb3dlciA9IHRleHQudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChsb3dlci5zdGFydHNXaXRoKFwicnVuXCIpIHx8IGxvd2VyLnN0YXJ0c1dpdGgoXCJva1wiKSkge1xuICAgICAgICBpZiAoIXJlYWR5KSB7XG4gICAgICAgICAgcmV0dXJuIFwiZmEgZmEtc3Bpbm5lciBmYS1zcGluIGdyZWVuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdmYSBmYS1wbGF5LWNpcmNsZSBncmVlbic7XG4gICAgICB9IGVsc2UgaWYgKGxvd2VyLnN0YXJ0c1dpdGgoXCJ3YWl0XCIpIHx8IGxvd2VyLnN0YXJ0c1dpdGgoXCJwZW5kXCIpKSB7XG4gICAgICAgIHJldHVybiAnZmEgZmEtZG93bmxvYWQnO1xuICAgICAgfSBlbHNlIGlmIChsb3dlci5zdGFydHNXaXRoKFwidGVybVwiKSB8fCBsb3dlci5zdGFydHNXaXRoKFwiZXJyb3JcIikgfHwgbG93ZXIuc3RhcnRzV2l0aChcImZhaWxcIikpIHtcbiAgICAgICAgcmV0dXJuICdmYSBmYS1vZmYgb3JhbmdlJztcbiAgICAgIH0gZWxzZSBpZiAobG93ZXIuc3RhcnRzV2l0aChcInN1Y2NlZWRlZFwiKSkge1xuICAgICAgICByZXR1cm4gJ2ZhIGZhLWNoZWNrLWNpcmNsZS1vIGdyZWVuJztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICdmYSBmYS1xdWVzdGlvbiByZWQnO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHBvZFN0YXR1cyhwb2QpIHtcbiAgICByZXR1cm4gZ2V0U3RhdHVzKHBvZCk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gaXNSZWFkeShwb2QpIHtcbiAgICB2YXIgc3RhdHVzID0gcG9kLnN0YXR1cyB8fCB7fTtcbiAgICB2YXIgYW5zd2VyID0gZmFsc2U7XG4gICAgYW5ndWxhci5mb3JFYWNoKHN0YXR1cy5jb25kaXRpb25zLCAoY29uZGl0aW9uKSA9PiB7XG4gICAgICB2YXIgdCA9IGNvbmRpdGlvbi50eXBlO1xuICAgICAgaWYgKHQgJiYgdCA9PT0gXCJSZWFkeVwiKSB7XG4gICAgICAgIHZhciBzdGF0dXMgPSBjb25kaXRpb24uc3RhdHVzO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBcIlRydWVcIikge1xuICAgICAgICAgIGFuc3dlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwcFZpZXdQb2RDb3VudGVycyhhcHBWaWV3KSB7XG4gICAgdmFyIGFycmF5ID0gW107XG4gICAgdmFyIG1hcCA9IHt9O1xuICAgIHZhciBwb2RzID0gYXBwVmlldy5wb2RzO1xuICAgIHZhciBsb3dlc3REYXRlID0gbnVsbDtcbiAgICBhbmd1bGFyLmZvckVhY2gocG9kcywgcG9kID0+IHtcbiAgICAgIHZhciBzZWxlY3RvciA9IGdldExhYmVscyhwb2QpO1xuICAgICAgdmFyIHNlbGVjdG9yVGV4dCA9IEt1YmVybmV0ZXMubGFiZWxzVG9TdHJpbmcoc2VsZWN0b3IsIFwiIFwiKTtcbiAgICAgIHZhciBhbnN3ZXIgPSBtYXBbc2VsZWN0b3JdO1xuICAgICAgaWYgKCFhbnN3ZXIpIHtcbiAgICAgICAgYW5zd2VyID0ge1xuICAgICAgICAgIGxhYmVsVGV4dDogc2VsZWN0b3JUZXh0LFxuICAgICAgICAgIHBvZHNMaW5rOiBVcmxIZWxwZXJzLmpvaW4oXCIva3ViZXJuZXRlcy9uYW1lc3BhY2UvXCIsIHBvZC5tZXRhZGF0YS5uYW1lc3BhY2UsIFwicG9kcz9xPVwiICsgZW5jb2RlVVJJQ29tcG9uZW50KHNlbGVjdG9yVGV4dCkpLFxuICAgICAgICAgIHZhbGlkOiAwLFxuICAgICAgICAgIHdhaXRpbmc6IDAsXG4gICAgICAgICAgZXJyb3I6IDBcbiAgICAgICAgfTtcbiAgICAgICAgbWFwW3NlbGVjdG9yXSA9IGFuc3dlcjtcbiAgICAgICAgYXJyYXkucHVzaChhbnN3ZXIpO1xuICAgICAgfVxuICAgICAgdmFyIHN0YXR1cyA9IChwb2RTdGF0dXMocG9kKSB8fCBcIkVycm9yXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAoc3RhdHVzLnN0YXJ0c1dpdGgoXCJydW5cIikgfHwgc3RhdHVzLnN0YXJ0c1dpdGgoXCJva1wiKSkge1xuICAgICAgICBhbnN3ZXIudmFsaWQgKz0gMTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHVzLnN0YXJ0c1dpdGgoXCJ3YWl0XCIpIHx8IHN0YXR1cy5zdGFydHNXaXRoKFwicHduZFwiKSkge1xuICAgICAgICBhbnN3ZXIud2FpdGluZyArPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYW5zd2VyLmVycm9yICs9IDE7XG4gICAgICB9XG4gICAgICB2YXIgY3JlYXRpb25UaW1lc3RhbXAgPSBnZXRDcmVhdGlvblRpbWVzdGFtcChwb2QpO1xuICAgICAgaWYgKGNyZWF0aW9uVGltZXN0YW1wKSB7XG4gICAgICAgIHZhciBkID0gbmV3IERhdGUoY3JlYXRpb25UaW1lc3RhbXApO1xuICAgICAgICBpZiAoIWxvd2VzdERhdGUgfHwgZCA8IGxvd2VzdERhdGUpIHtcbiAgICAgICAgICBsb3dlc3REYXRlID0gZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIGFwcFZpZXcuJGNyZWF0aW9uRGF0ZSA9IGxvd2VzdERhdGU7XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwcFZpZXdTZXJ2aWNlVmlld3MoYXBwVmlldykge1xuICAgIHZhciBhcnJheSA9IFtdO1xuICAgIHZhciBwb2RzID0gYXBwVmlldy5wb2RzO1xuICAgIGFuZ3VsYXIuZm9yRWFjaChwb2RzLCBwb2QgPT4ge1xuICAgICAgdmFyIGlkID0gZ2V0TmFtZShwb2QpO1xuICAgICAgaWYgKGlkKSB7XG4gICAgICAgIHZhciBhYmJyZXYgPSBpZDtcbiAgICAgICAgdmFyIGlkeCA9IGlkLmluZGV4T2YoXCItXCIpO1xuICAgICAgICBpZiAoaWR4ID4gMSkge1xuICAgICAgICAgIGFiYnJldiA9IGlkLnN1YnN0cmluZygwLCBpZHgpO1xuICAgICAgICB9XG4gICAgICAgIHBvZC5pZEFiYnJldiA9IGFiYnJldjtcbiAgICAgIH1cbiAgICAgIHBvZC5zdGF0dXNDbGFzcyA9IHN0YXR1c1RleHRUb0Nzc0NsYXNzKHBvZFN0YXR1cyhwb2QpLCBpc1JlYWR5KHBvZCkpO1xuICAgIH0pO1xuXG4gICAgdmFyIHNlcnZpY2VzID0gYXBwVmlldy5zZXJ2aWNlcyB8fCBbXTtcbiAgICB2YXIgcmVwbGljYXRpb25Db250cm9sbGVycyA9IGFwcFZpZXcucmVwbGljYXRpb25Db250cm9sbGVycyB8fCBbXTtcbiAgICB2YXIgc2l6ZSA9IE1hdGgubWF4KHNlcnZpY2VzLmxlbmd0aCwgcmVwbGljYXRpb25Db250cm9sbGVycy5sZW5ndGgsIDEpO1xuICAgIHZhciBhcHBOYW1lID0gYXBwVmlldy4kaW5mby5uYW1lO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICB2YXIgc2VydmljZSA9IHNlcnZpY2VzW2ldO1xuICAgICAgdmFyIHJlcGxpY2F0aW9uQ29udHJvbGxlciA9IHJlcGxpY2F0aW9uQ29udHJvbGxlcnNbaV07XG4gICAgICB2YXIgY29udHJvbGxlcklkID0gZ2V0TmFtZShyZXBsaWNhdGlvbkNvbnRyb2xsZXIpO1xuICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHNlcnZpY2UpIHx8IGNvbnRyb2xsZXJJZDtcbiAgICAgIHZhciBhZGRyZXNzID0gQ29yZS5wYXRoR2V0KHNlcnZpY2UsIFtcInNwZWNcIiwgXCJwb3J0YWxJUFwiXSk7XG4gICAgICBpZiAoIW5hbWUgJiYgcG9kcy5sZW5ndGgpIHtcbiAgICAgICAgbmFtZSA9IHBvZHNbMF0uaWRBYmJyZXY7XG4gICAgICB9XG4gICAgICBpZiAoIWFwcFZpZXcuJGluZm8ubmFtZSkge1xuICAgICAgICBhcHBWaWV3LiRpbmZvLm5hbWUgPSBuYW1lO1xuICAgICAgfVxuICAgICAgaWYgKCFhcHBWaWV3LmlkICYmIHBvZHMubGVuZ3RoKSB7XG4gICAgICAgIGFwcFZpZXcuaWQgPSBnZXROYW1lKHBvZHNbMF0pO1xuICAgICAgfVxuICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgIGFwcE5hbWUgPSBuYW1lO1xuICAgICAgfVxuICAgICAgdmFyIHBvZENvdW50ID0gcG9kcy5sZW5ndGg7XG4gICAgICB2YXIgcG9kQ291bnRUZXh0ID0gcG9kQ291bnQgKyBcIiBwb2RcIiArIChwb2RDb3VudCA+IDEgPyBcInNcIiA6IFwiXCIpO1xuICAgICAgdmFyIHZpZXcgPSB7XG4gICAgICAgIGFwcE5hbWU6IGFwcE5hbWUgfHwgbmFtZSxcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgY3JlYXRlZERhdGU6IGFwcFZpZXcuJGNyZWF0aW9uRGF0ZSxcbiAgICAgICAgcG9kQ291bnQ6IHBvZENvdW50LFxuICAgICAgICBwb2RDb3VudFRleHQ6IHBvZENvdW50VGV4dCxcbiAgICAgICAgYWRkcmVzczogYWRkcmVzcyxcbiAgICAgICAgY29udHJvbGxlcklkOiBjb250cm9sbGVySWQsXG4gICAgICAgIHNlcnZpY2U6IHNlcnZpY2UsXG4gICAgICAgIHJlcGxpY2F0aW9uQ29udHJvbGxlcjogcmVwbGljYXRpb25Db250cm9sbGVyLFxuICAgICAgICBwb2RzOiBwb2RzXG4gICAgICB9O1xuICAgICAgYXJyYXkucHVzaCh2aWV3KTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgLyoqXG4gICAqIGNvbnZlcnRzIGEgZ2l0IHBhdGggaW50byBhbiBhY2Nlc3NpYmxlIFVSTCBmb3IgdGhlIGJyb3dzZXJcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBnaXRQYXRoVG9VcmwoaWNvblBhdGgsIGJyYW5jaCA9IFwibWFzdGVyXCIpIHtcbiAgICByZXR1cm4gKEhhd3Rpb0NvcmUuaW5qZWN0b3IuZ2V0PHN0cmluZz4oJ0FwcExpYnJhcnlVUkwnKSB8fCAnJykgKyBcIi9naXQvXCIgKyBicmFuY2ggKyBpY29uUGF0aDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFzRGF0ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA/IG5ldyBEYXRlKHZhbHVlKSA6IG51bGw7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoQnVpbGRDb25maWcoYnVpbGRDb25maWcsIHNvcnRlZEJ1aWxkcykge1xuICAgIGlmIChidWlsZENvbmZpZykge1xuICAgICAgdmFyIHRyaWdnZXJVcmw6c3RyaW5nID0gbnVsbDtcbiAgICAgIHZhciBtZXRhZGF0YSA9IGJ1aWxkQ29uZmlnLm1ldGFkYXRhIHx8IHt9O1xuICAgICAgdmFyIG5hbWUgPSBtZXRhZGF0YS5uYW1lO1xuICAgICAgYnVpbGRDb25maWcuJG5hbWUgPSBuYW1lO1xuICAgICAgdmFyIHByb2plY3RMaW5rID0gRGV2ZWxvcGVyLnByb2plY3RMaW5rKG5hbWUpO1xuICAgICAgdmFyIG5zID0gbWV0YWRhdGEubmFtZXNwYWNlIHx8IGN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgICBidWlsZENvbmZpZy4kbmFtZXNwYWNlID0gbnM7XG4gICAgICBidWlsZENvbmZpZy5lbnZpcm9ubWVudHMgPSBbXTtcbiAgICAgIGJ1aWxkQ29uZmlnLiRjcmVhdGlvbkRhdGUgPSBhc0RhdGUoS3ViZXJuZXRlcy5nZXRDcmVhdGlvblRpbWVzdGFtcChidWlsZENvbmZpZykpO1xuICAgICAgYnVpbGRDb25maWcuJGxhYmVsc1RleHQgPSBLdWJlcm5ldGVzLmxhYmVsc1RvU3RyaW5nKGdldExhYmVscyhidWlsZENvbmZpZykpO1xuXG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBidWlsZENvbmZpZy4kdmlld0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCJ3b3Jrc3BhY2VzXCIsIG5zLCBcInByb2plY3RzXCIsIG5hbWUsIFwiZW52aXJvbm1lbnRzXCIpO1xuICAgICAgICBidWlsZENvbmZpZy4kZWRpdExpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCJ3b3Jrc3BhY2VzXCIsIG5zLCBcInByb2plY3RzXCIsIG5hbWUsIFwiYnVpbGRDb25maWdFZGl0XCIpO1xuXG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChbZmFsc2UsIHRydWVdLCAoZmxhZykgPT4ge1xuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChidWlsZENvbmZpZy50cmlnZ2VycywgKHRyaWdnZXIpID0+IHtcbiAgICAgICAgICAgIGlmICghdHJpZ2dlclVybCkge1xuICAgICAgICAgICAgICB2YXIgdHlwZSA9IHRyaWdnZXIudHlwZTtcbiAgICAgICAgICAgICAgaWYgKHR5cGUgPT09IFwiZ2VuZXJpY1wiIHx8IGZsYWcpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ2VuZXJpYyA9IHRyaWdnZXJbdHlwZV07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGUgJiYgZ2VuZXJpYykge1xuICAgICAgICAgICAgICAgICAgdmFyIHNlY3JldCA9IGdlbmVyaWMuc2VjcmV0O1xuICAgICAgICAgICAgICAgICAgaWYgKHNlY3JldCkge1xuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyVXJsID0gVXJsSGVscGVycy5qb2luKGJ1aWxkQ29uZmlnSG9va3NSZXN0VVJMKCksIG5hbWUsIHNlY3JldCwgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIGJ1aWxkQ29uZmlnLiR0cmlnZ2VyVXJsID0gdHJpZ2dlclVybDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gbGV0cyBmaW5kIHRoZSBsYXRlc3QgYnVpbGQuLi5cbiAgICAgICAgaWYgKHNvcnRlZEJ1aWxkcykge1xuICAgICAgICAgIGJ1aWxkQ29uZmlnLiRsYXN0QnVpbGQgPSBfLmZpbmQoc29ydGVkQnVpbGRzLCB7XG4gICAgICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICBidWlsZGNvbmZpZzogbmFtZVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciAkZmFicmljOFZpZXdzID0ge307XG5cbiAgICAgIGZ1bmN0aW9uIGRlZmF1bHRQcm9wZXJ0aWVzSWZOb3RFeGlzdChuYW1lLCBvYmplY3QsIGF1dG9DcmVhdGUgPSBmYWxzZSkge1xuICAgICAgICB2YXIgdmlldyA9ICRmYWJyaWM4Vmlld3NbbmFtZV07XG4gICAgICAgIGlmIChhdXRvQ3JlYXRlICYmICF2aWV3KSB7XG4gICAgICAgICAgdmlldyA9IHt9XG4gICAgICAgICAgJGZhYnJpYzhWaWV3c1tuYW1lXSA9IHZpZXc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZpZXcpIHtcbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2gob2JqZWN0LCAodmFsdWUsIHByb3BlcnR5KSA9PiB7XG4gICAgICAgICAgICB2YXIgY3VycmVudCA9IHZpZXdbcHJvcGVydHldO1xuICAgICAgICAgICAgaWYgKCFjdXJyZW50KSB7XG4gICAgICAgICAgICAgIHZpZXdbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0U3RhcnRzV2l0aChwcmVmaXgsIG9iamVjdCwgYXV0b0NyZWF0ZSA9IGZhbHNlKSB7XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaCgkZmFicmljOFZpZXdzLCAodmlldywgbmFtZSkgPT4ge1xuICAgICAgICAgIGlmICh2aWV3ICYmIG5hbWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICAgICAgICBhbmd1bGFyLmZvckVhY2gob2JqZWN0LCAodmFsdWUsIHByb3BlcnR5KSA9PiB7XG4gICAgICAgICAgICAgIHZhciBjdXJyZW50ID0gdmlld1twcm9wZXJ0eV07XG4gICAgICAgICAgICAgIGlmICghY3VycmVudCkge1xuICAgICAgICAgICAgICAgIHZpZXdbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHZhciBsYWJlbHMgPSBtZXRhZGF0YS5sYWJlbHMgfHwge307XG4gICAgICB2YXIgYW5ub3RhdGlvbnMgPSBtZXRhZGF0YS5hbm5vdGF0aW9ucyB8fCB7fTtcblxuICAgICAgLy8gbGV0cyBkZWZhdWx0IHRoZSByZXBvIGFuZCB1c2VyXG4gICAgICBidWlsZENvbmZpZy4kdXNlciA9IGFubm90YXRpb25zW1wiZmFicmljOC5qZW5raW5zL3VzZXJcIl0gfHwgbGFiZWxzW1widXNlclwiXTtcbiAgICAgIGJ1aWxkQ29uZmlnLiRyZXBvID0gYW5ub3RhdGlvbnNbXCJmYWJyaWM4LmplbmtpbnMvcmVwb1wiXSB8fCBsYWJlbHNbXCJyZXBvXCJdO1xuXG4gICAgICBhbmd1bGFyLmZvckVhY2goYW5ub3RhdGlvbnMsICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGtleS5zcGxpdCgnLycsIDIpO1xuICAgICAgICBpZiAocGFydHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIHZhciBsaW5rSWQgPSBwYXJ0c1swXTtcbiAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwYXJ0c1sxXTtcbiAgICAgICAgICBpZiAobGlua0lkICYmIHByb3BlcnR5ICYmIGxpbmtJZC5zdGFydHNXaXRoKFwiZmFicmljOC5saW5rXCIpKSB7XG4gICAgICAgICAgICB2YXIgbGluayA9ICRmYWJyaWM4Vmlld3NbbGlua0lkXTtcbiAgICAgICAgICAgIGlmICghbGluaykge1xuICAgICAgICAgICAgICBsaW5rID0ge1xuICAgICAgICAgICAgICAgIGNsYXNzOiBsaW5rSWRcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgJGZhYnJpYzhWaWV3c1tsaW5rSWRdID0gbGluaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbmtbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgaWYgKGJ1aWxkQ29uZmlnLiR1c2VyICYmIGJ1aWxkQ29uZmlnLiRyZXBvKSB7XG4gICAgICAgIC8vIGJyb3dzZSBnb2dzIHJlcG8gdmlld1xuICAgICAgICB2YXIgZ29nc1VybCA9IHNlcnZpY2VMaW5rVXJsKGdvZ3NTZXJ2aWNlTmFtZSk7XG4gICAgICAgIGlmIChnb2dzVXJsKSB7XG4gICAgICAgICAgZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0KFwiZmFicmljOC5saW5rLmJyb3dzZUdvZ3Mudmlld1wiLCB7XG4gICAgICAgICAgICBsYWJlbDogXCJCcm93c2UuLi5cIixcbiAgICAgICAgICAgIHVybDogVXJsSGVscGVycy5qb2luKGdvZ3NVcmwsIGJ1aWxkQ29uZmlnLiR1c2VyLCBidWlsZENvbmZpZy4kcmVwbyksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogXCJCcm93c2UgdGhlIHNvdXJjZSBjb2RlIG9mIHRoaXMgcmVwb3NpdG9yeVwiLFxuICAgICAgICAgICAgaWNvbkNsYXNzOiBcImZhIGZhLWV4dGVybmFsLWxpbmtcIlxuICAgICAgICAgIH0sIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcnVuIGZvcmdlIGNvbW1hbmRzIHZpZXdcbiAgICAgICAgZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0KFwiZmFicmljOC5saW5rLmZvcmdlQ29tbWFuZC52aWV3XCIsIHtcbiAgICAgICAgICBsYWJlbDogXCJDb21tYW5kLi4uXCIsXG4gICAgICAgICAgdXJsOiBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmssIFwiL2ZvcmdlL2NvbW1hbmRzL3VzZXJcIiwgYnVpbGRDb25maWcuJHVzZXIsIGJ1aWxkQ29uZmlnLiRyZXBvKSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogXCJQZXJmb3JtIGFuIGFjdGlvbiBvbiB0aGlzIHByb2plY3RcIixcbiAgICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtcGxheS1jaXJjbGVcIlxuICAgICAgICB9LCB0cnVlKTtcblxuXG4gICAgICAgIC8vIGNvbmZpZ3VyZSBkZXZvcHMgdmlld1xuICAgICAgICBkZWZhdWx0UHJvcGVydGllc0lmTm90RXhpc3QoXCJmYWJyaWM4LmxpbmsuZm9yZ2VDb21tYW5kLmRldm9wcy5zZXR0aW5nc1wiLCB7XG4gICAgICAgICAgbGFiZWw6IFwiU2V0dGluZ3NcIixcbiAgICAgICAgICB1cmw6IFVybEhlbHBlcnMuam9pbihwcm9qZWN0TGluaywgXCIvZm9yZ2UvY29tbWFuZC9kZXZvcHMtZWRpdC91c2VyXCIsIGJ1aWxkQ29uZmlnLiR1c2VyLCBidWlsZENvbmZpZy4kcmVwbyksXG4gICAgICAgICAgZGVzY3JpcHRpb246IFwiQ29uZmlndXJlIHRoZSBEZXZPcHMgc2V0dGluZ3MgZm9yIHRoaXMgcHJvamVjdFwiLFxuICAgICAgICAgIGljb25DbGFzczogXCJmYSBmYS1wZW5jaWwtc3F1YXJlLW9cIlxuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgfVxuXG4gICAgICAvLyBhZGQgc29tZSBpY29ucyBhbmQgZGVzY3JpcHRpb25zXG4gICAgICBkZWZhdWx0UHJvcGVydGllc0lmTm90RXhpc3QoXCJmYWJyaWM4LmxpbmsucmVwb3NpdG9yeS5icm93c2VcIiwge1xuICAgICAgICBsYWJlbDogXCJCcm93c2UuLi5cIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiQnJvd3NlIHRoZSBzb3VyY2UgY29kZSBvZiB0aGlzIHJlcG9zaXRvcnlcIixcbiAgICAgICAgaWNvbkNsYXNzOiBcImZhIGZhLWV4dGVybmFsLWxpbmtcIlxuICAgICAgfSk7XG4gICAgICBkZWZhdWx0UHJvcGVydGllc0lmTm90RXhpc3QoXCJmYWJyaWM4LmxpbmsuamVua2lucy5qb2JcIiwge1xuICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtdGFza3NcIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiVmlldyB0aGUgSmVua2lucyBKb2IgZm9yIHRoaXMgYnVpbGRcIlxuICAgICAgfSk7XG4gICAgICBkZWZhdWx0UHJvcGVydGllc0lmTm90RXhpc3QoXCJmYWJyaWM4LmxpbmsuamVua2lucy5tb25pdG9yXCIsIHtcbiAgICAgICAgaWNvbkNsYXNzOiBcImZhIGZhLXRhY2hvbWV0ZXJcIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiVmlldyB0aGUgSmVua2lucyBNb25pdG9yIGRhc2hib2FyZCBmb3IgdGhpcyBwcm9qZWN0XCJcbiAgICAgIH0pO1xuICAgICAgZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0KFwiZmFicmljOC5saW5rLmplbmtpbnMucGlwZWxpbmVcIiwge1xuICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtYXJyb3ctY2lyY2xlLW8tcmlnaHRcIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiVmlldyB0aGUgSmVua2lucyBQaXBlbGluZSBmb3IgdGhpcyBwcm9qZWN0XCJcbiAgICAgIH0pO1xuICAgICAgZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0KFwiZmFicmljOC5saW5rLmxldHNjaGF0LnJvb21cIiwge1xuICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtY29tbWVudFwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogXCJDaGF0IHJvb20gZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9KTtcbiAgICAgIGRlZmF1bHRQcm9wZXJ0aWVzSWZOb3RFeGlzdChcImZhYnJpYzgubGluay5sZXRzY2hhdC5yb29tXCIsIHtcbiAgICAgICAgaWNvbkNsYXNzOiBcImZhIGZhLWNvbW1lbnRcIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiQ2hhdCByb29tIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSk7XG4gICAgICBkZWZhdWx0UHJvcGVydGllc0lmTm90RXhpc3QoXCJmYWJyaWM4LmxpbmsudGFpZ2FcIiwge1xuICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtY2hlY2stc3F1YXJlLW9cIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiSXNzdWUgdHJhY2tlciBmb3IgdGhpcyBwcm9qZWN0XCJcbiAgICAgIH0pO1xuICAgICAgZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0KFwiZmFicmljOC5saW5rLmlzc3Vlc1wiLCB7XG4gICAgICAgIGljb25DbGFzczogXCJmYSBmYS1jaGVjay1zcXVhcmUtb1wiLFxuICAgICAgICBkZXNjcmlwdGlvbjogXCJJc3N1ZXMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9KTtcbiAgICAgIGRlZmF1bHRQcm9wZXJ0aWVzSWZOb3RFeGlzdChcImZhYnJpYzgubGluay5yZWxlYXNlc1wiLCB7XG4gICAgICAgIGljb25DbGFzczogXCJmYSBmYS10YWdcIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiSXNzdWVzIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSk7XG4gICAgICBkZWZhdWx0UHJvcGVydGllc0lmTm90RXhpc3QoXCJmYWJyaWM4LmxpbmsudGFpZ2EudGVhbVwiLCB7XG4gICAgICAgIGljb25DbGFzczogXCJmYSBmYS11c2Vyc1wiLFxuICAgICAgICBkZXNjcmlwdGlvbjogXCJUZWFtIG1lbWJlcnMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9KTtcbiAgICAgIGRlZmF1bHRQcm9wZXJ0aWVzSWZOb3RFeGlzdChcImZhYnJpYzgubGluay50ZWFtXCIsIHtcbiAgICAgICAgaWNvbkNsYXNzOiBcImZhIGZhLXVzZXJzXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIlRlYW0gbWVtYmVycyBmb3IgdGhpcyBwcm9qZWN0XCJcbiAgICAgIH0pO1xuICAgICAgZGVmYXVsdFByb3BlcnRpZXNJZk5vdEV4aXN0U3RhcnRzV2l0aChcImZhYnJpYzgubGluay5lbnZpcm9ubWVudC5cIiwge1xuICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtY2xvdWRcIixcbiAgICAgICAgZGVzY3JpcHRpb246IFwiVGhlIGt1YmVybmV0ZXMgbmFtZXNwYWNlIGZvciB0aGlzIGVudmlyb25tZW50XCJcbiAgICAgIH0pO1xuXG5cbiAgICAgIC8vIGxldHMgcHV0IHRoZSB2aWV3cyBpbnRvIHNlY3Rpb25zLi4uXG4gICAgICB2YXIgJGZhYnJpYzhDb2RlVmlld3MgPSB7fTtcbiAgICAgIHZhciAkZmFicmljOEJ1aWxkVmlld3MgPSB7fTtcbiAgICAgIHZhciAkZmFicmljOFRlYW1WaWV3cyA9IHt9O1xuICAgICAgdmFyICRmYWJyaWM4RW52aXJvbm1lbnRWaWV3cyA9IHt9O1xuICAgICAgYW5ndWxhci5mb3JFYWNoKCRmYWJyaWM4Vmlld3MsICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgIHZhciB2aWV3O1xuICAgICAgICBpZiAoa2V5LmluZGV4T2YoXCJ0YWlnYVwiKSA+IDAgfHwga2V5LmluZGV4T2YoXCIuaXNzdWVcIikgPiAwIHx8IGtleS5pbmRleE9mKFwibGV0c2NoYXRcIikgPiAwfHwga2V5LmluZGV4T2YoXCIudGVhbVwiKSA+IDApIHtcbiAgICAgICAgICB2aWV3ID0gJGZhYnJpYzhUZWFtVmlld3M7XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5LmluZGV4T2YoXCJqZW5raW5zXCIpID4gMCkge1xuICAgICAgICAgIHZpZXcgPSAkZmFicmljOEJ1aWxkVmlld3M7XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5LmluZGV4T2YoXCIuZW52aXJvbm1lbnQuXCIpID4gMCkge1xuICAgICAgICAgIHZpZXcgPSAkZmFicmljOEVudmlyb25tZW50Vmlld3M7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmlldyA9ICRmYWJyaWM4Q29kZVZpZXdzO1xuICAgICAgICB9XG4gICAgICAgIHZpZXdba2V5XSA9IHZhbHVlO1xuICAgICAgfSk7XG5cblxuICAgICAgYnVpbGRDb25maWcuJGZhYnJpYzhWaWV3cyA9ICRmYWJyaWM4Vmlld3M7XG4gICAgICBidWlsZENvbmZpZy4kZmFicmljOENvZGVWaWV3cyA9ICRmYWJyaWM4Q29kZVZpZXdzO1xuICAgICAgYnVpbGRDb25maWcuJGZhYnJpYzhCdWlsZFZpZXdzID0gJGZhYnJpYzhCdWlsZFZpZXdzO1xuICAgICAgYnVpbGRDb25maWcuJGZhYnJpYzhFbnZpcm9ubWVudFZpZXdzID0gJGZhYnJpYzhFbnZpcm9ubWVudFZpZXdzO1xuICAgICAgYnVpbGRDb25maWcuJGZhYnJpYzhUZWFtVmlld3MgPSAkZmFicmljOFRlYW1WaWV3cztcblxuICAgICAgdmFyICRqZW5raW5zSm9iID0gYW5ub3RhdGlvbnNbXCJmYWJyaWM4LmlvL2plbmtpbnMtam9iXCJdO1xuICAgICAgaWYgKCEkamVua2luc0pvYiAmJiAkZmFicmljOFZpZXdzW1wiZmFicmljOC5saW5rLmplbmtpbnMuam9iXCJdKSB7XG4gICAgICAgICRqZW5raW5zSm9iID0gbmFtZTtcbiAgICAgIH1cbiAgICAgIGJ1aWxkQ29uZmlnLiRqZW5raW5zSm9iID0gJGplbmtpbnNKb2I7XG5cbiAgICAgIGFuZ3VsYXIuZm9yRWFjaCgkZmFicmljOEVudmlyb25tZW50Vmlld3MsIChlbnYpID0+IHtcbiAgICAgICAgdmFyIGMgPSBlbnYuY2xhc3M7XG4gICAgICAgIHZhciBwcmVmaXggPSBcImZhYnJpYzgubGluay5lbnZpcm9ubWVudC5cIjtcbiAgICAgICAgaWYgKGMgJiYgYy5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgICAgICB2YXIgZW5zID0gYy5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCk7XG4gICAgICAgICAgZW52Lm5hbWVzcGFjZSA9IGVucztcbiAgICAgICAgICBlbnYudXJsID0gVXJsSGVscGVycy5qb2luKFwiL3dvcmtzcGFjZXNcIiwgbnMsIFwicHJvamVjdHNcIiwgbmFtZSwgXCJuYW1lc3BhY2VcIiwgZW5zKTtcbiAgICAgICAgfVxuICAgICAgICBidWlsZENvbmZpZy5lbnZpcm9ubWVudHMucHVzaChlbnYpO1xuICAgICAgfSk7XG4gICAgICBpZiAoIWJ1aWxkQ29uZmlnLmVudmlyb25tZW50cy5sZW5ndGgpIHtcbiAgICAgICAgLy8gbGV0cyBjcmVhdGUgYSBzaW5nbGUgZW52aXJvbm1lbnRcbiAgICAgICAgdmFyIGVucyA9IG5zO1xuICAgICAgICB2YXIgZW52ID0ge1xuICAgICAgICAgIG5hbWVzcGFjZTogZW5zLFxuICAgICAgICAgIGxhYmVsOiBcIkN1cnJlbnRcIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogXCJUaGUgZW52aXJvbmVtbnQgdGhhdCB0aGlzIHByb2plY3QgaXMgYnVpbHQgYW5kIHJ1biBpbnNpZGVcIixcbiAgICAgICAgICBpY29uQ2xhc3M6IFwiZmEgZmEtY2xvdWRcIixcbiAgICAgICAgICB1cmw6IFVybEhlbHBlcnMuam9pbihcIi93b3Jrc3BhY2VzXCIsIG5zLCBcInByb2plY3RzXCIsIG5hbWUsIFwibmFtZXNwYWNlXCIsIGVucylcbiAgICAgICAgfTtcbiAgICAgICAgYnVpbGRDb25maWcuZW52aXJvbm1lbnRzLnB1c2goZW52KTtcblxuICAgICAgfVxuXG4gICAgICBidWlsZENvbmZpZy5lbnZpcm9ubWVudHMgPSBidWlsZENvbmZpZy5lbnZpcm9ubWVudHMucmV2ZXJzZSgpO1xuXG4gICAgICBidWlsZENvbmZpZy50b29scyA9IFtdO1xuICAgICAgYW5ndWxhci5mb3JFYWNoKCRmYWJyaWM4Q29kZVZpZXdzLCAoZW52KSA9PiB7XG4gICAgICAgIGJ1aWxkQ29uZmlnLnRvb2xzLnB1c2goZW52KTtcbiAgICAgIH0pO1xuICAgICAgYW5ndWxhci5mb3JFYWNoKCRmYWJyaWM4VGVhbVZpZXdzLCAoZW52KSA9PiB7XG4gICAgICAgIGJ1aWxkQ29uZmlnLnRvb2xzLnB1c2goZW52KTtcbiAgICAgIH0pO1xuXG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGVucmljaEJ1aWxkQ29uZmlncyhidWlsZENvbmZpZ3MsIHNvcnRlZEJ1aWxkcyA9IG51bGwpIHtcbiAgICBhbmd1bGFyLmZvckVhY2goYnVpbGRDb25maWdzLCAoYnVpbGRDb25maWcpID0+IHtcbiAgICAgIGVucmljaEJ1aWxkQ29uZmlnKGJ1aWxkQ29uZmlnLCBzb3J0ZWRCdWlsZHMpO1xuICAgIH0pO1xuICAgIHJldHVybiBidWlsZENvbmZpZ3M7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoQnVpbGRzKGJ1aWxkcykge1xuICAgIGFuZ3VsYXIuZm9yRWFjaChidWlsZHMsIChidWlsZCkgPT4ge1xuICAgICAgZW5yaWNoQnVpbGQoYnVpbGQpO1xuICAgIH0pO1xuICAgIHJldHVybiBfLnNvcnRCeShidWlsZHMsIFwiJGNyZWF0aW9uRGF0ZVwiKS5yZXZlcnNlKCk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoQnVpbGQoYnVpbGQpIHtcbiAgICBpZiAoYnVpbGQpIHtcbiAgICAgIHZhciBtZXRhZGF0YSA9IGJ1aWxkLm1ldGFkYXRhIHx8IHt9O1xuICAgICAgdmFyIGFubm90YXRpb25zID0gbWV0YWRhdGEuYW5ub3RhdGlvbnMgfHwge307XG4gICAgICB2YXIgbmFtZSA9IGdldE5hbWUoYnVpbGQpO1xuICAgICAgdmFyIG5hbWVzcGFjZSA9IGdldE5hbWVzcGFjZShidWlsZCk7XG4gICAgICBidWlsZC4kbmFtZSA9IG5hbWU7XG4gICAgICBidWlsZC4kbmFtZXNwYWNlID0gbmFtZXNwYWNlO1xuXG4gICAgICB2YXIgbmFtZUFycmF5ID0gbmFtZS5zcGxpdChcIi1cIik7XG4gICAgICB2YXIgbmFtZUFycmF5TGVuZ3RoID0gbmFtZUFycmF5Lmxlbmd0aDtcbiAgICAgIGJ1aWxkLiRzaG9ydE5hbWUgPSAobmFtZUFycmF5TGVuZ3RoID4gNCkgPyBuYW1lQXJyYXkuc2xpY2UoMCwgbmFtZUFycmF5TGVuZ3RoIC0gNCkuam9pbihcIi1cIikgOiBuYW1lLnN1YnN0cmluZygwLCAzMCk7XG5cbiAgICAgIHZhciBsYWJlbHMgPSBnZXRMYWJlbHMoYnVpbGQpO1xuICAgICAgdmFyIGNvbmZpZ0lkID0gbGFiZWxzLmJ1aWxkY29uZmlnO1xuICAgICAgYnVpbGQuJGNvbmZpZ0lkID0gY29uZmlnSWQ7XG4gICAgICBpZiAoY29uZmlnSWQpIHtcbiAgICAgICAgLy9idWlsZC4kY29uZmlnTGluayA9IFVybEhlbHBlcnMuam9pbihcImt1YmVybmV0ZXMvYnVpbGRDb25maWdzXCIsIGNvbmZpZ0lkKTtcbiAgICAgICAgYnVpbGQuJGNvbmZpZ0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCJ3b3Jrc3BhY2VzXCIsIGN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCksIFwicHJvamVjdHNcIiwgY29uZmlnSWQpO1xuICAgICAgfVxuICAgICAgdmFyIGNyZWF0aW9uVGltZXN0YW1wID0gZ2V0Q3JlYXRpb25UaW1lc3RhbXAoYnVpbGQpO1xuICAgICAgaWYgKGNyZWF0aW9uVGltZXN0YW1wKSB7XG4gICAgICAgIHZhciBkID0gbmV3IERhdGUoY3JlYXRpb25UaW1lc3RhbXApO1xuICAgICAgICBidWlsZC4kY3JlYXRpb25EYXRlID0gZDtcbiAgICAgIH1cbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIC8vYnVpbGQuJHZpZXdMaW5rID0gVXJsSGVscGVycy5qb2luKFwia3ViZXJuZXRlcy9idWlsZHNcIiwgbmFtZSk7XG4gICAgICAgIHZhciBwcm9qZWN0TGluayA9IFVybEhlbHBlcnMuam9pbihcIndvcmtzcGFjZXNcIiwgY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKSwgXCJwcm9qZWN0c1wiLCBjb25maWdJZCk7XG4gICAgICAgIGJ1aWxkLiR2aWV3TGluayA9IFVybEhlbHBlcnMuam9pbihwcm9qZWN0TGluaywgXCJidWlsZHNcIiwgbmFtZSk7XG4gICAgICAgIC8vYnVpbGQuJGxvZ3NMaW5rID0gVXJsSGVscGVycy5qb2luKFwia3ViZXJuZXRlcy9idWlsZExvZ3NcIiwgbmFtZSk7XG4gICAgICAgIGJ1aWxkLiRsb2dzTGluayA9IFVybEhlbHBlcnMuam9pbihwcm9qZWN0TGluaywgXCJidWlsZExvZ3NcIiwgbmFtZSk7XG4gICAgICB9XG4gICAgICBidWlsZC5wb2ROYW1lID0gYnVpbGQucG9kTmFtZSB8fCBhbm5vdGF0aW9uc1tcIm9wZW5zaGlmdC5pby9idWlsZC5wb2QtbmFtZVwiXTtcbiAgICAgIHZhciBwb2ROYW1lID0gYnVpbGQucG9kTmFtZTtcbiAgICAgIGlmIChwb2ROYW1lICYmIG5hbWVzcGFjZSkge1xuICAgICAgICB2YXIgcG9kTmFtZUFycmF5ID0gcG9kTmFtZS5zcGxpdChcIi1cIik7XG4gICAgICAgIHZhciBwb2ROYW1lQXJyYXlMZW5ndGggPSBwb2ROYW1lQXJyYXkubGVuZ3RoO1xuICAgICAgICBidWlsZC4kcG9kU2hvcnROYW1lID0gKHBvZE5hbWVBcnJheUxlbmd0aCA+IDUpID8gcG9kTmFtZUFycmF5W3BvZE5hbWVBcnJheUxlbmd0aCAtIDVdIDogcG9kTmFtZS5zdWJzdHJpbmcoMCwgMzApO1xuICAgICAgICBidWlsZC4kcG9kTGluayA9IFVybEhlbHBlcnMuam9pbihcImt1YmVybmV0ZXMvbmFtZXNwYWNlXCIsIG5hbWVzcGFjZSwgXCJwb2RzXCIsIHBvZE5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYnVpbGQ7XG4gIH1cblxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlbnJpY2hEZXBsb3ltZW50Q29uZmlnKGRlcGxveW1lbnRDb25maWcpIHtcbiAgICBpZiAoZGVwbG95bWVudENvbmZpZykge1xuICAgICAgdmFyIHRyaWdnZXJVcmw6c3RyaW5nID0gbnVsbDtcbiAgICAgIHZhciBuYW1lID0gQ29yZS5wYXRoR2V0KGRlcGxveW1lbnRDb25maWcsIFtcIm1ldGFkYXRhXCIsIFwibmFtZVwiXSk7XG4gICAgICBkZXBsb3ltZW50Q29uZmlnLiRuYW1lID0gbmFtZTtcbiAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgYW5ndWxhci5mb3JFYWNoKGRlcGxveW1lbnRDb25maWcudHJpZ2dlcnMsICh0cmlnZ2VyKSA9PiB7XG4gICAgICAgIHZhciB0eXBlID0gdHJpZ2dlci50eXBlO1xuICAgICAgICBpZiAoIWRlcGxveW1lbnRDb25maWcuJGltYWdlQ2hhbmdlUGFyYW1zICYmIHR5cGUgPT09IFwiSW1hZ2VDaGFuZ2VcIikge1xuICAgICAgICAgIHZhciBpbWFnZUNoYW5nZVBhcmFtcyA9IHRyaWdnZXIuaW1hZ2VDaGFuZ2VQYXJhbXM7XG4gICAgICAgICAgaWYgKGltYWdlQ2hhbmdlUGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgY29udGFpbmVyTmFtZXMgPSBpbWFnZUNoYW5nZVBhcmFtcy5jb250YWluZXJOYW1lcyB8fCBbXTtcbiAgICAgICAgICAgIGltYWdlQ2hhbmdlUGFyYW1zLiRjb250YWluZXJOYW1lcyA9IGNvbnRhaW5lck5hbWVzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgZGVwbG95bWVudENvbmZpZy4kaW1hZ2VDaGFuZ2VQYXJhbXMgPSBpbWFnZUNoYW5nZVBhcmFtcztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlbnJpY2hEZXBsb3ltZW50Q29uZmlncyhkZXBsb3ltZW50Q29uZmlncykge1xuICAgIGFuZ3VsYXIuZm9yRWFjaChkZXBsb3ltZW50Q29uZmlncywgKGRlcGxveW1lbnRDb25maWcpID0+IHtcbiAgICAgIGVucmljaERlcGxveW1lbnRDb25maWcoZGVwbG95bWVudENvbmZpZyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGRlcGxveW1lbnRDb25maWdzO1xuICB9XG5cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoRXZlbnQoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQpIHtcbiAgICAgIHZhciBtZXRhZGF0YSA9IGV2ZW50Lm1ldGFkYXRhIHx8IHt9O1xuXG4gICAgICB2YXIgZmlyc3RUaW1lc3RhbXAgPSBldmVudC5maXJzdFRpbWVzdGFtcDtcbiAgICAgIGlmIChmaXJzdFRpbWVzdGFtcCkge1xuICAgICAgICB2YXIgZCA9IG5ldyBEYXRlKGZpcnN0VGltZXN0YW1wKTtcbiAgICAgICAgZXZlbnQuJGZpcnN0VGltZXN0YW1wID0gZDtcbiAgICAgIH1cbiAgICAgIHZhciBsYXN0VGltZXN0YW1wID0gZXZlbnQubGFzdFRpbWVzdGFtcDtcbiAgICAgIGlmIChsYXN0VGltZXN0YW1wKSB7XG4gICAgICAgIHZhciBkID0gbmV3IERhdGUobGFzdFRpbWVzdGFtcCk7XG4gICAgICAgIGV2ZW50LiRsYXN0VGltZXN0YW1wID0gZDtcbiAgICAgIH1cbiAgICAgIHZhciBsYWJlbHMgPSBhbmd1bGFyLmNvcHkoZXZlbnQuc291cmNlIHx8IHt9KTtcbiAgICAgIHZhciBpbnZvbHZlZE9iamVjdCA9IGV2ZW50Lmludm9sdmVkT2JqZWN0IHx8IHt9O1xuICAgICAgdmFyIG5hbWUgPSBpbnZvbHZlZE9iamVjdC5uYW1lO1xuICAgICAgdmFyIGtpbmQgPSBpbnZvbHZlZE9iamVjdC5raW5kO1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgbGFiZWxzWyduYW1lJ10gPSBuYW1lO1xuICAgICAgfVxuICAgICAgaWYgKGtpbmQpIHtcbiAgICAgICAgbGFiZWxzWydraW5kJ10gPSBraW5kO1xuICAgICAgfVxuICAgICAgZXZlbnQuJGxhYmVsc1RleHQgPSBLdWJlcm5ldGVzLmxhYmVsc1RvU3RyaW5nKGxhYmVscyk7XG5cbiAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoRXZlbnRzKGV2ZW50cywgbW9kZWwgPSBudWxsKSB7XG4gICAgYW5ndWxhci5mb3JFYWNoKGV2ZW50cywgKGV2ZW50KSA9PiB7XG4gICAgICBlbnJpY2hFdmVudChldmVudCk7XG4gICAgfSk7XG5cbiAgICAvLyBsZXRzIHVwZGF0ZSBsaW5rcyB0byB0aGUgZXZlbnRzIGZvciBlYWNoIHBvZCBhbmQgUkNcbiAgICBpZiAobW9kZWwpIHtcbiAgICAgIGZ1bmN0aW9uIGNsZWFyRXZlbnRzKGVudGl0eSkge1xuICAgICAgICBlbnRpdHkuJGV2ZW50cyA9IFtdO1xuICAgICAgICBlbnRpdHkuJGV2ZW50c0xpbmsgPSBudWxsO1xuICAgICAgICBlbnRpdHkuJGV2ZW50Q291bnQgPSAwO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB1cGRhdGVFdmVudChlbnRpdHksIGV2ZW50KSB7XG4gICAgICAgIGlmIChlbnRpdHkpIHtcbiAgICAgICAgICBlbnRpdHkuJGV2ZW50cy5wdXNoKGV2ZW50KTtcbiAgICAgICAgICBpZiAoIWVudGl0eS4kZXZlbnRzTGluaykge1xuICAgICAgICAgICAgZW50aXR5LiRldmVudHNMaW5rID0gVXJsSGVscGVycy5qb2luKFwiL2t1YmVybmV0ZXMvbmFtZXNwYWNlL1wiLCBjdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpLCBcImV2ZW50c1wiKSArIFwiP3E9a2luZCUzRFwiICsgZW50aXR5LmtpbmQgKyBcIiUyMG5hbWUlM0RcIiArIGVudGl0eS5tZXRhZGF0YS5uYW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbnRpdHkuJGV2ZW50Q291bnQgPSBlbnRpdHkuJGV2ZW50cy5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIHBvZHMgPSBtb2RlbC5wb2RzIHx8IFtdO1xuICAgICAgdmFyIHJjcyA9IG1vZGVsLnJlcGxpY2F0aW9uQ29udHJvbGxlcnMgfHwgW107XG4gICAgICBhbmd1bGFyLmZvckVhY2gocG9kcywgY2xlYXJFdmVudHMpO1xuICAgICAgYW5ndWxhci5mb3JFYWNoKHJjcywgY2xlYXJFdmVudHMpO1xuXG4gICAgICBhbmd1bGFyLmZvckVhY2goZXZlbnRzLCAoZXZlbnQpID0+IHtcbiAgICAgICAgdmFyIGludm9sdmVkT2JqZWN0ID0gZXZlbnQuaW52b2x2ZWRPYmplY3QgfHwge307XG4gICAgICAgIHZhciBuYW1lID0gaW52b2x2ZWRPYmplY3QubmFtZTtcbiAgICAgICAgdmFyIGtpbmQgPSBpbnZvbHZlZE9iamVjdC5raW5kO1xuICAgICAgICB2YXIgbnMgPSBtb2RlbC5jdXJyZW50TmFtZXNwYWNlKCk7XG4gICAgICAgIGlmIChuYW1lICYmIGtpbmQgJiYgbnMpIHtcbiAgICAgICAgICB2YXIgZW50aXR5ID0gbnVsbDtcbiAgICAgICAgICBpZiAoa2luZCA9PT0gXCJSZXBsaWNhdGlvbkNvbnRyb2xsZXJcIikge1xuICAgICAgICAgICAgZW50aXR5ID0gbW9kZWwuZ2V0UmVwbGljYXRpb25Db250cm9sbGVyKG5zLCBuYW1lKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGtpbmQgPT09IFwiUG9kXCIpIHtcbiAgICAgICAgICAgIGVudGl0eSA9IG1vZGVsLmdldFBvZChucywgbmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChlbnRpdHkpIHtcbiAgICAgICAgICAgIHVwZGF0ZUV2ZW50KGVudGl0eSwgZXZlbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBldmVudHM7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoSW1hZ2VSZXBvc2l0b3J5KGltYWdlUmVwb3NpdG9yeSkge1xuICAgIGlmIChpbWFnZVJlcG9zaXRvcnkpIHtcbiAgICAgIHZhciB0cmlnZ2VyVXJsOnN0cmluZyA9IG51bGw7XG4gICAgICB2YXIgbmFtZSA9IENvcmUucGF0aEdldChpbWFnZVJlcG9zaXRvcnksIFtcIm1ldGFkYXRhXCIsIFwibmFtZVwiXSk7XG4gICAgICBpbWFnZVJlcG9zaXRvcnkuJG5hbWUgPSBuYW1lO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlbnJpY2hJbWFnZVJlcG9zaXRvcmllcyhpbWFnZVJlcG9zaXRvcmllcykge1xuICAgIGFuZ3VsYXIuZm9yRWFjaChpbWFnZVJlcG9zaXRvcmllcywgKGltYWdlUmVwb3NpdG9yeSkgPT4ge1xuICAgICAgZW5yaWNoSW1hZ2VSZXBvc2l0b3J5KGltYWdlUmVwb3NpdG9yeSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGltYWdlUmVwb3NpdG9yaWVzO1xuICB9XG5cblxuICB2YXIgbGFiZWxDb2xvcnMgPSB7XG4gICAgJ2JhdGNoJzogJ2s4cy1iYWRnZS1iYXRjaCcsXG4gICAgJ3JlZ2lvbic6ICdrOHMtYmFkZ2UtcmVnaW9uJyxcbiAgICAndHlwZSc6ICdrOHMtYmFkZ2UtdHlwZScsXG4gICAgJ3N5c3RlbSc6ICdrOHMtYmFkZ2Utc3lzdGVtJ1xuICB9O1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBjb250YWluZXJMYWJlbENsYXNzKGxhYmVsVHlwZTpzdHJpbmcpIHtcbiAgICBpZiAoIShsYWJlbFR5cGUgaW4gbGFiZWxDb2xvcnMpKSB7XG4gICAgICByZXR1cm4gJ21vdXNlLXBvaW50ZXInO1xuICAgIH1cbiAgICBlbHNlIHJldHVybiBsYWJlbENvbG9yc1tsYWJlbFR5cGVdICsgJyBtb3VzZS1wb2ludGVyJztcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgZmFicmljOCBmb3JnZSBwbHVnaW4gaXMgZW5hYmxlZFxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGlzRm9yZ2VFbmFibGVkKCkge1xuICAgIC8vIFRPRE8gc2hvdWxkIHJldHVybiB0cnVlIGlmIHRoZSBzZXJ2aWNlIFwiZmFicmljOC1mb3JnZVwiIGlzIHZhbGlkXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBrdWJlcm5ldGVzIHNlbGVjdGVkIG5hbWVzcGFjZSBvciB0aGUgZGVmYXVsdCBvbmVcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBjdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpIHtcbiAgICB2YXIgaW5qZWN0b3IgPSBIYXd0aW9Db3JlLmluamVjdG9yO1xuICAgIGlmIChpbmplY3Rvcikge1xuICAgICAgdmFyIEt1YmVybmV0ZXNTdGF0ZSA9IGluamVjdG9yLmdldDxhbnk+KFwiS3ViZXJuZXRlc1N0YXRlXCIpIHx8IHt9O1xuICAgICAgcmV0dXJuIEt1YmVybmV0ZXNTdGF0ZS5zZWxlY3RlZE5hbWVzcGFjZSB8fCBkZWZhdWx0TmFtZXNwYWNlO1xuICAgIH1cbiAgICByZXR1cm4gZGVmYXVsdE5hbWVzcGFjZTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBzZXRDdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZShucykge1xuICAgIGlmIChucykge1xuICAgICAgdmFyIEt1YmVybmV0ZXNTdGF0ZSA9IGluamVjdDxhbnk+KFwiS3ViZXJuZXRlc1N0YXRlXCIpIHx8IHt9O1xuICAgICAgS3ViZXJuZXRlc1N0YXRlLnNlbGVjdGVkTmFtZXNwYWNlID0gbnM7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZXMgdGhlIGpzb24gc2NoZW1hXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gY29uZmlndXJlU2NoZW1hKCkge1xuICAgIGFuZ3VsYXIuZm9yRWFjaChzY2hlbWEuZGVmaW5pdGlvbnMsIChkZWZpbml0aW9uLCBuYW1lKSA9PiB7XG4gICAgICB2YXIgcHJvcGVydGllcyA9IGRlZmluaXRpb24ucHJvcGVydGllcztcbiAgICAgIGlmIChwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHZhciBoaWRlUHJvcGVydGllcyA9IFtcImNyZWF0aW9uVGltZXN0YW1wXCIsIFwia2luZFwiLCBcImFwaVZlcnNpb25cIiwgXCJhbm5vdGF0aW9uc1wiLCBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCIsIFwibmFtZXNwYWNlXCIsIFwicmVzb3VyY2VWZXJzaW9uXCIsIFwic2VsZkxpbmtcIiwgXCJ1aWRcIl07XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChoaWRlUHJvcGVydGllcywgKHByb3BlcnR5TmFtZSkgPT4ge1xuICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcGVydHlOYW1lXTtcbiAgICAgICAgICBpZiAocHJvcGVydHkpIHtcbiAgICAgICAgICAgIHByb3BlcnR5W1wiaGlkZGVuXCJdICA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKHByb3BlcnRpZXMsIChwcm9wZXJ0eSwgcHJvcGVydHlOYW1lKSA9PiB7XG4gICAgICAgICAgdmFyIHJlZiA9IHByb3BlcnR5W1wiJHJlZlwiXTtcbiAgICAgICAgICB2YXIgdHlwZSA9IHByb3BlcnR5W1widHlwZVwiXTtcbiAgICAgICAgICBpZiAocmVmICYmICghdHlwZSB8fCB0eXBlID09PSBcIm9iamVjdFwiKSkge1xuICAgICAgICAgICAgcHJvcGVydHlbXCJ0eXBlXCJdID0gcmVmO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodHlwZSA9PT0gXCJhcnJheVwiKSB7XG4gICAgICAgICAgICB2YXIgaXRlbXMgPSBwcm9wZXJ0eVtcIml0ZW1zXCJdO1xuICAgICAgICAgICAgaWYgKGl0ZW1zKSB7XG4gICAgICAgICAgICAgIHZhciByZWYgPSBpdGVtc1tcIiRyZWZcIl07XG4gICAgICAgICAgICAgIHZhciB0eXBlID0gaXRlbXNbXCJ0eXBlXCJdO1xuICAgICAgICAgICAgICBpZiAocmVmICYmICghdHlwZSB8fCB0eXBlID09PSBcIm9iamVjdFwiKSkge1xuICAgICAgICAgICAgICAgIGl0ZW1zW1widHlwZVwiXSA9IHJlZjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHNjaGVtYS5kZWZpbml0aW9ucy5vc19idWlsZF9XZWJIb29rVHJpZ2dlci5wcm9wZXJ0aWVzLnNlY3JldC50eXBlID0gXCJwYXNzd29yZFwiO1xuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogTGV0cyByZW1vdmUgYW55IGVucmljaGVkIGRhdGEgdG8gbGVhdmUgdGhlIG9yaWdpbmFsIGpzb24gaW50YWN0XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gdW5lbnJpY2goaXRlbSkge1xuICAgIHZhciBvID0gXy5jbG9uZURlZXAoaXRlbSk7XG4gICAgYW5ndWxhci5mb3JFYWNoKG8sICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoXCIkXCIpIHx8IGtleS5zdGFydHNXaXRoKFwiX1wiKSkge1xuICAgICAgICBkZWxldGUgb1trZXldO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGRlbGV0ZSBvWydjb25uZWN0VG8nXTtcbiAgICByZXR1cm4gbztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB1bmVucmljaGVkIEpTT04gcmVwcmVzZW50YXRpb24gb2YgYW4gb2JqZWN0XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gdG9SYXdKc29uKGl0ZW0pIHtcbiAgICB2YXIgbyA9IHVuZW5yaWNoKGl0ZW0pO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvLCBudWxsLCAyKTsgLy8gc3BhY2luZyBsZXZlbCA9IDJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB1bmVucmljaGVkIFlBTUwgcmVwcmVzZW50YXRpb24gb2YgYW4gb2JqZWN0XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gdG9SYXdZYW1sKGl0ZW0pIHtcbiAgICB2YXIgbyA9IHVuZW5yaWNoKGl0ZW0pO1xuICAgIHJldHVybiBqc3lhbWwuZHVtcChvLCB7IGluZGVudDogMiB9KTtcbiAgfVxuXG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHdhdGNoKCRzY29wZTogYW55LCAkZWxlbWVudDogYW55LCBraW5kLCBucywgZm4sIGxhYmVsU2VsZWN0b3IgPSBudWxsKSB7XG4gICAgIHZhciBjb25uZWN0aW9uID0gS3ViZXJuZXRlc0FQSS53YXRjaCh7XG4gICAgICAgIGtpbmQ6IGtpbmQsXG4gICAgICAgIG5hbWVzcGFjZTogbnMsXG4gICAgICAgIGxhYmVsU2VsZWN0b3I6IGxhYmVsU2VsZWN0b3IsXG4gICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChvYmplY3RzKSB7XG4gICAgICAgICAgZm4ob2JqZWN0cyk7XG4gICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICAkZWxlbWVudC5vbignJGRlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiU3RhdGljIGNvbnRyb2xsZXJbXCIgKyBraW5kICsgXCIsIFwiICsgbnMgKyBcIl0gZWxlbWVudCBkZXN0cm95ZWRcIik7XG4gICAgICAgICRzY29wZS4kZGVzdHJveSgpO1xuICAgICAgfSk7XG4gICAgICAkc2NvcGUuJG9uKCckZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coXCJTdGF0aWMgY29udHJvbGxlcltcIiArIGtpbmQgKyBcIiwgXCIgKyBucyArIFwiXSBzY29wZSBkZXN0cm95ZWRcIik7XG4gICAgICAgIGNvbm5lY3Rpb24uZGlzY29ubmVjdCgpO1xuICAgICAgfSk7XG4gICAgICB2YXIgb2xkRGVsZXRlU2NvcGVGbiA9ICRzY29wZS5kZWxldGVTY29wZTtcbiAgICAgICRzY29wZS5kZWxldGVTY29wZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgJGVsZW1lbnQucmVtb3ZlKCk7XG4gICAgICAgIGlmIChhbmd1bGFyLmlzRnVuY3Rpb24ob2xkRGVsZXRlU2NvcGVGbikpIHtcbiAgICAgICAgICBvbGREZWxldGVTY29wZUZuKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBjcmVhdGVLdWJlcm5ldGVzQ2xpZW50KGtpbmQsIG5zID0gbnVsbCkge1xuICAgIHZhciBLOFNDbGllbnRGYWN0b3J5ID0gaW5qZWN0PGFueT4oXCJLOFNDbGllbnRGYWN0b3J5XCIpO1xuICAgIGlmICghSzhTQ2xpZW50RmFjdG9yeSkge1xuICAgICAgbG9nLndhcm4oXCJDb3VsZCBub3QgZmluZCBpbmplY3RlZCBLOFNDbGllbnRGYWN0b3J5IVwiKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoa2luZCA9PT0gXCJwcm9qZWN0c1wiIHx8IGtpbmQgPT09IFwibmFtZXNwYWNlc1wiKSB7XG4gICAgICBucyA9IG51bGw7XG4gICAgfSBlbHNlIGlmICghbnMpIHtcbiAgICAgIG5zID0gS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgIH1cbiAgICByZXR1cm4gSzhTQ2xpZW50RmFjdG9yeS5jcmVhdGUoa2luZCwgbnMpO1xuICB9XG5cblxuICBleHBvcnQgZnVuY3Rpb24gY3VycmVudFVzZXJOYW1lKCkge1xuICAgIHZhciB1c2VyRGV0YWlscyA9IEhhd3Rpb09BdXRoLmdldFVzZXJQcm9maWxlKCk7XG4gICAgdmFyIGFuc3dlciA9IG51bGw7XG4gICAgaWYgKHVzZXJEZXRhaWxzKSB7XG4gICAgICBhbnN3ZXIgPSBnZXROYW1lKHVzZXJEZXRhaWxzKTtcbiAgICB9XG4gICAgcmV0dXJuIGFuc3dlciB8fCBcImFkbWluXCI7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlTmFtZXNwYWNlKG5zLCBjbGllbnQ/KSB7XG4gICAgaWYgKCFjbGllbnQpIHtcbiAgICAgIGNsaWVudCA9IGlzT3BlblNoaWZ0ID8gS3ViZXJuZXRlcy5jcmVhdGVLdWJlcm5ldGVzQ2xpZW50KCdwcm9qZWN0cycpIDogS3ViZXJuZXRlcy5jcmVhdGVLdWJlcm5ldGVzQ2xpZW50KCduYW1lc3BhY2VzJyk7XG4gICAgfVxuICAgIGlmIChucyAmJiBucyAhPT0gY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKSkge1xuICAgICAgdmFyIG9iamVjdCA9IHtcbiAgICAgICAgYXBpVmVyc2lvbjogS3ViZXJuZXRlcy5kZWZhdWx0QXBpVmVyc2lvbixcbiAgICAgICAga2luZDogaXNPcGVuU2hpZnQgPyAnUHJvamVjdCcgOiAnTmFtZXNwYWNlJyxcbiAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICBuYW1lOiBucyxcbiAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBjbGllbnQucHV0KG9iamVjdCxcbiAgICAgICAgKGRhdGEpID0+IHtcbiAgICAgICAgICBsb2cuaW5mbyhcIkNyZWF0ZWQgbmFtZXNwYWNlOiBcIiArIG5zKVxuICAgICAgICB9LFxuICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gY3JlYXRlIG5hbWVzcGFjZTogXCIgKyBucyArIFwiOiBcIiArIGFuZ3VsYXIudG9Kc29uKGVycikpO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlUkMob2JqLCBvbkNvbXBsZXRlRm4gPSBudWxsKXtcbiAgICB2YXIgY2xpZW50ID0gIEt1YmVybmV0ZXMuY3JlYXRlS3ViZXJuZXRlc0NsaWVudCgncmVwbGljYXRpb25jb250cm9sbGVycycsJ2RlZmF1bHQnKTtcbiAgICB2YXIgUkNUZW1wbGF0ZSA9IG5ldyByZXNvdXJjZVJDVGVtcGxhdGUoKTtcbiAgICB2YXIgcmNUZW1wbGF0ZSA9IFJDVGVtcGxhdGUuY3JlYXRlUkMob2JqKTtcbiAgICBjbGllbnQucHV0KHJjVGVtcGxhdGUsIGZ1bmN0aW9uKG9iaikge1xuICAgICAgIGNvbnNvbGUubG9nKFwiQ3JlYXRlZDogXCIsIG9iaik7XG4gICAgICAgaWYgKGFuZ3VsYXIuaXNGdW5jdGlvbihvbkNvbXBsZXRlRm4pKSB7XG4gICAgICAgICAgIG9uQ29tcGxldGVGbihvYmopO1xuICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiB1cGRhdGVSZXBsaWNhdGlvbkNvbnRyb2xsZXJMYWJlbHMoJGh0dHAsIEt1YmVybmV0ZXNBcGlVUkwsIHJlcGxpY2F0aW9uQ29udHJvbGxlciwgbmV3TGFiZWxzLCBvbkNvbXBsZXRlRm4gPSBudWxsKXtcbiAgICB2YXIgaWQgPSBnZXROYW1lKHJlcGxpY2F0aW9uQ29udHJvbGxlcik7XG4gICAgdmFyIG5hbWVzcGFjZSA9IGdldE5hbWVzcGFjZShyZXBsaWNhdGlvbkNvbnRyb2xsZXIpIHx8IFwiXCI7XG4gICAgdmFyIHVybCA9IGt1YmVybmV0ZXNVcmxGb3JLaW5kKEt1YmVybmV0ZXNBcGlVUkwsIFwiUmVwbGljYXRpb25Db250cm9sbGVyXCIsIG5hbWVzcGFjZSwgaWQpO1xuICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICB2YXIgZGVzaXJlZExhYmVscyA9IGRhdGEubWV0YWRhdGE7XG4gICAgICAgICAgaWYgKCFkZXNpcmVkTGFiZWxzKSB7XG4gICAgICAgICAgICBkZXNpcmVkTGFiZWxzID0ge307XG4gICAgICAgICAgICBkYXRhLm1ldGFkYXRhID0gZGVzaXJlZExhYmVscztcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVzaXJlZExhYmVscy5sYWJlbHMgPSBuZXdMYWJlbHM7XG4gICAgICAgICAgJGh0dHAucHV0KHVybCwgZGF0YSkuXG4gICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICBsb2cuZGVidWcoXCJ1cGRhdGVkIGNvbnRyb2xsZXIgXCIgKyB1cmwpO1xuICAgICAgICAgICAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKG9uQ29tcGxldGVGbikpIHtcbiAgICAgICAgICAgICAgICBvbkNvbXBsZXRlRm4oKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuXG4gICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBzYXZlIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KS5cbiAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgfSk7XG4gIH1cblxuICAgZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3RPcmFjbGUoJGh0dHAsICR0aW1lb3V0LCB1cmwsIGNvbm5lY3RQYXJhbSwgcmNOYW1lLCBkZWxheVRpbWUpe1xuICAgICAgICR0aW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgJGh0dHAoe1xuICAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgICBtZXRob2Q6J1BPU1QnLFxuICAgICAgICAgICAgICAgcGFyYW1zOntvcmFjbGVOYW1lOiByY05hbWUsIHBhcmFtOiBjb25uZWN0UGFyYW19XG4gICAgICAgICAgIH0pLnN1Y2Nlc3MoZnVuY3Rpb24oZGF0YSxoZWFkZXIsY29uZmlnLHN0YXR1cyl7XG4gICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInN1Y2Nlc3NcIik7XG4gICAgICAgICAgIH0pLmVycm9yKGZ1bmN0aW9uKGRhdGEsaGVhZGVyLGNvbmZpZyxzdGF0dXMpe1xuICAgICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gY29ubmVjdCBcIiArIGNvbm5lY3RQYXJhbSArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgfSk7XG4gICAgICB9LCBkZWxheVRpbWUpO1xuICAgfVxuXG5cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBlbnJpY2hXb3Jrc3BhY2VzKHByb2plY3RzKSB7XG4gICAgYW5ndWxhci5mb3JFYWNoKHByb2plY3RzLCAocHJvamVjdCkgPT4ge1xuICAgICAgZW5yaWNoV29ya3NwYWNlKHByb2plY3QpO1xuICAgIH0pO1xuICAgIHJldHVybiBwcm9qZWN0cztcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlbnJpY2hXb3Jrc3BhY2UoYnVpbGQpIHtcbiAgICBpZiAoYnVpbGQpIHtcbiAgICAgIHZhciBuYW1lID0gS3ViZXJuZXRlcy5nZXROYW1lKGJ1aWxkKTtcbiAgICAgIGJ1aWxkLiRuYW1lID0gbmFtZTtcbiAgICAgIGJ1aWxkLiRzb3J0T3JkZXIgPSAwIC0gYnVpbGQubnVtYmVyO1xuXG4gICAgICB2YXIgbmFtZUFycmF5ID0gbmFtZS5zcGxpdChcIi1cIik7XG4gICAgICB2YXIgbmFtZUFycmF5TGVuZ3RoID0gbmFtZUFycmF5Lmxlbmd0aDtcbiAgICAgIGJ1aWxkLiRzaG9ydE5hbWUgPSAobmFtZUFycmF5TGVuZ3RoID4gNCkgPyBuYW1lQXJyYXkuc2xpY2UoMCwgbmFtZUFycmF5TGVuZ3RoIC0gNCkuam9pbihcIi1cIikgOiBuYW1lLnN1YnN0cmluZygwLCAzMCk7XG5cbiAgICAgIHZhciBsYWJlbHMgPSBLdWJlcm5ldGVzLmdldExhYmVscyhidWlsZCk7XG4gICAgICBidWlsZC4kY3JlYXRpb25EYXRlID0gYXNEYXRlKEt1YmVybmV0ZXMuZ2V0Q3JlYXRpb25UaW1lc3RhbXAoYnVpbGQpKTtcbiAgICAgIGJ1aWxkLiRsYWJlbHNUZXh0ID0gS3ViZXJuZXRlcy5sYWJlbHNUb1N0cmluZyhsYWJlbHMpO1xuXG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBidWlsZC4kcHJvamVjdHNMaW5rID0gVXJsSGVscGVycy5qb2luKFwid29ya3NwYWNlc1wiLCBuYW1lKTtcbiAgICAgICAgYnVpbGQuJHJ1bnRpbWVMaW5rID0gVXJsSGVscGVycy5qb2luKFwia3ViZXJuZXRlcy9uYW1lc3BhY2UvXCIsIG5hbWUsIFwiL2FwcHNcIik7XG4gICAgICAgIGJ1aWxkLiR2aWV3TGluayA9IGJ1aWxkLiRwcm9qZWN0c0xpbms7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBidWlsZDtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBhc0RhdGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPyBuZXcgRGF0ZSh2YWx1ZSkgOiBudWxsO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGVucmljaEplbmtpbnNKb2JzKGpvYnNEYXRhLCBwcm9qZWN0SWQsIGpvYk5hbWUpIHtcbiAgICBpZiAoam9ic0RhdGEpIHtcbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChqb2JzRGF0YS5qb2JzLCAoam9iKSA9PiB7XG4gICAgICAgIGVucmljaEplbmtpbnNKb2Ioam9iLCBwcm9qZWN0SWQsIGpvYk5hbWUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBqb2JzRGF0YTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlbnJpY2hKZW5raW5zSm9iKGpvYiwgcHJvamVjdElkLCBqb2JOYW1lKSB7XG4gICAgaWYgKGpvYikge1xuICAgICAgam9iTmFtZSA9IGpvYk5hbWUgfHwgam9iLm5hbWUgfHwgcHJvamVjdElkO1xuICAgICAgam9iLiRqb2JJZCA9IGpvYk5hbWU7XG4gICAgICBqb2IuJHByb2plY3QgPSBwcm9qZWN0SWQgfHwgam9iTmFtZTtcbiAgICAgIHZhciBsYXN0QnVpbGQgPSBqb2IubGFzdEJ1aWxkO1xuICAgICAgdmFyIGxhc3RCdWlsZFJlc3VsdCA9IGxhc3RCdWlsZCA/IGxhc3RCdWlsZC5yZXN1bHQgOiBcIk5PVF9TVEFSVEVEXCI7XG4gICAgICB2YXIgJGljb25DbGFzcyA9IGNyZWF0ZUJ1aWxkU3RhdHVzSWNvbkNsYXNzKGxhc3RCdWlsZFJlc3VsdCk7XG5cbiAgICAgIGpvYi4kbGFzdEJ1aWxkTnVtYmVyID0gZW5yaWNoSmVua2luc0J1aWxkKGpvYiwgbGFzdEJ1aWxkKTtcbiAgICAgIGpvYi4kbGFzdFN1Y2Nlc3NmdWxCdWlsZE51bWJlciA9IGVucmljaEplbmtpbnNCdWlsZChqb2IsIGpvYi5sYXN0U3VjY2Vzc2Z1bEJ1aWxkKTtcbiAgICAgIGpvYi4kbGFzdEZhaWxlZGxCdWlsZE51bWJlciA9IGVucmljaEplbmtpbnNCdWlsZChqb2IsIGpvYi5sYXN0RmFpbGVkbEJ1aWxkKTtcblxuICAgICAgaWYgKGxhc3RCdWlsZCkge1xuICAgICAgICBqb2IuJGR1cmF0aW9uID0gbGFzdEJ1aWxkLmR1cmF0aW9uO1xuICAgICAgICBqb2IuJHRpbWVzdGFtcCA9IGFzRGF0ZShsYXN0QnVpbGQudGltZXN0YW1wKTtcbiAgICAgIH1cbiAgICAgIHZhciBqb2JVcmwgPSAoam9iIHx8IHt9KS51cmw7XG4gICAgICBpZiAoIWpvYlVybCB8fCAham9iVXJsLnN0YXJ0c1dpdGgoXCJodHRwXCIpKSB7XG4gICAgICAgIHZhciBqZW5raW5zVXJsID0gamVua2luc0xpbmsoKTtcbiAgICAgICAgaWYgKGplbmtpbnNVcmwpIHtcbiAgICAgICAgICBqb2JVcmwgPSBVcmxIZWxwZXJzLmpvaW4oamVua2luc1VybCwgXCJqb2JcIiwgam9iTmFtZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGpvYlVybCkge1xuICAgICAgICBqb2IuJGpvYkxpbmsgPSBqb2JVcmw7XG4gICAgICAgIHZhciB3b3Jrc3BhY2VOYW1lID0gS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgICAgICBqb2IuJHBpcGVsaW5lc0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIGpvYi4kcHJvamVjdCwgXCJqZW5raW5zSm9iXCIsIGpvYk5hbWUsIFwicGlwZWxpbmVzXCIpO1xuICAgICAgICBqb2IuJGJ1aWxkc0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIGpvYi4kcHJvamVjdCwgXCJqZW5raW5zSm9iXCIsIGpvYk5hbWUpO1xuICAgICAgfVxuICAgICAgam9iLiRpY29uQ2xhc3MgPSAkaWNvbkNsYXNzO1xuXG4gICAgICBhbmd1bGFyLmZvckVhY2goam9iLmJ1aWxkcywgKGJ1aWxkKSA9PiB7XG4gICAgICAgIGVucmljaEplbmtpbnNCdWlsZChqb2IsIGJ1aWxkKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gam9iO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUJ1aWxkU3RhdHVzSWNvbkNsYXNzKHJlc3VsdCkge1xuICAgIHZhciAkaWNvbkNsYXNzID0gXCJmYSBmYS1zcGlubmVyIGZhLXNwaW5cIjtcbiAgICBpZiAocmVzdWx0KSB7XG4gICAgICBpZiAocmVzdWx0ID09PSBcIkZBSUxVUkVcIiB8fCByZXN1bHQgPT09IFwiRkFJTEVEXCIpIHtcbiAgICAgICAgLy8gVE9ETyBub3QgYXZhaWxhYmxlIHlldFxuICAgICAgICAkaWNvbkNsYXNzID0gXCJmYSBmYS1leGNsYW1hdGlvbi1jaXJjbGUgcmVkXCI7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gXCJBQk9SVEVEXCIgfHwgcmVzdWx0ID09PSBcIklOVEVSVVBURURcIikge1xuICAgICAgICAkaWNvbkNsYXNzID0gXCJmYSBmYS1jaXJjbGUgZ3JleVwiO1xuICAgICAgfSBlbHNlIGlmIChyZXN1bHQgPT09IFwiU1VDQ0VTU1wiIHx8IHJlc3VsdCA9PT0gXCJDT01QTEVURVwiIHx8IHJlc3VsdCA9PT0gXCJDT01QTEVURURcIikge1xuICAgICAgICAkaWNvbkNsYXNzID0gXCJmYSBmYS1jaGVjay1jaXJjbGUgZ3JlZW5cIjtcbiAgICAgIH0gZWxzZSBpZiAocmVzdWx0ID09PSBcIk5PVF9TVEFSVEVEXCIpIHtcbiAgICAgICAgJGljb25DbGFzcyA9IFwiZmEgZmEtY2lyY2xlLXRoaW4gZ3JleVwiO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJGljb25DbGFzcztcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBjcmVhdGVCdWlsZFN0YXR1c0JhY2tncm91bmRDbGFzcyhyZXN1bHQpIHtcbiAgICB2YXIgJGljb25DbGFzcyA9IFwiYnVpbGQtcGVuZGluZ1wiO1xuICAgIGlmIChyZXN1bHQpIHtcbiAgICAgIGlmIChyZXN1bHQgPT09IFwiRkFJTFVSRVwiIHx8IHJlc3VsdCA9PT0gXCJGQUlMRURcIikge1xuICAgICAgICAkaWNvbkNsYXNzID0gXCJidWlsZC1mYWlsXCI7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gXCJBQk9SVEVEXCIgfHwgcmVzdWx0ID09PSBcIklOVEVSVVBURURcIikge1xuICAgICAgICAkaWNvbkNsYXNzID0gXCJidWlsZC1hYm9ydGVkXCI7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gXCJTVUNDRVNTXCIgfHwgcmVzdWx0ID09PSBcIkNPTVBMRVRFXCIgfHwgcmVzdWx0ID09PSBcIkNPTVBMRVRFRFwiKSB7XG4gICAgICAgICRpY29uQ2xhc3MgPSBcImJ1aWxkLXN1Y2Nlc3NcIjtcbiAgICAgIH0gZWxzZSBpZiAocmVzdWx0ID09PSBcIk5PVF9TVEFSVEVEXCIpIHtcbiAgICAgICAgJGljb25DbGFzcyA9IFwiYnVpbGQtbm90LXN0YXJ0ZWRcIjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICRpY29uQ2xhc3M7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoSmVua2luc0J1aWxkKGpvYiwgYnVpbGQpIHtcbiAgICB2YXIgbnVtYmVyID0gbnVsbDtcbiAgICBpZiAoYnVpbGQpIHtcbiAgICAgIGJ1aWxkLiRkdXJhdGlvbiA9IGJ1aWxkLmR1cmF0aW9uO1xuICAgICAgYnVpbGQuJHRpbWVzdGFtcCA9IGFzRGF0ZShidWlsZC50aW1lc3RhbXApO1xuICAgICAgdmFyIHByb2plY3RJZCA9IGpvYi4kcHJvamVjdDtcbiAgICAgIHZhciBqb2JOYW1lID0gam9iLiRqb2JJZCB8fCBwcm9qZWN0SWQ7XG4gICAgICB2YXIgYnVpbGRJZCA9IGJ1aWxkLmlkO1xuICAgICAgbnVtYmVyID0gYnVpbGQubnVtYmVyO1xuICAgICAgdmFyIHdvcmtzcGFjZU5hbWUgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG5cbiAgICAgIHZhciAkaWNvbkNsYXNzID0gY3JlYXRlQnVpbGRTdGF0dXNJY29uQ2xhc3MoYnVpbGQucmVzdWx0KTtcbiAgICAgIHZhciBqb2JVcmwgPSAoam9iIHx8IHt9KS51cmw7XG4gICAgICBpZiAoIWpvYlVybCB8fCAham9iVXJsLnN0YXJ0c1dpdGgoXCJodHRwXCIpKSB7XG4gICAgICAgIHZhciBqZW5raW5zVXJsID0gamVua2luc0xpbmsoKTtcbiAgICAgICAgaWYgKGplbmtpbnNVcmwpIHtcbiAgICAgICAgICBqb2JVcmwgPSBVcmxIZWxwZXJzLmpvaW4oamVua2luc1VybCwgXCJqb2JcIiwgam9iTmFtZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGpvYlVybCkge1xuICAgICAgICBidWlsZC4kam9iTGluayA9IGpvYlVybDtcbiAgICAgICAgaWYgKGJ1aWxkSWQpIHtcbiAgICAgICAgICAvL2J1aWxkLiRsb2dzTGluayA9IFVybEhlbHBlcnMuam9pbihidWlsZC4kYnVpbGRMaW5rLCBcImNvbnNvbGVcIik7XG4gICAgICAgICAgYnVpbGQuJGxvZ3NMaW5rID0gVXJsSGVscGVycy5qb2luKFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCJwcm9qZWN0c1wiLCBwcm9qZWN0SWQsIFwiamVua2luc0pvYlwiLCBqb2JOYW1lLCBcImxvZ1wiLCBidWlsZElkKTtcbiAgICAgICAgICBidWlsZC4kcGlwZWxpbmVMaW5rID0gVXJsSGVscGVycy5qb2luKFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCJwcm9qZWN0c1wiLCBwcm9qZWN0SWQsIFwiamVua2luc0pvYlwiLCBqb2JOYW1lLCBcInBpcGVsaW5lXCIsIGJ1aWxkSWQpO1xuICAgICAgICAgIGJ1aWxkLiRidWlsZHNMaW5rID0gVXJsSGVscGVycy5qb2luKFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCJwcm9qZWN0c1wiLCBwcm9qZWN0SWQsIFwiamVua2luc0pvYlwiLCBqb2JOYW1lKTtcbiAgICAgICAgICAvL2J1aWxkLiRidWlsZExpbmsgPSBVcmxIZWxwZXJzLmpvaW4oam9iVXJsLCBidWlsZC5pZCk7XG4gICAgICAgICAgYnVpbGQuJGJ1aWxkTGluayA9IGJ1aWxkLiRsb2dzTGluaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnVpbGQuJGljb25DbGFzcyA9ICRpY29uQ2xhc3M7XG4gICAgfVxuICAgIHJldHVybiBudW1iZXI7XG4gIH1cblxuXG4gIGV4cG9ydCBmdW5jdGlvbiBqZW5raW5zTGluaygpIHtcbiAgICB2YXIgU2VydmljZVJlZ2lzdHJ5ID0gS3ViZXJuZXRlcy5pbmplY3Q8YW55PihcIlNlcnZpY2VSZWdpc3RyeVwiKTtcbiAgICBpZiAoU2VydmljZVJlZ2lzdHJ5KSB7XG4gICAgICByZXR1cm4gU2VydmljZVJlZ2lzdHJ5LnNlcnZpY2VMaW5rKGplbmtpbnNTZXJ2aWNlTmFtZSk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGZvcmdlUmVhZHlMaW5rKCkge1xuICAgIHZhciBTZXJ2aWNlUmVnaXN0cnkgPSBLdWJlcm5ldGVzLmluamVjdDxhbnk+KFwiU2VydmljZVJlZ2lzdHJ5XCIpO1xuICAgIGlmIChTZXJ2aWNlUmVnaXN0cnkpIHtcbiAgICAgIHJldHVybiBTZXJ2aWNlUmVnaXN0cnkuc2VydmljZVJlYWR5TGluayhLdWJlcm5ldGVzLmZhYnJpYzhGb3JnZVNlcnZpY2VOYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoSmVua2luc1BpcGVsaW5lSm9iKGpvYiwgcHJvamVjdElkLCBqb2JJZCkge1xuICAgIGlmIChqb2IpIHtcbiAgICAgIGpvYi4kcHJvamVjdCA9IHByb2plY3RJZDtcbiAgICAgIGpvYi4kam9iSWQgPSBqb2JJZDtcbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChqb2IuYnVpbGRzLCAoYnVpbGQpID0+IHtcbiAgICAgICAgZW5yaWNoSmVua2luc1N0YWdlcyhidWlsZCwgcHJvamVjdElkLCBqb2JJZCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoSmVua2luc1N0YWdlcyhidWlsZCwgcHJvamVjdElkLCBqb2JOYW1lKSB7XG4gICAgaWYgKGJ1aWxkKSB7XG4gICAgICBidWlsZC4kcHJvamVjdCA9IHByb2plY3RJZDtcbiAgICAgIGJ1aWxkLiRqb2JJZCA9IGpvYk5hbWU7XG4gICAgICBidWlsZC4kdGltZXN0YW1wID0gYXNEYXRlKGJ1aWxkLnRpbWVJbk1pbGxpcyk7XG4gICAgICBidWlsZC4kaWNvbkNsYXNzID0gY3JlYXRlQnVpbGRTdGF0dXNJY29uQ2xhc3MoYnVpbGQucmVzdWx0IHx8IFwiTk9UX1NUQVJURURcIik7XG5cbiAgICAgIHZhciB3b3Jrc3BhY2VOYW1lID0gS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgICAgdmFyIHBhcmFtZXRlcnMgPSBidWlsZC5wYXJhbWV0ZXJzO1xuICAgICAgdmFyICRwYXJhbWV0ZXJDb3VudCA9IDA7XG4gICAgICB2YXIgJHBhcmFtZXRlclRleHQgPSBcIk5vIHBhcmFtZXRlcnNcIjtcbiAgICAgIGlmIChwYXJhbWV0ZXJzKSB7XG4gICAgICAgICRwYXJhbWV0ZXJDb3VudCA9IF8ua2V5cyhwYXJhbWV0ZXJzKS5sZW5ndGggfHwgMDtcbiAgICAgICAgJHBhcmFtZXRlclRleHQgPSBLdWJlcm5ldGVzLmxhYmVsc1RvU3RyaW5nKHBhcmFtZXRlcnMsIFwiIFwiKTtcbiAgICAgIH1cbiAgICAgIGJ1aWxkLiRwYXJhbWV0ZXJDb3VudCA9ICRwYXJhbWV0ZXJDb3VudDtcbiAgICAgIGJ1aWxkLiRwYXJhbWV0ZXJUZXh0ID0gJHBhcmFtZXRlclRleHQ7XG4gICAgICB2YXIgamVua2luc1VybCA9IGplbmtpbnNMaW5rKCk7XG4gICAgICBpZiAoamVua2luc1VybCkge1xuICAgICAgICB2YXIgdXJsID0gYnVpbGQudXJsO1xuICAgICAgICBpZiAodXJsKSB7XG4vKlxuICAgICAgICAgIGJ1aWxkLiR2aWV3TGluayA9IFVybEhlbHBlcnMuam9pbihqZW5raW5zVXJsLCB1cmwpO1xuICAgICAgICAgIGJ1aWxkLiRsb2dMaW5rID0gVXJsSGVscGVycy5qb2luKGJ1aWxkLiR2aWV3TGluaywgXCJsb2dcIik7XG4qL1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBidWlsZC4kbG9nTGluayA9IFVybEhlbHBlcnMuam9pbihcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdElkLCBcImplbmtpbnNKb2JcIiwgam9iTmFtZSwgXCJsb2dcIiwgYnVpbGQuaWQpO1xuICAgICAgYnVpbGQuJHZpZXdMaW5rID0gYnVpbGQuJGxvZ0xpbms7XG5cbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChidWlsZC5zdGFnZXMsIChzdGFnZSkgPT4ge1xuICAgICAgICBlbnJpY2hKZW5raW5zU3RhZ2Uoc3RhZ2UsIGJ1aWxkKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYnVpbGQ7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZW5yaWNoSmVua2luc1N0YWdlKHN0YWdlLCBidWlsZCA9IG51bGwpIHtcbiAgICBpZiAoc3RhZ2UpIHtcbiAgICAgIGlmIChidWlsZCkge1xuICAgICAgICBzdGFnZS4kYnVpbGRJZCA9IGJ1aWxkLmlkO1xuICAgICAgICBzdGFnZS4kcHJvamVjdCA9IGJ1aWxkLiRwcm9qZWN0O1xuICAgICAgfVxuICAgICAgdmFyIHByb2plY3RJZCA9IGJ1aWxkLiRwcm9qZWN0O1xuICAgICAgdmFyIGpvYk5hbWUgPSBidWlsZC4kam9iSWQgfHwgcHJvamVjdElkO1xuICAgICAgdmFyIGJ1aWxkSWQgPSBidWlsZC5pZDtcbiAgICAgIHZhciB3b3Jrc3BhY2VOYW1lID0gS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgICAgc3RhZ2UuJGJhY2tncm91bmRDbGFzcyA9ICBjcmVhdGVCdWlsZFN0YXR1c0JhY2tncm91bmRDbGFzcyhzdGFnZS5zdGF0dXMpO1xuICAgICAgc3RhZ2UuJGljb25DbGFzcyA9IGNyZWF0ZUJ1aWxkU3RhdHVzSWNvbkNsYXNzKHN0YWdlLnN0YXR1cyk7XG4gICAgICBzdGFnZS4kc3RhcnRUaW1lID0gYXNEYXRlKHN0YWdlLnN0YXJ0VGltZSk7XG4gICAgICBpZiAoIXN0YWdlLmR1cmF0aW9uKSB7XG4gICAgICAgIHN0YWdlLmR1cmF0aW9uID0gMDtcbiAgICAgIH1cbiAgICAgIHZhciBqZW5raW5zVXJsID0gamVua2luc0xpbmsoKTtcbiAgICAgIGlmIChqZW5raW5zVXJsKSB7XG4gICAgICAgIHZhciB1cmwgPSBzdGFnZS51cmw7XG4gICAgICAgIGlmICh1cmwpIHtcbiAgICAgICAgICBzdGFnZS4kdmlld0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oamVua2luc1VybCwgdXJsKTtcbiAgICAgICAgICBzdGFnZS4kbG9nTGluayA9IFVybEhlbHBlcnMuam9pbihzdGFnZS4kdmlld0xpbmssIFwibG9nXCIpO1xuICAgICAgICAgIGlmIChwcm9qZWN0SWQgJiYgYnVpbGRJZCkge1xuICAgICAgICAgICAgc3RhZ2UuJGxvZ0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIHByb2plY3RJZCwgXCJqZW5raW5zSm9iXCIsIGpvYk5hbWUsIFwibG9nXCIsIGJ1aWxkSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBjb250ZXh0ID0gJy93b3Jrc3BhY2VzJztcbiAgZXhwb3J0IHZhciBoYXNoID0gJyMnICsgY29udGV4dDtcbiAgZXhwb3J0IHZhciBwbHVnaW5OYW1lID0gJ0RldmVsb3Blcic7XG4gIGV4cG9ydCB2YXIgcGx1Z2luUGF0aCA9ICdwbHVnaW5zL2RldmVsb3Blci8nO1xuICBleHBvcnQgdmFyIHRlbXBsYXRlUGF0aCA9IHBsdWdpblBhdGggKyAnaHRtbC8nO1xuICBleHBvcnQgdmFyIGxvZzpMb2dnaW5nLkxvZ2dlciA9IExvZ2dlci5nZXQocGx1Z2luTmFtZSk7XG5cbiAgZXhwb3J0IHZhciBqZW5raW5zU2VydmljZU5hbWUgPSBcImplbmtpbnNcIjtcbiAgZXhwb3J0IHZhciBqZW5raW5zU2VydmljZU5hbWVBbmRQb3J0ID0gamVua2luc1NlcnZpY2VOYW1lICsgXCI6aHR0cFwiO1xuXG4gIGV4cG9ydCB2YXIgamVua2luc0h0dHBDb25maWcgPSB7XG4gICAgaGVhZGVyczoge1xuICAgICAgQWNjZXB0OiBcImFwcGxpY2F0aW9uL2pzb24sIHRleHQveC1qc29uLCB0ZXh0L3BsYWluXCJcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgdmFsdWUgaGFzbid0IGNoYW5nZWQgZnJvbSB0aGUgbGFzdCBjYWNoZWQgSlNPTiB2ZXJzaW9uIG9mIHRoaXMgb2JqZWN0XG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gaGFzT2JqZWN0Q2hhbmdlZCh2YWx1ZSwgc3RhdGUpIHtcbiAgICB2YXIganNvbiA9IGFuZ3VsYXIudG9Kc29uKHZhbHVlIHx8IFwiXCIpO1xuICAgIHZhciBvbGRKc29uID0gc3RhdGUuanNvbjtcbiAgICBzdGF0ZS5qc29uID0ganNvbjtcbiAgICByZXR1cm4gIW9sZEpzb24gfHwganNvbiAhPT0gb2xkSnNvbjtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBwcm9qZWN0Rm9yU2NvcGUoJHNjb3BlKSB7XG4gICAgaWYgKCRzY29wZSkge1xuICAgICAgcmV0dXJuICRzY29wZS5idWlsZENvbmZpZyB8fCAkc2NvcGUuZW50aXR5IHx8ICgkc2NvcGUubW9kZWwgfHwge30pLnByb2plY3Q7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG4gIC8qKlxuICAgKiBMZXRzIGxvYWQgdGhlIHByb2plY3QgdmVyc2lvbnMgZm9yIHRoZSBnaXZlbiBuYW1lc3BhY2VcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBsb2FkUHJvamVjdFZlcnNpb25zKCRzY29wZSwgJGVsZW1lbnQsIHByb2plY3QsIGVudiwgbnMsIGFuc3dlciwgY2FjaGVzKSB7XG4gICAgdmFyIHByb2plY3RBbm5vdGF0aW9uID0gXCJwcm9qZWN0XCI7XG4gICAgdmFyIHZlcnNpb25Bbm5vdGF0aW9uID0gXCJ2ZXJzaW9uXCI7XG5cbiAgICB2YXIgcHJvamVjdE5hbWVzcGFjZSA9IHByb2plY3QuJG5hbWVzcGFjZTtcbiAgICB2YXIgcHJvamVjdE5hbWUgPSBwcm9qZWN0LiRuYW1lO1xuXG4gICAgdmFyIGNhY2hlID0gY2FjaGVzW25zXTtcbiAgICBpZiAoIWNhY2hlKSB7XG4gICAgICBjYWNoZSA9IHt9O1xuICAgICAgY2FjaGVzW25zXSA9IGNhY2hlO1xuICAgIH1cblxuICAgIHZhciBzdGF0dXMgPSB7XG4gICAgICByY3M6IFtdLFxuICAgICAgcG9kczogW10sXG4gICAgICByb3V0ZXM6IFtdLFxuICAgICAgc2VydmljZXM6IFtdXG4gICAgfTtcblxuICAgIHZhciBpbWFnZVN0cmVhbVRhZ3MgPSBbXTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU1vZGVsKCkge1xuICAgICAgdmFyIHByb2plY3RJbmZvcyA9IHt9O1xuICAgICAgdmFyIG1vZGVsID0gJHNjb3BlLm1vZGVsIHx8IHt9O1xuXG4gICAgICBhbmd1bGFyLmZvckVhY2goc3RhdHVzLnJjcywgKGl0ZW0pID0+IHtcbiAgICAgICAgdmFyIG1ldGFkYXRhID0gaXRlbS5tZXRhZGF0YSB8fCB7fTtcbiAgICAgICAgdmFyIG5hbWUgPSBtZXRhZGF0YS5uYW1lO1xuICAgICAgICB2YXIgbGFiZWxzID0gbWV0YWRhdGEubGFiZWxzIHx8IHt9O1xuICAgICAgICB2YXIgYW5ub3RhdGlvbnMgPSBtZXRhZGF0YS5hbm5vdGF0aW9ucyB8fCB7fTtcbiAgICAgICAgdmFyIHNwZWMgPSBpdGVtLnNwZWMgfHwge307XG4gICAgICAgIHZhciBzZWxlY3RvciA9IHNwZWMuc2VsZWN0b3I7XG5cbiAgICAgICAgdmFyIHByb2plY3QgPSBsYWJlbHNbcHJvamVjdEFubm90YXRpb25dO1xuICAgICAgICB2YXIgdmVyc2lvbiA9IGxhYmVsc1t2ZXJzaW9uQW5ub3RhdGlvbl07XG5cbiAgICAgICAgLy8gbGV0cyB0cnkgdGhlIFMySSBkZWZhdWx0cy4uLlxuICAgICAgICBpZiAoIXByb2plY3QpIHtcbiAgICAgICAgICBwcm9qZWN0ID0gbGFiZWxzW1wiYXBwXCJdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdmVyc2lvbikge1xuICAgICAgICAgIHZlcnNpb24gPSBhbm5vdGF0aW9uc1tcIm9wZW5zaGlmdC5pby9kZXBsb3ltZW50LWNvbmZpZy5sYXRlc3QtdmVyc2lvblwiXVxuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9qZWN0ICYmIHZlcnNpb24gJiYgcHJvamVjdCA9PT0gcHJvamVjdE5hbWUpIHtcbiAgICAgICAgICB2YXIgcHJvamVjdHMgPSBwcm9qZWN0SW5mb3NbcHJvamVjdF07XG4gICAgICAgICAgaWYgKCFwcm9qZWN0cykge1xuICAgICAgICAgICAgcHJvamVjdHMgPSB7XG4gICAgICAgICAgICAgIHByb2plY3Q6IHByb2plY3QsXG4gICAgICAgICAgICAgIHZlcnNpb25zOiB7fVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHByb2plY3RJbmZvc1twcm9qZWN0XSA9IHByb2plY3RzO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgdmVyc2lvbkluZm8gPSBwcm9qZWN0cy52ZXJzaW9uc1t2ZXJzaW9uXTtcbiAgICAgICAgICBpZiAoIXZlcnNpb25JbmZvKSB7XG4gICAgICAgICAgICB2ZXJzaW9uSW5mbyA9IHtcbiAgICAgICAgICAgICAgcmVwbGljYXRpb25Db250cm9sbGVyczoge31cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBwcm9qZWN0cy52ZXJzaW9uc1t2ZXJzaW9uXSA9IHZlcnNpb25JbmZvO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobmFtZSkge1xuICAgICAgICAgICAgdmVyc2lvbkluZm8ucmVwbGljYXRpb25Db250cm9sbGVyc1tuYW1lXSA9IGl0ZW07XG4gICAgICAgICAgICBpdGVtLiRuYW1lID0gbmFtZTtcbiAgICAgICAgICAgIGlmIChwcm9qZWN0TmFtZXNwYWNlICYmIHByb2plY3ROYW1lKSB7XG4gICAgICAgICAgICAgIGl0ZW0uJHZpZXdMaW5rID0gVXJsSGVscGVycy5qb2luKFwiL3dvcmtzcGFjZXMvXCIsIHByb2plY3ROYW1lc3BhY2UsIFwicHJvamVjdHNcIiwgcHJvamVjdE5hbWUsIFwibmFtZXNwYWNlXCIsIG5zLCBcInJlcGxpY2F0aW9uQ29udHJvbGxlcnNcIiwgbmFtZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBsb2cud2FybihcIk1pc3NpbmcgcHJvamVjdCBkYXRhISBcIiArIHByb2plY3ROYW1lc3BhY2UgKyBcIiBuYW1lIFwiICsgcHJvamVjdE5hbWUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpdGVtLiRzZXJ2aWNlcyA9IFtdO1xuICAgICAgICAgICAgdmFyIHJjTGluayA9IG51bGw7XG4gICAgICAgICAgICBzdGF0dXMuc2VydmljZXMuZm9yRWFjaCgoc2VydmljZSkgPT4ge1xuICAgICAgICAgICAgICB2YXIgcmVwU2VsZWN0b3IgPSBLdWJlcm5ldGVzLmdldFNlbGVjdG9yKGl0ZW0pO1xuICAgICAgICAgICAgICB2YXIgc2VydmljZVNlbGVjdG9yID0gS3ViZXJuZXRlcy5nZXRTZWxlY3RvcihzZXJ2aWNlKTtcbiAgICAgICAgICAgICAgaWYgKHNlcnZpY2VTZWxlY3RvciAmJiByZXBTZWxlY3RvciAmJlxuICAgICAgICAgICAgICAgIEt1YmVybmV0ZXMuc2VsZWN0b3JNYXRjaGVzKHNlcnZpY2VTZWxlY3RvciwgcmVwU2VsZWN0b3IpICYmXG4gICAgICAgICAgICAgICAgS3ViZXJuZXRlcy5nZXROYW1lc3BhY2Uoc2VydmljZSkgPT09IEt1YmVybmV0ZXMuZ2V0TmFtZXNwYWNlKGl0ZW0pKSB7XG4gICAgICAgICAgICAgICAgc3RhdHVzLnJvdXRlcy5mb3JFYWNoKChyb3V0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgdmFyIHNlcnZpY2VOYW1lID0gS3ViZXJuZXRlcy5nZXROYW1lKHNlcnZpY2UpO1xuICAgICAgICAgICAgICAgICAgaWYgKHNlcnZpY2VOYW1lID09PSBLdWJlcm5ldGVzLmdldE5hbWUocm91dGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlcnZpY2VbXCIkcm91dGVcIl0gPSByb3V0ZTtcbiAgICAgICAgICAgICAgICAgICAgc2VydmljZVtcIiRob3N0XCJdID0gQ29yZS5wYXRoR2V0KHJvdXRlLCBbXCJzcGVjXCIsIFwiaG9zdFwiXSk7XG4gICAgICAgICAgICAgICAgICAgIGl0ZW0uJHNlcnZpY2VzLnB1c2goc2VydmljZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcmNMaW5rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMuc2VydmljZUxpbmtVcmwoc2VydmljZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETyBmaW5kIGljb24gZXRjP1xuICAgICAgICAgICAgICAgICAgICAgICAgcmNMaW5rID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBzZXJ2aWNlTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaHJlZjogdXJsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGl0ZW1bXCIkc2VydmljZUxpbmtcIl0gPSByY0xpbms7XG4gICAgICAgICAgfVxuICAgICAgICAgIGl0ZW0uJGJ1aWxkSWQgPSBhbm5vdGF0aW9uc1tcImZhYnJpYzguaW8vYnVpbGQtaWRcIl0gfHwgaXRlbS4kYnVpbGRJZDtcbiAgICAgICAgICBpdGVtLiRidWlsZFVybCA9IGFubm90YXRpb25zW1wiZmFicmljOC5pby9idWlsZC11cmxcIl0gfHwgaXRlbS4kYnVpbGRVcmw7XG4gICAgICAgICAgaXRlbS4kZ2l0Q29tbWl0ID0gYW5ub3RhdGlvbnNbXCJmYWJyaWM4LmlvL2dpdC1jb21taXRcIl0gfHwgaXRlbS4kZ2l0Q29tbWl0O1xuICAgICAgICAgIGl0ZW0uJGdpdFVybCA9IGFubm90YXRpb25zW1wiZmFicmljOC5pby9naXQtdXJsXCJdIHx8IGl0ZW0uJGdpdFVybDtcbiAgICAgICAgICBpdGVtLiRnaXRCcmFuY2ggPSBhbm5vdGF0aW9uc1tcImZhYnJpYzguaW8vZ2l0LWJyYW5jaFwiXSB8fCBpdGVtLiRnaXRCcmFuY2g7XG4gICAgICAgICAgaWYgKCFpdGVtLiRnaXRDb21taXQpIHtcbiAgICAgICAgICAgIHZhciBpbWFnZSA9IGdldEltYWdlKGl0ZW0pO1xuICAgICAgICAgICAgaWYgKGltYWdlKSB7XG4gICAgICAgICAgICAgIGlmICghJHNjb3BlLiRpc1dhdGNoSW1hZ2VzKSB7XG4gICAgICAgICAgICAgICAgJHNjb3BlLiRpc1dhdGNoSW1hZ2VzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLndhdGNoKCRzY29wZSwgJGVsZW1lbnQsIFwiaW1hZ2VzXCIsIG51bGwsIChkYXRhKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpbWFnZVN0cmVhbVRhZ3MgPSBkYXRhO1xuICAgICAgICAgICAgICAgICAgY2hlY2tGb3JNaXNzaW5nTWV0YWRhdGEoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjaGVja0Zvck1pc3NpbmdNZXRhZGF0YSgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldEltYWdlKGl0ZW0pIHtcbiAgICAgICAgICAgICAgdmFyIGltYWdlID0gXCJcIjtcbiAgICAgICAgICAgICAgLy8gbGV0cyBzZWUgaWYgd2UgY2FuIGZpbmQgdGhlIGNvbW1pdCBpZCBmcm9tIGEgUzJJIGltYWdlIG5hbWVcbiAgICAgICAgICAgICAgLy8gVE9ETyBuZWVkcyB0aGlzIGlzc3VlIGZpeGVkIHRvIGZpbmQgaXQgdmlhIGFuIE9wZW5TaGlmdCBhbm5vdGF0aW9uOlxuICAgICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vb3BlbnNoaWZ0L29yaWdpbi9pc3N1ZXMvNjI0MVxuICAgICAgICAgICAgICB2YXIgY29udGFpbmVycyA9IENvcmUucGF0aEdldChpdGVtLCBbXCJzcGVjXCIsIFwidGVtcGxhdGVcIiwgXCJzcGVjXCIsIFwiY29udGFpbmVyc1wiXSk7XG4gICAgICAgICAgICAgIGlmIChjb250YWluZXJzICYmIGNvbnRhaW5lcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5lciA9IGNvbnRhaW5lcnNbMF07XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgICAgaW1hZ2UgPSBjb250YWluZXIuaW1hZ2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBpbWFnZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2tGb3JNaXNzaW5nTWV0YWRhdGEoKSB7XG4gICAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChwcm9qZWN0cy52ZXJzaW9ucywgKHZpKSA9PiB7XG4gICAgICAgICAgICAgICAgYW5ndWxhci5mb3JFYWNoKHZpLnJlcGxpY2F0aW9uQ29udHJvbGxlcnMsIChpdGVtLCBuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoIWl0ZW0uJGdpdENvbW1pdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW1hZ2UgPSBnZXRJbWFnZShpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgYW5ndWxhci5mb3JFYWNoKGltYWdlU3RyZWFtVGFncywgKGltYWdlU3RyZWFtVGFnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW1hZ2VOYW1lID0gaW1hZ2VTdHJlYW1UYWcuZG9ja2VySW1hZ2VSZWZlcmVuY2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2VOYW1lICYmIGltYWdlTmFtZSA9PT0gaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZvdW5kSVNUYWcgPSBpbWFnZVN0cmVhbVRhZztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1hbmlmZXN0SlNPTiA9IGltYWdlU3RyZWFtVGFnLmRvY2tlckltYWdlTWFuaWZlc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYW5pZmVzdEpTT04pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFuaWZlc3QgPSBhbmd1bGFyLmZyb21Kc29uKG1hbmlmZXN0SlNPTikgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhpc3RvcnkgPSBtYW5pZmVzdC5oaXN0b3J5O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoaXN0b3J5ICYmIGhpc3RvcnkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdjEgPSBoaXN0b3J5WzBdLnYxQ29tcGF0aWJpbGl0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2MSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IGFuZ3VsYXIuZnJvbUpzb24odjEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW52ID0gQ29yZS5wYXRoR2V0KGRhdGEsIFtcImNvbmZpZ1wiLCBcIkVudlwiXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChlbnYsIChlbnZFeHApID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW52RXhwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gZW52RXhwLnNwbGl0KFwiPVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID09PSAyICYmIHZhbHVlc1swXSA9PSBcIk9QRU5TSElGVF9CVUlMRF9OQU1FXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1aWxkTmFtZSA9IHZhbHVlc1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJ1aWxkTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uJGJ1aWxkSWQgPSBidWlsZE5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS4kYnVpbGRVcmwgPSBEZXZlbG9wZXIucHJvamVjdFdvcmtzcGFjZUxpbmsobnMsIHByb2plY3ROYW1lLCBcImJ1aWxkTG9ncy9cIiArIGJ1aWxkTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGFiZWxzID0gQ29yZS5wYXRoR2V0KGRhdGEsIFtcImNvbmZpZ1wiLCBcIkxhYmVsc1wiXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYWJlbHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLiRnaXRDb21taXQgPSBsYWJlbHNbXCJpby5vcGVuc2hpZnQuYnVpbGQuY29tbWl0LmlkXCJdIHx8IGl0ZW0uJGdpdENvbW1pdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLiRnaXRDb21taXRBdXRob3IgPSBsYWJlbHNbXCJpby5vcGVuc2hpZnQuYnVpbGQuY29tbWl0LmF1dGhvclwiXSB8fCBpdGVtLiRnaXRDb21taXRBdXRob3I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbS4kZ2l0Q29tbWl0RGF0ZSA9IGxhYmVsc1tcImlvLm9wZW5zaGlmdC5idWlsZC5jb21taXQuZGF0ZVwiXSB8fCBpdGVtLiRnaXRDb21taXREYXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uJGdpdENvbW1pdE1lc3NhZ2UgPSBsYWJlbHNbXCJpby5vcGVuc2hpZnQuYnVpbGQuY29tbWl0Lm1lc3NhZ2VcIl0gfHwgaXRlbS4kZ2l0Q29tbWl0TWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLiRnaXRCcmFuY2ggPSBsYWJlbHNbXCJpby5vcGVuc2hpZnQuYnVpbGQuY29tbWl0LnJlZlwiXSB8fCBpdGVtLiRnaXRCcmFuY2g7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWl0ZW0uJGdpdFVybCAmJiBpdGVtLiRnaXRDb21taXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uJGdpdFVybCA9IERldmVsb3Blci5wcm9qZWN0V29ya3NwYWNlTGluayhucywgcHJvamVjdE5hbWUsIFwid2lraS9jb21taXREZXRhaWwvLy9cIiArIGl0ZW0uJGdpdENvbW1pdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgICB2YXIgc2VsZWN0b3JUZXh0ID0gS3ViZXJuZXRlcy5sYWJlbHNUb1N0cmluZyhzZWxlY3RvciwgXCIsXCIpO1xuICAgICAgICAgICAgdmFyIHBvZExpbmtVcmwgPSBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmsocHJvamVjdE5hbWUpLCBcIm5hbWVzcGFjZVwiLCBucywgXCJwb2RzXCIpO1xuICAgICAgICAgICAgaXRlbS5wb2RzID0gW107XG4gICAgICAgICAgICBpdGVtLiRwb2RDb3VudGVycyA9IEt1YmVybmV0ZXMuY3JlYXRlUG9kQ291bnRlcnMoc2VsZWN0b3IsIHN0YXR1cy5wb2RzLCBpdGVtLnBvZHMsIHNlbGVjdG9yVGV4dCwgcG9kTGlua1VybCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gbGV0cyBjaGVjayBmb3IgYSBwcm9qZWN0IG5hbWUgaWYgd2UgaGF2ZSBsb3RzIG9mIFJDcyB3aXRoIG5vIHBvZHMsIGxldHMgcmVtb3ZlIHRoZW0hXG4gICAgICBhbmd1bGFyLmZvckVhY2gocHJvamVjdEluZm9zLCAocHJvamVjdCwgcHJvamVjdE5hbWUpID0+IHtcbiAgICAgICAgdmFyIHJjc05vUG9kcyA9IFtdO1xuICAgICAgICB2YXIgcmNzV2l0aFBvZHMgPSBbXTtcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKHByb2plY3QudmVyc2lvbnMsICh2ZXJzaW9uSW5mbykgPT4ge1xuICAgICAgICAgIHZhciByY3MgPSB2ZXJzaW9uSW5mby5yZXBsaWNhdGlvbkNvbnRyb2xsZXJzO1xuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChyY3MsIChpdGVtLCBuYW1lKSA9PiB7XG4gICAgICAgICAgICB2YXIgY291bnQgPSBLdWJlcm5ldGVzLnBvZENvdW50ZXJUb3RhbChpdGVtLiRwb2RDb3VudGVycyk7XG4gICAgICAgICAgICBpZiAoY291bnQpIHtcbiAgICAgICAgICAgICAgcmNzV2l0aFBvZHMucHVzaChuYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJjc05vUG9kcy5wdXNoKCgpID0+IHtcbiAgICAgICAgICAgICAgICBkZWxldGUgcmNzW25hbWVdO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyY3NXaXRoUG9kcy5sZW5ndGgpIHtcbiAgICAgICAgICAvLyBsZXRzIHJlbW92ZSBhbGwgdGhlIGVtcHR5IFJDc1xuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChyY3NOb1BvZHMsIChmbikgPT4ge1xuICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGlmIChoYXNPYmplY3RDaGFuZ2VkKHByb2plY3RJbmZvcywgY2FjaGUpKSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhcInByb2plY3QgdmVyc2lvbnMgaGFzIGNoYW5nZWQhXCIpO1xuICAgICAgICBhbnN3ZXJbbnNdID0gcHJvamVjdEluZm9zO1xuICAgICAgfVxuICAgIH1cblxuICAgIEt1YmVybmV0ZXMud2F0Y2goJHNjb3BlLCAkZWxlbWVudCwgXCJyZXBsaWNhdGlvbmNvbnRyb2xsZXJzXCIsIG5zLCAoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgc3RhdHVzLnJjcyA9IGRhdGE7XG4gICAgICAgIHVwZGF0ZU1vZGVsKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgS3ViZXJuZXRlcy53YXRjaCgkc2NvcGUsICRlbGVtZW50LCBcInNlcnZpY2VzXCIsIG5zLCAoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgc3RhdHVzLnNlcnZpY2VzID0gZGF0YTtcbiAgICAgICAgdXBkYXRlTW9kZWwoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBLdWJlcm5ldGVzLndhdGNoKCRzY29wZSwgJGVsZW1lbnQsIFwicm91dGVzXCIsIG5zLCAoZGF0YSkgPT4ge1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgc3RhdHVzLnJvdXRlcyA9IGRhdGE7XG4gICAgICAgIHVwZGF0ZU1vZGVsKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgS3ViZXJuZXRlcy53YXRjaCgkc2NvcGUsICRlbGVtZW50LCBcInBvZHNcIiwgbnMsIChkYXRhKSA9PiB7XG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICBzdGF0dXMucG9kcyA9IGRhdGE7XG4gICAgICAgIHVwZGF0ZU1vZGVsKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG59IiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxubW9kdWxlIERldmVsb3BlciB7XG5cbi8qXG4gIGZ1bmN0aW9uIGhvbWVCcmVhZGNydW1iKCkge1xuICAgIHJldHVybiB7XG4gICAgICBocmVmOiBcIi9ob21lXCIsXG4gICAgICBsYWJlbDogXCJIb21lXCIsXG4gICAgICB0aXRsZTogXCJHbyB0byB0aGUgaG9tZSBwYWdlXCJcbiAgICB9XG4gIH1cbiovXG4gIGZ1bmN0aW9uIGRldmVsb3BCcmVhZGNydW1iKCkge1xuICAgIHJldHVybiB7XG4gICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIvd29ya3NwYWNlc1wiKSxcbiAgICAgIGxhYmVsOiBcIkRldmVsb3BcIixcbiAgICAgIHRpdGxlOiBcIlZpZXcgYWxsIHRoZSBhcHBzIGZvciBhIHByb2plY3RcIlxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gb3BlcmF0ZUJyZWFkY3J1bWIoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi9uYW1lc3BhY2VzXCIpLFxuICAgICAgbGFiZWw6IFwiTWFuYWdlXCIsXG4gICAgICB0aXRsZTogXCJNYW5hZ2UgdGhlIHByb2plY3RzIGFuZCByZXNvdXJjZXMgaW5zaWRlIHRoZW1cIlxuICAgIH07XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gd29ya3NwYWNlTGluaygpIHtcbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL3dvcmtzcGFjZXNcIiwgS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBwcm9qZWN0TGluayhwcm9qZWN0SWQpIHtcbiAgICB2YXIgbGluayA9IHdvcmtzcGFjZUxpbmsoKTtcbiAgICBpZiAocHJvamVjdElkKSB7XG4gICAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKGxpbmssIFwiL3Byb2plY3RzXCIsIHByb2plY3RJZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBsaW5rO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBjcmVhdGVXb3Jrc3BhY2VzQnJlYWRjcnVtYnMoZGV2ZWxvcFBlcnNwZWN0aXZlKSB7XG4vKlxuICAgIGlmIChkZXZlbG9wUGVyc3BlY3RpdmUpIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIC8vaG9tZUJyZWFkY3J1bWIoKSxcbiAgICAgICAgZGV2ZWxvcEJyZWFkY3J1bWIoKVxuICAgICAgXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgLy9ob21lQnJlYWRjcnVtYigpLFxuICAgICAgICBvcGVyYXRlQnJlYWRjcnVtYigpXG4gICAgICBdO1xuICAgIH1cbiovXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlV29ya3NwYWNlc1N1Yk5hdkJhcnMoZGV2ZWxvcFBlcnNwZWN0aXZlKSB7XG4gICAgICByZXR1cm4gYWN0aXZhdGVDdXJyZW50KFtcbiAgICAgICAgZGV2ZWxvcEJyZWFkY3J1bWIoKSxcbiAgICAgICAgb3BlcmF0ZUJyZWFkY3J1bWIoKVxuICAgICAgXSk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlV29ya3NwYWNlQnJlYWRjcnVtYnMoY2hpbGRyZW4gPSBudWxsLCB3b3Jrc3BhY2VOYW1lID0gbnVsbCkge1xuICAgIHZhciBhbnN3ZXIgPSBbXG4gICAgICAvL2hvbWVCcmVhZGNydW1iKCksXG4gICAgICBkZXZlbG9wQnJlYWRjcnVtYigpXG4gICAgXTtcbiAgICBpZiAoIXdvcmtzcGFjZU5hbWUpIHtcbiAgICAgIHdvcmtzcGFjZU5hbWUgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgfVxuICAgIGlmICh3b3Jrc3BhY2VOYW1lKSB7XG4gICAgICBhbnN3ZXIucHVzaChcbiAgICAgICAge1xuICAgICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzL1wiLCB3b3Jrc3BhY2VOYW1lKSxcbiAgICAgICAgICBsYWJlbDogd29ya3NwYWNlTmFtZSxcbiAgICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBwcm9qZWN0OiBcIiArIHdvcmtzcGFjZU5hbWVcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIHJldHVybiBwcm9jZXNzQ2hpbGRyZW4oYW5zd2VyLCBjaGlsZHJlbik7XG4gICAgfVxuICAgIHJldHVybiBhbnN3ZXI7XG4gIH1cblxuXG4gIGV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZpcm9ubWVudEJyZWFkY3J1bWJzKCRzY29wZSwgJGxvY2F0aW9uLCAkcm91dGVQYXJhbXMpIHtcbiAgICB2YXIgbnMgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgdmFyIG5hbWVzcGFjZXNMaW5rID0gVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL2t1YmVybmV0ZXMvbmFtZXNwYWNlXCIpO1xuICAgIHZhciB3b3Jrc3BhY2VOYW1lID0gJHJvdXRlUGFyYW1zLndvcmtzcGFjZTtcbiAgICB2YXIgcHJvamVjdCA9ICRyb3V0ZVBhcmFtcy5wcm9qZWN0O1xuICAgIGlmICh3b3Jrc3BhY2VOYW1lICYmIHByb2plY3QpIHtcbiAgICAgIHZhciBwcm9qZWN0TGluayA9IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdCk7XG4gICAgICAkc2NvcGUuJHByb2plY3RMaW5rID0gcHJvamVjdExpbms7XG4gICAgICAkc2NvcGUuJHByb2plY3ROYW1lc3BhY2VMaW5rID0gVXJsSGVscGVycy5qb2luKHByb2plY3RMaW5rLCBcIm5hbWVzcGFjZVwiLCBucyk7XG4gICAgICBuYW1lc3BhY2VzTGluayA9IFVybEhlbHBlcnMuam9pbihwcm9qZWN0TGluaywgXCJuYW1lc3BhY2VcIik7XG4gICAgICAvLyBUT0RPIHVzZSB0aGUgbG9naWNhbCBuYW1lP1xuICAgICAgdmFyIGVudk5hbWUgPSBucztcbiAgICAgIHZhciBidWlsZENvbmZpZyA9IG51bGw7XG4gICAgICBpZiAoJHNjb3BlLm1vZGVsKSB7XG4gICAgICAgIGJ1aWxkQ29uZmlnID0gJHNjb3BlLm1vZGVsLmdldFByb2plY3QocHJvamVjdCwgd29ya3NwYWNlTmFtZSk7XG4gICAgICAgIGlmIChidWlsZENvbmZpZykge1xuICAgICAgICAgIC8vIGxldHMgZmluZCB0aGUgbGFiZWwgZm9yIHRoZSBuYW1lc3BhY2VcbiAgICAgICAgICB2YXIgZW52ID0gXy5maW5kKGJ1aWxkQ29uZmlnLmVudmlyb25tZW50cywgeyBuYW1lc3BhY2U6IG5zfSk7XG4gICAgICAgICAgaWYgKGVudikge1xuICAgICAgICAgICAgZW52TmFtZSA9IGVudlsnbGFiZWwnXSB8fCBlbnZOYW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgICBsb2cuaW5mbyhcImVudiBmb3VuZDogXCIgKyBlbnYgKyBcIiBmb3IgbmFtZXBwYWNlIFwiICsgbnMgKyBcIiBvbiBidWlsZENvbmZpZzogXCIgKyBidWlsZENvbmZpZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBjaGlsZHJlbiA9IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmssIFwiZW52aXJvbm1lbnRzXCIpLFxuICAgICAgICAgICAgbGFiZWw6IFwiRW52aXJvbm1lbnRzXCIsXG4gICAgICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBlbnZpcm9ubWVudHMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4obmFtZXNwYWNlc0xpbmssIG5zLCBcImFwcHNcIiksXG4gICAgICAgICAgICBsYWJlbDogZW52TmFtZSxcbiAgICAgICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIHJ1bnRpbWUgb2YgdGhlIHdvcmtzcGFjZTogXCIgKyBuc1xuICAgICAgICAgIH1cbiAgICAgICAgICBdO1xuICAgICAgcmV0dXJuIGNyZWF0ZVByb2plY3RCcmVhZGNydW1icyhwcm9qZWN0LCBjaGlsZHJlbiwgd29ya3NwYWNlTmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghd29ya3NwYWNlTmFtZSkge1xuICAgICAgICB3b3Jrc3BhY2VOYW1lID0gS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjdGl2YXRlQ3VycmVudChbXG4gICAgICAgIC8vaG9tZUJyZWFkY3J1bWIoKSxcbiAgICAgICAgb3BlcmF0ZUJyZWFkY3J1bWIoKSxcbiAgICAgICAge1xuICAgICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihuYW1lc3BhY2VzTGluaywgbnMsIFwiYXBwc1wiKSxcbiAgICAgICAgICBsYWJlbDogd29ya3NwYWNlTmFtZSxcbiAgICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBydW50aW1lIG9mIHRoZSB3b3Jrc3BhY2U6IFwiICsgbnNcbiAgICAgICAgfVxuICAgICAgXSk7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVByb2plY3RCcmVhZGNydW1icyhwcm9qZWN0TmFtZSA9IG51bGwsIGNoaWxkcmVuID0gbnVsbCwgd29ya3NwYWNlTmFtZSA9IG51bGwpIHtcbiAgICBpZiAoIXdvcmtzcGFjZU5hbWUpIHtcbiAgICAgIHdvcmtzcGFjZU5hbWUgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgfVxuICAgIHZhciBhbnN3ZXIgPSBjcmVhdGVXb3Jrc3BhY2VCcmVhZGNydW1icyhudWxsLCB3b3Jrc3BhY2VOYW1lKTtcbiAgICBpZiAod29ya3NwYWNlTmFtZSkge1xuICAgICAgaWYgKHByb2plY3ROYW1lKSB7XG4gICAgICAgIGFuc3dlci5wdXNoKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiksXG4gICAgICAgICAgICBsYWJlbDogXCJBcHBzXCIsXG4gICAgICAgICAgICB0aXRsZTogXCJWaWV3IGFsbCB0aGUgYXBwcyBpbiB0aGlzIHByb2plY3RcIlxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBhbnN3ZXIucHVzaChcbiAgICAgICAgICB7XG4gICAgICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIHByb2plY3ROYW1lKSxcbiAgICAgICAgICAgIGxhYmVsOiBwcm9qZWN0TmFtZSxcbiAgICAgICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIHByb2plY3Q6IFwiICsgcHJvamVjdE5hbWVcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJvY2Vzc0NoaWxkcmVuKGFuc3dlciwgY2hpbGRyZW4pO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG5cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlUHJvamVjdFNldHRpbmdzQnJlYWRjcnVtYnMocHJvamVjdE5hbWUsIHdvcmtzcGFjZU5hbWUgPSBudWxsKSB7XG4gICAgdmFyIGNoaWxkcmVuID0gW3tcbiAgICAgIGxhYmVsOiBcIlNldHRpbmdzXCIsXG4gICAgICB0aXRsZTogXCJWaWV3IHRoZSBzZXR0aW5ncyBvZiB0aGlzIGFwcFwiXG4gICAgfV07XG4gICAgaWYgKCFwcm9qZWN0TmFtZSkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gW3tcbiAgICAgICAgbGFiZWw6IFwiTmV3IEFwcFwiLFxuICAgICAgICB0aXRsZTogXCJMZXRzIG1ha2UgYSBuZXcgYXBwXCJcbiAgICAgIH1dO1xuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlUHJvamVjdEJyZWFkY3J1bWJzKHByb2plY3ROYW1lLCBjaGlsZHJlbiwgd29ya3NwYWNlTmFtZSk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlV29ya3NwYWNlU3ViTmF2QmFycygpIHtcbiAgICB2YXIgd29ya3NwYWNlTmFtZSA9IEt1YmVybmV0ZXMuY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcbiAgICByZXR1cm4gYWN0aXZhdGVDdXJyZW50KFtcbiAgICAgIHtcbiAgICAgICAgaHJlZjogVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSksXG4gICAgICAgIGxhYmVsOiBcIkFwcHNcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEtcm9ja2V0XCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIGFwcHMgaW4gdGhpcyBwcm9qZWN0XCJcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGlzVmFsaWQ6ICgpID0+IGplbmtpbnNMaW5rKCksXG4gICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwiamVua2luc0pvYlwiKSxcbiAgICAgICAgbGFiZWw6IFwiQnVpbGRzXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLWNvZGVcIixcbiAgICAgICAgdGl0bGU6IFwiVmlldyB0aGUgYnVpbGRzIGluIHRoaXMgcHJvamVjdFwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIva3ViZXJuZXRlcy9uYW1lc3BhY2VcIiwgd29ya3NwYWNlTmFtZSwgXCJhcHBzXCIpLFxuICAgICAgICBsYWJlbDogXCJSdW50aW1lXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLWdlYXJzXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIHJ1bnRpbWUgcmVzb3VyY2VzIGluIHRoaXMgcHJvamVjdFwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcImRldGFpbFwiKSxcbiAgICAgICAgbGFiZWw6IFwiRGV0YWlsc1wiLFxuICAgICAgICBjbGFzczogXCJmYSBmYS1nZWFyXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIHByb2plY3QgZGV0YWlsc1wiXG4gICAgICB9XG4gICAgXSk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVCdWlsZHNMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lLCBqZW5raW5zSm9iSWQpIHtcbiAgICB3b3Jrc3BhY2VOYW1lID0gd29ya3NwYWNlTmFtZSB8fCBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdE5hbWUsIFwiamVua2luc0pvYlwiLCBqZW5raW5zSm9iSWQpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVByb2plY3RTdWJOYXZCYXJzKHByb2plY3ROYW1lLCBqZW5raW5zSm9iSWQgPSBudWxsLCAkc2NvcGUgPSBudWxsKSB7XG4gICAgdmFyIHdvcmtzcGFjZU5hbWUgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgdmFyIHByb2plY3RMaW5rID0gVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCJwcm9qZWN0c1wiLCBwcm9qZWN0TmFtZSk7XG4gICAgdmFyIGJ1aWxkc0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmssIFwiYnVpbGRzXCIpO1xuICAgIGlmICghamVua2luc0pvYklkKSB7XG4gICAgICBqZW5raW5zSm9iSWQgPSBwcm9qZWN0TmFtZTtcbiAgICB9XG4gICAgdmFyIGplbmtpbnNCdWlsZExpbmsgPSBudWxsO1xuICAgIHZhciBwaXBlbGluZXNMaW5rID0gbnVsbDtcbiAgICBpZiAocHJvamVjdE5hbWUgJiYgamVua2luc0pvYklkKSB7XG4gICAgICBqZW5raW5zQnVpbGRMaW5rID0gY3JlYXRlQnVpbGRzTGluayh3b3Jrc3BhY2VOYW1lLCBwcm9qZWN0TmFtZSwgamVua2luc0pvYklkKTtcbiAgICAgIHBpcGVsaW5lc0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4oamVua2luc0J1aWxkTGluaywgXCJwaXBlbGluZXNcIik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNKZW5raW5zQnVpbGQoKSB7XG4gICAgICB2YXIgYW5zd2VyID0gamVua2luc0xpbmsoKSAmJiBqZW5raW5zQnVpbGRMaW5rO1xuICAgICAgaWYgKGFuc3dlciAmJiAkc2NvcGUpIHtcbiAgICAgICAgdmFyIGVudGl0eSA9IERldmVsb3Blci5wcm9qZWN0Rm9yU2NvcGUoJHNjb3BlKTtcbiAgICAgICAgaWYgKGVudGl0eSkge1xuICAgICAgICAgIHJldHVybiBhbnN3ZXIgJiYgZW50aXR5LiRqZW5raW5zSm9iO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYW5zd2VyO1xuICAgIH1cblxuICAgIHZhciBhbnN3ZXIgPSBbXG4gICAgICB7XG4gICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUpLFxuICAgICAgICBsYWJlbDogXCJBbGwgQXBwc1wiLFxuICAgICAgICBjbGFzczogJ2ZhIGZhLWFuZ2xlLWRvdWJsZS1sZWZ0JyxcbiAgICAgICAgdGl0bGU6IFwiVmlldyB0aGUgYXBwcyBpbiB0aGlzIHByb2plY3RcIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgdGVtcGxhdGU6IGA8ZGl2IG5nLWluY2x1ZGU9XCIncGx1Z2lucy9kZXZlbG9wZXIvaHRtbC9wcm9qZWN0U2VsZWN0b3IuaHRtbCdcIj48L2Rpdj5gXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIHByb2plY3ROYW1lLCBcImVudmlyb25tZW50c1wiKSxcbiAgICAgICAgaXNBY3RpdmU6IChzdWJUYWIsIHBhdGgpID0+IHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwic3ViVGFiOiBcIiwgc3ViVGFiLCBcIiBwYXRoOiBcIiwgcGF0aCk7XG4gICAgICAgICAgaWYgKHBhdGggPT09IHN1YlRhYi5ocmVmKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHJvb3RQYXRoID0gc3ViVGFiLmhyZWYucmVwbGFjZSgvXFwvZW52aXJvbm1lbnRzLywgJycpO1xuICAgICAgICAgIGlmIChwYXRoID09PSByb290UGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSxcbiAgICAgICAgLy9ocmVmOiBVcmxIZWxwZXJzLmpvaW4oXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIHByb2plY3ROYW1lKSxcbiAgICAgICAgbGFiZWw6IFwiRGFzaGJvYXJkXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLXRhY2hvbWV0ZXJcIixcbiAgICAgICAgdGl0bGU6IFwiVmlldyB0aGUgYXBwIGRhc2hib2FyZCBmb3IgdGhlIGFjdGl2aXR5LCBlbnZpcm9ubWVudHMgYW5kIHBpcGVsaW5lc1wiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBpc1ZhbGlkOiAoKSA9PiBpc0plbmtpbnNCdWlsZCgpICYmIHBpcGVsaW5lc0xpbmssXG4gICAgICAgIGlkOiBcInBpcGVsaW5lc1wiLFxuICAgICAgICBocmVmOiBwaXBlbGluZXNMaW5rLFxuICAgICAgICBsYWJlbDogXCJQaXBlbGluZXNcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEtZWxsaXBzaXMtaFwiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBwaXBlbGluZSBidWlsZHMgZm9yIHRoaXMgYXBwXCJcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGlzVmFsaWQ6ICgpID0+ICFpc0plbmtpbnNCdWlsZCgpLFxuICAgICAgICBocmVmOiBidWlsZHNMaW5rLFxuICAgICAgICBsYWJlbDogXCJCdWlsZHNcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEtYmFyc1wiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBidWlsZHMgZm9yIHRoaXMgYXBwXCJcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGlzVmFsaWQ6ICgpID0+IGlzSmVua2luc0J1aWxkKCksXG4gICAgICAgIGlkOiBcImJ1aWxkc1wiLFxuICAgICAgICBocmVmOiBqZW5raW5zQnVpbGRMaW5rLFxuICAgICAgICBsYWJlbDogXCJCdWlsZHNcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEtYmFyc1wiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBKZW5raW5zIGJ1aWxkcyBmb3IgdGhpcyBhcHBcIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaXNWYWxpZDogKCkgPT4gaXNKZW5raW5zQnVpbGQoKSxcbiAgICAgICAgaHJlZjogVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCJwcm9qZWN0c1wiLCBwcm9qZWN0TmFtZSwgXCJqZW5raW5zSm9iXCIsIGplbmtpbnNKb2JJZCwgXCJtZXRyaWNzXCIpLFxuICAgICAgICBsYWJlbDogXCJNZXRyaWNzXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLWJhci1jaGFydFwiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBtZXRyaWNzIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSxcbi8qXG4gICAgICB7XG4gICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdE5hbWUsIFwidG9vbHNcIiksXG4gICAgICAgIGxhYmVsOiBcIlRvb2xzXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIHRvb2xzIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSxcbiovXG4gICAgICB7XG4gICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdE5hbWUsIFwiYnVpbGRDb25maWdFZGl0XCIpLFxuICAgICAgICBsYWJlbDogXCJTZXR0aW5nc1wiLFxuICAgICAgICBjbGFzczogXCJmYSBmYS1jb2dcIixcbiAgICAgICAgdGl0bGU6IFwiVmlldyB0aGUgYXBwIGNvbmZpZ3VyYXRpb25cIixcbiAgICAgICAgaXNBY3RpdmU6IChzdWJUYWIsIHBhdGgpID0+IHtcbiAgICAgICAgICBpZiAoXy5lbmRzV2l0aChwYXRoLCAnL2J1aWxkQ29uZmlnRWRpdCcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKF8uZW5kc1dpdGgocGF0aCwgJy9mb3JnZS9zZWNyZXRzJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoXy5lbmRzV2l0aChwYXRoLCAnL2ZvcmdlL2NvbW1hbmQvZGV2b3BzLWVkaXQnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIF07XG5cbiAgICB2YXIgY29udGV4dCA9IHtcbiAgICAgIHdvcmtzcGFjZU5hbWU6IHdvcmtzcGFjZU5hbWUsXG4gICAgICBwcm9qZWN0TmFtZTogcHJvamVjdE5hbWUsXG4gICAgICBwcm9qZWN0TGluazogcHJvamVjdExpbmssXG4gICAgICBqZW5raW5zSm9iSWQ6IGplbmtpbnNKb2JJZCxcbiAgICAgICRzY29wZTogJHNjb3BlXG4gICAgfTtcbiAgICBhbmd1bGFyLmZvckVhY2goY3VzdG9tUHJvamVjdFN1YlRhYkZhY3RvcmllcywgKGZuKSA9PiB7XG4gICAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKGZuKSkge1xuICAgICAgICB2YXIgc3VidGFiID0gZm4oY29udGV4dCk7XG4gICAgICAgIGlmIChzdWJ0YWIpIHtcbiAgICAgICAgICBpZiAoYW5ndWxhci5pc0FycmF5KHN1YnRhYikpIHtcbiAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChzdWJ0YWIsICh0KSA9PiB7XG4gICAgICAgICAgICAgIGFuc3dlci5wdXNoKHQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFuc3dlci5wdXNoKHN1YnRhYik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYWN0aXZhdGVDdXJyZW50KGFuc3dlcik7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlUHJvamVjdFNldHRpbmdzU3ViTmF2QmFycyhwcm9qZWN0TmFtZSwgamVua2luc0pvYklkID0gbnVsbCkge1xuICAgIGlmICghcHJvamVjdE5hbWUpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdmFyIHdvcmtzcGFjZU5hbWUgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgdmFyIHByb2plY3RMaW5rID0gVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCJwcm9qZWN0c1wiLCBwcm9qZWN0TmFtZSk7XG4gICAgaWYgKCFqZW5raW5zSm9iSWQpIHtcbiAgICAgIGplbmtpbnNKb2JJZCA9IHByb2plY3ROYW1lO1xuICAgIH1cbiAgICB2YXIgYW5zd2VyID0gW1xuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIHByb2plY3ROYW1lLCBcImJ1aWxkQ29uZmlnRWRpdFwiKSxcbiAgICAgICAgbGFiZWw6IFwiQ29yZVwiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBjb3JlIGJ1aWxkIGNvbmZpZ3VyYXRpb25cIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaHJlZjogcHJvamVjdFNlY3JldHNMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lKSxcbiAgICAgICAgbGFiZWw6IFwiU2VjcmV0c1wiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IG9yIGNoYW5nZSB0aGUgc2VjcmV0cyB1c2VkIHRvIGVkaXQgc291cmNlIGNvZGUgaW4gdGhlIHNvdXJjZSBjb250cm9sIHN5c3RlbVwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBlZGl0UGlwZWxpbmVMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lKSxcbiAgICAgICAgbGFiZWw6IFwiUGlwZWxpbmVcIixcbiAgICAgICAgdGl0bGU6IFwiVmlldyB0aGUgRGV2T3BzIGFuZCBwaXBlbGluZSBjb25maWd1cmF0aW9uXCJcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGlzVmFsaWQ6ICgpID0+IGZvcmdlUHJvamVjdEhhc0J1aWxkZXIoXCJtYXZlblwiKSxcbiAgICAgICAgaHJlZjogZWRpdE1hdmVuQnVpbGRMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lKSxcbiAgICAgICAgbGFiZWw6IFwiTWF2ZW5cIixcbiAgICAgICAgdGl0bGU6IFwiVmlldyB0aGUgTWF2ZW4gYnVpbGQgY29uZmlndXJhdGlvblwiXG4gICAgICB9XG4gICAgXTtcbiAgICByZXR1cm4gYWN0aXZhdGVDdXJyZW50KGFuc3dlcik7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZm9yZ2VQcm9qZWN0SGFzQnVpbGRlcihuYW1lKSB7XG4gICAgdmFyIGZvcmdlUHJvamVjdCA9IEt1YmVybmV0ZXMuaW5qZWN0PGFueT4oXCJGb3JnZVByb2plY3RcIik7XG4gICAgaWYgKGZvcmdlUHJvamVjdCkge1xuICAgICAgcmV0dXJuIGZvcmdlUHJvamVjdC5oYXNCdWlsZGVyKG5hbWUpO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZm9yZ2VQcm9qZWN0SGFzUGVyc3BlY3RpdmUobmFtZSkge1xuICAgIHZhciBmb3JnZVByb2plY3QgPSBLdWJlcm5ldGVzLmluamVjdDxhbnk+KFwiRm9yZ2VQcm9qZWN0XCIpO1xuICAgIGlmIChmb3JnZVByb2plY3QpIHtcbiAgICAgIHJldHVybiBmb3JnZVByb2plY3QuaGFzUGVyc3BlY3RpdmUobmFtZSk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlZGl0UGlwZWxpbmVMaW5rU2NvcGUoJHNjb3BlKSB7XG4gICAgcmV0dXJuIGVkaXRQaXBlbGluZUxpbmsoJHNjb3BlLm5hbWVzcGFjZSwgJHNjb3BlLnByb2plY3RJZCB8fCAkc2NvcGUucHJvamVjdE5hbWUgfHwgJHNjb3BlLnByb2plY3QpO1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVByb2plY3RMaW5rKHdvcmtzcGFjZU5hbWUgPSBudWxsKSB7XG4gICAgaWYgKCF3b3Jrc3BhY2VOYW1lKSB7XG4gICAgICB3b3Jrc3BhY2VOYW1lID0gS3ViZXJuZXRlcy5jdXJyZW50S3ViZXJuZXRlc05hbWVzcGFjZSgpO1xuICAgIH1cbiAgICByZXR1cm4gVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL3dvcmtzcGFjZXNcIiwgd29ya3NwYWNlTmFtZSwgXCIvZm9yZ2UvY3JlYXRlUHJvamVjdFwiKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBlZGl0UGlwZWxpbmVMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lKSB7XG4gICAgcmV0dXJuIHByb2plY3RXb3Jrc3BhY2VMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lLCBcImZvcmdlL2NvbW1hbmQvZGV2b3BzLWVkaXRcIik7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZWRpdE1hdmVuQnVpbGRMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lKSB7XG4gICAgcmV0dXJuIHByb2plY3RXb3Jrc3BhY2VMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lLCBcImZvcmdlL2NvbW1hbmQvZmFicmljOC1zZXR1cFwiKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiBwcm9qZWN0U2VjcmV0c0xpbmsod29ya3NwYWNlTmFtZSwgcHJvamVjdE5hbWUpIHtcbiAgICByZXR1cm4gcHJvamVjdFdvcmtzcGFjZUxpbmsod29ya3NwYWNlTmFtZSwgcHJvamVjdE5hbWUsIFwiZm9yZ2Uvc2VjcmV0c1wiLCBmYWxzZSk7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gc2VjcmV0c05hbWVzcGFjZUxpbmsod29ya3NwYWNlTmFtZSwgcHJvamVjdE5hbWUsIHNlY3JldHNOYW1lc3BhY2UpIHtcbiAgICB2YXIgcHJlZml4ID0gcHJvamVjdFdvcmtzcGFjZUxpbmsod29ya3NwYWNlTmFtZSwgcHJvamVjdE5hbWUsIFwiXCIpIHx8IFwia3ViZXJuZXRlc1wiO1xuICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4ocHJlZml4LCBcIm5hbWVzcGFjZVwiLCBzZWNyZXRzTmFtZXNwYWNlLCBcInNlY3JldHNcIik7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gcHJvamVjdFdvcmtzcGFjZUxpbmsod29ya3NwYWNlTmFtZSwgcHJvamVjdE5hbWUsIHBhdGgsIGlnbm9yZUJsYW5rUHJvamVjdCA9IHRydWUpIHtcbiAgICBpZiAoaWdub3JlQmxhbmtQcm9qZWN0ICYmICFwcm9qZWN0TmFtZSkge1xuICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIGlmICghd29ya3NwYWNlTmFtZSkge1xuICAgICAgd29ya3NwYWNlTmFtZSA9IEt1YmVybmV0ZXMuY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcbiAgICB9XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdE5hbWUsIHBhdGgpO1xuICB9XG5cbiAgZXhwb3J0IHZhciBjdXN0b21Qcm9qZWN0U3ViVGFiRmFjdG9yaWVzID0gW107XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUplbmtpbnNCcmVhZGNydW1icyhwcm9qZWN0TmFtZSwgam9iSWQsIGJ1aWxkSWQpIHtcbiAgICB2YXIgd29ya3NwYWNlTmFtZSA9IEt1YmVybmV0ZXMuY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcbiAgICB2YXIgY2hpbGRyZW4gPSBbXG4gICAgICB7XG4gICAgICAgIGlkOiBcImJ1aWxkc1wiLFxuICAgICAgICBocmVmOiBjcmVhdGVCdWlsZHNMaW5rKHdvcmtzcGFjZU5hbWUsIHByb2plY3ROYW1lLCBqb2JJZCksXG4gICAgICAgIGxhYmVsOiBcIkJ1aWxkc1wiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBidWlsZHMgZm9yIHRoaXMgYXBwXCJcbiAgICAgIH1cbiAgICBdO1xuICAgIGlmIChidWlsZElkKSB7XG4gICAgICBjaGlsZHJlbi5wdXNoKHtcbiAgICAgICAgaWQ6IFwiXCIsXG4gICAgICAgIGhyZWY6IFwiXCIsXG4gICAgICAgIGxhYmVsOiBcIiNcIiArIGJ1aWxkSWQsXG4gICAgICAgIHRpdGxlOiBcIkJ1aWxkICNcIiArIGJ1aWxkSWRcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlUHJvamVjdEJyZWFkY3J1bWJzKHByb2plY3ROYW1lLCBjaGlsZHJlbik7XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlSmVua2luc1N1Yk5hdkJhcnMocHJvamVjdE5hbWUsIGplbmtpbnNKb2JJZCwgYnVpbGRJZCwgZXh0cmFPcHRpb246IGFueSA9IG51bGwpIHtcbiAgICB2YXIgYW5zd2VyID0gY3JlYXRlUHJvamVjdFN1Yk5hdkJhcnMocHJvamVjdE5hbWUsIGplbmtpbnNKb2JJZCk7XG4gICAgaWYgKGV4dHJhT3B0aW9uKSB7XG4gICAgICBleHRyYU9wdGlvbi5hY3RpdmUgPSB0cnVlO1xuICAgICAgYW5zd2VyLnB1c2goZXh0cmFPcHRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG5cblxuICBleHBvcnQgZnVuY3Rpb24gY3JlYXRlRW52aXJvbm1lbnRTdWJOYXZCYXJzKCRzY29wZSwgJGxvY2F0aW9uLCAkcm91dGVQYXJhbXMpIHtcbiAgICB2YXIgbnMgPSBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCk7XG4gICAgdmFyIHdvcmtzcGFjZU5hbWUgPSAkcm91dGVQYXJhbXMud29ya3NwYWNlO1xuICAgIHZhciBwcm9qZWN0ID0gJHJvdXRlUGFyYW1zLnByb2plY3Q7XG4gICAgdmFyIHByb2plY3RMaW5rID0gVXJsSGVscGVycy5qb2luKEhhd3Rpb0NvcmUuZG9jdW1lbnRCYXNlKCksIFwiL2t1YmVybmV0ZXNcIik7XG4gICAgaWYgKHdvcmtzcGFjZU5hbWUgJiYgcHJvamVjdCkge1xuICAgICAgcHJvamVjdExpbmsgPSBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIvd29ya3NwYWNlc1wiLCB3b3Jrc3BhY2VOYW1lLCBcInByb2plY3RzXCIsIHByb2plY3QpO1xuICAgIH1cbiAgICB2YXIgbmFtZXNwYWNlc0xpbmsgPSBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmssIFwibmFtZXNwYWNlXCIpO1xuICAgIHJldHVybiBhY3RpdmF0ZUN1cnJlbnQoW1xuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmssIFwiZW52aXJvbm1lbnRzXCIpLFxuICAgICAgICBsYWJlbDogXCI8PCBCYWNrIFRvIEFwcFwiLFxuICAgICAgICB0aXRsZTogXCJHbyBiYWNrIHRvIHRoZSBEYXNoYm9hcmQgZm9yIHRoaXMgQXBwXCIsXG4gICAgICAgIGlzVmFsaWQ6ICgpID0+IHByb2plY3RcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihuYW1lc3BhY2VzTGluaywgbnMsIFwiYXBwc1wiKSxcbiAgICAgICAgbGFiZWw6IFwiT3ZlcnZpZXdcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEtbGlzdFwiLFxuICAgICAgICB0aXRsZTogXCJPdmVydmlldyBvZiBhbGwgdGhlIGFwcHMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4obmFtZXNwYWNlc0xpbmssIG5zLCBcInNlcnZpY2VzXCIpLFxuICAgICAgICBsYWJlbDogXCJTZXJ2aWNlc1wiLFxuICAgICAgICBjbGFzczogXCJmYSBmYS1wbHVnXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIGFwcHMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4obmFtZXNwYWNlc0xpbmssIG5zLCBcInJlcGxpY2F0aW9uQ29udHJvbGxlcnNcIiksXG4gICAgICAgIGxhYmVsOiBcIkNvbnRyb2xsZXJzXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLWNsb25lXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIFJlcGxpY2F0aW9uIENvbnRyb2xsZXJzIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaHJlZjogVXJsSGVscGVycy5qb2luKG5hbWVzcGFjZXNMaW5rLCBucywgXCJwb2RzXCIpLFxuICAgICAgICBsYWJlbDogXCJQb2RzXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLXB1enpsZS1waWVjZVwiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBwb2RzIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaHJlZjogVXJsSGVscGVycy5qb2luKG5hbWVzcGFjZXNMaW5rLCBucywgXCJldmVudHNcIiksXG4gICAgICAgIGxhYmVsOiBcIkV2ZW50c1wiLFxuICAgICAgICBjbGFzczogXCJmYSBmYS1uZXdzcGFwZXItb1wiLFxuICAgICAgICB0aXRsZTogXCJWaWV3IHRoZSBldmVudHMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4obmFtZXNwYWNlc0xpbmssIG5zLCBcInNlY3JldHNcIiksXG4gICAgICAgIGxhYmVsOiBcIlNlY3JldHNcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEta2V5XCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIHNlY3JldHMgZm9yIHRoaXMgcHJvamVjdFwiXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBocmVmOiBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIva3ViZXJuZXRlcy9ob3N0c1wiKSxcbiAgICAgICAgbGFiZWw6IFwiTm9kZXNcIixcbiAgICAgICAgY2xhc3M6IFwiZmEgZmEtc2VydmVyXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgdGhlIG5vZGVzIGZvciB0aGlzIHByb2plY3RcIlxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaHJlZjogVXJsSGVscGVycy5qb2luKG5hbWVzcGFjZXNMaW5rLCBucywgXCJvdmVydmlld1wiKSxcbiAgICAgICAgbGFiZWw6IFwiRGlhZ3JhbVwiLFxuICAgICAgICBjbGFzczogXCJmYSBmYS1zaXRlbWFwXCIsXG4gICAgICAgIHRpdGxlOiBcIlZpZXcgYWxsIHRoZSBvYmplY3RzIGluIHRoaXMgcHJvamVjdCBhbmQgdGhlaXIgcmVsYXRpb25zaGlwXCJcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGhyZWY6IFVybEhlbHBlcnMuam9pbihuYW1lc3BhY2VzTGluaywgbnMsIFwiYW5ncnlQb2RzXCIpLFxuICAgICAgICBsYWJlbDogXCJBbmdyeSBQb2RzXCIsXG4gICAgICAgIGNsYXNzOiBcImZhIGZhLWdhbWVwYWRcIixcbiAgICAgICAgdGl0bGU6IFwiVHJ5IHRoZSBBbmdyeSBQb2RzIGdhbWUhXCJcbiAgICAgIH0sXG4gICAgXSk7XG4gIH1cblxuXG4gIGV4cG9ydCBmdW5jdGlvbiBuYW1lc3BhY2VMaW5rKCRzY29wZSwgJHJvdXRlUGFyYW1zLCBwYXRoID0gbnVsbCkge1xuICAgIHZhciBucyA9IEt1YmVybmV0ZXMuY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcbiAgICB2YXIgd29ya3NwYWNlTmFtZSA9ICRyb3V0ZVBhcmFtcy53b3Jrc3BhY2U7XG4gICAgdmFyIHByb2plY3QgPSAkcm91dGVQYXJhbXMucHJvamVjdDtcbiAgICB2YXIgcHJvamVjdExpbmsgPSBVcmxIZWxwZXJzLmpvaW4oSGF3dGlvQ29yZS5kb2N1bWVudEJhc2UoKSwgXCIva3ViZXJuZXRlc1wiKTtcbiAgICBpZiAod29ya3NwYWNlTmFtZSAmJiBwcm9qZWN0KSB7XG4gICAgICBwcm9qZWN0TGluayA9IFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCBcIi93b3Jrc3BhY2VzXCIsIHdvcmtzcGFjZU5hbWUsIFwicHJvamVjdHNcIiwgcHJvamVjdCk7XG4gICAgfVxuICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4ocHJvamVjdExpbmssIFwibmFtZXNwYWNlXCIsIG5zLCBwYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHRoZSBVUkwgcXVlcnkgc3RyaW5nIGlmIGl0cyBpbnNpZGUgdGhlIGdpdmVuIHRleHRcbiAgICovXG4gIGZ1bmN0aW9uIHRyaW1RdWVyeSh0ZXh0KSB7XG4gICAgaWYgKHRleHQpIHtcbiAgICAgIHZhciBpZHggPSB0ZXh0LmluZGV4T2YoXCI/XCIpO1xuICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgIHJldHVybiB0ZXh0LnN1YnN0cmluZygwLCBpZHgpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFjdGl2YXRlQ3VycmVudChuYXZCYXJJdGVtcykge1xuICAgIG5hdkJhckl0ZW1zID0gXy5jb21wYWN0KG5hdkJhckl0ZW1zKTtcbiAgICB2YXIgaW5qZWN0b3IgPSBIYXd0aW9Db3JlLmluamVjdG9yO1xuICAgIHZhciAkbG9jYXRpb24gPSBpbmplY3RvciA/IGluamVjdG9yLmdldDxuZy5JTG9jYXRpb25TZXJ2aWNlPihcIiRsb2NhdGlvblwiKSA6IG51bGw7XG4gICAgaWYgKCRsb2NhdGlvbikge1xuICAgICAgdmFyIHBhdGggPSB0cmltUXVlcnkoJGxvY2F0aW9uLnBhdGgoKSk7XG4gICAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICAgIGZ1bmN0aW9uIG1ha2VBY3RpdmUoaXRlbSkge1xuICAgICAgICBpdGVtLmFjdGl2ZSA9IHRydWU7XG4gICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGFuZ3VsYXIuZm9yRWFjaChuYXZCYXJJdGVtcywgKGl0ZW0pID0+IHtcbiAgICAgICAgaWYgKGl0ZW0pIHtcbiAgICAgICAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKGl0ZW0uaXNBY3RpdmUpKSB7XG4gICAgICAgICAgICBpZiAoIWZvdW5kICYmIGl0ZW0uaXNBY3RpdmUoaXRlbSwgcGF0aCkpIHtcbiAgICAgICAgICAgICAgbWFrZUFjdGl2ZShpdGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGhyZWYgPSBpdGVtLmhyZWY7XG4gICAgICAgICAgICB2YXIgdHJpbUhyZWYgPSB0cmltUXVlcnkoaHJlZik7XG4gICAgICAgICAgICBpZiAoIWZvdW5kICYmIHRyaW1IcmVmICYmIHRyaW1IcmVmID09PSBwYXRoKSB7XG4gICAgICAgICAgICAgIG1ha2VBY3RpdmUoaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5hdkJhckl0ZW1zO1xuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc0NoaWxkcmVuKGFuc3dlciwgY2hpbGRyZW4pIHtcbiAgICBpZiAoY2hpbGRyZW4pIHtcbiAgICAgIGlmIChhbmd1bGFyLmlzQXJyYXkoY2hpbGRyZW4pKSB7XG4gICAgICAgIGFuc3dlciA9IGFuc3dlci5jb25jYXQoY2hpbGRyZW4pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYW5zd2VyLnB1c2goY2hpbGRyZW4pO1xuICAgICAgfVxuICAgIH1cbiAgICBhY3RpdmF0ZUN1cnJlbnQoYW5zd2VyKTtcbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XHJcbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9rdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxyXG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxyXG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVySGVscGVycy50c1wiLz5cclxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XHJcblxyXG5tb2R1bGUgRGV2ZWxvcGVyIHtcclxuICAgLyogZXhwb3J0IHZhciBEYXRhT3ZlclZpZXcgPSBjb250cm9sbGVyKFwiRGF0YU92ZXJWaWV3XCIsXHJcbiAgICAgICAgW1wiJHNjb3BlXCIsICBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgKCRzY29wZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0KSA9PiB7XHJcbiAgICAgICAgICAgICRzY29wZS50cmVlT3B0aW9ucyA9IHtcclxuICAgICAgICAgICAgICAgIG5vZGVDaGlsZHJlbjogXCJjaGlsZHJlblwiLFxyXG4gICAgICAgICAgICAgICAgZGlyU2VsZWN0YWJsZTogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGluamVjdENsYXNzZXM6IHtcclxuICAgICAgICAgICAgICAgICAgICB1bDogXCJhMVwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGxpOiBcImEyXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgbGlTZWxlY3RlZDogXCJhN1wiLFxyXG4gICAgICAgICAgICAgICAgICAgIGlFeHBhbmRlZDogXCJhM1wiLFxyXG4gICAgICAgICAgICAgICAgICAgIGlDb2xsYXBzZWQ6IFwiYTRcIixcclxuICAgICAgICAgICAgICAgICAgICBpTGVhZjogXCJhNVwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsOiBcImE2XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgbGFiZWxTZWxlY3RlZDogXCJhOFwiXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICRzY29wZS5kYXRhRm9yVGhlVHJlZSA9XHJcbiAgICAgICAgICAgICAgICBbXHJcbiAgICAgICAgICAgICAgICAgICAgeyBcIm5hbWVcIiA6IFwiSm9lXCIsIFwiYWdlXCIgOiBcIjIxXCIsIFwiY2hpbGRyZW5cIiA6IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgeyBcIm5hbWVcIiA6IFwiU21pdGhcIiwgXCJhZ2VcIiA6IFwiNDJcIiwgXCJjaGlsZHJlblwiIDogW10gfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgeyBcIm5hbWVcIiA6IFwiR2FyeVwiLCBcImFnZVwiIDogXCIyMVwiLCBcImNoaWxkcmVuXCIgOiBbXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IFwibmFtZVwiIDogXCJKZW5pZmVyXCIsIFwiYWdlXCIgOiBcIjIzXCIsIFwiY2hpbGRyZW5cIiA6IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IFwibmFtZVwiIDogXCJEYW5pXCIsIFwiYWdlXCIgOiBcIjMyXCIsIFwiY2hpbGRyZW5cIiA6IFtdIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeyBcIm5hbWVcIiA6IFwiTWF4XCIsIFwiYWdlXCIgOiBcIjM0XCIsIFwiY2hpbGRyZW5cIiA6IFtdIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIF19XHJcbiAgICAgICAgICAgICAgICAgICAgXX0sXHJcbiAgICAgICAgICAgICAgICAgICAgeyBcIm5hbWVcIiA6IFwiQWxiZXJ0XCIsIFwiYWdlXCIgOiBcIjMzXCIsIFwiY2hpbGRyZW5cIiA6IFtdIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgeyBcIm5hbWVcIiA6IFwiUm9uXCIsIFwiYWdlXCIgOiBcIjI5XCIsIFwiY2hpbGRyZW5cIiA6IFtdIH1cclxuICAgICAgICAgICAgICAgIF07XHJcbiAgICAgICAgfV0pOyovXHJcbn1cclxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCB2YXIgX21vZHVsZSA9IGFuZ3VsYXIubW9kdWxlKHBsdWdpbk5hbWUsIFsnaGF3dGlvLWNvcmUnLCAnaGF3dGlvLXVpJywgJ3VpLmNvZGVtaXJyb3InLCAnbnZkMycsICd0cmVlQ29udHJvbCddKTtcbiAgZXhwb3J0IHZhciBjb250cm9sbGVyID0gUGx1Z2luSGVscGVycy5jcmVhdGVDb250cm9sbGVyRnVuY3Rpb24oX21vZHVsZSwgcGx1Z2luTmFtZSk7XG4gIGV4cG9ydCB2YXIgcm91dGUgPSBQbHVnaW5IZWxwZXJzLmNyZWF0ZVJvdXRpbmdGdW5jdGlvbih0ZW1wbGF0ZVBhdGgpO1xuXG4gIF9tb2R1bGUuY29uZmlnKFsnJHJvdXRlUHJvdmlkZXInLCAoJHJvdXRlUHJvdmlkZXI6bmcucm91dGUuSVJvdXRlUHJvdmlkZXIpID0+IHtcbiAgICAkcm91dGVQcm92aWRlci53aGVuKGNvbnRleHQsIHJvdXRlKCd3b3Jrc3BhY2VzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihcIi9uYW1lc3BhY2VzXCIsIHJvdXRlKCd3b3Jrc3BhY2VzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAvLy53aGVuKFwiL2hvbWVcIiwgcm91dGUoJ2hvbWUuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgICAgICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnLzpuYW1lc3BhY2UnKSwgcm91dGUoJ3Byb2plY3RzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL2RldGFpbCcpLCByb3V0ZSgnd29ya3NwYWNlLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL2plbmtpbnNKb2InKSwgcm91dGUoJ2plbmtpbnNKb2JzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL3Byb2plY3RzJyksIHJvdXRlKCdwcm9qZWN0cy5odG1sJywgZmFsc2UpKVxuICAgICAgICAgICAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvOm5hbWVzcGFjZS9wcm9qZWN0cy86aWQnKSwgcm91dGUoJ2Vudmlyb25tZW50cy5odG1sJywgZmFsc2UpKVxuICAgICAgICAgICAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvOm5hbWVzcGFjZS9wcm9qZWN0cy86aWQvZGV0YWlsJyksIEt1YmVybmV0ZXMucm91dGUoJ2J1aWxkQ29uZmlnLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL3Byb2plY3RzLzppZC9idWlsZHMnKSwgS3ViZXJuZXRlcy5yb3V0ZSgnYnVpbGRzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL3Byb2plY3RzLzppZC9lbnZpcm9ubWVudHMnKSwgcm91dGUoJ2Vudmlyb25tZW50cy5odG1sJywgZmFsc2UpKVxuICAgICAgICAgICAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvOm5hbWVzcGFjZS9wcm9qZWN0cy86aWQvamVua2luc0pvYi86am9iJyksIHJvdXRlKCdqZW5raW5zSm9iLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL3Byb2plY3RzLzppZC9qZW5raW5zSm9iLzpqb2IvbG9nLzpidWlsZCcpLCByb3V0ZSgnamVua2luc0xvZy5odG1sJywgZmFsc2UpKVxuICAgICAgICAgICAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvOm5hbWVzcGFjZS9wcm9qZWN0cy86aWQvamVua2luc0pvYi86am9iL3BpcGVsaW5lcycpLCByb3V0ZSgncGlwZWxpbmVzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL3Byb2plY3RzLzppZC9qZW5raW5zSm9iLzpqb2IvcGlwZWxpbmUvOmJ1aWxkJyksIHJvdXRlKCdwaXBlbGluZS5odG1sJywgZmFsc2UpKVxuICAgICAgICAgICAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvOm5hbWVzcGFjZS9wcm9qZWN0cy86aWQvamVua2luc0pvYi86am9iL21ldHJpY3MnKSwgcm91dGUoJ2plbmtpbnNNZXRyaWNzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy86bmFtZXNwYWNlL3Byb2plY3RzLzppZC9qZW5raW5zTWV0cmljcycpLCByb3V0ZSgnamVua2luc01ldHJpY3MuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgICAgICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnLzpuYW1lc3BhY2UvcHJvamVjdHMvOmlkL3Rvb2xzJyksIHJvdXRlKCd0b29scy5odG1sJywgZmFsc2UpKVxuICAgICAgICAgICAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvOndvcmtzcGFjZS9wcm9qZWN0cy86cHJvamVjdC9lbnZpcm9ubWVudHMvOm5hbWVzcGFjZScpLCByb3V0ZSgnZW52aXJvbm1lbnQuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgICAgICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnLzp3b3Jrc3BhY2UvcHJvamVjdHMvOnByb2plY3QvZW52aXJvbm1lbnRzLzpuYW1lc3BhY2UnKSwgcm91dGUoJ2Vudmlyb25tZW50Lmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9BZ2dyZWdhdGUvb3ZlcnZpZXcnKSwgcm91dGUoJ2FkZERhdGFGaWxlLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAub3RoZXJ3aXNlKFwiL3dvcmtzcGFjZXNcIik7XG4gIH1dKTtcbiAgXG5cbiAgX21vZHVsZS5ydW4oWyd2aWV3UmVnaXN0cnknLCAnU2VydmljZVJlZ2lzdHJ5JywgJ0hhd3Rpb05hdicsICdLdWJlcm5ldGVzTW9kZWwnLCAnJHRlbXBsYXRlQ2FjaGUnLCAnRGF0YUluZm9Nb2RlbCcsKHZpZXdSZWdpc3RyeSwgU2VydmljZVJlZ2lzdHJ5LCBIYXd0aW9OYXYsIEt1YmVybmV0ZXNNb2RlbCwgJHRlbXBsYXRlQ2FjaGUsIERhdGFJbmZvTW9kZWwpID0+IHtcbiAgICBsb2cuZGVidWcoXCJSdW5uaW5nXCIpO1xuICAgIHZpZXdSZWdpc3RyeVsnd29ya3NwYWNlcyddID0gS3ViZXJuZXRlcy50ZW1wbGF0ZVBhdGggKyAnbGF5b3V0S3ViZXJuZXRlcy5odG1sJztcbiAgICB2aWV3UmVnaXN0cnlbJ25hbWVzcGFjZXMnXSA9IEt1YmVybmV0ZXMudGVtcGxhdGVQYXRoICsgJ2xheW91dEt1YmVybmV0ZXMuaHRtbCc7XG5cbiAgICB2YXIgYnVpbGRlciA9IEhhd3Rpb05hdi5idWlsZGVyKCk7XG4gICAgdmFyIHdvcmtzcGFjZXMgPSBidWlsZGVyLmlkKCd3b3Jrc3BhY2VzJylcbiAgICAgICAgICAgICAgICAgICAgICAuaHJlZigoKSA9PiBjb250ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgIC50aXRsZSgoKSA9PiAn5p+l55yLJylcbiAgICAgICAgICAgICAgICAgICAgICAuYnVpbGQoKTtcbi8qXG4gICAgdmFyIHdvcmtzcGFjZU92ZXJ2aWV3ID0gYnVpbGRlci5pZCgnd29ya3NwYWNlcycpXG4gICAgICAgICAgICAgICAgICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdvdmVydmlldycpKVxuICAgICAgICAgICAgICAgICAgICAgIC50aXRsZSgoKSA9PiAnV29ya3NwYWNlJylcbiAgICAgICAgICAgICAgICAgICAgICAuYnVpbGQoKTtcbiovXG4vKiAgICB2YXIgZGF0YWFkZCA9IGJ1aWxkZXIuaWQoJ2RhdGFhZGQnKVxuICAgICAgICAgICAgICAgICAgICAgIC5ocmVmKCgpID0+IGNvbnRleHQpXG4gICAgICAgICAgICAgICAgICAgICAgLnRpdGxlKCgpID0+ICfmsYfmgLsnKVxuICAgICAgICAgICAgICAgICAgICAgIC5idWlsZCgpO1xuKi9cbiAgICB2YXIgQWdncmVnYXRlID0gYnVpbGRlci5pZCgnQWdncmVnYXRlOycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgLnJhbmsoMjAwKVxuICAgICAgICAgICAgICAgICAgICAgICAgIC5ocmVmKCgpID0+IGNvbnRleHQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgLnRpdGxlKCgpID0+ICfmlbDmja7msYfmgLsnKVxuICAgICAgICAgICAgICAgICAgICAgICAgIC8vLmlzVmFsaWQoKCkgPT4gIUNvcmUuaXNSZW1vdGVDb25uZWN0aW9uKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgLnRhYnMod29ya3NwYWNlcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAuYnVpbGQoKTtcblxuICAgIEhhd3Rpb05hdi5hZGQoQWdncmVnYXRlKTtcbiAgfV0pO1xuXG4gIF9tb2R1bGUuZmlsdGVyKCdhc1RydXN0ZWRIdG1sJywgWyckc2NlJywgZnVuY3Rpb24gKCRzY2UpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgIHJldHVybiAkc2NlLnRydXN0QXNIdG1sKHRleHQpO1xuICAgIH07XG4gIH1dKTtcblxuICBoYXd0aW9QbHVnaW5Mb2FkZXIuYWRkTW9kdWxlKHBsdWdpbk5hbWUpO1xuXG4gIC8vIGZvciBzY3JvbGwtZ2x1ZSBkaXJlY3RpdmVcbiAgaGF3dGlvUGx1Z2luTG9hZGVyLmFkZE1vZHVsZSgnbHVlZ2cuZGlyZWN0aXZlcycpO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlclBsdWdpbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG4gIF9tb2R1bGUuY29udHJvbGxlcignRGV2ZWxvcGVyLkVudmlyb25tZW50UGFuZWxDb250cm9sbGVyJywgKCRzY29wZSwgJGVsZW1lbnQsICRsb2NhdGlvbiwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWw6S3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCkgPT4ge1xuXG4gICAgJHNjb3BlLmVudlZlcnNpb25zID0ge307XG4gICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICRzY29wZS5lbnYgPSAkc2NvcGUuJGV2YWwoJ2VudicpO1xuICAgICRzY29wZS5idWlsZENvbmZpZyA9ICRzY29wZS4kZXZhbCgnZW50aXR5Jyk7XG5cbiAgICAkc2NvcGUub3BlbiA9IHRydWU7XG5cbiAgICAkc2NvcGUudG9nZ2xlID0gKCkgPT4gJHNjb3BlLm9wZW4gPSAhJHNjb3BlLm9wZW47XG5cbiAgICB2YXIgY2FjaGVzID0ge307XG5cbiAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG5cbiAgICBsb2FkUHJvamVjdFZlcnNpb25zKCRzY29wZSwgJGVsZW1lbnQsICRzY29wZS5idWlsZENvbmZpZywgJHNjb3BlLmVudiwgJHNjb3BlLmVudi5uYW1lc3BhY2UsICRzY29wZS5lbnZWZXJzaW9ucywgY2FjaGVzKTtcblxuICB9KTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9rdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckVucmljaGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCB2YXIgSG9tZUNvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiSG9tZUNvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJLdWJlcm5ldGVzU2NoZW1hXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLm5hbWVzcGFjZSA9IEt1YmVybmV0ZXMuY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcblxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyTmF2aWdhdGlvbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBKZW5raW5zSm9iQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJKZW5raW5zSm9iQ29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIkt1YmVybmV0ZXNTY2hlbWFcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsIFwiU2VydmljZVJlZ2lzdHJ5XCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6S3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNTY2hlbWEsXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwsIFNlcnZpY2VSZWdpc3RyeSkgPT4ge1xuXG4gICAgICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICAgICAkc2NvcGUuam9iSWQgPSAkcm91dGVQYXJhbXNbXCJqb2JcIl07XG4gICAgICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICAgICAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlID0ge307XG5cbiAgICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuICAgICAgICAkc2NvcGUuYnJlYWRjcnVtYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0QnJlYWRjcnVtYnMoJHNjb3BlLmlkKTtcbiAgICAgICAgJHNjb3BlLnN1YlRhYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0U3ViTmF2QmFycygkc2NvcGUuaWQsICRzY29wZS5qb2JJZCk7XG5cbiAgICAgICAgJHNjb3BlLiRvbigna3ViZXJuZXRlc01vZGVsVXBkYXRlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB1cGRhdGVEYXRhKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgICAgICB1cGRhdGVEYXRhKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgICAgICBkYXRhOiAnam9iLmJ1aWxkcycsXG4gICAgICAgICAgc2hvd1NlbGVjdGlvbkNoZWNrYm94OiB0cnVlLFxuICAgICAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICBtdWx0aVNlbGVjdDogdHJ1ZSxcbiAgICAgICAgICBzZWxlY3RlZEl0ZW1zOiBbXSxcbiAgICAgICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgICAgICBmaWx0ZXJUZXh0OiAkbG9jYXRpb24uc2VhcmNoKClbXCJxXCJdIHx8ICcnXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpZWxkOiAnJHNvcnRPcmRlcicsXG4gICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTmFtZScsXG4gICAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiamVua2luc0J1aWxkSWRUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWVsZDogJyRidWlsZExpbmsnLFxuICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogJ1ZpZXdzJyxcbiAgICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJqZW5raW5zQnVpbGRCdXR0b25zVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZmllbGQ6ICckZHVyYXRpb24nLFxuICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogJ0R1cmF0aW9uJyxcbiAgICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJqZW5raW5zQnVpbGREdXJhdGlvblRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpZWxkOiAnJHRpbWVzdGFtcCcsXG4gICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnVGltZSBTdGFydGVkJyxcbiAgICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJqZW5raW5zQnVpbGRUaW1lc3RhbXBUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgXVxuICAgICAgICB9O1xuICAgICAgICB1cGRhdGVEYXRhKCk7XG5cblxuICAgICAgICBmdW5jdGlvbiB1cGRhdGVEYXRhKCkge1xuICAgICAgICAgIGlmICgkc2NvcGUuam9iSWQpIHtcbiAgICAgICAgICAgIHZhciB1cmwgPSBLdWJlcm5ldGVzLmt1YmVybmV0ZXNQcm94eVVybEZvclNlcnZpY2VDdXJyZW50TmFtZXNwYWNlKGplbmtpbnNTZXJ2aWNlTmFtZUFuZFBvcnQsIFVybEhlbHBlcnMuam9pbihcImpvYlwiLCAkc2NvcGUuam9iSWQsIFwiYXBpL2pzb24/ZGVwdGg9MVwiKSk7XG4gICAgICAgICAgICBpZiAodXJsICYmICghJHNjb3BlLmpvYiB8fCBLdWJlcm5ldGVzLmtlZXBQb2xsaW5nTW9kZWwpKSB7XG4gICAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBlbnJpY2hKZW5raW5zSm9iKGRhdGEsICRzY29wZS5pZCwgJHNjb3BlLmpvYklkKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGhhc09iamVjdENoYW5nZWQoZGF0YSwgJHNjb3BlLmVudGl0eUNoYW5nZWRDYWNoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbyhcImVudGl0eSBoYXMgY2hhbmdlZCFcIik7XG4gICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmpvYiA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICAgICAgfSkuXG4gICAgICAgICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkc2NvcGUubW9kZWwuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyTmF2aWdhdGlvbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBKZW5raW5zSm9ic0NvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiSmVua2luc0pvYnNDb250cm9sbGVyXCIsXG4gICAgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc1NjaGVtYVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIiwgXCJTZXJ2aWNlUmVnaXN0cnlcIixcbiAgICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSxcbiAgICAgICAkdGVtcGxhdGVDYWNoZTpuZy5JVGVtcGxhdGVDYWNoZVNlcnZpY2UsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCAkcm91dGVQYXJhbXMsICRodHRwLCAkdGltZW91dCwgS3ViZXJuZXRlc0FwaVVSTCwgU2VydmljZVJlZ2lzdHJ5KSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG4gICAgICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICAgICAkc2NvcGUuamVua2lucyA9IG51bGw7XG4gICAgICAgICRzY29wZS5lbnRpdHlDaGFuZ2VkQ2FjaGUgPSB7fTtcblxuICAgICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gICAgICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gY3JlYXRlUHJvamVjdEJyZWFkY3J1bWJzKCk7XG4gICAgICAgICRzY29wZS5zdWJUYWJDb25maWcgPSBEZXZlbG9wZXIuY3JlYXRlV29ya3NwYWNlU3ViTmF2QmFycygpO1xuXG4gICAgICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkc2NvcGUuJG9uKCckcm91dGVVcGRhdGUnLCAoJGV2ZW50KSA9PiB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkc2NvcGUudGFibGVDb25maWcgPSB7XG4gICAgICAgICAgZGF0YTogJ2plbmtpbnMuam9icycsXG4gICAgICAgICAgc2hvd1NlbGVjdGlvbkNoZWNrYm94OiB0cnVlLFxuICAgICAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICBtdWx0aVNlbGVjdDogdHJ1ZSxcbiAgICAgICAgICBzZWxlY3RlZEl0ZW1zOiBbXSxcbiAgICAgICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgICAgICBmaWx0ZXJUZXh0OiAkbG9jYXRpb24uc2VhcmNoKClbXCJxXCJdIHx8ICcnXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpZWxkOiAnbmFtZScsXG4gICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTmFtZScsXG4gICAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiamVua2luc0pvYk5hbWVUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWVsZDogJyRidWlsZExpbmsnLFxuICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogJ1ZpZXdzJyxcbiAgICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJqZW5raW5zSm9iQnV0dG9uc1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZpZWxkOiAnJGxhc3RTdWNjZXNzZnVsQnVpbGROdW1iZXInLFxuICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogJ0xhc3QgU3VjY2VzcycsXG4gICAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiamVua2luc0xhc3RTdWNjZXNzVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZmllbGQ6ICckbGFzdEZhaWxlZGxCdWlsZE51bWJlcicsXG4gICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTGFzdCBGYWlsdXJlJyxcbiAgICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJqZW5raW5zTGFzdEZhaWx1cmVUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWVsZDogJyRkdXJhdGlvbicsXG4gICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTGFzdCBEdXJhdGlvbicsXG4gICAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiamVua2luc0J1aWxkRHVyYXRpb25UZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmaWVsZDogJyR0aW1lc3RhbXAnLFxuICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogJ1RpbWUgU3RhcnRlZCcsXG4gICAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiamVua2luc0J1aWxkVGltZXN0YW1wVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIF1cbiAgICAgICAgfTtcbiAgICAgICAgdXBkYXRlRGF0YSgpO1xuXG5cbiAgICAgICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgICAgICAvLyBUT0RPIG9ubHkgbmVlZCBkZXB0aCAyIHRvIGJlIGFibGUgdG8gZmV0Y2ggdGhlIGxhc3RCdWlsZFxuICAgICAgICAgIHZhciB1cmwgPSBLdWJlcm5ldGVzLmt1YmVybmV0ZXNQcm94eVVybEZvclNlcnZpY2VDdXJyZW50TmFtZXNwYWNlKGplbmtpbnNTZXJ2aWNlTmFtZUFuZFBvcnQsIFwiYXBpL2pzb24/ZGVwdGg9MlwiKTtcbiAgICAgICAgICBsb2cuaW5mbyhcIlwiKTtcbiAgICAgICAgICBpZiAodXJsICYmICghJHNjb3BlLmplbmtpbnMgfHwgS3ViZXJuZXRlcy5rZWVwUG9sbGluZ01vZGVsKSkge1xuICAgICAgICAgICAgJGh0dHAuZ2V0KHVybCwgamVua2luc0h0dHBDb25maWcpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICBlbnJpY2hKZW5raW5zSm9icyhkYXRhLCAkc2NvcGUuaWQsICRzY29wZS5pZCk7XG4gICAgICAgICAgICAgICAgICBpZiAoaGFzT2JqZWN0Q2hhbmdlZChkYXRhLCAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlKSkge1xuICAgICAgICAgICAgICAgICAgICBsb2cuaW5mbyhcImVudGl0eSBoYXMgY2hhbmdlZCFcIik7XG4gICAgICAgICAgICAgICAgICAgICRzY29wZS5qZW5raW5zID0gZGF0YTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJHNjb3BlLm1vZGVsLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cblxuZGVjbGFyZSB2YXIgT1NPQXV0aENvbmZpZzphbnk7XG5kZWNsYXJlIHZhciBHb29nbGVPQXV0aENvbmZpZzphbnk7XG5kZWNsYXJlIHZhciBLZXljbG9ha0NvbmZpZzphbnk7XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIF9tb2R1bGUgPSBhbmd1bGFyLm1vZHVsZShwbHVnaW5OYW1lLCBbJ2hhd3Rpby1jb3JlJywgJ2hhd3Rpby11aScsICd1aS5jb2RlbWlycm9yJywgJ3VpLnZhbGlkYXRlJywna3ViZXJuZXRlc1VJJ10pO1xuICBleHBvcnQgdmFyIGNvbnRyb2xsZXIgPSBQbHVnaW5IZWxwZXJzLmNyZWF0ZUNvbnRyb2xsZXJGdW5jdGlvbihfbW9kdWxlLCBwbHVnaW5OYW1lKTtcbiAgZXhwb3J0IHZhciByb3V0ZSA9IFBsdWdpbkhlbHBlcnMuY3JlYXRlUm91dGluZ0Z1bmN0aW9uKHRlbXBsYXRlUGF0aCk7XG5cbiAgX21vZHVsZS5jb25maWcoWyckcm91dGVQcm92aWRlcicsICgkcm91dGVQcm92aWRlcjpuZy5yb3V0ZS5JUm91dGVQcm92aWRlcikgPT4ge1xuXG4gICAgJHJvdXRlUHJvdmlkZXJcbiAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL3BvZHMnKSwgcm91dGUoJ3BvZHMuaHRtbCcsIGZhbHNlKSlcbiAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAncmVwbGljYXRpb25Db250cm9sbGVycycpLCByb3V0ZSgncmVwbGljYXRpb25Db250cm9sbGVycy5odG1sJywgZmFsc2UpKVxuICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdzZXJ2aWNlcycpLCByb3V0ZSgnc2VydmljZXMuaHRtbCcsIGZhbHNlKSlcbiAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnZXZlbnRzJyksIHJvdXRlKCdldmVudHMuaHRtbCcsIGZhbHNlKSlcbiAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnYXBwcycpLCByb3V0ZSgnYXBwcy5odG1sJywgZmFsc2UpKVxuICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdhcHBzLzpuYW1lc3BhY2UnKSwgcm91dGUoJ2FwcHMuaHRtbCcsIGZhbHNlKSlcbiAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAndGVtcGxhdGVzJyksIHJvdXRlKCd0ZW1wbGF0ZXMuaHRtbCcsIGZhbHNlKSlcbiAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnaG9zdHMnKSwgcm91dGUoJ2hvc3RzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2hvc3RzLzppZCcpLCByb3V0ZSgnaG9zdC5odG1sJywgdHJ1ZSkpXG4gICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ3BpcGVsaW5lcycpLCByb3V0ZSgncGlwZWxpbmVzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ292ZXJ2aWV3JyksIHJvdXRlKCdvdmVydmlldy5odG1sJywgdHJ1ZSkpXG4gICAgICAud2hlbihjb250ZXh0LCB7cmVkaXJlY3RUbzogVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdyZXBsaWNhdGlvbkNvbnRyb2xsZXJzJyl9KTtcblxuXG4gICAgYW5ndWxhci5mb3JFYWNoKFtjb250ZXh0LCBcIi93b3Jrc3BhY2VzLzp3b3Jrc3BhY2UvcHJvamVjdHMvOnByb2plY3RcIl0sIChjb250ZXh0KSA9PiB7XG4gICAgICAkcm91dGVQcm92aWRlclxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9wb2RDcmVhdGUnKSwgcm91dGUoJ3BvZENyZWF0ZS5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9wb2RFZGl0LzppZCcpLCByb3V0ZSgncG9kRWRpdC5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9wb2RzJyksIHJvdXRlKCdwb2RzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL3BvZHMvOmlkJyksIHJvdXRlKCdwb2QuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvbmFtZXNwYWNlLzpuYW1lc3BhY2UvcmVwbGljYXRpb25Db250cm9sbGVycycpLCByb3V0ZSgncmVwbGljYXRpb25Db250cm9sbGVycy5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9yZXBsaWNhdGlvbkNvbnRyb2xsZXJzLzppZCcpLCByb3V0ZSgncmVwbGljYXRpb25Db250cm9sbGVyLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL3JlcGxpY2F0aW9uQ29udHJvbGxlckNyZWF0ZScpLCByb3V0ZSgncmVwbGljYXRpb25Db250cm9sbGVyQ3JlYXRlLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL3JlcGxpY2F0aW9uQ29udHJvbGxlckVkaXQvOmlkJyksIHJvdXRlKCdyZXBsaWNhdGlvbkNvbnRyb2xsZXJFZGl0Lmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL3NlY3JldHMnKSwgcm91dGUoJ3NlY3JldHMuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvbmFtZXNwYWNlLzpuYW1lc3BhY2Uvc2VjcmV0cy86aWQnKSwgcm91dGUoJ3NlY3JldC5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9zZWNyZXRDcmVhdGUnKSwgcm91dGUoJ3NlY3JldC5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9zZXJ2aWNlcycpLCByb3V0ZSgnc2VydmljZXMuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvbmFtZXNwYWNlLzpuYW1lc3BhY2Uvc2VydmljZXMvOmlkJyksIHJvdXRlKCdzZXJ2aWNlLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL3NlcnZpY2VDcmVhdGUnKSwgcm91dGUoJ3NlcnZpY2VDcmVhdGUuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvbmFtZXNwYWNlLzpuYW1lc3BhY2Uvc2VydmljZUVkaXQvOmlkJyksIHJvdXRlKCdzZXJ2aWNlRWRpdC5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9ldmVudHMnKSwgcm91dGUoJ2V2ZW50cy5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJy9uYW1lc3BhY2UvOm5hbWVzcGFjZS9hcHBzJyksIHJvdXRlKCdhcHBzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL292ZXJ2aWV3JyksIHJvdXRlKCdvdmVydmlldy5odG1sJywgdHJ1ZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnL25hbWVzcGFjZS86bmFtZXNwYWNlL3RlbXBsYXRlcy86dGFyZ2V0TmFtZXNwYWNlJyksIHJvdXRlKCd0ZW1wbGF0ZXMuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICcvbmFtZXNwYWNlLzpuYW1lc3BhY2UnKSwgcm91dGUoJ2FwcHMuaHRtbCcsIGZhbHNlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdidWlsZHMnKSwgcm91dGUoJ2J1aWxkcy5odG1sJywgZmFsc2UpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2J1aWxkcy86aWQnKSwgcm91dGUoJ2J1aWxkLmh0bWwnLCB0cnVlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdidWlsZExvZ3MvOmlkJyksIHJvdXRlKCdidWlsZExvZ3MuaHRtbCcsIHRydWUpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2J1aWxkQ29uZmlncycpLCByb3V0ZSgnYnVpbGRDb25maWdzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnYnVpbGRDb25maWdzLzppZCcpLCByb3V0ZSgnYnVpbGRDb25maWcuaHRtbCcsIHRydWUpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2J1aWxkQ29uZmlnRWRpdC86aWQnKSwgcm91dGUoJ2J1aWxkQ29uZmlnRWRpdC5odG1sJywgdHJ1ZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnZGVwbG95bWVudENvbmZpZ3MnKSwgcm91dGUoJ2RlcGxveW1lbnRDb25maWdzLmh0bWwnLCBmYWxzZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnZGVwbG95bWVudENvbmZpZ3MvOmlkJyksIHJvdXRlKCdkZXBsb3ltZW50Q29uZmlnLmh0bWwnLCB0cnVlKSlcbiAgICAgICAgLndoZW4oVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdpbWFnZVJlcG9zaXRvcmllcycpLCByb3V0ZSgnaW1hZ2VSZXBvc2l0b3JpZXMuaHRtbCcsIGZhbHNlKSlcbiAgICB9KTtcblxuICAgIGFuZ3VsYXIuZm9yRWFjaChbY29udGV4dCwgXCIvd29ya3NwYWNlcy86d29ya3NwYWNlXCIsIFwiL3dvcmtzcGFjZXMvOndvcmtzcGFjZS9wcm9qZWN0cy86cHJvamVjdFwiXSwgKGNvbnRleHQpID0+IHtcbiAgICAgICRyb3V0ZVByb3ZpZGVyXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnYnVpbGRDb25maWdFZGl0JyksIHJvdXRlKCdidWlsZENvbmZpZ0VkaXQuaHRtbCcsIHRydWUpKVxuICAgICAgICAud2hlbihVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2J1aWxkQ29uZmlnRWRpdC86aWQnKSwgcm91dGUoJ2J1aWxkQ29uZmlnRWRpdC5odG1sJywgdHJ1ZSkpXG4gICAgICAgIC53aGVuKFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnaW1wb3J0UHJvamVjdCcpLCByb3V0ZSgnaW1wb3J0UHJvamVjdC5odG1sJywgdHJ1ZSkpXG4gICAgfSk7XG4gIH1dKTtcblxuXG4gIF9tb2R1bGUuZmFjdG9yeSgnQXBwTGlicmFyeVVSTCcsIFsnJHJvb3RTY29wZScsICgkcm9vdFNjb3BlOm5nLklSb290U2NvcGVTZXJ2aWNlKSA9PiB7XG4gICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbihrdWJlcm5ldGVzQXBpVXJsKCksIFwiL3Byb3h5XCIsIGt1YmVybmV0ZXNOYW1lc3BhY2VQYXRoKCksIFwiL3NlcnZpY2VzL2FwcC1saWJyYXJ5XCIpO1xuICB9XSk7XG5cbiAgX21vZHVsZS5mYWN0b3J5KCdXaWtpR2l0VXJsUHJlZml4JywgKCkgPT4ge1xuICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4oa3ViZXJuZXRlc0FwaVVybCgpLCBcIi9wcm94eVwiLCBrdWJlcm5ldGVzTmFtZXNwYWNlUGF0aCgpLCBcInNlcnZpY2VzL2FwcC1saWJyYXJ5XCIpO1xuICB9KTtcblxuICBfbW9kdWxlLmZhY3RvcnkoJ3dpa2lSZXBvc2l0b3J5JywgW1wiJGxvY2F0aW9uXCIsIFwibG9jYWxTdG9yYWdlXCIsICgkbG9jYXRpb24sIGxvY2FsU3RvcmFnZSkgPT4ge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfV0pO1xuXG4gIF9tb2R1bGUuZmFjdG9yeSgnQ29ubmVjdERpYWxvZ1NlcnZpY2UnLCBbJyRyb290U2NvcGUnLCAoJHJvb3RTY29wZTpuZy5JUm9vdFNjb3BlU2VydmljZSkgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICBkaWFsb2c6IG5ldyBVSS5EaWFsb2coKSxcbiAgICAgIHNhdmVDcmVkZW50aWFsczogZmFsc2UsXG4gICAgICB1c2VyTmFtZTogbnVsbCxcbiAgICAgIHBhc3N3b3JkOiBudWxsLFxuICAgICAgam9sb2tpYVVybDogbnVsbCxcbiAgICAgIGNvbnRhaW5lck5hbWU6IG51bGwsXG4gICAgICB2aWV3OiBudWxsXG4gICAgfTtcbiAgfV0pO1xuXG4gIF9tb2R1bGUuZmlsdGVyKCdrdWJlcm5ldGVzUGFnZUxpbmsnLCAoKSA9PiBlbnRpdHlQYWdlTGluayk7XG5cbiAgX21vZHVsZS5maWx0ZXIoJ3JlbGF0aXZlVGltZScsICgpID0+IHtcbiAgICByZXR1cm4gKGRhdGUpID0+IHtcbiAgICAgIHJldHVybiBodW1hbmRhdGUucmVsYXRpdmVUaW1lKGRhdGUpO1xuICAgIH1cbiAgfSk7XG5cbiAgX21vZHVsZS5ydW4oWyd2aWV3UmVnaXN0cnknLCAnU2VydmljZVJlZ2lzdHJ5JywgJ0hhd3Rpb05hdicsICdLdWJlcm5ldGVzTW9kZWwnLCAnJHRlbXBsYXRlQ2FjaGUnLCAodmlld1JlZ2lzdHJ5LCBTZXJ2aWNlUmVnaXN0cnksIEhhd3Rpb05hdiwgS3ViZXJuZXRlc01vZGVsLCAkdGVtcGxhdGVDYWNoZSkgPT4ge1xuXG4gICAgbG9nLmRlYnVnKFwiUnVubmluZ1wiKTtcbiAgICB2aWV3UmVnaXN0cnlbJ2t1YmVybmV0ZXMnXSA9IHRlbXBsYXRlUGF0aCArICdsYXlvdXRLdWJlcm5ldGVzLmh0bWwnO1xuICAgIHZhciBidWlsZGVyID0gSGF3dGlvTmF2LmJ1aWxkZXIoKTtcbiAgICB2YXIgYXBwcyA9IGJ1aWxkZXIuaWQoJ2t1YmUtYXBwcycpXG4gICAgICAuaHJlZigoKSA9PiBVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2FwcHMnKSlcbiAgICAgIC50aXRsZSgoKSA9PiAnQXBwcycpXG4gICAgICAuYnVpbGQoKTtcblxuICAgIHZhciBzZXJ2aWNlcyA9IGJ1aWxkZXIuaWQoJ2t1YmUtc2VydmljZXMnKVxuICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdzZXJ2aWNlcycpKVxuICAgICAgLnRpdGxlKCgpID0+ICdTZXJ2aWNlcycpXG4gICAgICAuYnVpbGQoKTtcblxuICAgIHZhciBjb250cm9sbGVycyA9IGJ1aWxkZXIuaWQoJ2t1YmUtY29udHJvbGxlcnMnKVxuICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdyZXBsaWNhdGlvbkNvbnRyb2xsZXJzJykpXG4gICAgICAudGl0bGUoKCkgPT4gJ29yYWNsZeacjeWKoScpXG4gICAgICAuYnVpbGQoKTtcblxuICAgIHZhciBwb2RzID0gYnVpbGRlci5pZCgna3ViZS1wb2RzJylcbiAgICAgIC5ocmVmKCgpID0+IFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAncG9kcycpKVxuICAgICAgLnRpdGxlKCgpID0+ICfmtYvor5XpobXpnaInKVxuICAgICAgLmJ1aWxkKCk7XG5cbiAgICB2YXIgZXZlbnRzID0gYnVpbGRlci5pZCgna3ViZS1ldmVudHMnKVxuICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdldmVudHMnKSlcbiAgICAgIC50aXRsZSgoKSA9PiAn5pyN5Yqh5ZCv5Yqo5pel5b+XJylcbiAgICAgIC5idWlsZCgpO1xuXG4gICAgdmFyIGhvc3RzID0gYnVpbGRlci5pZCgna3ViZS1ob3N0cycpXG4gICAgICAuaHJlZigoKSA9PiBVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2hvc3RzJykpXG4gICAgICAudGl0bGUoKCkgPT4gJ+mbhue+pOiKgueCuScpXG4gICAgICAuYnVpbGQoKTtcblxuICAgIHZhciBvdmVydmlldyA9IGJ1aWxkZXIuaWQoJ2t1YmUtb3ZlcnZpZXcnKVxuICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdvdmVydmlldycpKVxuICAgICAgLnRpdGxlKCgpID0+ICdEaWFncmFtJylcbiAgICAgIC5idWlsZCgpO1xuXG4gICAgdmFyIGJ1aWxkcyA9IGJ1aWxkZXIuaWQoJ2t1YmUtYnVpbGRzJylcbiAgICAgIC5ocmVmKCgpID0+IFVybEhlbHBlcnMuam9pbihjb250ZXh0LCAnYnVpbGRzJykpXG4gICAgICAudGl0bGUoKCkgPT4gJ0J1aWxkcycpXG4gICAgICAuYnVpbGQoKTtcblxuICAgIHZhciBidWlsZENvbmZpZ3MgPSBidWlsZGVyLmlkKCdrdWJlLWJ1aWxkQ29uZmlncycpXG4gICAgICAuaHJlZigoKSA9PiBVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2J1aWxkQ29uZmlncycpKVxuICAgICAgLnRpdGxlKCgpID0+ICdCdWlsZCBDb25maWdzJylcbiAgICAgIC5idWlsZCgpO1xuXG4gICAgdmFyIGRlcGxveXMgPSBidWlsZGVyLmlkKCdrdWJlLWRlcGxveXMnKVxuICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdkZXBsb3ltZW50Q29uZmlncycpKVxuICAgICAgLnRpdGxlKCgpID0+ICdEZXBsb3lzJylcbiAgICAgIC5idWlsZCgpO1xuXG4gICAgdmFyIGltYWdlUmVwb3NpdG9yaWVzID0gYnVpbGRlci5pZCgna3ViZS1pbWFnZVJlcG9zaXRvcmllcycpXG4gICAgICAuaHJlZigoKSA9PiBVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2ltYWdlUmVwb3NpdG9yaWVzJykpXG4gICAgICAudGl0bGUoKCkgPT4gJ1JlZ2lzdHJpZXMnKVxuICAgICAgLmJ1aWxkKCk7XG5cbiAgICB2YXIgcGlwZWxpbmVzID0gYnVpbGRlci5pZCgna3ViZS1waXBlbGluZXMnKVxuICAgICAgLmhyZWYoKCkgPT4gVXJsSGVscGVycy5qb2luKGNvbnRleHQsICdwaXBlbGluZXMnKSlcbiAgICAgIC50aXRsZSgoKSA9PiAnUGlwZWxpbmVzJylcbiAgICAgIC5idWlsZCgpO1xuXG4gICAgdmFyIHJlcG9zID0gYnVpbGRlci5pZCgna3ViZS1yZXBvcycpXG4gICAgICAuaHJlZigoKSA9PiBcIi9mb3JnZS9yZXBvc1wiKVxuICAgICAgLmlzVmFsaWQoKCkgPT4gU2VydmljZVJlZ2lzdHJ5Lmhhc1NlcnZpY2UoZmFicmljOEZvcmdlU2VydmljZU5hbWUpICYmIFNlcnZpY2VSZWdpc3RyeS5oYXNTZXJ2aWNlKGdvZ3NTZXJ2aWNlTmFtZSkpXG4gICAgICAudGl0bGUoKCkgPT4gJ1JlcG9zaXRvcmllcycpXG4gICAgICAuYnVpbGQoKTtcblxuICAgIHZhciBtYWluVGFiID0gYnVpbGRlci5pZCgna3ViZXJuZXRlcycpXG4gICAgICAucmFuaygxMDApXG4gICAgICAuZGVmYXVsdFBhZ2Uoe1xuICAgICAgICByYW5rOiAyMCxcbiAgICAgICAgaXNWYWxpZDogKHllcywgbm8pID0+IHtcbiAgICAgICAgICB5ZXMoKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC5ocmVmKCgpID0+IGNvbnRleHQpXG4gICAgICAudGl0bGUoKCkgPT4gJ+acjeWKoembhue+pCcpXG4gICAgICAudGFicyhjb250cm9sbGVycywgZXZlbnRzKVxuICAgICAgLmJ1aWxkKCk7XG4gICAgSGF3dGlvTmF2LmFkZChtYWluVGFiKTtcblxuICAgIC8qIHRlc3RLdWJlcm5ldGVzTW9kZWxcbiAgICBIYXd0aW9OYXYuYWRkKHtcbiAgICAgIGlkOiAnazhzQXBwU3dpdGNoZXInLFxuICAgICAgdGl0bGU6ICgpID0+ICcnLCAvLyBub3QgdXNlZCBhcyAndGVtcGxhdGUnIGJlbG93IG92ZXJyaWRlcyB0aGlzXG4gICAgICBpc1ZhbGlkOiAoKSA9PiBLdWJlcm5ldGVzTW9kZWwuc2VydmljZUFwcHMubGVuZ3RoID4gMCxcbiAgICAgIGNvbnRleHQ6IHRydWUsXG4gICAgICB0ZW1wbGF0ZTogKCkgPT4gJHRlbXBsYXRlQ2FjaGUuZ2V0KFVybEhlbHBlcnMuam9pbih0ZW1wbGF0ZVBhdGgsICdzZXJ2aWNlQXBwcy5odG1sJykpXG4gICAgfSk7XG4gICAgKi9cblxuICAgIHZhciBwcm9qZWN0c1RhYiA9IGJ1aWxkZXIuaWQoJ29wZW5zaGlmdCcpXG4gICAgICAucmFuaygxMDApXG4gICAgICAuaHJlZigoKSA9PiBVcmxIZWxwZXJzLmpvaW4oY29udGV4dCwgJ2J1aWxkQ29uZmlncycpICsgJz9zdWItdGFiPWt1YmUtYnVpbGRDb25maWdzJylcbiAgICAgIC50aXRsZSgoKSA9PiAnUHJvamVjdHMnKVxuICAgICAgLy8gbGV0cyBkaXNhYmxlIHRoZSBwaXBlbGluZXMgdmlldyBmb3Igbm93XG4gICAgICAvLyBwaXBlbGluZXMsXG4gICAgICAudGFicyhyZXBvcywgYnVpbGRDb25maWdzLCBidWlsZHMsIGRlcGxveXMsIGltYWdlUmVwb3NpdG9yaWVzKVxuICAgICAgLmJ1aWxkKCk7XG5cbiAgICAvL0hhd3Rpb05hdi5hZGQocHJvamVjdHNUYWIpO1xuICB9XSk7XG5cbiAgaGF3dGlvUGx1Z2luTG9hZGVyLnJlZ2lzdGVyUHJlQm9vdHN0cmFwVGFzayh7XG4gICAgbmFtZTogJ0t1YmVybmV0ZXNJbml0JyxcbiAgICB0YXNrOiAobmV4dCkgPT4ge1xuICAgICAgJC5nZXRTY3JpcHQoJ29zY29uc29sZS9jb25maWcuanMnKVxuICAgICAgICAuZG9uZSgoc2NyaXB0LCB0ZXh0U3RhdHVzKSA9PiB7XG4gICAgICAgICAgdmFyIGNvbmZpZzpLdWJlcm5ldGVzQ29uZmlnID0gS3ViZXJuZXRlcy5vc0NvbmZpZyA9IHdpbmRvd1snT1BFTlNISUZUX0NPTkZJRyddO1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZldGNoZWQgT0F1dGggY29uZmlnOiBcIiwgY29uZmlnKTtcbiAgICAgICAgICB2YXIgbWFzdGVyOnN0cmluZyA9IGNvbmZpZy5tYXN0ZXJfdXJpO1xuICAgICAgICAgIGlmICghbWFzdGVyICYmIGNvbmZpZy5hcGkgJiYgY29uZmlnLmFwaS5rOHMpIHtcbiAgICAgICAgICAgIHZhciBtYXN0ZXJVcmkgPSBuZXcgVVJJKCkuaG9zdChjb25maWcuYXBpLms4cy5ob3N0UG9ydCkucGF0aChcIlwiKS5xdWVyeShcIlwiKTtcbiAgICAgICAgICAgIGlmIChjb25maWcuYXBpLms4cy5wcm90bykge1xuICAgICAgICAgICAgICBtYXN0ZXJVcmkucHJvdG9jb2woY29uZmlnLmFwaS5rOHMucHJvdG8pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWFzdGVyID0gbWFzdGVyVXJpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgT1NPQXV0aENvbmZpZyA9IGNvbmZpZy5vcGVuc2hpZnQ7XG4gICAgICAgICAgR29vZ2xlT0F1dGhDb25maWcgPSBjb25maWcuZ29vZ2xlO1xuICAgICAgICAgIEtleWNsb2FrQ29uZmlnID0gY29uZmlnLmtleWNsb2FrO1xuXG4gICAgICAgICAgaWYgKE9TT0F1dGhDb25maWcgJiYgIW1hc3Rlcikge1xuICAgICAgICAgICAgLy8gVE9ETyBhdXRoLm1hc3Rlcl91cmkgbm8gbG9uZ2VyIHVzZWQgcmlnaHQ/XG4gICAgICAgICAgICAvLyBtYXN0ZXIgPSBPU09BdXRoQ29uZmlnLm1hc3Rlcl91cmk7XG4gICAgICAgICAgICBpZiAoIW1hc3Rlcikge1xuICAgICAgICAgICAgICB2YXIgb2F1dGhfYXV0aG9yaXplX3VyaSA9IE9TT0F1dGhDb25maWcub2F1dGhfYXV0aG9yaXplX3VyaTtcbiAgICAgICAgICAgICAgaWYgKG9hdXRoX2F1dGhvcml6ZV91cmkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IG9hdXRoX2F1dGhvcml6ZV91cmk7XG4gICAgICAgICAgICAgICAgdmFyIGlkeCA9IHRleHQuaW5kZXhPZihcIjovL1wiKTtcbiAgICAgICAgICAgICAgICBpZiAoaWR4ID4gMCkge1xuICAgICAgICAgICAgICAgICAgaWR4ICs9IDM7XG4gICAgICAgICAgICAgICAgICBpZHggPSB0ZXh0LmluZGV4T2YoXCIvXCIsIGlkeCk7XG4gICAgICAgICAgICAgICAgICBpZiAoaWR4ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBtYXN0ZXIgPSB0ZXh0LnN1YnN0cmluZygwLCArK2lkeCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICgoIUt1YmVybmV0ZXMubWFzdGVyVXJsIHx8IEt1YmVybmV0ZXMubWFzdGVyVXJsID09PSBcIi9cIikgJiYgKCFtYXN0ZXIgfHwgbWFzdGVyID09PSBcIi9cIikpIHtcbiAgICAgICAgICAgIC8vIGxldHMgZGVmYXVsdCB0aGUgbWFzdGVyIHRvIHRoZSBjdXJyZW50IHByb3RvY29sIGFuZCBob3N0L3BvcnRcbiAgICAgICAgICAgIC8vIGluIGNhc2UgdGhlIG1hc3RlciB1cmwgaXMgXCIvXCIgYW5kIHdlIGFyZVxuICAgICAgICAgICAgLy8gc2VydmluZyB1cCBzdGF0aWMgY29udGVudCBmcm9tIGluc2lkZSAvYXBpL3YxL25hbWVzcGFjZXMvZGVmYXVsdC9zZXJ2aWNlcy9mYWJyaWM4IG9yIHNvbWV0aGluZyBsaWtlIHRoYXRcbiAgICAgICAgICAgIHZhciBocmVmID0gbG9jYXRpb24uaHJlZjtcbiAgICAgICAgICAgIGlmIChocmVmKSB7XG4gICAgICAgICAgICAgIG1hc3RlciA9IG5ldyBVUkkoaHJlZikucXVlcnkoXCJcIikucGF0aChcIlwiKS50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobWFzdGVyKSB7XG4gICAgICAgICAgICBLdWJlcm5ldGVzLm1hc3RlclVybCA9IG1hc3RlcjtcbiAgICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5mYWlsKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcIkVycm9yIGZldGNoaW5nIE9BVVRIIGNvbmZpZzogXCIsIHJlc3BvbnNlKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmFsd2F5cygoKSA9PiB7XG4gICAgICAgICAgbmV4dCgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH0sIHRydWUpO1xuXG4gIGhhd3Rpb1BsdWdpbkxvYWRlci5hZGRNb2R1bGUoJ25nUmVzb3VyY2UnKTtcbiAgaGF3dGlvUGx1Z2luTG9hZGVyLmFkZE1vZHVsZShwbHVnaW5OYW1lKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBGQUJSSUM4X1BST0pFQ1RfSlNPTiA9IFwiZmFicmljOFByb2plY3RKc29uXCI7XG5cbiAgZnVuY3Rpb24gYnlJZCh0aGluZykge1xuICAgIHJldHVybiB0aGluZy5pZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZUtleShuYW1lc3BhY2UsIGlkLCBraW5kKSB7XG4gICAgcmV0dXJuIChuYW1lc3BhY2UgfHwgXCJcIikgKyBcIi1cIiArIChraW5kIHx8ICd1bmRlZmluZWQnKS50b0xvd2VyQ2FzZSgpICsgJy0nICsgKGlkIHx8ICd1bmRlZmluZWQnKS5yZXBsYWNlKC9cXC4vZywgJy0nKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvcHVsYXRlS2V5KGl0ZW0pIHtcbiAgICB2YXIgcmVzdWx0ID0gaXRlbTtcbiAgICByZXN1bHRbJ19rZXknXSA9IGNyZWF0ZUtleShnZXROYW1lc3BhY2UoaXRlbSksIGdldE5hbWUoaXRlbSksIGdldEtpbmQoaXRlbSkpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBwb3B1bGF0ZUtleXMoaXRlbXM6QXJyYXk8YW55Pikge1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICBhbmd1bGFyLmZvckVhY2goaXRlbXMsIChpdGVtKSA9PiB7XG4gICAgICByZXN1bHQucHVzaChwb3B1bGF0ZUtleShpdGVtKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbGVjdFBvZHMocG9kcywgbmFtZXNwYWNlLCBsYWJlbHMpIHtcbiAgICByZXR1cm4gcG9kcy5maWx0ZXIoKHBvZCkgPT4ge1xuICAgICAgcmV0dXJuIGdldE5hbWVzcGFjZShwb2QpID09PSBuYW1lc3BhY2UgJiYgc2VsZWN0b3JNYXRjaGVzKGxhYmVscywgZ2V0TGFiZWxzKHBvZCkpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvYmplY3Qgd2hpY2gga2VlcHMgdHJhY2sgb2YgYWxsIHRoZSBwb2RzLCByZXBsaWNhdGlvbiBjb250cm9sbGVycywgc2VydmljZXMgYW5kIHRoZWlyIGFzc29jaWF0aW9uc1xuICAgKi9cbiAgZXhwb3J0IGNsYXNzIEt1YmVybmV0ZXNNb2RlbFNlcnZpY2Uge1xuICAgIHB1YmxpYyBrdWJlcm5ldGVzID0gPEt1YmVybmV0ZXNTdGF0ZT4gbnVsbDtcbiAgICBwdWJsaWMgYXBwcyA9IFtdO1xuICAgIHB1YmxpYyBzZXJ2aWNlcyA9IFtdO1xuXG4gICAgcHVibGljIHJlcGxpY2F0aW9uY29udHJvbGxlcnMgPSBbXTtcbiAgICBwdWJsaWMgZ2V0IHJlcGxpY2F0aW9uQ29udHJvbGxlcnMoKTpBcnJheTxhbnk+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlcGxpY2F0aW9uY29udHJvbGxlcnM7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgcmVwbGljYXRpb25Db250cm9sbGVycyhyZXBsaWNhdGlvbkNvbnRyb2xsZXJzOkFycmF5PGFueT4pIHtcbiAgICAgIHRoaXMucmVwbGljYXRpb25jb250cm9sbGVycyA9IHJlcGxpY2F0aW9uQ29udHJvbGxlcnM7XG4gICAgfVxuICAgIHB1YmxpYyBwb2RzID0gW107XG4gICAgcHVibGljIGhvc3RzID0gW107XG4gICAgcHVibGljIGdldCBuYW1lc3BhY2VzKCk6QXJyYXk8c3RyaW5nPiB7XG4gICAgICByZXR1cm4gdGhpcy5rdWJlcm5ldGVzLm5hbWVzcGFjZXM7XG4gICAgfVxuICAgIC8vcHVibGljIG5hbWVzcGFjZXMgPSBbXTtcbiAgICBwdWJsaWMgcm91dGVzID0gW107XG4gICAgcHVibGljIHRlbXBsYXRlcyA9IFtdO1xuICAgIHB1YmxpYyByZWRyYXcgPSBmYWxzZTtcbiAgICBwdWJsaWMgcmVzb3VyY2VWZXJzaW9ucyA9IHt9O1xuXG4gICAgLy8gdmFyaW91cyB2aWV3cyBvbiB0aGUgZGF0YVxuICAgIHB1YmxpYyBwb2RzQnlIb3N0ID0ge307XG4gICAgcHVibGljIHNlcnZpY2VzQnlLZXkgPSB7fTtcbiAgICBwdWJsaWMgcmVwbGljYXRpb25Db250cm9sbGVyc0J5S2V5ID0ge307XG4gICAgcHVibGljIHBvZHNCeUtleSA9IHt9O1xuXG4gICAgcHVibGljIGFwcEluZm9zID0gW107XG4gICAgcHVibGljIGFwcFZpZXdzID0gW107XG4gICAgcHVibGljIGFwcEZvbGRlcnMgPSBbXTtcblxuICAgIHB1YmxpYyBmZXRjaGVkID0gZmFsc2U7XG4gICAgcHVibGljIGdldCBzaG93UnVuQnV0dG9uKCk6Ym9vbGVhbiB7XG4gICAgICBpZiAoaXNPcGVuU2hpZnQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gXy5hbnkodGhpcy5zZXJ2aWNlcywgKHNlcnZpY2UpID0+IHtcbiAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHNlcnZpY2UpO1xuICAgICAgICBpZiAobmFtZSA9PT0gXCJ0ZW1wbGF0ZXNcIikge1xuICAgICAgICAgIHZhciBwb2RDb3VudGVycyA9IHNlcnZpY2UuJHBvZENvdW50ZXJzO1xuICAgICAgICAgIHJldHVybiBwb2RDb3VudGVycyAmJiAocG9kQ291bnRlcnMudmFsaWQgfHwgcG9kQ291bnRlcnMucmVhZHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGJ1aWxkY29uZmlncyA9IFtdO1xuICAgIHB1YmxpYyBldmVudHMgPSBbXTtcbiAgICBwdWJsaWMgd29ya3NwYWNlcyA9IFtdO1xuICAgIHB1YmxpYyBwcm9qZWN0cyA9IFtdO1xuICAgIHB1YmxpYyBwcm9qZWN0ID0gbnVsbDtcblxuICAgIHB1YmxpYyBnZXQgc2VydmljZUFwcHMoKTpBcnJheTxhbnk+IHtcbiAgICAgIHJldHVybiBfLmZpbHRlcih0aGlzLnNlcnZpY2VzLCAocykgPT4ge1xuICAgICAgICByZXR1cm4gcy4kaG9zdCAmJiBzLiRzZXJ2aWNlVXJsICYmIHMuJHBvZENvdW50XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgJGtlZXBQb2xsaW5nKCkge1xuICAgICAgcmV0dXJuIGtlZXBQb2xsaW5nTW9kZWw7XG4gICAgfVxuXG4gICAgcHVibGljIG9yUmVkcmF3KGZsYWcpIHtcbiAgICAgIHRoaXMucmVkcmF3ID0gdGhpcy5yZWRyYXcgfHwgZmxhZztcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2VydmljZShuYW1lc3BhY2UsIGlkKSB7XG4gICAgICByZXR1cm4gdGhpcy5zZXJ2aWNlc0J5S2V5W2NyZWF0ZUtleShuYW1lc3BhY2UsIGlkLCAnc2VydmljZScpXTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UmVwbGljYXRpb25Db250cm9sbGVyKG5hbWVzcGFjZSwgaWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlcGxpY2F0aW9uQ29udHJvbGxlcnNCeUtleVtjcmVhdGVLZXkobmFtZXNwYWNlLCBpZCwgJ3JlcGxpY2F0aW9uQ29udHJvbGxlcicpXTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UG9kKG5hbWVzcGFjZSwgaWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBvZHNCeUtleVtjcmVhdGVLZXkobmFtZXNwYWNlLCBpZCwgJ3BvZCcpXTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcG9kc0Zvck5hbWVzcGFjZShuYW1lc3BhY2UgPSB0aGlzLmN1cnJlbnROYW1lc3BhY2UoKSkge1xuICAgICAgcmV0dXJuIF8uZmlsdGVyKHRoaXMucG9kcywgeyBuYW1lc3BhY2U6IG5hbWVzcGFjZSB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0QnVpbGRDb25maWcobmFtZSkge1xuICAgICAgcmV0dXJuIF8uZmluZCh0aGlzLmJ1aWxkY29uZmlncywgeyAkbmFtZTogbmFtZSB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UHJvamVjdChuYW1lLCBucyA9IHRoaXMuY3VycmVudE5hbWVzcGFjZSgpKSB7XG4gICAgICB2YXIgYnVpbGRDb25maWcgPSB0aGlzLnByb2plY3Q7XG4gICAgICBpZiAoIWJ1aWxkQ29uZmlnKSB7XG4gICAgICAgIHZhciB0ZXh0ID0gbG9jYWxTdG9yYWdlW0ZBQlJJQzhfUFJPSkVDVF9KU09OXTtcbiAgICAgICAgaWYgKHRleHQpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYnVpbGRDb25maWcgPSBhbmd1bGFyLmZyb21Kc29uKHRleHQpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZy53YXJuKFwiQ291bGQgbm90IHBhcnNlIGpzb24gZm9yIFwiICsgRkFCUklDOF9QUk9KRUNUX0pTT04gKyBcIi4gV2FzOiBcIiArIHRleHQgKyBcIi4gXCIgKyBlLCBlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChidWlsZENvbmZpZyAmJiBucyAhPSBnZXROYW1lc3BhY2UoYnVpbGRDb25maWcpICYmIG5hbWUgIT0gYnVpbGRDb25maWcuJG5hbWUpIHtcbiAgICAgICAgYnVpbGRDb25maWcgPSB0aGlzLmdldEJ1aWxkQ29uZmlnKG5hbWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkQ29uZmlnO1xuICAgIH1cblxuXG4gICAgcHVibGljIHNldFByb2plY3QoYnVpbGRDb25maWcpIHtcbiAgICAgIHRoaXMucHJvamVjdCA9IGJ1aWxkQ29uZmlnO1xuICAgICAgaWYgKGJ1aWxkQ29uZmlnKSB7XG4gICAgICAgIC8vIGxldHMgc3RvcmUgaW4gbG9jYWwgc3RvcmFnZVxuICAgICAgICB2YXIgbG9jYWxTdG9yYWdlID0gaW5qZWN0KFwibG9jYWxTdG9yYWdlXCIpO1xuICAgICAgICBpZiAobG9jYWxTdG9yYWdlKSB7XG4gICAgICAgICAgbG9jYWxTdG9yYWdlW0ZBQlJJQzhfUFJPSkVDVF9KU09OXSA9IGFuZ3VsYXIudG9Kc29uKGJ1aWxkQ29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgbmFtZXNwYWNlIG9yIHRoZSBkZWZhdWx0IG5hbWVzcGFjZVxuICAgICAqL1xuICAgIHB1YmxpYyBjdXJyZW50TmFtZXNwYWNlKCkge1xuICAgICAgdmFyIGFuc3dlciA9IG51bGw7XG4gICAgICBpZiAodGhpcy5rdWJlcm5ldGVzKSB7XG4gICAgICAgIGFuc3dlciA9IHRoaXMua3ViZXJuZXRlcy5zZWxlY3RlZE5hbWVzcGFjZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhbnN3ZXIgfHwgZGVmYXVsdE5hbWVzcGFjZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgdXBkYXRlSWNvblVybEFuZEFwcEluZm8oZW50aXR5LCBuYW1lRmllbGQ6IHN0cmluZykge1xuICAgICAgdmFyIGFuc3dlciA9IG51bGw7XG4gICAgICB2YXIgaWQgPSBnZXROYW1lKGVudGl0eSk7XG4gICAgICBlbnRpdHkuJGljb25VcmwgPSBDb3JlLnBhdGhHZXQoZW50aXR5LCBbJ21ldGFkYXRhJywgJ2Fubm90YXRpb25zJywgJ2ZhYnJpYzguJyArIGlkICsgJy9pY29uVXJsJ10pO1xuICAgICAgZW50aXR5LiRpbmZvID0gQ29yZS5wYXRoR2V0KGVudGl0eSwgWydtZXRhZGF0YScsICdhbm5vdGF0aW9ucycsICdmYWJyaWM4LicgKyBpZCArICcvc3VtbWFyeSddKTtcbiAgICAgIGlmIChlbnRpdHkuJGljb25VcmwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGlkICYmIG5hbWVGaWVsZCkge1xuICAgICAgICAodGhpcy50ZW1wbGF0ZXMgfHwgW10pLmZvckVhY2goKHRlbXBsYXRlKSA9PiB7XG4gICAgICAgICAgdmFyIG1ldGFkYXRhID0gdGVtcGxhdGUubWV0YWRhdGE7XG4gICAgICAgICAgaWYgKG1ldGFkYXRhKSB7XG4gICAgICAgICAgICB2YXIgYW5ub3RhdGlvbnMgPSBtZXRhZGF0YS5hbm5vdGF0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIHZhciBpY29uVXJsID0gYW5ub3RhdGlvbnNbXCJmYWJyaWM4LlwiICsgaWQgKyBcIi9pY29uVXJsXCJdIHx8IGFubm90YXRpb25zW1wiZmFicmljOC9pY29uVXJsXCJdO1xuICAgICAgICAgICAgaWYgKGljb25VcmwpIHtcbiAgICAgICAgICAgICAgKHRlbXBsYXRlLm9iamVjdHMgfHwgW10pLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICB2YXIgZW50aXR5TmFtZSA9IGdldE5hbWUoaXRlbSk7XG4gICAgICAgICAgICAgICAgaWYgKGlkID09PSBlbnRpdHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgICBlbnRpdHkuJGljb25VcmwgPSBpY29uVXJsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgKHRoaXMuYXBwSW5mb3MgfHwgW10pLmZvckVhY2goKGFwcEluZm8pID0+IHtcbiAgICAgICAgICB2YXIgaWNvblBhdGggPSBhcHBJbmZvLmljb25QYXRoO1xuICAgICAgICAgIGlmIChpY29uUGF0aCAmJiAhYW5zd2VyICYmIGljb25QYXRoICE9PSBcIm51bGxcIikge1xuICAgICAgICAgICAgdmFyIGljb25VcmwgPSBnaXRQYXRoVG9VcmwoaWNvblBhdGgpO1xuICAgICAgICAgICAgdmFyIGlkcyA9IENvcmUucGF0aEdldChhcHBJbmZvLCBbXCJuYW1lc1wiLCBuYW1lRmllbGRdKTtcbiAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChpZHMsIChhcHBJZCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoYXBwSWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgICAgZW50aXR5LiRpY29uVXJsID0gaWNvblVybDtcbiAgICAgICAgICAgICAgICBlbnRpdHkuYXBwUGF0aCA9IGFwcEluZm8uYXBwUGF0aDtcbiAgICAgICAgICAgICAgICBlbnRpdHkuJGluZm8gPSBhcHBJbmZvO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKCFlbnRpdHkuJGljb25VcmwpIHtcbiAgICAgICAgZW50aXR5LiRpY29uVXJsID0gZGVmYXVsdEljb25Vcmw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIG1heWJlSW5pdCgpIHtcbiAgICAgIHRoaXMuZmV0Y2hlZCA9IHRydWU7XG4gICAgICB0aGlzLnNlcnZpY2VzQnlLZXkgPSB7fTtcbiAgICAgIHRoaXMucG9kc0J5S2V5ID0ge307XG4gICAgICB0aGlzLnJlcGxpY2F0aW9uQ29udHJvbGxlcnNCeUtleSA9IHt9O1xuXG4gICAgICB0aGlzLnBvZHMuZm9yRWFjaCgocG9kKSA9PiB7XG4gICAgICAgIGlmICghcG9kLmtpbmQpIHBvZC5raW5kID0gXCJQb2RcIjtcbiAgICAgICAgdGhpcy5wb2RzQnlLZXlbcG9kLl9rZXldID0gcG9kO1xuICAgICAgICB2YXIgaG9zdCA9IGdldEhvc3QocG9kKTtcbiAgICAgICAgcG9kLiRsYWJlbHNUZXh0ID0gS3ViZXJuZXRlcy5sYWJlbHNUb1N0cmluZyhnZXRMYWJlbHMocG9kKSk7XG4gICAgICAgIGlmIChob3N0KSB7XG4gICAgICAgICAgcG9kLiRsYWJlbHNUZXh0ICs9IGxhYmVsRmlsdGVyVGV4dFNlcGFyYXRvciArIFwiaG9zdD1cIiArIGhvc3Q7XG4gICAgICAgIH1cbiAgICAgICAgcG9kLiRpY29uVXJsID0gZGVmYXVsdEljb25Vcmw7XG4gICAgICAgIHRoaXMuZGlzY292ZXJQb2RDb25uZWN0aW9ucyhwb2QpO1xuICAgICAgICBwb2QuJGNvbnRhaW5lclBvcnRzID0gW107XG5cbiAgICAgICAgdmFyIHBvZFN0YXR1cyA9IHBvZC5zdGF0dXMgfHwge307XG4gICAgICAgIHZhciBzdGFydFRpbWUgPSBwb2RTdGF0dXMuc3RhcnRUaW1lO1xuICAgICAgICBwb2QuJHN0YXJ0VGltZSA9IG51bGw7XG4gICAgICAgIGlmIChzdGFydFRpbWUpIHtcbiAgICAgICAgICBwb2QuJHN0YXJ0VGltZSA9IG5ldyBEYXRlKHN0YXJ0VGltZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNyZWF0ZWRUaW1lID0gZ2V0Q3JlYXRpb25UaW1lc3RhbXAocG9kKTtcbiAgICAgICAgcG9kLiRjcmVhdGVkVGltZSA9IG51bGw7XG4gICAgICAgIHBvZC4kYWdlID0gbnVsbDtcbiAgICAgICAgaWYgKGNyZWF0ZWRUaW1lKSB7XG4gICAgICAgICAgcG9kLiRjcmVhdGVkVGltZSA9IG5ldyBEYXRlKGNyZWF0ZWRUaW1lKTtcbiAgICAgICAgICBwb2QuJGFnZSA9IGh1bWFuZGF0ZS5yZWxhdGl2ZVRpbWUocG9kLiRjcmVhdGVkVGltZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlYWR5ID0gaXNSZWFkeShwb2QpO1xuICAgICAgICBwb2QuJHJlYWR5ID0gcmVhZHk7XG4gICAgICAgIHBvZC4kc3RhdHVzQ3NzID0gc3RhdHVzVGV4dFRvQ3NzQ2xhc3MocG9kU3RhdHVzLnBoYXNlLCByZWFkeSk7XG5cbiAgICAgICAgdmFyIG1heFJlc3RhcnRDb3VudCA9IDA7XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChDb3JlLnBhdGhHZXQocG9kLCBbXCJzdGF0dXNcIiwgXCJjb250YWluZXJTdGF0dXNlc1wiXSksIChzdGF0dXMpID0+IHtcbiAgICAgICAgICB2YXIgcmVzdGFydENvdW50ID0gc3RhdHVzLnJlc3RhcnRDb3VudDtcbiAgICAgICAgICBpZiAocmVzdGFydENvdW50KSB7XG4gICAgICAgICAgICBpZiAocmVzdGFydENvdW50ID4gbWF4UmVzdGFydENvdW50KSB7XG4gICAgICAgICAgICAgIG1heFJlc3RhcnRDb3VudCA9IHJlc3RhcnRDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAobWF4UmVzdGFydENvdW50ICkge1xuICAgICAgICAgIHBvZC4kcmVzdGFydENvdW50ID0gbWF4UmVzdGFydENvdW50O1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbWFnZU5hbWVzID0gXCJcIjtcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKENvcmUucGF0aEdldChwb2QsIFtcInNwZWNcIiwgXCJjb250YWluZXJzXCJdKSwgKGNvbnRhaW5lcikgPT4ge1xuICAgICAgICAgIHZhciBpbWFnZSA9IGNvbnRhaW5lci5pbWFnZTtcbiAgICAgICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgICAgIGlmICghaW1hZ2VOYW1lcykge1xuICAgICAgICAgICAgICBpbWFnZU5hbWVzID0gaW1hZ2U7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpbWFnZU5hbWVzID0gaW1hZ2VOYW1lcyArIFwiIFwiICsgaW1hZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaWR4ID0gaW1hZ2UubGFzdEluZGV4T2YoXCI6XCIpO1xuICAgICAgICAgICAgaWYgKGlkeCA+IDApIHtcbiAgICAgICAgICAgICAgaW1hZ2UgPSBpbWFnZS5zdWJzdHJpbmcoMCwgaWR4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwYXRocyA9IGltYWdlLnNwbGl0KFwiL1wiLCAzKTtcbiAgICAgICAgICAgIGlmIChwYXRocy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgdmFyIGFuc3dlciA9IG51bGw7XG4gICAgICAgICAgICAgIGlmIChwYXRocy5sZW5ndGggPT0gMykge1xuICAgICAgICAgICAgICAgIGFuc3dlciA9IHBhdGhzWzFdICsgXCIvXCIgKyBwYXRoc1syXTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChwYXRocy5sZW5ndGggPT0gMikge1xuICAgICAgICAgICAgICAgIGFuc3dlciA9IHBhdGhzWzBdICsgXCIvXCIgKyBwYXRoc1sxXTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbnN3ZXIgPSBwYXRoc1swXSArIFwiL1wiICsgcGF0aHNbMV07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29udGFpbmVyLiRpbWFnZUxpbmsgPSBVcmxIZWxwZXJzLmpvaW4oXCJodHRwczovL3JlZ2lzdHJ5Lmh1Yi5kb2NrZXIuY29tL3UvXCIsIGFuc3dlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChjb250YWluZXIucG9ydHMsIChwb3J0KSA9PiB7XG4gICAgICAgICAgICB2YXIgY29udGFpbmVyUG9ydCA9IHBvcnQuY29udGFpbmVyUG9ydDtcbiAgICAgICAgICAgIGlmIChjb250YWluZXJQb3J0KSB7XG4gICAgICAgICAgICAgIHBvZC4kY29udGFpbmVyUG9ydHMucHVzaChjb250YWluZXJQb3J0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHBvZC4kaW1hZ2VOYW1lcyA9IGltYWdlTmFtZXM7XG4gICAgICAgIHZhciBwb2RTdGF0dXMgPSBwb2RTdGF0dXM7XG4gICAgICAgIHZhciBwb2RTcGVjID0gKHBvZC5zcGVjIHx8IHt9KTtcbiAgICAgICAgcG9kLiRwb2RJUCA9IHBvZFN0YXR1cy5wb2RJUDtcbiAgICAgICAgcG9kLiRob3N0ID0gcG9kU3BlYy5ob3N0IHx8IHBvZFNwZWMubm9kZU5hbWUgfHwgcG9kU3RhdHVzLmhvc3RJUDtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLnNlcnZpY2VzLmZvckVhY2goKHNlcnZpY2UpID0+IHtcbiAgICAgICAgaWYgKCFzZXJ2aWNlLmtpbmQpIHNlcnZpY2Uua2luZCA9IFwiU2VydmljZVwiO1xuICAgICAgICB0aGlzLnNlcnZpY2VzQnlLZXlbc2VydmljZS5fa2V5XSA9IHNlcnZpY2U7XG4gICAgICAgIHZhciBzZWxlY3RvciA9IGdldFNlbGVjdG9yKHNlcnZpY2UpO1xuICAgICAgICBzZXJ2aWNlLiRwb2RzID0gW107XG4gICAgICAgIGlmICghc2VydmljZS4kcG9kQ291bnRlcnMpIHtcbiAgICAgICAgICBzZXJ2aWNlLiRwb2RDb3VudGVycyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBwb2RMaW5rVXJsID0gVXJsSGVscGVycy5qb2luKFwiL2t1YmVybmV0ZXMvbmFtZXNwYWNlXCIsIHNlcnZpY2UubWV0YWRhdGEubmFtZXNwYWNlLCBcInBvZHNcIik7XG4gICAgICAgIF8uYXNzaWduKHNlcnZpY2UuJHBvZENvdW50ZXJzLCBzZWxlY3RvciA/IGNyZWF0ZVBvZENvdW50ZXJzKHNlbGVjdG9yLCB0aGlzLnBvZHMsIHNlcnZpY2UuJHBvZHMsIEt1YmVybmV0ZXMubGFiZWxzVG9TdHJpbmcoc2VsZWN0b3IsIFwiLFwiKSwgcG9kTGlua1VybCkgOiB7fSk7XG4gICAgICAgIHNlcnZpY2UuJHBvZENvdW50ID0gc2VydmljZS4kcG9kcy5sZW5ndGg7XG5cbiAgICAgICAgdmFyIHNlbGVjdGVkUG9kcyA9IHNlcnZpY2UuJHBvZHM7XG4gICAgICAgIHNlcnZpY2UuY29ubmVjdFRvID0gc2VsZWN0ZWRQb2RzLm1hcCgocG9kKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHBvZC5fa2V5O1xuICAgICAgICB9KS5qb2luKCcsJyk7XG4gICAgICAgIHNlcnZpY2UuJGxhYmVsc1RleHQgPSBLdWJlcm5ldGVzLmxhYmVsc1RvU3RyaW5nKGdldExhYmVscyhzZXJ2aWNlKSk7XG4gICAgICAgIHRoaXMudXBkYXRlSWNvblVybEFuZEFwcEluZm8oc2VydmljZSwgXCJzZXJ2aWNlTmFtZXNcIik7XG4gICAgICAgIHZhciBzcGVjID0gc2VydmljZS5zcGVjIHx8IHt9O1xuICAgICAgICBzZXJ2aWNlLiRwb3J0YWxJUCA9IHNwZWMucG9ydGFsSVA7XG4gICAgICAgIHNlcnZpY2UuJHNlbGVjdG9yVGV4dCA9IEt1YmVybmV0ZXMubGFiZWxzVG9TdHJpbmcoc3BlYy5zZWxlY3Rvcik7XG4gICAgICAgIHZhciBwb3J0cyA9IF8ubWFwKHNwZWMucG9ydHMgfHwgW10sIFwicG9ydFwiKTtcbiAgICAgICAgc2VydmljZS4kcG9ydHMgPSBwb3J0cztcbiAgICAgICAgc2VydmljZS4kcG9ydHNUZXh0ID0gcG9ydHMuam9pbihcIiwgXCIpO1xuICAgICAgICB2YXIgaWNvblVybCA9IHNlcnZpY2UuJGljb25Vcmw7XG4gICAgICAgIGlmIChpY29uVXJsICYmIHNlbGVjdGVkUG9kcykge1xuICAgICAgICAgIHNlbGVjdGVkUG9kcy5mb3JFYWNoKChwb2QpID0+IHtcbiAgICAgICAgICAgIHBvZC4kaWNvblVybCA9IGljb25Vcmw7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgc2VydmljZS4kc2VydmljZVVybCA9IHNlcnZpY2VMaW5rVXJsKHNlcnZpY2UpO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMucmVwbGljYXRpb25Db250cm9sbGVycy5mb3JFYWNoKChyZXBsaWNhdGlvbkNvbnRyb2xsZXIpID0+IHtcbiAgICAgICAgaWYgKCFyZXBsaWNhdGlvbkNvbnRyb2xsZXIua2luZCkgcmVwbGljYXRpb25Db250cm9sbGVyLmtpbmQgPSBcIlJlcGxpY2F0aW9uQ29udHJvbGxlclwiO1xuICAgICAgICB0aGlzLnJlcGxpY2F0aW9uQ29udHJvbGxlcnNCeUtleVtyZXBsaWNhdGlvbkNvbnRyb2xsZXIuX2tleV0gPSByZXBsaWNhdGlvbkNvbnRyb2xsZXJcbiAgICAgICAgICB2YXIgc2VsZWN0b3IgPSBnZXRTZWxlY3RvcihyZXBsaWNhdGlvbkNvbnRyb2xsZXIpO1xuICAgICAgICByZXBsaWNhdGlvbkNvbnRyb2xsZXIuJHBvZHMgPSBbXTtcblxuICAgICAgICByZXBsaWNhdGlvbkNvbnRyb2xsZXIuJHBvZENvdW50ZXJzID0gc2VsZWN0b3IgPyBjcmVhdGVQb2RDb3VudGVycyhzZWxlY3RvciwgdGhpcy5wb2RzLCByZXBsaWNhdGlvbkNvbnRyb2xsZXIuJHBvZHMpIDogbnVsbDtcbiAgICAgICAgcmVwbGljYXRpb25Db250cm9sbGVyLiRwb2RDb3VudCA9IHJlcGxpY2F0aW9uQ29udHJvbGxlci4kcG9kcy5sZW5ndGg7XG4gICAgICAgIHJlcGxpY2F0aW9uQ29udHJvbGxlci4kcmVwbGljYXMgPSAocmVwbGljYXRpb25Db250cm9sbGVyLnNwZWMgfHwge30pLnJlcGxpY2FzO1xuXG4gICAgICAgIHZhciBzZWxlY3RlZFBvZHMgPSByZXBsaWNhdGlvbkNvbnRyb2xsZXIuJHBvZHM7XG4gICAgICAgIHJlcGxpY2F0aW9uQ29udHJvbGxlci5jb25uZWN0VG8gPSBzZWxlY3RlZFBvZHMubWFwKChwb2QpID0+IHtcbiAgICAgICAgICByZXR1cm4gcG9kLl9rZXk7XG4gICAgICAgIH0pLmpvaW4oJywnKTtcbiAgICAgICAgcmVwbGljYXRpb25Db250cm9sbGVyLiRsYWJlbHNUZXh0ID0gS3ViZXJuZXRlcy5sYWJlbHNUb1N0cmluZyhnZXRMYWJlbHMocmVwbGljYXRpb25Db250cm9sbGVyKSk7XG4gICAgICAgIHJlcGxpY2F0aW9uQ29udHJvbGxlci5tZXRhZGF0YS5sYWJlbHMgPSBLdWJlcm5ldGVzLmxhYmVsVG9DaGluZXNlKGdldExhYmVscyhyZXBsaWNhdGlvbkNvbnRyb2xsZXIpKTtcbiAgICAgICAgdGhpcy51cGRhdGVJY29uVXJsQW5kQXBwSW5mbyhyZXBsaWNhdGlvbkNvbnRyb2xsZXIsIFwicmVwbGljYXRpb25Db250cm9sbGVyTmFtZXNcIik7XG4gICAgICAgIHZhciBpY29uVXJsID0gIHJlcGxpY2F0aW9uQ29udHJvbGxlci4kaWNvblVybDtcbiAgICAgICAgaWYgKGljb25VcmwgJiYgc2VsZWN0ZWRQb2RzKSB7XG4gICAgICAgICAgc2VsZWN0ZWRQb2RzLmZvckVhY2goKHBvZCkgPT4ge1xuICAgICAgICAgICAgcG9kLiRpY29uVXJsID0gaWNvblVybDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIHNlcnZpY2VzIG1heSBub3QgbWFwIHRvIGFuIGljb24gYnV0IHRoZWlyIHBvZHMgbWF5IGRvIHZpYSB0aGUgUkNcbiAgICAgIC8vIHNvIGxldHMgZGVmYXVsdCBpdC4uLlxuICAgICAgdGhpcy5zZXJ2aWNlcy5mb3JFYWNoKChzZXJ2aWNlKSA9PiB7XG4gICAgICAgIHZhciBpY29uVXJsID0gc2VydmljZS4kaWNvblVybDtcbiAgICAgICAgdmFyIHNlbGVjdGVkUG9kcyA9IHNlcnZpY2UuJHBvZHM7XG4gICAgICAgIGlmIChzZWxlY3RlZFBvZHMpIHtcbiAgICAgICAgICBpZiAoIWljb25VcmwgfHwgaWNvblVybCA9PT0gZGVmYXVsdEljb25VcmwpIHtcbiAgICAgICAgICAgIGljb25VcmwgPSBudWxsO1xuICAgICAgICAgICAgc2VsZWN0ZWRQb2RzLmZvckVhY2goKHBvZCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIWljb25VcmwpIHtcbiAgICAgICAgICAgICAgICBpY29uVXJsID0gcG9kLiRpY29uVXJsO1xuICAgICAgICAgICAgICAgIGlmIChpY29uVXJsKSB7XG4gICAgICAgICAgICAgICAgICBzZXJ2aWNlLiRpY29uVXJsID0gaWNvblVybDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMudXBkYXRlQXBwcygpO1xuXG4gICAgICB2YXIgcG9kc0J5SG9zdCA9IHt9O1xuICAgICAgdGhpcy5wb2RzLmZvckVhY2goKHBvZCkgPT4ge1xuICAgICAgICB2YXIgaG9zdCA9IGdldEhvc3QocG9kKTtcbiAgICAgICAgdmFyIHBvZHNGb3JIb3N0ID0gcG9kc0J5SG9zdFtob3N0XTtcbiAgICAgICAgaWYgKCFwb2RzRm9ySG9zdCkge1xuICAgICAgICAgIHBvZHNGb3JIb3N0ID0gW107XG4gICAgICAgICAgcG9kc0J5SG9zdFtob3N0XSA9IHBvZHNGb3JIb3N0O1xuICAgICAgICB9XG4gICAgICAgIHBvZHNGb3JIb3N0LnB1c2gocG9kKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5wb2RzQnlIb3N0ID0gcG9kc0J5SG9zdDtcblxuICAgICAgdmFyIHRtcEhvc3RzID0gW107XG4gICAgICBmb3IgKHZhciBob3N0S2V5IGluIHBvZHNCeUhvc3QpIHtcbiAgICAgICAgdmFyIGhvc3RQb2RzID0gW107XG4gICAgICAgIHZhciBwb2RDb3VudGVycyA9IGNyZWF0ZVBvZENvdW50ZXJzKChwb2QpID0+IGdldEhvc3QocG9kKSA9PT0gaG9zdEtleSwgdGhpcy5wb2RzLCBob3N0UG9kcywgXCJob3N0PVwiICsgaG9zdEtleSk7XG4gICAgICAgIHZhciBob3N0SVAgPSBudWxsO1xuICAgICAgICBpZiAoaG9zdFBvZHMubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIHBvZCA9IGhvc3RQb2RzWzBdO1xuICAgICAgICAgIHZhciBjdXJyZW50U3RhdGUgPSBwb2Quc3RhdHVzO1xuICAgICAgICAgIGlmIChjdXJyZW50U3RhdGUpIHtcbiAgICAgICAgICAgIGhvc3RJUCA9IGN1cnJlbnRTdGF0ZS5ob3N0SVA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBob3N0RGV0YWlscyA9IHtcbiAgICAgICAgICBuYW1lOiBob3N0S2V5LFxuICAgICAgICAgIGlkOiBob3N0S2V5LFxuICAgICAgICAgIGVsZW1lbnRJZDogaG9zdEtleS5yZXBsYWNlKC9cXC4vZywgJ18nKSxcbiAgICAgICAgICBob3N0SVA6IGhvc3RJUCxcbiAgICAgICAgICBwb2RzOiBob3N0UG9kcyxcbiAgICAgICAgICBraW5kOiBcIkhvc3RcIixcbiAgICAgICAgICAgICRwb2RDb3VudGVyczogcG9kQ291bnRlcnMsXG4gICAgICAgICAgICAkaWNvblVybDogaG9zdEljb25VcmxcbiAgICAgICAgfTtcbiAgICAgICAgdG1wSG9zdHMucHVzaChob3N0RGV0YWlscyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaG9zdHMgPSB0bXBIb3N0cztcblxuICAgICAgZW5yaWNoQnVpbGRDb25maWdzKHRoaXMuYnVpbGRjb25maWdzKTtcbiAgICAgIGVucmljaEV2ZW50cyh0aGlzLmV2ZW50cywgdGhpcyk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUFwcHMoKSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBsZXRzIGNyZWF0ZSB0aGUgYXBwIHZpZXdzIGJ5IHRyeWluZyB0byBqb2luIGNvbnRyb2xsZXJzIC8gc2VydmljZXMgLyBwb2RzIHRoYXQgYXJlIHJlbGF0ZWRcbiAgICAgICAgdmFyIGFwcFZpZXdzID0gW107XG5cbiAgICAgICAgdGhpcy5yZXBsaWNhdGlvbkNvbnRyb2xsZXJzLmZvckVhY2goKHJlcGxpY2F0aW9uQ29udHJvbGxlcikgPT4ge1xuICAgICAgICAgIHZhciBuYW1lID0gZ2V0TmFtZShyZXBsaWNhdGlvbkNvbnRyb2xsZXIpO1xuICAgICAgICAgIHZhciAkaWNvblVybCA9IHJlcGxpY2F0aW9uQ29udHJvbGxlci4kaWNvblVybDtcbiAgICAgICAgICBhcHBWaWV3cy5wdXNoKHtcbiAgICAgICAgICAgIGFwcFBhdGg6IFwiL2R1bW15UGF0aC9cIiArIG5hbWUsXG4gICAgICAgICAgICAkbmFtZTogbmFtZSxcbiAgICAgICAgICAgICRpbmZvOiB7XG4gICAgICAgICAgICAgICRpY29uVXJsOiAkaWNvblVybFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICRpY29uVXJsOiAkaWNvblVybCxcbiAgICAgICAgICAgIHJlcGxpY2F0aW9uQ29udHJvbGxlcnM6IFtyZXBsaWNhdGlvbkNvbnRyb2xsZXJdLFxuICAgICAgICAgICAgcG9kczogcmVwbGljYXRpb25Db250cm9sbGVyLiRwb2RzIHx8IFtdLFxuICAgICAgICAgICAgc2VydmljZXM6IFtdXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBub01hdGNoZXMgPSBbXTtcbiAgICAgICAgdGhpcy5zZXJ2aWNlcy5mb3JFYWNoKChzZXJ2aWNlKSA9PiB7XG4gICAgICAgICAgLy8gbm93IGxldHMgc2VlIGlmIHdlIGNhbiBmaW5kIGFuIGFwcCB3aXRoIGFuIFJDIG9mIHRoZSBzYW1lIHNlbGVjdG9yXG4gICAgICAgICAgdmFyIG1hdGNoZXNBcHAgPSBudWxsO1xuICAgICAgICAgIGFwcFZpZXdzLmZvckVhY2goKGFwcFZpZXcpID0+IHtcbiAgICAgICAgICAgIGFwcFZpZXcucmVwbGljYXRpb25Db250cm9sbGVycy5mb3JFYWNoKChyZXBsaWNhdGlvbkNvbnRyb2xsZXIpID0+IHtcbiAgICAgICAgICAgICAgdmFyIHJlcFNlbGVjdG9yID0gZ2V0U2VsZWN0b3IocmVwbGljYXRpb25Db250cm9sbGVyKTtcbiAgICAgICAgICAgICAgaWYgKHJlcFNlbGVjdG9yICYmXG4gICAgICAgICAgICAgICAgICBzZWxlY3Rvck1hdGNoZXMocmVwU2VsZWN0b3IsIGdldFNlbGVjdG9yKHNlcnZpY2UpKSAmJlxuICAgICAgICAgICAgICAgICAgZ2V0TmFtZXNwYWNlKHNlcnZpY2UpID09PSBnZXROYW1lc3BhY2UocmVwbGljYXRpb25Db250cm9sbGVyKSkge1xuICAgICAgICAgICAgICAgIG1hdGNoZXNBcHAgPSBhcHBWaWV3O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChtYXRjaGVzQXBwKSB7XG4gICAgICAgICAgICBtYXRjaGVzQXBwLnNlcnZpY2VzLnB1c2goc2VydmljZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5vTWF0Y2hlcy5wdXNoKHNlcnZpY2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGxvZy5kZWJ1ZyhcIm5vIG1hdGNoZXM6IFwiLCBub01hdGNoZXMpO1xuICAgICAgICBub01hdGNoZXMuZm9yRWFjaCgoc2VydmljZSkgPT4ge1xuICAgICAgICAgIHZhciBhcHBWaWV3ID0gXy5maW5kKGFwcFZpZXdzLCAoYXBwVmlldykgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIF8uYW55KGFwcFZpZXcucmVwbGljYXRpb25Db250cm9sbGVycywgKHJjKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBfLnN0YXJ0c1dpdGgoZ2V0TmFtZShyYyksIGdldE5hbWUoc2VydmljZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKGFwcFZpZXcpIHtcbiAgICAgICAgICAgIGFwcFZpZXcuc2VydmljZXMucHVzaChzZXJ2aWNlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyICRpY29uVXJsID0gc2VydmljZS4kaWNvblVybDtcbiAgICAgICAgICAgIGFwcFZpZXdzLnB1c2goe1xuICAgICAgICAgICAgICBhcHBQYXRoOiBcIi9kdW1teVBhdGgvXCIgKyBuYW1lLFxuICAgICAgICAgICAgICAkbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgJGluZm86IHtcbiAgICAgICAgICAgICAgICAkaWNvblVybDogJGljb25VcmxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAkaWNvblVybDogJGljb25VcmwsXG4gICAgICAgICAgICAgIHJlcGxpY2F0aW9uQ29udHJvbGxlcnM6IFtdLFxuICAgICAgICAgICAgICBwb2RzOiBzZXJ2aWNlLiRwb2RzIHx8IFtdLFxuICAgICAgICAgICAgICBzZXJ2aWNlczogW3NlcnZpY2VdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaCh0aGlzLnJvdXRlcywgKHJvdXRlKSA9PiB7XG4gICAgICAgICAgdmFyIG1ldGFkYXRhID0gcm91dGUubWV0YWRhdGEgfHwge307XG4gICAgICAgICAgdmFyIHNwZWMgPSByb3V0ZS5zcGVjIHx8IHt9O1xuICAgICAgICAgIHZhciBzZXJ2aWNlTmFtZSA9IENvcmUucGF0aEdldChzcGVjLCBbXCJ0b1wiLCBcIm5hbWVcIl0pO1xuICAgICAgICAgIHZhciBob3N0ID0gc3BlYy5ob3N0O1xuICAgICAgICAgIHZhciBuYW1lc3BhY2UgPSBnZXROYW1lc3BhY2Uocm91dGUpO1xuICAgICAgICAgIGlmIChzZXJ2aWNlTmFtZSAmJiBob3N0KSB7XG4gICAgICAgICAgICB2YXIgc2VydmljZSA9IHRoaXMuZ2V0U2VydmljZShuYW1lc3BhY2UsIHNlcnZpY2VOYW1lKTtcbiAgICAgICAgICAgIGlmIChzZXJ2aWNlKSB7XG4gICAgICAgICAgICAgIHNlcnZpY2UuJGhvc3QgPSBob3N0O1xuXG4gICAgICAgICAgICAgIC8vIFRPRE8gd2UgY291bGQgdXNlIHNvbWUgYW5ub3RhdGlvbnMgLyBtZXRhZGF0YSB0byBkZWR1Y2Ugd2hhdCBVUkwgd2Ugc2hvdWxkIHVzZSB0byBvcGVuIHRoaXNcbiAgICAgICAgICAgICAgLy8gc2VydmljZSBpbiB0aGUgY29uc29sZS4gRm9yIG5vdyBqdXN0IGFzc3VtZSBpdHMgaHR0cDpcblxuICAgICAgICAgICAgICBpZiAoaG9zdCkge1xuICAgICAgICAgICAgICAgIHZhciBob3N0VXJsID0gIGhvc3Q7XG4gICAgICAgICAgICAgICAgaWYgKGhvc3RVcmwuaW5kZXhPZihcIjovL1wiKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgIGhvc3RVcmwgPSBcImh0dHA6Ly9cIiArIGhvc3Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlcnZpY2UuJGNvbm5lY3RVcmwgPSBVcmxIZWxwZXJzLmpvaW4oaG9zdFVybCwgIFwiL1wiKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vIFRPRE8gZGVmaW5pdGVseSBuZWVkIHRoYXQgYW5ub3RhdGlvbiwgdGVtcCBoYWNrIGZvciBhcGltYW4gbGlua1xuICAgICAgICAgICAgICBpZiAoZ2V0TmFtZShzZXJ2aWNlKSA9PT0gJ2FwaW1hbicgJiYgaG9zdCkge1xuICAgICAgICAgICAgICAgIHNlcnZpY2UuJGNvbm5lY3RVcmwgPSAoPGFueT4gbmV3IFVSSSgpLmhvc3Qoc2VydmljZS4kaG9zdClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucGF0aCgnYXBpbWFudWkvaW5kZXguaHRtbCcpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5xdWVyeSh7fSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuaGFzaChVUkkuZW5jb2RlKGFuZ3VsYXIudG9Kc29uKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tUbzogbmV3IFVSSSgpLnRvU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogSGF3dGlvT0F1dGguZ2V0T0F1dGhUb2tlbigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpKS50b1N0cmluZygpO1xuXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkNvdWxkIG5vdCBmaW5kIHNlcnZpY2UgXCIgKyBzZXJ2aWNlTmFtZSArIFwiIG5hbWVzcGFjZSBcIiArIG5hbWVzcGFjZSArIFwiIGZvciByb3V0ZTogXCIgKyBtZXRhZGF0YS5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGFwcFZpZXdzID0gXy5zb3J0QnkocG9wdWxhdGVLZXlzKGFwcFZpZXdzKSwgKGFwcFZpZXcpID0+IGFwcFZpZXcuX2tleSk7XG5cbiAgICAgICAgQXJyYXlIZWxwZXJzLnN5bmModGhpcy5hcHBWaWV3cywgYXBwVmlld3MsICckbmFtZScpO1xuXG4gICAgICAgIGlmICh0aGlzLmFwcEluZm9zICYmIHRoaXMuYXBwVmlld3MpIHtcbiAgICAgICAgICB2YXIgZm9sZGVyTWFwID0ge307XG4gICAgICAgICAgdmFyIGZvbGRlcnMgPSBbXTtcbiAgICAgICAgICB2YXIgYXBwTWFwID0ge307XG4gICAgICAgICAgYW5ndWxhci5mb3JFYWNoKHRoaXMuYXBwSW5mb3MsIChhcHBJbmZvKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWFwcEluZm8uJGljb25VcmwgJiYgYXBwSW5mby5pY29uUGF0aCAmJiBhcHBJbmZvLmljb25QYXRoICE9PSBcIm51bGxcIikge1xuICAgICAgICAgICAgICBhcHBJbmZvLiRpY29uVXJsID0gZ2l0UGF0aFRvVXJsKGFwcEluZm8uaWNvblBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGFwcFBhdGggPSBhcHBJbmZvLmFwcFBhdGg7XG4gICAgICAgICAgICBpZiAoYXBwUGF0aCkge1xuICAgICAgICAgICAgICBhcHBNYXBbYXBwUGF0aF0gPSBhcHBJbmZvO1xuICAgICAgICAgICAgICB2YXIgaWR4ID0gYXBwUGF0aC5sYXN0SW5kZXhPZihcIi9cIik7XG4gICAgICAgICAgICAgIHZhciBmb2xkZXJQYXRoID0gXCJcIjtcbiAgICAgICAgICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgZm9sZGVyUGF0aCA9IGFwcFBhdGguc3Vic3RyaW5nKDAsIGlkeCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZm9sZGVyUGF0aCA9IENvcmUudHJpbUxlYWRpbmcoZm9sZGVyUGF0aCwgXCIvXCIpO1xuICAgICAgICAgICAgICB2YXIgZm9sZGVyID0gZm9sZGVyTWFwW2ZvbGRlclBhdGhdO1xuICAgICAgICAgICAgICBpZiAoIWZvbGRlcikge1xuICAgICAgICAgICAgICAgIGZvbGRlciA9IHtcbiAgICAgICAgICAgICAgICAgIHBhdGg6IGZvbGRlclBhdGgsXG4gICAgICAgICAgICAgICAgICBleHBhbmRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgIGFwcHM6IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBmb2xkZXJzLnB1c2goZm9sZGVyKTtcbiAgICAgICAgICAgICAgICBmb2xkZXJNYXBbZm9sZGVyUGF0aF0gPSBmb2xkZXI7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZm9sZGVyLmFwcHMucHVzaChhcHBJbmZvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLmFwcEZvbGRlcnMgPSBfLnNvcnRCeShmb2xkZXJzLCBcInBhdGhcIik7XG5cbiAgICAgICAgICB2YXIgYXBwcyA9IFtdO1xuICAgICAgICAgIHZhciBkZWZhdWx0SW5mbyA9IHtcbiAgICAgICAgICAgICRpY29uVXJsOiBkZWZhdWx0SWNvblVybFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2godGhpcy5hcHBWaWV3cywgKGFwcFZpZXc6YW55KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICB2YXIgYXBwUGF0aCA9IGFwcFZpZXcuYXBwUGF0aDtcblxuICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgVE9ET1xuICAgICAgICAgICAgICAgYXBwVmlldy4kc2VsZWN0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgS3ViZXJuZXRlcy5zZXRKc29uKCRzY29wZSwgYXBwVmlldy5pZCwgJHNjb3BlLm1vZGVsLmFwcHMpO1xuICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgICAgdmFyIGFwcEluZm86YW55ID0gYW5ndWxhci5jb3B5KGRlZmF1bHRJbmZvKTtcbiAgICAgICAgICAgICAgaWYgKGFwcFBhdGgpIHtcbiAgICAgICAgICAgICAgICBhcHBJbmZvID0gYXBwTWFwW2FwcFBhdGhdIHx8IGFwcEluZm87XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKCFhcHBWaWV3LiRpbmZvKSB7XG4gICAgICAgICAgICAgICAgYXBwVmlldy4kaW5mbyA9IGRlZmF1bHRJbmZvO1xuICAgICAgICAgICAgICAgIGFwcFZpZXcuJGluZm8gPSBhcHBJbmZvO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGFwcFZpZXcuaWQgPSBhcHBQYXRoO1xuICAgICAgICAgICAgICBpZiAoIWFwcFZpZXcuJG5hbWUpIHtcbiAgICAgICAgICAgICAgICBhcHBWaWV3LiRuYW1lID0gYXBwSW5mby5uYW1lIHx8IGFwcFZpZXcuJG5hbWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKCFhcHBWaWV3LiRpY29uVXJsKSB7XG4gICAgICAgICAgICAgICAgYXBwVmlldy4kaWNvblVybCA9IGFwcEluZm8uJGljb25Vcmw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYXBwcy5wdXNoKGFwcFZpZXcpO1xuICAgICAgICAgICAgICBhcHBWaWV3LiRwb2RDb3VudGVycyA9IGNyZWF0ZUFwcFZpZXdQb2RDb3VudGVycyhhcHBWaWV3KTtcbiAgICAgICAgICAgICAgYXBwVmlldy4kcG9kQ291bnQgPSAoYXBwVmlldy5wb2RzIHx8IFtdKS5sZW5ndGg7XG4gICAgICAgICAgICAgIGFwcFZpZXcuJHJlcGxpY2F0aW9uQ29udHJvbGxlcnNUZXh0ID0gKGFwcFZpZXcucmVwbGljYXRpb25Db250cm9sbGVycyB8fCBbXSkubWFwKChpKSA9PiBpW1wiX2tleVwiXSkuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgIGFwcFZpZXcuJHNlcnZpY2VzVGV4dD0gKGFwcFZpZXcuc2VydmljZXMgfHwgW10pLm1hcCgoaSkgPT4gaVtcIl9rZXlcIl0pLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICBhcHBWaWV3LiRzZXJ2aWNlVmlld3MgPSBjcmVhdGVBcHBWaWV3U2VydmljZVZpZXdzKGFwcFZpZXcpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byB1cGRhdGUgYXBwVmlld3M6IFwiICsgZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgLy90aGlzLmFwcHMgPSBhcHBzO1xuICAgICAgICAgIHRoaXMuYXBwcyA9IHRoaXMuYXBwVmlld3M7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbG9nLndhcm4oXCJDYXVnaHQgZXJyb3I6IFwiICsgZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGRpc2NvdmVyUG9kQ29ubmVjdGlvbnMoZW50aXR5KSB7XG4gICAgICB2YXIgaW5mbyA9IENvcmUucGF0aEdldChlbnRpdHksIFtcInN0YXR1c1wiLCBcImluZm9cIl0pO1xuICAgICAgdmFyIGhvc3RQb3J0ID0gbnVsbDtcbiAgICAgIHZhciBjdXJyZW50U3RhdGUgPSBlbnRpdHkuc3RhdHVzIHx8IHt9O1xuICAgICAgdmFyIGRlc2lyZWRTdGF0ZSA9IGVudGl0eS5zcGVjIHx8IHt9O1xuICAgICAgdmFyIHBvZElkID0gZ2V0TmFtZShlbnRpdHkpO1xuICAgICAgdmFyIGhvc3QgPSBjdXJyZW50U3RhdGVbXCJob3N0SVBcIl07XG4gICAgICB2YXIgcG9kSVAgPSBjdXJyZW50U3RhdGVbXCJwb2RJUFwiXTtcbiAgICAgIHZhciBoYXNEb2NrZXIgPSBmYWxzZTtcbiAgICAgIHZhciBmb3VuZENvbnRhaW5lclBvcnQgPSBudWxsO1xuICAgICAgaWYgKGRlc2lyZWRTdGF0ZSkge1xuICAgICAgICB2YXIgY29udGFpbmVycyA9IGRlc2lyZWRTdGF0ZS5jb250YWluZXJzO1xuICAgICAgICBhbmd1bGFyLmZvckVhY2goY29udGFpbmVycywgKGNvbnRhaW5lcikgPT4ge1xuICAgICAgICAgIGlmICghaG9zdFBvcnQpIHtcbiAgICAgICAgICAgIHZhciBwb3J0cyA9IGNvbnRhaW5lci5wb3J0cztcbiAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChwb3J0cywgKHBvcnQpID0+IHtcbiAgICAgICAgICAgICAgaWYgKCFob3N0UG9ydCkge1xuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJQb3J0ID0gcG9ydC5jb250YWluZXJQb3J0O1xuICAgICAgICAgICAgICAgIHZhciBwb3J0TmFtZSA9IHBvcnQubmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgY29udGFpbmVySG9zdFBvcnQgPSBwb3J0Lmhvc3RQb3J0O1xuICAgICAgICAgICAgICAgIGlmIChjb250YWluZXJQb3J0ID09PSA4Nzc4IHx8IFwiam9sb2tpYVwiID09PSBwb3J0TmFtZSkge1xuICAgICAgICAgICAgICAgICAgaWYgKGNvbnRhaW5lclBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvZElQKSB7XG4gICAgICAgICAgICAgICAgICAgICAgZm91bmRDb250YWluZXJQb3J0ID0gY29udGFpbmVyUG9ydDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY29udGFpbmVySG9zdFBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBob3N0UG9ydCA9IGNvbnRhaW5lckhvc3RQb3J0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGZvdW5kQ29udGFpbmVyUG9ydCAmJiBwb2RJZCAmJiBpc1J1bm5pbmcoY3VycmVudFN0YXRlKSkge1xuICAgICAgICBpZiAoIUt1YmVybmV0ZXMuaXNPcGVuU2hpZnQpIHtcbiAgICAgICAgICAvLyBUT0RPIHRlbXAgd29ya2Fyb3VuZCBmb3IgazhzIG9uIEdLRSBodHRwczovL2dpdGh1Yi5jb20va3ViZXJuZXRlcy9rdWJlcm5ldGVzL2lzc3Vlcy8xNzE3MlxuICAgICAgICAgIGVudGl0eS4kam9sb2tpYVVybCA9IFVybEhlbHBlcnMuam9pbihLdWJlcm5ldGVzLm1hc3RlckFwaVVybCgpLFxuICAgICAgICAgICAgICBcImFwaVwiLFxuICAgICAgICAgICAgICBLdWJlcm5ldGVzLmRlZmF1bHRBcGlWZXJzaW9uLFxuICAgICAgICAgICAgICBcInByb3h5XCIsXG4gICAgICAgICAgICAgIFwibmFtZXNwYWNlc1wiLFxuICAgICAgICAgICAgICBlbnRpdHkubWV0YWRhdGEubmFtZXNwYWNlICxcbiAgICAgICAgICAgICAgXCJwb2RzXCIsXG4gICAgICAgICAgICAgIC8vXCJodHRwczpcIiArIHBvZElkICsgXCI6XCIgKyBmb3VuZENvbnRhaW5lclBvcnQsXG4gICAgICAgICAgICAgIHBvZElkICsgXCI6XCIgKyBmb3VuZENvbnRhaW5lclBvcnQsXG4gICAgICAgICAgICAgIFwiam9sb2tpYS9cIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW50aXR5LiRqb2xva2lhVXJsID0gVXJsSGVscGVycy5qb2luKEt1YmVybmV0ZXMubWFzdGVyQXBpVXJsKCksXG4gICAgICAgICAgICAgIFwiYXBpXCIsXG4gICAgICAgICAgICAgIEt1YmVybmV0ZXMuZGVmYXVsdEFwaVZlcnNpb24sXG4gICAgICAgICAgICAgIFwibmFtZXNwYWNlc1wiLFxuICAgICAgICAgICAgICBlbnRpdHkubWV0YWRhdGEubmFtZXNwYWNlICxcbiAgICAgICAgICAgICAgXCJwb2RzXCIsXG4gICAgICAgICAgICAgIFwiaHR0cHM6XCIgKyBwb2RJZCArIFwiOlwiICsgZm91bmRDb250YWluZXJQb3J0LFxuICAgICAgICAgICAgICBcInByb3h5L2pvbG9raWEvXCIpO1xuXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUZW1wbGF0ZVNlcnZpY2UobW9kZWwpIHtcbiAgICB2YXIga2V5ID0gY3JlYXRlS2V5KCdkZWZhdWx0JywgJ3RlbXBsYXRlcycsICdzZXJ2aWNlJyk7XG4gICAgdmFyIGFuc3dlciA9IG1vZGVsLnNlcnZpY2VzQnlLZXlba2V5XTtcbiAgICBsb2cuZGVidWcoXCJmb3VuZCB0ZW1wbGF0ZSBzZXJ2aWNlOiBcIiwgYW5zd2VyKTtcbiAgICByZXR1cm4gYW5zd2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtb2RlbCBzZXJ2aWNlIHdoaWNoIGtlZXBzIHRyYWNrIG9mIGFsbCB0aGUgcG9kcywgcmVwbGljYXRpb24gY29udHJvbGxlcnMgYW5kIHNlcnZpY2VzIGFsb25nXG4gICAqIHdpdGggdGhlaXIgYXNzb2NpYXRpb25zIGFuZCBzdGF0dXNcbiAgICovXG4gIF9tb2R1bGUuZmFjdG9yeSgnS3ViZXJuZXRlc01vZGVsJywgWyckcm9vdFNjb3BlJywgJyRodHRwJywgJ0t1YmVybmV0ZXNBcGlVUkwnLCAnS3ViZXJuZXRlc1N0YXRlJywgJ1dhdGNoZXJTZXJ2aWNlJywgJyRsb2NhdGlvbicsICckcmVzb3VyY2UnLCAoJHJvb3RTY29wZSwgJGh0dHAsIEFwcExpYnJhcnlVUkwsIEt1YmVybmV0ZXNTdGF0ZSwgd2F0Y2hlcjpXYXRjaGVyU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyZXNvdXJjZTpuZy5yZXNvdXJjZS5JUmVzb3VyY2VTZXJ2aWNlKSA9PiB7XG5cbiAgICB2YXIgJHNjb3BlID0gbmV3IEt1YmVybmV0ZXNNb2RlbFNlcnZpY2UoKTtcbiAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcblxuICAgIC8vIGNyZWF0ZSBhbGwgb2Ygb3VyIHJlc291cmNlIGNsYXNzZXNcbiAgICB2YXIgdHlwZU5hbWVzID0gd2F0Y2hlci5nZXRUeXBlcygpO1xuICAgIF8uZm9yRWFjaCh0eXBlTmFtZXMsICh0eXBlOnN0cmluZykgPT4ge1xuICAgICAgdmFyIHVybFRlbXBsYXRlID0gdXJpVGVtcGxhdGVGb3JLdWJlcm5ldGVzS2luZCh0eXBlKTtcbiAgICAgICRzY29wZVt0eXBlICsgJ1Jlc291cmNlJ10gPSBjcmVhdGVSZXNvdXJjZSh0eXBlLCB1cmxUZW1wbGF0ZSwgJHJlc291cmNlLCAkc2NvcGUpO1xuICAgIH0pO1xuXG4gICAgaWYgKCFpc09wZW5TaGlmdCkge1xuICAgICAgLy8gcmVnaXN0ZXIgY3VzdG9tIFVSTCBmYWN0b3JpZXMgZm9yIHRlbXBsYXRlcy9wcm9qZWN0c1xuICAgICAgd2F0Y2hlci5yZWdpc3RlckN1c3RvbVVybEZ1bmN0aW9uKEt1YmVybmV0ZXNBUEkuV2F0Y2hUeXBlcy5CVUlMRF9DT05GSUdTLCAob3B0aW9uczpLdWJlcm5ldGVzQVBJLks4U09wdGlvbnMpID0+IHtcbiAgICAgICAgdmFyIHRlbXBsYXRlU2VydmljZSA9IGdldFRlbXBsYXRlU2VydmljZSgkc2NvcGUpO1xuICAgICAgICBpZiAodGVtcGxhdGVTZXJ2aWNlKSB7XG4gICAgICAgICAgcmV0dXJuIFVybEhlbHBlcnMuam9pbih0ZW1wbGF0ZVNlcnZpY2UucHJveHlVcmwsICcvb2FwaS92MS9uYW1lc3BhY2VzL2RlZmF1bHQvYnVpbGRjb25maWdzLycpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSk7XG4gICAgICAvLyByZWdpc3RlciBjdXN0b20gVVJMIGZhY3RvcmllcyBmb3IgdGVtcGxhdGVzL3Byb2plY3RzXG4gICAgICB3YXRjaGVyLnJlZ2lzdGVyQ3VzdG9tVXJsRnVuY3Rpb24oS3ViZXJuZXRlc0FQSS5XYXRjaFR5cGVzLlRFTVBMQVRFUywgKG9wdGlvbnM6S3ViZXJuZXRlc0FQSS5LOFNPcHRpb25zKSA9PiB7XG4gICAgICAgIHZhciB0ZW1wbGF0ZVNlcnZpY2UgPSBnZXRUZW1wbGF0ZVNlcnZpY2UoJHNjb3BlKTtcbiAgICAgICAgaWYgKHRlbXBsYXRlU2VydmljZSkge1xuICAgICAgICAgIHJldHVybiBVcmxIZWxwZXJzLmpvaW4odGVtcGxhdGVTZXJ2aWNlLnByb3h5VXJsLCAnL29hcGkvdjEvbmFtZXNwYWNlcy9kZWZhdWx0L3RlbXBsYXRlcy8nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIHJlZ2lzdGVyIGZvciBhbGwgdXBkYXRlcyBvbiBvYmplY3RzXG5cdFx0d2F0Y2hlci5yZWdpc3Rlckxpc3RlbmVyKChvYmplY3RzOk9iamVjdE1hcCkgPT4ge1xuXHRcdFx0dmFyIHR5cGVzID0gd2F0Y2hlci5nZXRUeXBlcygpO1xuXHRcdFx0Xy5mb3JFYWNoKHR5cGVzLCAodHlwZTpzdHJpbmcpID0+IHtcblx0XHRcdFx0c3dpdGNoICh0eXBlKSB7XG5cdFx0XHRcdFx0Y2FzZSBXYXRjaFR5cGVzLlNFUlZJQ0VTOlxuXHRcdFx0XHRcdFx0dmFyIGl0ZW1zID0gcG9wdWxhdGVLZXlzKG9iamVjdHNbdHlwZV0pO1xuXHRcdFx0XHRcdFx0YW5ndWxhci5mb3JFYWNoKGl0ZW1zLCAoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICBpdGVtLnByb3h5VXJsID0ga3ViZXJuZXRlc1Byb3h5VXJsRm9yU2VydmljZShrdWJlcm5ldGVzQXBpVXJsKCksIGl0ZW0pO1xuICAgICAgICAgICAgfSk7XG5cdFx0XHRcdFx0XHQkc2NvcGVbdHlwZV0gPSBpdGVtcztcblx0XHRcdFx0XHRcdGJyZWFrO1xuICAgICAgICAgIGNhc2UgV2F0Y2hUeXBlcy5URU1QTEFURVM6XG4gICAgICAgICAgY2FzZSBXYXRjaFR5cGVzLlJPVVRFUzpcbiAgICAgICAgICBjYXNlIFdhdGNoVHlwZXMuQlVJTERTOlxuICAgICAgICAgIGNhc2UgV2F0Y2hUeXBlcy5CVUlMRF9DT05GSUdTOlxuICAgICAgICAgIGNhc2UgV2F0Y2hUeXBlcy5JTUFHRV9TVFJFQU1TOlxuICAgICAgICAgICAgLy8gZG9uJ3QgcHV0IGEgYnJlYWsgaGVyZSA6LSlcblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0JHNjb3BlW3R5cGVdID0gcG9wdWxhdGVLZXlzKG9iamVjdHNbdHlwZV0pO1xuXHRcdFx0XHR9XG4gICAgICAgIGxvZy5kZWJ1ZyhcIlR5cGU6IFwiLCB0eXBlLCBcIiBvYmplY3Q6IFwiLCAkc2NvcGVbdHlwZV0pO1xuXHRcdFx0fSk7XG5cdFx0XHQkc2NvcGUubWF5YmVJbml0KCk7XG4gICAgICAkcm9vdFNjb3BlLiRicm9hZGNhc3QoJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCAkc2NvcGUpO1xuICAgICAgQ29yZS4kYXBwbHkoJHJvb3RTY29wZSk7XG5cdFx0fSk7XG5cbiAgICAvLyBzZXQgdGhlIHNlbGVjdGVkIG5hbWVzcGFjZSBpZiBzZXQgaW4gdGhlIGxvY2F0aW9uIGJhclxuICAgIC8vIG90aGVyd2lzZSB1c2Ugd2hhdGV2ZXIgcHJldmlvdXNseSBzZWxlY3RlZCBuYW1lc3BhY2UgaXNcbiAgICAvLyBhdmFpbGFibGVcbiAgICB2YXIgc2VhcmNoID0gJGxvY2F0aW9uLnNlYXJjaCgpO1xuICAgIGlmICgnbmFtZXNwYWNlJyBpbiBzZWFyY2gpIHtcbiAgICAgIHdhdGNoZXIuc2V0TmFtZXNwYWNlKHNlYXJjaFsnbmFtZXNwYWNlJ10pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNlbGVjdFBvZHMocG9kcywgbmFtZXNwYWNlLCBsYWJlbHMpIHtcbiAgICAgIHJldHVybiBwb2RzLmZpbHRlcigocG9kKSA9PiB7XG4gICAgICAgIHJldHVybiBnZXROYW1lc3BhY2UocG9kKSA9PT0gbmFtZXNwYWNlICYmIHNlbGVjdG9yTWF0Y2hlcyhsYWJlbHMsIGdldExhYmVscyhwb2QpKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gJHNjb3BlO1xuICB9XSk7XG5cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9rdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0ludGVyZmFjZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4va3ViZXJuZXRlcy90cy9rdWJlcm5ldGVzTW9kZWwudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyUGx1Z2luLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckVucmljaGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBjbGlja0FwcHJvdmUoZWxlbWVudCwgdXJsKSB7XG4gICAgdmFyICRzY29wZTogYW55ID0gYW5ndWxhci5lbGVtZW50KGVsZW1lbnQpLnNjb3BlKCk7XG4gICAgaWYgKCRzY29wZSkge1xuICAgICAgJHNjb3BlLmFwcHJvdmUodXJsLCBlbGVtZW50LnRleHQpO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCB2YXIgSmVua2luc0xvZ0NvbnRyb2xsZXIgPSBfbW9kdWxlLmNvbnRyb2xsZXIoXCJEZXZlbG9wZXIuSmVua2luc0xvZ0NvbnRyb2xsZXJcIiwgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICAkdGVtcGxhdGVDYWNoZTpuZy5JVGVtcGxhdGVDYWNoZVNlcnZpY2UsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCAkcm91dGVQYXJhbXMsICRodHRwLCAkdGltZW91dCwgJG1vZGFsLCBLdWJlcm5ldGVzQXBpVVJMLCBTZXJ2aWNlUmVnaXN0cnksICRlbGVtZW50KSA9PiB7XG5cbiAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG5cbiAgICAkc2NvcGUuc2VsZWN0ZWRCdWlsZCA9ICRzY29wZS4kZXZhbCgnYnVpbGQnKSB8fCAkc2NvcGUuJGV2YWwoJ3NlbGVjdGVkQnVpbGQnKTtcblxuICAgICRzY29wZS5pZCA9ICRzY29wZS4kZXZhbCgnYnVpbGQuaWQnKSB8fCAkcm91dGVQYXJhbXNbXCJpZFwiXTtcbiAgICAkc2NvcGUuc2NoZW1hID0gS3ViZXJuZXRlc1NjaGVtYTtcbiAgICAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlID0ge307XG5cbiAgICAkZWxlbWVudC5vbignJGRlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAkc2NvcGUuJGRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgICRzY29wZS5sb2cgPSB7XG4gICAgICBodG1sOiBcIlwiLFxuICAgICAgc3RhcnQ6IDAsXG4gICAgICBmaXJzdElkeDogbnVsbFxuICAgIH07XG5cbiAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgdXBkYXRlSmVua2luc0xpbmsoKTtcbiAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgfSk7XG5cbiAgICAkc2NvcGUuJG9uKCdqZW5raW5zU2VsZWN0ZWRCdWlsZCcsIChldmVudCwgYnVpbGQpID0+IHtcbiAgICAgIGxvZy5pbmZvKFwiPT09PSBqZW5raW5zIGJ1aWxkIHNlbGVjdGVkISBcIiArIGJ1aWxkLmlkICsgXCIgXCIgKyBidWlsZC4kam9iSWQpO1xuICAgICAgJHNjb3BlLnNlbGVjdGVkQnVpbGQgPSBidWlsZDtcbiAgICB9KTtcblxuXG4gICAgJHNjb3BlLiR3YXRjaCgnc2VsZWN0ZWRCdWlsZCcsIChzZWxlY3RlZEJ1aWxkKSA9PiB7XG4gICAgICBsb2cuaW5mbyhcIlNlbGVjdGVkIGJ1aWxkIHVwZGF0ZWQ6IFwiLCBzZWxlY3RlZEJ1aWxkKTtcbiAgICAgICRzY29wZS5mZXRjaCgpO1xuICAgIH0pO1xuXG4gICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gY3JlYXRlSmVua2luc0JyZWFkY3J1bWJzKCRzY29wZS5pZCwgZ2V0Sm9iSWQoKSwgZ2V0QnVpbGRJZCgpKTtcbiAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gY3JlYXRlSmVua2luc1N1Yk5hdkJhcnMoJHNjb3BlLmlkLCBnZXRKb2JJZCgpLCBnZXRCdWlsZElkKCksIHtcbiAgICAgIGxhYmVsOiBcIkxvZ1wiLFxuICAgICAgdGl0bGU6IFwiVmlld3MgdGhlIGxvZ3Mgb2YgdGhpcyBidWlsZFwiXG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBnZXRKb2JJZCgpIHtcbiAgICAgIC8vIGxldHMgYWxsb3cgdGhlIHBhcmVudCBzY29wZSB0byBiZSB1c2VkIHRvbyBmb3Igd2hlbiB0aGlzIGlzIHVzZWQgYXMgYSBwYW5lbFxuICAgICAgcmV0dXJuICRyb3V0ZVBhcmFtc1tcImpvYlwiXSB8fCAoJHNjb3BlLnNlbGVjdGVkQnVpbGQgfHwge30pLiRqb2JJZDtcbiAgICB9XG4gICAgJHNjb3BlLmdldEpvYklkID0gZ2V0Sm9iSWQ7XG5cbiAgICBmdW5jdGlvbiBnZXRCdWlsZElkKCkge1xuICAgICAgLy8gbGV0cyBhbGxvdyB0aGUgcGFyZW50IHNjb3BlIHRvIGJlIHVzZWQgdG9vIGZvciB3aGVuIHRoaXMgaXMgdXNlZCBhcyBhIHBhbmVsXG4gICAgICByZXR1cm4gJHJvdXRlUGFyYW1zW1wiYnVpbGRcIl0gfHwgKCRzY29wZS5zZWxlY3RlZEJ1aWxkIHx8IHt9KS5pZDtcbiAgICB9XG4gICAgJHNjb3BlLmdldEJ1aWxkSWQgPSBnZXRCdWlsZElkO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlSmVua2luc0xpbmsoKSB7XG4gICAgICB2YXIgamVua2luc1VybCA9IGplbmtpbnNMaW5rKCk7XG4gICAgICBpZiAoamVua2luc1VybCkge1xuICAgICAgICAkc2NvcGUuJHZpZXdKZW5raW5zQnVpbGRMaW5rID0gVXJsSGVscGVycy5qb2luKGplbmtpbnNVcmwsIFwiam9iXCIsIGdldEpvYklkKCksIGdldEJ1aWxkSWQoKSk7XG4gICAgICAgICRzY29wZS4kdmlld0plbmtpbnNMb2dMaW5rID0gVXJsSGVscGVycy5qb2luKCRzY29wZS4kdmlld0plbmtpbnNCdWlsZExpbmssIFwiY29uc29sZVwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcXVlcnlTaXplID0gNTAwMDA7XG5cbiAgICAkc2NvcGUuYXBwcm92ZSA9ICh1cmwsIG9wZXJhdGlvbikgPT4ge1xuICAgICAgdmFyIG1vZGFsID0gJG1vZGFsLm9wZW4oe1xuICAgICAgdGVtcGxhdGVVcmw6IFVybEhlbHBlcnMuam9pbih0ZW1wbGF0ZVBhdGgsICdqZW5raW5zQXBwcm92ZU1vZGFsLmh0bWwnKSxcbiAgICAgIGNvbnRyb2xsZXI6IFsnJHNjb3BlJywgJyRtb2RhbEluc3RhbmNlJywgKCRzY29wZSwgJG1vZGFsSW5zdGFuY2UpID0+IHtcbiAgICAgICAgJHNjb3BlLm9wZXJhdGlvbiA9IG9wZXJhdGlvbjtcbiAgICAgICAgJHNjb3BlLmhlYWRlciA9IG9wZXJhdGlvbiArIFwiP1wiO1xuICAgICAgICAkc2NvcGUub2sgPSAoKSA9PiB7XG4gICAgICAgICAgbW9kYWwuY2xvc2UoKTtcbiAgICAgICAgICBwb3N0VG9KZW5raW5zKHVybCwgb3BlcmF0aW9uKTtcbiAgICAgICAgfTtcbiAgICAgICAgJHNjb3BlLmNhbmNlbCA9ICgpID0+IHtcbiAgICAgICAgICBtb2RhbC5kaXNtaXNzKCk7XG4gICAgICAgIH07XG4gICAgICB9XVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIHBvc3RUb0plbmtpbnModXJpLCBvcGVyYXRpb24pIHtcbiAgICAgIHZhciB1cmwgPSAgS3ViZXJuZXRlcy5rdWJlcm5ldGVzUHJveHlVcmxGb3JTZXJ2aWNlQ3VycmVudE5hbWVzcGFjZShqZW5raW5zU2VydmljZU5hbWVBbmRQb3J0LCB1cmkpO1xuICAgICAgaWYgKHVybCkge1xuICAgICAgICB2YXIgYm9keSA9IG51bGw7XG4gICAgICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBsb2cuaW5mbyhcInBvc3RpbmcgdG8gamVua2luc1VybDogXCIgKyB1cmwpO1xuICAgICAgICAkaHR0cC5wb3N0KHVybCwgYm9keSwgY29uZmlnKS5cbiAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgbG9nLmluZm8oXCJNYW5hZ2VkIHRvIFwiICsgb3BlcmF0aW9uICsgXCIgYXQgXCIgKyB1cmwpO1xuICAgICAgICAgIH0pLlxuICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCBcIiArIG9wZXJhdGlvbiArIFwiIGpvYiBhdCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2cud2FybihcIkNhbm5vdCBwb3N0IHRvIGplbmtpbnMgVVJJOiBcIiArIHVyaSArIFwiIGFzIG5vIGplbmtpbnMgZm91bmQhXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgICRzY29wZS4ka2VlcFBvbGxpbmcgPSAoKSA9PiBLdWJlcm5ldGVzLmtlZXBQb2xsaW5nTW9kZWw7XG5cbiAgICAkc2NvcGUuZmV0Y2ggPSBQb2xsSGVscGVycy5zZXR1cFBvbGxpbmcoJHNjb3BlLCAobmV4dDooKSA9PiB2b2lkKSA9PiB7XG4gICAgICBpZiAoJHNjb3BlLiRldmFsKCdoaWRlTG9ncyAmJiAhYnVpbGQuYnVpbGRpbmcnKSkge1xuICAgICAgICBsb2cuZGVidWcoXCJMb2cgaGlkZGVuLCBub3QgZmV0Y2hpbmcgbG9nc1wiKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nLmRlYnVnKFwiRmV0Y2hpbmcgbG9ncyBmb3IgYnVpbGQ6IFwiLCAkc2NvcGUuJGV2YWwoJ2J1aWxkJykpO1xuICAgICAgfVxuICAgICAgdmFyIGJ1aWxkSWQgPSBnZXRCdWlsZElkKCk7XG4gICAgICB2YXIgam9iSWQgPSBnZXRKb2JJZCgpO1xuICAgICAgLy9sb2cuaW5mbyhcIj09PSBqZW5raW5zIGxvZyBxdWVyeWluZyBqb2IgXCIgKyBqb2JJZCArIFwiIGJ1aWxkIFwiICsgYnVpbGRJZCArIFwiIHNlbGVjdGVkIGJ1aWxkIFwiICsgICRzY29wZS5zZWxlY3RlZEJ1aWxkKTtcbiAgICAgIGlmIChqb2JJZCAmJiBidWlsZElkKSB7XG4gICAgICAgIGlmICgkc2NvcGUuYnVpbGRJZCAhPT0gYnVpbGRJZCB8fCAkc2NvcGUuam9iSWQgIT09IGpvYklkKSB7XG4gICAgICAgICAgLy8gbGV0cyBjbGVhciB0aGUgcXVlcnlcbiAgICAgICAgICAkc2NvcGUubG9nID0ge1xuICAgICAgICAgICAgaHRtbDogXCJcIixcbiAgICAgICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICAgICAgZmlyc3RJZHg6IG51bGxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgICRzY29wZS5idWlsZElkID0gYnVpbGRJZDtcbiAgICAgICAgJHNjb3BlLmpvYklkID0gam9iSWQ7XG5cbiAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMua3ViZXJuZXRlc1Byb3h5VXJsRm9yU2VydmljZUN1cnJlbnROYW1lc3BhY2UoamVua2luc1NlcnZpY2VOYW1lQW5kUG9ydCwgVXJsSGVscGVycy5qb2luKFwiam9iXCIsIGpvYklkLCBidWlsZElkLCBcImZhYnJpYzgvbG9nSHRtbD90YWlsPTEmc3RhcnQ9XCIgKyAkc2NvcGUubG9nLnN0YXJ0ICsgXCImc2l6ZT1cIiArIHF1ZXJ5U2l6ZSkpO1xuICAgICAgICBpZiAoJHNjb3BlLmxvZy5maXJzdElkeCAhPT0gbnVsbCkge1xuICAgICAgICAgIHVybCArPSBcIiZmaXJzdD1cIiArICRzY29wZS5sb2cuZmlyc3RJZHg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVybCAmJiAoISRzY29wZS5sb2cuZmV0Y2hlZCB8fCBLdWJlcm5ldGVzLmtlZXBQb2xsaW5nTW9kZWwpKSB7XG4gICAgICAgICAgJGh0dHAuZ2V0KHVybCkuXG4gICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlQ2x1c3RlcklQc0luSHRtbCA9IHJlcGxhY2VDbHVzdGVySXBGdW5jdGlvbigpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEkc2NvcGUubG9nLmxvZ3MpIHtcbiAgICAgICAgICAgICAgICAgICRzY29wZS5sb2cubG9ncyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbGluZXMgPSBkYXRhLmxpbmVzO1xuICAgICAgICAgICAgICAgIHZhciByZXR1cm5lZExlbmd0aCA9IGRhdGEucmV0dXJuZWRMZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxvZ0xlbmd0aCA9IGRhdGEubG9nTGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciByZXR1cm5lZFN0YXJ0ID0gZGF0YS5zdGFydDtcbiAgICAgICAgICAgICAgICB2YXIgZWFybGllckxvZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmIChhbmd1bGFyLmlzRGVmaW5lZChyZXR1cm5lZFN0YXJ0KSkge1xuICAgICAgICAgICAgICAgICAgZWFybGllckxvZyA9IHJldHVybmVkU3RhcnQgPCAkc2NvcGUubG9nLnN0YXJ0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbGluZVNwbGl0ID0gZGF0YS5saW5lU3BsaXQ7XG4gICAgICAgICAgICAgICAgLy8gbG9nLmluZm8oXCJzdGFydCB3YXM6IFwiICsgJHNjb3BlLmxvZy5zdGFydCArIFwiIGZpcnN0OiBcIiArICRzY29wZS5sb2cuZmlyc3RJZHggKyBcIiA9PiByZXR1cm5lZExlbmd0aDogXCIgKyByZXR1cm5lZExlbmd0aCArIFwiIGxvZ0xlbmd0aDogXCIgKyBsb2dMZW5ndGggKyAgXCIgcmV0dXJuZWRTdGFydDogXCIgKyByZXR1cm5lZFN0YXJ0ICsgXCIgZWFybGllckxvZzogXCIgKyBlYXJsaWVyTG9nICsgXCIgbGluZVNwbGl0OiBcIiArIGxpbmVTcGxpdCk7XG4gICAgICAgICAgICAgICAgaWYgKGxpbmVzKSB7XG4gICAgICAgICAgICAgICAgICB2YXIgY3VycmVudExvZ3MgPSAkc2NvcGUubG9nLmxvZ3M7XG5cbiAgICAgICAgICAgICAgICAgIC8vIGxldHMgcmUtam9pbiBzcGxpdCBsaW5lc1xuICAgICAgICAgICAgICAgICAgaWYgKGxpbmVTcGxpdCAmJiBjdXJyZW50TG9ncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3RPZkxpbmU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlYXJsaWVyTG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICByZXN0T2ZMaW5lID0gbGluZXMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3RPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRMb2dzW2xhc3RJbmRleF0gPSByZXBsYWNlQ2x1c3RlcklQc0luSHRtbChyZXN0T2ZMaW5lICsgY3VycmVudExvZ3NbbGFzdEluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IGN1cnJlbnRMb2dzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgICAgICAgcmVzdE9mTGluZSA9IGxpbmVzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3RPZkxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRMb2dzW2xhc3RJbmRleF0gPSByZXBsYWNlQ2x1c3RlcklQc0luSHRtbChjdXJyZW50TG9nc1tsYXN0SW5kZXhdICsgcmVzdE9mTGluZSk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmVzW2ldID0gcmVwbGFjZUNsdXN0ZXJJUHNJbkh0bWwobGluZXNbaV0pO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKGVhcmxpZXJMb2cpIHtcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmxvZy5sb2dzID0gbGluZXMuY29uY2F0KGN1cnJlbnRMb2dzKTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICRzY29wZS5sb2cubG9ncyA9IGN1cnJlbnRMb2dzLmNvbmNhdChsaW5lcyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBtb3ZlRm9yd2FyZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKGFuZ3VsYXIuaXNEZWZpbmVkKHJldHVybmVkU3RhcnQpKSB7XG4gICAgICAgICAgICAgICAgICBpZiAocmV0dXJuZWRTdGFydCA+ICRzY29wZS5sb2cuc3RhcnQgJiYgJHNjb3BlLmxvZy5zdGFydCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyB3ZSd2ZSBqdW1wZWQgdG8gdGhlIGVuZCBvZiB0aGUgZmlsZSB0byByZWFkIHRoZSB0YWlsIG9mIGl0XG4gICAgICAgICAgICAgICAgICAgICRzY29wZS5sb2cuc3RhcnQgPSByZXR1cm5lZFN0YXJ0O1xuICAgICAgICAgICAgICAgICAgICAkc2NvcGUubG9nLmZpcnN0SWR4ID0gcmV0dXJuZWRTdGFydDtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJHNjb3BlLmxvZy5maXJzdElkeCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBsZXRzIHJlbWVtYmVyIHdoZXJlIHRoZSBmaXJzdCByZXF1ZXN0IHN0YXJ0ZWRcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmxvZy5maXJzdElkeCA9IHJldHVybmVkU3RhcnQ7XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJldHVybmVkU3RhcnQgPCAkc2NvcGUubG9nLmZpcnN0SWR4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHdlJ3ZlIGdvdCBhbiBlYXJsaWVyIGJpdCBvZiB0aGUgbG9nXG4gICAgICAgICAgICAgICAgICAgIC8vIGFmdGVyIHN0YXJ0aW5nIGF0IHRoZSB0YWlsXG4gICAgICAgICAgICAgICAgICAgIC8vIHNvIGxldHMgbW92ZSBmaXJzdElkeCBiYWNrd2FyZHMgYW5kIGxlYXZlIHN0YXJ0IGFzIGl0IGlzIChhdCB0aGUgZW5kIG9mIHRoZSBmaWxlKVxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUubG9nLmZpcnN0SWR4ID0gcmV0dXJuZWRTdGFydDtcbiAgICAgICAgICAgICAgICAgICAgbW92ZUZvcndhcmQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1vdmVGb3J3YXJkICYmIHJldHVybmVkTGVuZ3RoICYmICFlYXJsaWVyTG9nKSB7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUubG9nLnN0YXJ0ICs9IHJldHVybmVkTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgaWYgKGxvZ0xlbmd0aCAmJiAkc2NvcGUubG9nLnN0YXJ0ID4gbG9nTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICRzY29wZS5sb2cuc3RhcnQgPSBsb2dMZW5ndGg7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHVwZGF0ZUplbmtpbnNMaW5rKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgJHNjb3BlLmxvZy5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgLy8gQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgICAgfSkuXG4gICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkc2NvcGUubG9nLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICBuZXh0KCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKCRzY29wZS5mZXRjaCkpIHtcbiAgICAgICRzY29wZS5mZXRjaCgpO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gcmVwbGFjZUNsdXN0ZXJJcEZ1bmN0aW9uKCkge1xuICAgICAgZnVuY3Rpb24gY3JlYXRlUmVwbGFjZUZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gICAgICAgIHJldHVybiAodGV4dCkgPT4gcmVwbGFjZVRleHQodGV4dCwgZnJvbSwgdG8pO1xuICAgICAgfVxuXG4gICAgICB2YXIgcmVwbGFjZW1lbnRzID0gW107XG4gICAgICBhbmd1bGFyLmZvckVhY2goJHNjb3BlLm1vZGVsLnNlcnZpY2VzLCAoc2VydmljZSkgPT4ge1xuICAgICAgICB2YXIgJHBvcnRhbElQID0gc2VydmljZS4kcG9ydGFsSVA7XG4gICAgICAgIHZhciAkc2VydmljZVVybCA9IHNlcnZpY2UuJHNlcnZpY2VVcmw7XG4gICAgICAgIHZhciAkcG9ydHNUZXh0ID0gc2VydmljZS4kcG9ydHNUZXh0O1xuICAgICAgICBpZiAoJHBvcnRhbElQICYmICRzZXJ2aWNlVXJsKSB7XG4gICAgICAgICAgdmFyIGlkeCA9ICRzZXJ2aWNlVXJsLmluZGV4T2YoXCI6Ly9cIik7XG4gICAgICAgICAgaWYgKGlkeCA+IDApIHtcbiAgICAgICAgICAgIHZhciByZXBsYWNlV2l0aCA9ICRzZXJ2aWNlVXJsLnN1YnN0cmluZyhpZHgsICRzZXJ2aWNlVXJsLmxlbmd0aCk7XG4gICAgICAgICAgICBpZiAoIXJlcGxhY2VXaXRoLmVuZHNXaXRoKFwiL1wiKSkge1xuICAgICAgICAgICAgICByZXBsYWNlV2l0aCArPSBcIi9cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXBsYWNlV2l0aC5sZW5ndGggPiA0KSB7XG4gICAgICAgICAgICAgIHJlcGxhY2VtZW50cy5wdXNoKGNyZWF0ZVJlcGxhY2VGdW5jdGlvbihcbiAgICAgICAgICAgICAgICAgICAgXCI6Ly9cIiArICRwb3J0YWxJUCArIFwiL1wiLFxuICAgICAgICAgICAgICAgICAgICByZXBsYWNlV2l0aFxuICAgICAgICAgICAgICAgICAgICApKTtcbiAgICAgICAgICAgICAgaWYgKCRwb3J0c1RleHQpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3VmZml4ID0gXCI6XCIgKyAkcG9ydHNUZXh0O1xuICAgICAgICAgICAgICAgIHZhciBzZXJ2aWNlV2l0aFBvcnQgPSByZXBsYWNlV2l0aC5zdWJzdHJpbmcoMCwgcmVwbGFjZVdpdGgubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgaWYgKCFzZXJ2aWNlV2l0aFBvcnQuZW5kc1dpdGgoc3VmZml4KSkge1xuICAgICAgICAgICAgICAgICAgc2VydmljZVdpdGhQb3J0ICs9IHN1ZmZpeDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VydmljZVdpdGhQb3J0ICs9IFwiL1wiO1xuICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50cy5wdXNoKGNyZWF0ZVJlcGxhY2VGdW5jdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICBcIjovL1wiICsgJHBvcnRhbElQICsgXCI6XCIgKyAkcG9ydHNUZXh0ICsgXCIvXCIsXG4gICAgICAgICAgICAgICAgICAgICAgc2VydmljZVdpdGhQb3J0XG4gICAgICAgICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBmdW5jdGlvbiBhZGRSZXBsYWNlRm4oZnJvbSwgdG8pIHtcbiAgICAgICAgcmVwbGFjZW1lbnRzLnB1c2goKHRleHQpID0+IHtcbiAgICAgICAgICByZXR1cm4gcmVwbGFjZVRleHQodGV4dCwgZnJvbSwgdG8pO1xuICAgICAgICB9KTtcblxuICAgICAgfVxuICAgICAgYWRkUmVwbGFjZUZuKFwiW0lORk9dXCIsIFwiPHNwYW4gY2xhc3M9J2xvZy1zdWNjZXNzJz5bSU5GT108L3NwYW4+XCIpO1xuICAgICAgYWRkUmVwbGFjZUZuKFwiW1dBUk5dXCIsIFwiPHNwYW4gY2xhc3M9J2xvZy13YXJuJz5bV0FSTl08L3NwYW4+XCIpO1xuICAgICAgYWRkUmVwbGFjZUZuKFwiW1dBUk5JTkddXCIsIFwiPHNwYW4gY2xhc3M9J2xvZy13YXJuJz5bV0FSTklOR108L3NwYW4+XCIpO1xuICAgICAgYWRkUmVwbGFjZUZuKFwiW0VSUk9SXVwiLCBcIjxzcGFuIGNsYXNzPSdsb2ctZXJyb3InPltFUlJPUl08L3NwYW4+XCIpO1xuICAgICAgYWRkUmVwbGFjZUZuKFwiRkFJTFVSRVwiLCBcIjxzcGFuIGNsYXNzPSdsb2ctZXJyb3InPkZBSUxVUkU8L3NwYW4+XCIpO1xuICAgICAgYWRkUmVwbGFjZUZuKFwiU1VDQ0VTU1wiLCBcIjxzcGFuIGNsYXNzPSdsb2ctc3VjY2Vzcyc+U1VDQ0VTUzwvc3Bhbj5cIik7XG5cbiAgICAgIC8vIGxldHMgdHJ5IGNvbnZlcnQgdGhlIFByb2NlZWQgLyBBYm9ydCBsaW5rc1xuICAgICAgcmVwbGFjZW1lbnRzLnB1c2goKHRleHQpID0+IHtcbiAgICAgICAgdmFyIHByZWZpeCA9IFwiPGEgaHJlZj0nIycgb25jbGljaz1cXFwibmV3IEFqYXguUmVxdWVzdCgnXCI7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB3aGlsZSAoaWR4ID49IDApIHtcbiAgICAgICAgICBpZHggPSB0ZXh0LmluZGV4T2YocHJlZml4LCBpZHgpO1xuICAgICAgICAgIGlmIChpZHggPj0gMCkge1xuICAgICAgICAgICAgdmFyIHN0YXJ0ID0gaWR4ICsgcHJlZml4Lmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBlbmRRdW90ZSA9IHRleHQuaW5kZXhPZihcIidcIiwgc3RhcnQgKyAxKTtcbiAgICAgICAgICAgIGlmIChlbmRRdW90ZSA8PSAwKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGVuZERvdWJsZVF1b3RlID0gdGV4dC5pbmRleE9mKCdcIicsIGVuZFF1b3RlICsgMSk7XG4gICAgICAgICAgICBpZiAoZW5kRG91YmxlUXVvdGUgPD0gMCkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB1cmwgPSB0ZXh0LnN1YnN0cmluZyhzdGFydCwgZW5kUXVvdGUpO1xuICAgICAgICAgICAgLy8gVE9ETyB1c2luZyAkY29tcGlsZSBpcyBhIHRhZCBjb21wbGV4LCBmb3Igbm93IGxldHMgY2hlYXQgd2l0aCBhIGxpdHRsZSBvbmNsaWNrIDspXG4gICAgICAgICAgICAvL3RleHQgPSB0ZXh0LnN1YnN0cmluZygwLCBpZHgpICsgXCI8YSBjbGFzcz0nYnRuIGJ0bi1kZWZhdWx0IGJ0bi1sZycgbmctY2xpY2s9XFxcImFwcHJvdmUoJ1wiICsgdXJsICsgXCInKVxcXCJcIiArIHRleHQuc3Vic3RyaW5nKGVuZERvdWJsZVF1b3RlICsgMSk7XG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC5zdWJzdHJpbmcoMCwgaWR4KSArIFwiPGEgY2xhc3M9J2J0biBidG4tZGVmYXVsdCBidG4tbGcnIG9uY2xpY2s9XFxcIkRldmVsb3Blci5jbGlja0FwcHJvdmUodGhpcywgJ1wiICsgdXJsICsgXCInKVxcXCJcIiArIHRleHQuc3Vic3RyaW5nKGVuZERvdWJsZVF1b3RlICsgMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odGV4dCkge1xuICAgICAgICB2YXIgYW5zd2VyID0gdGV4dDtcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKHJlcGxhY2VtZW50cywgKGZuKSA9PiB7XG4gICAgICAgICAgYW5zd2VyID0gZm4oYW5zd2VyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBhbnN3ZXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVwbGFjZVRleHQodGV4dCwgZnJvbSwgdG8pIHtcbiAgICAgIGlmIChmcm9tICYmIHRvICYmIHRleHQpIHtcbiAgICAgICAgLy9sb2cuaW5mbyhcIlJlcGxhY2luZyAnXCIgKyBmcm9tICsgXCInID0+ICdcIiArIHRvICsgXCInXCIpO1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICBpZHggPSB0ZXh0LmluZGV4T2YoZnJvbSwgaWR4KTtcbiAgICAgICAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgICAgICAgIHRleHQgPSB0ZXh0LnN1YnN0cmluZygwLCBpZHgpICsgdG8gKyB0ZXh0LnN1YnN0cmluZyhpZHggKyBmcm9tLmxlbmd0aCk7XG4gICAgICAgICAgICBpZHggKz0gdG8ubGVuZ3RoO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cbiAgfSk7XG5cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9rdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckVucmljaGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCB2YXIgSmVua2luc01ldHJpY3NDb250cm9sbGVyID0gY29udHJvbGxlcihcIkplbmtpbnNNZXRyaWNzQ29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIkt1YmVybmV0ZXNTY2hlbWFcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsIFwiU2VydmljZVJlZ2lzdHJ5XCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6S3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNTY2hlbWEsXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwsIFNlcnZpY2VSZWdpc3RyeSkgPT4ge1xuXG4gICAgICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICAgICAkc2NvcGUuam9iSWQgPSAkcm91dGVQYXJhbXNbXCJqb2JcIl07XG4gICAgICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICAgICAkc2NvcGUuamVua2lucyA9IG51bGw7XG4gICAgICAgICRzY29wZS5lbnRpdHlDaGFuZ2VkQ2FjaGUgPSB7fTtcblxuICAgICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gICAgICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RCcmVhZGNydW1icygkc2NvcGUuaWQpO1xuICAgICAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RTdWJOYXZCYXJzKCRzY29wZS5pZCwgJHNjb3BlLmpvYklkKTtcblxuICAgICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLm9wdGlvbnMgPSB7XG4gICAgICAgICAgY2hhcnQ6IHtcbiAgICAgICAgICAgIHR5cGU6ICdkaXNjcmV0ZUJhckNoYXJ0JyxcbiAgICAgICAgICAgIGF1dG9yZWZyZXNoOiBmYWxzZSxcbiAgICAgICAgICAgIGhlaWdodDogNDUwLFxuICAgICAgICAgICAgbWFyZ2luOiB7XG4gICAgICAgICAgICAgIHRvcDogMjAsXG4gICAgICAgICAgICAgIHJpZ2h0OiAyMCxcbiAgICAgICAgICAgICAgYm90dG9tOiA2MCxcbiAgICAgICAgICAgICAgbGVmdDogNDVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbGlwRWRnZTogdHJ1ZSxcbiAgICAgICAgICAgIHN0YWdnZXJMYWJlbHM6IGZhbHNlLFxuICAgICAgICAgICAgdHJhbnNpdGlvbkR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgICBzdGFja2VkOiBmYWxzZSxcbiAgICAgICAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgICAgICAgdG9vbHRpcDoge1xuICAgICAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgICAgICBjb250ZW50R2VuZXJhdG9yOiAoYXJncykgPT4ge1xuICAgICAgICAgICAgICAgIHZhciBkYXRhID0gYXJncy5kYXRhIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJldHVybiBkYXRhLnRvb2x0aXA7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IChkLCBpKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBkLmNvbG9yO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHhBeGlzOiB7XG4gICAgICAgICAgICAgIGF4aXNMYWJlbDogJ0J1aWxkcycsXG4gICAgICAgICAgICAgIHNob3dNYXhNaW46IGZhbHNlLFxuICAgICAgICAgICAgICB0aWNrRm9ybWF0OiBmdW5jdGlvbiAoZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIiNcIiArIGQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB5QXhpczoge1xuICAgICAgICAgICAgICBheGlzTGFiZWw6ICdCdWlsZCBEdXJhdGlvbiAoc2Vjb25kcyknLFxuICAgICAgICAgICAgICB0aWNrRm9ybWF0OiBmdW5jdGlvbiAoZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkMy5mb3JtYXQoJywuMWYnKShkKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAkc2NvcGUuZGF0YSA9IFtdO1xuXG4gICAgICAgIHVwZGF0ZURhdGEoKTtcblxuICAgICAgICBmdW5jdGlvbiBiYXJDb2xvdXJGb3JCdWlsZFJlc3VsdChyZXN1bHQpIHtcbiAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICBpZiAocmVzdWx0ID09PSBcIkZBSUxVUkVcIiB8fCByZXN1bHQgPT09IFwiRkFJTEVEXCIpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFwicmVkXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gXCJBQk9SVEVEXCIgfHwgcmVzdWx0ID09PSBcIklOVEVSVVBURURcIikge1xuICAgICAgICAgICAgICByZXR1cm4gXCJ0YW5cIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzdWx0ID09PSBcIlNVQ0NFU1NcIikge1xuICAgICAgICAgICAgICByZXR1cm4gXCJncmVlblwiO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChyZXN1bHQgPT09IFwiTk9UX1NUQVJURURcIikge1xuICAgICAgICAgICAgICByZXR1cm4gXCJsaWdodGdyZXlcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gXCJkYXJrZ3JleVwiO1xuICAgICAgICB9XG5cblxuICAgICAgICBmdW5jdGlvbiB1cGRhdGVDaGFydERhdGEoKSB7XG4gICAgICAgICAgdmFyIHVzZVNpbmdsZVNldCA9IHRydWU7XG4gICAgICAgICAgdmFyIGJ1aWxkc1N1Y2NlZWRlZCA9IFtdO1xuICAgICAgICAgIHZhciBidWlsZHNGYWlsZWQgPSBbXTtcbiAgICAgICAgICB2YXIgc3VjY2Vzc0J1aWxkS2V5ID0gXCJTdWNjZWVkZWQgYnVpbGRzXCI7XG4gICAgICAgICAgdmFyIGZhaWxlZEJ1aWxkS2V5ID0gXCJGYWlsZWQgYnVpbGRzXCI7XG5cbiAgICAgICAgICBpZiAodXNlU2luZ2xlU2V0KSB7XG4gICAgICAgICAgICBzdWNjZXNzQnVpbGRLZXkgPSBcIkJ1aWxkc1wiO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBjb3VudCA9IDA7XG4gICAgICAgICAgdmFyIGJ1aWxkcyA9IF8uc29ydEJ5KCRzY29wZS5tZXRyaWNzLmJ1aWxkcyB8fCBbXSwgXCJudW1iZXJcIik7XG4gICAgICAgICAgYW5ndWxhci5mb3JFYWNoKGJ1aWxkcywgKGJ1aWxkOmFueSkgPT4ge1xuICAgICAgICAgICAgdmFyIHggPSBidWlsZC5udW1iZXI7XG4gICAgICAgICAgICB2YXIgeSA9IGJ1aWxkLmR1cmF0aW9uIC8gMTAwMDtcbiAgICAgICAgICAgIHZhciBkYXRlID0gRGV2ZWxvcGVyLmFzRGF0ZShidWlsZC50aW1lSW5NaWxsaXMpO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGJ1aWxkLnJlc3VsdCB8fCBcIk5PVF9TVEFSVEVEXCI7XG4gICAgICAgICAgICB2YXIgY29sb3IgPSBiYXJDb2xvdXJGb3JCdWlsZFJlc3VsdChyZXN1bHQpO1xuICAgICAgICAgICAgdmFyIGljb25DbGFzcyA9IGNyZWF0ZUJ1aWxkU3RhdHVzSWNvbkNsYXNzKHJlc3VsdCk7XG4gICAgICAgICAgICB2YXIgdG9vbHRpcCA9ICc8aDM+PGkgY2xhc3M9XCInICsgaWNvbkNsYXNzICsgJ1wiPjwvaT4gJyArIGJ1aWxkLmRpc3BsYXlOYW1lICsgJzwvaDM+JyArXG4gICAgICAgICAgICAgICc8cD5kdXJhdGlvbjogPGI+JyArIHkgKyAnPC9iPiBzZWNvbmRzPC9wPic7XG4gICAgICAgICAgICBpZiAoZGF0ZSkge1xuICAgICAgICAgICAgICB0b29sdGlwICs9ICc8cD5zdGFydGVkOiA8Yj4nICsgZGF0ZSArICc8L2I+PC9wPic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgIHRvb2x0aXAgKz0gJzxwPnJlc3VsdDogPGI+JyArIHJlc3VsdCArICc8L2I+PC9wPic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh4KSB7XG4gICAgICAgICAgICAgIHZhciBkYXRhID0gYnVpbGRzU3VjY2VlZGVkO1xuICAgICAgICAgICAgICB2YXIga2V5ID0gc3VjY2Vzc0J1aWxkS2V5O1xuICAgICAgICAgICAgICBpZiAoIXN1Y2Nlc3NCdWlsZEtleSAmJiAoIXJlc3VsdCB8fCAhcmVzdWx0LnN0YXJ0c1dpdGgoXCJTVUNDXCIpKSkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBidWlsZHNGYWlsZWQ7XG4gICAgICAgICAgICAgICAga2V5ID0gZmFpbGVkQnVpbGRLZXk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZGF0YS5wdXNoKHtcbiAgICAgICAgICAgICAgICB0b29sdGlwOiB0b29sdGlwLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBjb2xvcixcbiAgICAgICAgICAgICAgICB4OiB4LCB5OiB5fSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHNjb3BlLmRhdGEgPSBbXTtcbiAgICAgICAgICBpZiAoYnVpbGRzU3VjY2VlZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgJHNjb3BlLmRhdGEucHVzaCh7XG4gICAgICAgICAgICAgIGtleTogc3VjY2Vzc0J1aWxkS2V5LFxuICAgICAgICAgICAgICB2YWx1ZXM6IGJ1aWxkc1N1Y2NlZWRlZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChidWlsZHNGYWlsZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAkc2NvcGUuZGF0YS5wdXNoKHtcbiAgICAgICAgICAgICAga2V5OiBmYWlsZWRCdWlsZEtleSxcbiAgICAgICAgICAgICAgdmFsdWVzOiBidWlsZHNGYWlsZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICAkc2NvcGUuYXBpLnVwZGF0ZVdpdGhEYXRhKCRzY29wZS5kYXRhKTtcblxuICAgICAgICAgICR0aW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICRzY29wZS5hcGkudXBkYXRlKCk7XG4gICAgICAgICAgfSwgNTApO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgICAgICB2YXIgbWV0cmljc1BhdGggPSAkc2NvcGUuam9iSWQgPyBVcmxIZWxwZXJzLmpvaW4oXCJqb2JcIiwgJHNjb3BlLmpvYklkLCBcImZhYnJpYzgvbWV0cmljc1wiKSA6IFwiZmFicmljOC9tZXRyaWNzXCI7XG4gICAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMua3ViZXJuZXRlc1Byb3h5VXJsRm9yU2VydmljZUN1cnJlbnROYW1lc3BhY2UoamVua2luc1NlcnZpY2VOYW1lQW5kUG9ydCwgbWV0cmljc1BhdGgpO1xuICAgICAgICAgIGxvZy5pbmZvKFwiXCIpO1xuICAgICAgICAgIGlmICh1cmwgJiYgKCEkc2NvcGUuamVua2lucyB8fCBLdWJlcm5ldGVzLmtlZXBQb2xsaW5nTW9kZWwpKSB7XG4gICAgICAgICAgICAkaHR0cC5nZXQodXJsLCBqZW5raW5zSHR0cENvbmZpZykuXG4gICAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChoYXNPYmplY3RDaGFuZ2VkKGRhdGEsICRzY29wZS5lbnRpdHlDaGFuZ2VkQ2FjaGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiZW50aXR5IGhhcyBjaGFuZ2VkIVwiKTtcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLm1ldHJpY3MgPSBkYXRhO1xuICAgICAgICAgICAgICAgICAgICB1cGRhdGVDaGFydERhdGEoKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJHNjb3BlLm1vZGVsLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9rdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckVucmljaGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCB2YXIgTmF2QmFyQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJOYXZCYXJDb250cm9sbGVyXCIsXG4gICAgW1wiJHNjb3BlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkdGltZW91dCkgPT4ge1xuXG4gICAgICAgICRzY29wZS5pc1ZhbGlkID0gKGl0ZW0pID0+IHtcbiAgICAgICAgICBpZiAoaXRlbSkge1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gaXRlbS5pc1ZhbGlkO1xuICAgICAgICAgICAgaWYgKGFuZ3VsYXIuaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlKGl0ZW0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gYW5ndWxhci5pc1VuZGVmaW5lZCh2YWx1ZSkgfHwgdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyTmF2aWdhdGlvbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBQaXBlbGluZUNvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiUGlwZWxpbmVDb250cm9sbGVyXCIsXG4gICAgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc1NjaGVtYVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIiwgXCJTZXJ2aWNlUmVnaXN0cnlcIixcbiAgICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSxcbiAgICAgICAkdGVtcGxhdGVDYWNoZTpuZy5JVGVtcGxhdGVDYWNoZVNlcnZpY2UsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCAkcm91dGVQYXJhbXMsICRodHRwLCAkdGltZW91dCwgS3ViZXJuZXRlc0FwaVVSTCwgU2VydmljZVJlZ2lzdHJ5KSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5rdWJlTW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICAgICAkc2NvcGUuam9iSWQgPSAkcm91dGVQYXJhbXNbXCJqb2JcIl07XG4gICAgICAgICRzY29wZS5idWlsZElkID0gJHJvdXRlUGFyYW1zW1wiYnVpbGRcIl07XG4gICAgICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICAgICAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlID0ge307XG5cbiAgICAgICAgJHNjb3BlLm1vZGVsID0ge1xuICAgICAgICAgIHN0YWdlczogbnVsbFxuICAgICAgICB9O1xuICAgICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gICAgICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RCcmVhZGNydW1icygkc2NvcGUuaWQpO1xuICAgICAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RTdWJOYXZCYXJzKCRzY29wZS5pZCwgJHNjb3BlLmpvYklkKTtcblxuICAgICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdXBkYXRlRGF0YSgpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgICAgaWYgKCRzY29wZS5qb2JJZCkge1xuICAgICAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMua3ViZXJuZXRlc1Byb3h5VXJsRm9yU2VydmljZUN1cnJlbnROYW1lc3BhY2UoamVua2luc1NlcnZpY2VOYW1lQW5kUG9ydCwgVXJsSGVscGVycy5qb2luKFwiam9iXCIsICRzY29wZS5qb2JJZCwgJHNjb3BlLmJ1aWxkSWQsIFwiZmFicmljOC9zdGFnZXMvXCIpKTtcbiAgICAgICAgICAgIGlmICh1cmwgJiYgKCEkc2NvcGUubW9kZWwuc3RhZ2VzIHx8IEt1YmVybmV0ZXMua2VlcFBvbGxpbmdNb2RlbCkpIHtcbiAgICAgICAgICAgICAgJGh0dHAuZ2V0KHVybCkuXG4gICAgICAgICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGVucmljaEplbmtpbnNTdGFnZXMoZGF0YSwgJHNjb3BlLmlkLCAkc2NvcGUuam9iSWQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGFzT2JqZWN0Q2hhbmdlZChkYXRhLCAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlKSkge1xuICAgICAgICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiZW50aXR5IGhhcyBjaGFuZ2VkIVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuYnVpbGQgPSBkYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5tb2RlbC5zdGFnZXMgPSBkYXRhLnN0YWdlcztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgJHNjb3BlLm1vZGVsLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgICAgICB9KS5cbiAgICAgICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4va3ViZXJuZXRlcy90cy9rdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJFbnJpY2hlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVySGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJOYXZpZ2F0aW9uLnRzXCIvPlxuXG5tb2R1bGUgRGV2ZWxvcGVyIHtcbiAgX21vZHVsZS5kaXJlY3RpdmUoXCJwaXBlbGluZVZpZXdcIiwgKCkgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICB0ZW1wbGF0ZVVybDogdGVtcGxhdGVQYXRoICsgJ3BpcGVsaW5lVmlldy5odG1sJ1xuICAgIH07XG4gIH0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyUGx1Z2luLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckVucmljaGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCB2YXIgUGlwZWxpbmVzQ29udHJvbGxlciA9IF9tb2R1bGUuY29udHJvbGxlcihcIkRldmVsb3Blci5QaXBlbGluZXNDb250cm9sbGVyXCIsICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSxcbiAgICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwsIFNlcnZpY2VSZWdpc3RyeSwgJGVsZW1lbnQpID0+IHtcblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5rdWJlTW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG4gICAgJHNjb3BlLmpvYklkID0gJHNjb3BlLmpvYklkIHx8ICRyb3V0ZVBhcmFtc1tcImpvYlwiXTtcbiAgICAkc2NvcGUuc2NoZW1hID0gS3ViZXJuZXRlc1NjaGVtYTtcbiAgICAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlID0ge307XG5cbiAgICAkZWxlbWVudC5vbignJGRlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAkc2NvcGUuJGRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgICRzY29wZS5tb2RlbCA9IHtcbiAgICAgIGpvYjogbnVsbCxcbiAgICAgIHBlbmRpbmdPbmx5OiAkc2NvcGUucGVuZGluZ1BpcGVsaW5lc09ubHlcbiAgICB9O1xuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcbiAgICAkc2NvcGUuYnJlYWRjcnVtYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0QnJlYWRjcnVtYnMoJHNjb3BlLmlkKTtcbiAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RTdWJOYXZCYXJzKCRzY29wZS5pZCwgJHNjb3BlLmpvYklkKTtcblxuICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB1cGRhdGVEYXRhKCk7XG4gICAgfSk7XG5cbiAgICAkc2NvcGUuJG9uKCckcm91dGVVcGRhdGUnLCAoJGV2ZW50KSA9PiB7XG4gICAgICB1cGRhdGVEYXRhKCk7XG4gICAgfSk7XG5cbiAgICAkc2NvcGUuJHdhdGNoKCdtb2RlbC5wZW5kaW5nT25seScsICgkZXZlbnQpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9KTtcblxuICAgICRzY29wZS5zZWxlY3RCdWlsZCA9IChidWlsZCkgPT4ge1xuICAgICAgdmFyIGlkID0gYnVpbGQuaWQ7XG4gICAgICBpZiAoaWQpIHtcbiAgICAgICAgaWYgKGlkICE9PSAkc2NvcGUuc2VsZWN0ZWRCdWlsZElkKSB7XG4gICAgICAgICAgJHNjb3BlLnNlbGVjdGVkQnVpbGRJZCA9IGlkO1xuICAgICAgICAgICRzY29wZS4kYnJvYWRjYXN0KFwiamVua2luc1NlbGVjdGVkQnVpbGRcIiwgYnVpbGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHZhciB1cGRhdGVEYXRhID0gXy5kZWJvdW5jZSgoKSA9PiB7XG4gICAgICB2YXIgZW50aXR5ID0gJHNjb3BlLmVudGl0eTtcbiAgICAgIGlmICgkc2NvcGUuam9iSWQpIHtcbiAgICAgICAgaWYgKCghZW50aXR5IHx8IGVudGl0eS4kamVua2luc0pvYikpIHtcbiAgICAgICAgICB2YXIgcXVlcnlQYXRoID0gXCJmYWJyaWM4L3N0YWdlcy9cIjtcbiAgICAgICAgICBpZiAoJHNjb3BlLm1vZGVsLnBlbmRpbmdPbmx5KSB7XG4gICAgICAgICAgICBxdWVyeVBhdGggPSBcImZhYnJpYzgvcGVuZGluZ1N0YWdlcy9cIjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMua3ViZXJuZXRlc1Byb3h5VXJsRm9yU2VydmljZUN1cnJlbnROYW1lc3BhY2UoamVua2luc1NlcnZpY2VOYW1lQW5kUG9ydCwgVXJsSGVscGVycy5qb2luKFwiam9iXCIsICRzY29wZS5qb2JJZCwgcXVlcnlQYXRoKSk7XG4gICAgICAgICAgaWYgKHVybCAmJiAoISRzY29wZS5tb2RlbC5qb2IgfHwgS3ViZXJuZXRlcy5rZWVwUG9sbGluZ01vZGVsKSkge1xuICAgICAgICAgICAgJGh0dHAuZ2V0KHVybCkuXG4gICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgIGVucmljaEplbmtpbnNQaXBlbGluZUpvYihkYXRhLCAkc2NvcGUuaWQsICRzY29wZS5qb2JJZCk7XG4gICAgICAgICAgICAgICAgaWYgKGhhc09iamVjdENoYW5nZWQoZGF0YSwgJHNjb3BlLmVudGl0eUNoYW5nZWRDYWNoZSkpIHtcbiAgICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiZW50aXR5IGhhcyBjaGFuZ2VkIVwiKTtcbiAgICAgICAgICAgICAgICAgICRzY29wZS5tb2RlbC5qb2IgPSBkYXRhO1xuXG4gICAgICAgICAgICAgICAgICB2YXIgYnVpbGRzID0gZGF0YS5idWlsZHM7XG4gICAgICAgICAgICAgICAgICBpZiAoYnVpbGRzICYmIGJ1aWxkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNlbGVjdEJ1aWxkKGJ1aWxkc1swXSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoJHNjb3BlLm1vZGVsKSB7XG4gICAgICAgICAgICBLdWJlcm5ldGVzLmVucmljaEJ1aWxkcygkc2NvcGUua3ViZU1vZGVsLmJ1aWxkcyk7XG5cbiAgICAgICAgICAgIHZhciBidWlsZHMgPSBbXTtcbiAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaCgkc2NvcGUua3ViZU1vZGVsLmJ1aWxkcywgKGJ1aWxkKSA9PiB7XG4gICAgICAgICAgICAgIHZhciBsYWJlbHMgPSBLdWJlcm5ldGVzLmdldExhYmVscyhidWlsZCk7XG4gICAgICAgICAgICAgIHZhciBhcHAgPSBsYWJlbHNbXCJhcHBcIl07XG4gICAgICAgICAgICAgIGlmIChhcHAgPT09ICRzY29wZS5wcm9qZWN0SWQpIHtcbiAgICAgICAgICAgICAgICBidWlsZHMucHVzaChidWlsZCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYnVpbGRzID0gXy5zb3J0QnkoYnVpbGRzLCBcIiRjcmVhdGlvbkRhdGVcIikucmV2ZXJzZSgpO1xuICAgICAgICAgICAgdmFyIGFsbEJ1aWxkcyA9IGJ1aWxkcztcbiAgICAgICAgICAgIGlmIChhbGxCdWlsZHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICBidWlsZHMgPSBfLmZpbHRlcihhbGxCdWlsZHMsIChiKSA9PiAhYi4kY3JlYXRpb25EYXRlKTtcbiAgICAgICAgICAgICAgaWYgKCFidWlsZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYnVpbGRzID0gW2FsbEJ1aWxkc1swXV07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwaXBlbGluZXMgPSBbXTtcbiAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChidWlsZHMsIChidWlsZCkgPT4ge1xuICAgICAgICAgICAgICB2YXIgYnVpbGRTdGF0dXMgPSBidWlsZC5zdGF0dXMgfHwge307XG4gICAgICAgICAgICAgIHZhciByZXN1bHQgPSBidWlsZFN0YXR1cy5waGFzZSB8fCBcIlwiO1xuICAgICAgICAgICAgICB2YXIgcmVzdWx0VXBwZXJDYXNlID0gcmVzdWx0LnRvVXBwZXJDYXNlKCk7XG5cbiAgICAgICAgICAgICAgdmFyIGRlc2NyaXB0aW9uID0gXCJcIjtcbiAgICAgICAgICAgICAgdmFyICR2aWV3TGluayA9IGJ1aWxkLiR2aWV3TGluaztcbiAgICAgICAgICAgICAgdmFyICRsb2dMaW5rID0gYnVpbGQuJGxvZ3NMaW5rO1xuICAgICAgICAgICAgICB2YXIgJHRpbWVzdGFtcCA9IGJ1aWxkLiRjcmVhdGlvbkRhdGU7XG4gICAgICAgICAgICAgIHZhciBkdXJhdGlvbiA9IGJ1aWxkU3RhdHVzLmR1cmF0aW9uO1xuICAgICAgICAgICAgICBpZiAoZHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICAvLyAxN3MgPSAxNywwMDAsMDAwLDAwMCBvbiBvcGVuc2hpZnRcbiAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IGR1cmF0aW9uIC8gMTAwMDAwMDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB2YXIgZGlzcGxheU5hbWUgPSBLdWJlcm5ldGVzLmdldE5hbWUoYnVpbGQpO1xuICAgICAgICAgICAgICB2YXIgJGljb25DbGFzcyA9IGNyZWF0ZUJ1aWxkU3RhdHVzSWNvbkNsYXNzKHJlc3VsdFVwcGVyQ2FzZSk7XG4gICAgICAgICAgICAgIHZhciAkYmFja2dyb3VuZENsYXNzID0gY3JlYXRlQnVpbGRTdGF0dXNCYWNrZ3JvdW5kQ2xhc3MocmVzdWx0VXBwZXJDYXNlKTtcbiAgICAgICAgICAgICAgdmFyIHN0YWdlID0ge1xuICAgICAgICAgICAgICAgIHN0YWdlTmFtZTogXCJPcGVuU2hpZnQgQnVpbGRcIixcbiAgICAgICAgICAgICAgICAkdmlld0xpbms6ICR2aWV3TGluayxcbiAgICAgICAgICAgICAgICAkbG9nTGluazogJGxvZ0xpbmssXG4gICAgICAgICAgICAgICAgJHN0YXJ0VGltZTogJHRpbWVzdGFtcCxcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogZHVyYXRpb24sXG4gICAgICAgICAgICAgICAgc3RhdHVzOiByZXN1bHQsXG4gICAgICAgICAgICAgICAgJGljb25DbGFzczogJGljb25DbGFzcyxcbiAgICAgICAgICAgICAgICAkYmFja2dyb3VuZENsYXNzOiAkYmFja2dyb3VuZENsYXNzXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIHZhciBwaXBlbGluZSA9IHtcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6IGRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgICAgICR2aWV3TGluazogJHZpZXdMaW5rLFxuICAgICAgICAgICAgICAgICRsb2dMaW5rOiAkbG9nTGluayxcbiAgICAgICAgICAgICAgICAkdGltZXN0YW1wOiAkdGltZXN0YW1wLFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgICAgICAgICBzdGFnZXM6IFtzdGFnZV1cbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgcGlwZWxpbmVzLnB1c2gocGlwZWxpbmUpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGxldHMgZmlsdGVyIHRoZSBPcGVuU2hpZnQgYnVpbGRzIGFuZCBtYWtlIGEgcGlwZWxpbmUgZnJvbSB0aGF0XG4gICAgICAgICAgICAkc2NvcGUubW9kZWwuam9iID0ge1xuICAgICAgICAgICAgICAkam9iSWQ6ICRzY29wZS5qb2JJZCxcbiAgICAgICAgICAgICAgJHByb2plY3Q6ICRzY29wZS5wcm9qZWN0SWQsXG4gICAgICAgICAgICAgIGJ1aWxkczogcGlwZWxpbmVzXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICAkc2NvcGUubW9kZWwuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHNjb3BlLm1vZGVsLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgfVxuICAgIH0sIDUwKTtcblxuICAgIHVwZGF0ZURhdGEoKTtcblxuICB9KTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9rdWJlcm5ldGVzL3RzL2t1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckVucmljaGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJkZXZlbG9wZXJIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3Blck5hdmlnYXRpb24udHNcIi8+XG5cbm1vZHVsZSBEZXZlbG9wZXIge1xuXG4gIGV4cG9ydCB2YXIgUHJvamVjdENvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiUHJvamVjdENvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCIkZWxlbWVudFwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIkt1YmVybmV0ZXNTY2hlbWFcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCAkZWxlbWVudCwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG5cbiAgICAgICAgJHNjb3BlLnNjaGVtYSA9IEt1YmVybmV0ZXNTY2hlbWE7XG4gICAgICAgICRzY29wZS5jb25maWcgPSBLdWJlcm5ldGVzU2NoZW1hLmRlZmluaXRpb25zLm9zX2J1aWxkX0J1aWxkQ29uZmlnO1xuICAgICAgICAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlID0ge307XG4gICAgICAgICRzY29wZS5lbnZWZXJzaW9uc0NhY2hlID0ge307XG4gICAgICAgICRzY29wZS5lbnZOU0NhY2hlcyA9IHt9O1xuICAgICAgICAkc2NvcGUuZW52VmVyc2lvbnMgPSB7fTtcblxuICAgICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gICAgICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gW107IC8vRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RCcmVhZGNydW1icygkc2NvcGUuaWQpO1xuICAgICAgICB1cGRhdGVUYWJzKCk7XG4gICAgICAgIC8vIHRoaXMgaXMgdXNlZCBmb3IgdGhlIHBlbmRpbmdQaXBlbGluZXMgdmlld1xuICAgICAgICAkc2NvcGUuam9iSWQgPSAkc2NvcGUuaWQ7XG4gICAgICAgICRzY29wZS5wZW5kaW5nUGlwZWxpbmVzT25seSA9IHRydWU7XG5cbiAgICAgICAgJHNjb3BlLiRvbignamVua2luc1NlbGVjdGVkQnVpbGQnLCAoZXZlbnQsIGJ1aWxkKSA9PiB7XG4gICAgICAgICAgJHNjb3BlLnNlbGVjdGVkQnVpbGQgPSBidWlsZDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gVE9ETyB0aGlzIHNob3VsZCBiZSB1bm5lY2Vzc2FyeSBidXQgc2VlbXMgc29tZXRpZW1zIHRoaXMgd2F0Y2ggZG9lc24ndCBhbHdheXMgdHJpZ2dlciB1bmxlc3MgeW91IGhpdCByZWxvYWQgb24gdGhpcyBwYWdlXG4gICAgICAgIGlmICgkc2NvcGUubW9kZWwuYnVpbGRjb25maWdzKSB7XG4gICAgICAgICAgb25CdWlsZENvbmZpZ3MoJHNjb3BlLm1vZGVsLmJ1aWxkY29uZmlncyk7XG4gICAgICAgIH1cbiAgICAgICAgS3ViZXJuZXRlcy53YXRjaCgkc2NvcGUsICRlbGVtZW50LCBcImJ1aWxkY29uZmlnc1wiLCAkc2NvcGUubmFtZXNwYWNlLCBvbkJ1aWxkQ29uZmlncyk7XG5cbiAgICAgICAgZnVuY3Rpb24gb25CdWlsZENvbmZpZ3MoYnVpbGRDb25maWdzKSB7XG4gICAgICAgICAgYW5ndWxhci5mb3JFYWNoKGJ1aWxkQ29uZmlncywgKGRhdGEpID0+IHtcbiAgICAgICAgICAgIHZhciBuYW1lID0gS3ViZXJuZXRlcy5nZXROYW1lKGRhdGEpO1xuICAgICAgICAgICAgaWYgKG5hbWUgPT09ICRzY29wZS5pZCkge1xuICAgICAgICAgICAgICB2YXIgc29ydGVkQnVpbGRzID0gbnVsbDtcbiAgICAgICAgICAgICAgS3ViZXJuZXRlcy5lbnJpY2hCdWlsZENvbmZpZyhkYXRhLCBzb3J0ZWRCdWlsZHMpO1xuICAgICAgICAgICAgICBpZiAoaGFzT2JqZWN0Q2hhbmdlZChkYXRhLCAkc2NvcGUuZW50aXR5Q2hhbmdlZENhY2hlKSkge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiZW50aXR5IGhhcyBjaGFuZ2VkIVwiKTtcbiAgICAgICAgICAgICAgICAkc2NvcGUuZW50aXR5ID0gZGF0YTtcbiAgICAgICAgICAgICAgICAkc2NvcGUuZW50aXR5LiRidWlsZCA9IChkYXRhLiRmYWJyaWM4Q29kZVZpZXdzIHx8IHt9KVsnZmFicmljOC5saW5rLmJyb3dzZUdvZ3MudmlldyddO1xuICAgICAgICAgICAgICAgICRzY29wZS5tb2RlbC5zZXRQcm9qZWN0KCRzY29wZS5lbnRpdHkpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHVwZGF0ZUVudmlyb25tZW50V2F0Y2goKTtcbiAgICAgICAgICAgICAgdXBkYXRlVGFicygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICB9XG5cblxuICAgICAgICAvKipcbiAgICAgICAgICogV2UgaGF2ZSB1cGRhdGVkIHRoZSBlbnRpdHkgc28gbGV0cyBtYWtlIHN1cmUgd2UgYXJlIHdhdGNoaW5nIGFsbCB0aGUgZW52aXJvbm1lbnRzIHRvIGZpbmRcbiAgICAgICAgICogdGhlIHByb2plY3QgdmVyc2lvbnMgZm9yIGVhY2ggbmFtZXNwYWNlXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiB1cGRhdGVFbnZpcm9ubWVudFdhdGNoKCkge1xuICAgICAgICAgIHZhciBwcm9qZWN0ID0gJHNjb3BlLmVudGl0eTtcbiAgICAgICAgICBpZiAocHJvamVjdCkge1xuICAgICAgICAgICAgdmFyIGplbmtpbnNKb2IgPSBwcm9qZWN0LiRqZW5raW5zSm9iO1xuICAgICAgICAgICAgaWYgKGplbmtpbnNKb2IpIHtcbiAgICAgICAgICAgICAgdmFyIGJ1aWxkc1RhYiA9IF8uZmluZCgkc2NvcGUuc3ViVGFiQ29uZmlnLCB7aWQ6IFwiYnVpbGRzXCJ9KTtcbiAgICAgICAgICAgICAgaWYgKGJ1aWxkc1RhYikge1xuICAgICAgICAgICAgICAgIGJ1aWxkc1RhYltcImhyZWZcIl0gPSBVcmxIZWxwZXJzLmpvaW4oXCIvd29ya3NwYWNlc1wiLCBLdWJlcm5ldGVzLmN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCksIFwicHJvamVjdHNcIiwgJHNjb3BlLmlkLCBcImplbmtpbnNKb2JcIiwgamVua2luc0pvYik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYW5ndWxhci5mb3JFYWNoKHByb2plY3QuZW52aXJvbm1lbnRzLCAoZW52KSA9PiB7XG4gICAgICAgICAgICAgIHZhciBucyA9IGVudi5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgIHZhciBjYWNoZXMgPSAkc2NvcGUuZW52TlNDYWNoZXNbbnNdO1xuICAgICAgICAgICAgICBpZiAoIWNhY2hlcykge1xuICAgICAgICAgICAgICAgIGNhY2hlcyA9IHt9O1xuICAgICAgICAgICAgICAgICRzY29wZS5lbnZOU0NhY2hlc1tuc10gPSBjYWNoZXM7XG4gICAgICAgICAgICAgICAgbG9hZFByb2plY3RWZXJzaW9ucygkc2NvcGUsICRlbGVtZW50LCBwcm9qZWN0LCBlbnYsIG5zLCAkc2NvcGUuZW52VmVyc2lvbnMsIGNhY2hlcyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVRhYnMoKSB7XG4gICAgICAgICAgJHNjb3BlLnN1YlRhYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0U3ViTmF2QmFycygkc2NvcGUuaWQsIG51bGwsICRzY29wZSk7XG4gICAgICAgIH1cblxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlclBsdWdpbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgX21vZHVsZS5jb250cm9sbGVyKCdEZXZlbG9wZXIuUHJvamVjdFNlbGVjdG9yJywgWyckc2NvcGUnLCAnJHJvdXRlUGFyYW1zJywgJ0t1YmVybmV0ZXNNb2RlbCcsICgkc2NvcGUsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsKSA9PiB7XG4gICAgdmFyIHByb2plY3RJZCA9ICRyb3V0ZVBhcmFtc1sncHJvamVjdElkJ10gfHwgJHJvdXRlUGFyYW1zWydwcm9qZWN0J10gfHwgJHJvdXRlUGFyYW1zWydpZCddO1xuICAgIGlmIChwcm9qZWN0SWQpIHtcbiAgICAgICRzY29wZS5wcm9qZWN0SWQgPSBwcm9qZWN0SWQ7XG4gICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWxcbiAgICAgICRzY29wZS4kd2F0Y2goJ21vZGVsLmJ1aWxkY29uZmlncycsIChidWlsZGNvbmZpZ3MpID0+IHtcbiAgICAgICAgJHNjb3BlLnByb2plY3RzID0gYnVpbGRjb25maWdzO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy5pbmZvKFwibm8gcHJvamVjdCBJRCBpbiByb3V0ZVBhcmFtczogXCIsICRyb3V0ZVBhcmFtcyk7XG4gICAgfVxuICB9XSk7XG5cbn1cblxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyTmF2aWdhdGlvbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBQcm9qZWN0c0NvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiUHJvamVjdHNDb250cm9sbGVyXCIsIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIiRkaWFsb2dcIiwgXCIkd2luZG93XCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkbG9jYXRpb25cIiwgXCJsb2NhbFN0b3JhZ2VcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgJGRpYWxvZywgJHdpbmRvdywgJHRlbXBsYXRlQ2FjaGUsICRyb3V0ZVBhcmFtcywgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsIGxvY2FsU3RvcmFnZSwgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuXG4gICAgICAkc2NvcGUudGFibGVDb25maWcgPSB7XG4gICAgICAgIGRhdGE6ICdtb2RlbC5idWlsZGNvbmZpZ3MnLFxuICAgICAgICBzaG93U2VsZWN0aW9uQ2hlY2tib3g6IHRydWUsXG4gICAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgbXVsdGlTZWxlY3Q6IHRydWUsXG4gICAgICAgIHNlbGVjdGVkSXRlbXM6IFtdLFxuICAgICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgICAgZmlsdGVyVGV4dDogJGxvY2F0aW9uLnNlYXJjaCgpW1wicVwiXSB8fCAnJ1xuICAgICAgICB9LFxuICAgICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckbmFtZScsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ05hbWUnLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJpZFRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuLypcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3NwZWMuc291cmNlLnR5cGUnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdTb3VyY2UnXG4gICAgICAgICAgfSxcbiovXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLnNvdXJjZS5naXQudXJpJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUmVwb3NpdG9yeSdcbiAgICAgICAgICB9LFxuLypcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3NwZWMuc3RyYXRlZ3kudHlwZScsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ1N0cmF0ZWd5J1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLnN0cmF0ZWd5LnN0aVN0cmF0ZWd5LmltYWdlJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnU291cmNlIEltYWdlJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLm91dHB1dC5pbWFnZVRhZycsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ091dHB1dCBJbWFnZSdcbiAgICAgICAgICB9LFxuKi9cbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ21ldGFkYXRhLmRlc2NyaXB0aW9uJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnRGVzY3JpcHRpb24nXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJyRjcmVhdGlvbkRhdGUnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdDcmVhdGVkJyxcbiAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiY3JlYXRpb25UaW1lVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckbGFiZWxzVGV4dCcsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ0xhYmVscycsXG4gICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImxhYmVsVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgIH1cbiAgICAgICAgXVxuICAgICAgfTtcblxuICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuXG4gICAgICAkc2NvcGUuYnJlYWRjcnVtYkNvbmZpZyA9IGNyZWF0ZVByb2plY3RCcmVhZGNydW1icygpO1xuICAgICAgJHNjb3BlLnN1YlRhYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVXb3Jrc3BhY2VTdWJOYXZCYXJzKCk7XG5cbiAgICAgIC8vIFRPRE9cbiAgICAgIC8vJHNjb3BlLmlzTG9nZ2VkSW50b0dvZ3MgPSBGb3JnZS5pc0xvZ2dlZEludG9Hb2dzO1xuXG4gICAgICAkc2NvcGUuZGVsZXRlUHJvbXB0ID0gKHNlbGVjdGVkKSA9PiB7XG4gICAgICAgIFVJLm11bHRpSXRlbUNvbmZpcm1BY3Rpb25EaWFsb2coPFVJLk11bHRpSXRlbUNvbmZpcm1BY3Rpb25PcHRpb25zPntcbiAgICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgICBpbmRleDogJyRuYW1lJyxcbiAgICAgICAgICBvbkNsb3NlOiAocmVzdWx0OmJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgZnVuY3Rpb24gZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIG5leHQpIHtcbiAgICAgICAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgICAgICAgZGVsZXRlRW50aXR5KG5leHQsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIC8vIFRPRE9cbiAgICAgICAgICAgICAgICAgIC8vIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICB0aXRsZTogJ0RlbGV0ZSBBcHBzJyxcbiAgICAgICAgICBhY3Rpb246ICdUaGUgZm9sbG93aW5nIEFwcHMgd2lsbCBiZSBkZWxldGVkOicsXG4gICAgICAgICAgb2tUZXh0OiAnRGVsZXRlJyxcbiAgICAgICAgICBva0NsYXNzOiAnYnRuLWRhbmdlcicsXG4gICAgICAgICAgY3VzdG9tOiBcIlRoaXMgb3BlcmF0aW9uIGlzIHBlcm1hbmVudCBvbmNlIGNvbXBsZXRlZCFcIixcbiAgICAgICAgICBjdXN0b21DbGFzczogXCJhbGVydCBhbGVydC13YXJuaW5nXCJcbiAgICAgICAgfSkub3BlbigpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gZGVsZXRlRW50aXR5KHNlbGVjdGlvbiwgbmV4dENhbGxiYWNrKSB7XG4gICAgICAgIHZhciBuYW1lID0gKHNlbGVjdGlvbiB8fCB7fSkuJG5hbWU7XG4gICAgICAgIHZhciBqZW5raW5zSm9iID0gc2VsZWN0aW9uLiRqZW5raW5zSm9iO1xuICAgICAgICB2YXIgcHVibGljSmVua2luc1VybCA9IGplbmtpbnNMaW5rKCk7XG4gICAgICAgIC8vdmFyIGplbmtpbnNVcmwgPSBDb3JlLnBhdGhHZXQoc2VsZWN0aW9uLCBbXCIkZmFicmljOFZpZXdzXCIsIFwiZmFicmljOC5saW5rLmplbmtpbnMuam9iXCIsIFwidXJsXCJdKTtcbiAgICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFib3V0IHRvIGRlbGV0ZSBidWlsZCBjb25maWc6IFwiICsgbmFtZSk7XG4gICAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMuYnVpbGRDb25maWdSZXN0VXJsKG5hbWUpO1xuICAgICAgICAgICRodHRwLmRlbGV0ZSh1cmwpLlxuICAgICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgbmV4dENhbGxiYWNrKCk7XG4gICAgICAgICAgICB9KS5cbiAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBkZWxldGUgYnVpbGQgY29uZmlnIG9uIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgICBuZXh0Q2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwid2FybmluZzogbm8gbmFtZSBmb3Igc2VsZWN0aW9uOiBcIiArIGFuZ3VsYXIudG9Kc29uKHNlbGVjdGlvbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGplbmtpbnNKb2IgJiYgcHVibGljSmVua2luc1VybCkge1xuICAgICAgICAgIHZhciB1cmwgPSBLdWJlcm5ldGVzLmt1YmVybmV0ZXNQcm94eVVybEZvclNlcnZpY2VDdXJyZW50TmFtZXNwYWNlKGplbmtpbnNTZXJ2aWNlTmFtZUFuZFBvcnQsIFVybEhlbHBlcnMuam9pbihcImpvYlwiLCBqZW5raW5zSm9iLCBcImRvRGVsZXRlXCIpKTtcbiAgICAgICAgICB2YXIgYm9keSA9IFwiXCI7XG4gICAgICAgICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6IFwidGV4dC9wbGFpblwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcbiAgICAgICAgICBsb2cuaW5mbyhcInBvc3RpbmcgdG8gamVua2luc1VybDogXCIgKyB1cmwpO1xuICAgICAgICAgICRodHRwLnBvc3QodXJsLCBib2R5LCBjb25maWcpLlxuICAgICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgbG9nLmluZm8oXCJNYW5hZ2VkIHRvIGRlbGV0ZSBcIiArIHVybCk7XG4gICAgICAgICAgICB9KS5cbiAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBkZWxldGUgamVua2lucyBqb2IgYXQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4vKlxuICAgICAgJHNjb3BlLiRrZWVwUG9sbGluZyA9ICgpID0+IEt1YmVybmV0ZXMua2VlcFBvbGxpbmdNb2RlbDtcbiAgICAgICRzY29wZS5mZXRjaCA9IFBvbGxIZWxwZXJzLnNldHVwUG9sbGluZygkc2NvcGUsIChuZXh0OigpID0+IHZvaWQpID0+IHtcbiAgICAgICAgdmFyIHVybCA9IEt1YmVybmV0ZXMuYnVpbGRDb25maWdzUmVzdFVSTCgpO1xuICAgICAgICAkaHR0cC5nZXQodXJsKS5cbiAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcImdvdCBkYXRhIFwiICsgYW5ndWxhci50b0pzb24oZGF0YSwgdHJ1ZSkpO1xuICAgICAgICAgICAgICB2YXIgc29ydGVkQnVpbGRzID0gbnVsbDtcbiAgICAgICAgICAgICAgJHNjb3BlLmJ1aWxkQ29uZmlncyA9IEt1YmVybmV0ZXMuZW5yaWNoQnVpbGRDb25maWdzKGRhdGEuaXRlbXMsIHNvcnRlZEJ1aWxkcyk7XG4gICAgICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLlxuICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICAkc2NvcGUuZmV0Y2goKTtcbiovXG4gICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyTmF2aWdhdGlvbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBXb3Jrc3BhY2VDb250cm9sbGVyID0gY29udHJvbGxlcihcIldvcmtzcGFjZUNvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJLdWJlcm5ldGVzU2NoZW1hXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wibmFtZXNwYWNlXCJdO1xuICAgICAgICAkc2NvcGUuc2NoZW1hID0gS3ViZXJuZXRlc1NjaGVtYTtcbiAgICAgICAgJHNjb3BlLmNvbmZpZyA9IEt1YmVybmV0ZXNTY2hlbWEuZGVmaW5pdGlvbnMua3ViZXJuZXRlc19OYW1lc3BhY2U7XG5cbiAgICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuICAgICAgICAkc2NvcGUuYnJlYWRjcnVtYkNvbmZpZyA9IGNyZWF0ZVdvcmtzcGFjZUJyZWFkY3J1bWJzKCk7XG4gICAgICAgICRzY29wZS5zdWJUYWJDb25maWcgPSBEZXZlbG9wZXIuY3JlYXRlV29ya3NwYWNlU3ViTmF2QmFycygpO1xuXG4gICAgICAgICRzY29wZS4ka2VlcFBvbGxpbmcgPSAoKSA9PiBLdWJlcm5ldGVzLmtlZXBQb2xsaW5nTW9kZWw7XG4gICAgICAgICRzY29wZS5mZXRjaCA9IFBvbGxIZWxwZXJzLnNldHVwUG9sbGluZygkc2NvcGUsIChuZXh0OigpID0+IHZvaWQpID0+IHtcbiAgICAgICAgICAkc2NvcGUuaXRlbSA9IG51bGw7XG4gICAgICAgICAgaWYgKCRzY29wZS5pZCkge1xuICAgICAgICAgICAgdmFyIHVybCA9IFVybEhlbHBlcnMuam9pbihLdWJlcm5ldGVzLnJlc291cmNlc1VyaUZvcktpbmQoXCJQcm9qZWN0c1wiKSwgJHNjb3BlLmlkKTtcbiAgICAgICAgICAgIGxvZy5pbmZvKFwiTG9hZGluZyB1cmw6IFwiICsgdXJsKTtcbiAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUuZW50aXR5ID0gZW5yaWNoV29ya3NwYWNlKGRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgICAgICBuZXh0KCk7XG4gICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRzY29wZS5tb2RlbC5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICBuZXh0KCk7XG5cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS5mZXRjaCgpO1xuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2t1YmVybmV0ZXMvdHMva3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyRW5yaWNoZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImRldmVsb3BlckhlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiZGV2ZWxvcGVyTmF2aWdhdGlvbi50c1wiLz5cblxubW9kdWxlIERldmVsb3BlciB7XG5cbiAgZXhwb3J0IHZhciBXb3Jrc3BhY2VzQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJXb3Jrc3BhY2VzQ29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIk9yYWNsZVN0YXR1c01vZGVsXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLCBcIkRhdGFJbmZvTW9kZWxcIiwgXCIkaW50ZXJ2YWxcIixcbiAgICAgICgkc2NvcGUsIE9yYWNsZVN0YXR1c01vZGVsLCBLdWJlcm5ldGVzTW9kZWw6S3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMLCBEYXRhSW5mb01vZGVsLCRpbnRlcnZhbCkgPT4ge1xuICAgICAgICAkc2NvcGUubW9kZWwgPSBEYXRhSW5mb01vZGVsO1xuICAgICAgICAkc2NvcGUuaXRlbXM9W107XG5cbiAgICAgICAgJHNjb3BlLmxvY2FsaXRlbXM9W107XG4gICAgICAgIHZhciByb290UGF0aD1cIlwiO1xuICAgICAgICB2YXIgRmlsdGVyTGlzdCA9e1xuICAgICAgICAgICAgbGVuZ3RoOjBcbiAgICAgICAgfTtcblxuICAgICAgICB1cGRhdGUoKTtcblxuICAgICAgICAkc2NvcGUudHJlZU9wdGlvbnMgPSB7XG4gICAgICAgICAgbm9kZUNoaWxkcmVuOiBcImNoaWxkcmVuXCIsXG4gICAgICAgICAgZGlyU2VsZWN0YWJsZTogdHJ1ZSxcbiAgICAgICAgICBtdWx0aVNlbGVjdGlvbjogZmFsc2UsXG4gICAgICAgICAgaW5qZWN0Q2xhc3Nlczoge1xuICAgICAgICAgICAgdWw6IFwiYTFcIixcbiAgICAgICAgICAgIGxpOiBcImEyXCIsXG4gICAgICAgICAgICBsaVNlbGVjdGVkOiBcImE3XCIsXG4gICAgICAgICAgICBpRXhwYW5kZWQ6IFwiYTNcIixcbiAgICAgICAgICAgIGlDb2xsYXBzZWQ6IFwiYTRcIixcbiAgICAgICAgICAgIGlMZWFmOiBcImE1XCIsXG4gICAgICAgICAgICBsYWJlbDogXCJhNlwiLFxuICAgICAgICAgICAgbGFiZWxTZWxlY3RlZDogXCJhOFwiXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS50cmVlT3B0aW9uc3MgPSB7XG4gICAgICAgICAgbm9kZUNoaWxkcmVuOiBcImNoaWxkcmVuXCIsXG4gICAgICAgICAgZGlyU2VsZWN0YWJsZTogdHJ1ZSxcbiAgICAgICAgICBtdWx0aVNlbGVjdGlvbjogdHJ1ZSxcbiAgICAgICAgICBpbmplY3RDbGFzc2VzOiB7XG4gICAgICAgICAgICB1bDogXCJhMVwiLFxuICAgICAgICAgICAgbGk6IFwiYTJcIixcbiAgICAgICAgICAgIGxpU2VsZWN0ZWQ6IFwiYTdcIixcbiAgICAgICAgICAgIGlFeHBhbmRlZDogXCJhM1wiLFxuICAgICAgICAgICAgaUNvbGxhcHNlZDogXCJhNFwiLFxuICAgICAgICAgICAgaUxlYWY6IFwiYTVcIixcbiAgICAgICAgICAgIGxhYmVsOiBcImE2XCIsXG4gICAgICAgICAgICBsYWJlbFNlbGVjdGVkOiBcImE4XCJcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgJHNjb3BlLnNob3dTZWxlY3RlZCA9IChub2RlLHNlbGVjdGVkKT0+e1xuXG4gICAgICAgICAgICRzY29wZS5tb2RlbC5zZXJ2ZXJpdGVtcyA9IFtdO1xuICAgICAgICAgICB2YXIgYXJyYXkgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgaWYoc2VsZWN0ZWQpe1xuICAgICAgICAgICAgICBpZihub2RlLmNoaWxkcmVuLmxlbmd0aCA+IDApe1xuICAgICAgICAgICAgICAgICBhcnJheS51bnNoaWZ0KG5vZGUpO1xuICAgICAgICAgICAgICAgICB3aGlsZShhcnJheS5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZT1hcnJheS5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoY2hpbGROb2RlLmNoaWxkcmVuLmxlbmd0aD4wKXtcbiAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBpPTA7aTxjaGlsZE5vZGUuY2hpbGRyZW4ubGVuZ3RoO2krKylcbiAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheS51bnNoaWZ0KGNoaWxkTm9kZS5jaGlsZHJlbltpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICAgICAgICAgICBpZihjaGlsZE5vZGUuaGFzT3duUHJvcGVydHkoXCJwYXRoXCIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwuc2VydmVyaXRlbXMucHVzaChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgIGlmKG5vZGUuaGFzT3duUHJvcGVydHkoXCJwYXRoXCIpKVxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwuc2VydmVyaXRlbXMucHVzaChub2RlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgJHNjb3BlLmRhdGFGb3JUaGVUcmVlID0gJHNjb3BlLm1vZGVsLnNlcnZlcmRhdGE7XG4gICAgICAgICRzY29wZS5kYXRhRm9yVGhlVHJlZUxvY2FsID0gJHNjb3BlLm1vZGVsLmxvY2FsZGF0YTtcblxuICAgICAgICAkc2NvcGUuJHdhdGNoKCdtb2RlbC5zZXJ2ZXJkYXRhJywgZnVuY3Rpb24obmV3VmFsdWUsb2xkVmFsdWUpe1xuICAgICAgICAgICBpZihuZXdWYWx1ZSl7XG4gICAgICAgICAgICAgICRzY29wZS5kYXRhRm9yVGhlVHJlZSA9ICRzY29wZS5tb2RlbC5zZXJ2ZXJkYXRhO1xuICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS4kd2F0Y2goJ21vZGVsLmxvY2FsZGF0YScsIGZ1bmN0aW9uKG5ld1ZhbHVlLG9sZFZhbHVlKXtcbiAgICAgICAgICAgaWYobmV3VmFsdWUpe1xuICAgICAgICAgICAgICAkc2NvcGUuZGF0YUZvclRoZVRyZWVMb2NhbCA9ICRzY29wZS5tb2RlbC5sb2NhbGRhdGE7XG4gICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLnVwTG9hZFhNTEZpbGUgPSAoZmlsZXMpID0+IHtcbiAgICAgICAgICAgRmlsdGVyTGlzdC5sZW5ndGg9MDtcbiAgICAgICAgICAgaWYoZmlsZXMubGVuZ3RoPjApe1xuICAgICAgICAgICAgIHZhciBqPTA7XG4gICAgICAgICAgICAgZm9yKHZhciBpPTA7aTxmaWxlcy5sZW5ndGg7aSsrKXtcbiAgICAgICAgICAgICAgIGlmKGZpbGVzW2ldLm5hbWUuaW5kZXhPZihcImRhdGEueG1sXCIpIT0tMSl7XG4gICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKGZpbGVzW2ldKTtcbiAgICAgICAgICAgICAgICAgIHJvb3RQYXRoPWZpbGVzW2ldLndlYmtpdFJlbGF0aXZlUGF0aC5yZXBsYWNlKC9cXC9kYXRhLnhtbCQvLFwiXCIpO1xuICAgICAgICAgICAgICAgICAgdmFyIHJlYWRlcj0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgICAgICAgICAgICAgICAgIHZhciByZXN1bHRTdHJpbmcgPSBcIntcXFwibmFtZVxcXCI6IFxcXCLmlbDmja5cXFwiLCBcXFwiY2hpbGRyZW5cXFwiOltcIjtcbiAgICAgICAgICAgICAgICAgIHJlYWRlci5vbmxvYWQgPSBmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgICAgICAgdmFyIHN0ciA9IGV2ZW50LnRhcmdldC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAvLyAgICAgYWxlcnQoc3RyKTtcbiAgICAgICAgICAgICAgICAgICAgIHZhciBpdGVtID0gXCI8RGF0YT5cIjtcbiAgICAgICAgICAgICAgICAgICAgIHZhciBpdGVtRW5kID0gXCI8L0RhdGE+XCI7XG4gICAgICAgICAgICAgICAgICAgICAvLyDCtMO9wrfCtcK7w5jCtcOEwr3DocK5w7vCo8K6XG4gICAgICAgICAgICAgICAgICAgICBpZihzdHIgIT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIMOVw7vCuMO2eG1sIMONw6rDlcO7w4rDvcK+w53Co8K6eG1sZGF0YVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHhtbGRhdGEgPSBzdHIudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIMKwwrTCtsOUw4/Ds8K3w5bCtcOEw4rDvcK+w53Co8K6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUFycmF5ID0geG1sZGF0YS5zcGxpdChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpdGVtc2l6ZSA9IGl0ZW1BcnJheS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGsgPSAxOyBrIDwgaXRlbXNpemU7IGsrKyl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW12YWx1ZSA9IGl0ZW1BcnJheVtrXS5zcGxpdChpdGVtRW5kKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwcm92aW5jZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm92aW5jZVZhbHVlVGVtcCA9IGl0ZW12YWx1ZVswXS5zcGxpdChcIjxwcm92aW5jZT5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3ZpbmNlVmFsdWUgPSBwcm92aW5jZVZhbHVlVGVtcFtwcm92aW5jZVZhbHVlVGVtcC5sZW5ndGgtMV0uc3BsaXQoXCI8L3Byb3ZpbmNlPlwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9jaXR5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNpdHlWYWx1ZVRlbXAgPSBpdGVtdmFsdWVbMF0uc3BsaXQoXCI8Y2l0eT5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNpdHlWYWx1ZSA9IGNpdHlWYWx1ZVRlbXBbY2l0eVZhbHVlVGVtcC5sZW5ndGgtMV0uc3BsaXQoXCI8L2NpdHk+XCIpWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb3VudHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY291bnR5VmFsdWVUZW1wID0gaXRlbXZhbHVlWzBdLnNwbGl0KFwiPGNvdW50eT5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNvdW50eVZhbHVlID0gY291bnR5VmFsdWVUZW1wW2NvdW50eVZhbHVlVGVtcC5sZW5ndGgtMV0uc3BsaXQoXCI8L2NvdW50eT5cIilbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxjb2RlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjb2RlVmFsdWVUZW1wID0gaXRlbXZhbHVlWzBdLnNwbGl0KFwiPGNvZGU+XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjb2RlVmFsdWUgPSBjb2RlVmFsdWVUZW1wW2NvZGVWYWx1ZVRlbXAubGVuZ3RoLTFdLnNwbGl0KFwiPC9jb2RlPlwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxzeXNfbmFtZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3lzX25hbWVWYWx1ZVRlbXAgPSBpdGVtdmFsdWVbMF0uc3BsaXQoXCI8c3lzX25hbWU+XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzeXNfbmFtZVZhbHVlID0gc3lzX25hbWVWYWx1ZVRlbXBbc3lzX25hbWVWYWx1ZVRlbXAubGVuZ3RoLTFdLnNwbGl0KFwiPC9zeXNfbmFtZT5cIilbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxjaGFyYWN0ZXJfc2V0PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGFyYWN0ZXJfc2V0VmFsdWVUZW1wID0gaXRlbXZhbHVlWzBdLnNwbGl0KFwiPGNoYXJhY3Rlcl9zZXQ+XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGFyYWN0ZXJfc2V0VmFsdWUgPSBjaGFyYWN0ZXJfc2V0VmFsdWVUZW1wW2NoYXJhY3Rlcl9zZXRWYWx1ZVRlbXAubGVuZ3RoLTFdLnNwbGl0KFwiPC9jaGFyYWN0ZXJfc2V0PlwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxzeXNfbmFtZV9jb2RlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzeXNfbmFtZV9jb2RlVmFsdWVUZW1wID0gaXRlbXZhbHVlWzBdLnNwbGl0KFwiPHN5c19uYW1lX2NvZGU+XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzeXNfbmFtZV9jb2RlVmFsdWUgPSBzeXNfbmFtZV9jb2RlVmFsdWVUZW1wW3N5c19uYW1lX2NvZGVWYWx1ZVRlbXAubGVuZ3RoLTFdLnNwbGl0KFwiPC9zeXNfbmFtZV9jb2RlPlwiKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8Y29udGFjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29udGFjdFZhbHVlVGVtcCA9IGl0ZW12YWx1ZVswXS5zcGxpdChcIjxjb250YWN0PlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29udGFjdFZhbHVlID0gY29udGFjdFZhbHVlVGVtcFtjb250YWN0VmFsdWVUZW1wLmxlbmd0aC0xXS5zcGxpdChcIjwvY29udGFjdD5cIilbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8cGhvbmU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBob25lVmFsdWVUZW1wID0gaXRlbXZhbHVlWzBdLnNwbGl0KFwiPHBob25lPlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGhvbmVWYWx1ZSA9IHBob25lVmFsdWVUZW1wW3Bob25lVmFsdWVUZW1wLmxlbmd0aC0xXS5zcGxpdChcIjwvcGhvbmU+XCIpWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPGRhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRhdGVWYWx1ZVRlbXAgPSBpdGVtdmFsdWVbMF0uc3BsaXQoXCI8ZGF0ZT5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRhdGVWYWx1ZSA9IGRhdGVWYWx1ZVRlbXBbZGF0ZVZhbHVlVGVtcC5sZW5ndGgtMV0uc3BsaXQoXCI8L2RhdGU+XCIpWzBdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9pZCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JZCA9IGNvZGVWYWx1ZSArIFwiX1wiICsgc3lzX25hbWVfY29kZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGh0dHAgZ2V0IHZlcnNpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmlkID0gaXRlbUlkLy8ucmVwbGFjZSgvXFxcIi9nLCBcIlwiKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE8gdHlwZVZhbHVlIOmAmui/h+WJjeerr+mhtemdouiOt+WPluaIluiAhe+8n++8n++8jOi0ouaUvzAx5oiW56S+5L+dMDJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZVZhbHVlID0gXCIwMVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE8gYmF0Y2hWYWx1ZSDpgJrov4fliY3nq6/pobXpnaLojrflj5bmiJbogIXvvJ/vvJ/vvIzmibnmrKFBIO+8muWkp+WGmeeahEHvvIzmibnmrKFCIO+8muWkp+WGmeeahELvvIxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYmF0Y2hWYWx1ZSA9IFwiQVwiO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1uYW1lID0gY2l0eVZhbHVlICsgY291bnR5VmFsdWUgKyBzeXNfbmFtZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uaWQgPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2U9ZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoeGhyLnJlYWR5U3RhdGU9PTQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoeGhyLnN0YXR1cz09MjAwKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnNpb25pZCA9IHhoci5yZXNwb25zZVRleHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeGhyLm9wZW4oXCJnZXRcIixcIi9nZXR2ZXJzaW9uP2lkPVwiK3JpZCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhoci5zZW5kKG51bGwpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGpzb2JqID0gSlNPTi5wYXJzZSh2ZXJzaW9uaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB4bWx2ZXJzaW9uID0ganNvYmouaWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVyVmFsdWUgPSBcIntcXFwiaWRcXFwiOlxcXCJcIitpdGVtSWQrXCJcXFwiLCBcXFwibmFtZVxcXCI6XFxcIlwiK2l0ZW1uYW1lK1wiXFxcIiwgXFxcImNpdHlcXFwiOlxcXCJcIitcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0eVZhbHVlICsgXCJcXFwiLCBcXFwiY291bnR5XFxcIjpcXFwiXCIrY291bnR5VmFsdWUrXCJcXFwiLCBcXFwic3lzdGVtXFxcIjpcXFwiXCIrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN5c19uYW1lVmFsdWUrXCJcXFwiLCBcXFwidHlwZVxcXCI6XFxcIlwiICsgdHlwZVZhbHVlICsgXCJcXFwiLFxcXCJiYXRjaFxcXCI6XFxcIlwiK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaFZhbHVlK1wiXFxcIixcXFwidmVyc2lvblxcXCI6XFxcIlwiK3htbHZlcnNpb24rXCJcXFwiLCBcXFwicHJvdmluY2VcXFwiOlxcXCJcIitcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmluY2VWYWx1ZSArXCJcXFwiLCBcXFwiY29kZVxcXCI6XFxcIlwiK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlVmFsdWUgK1wiXFxcIiwgXFxcImNoYXJhY3Rlcl9zZXRcXFwiOlxcXCJcIitcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhcmFjdGVyX3NldFZhbHVlICtcIlxcXCIsIFxcXCJzeXNfbmFtZV9jb2RlXFxcIjpcXFwiXCIrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN5c19uYW1lX2NvZGVWYWx1ZSArXCJcXFwiLCBcXFwiY29udGFjdFxcXCI6XFxcIlwiK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWN0VmFsdWUgK1wiXFxcIiwgXFxcInBob25lXFxcIjpcXFwiXCIrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBob25lVmFsdWUgK1wiXFxcIiwgXFxcImRhdGVcXFwiOlxcXCJcIitcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZVZhbHVlICtcIlxcXCJ9XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0U3RyaW5nID0gcmVzdWx0U3RyaW5nICsgcHJvcGVyVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoayA8IGl0ZW1zaXplLTEpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgPXJlc3VsdFN0cmluZytcIiwgXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRTdHJpbmcgPSByZXN1bHRTdHJpbmcrXCJdfVwiO1xuICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwubG9jYWxkYXRhID0gSlNPTi5wYXJzZShyZXN1bHRTdHJpbmcudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc1RleHQoZmlsZXNbaV0sXCJ1dGYtOFwiKTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgRmlsdGVyTGlzdC5sZW5ndGgrPTE7XG4gICAgICAgICAgICAgICAgICAgdmFyIGZpbGVfaWQ9ZmlsZXNbaV0ubmFtZS5yZXBsYWNlKC9cXC5cXHcqJC8sJycpO1xuICAgICAgICAgICAgICAgICAgIC8vIHZhciBmaWxlX2lkPWZpbGVbaV0ud2Via2l0UmVsYXRpdmVQYXRoLnJlcGxhY2UoL15bYS16XSpcXC8kLywnJyk7XG4gICAgICAgICAgICAgICAgICAgLy9cdCAgZmlsZV9pZCA9IGZpbGVfaWQucmVwbGFjZSgvXFwvXFx3KyQvLCcnKTtcbiAgICAgICAgICAgICAgICAgIEZpbHRlckxpc3RbaisrXT1maWxlc1tpXTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICB9XG4gICAgICAgICAgIH1cbiAgICAgICAgICAgJHNjb3BlLm1vZGVsLnVwbG9hZHByb2Nlc3MgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAkc2NvcGUudXBMb2FkRmlsZXMgPSAoKT0+e1xuICAgICAgICAgaWYoJHNjb3BlLm1vZGVsLnVwbG9hZGVkU3RhdHVzID09IFwib25jZVwiKXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgIH1cbiAgICAgICAgICRzY29wZS5tb2RlbC51cGxvYWRlZFN0YXR1cyA9IFwib25jZVwiO1xuICAgICAgICAgJHNjb3BlLm1vZGVsLmNyZWF0ZUZvbGRlckxpc3QoRmlsdGVyTGlzdCxyb290UGF0aCk7XG4gICAgICAgICBpZigkc2NvcGUubW9kZWwuZm9sZGVyTGlzdC5sZW5ndGggPjAgJiYgJHNjb3BlLm1vZGVsLnNlbGVjdGVkbm9kZXMubGVuZ3RoID4wKXtcbiAgICAgICAgICAgIHZhciBpc05vdEV4aXRlZCA9IFtdO1xuICAgICAgICAgICAgdmFyIGlzRXhpdGVkID0gW107XG4gICAgICAgICAgICBmb3IodmFyIG5vZGUgaW4gJHNjb3BlLm1vZGVsLnNlbGVjdGVkbm9kZXMpe1xuICAgICAgICAgICAgICAgaWYoISRzY29wZS5tb2RlbC5mb2xkZXJMaXN0Lmhhc093blByb3BlcnR5KCRzY29wZS5tb2RlbC5zZWxlY3RlZG5vZGVzW25vZGVdLmlkKSl7XG4gICAgICAgICAgICAgICAgICBpc05vdEV4aXRlZC5wdXNoKCRzY29wZS5tb2RlbC5zZWxlY3RlZG5vZGVzW25vZGVdKTtcbiAgICAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICAgICAgaWYoJHNjb3BlLm1vZGVsLnVwbG9hZHByb2Nlc3NbJHNjb3BlLm1vZGVsLnNlbGVjdGVkbm9kZXNbbm9kZV0uaWRdID09PSAndW5kZWZpbmVkJyB8fCAkc2NvcGUubW9kZWwudXBsb2FkcHJvY2Vzc1skc2NvcGUubW9kZWwuc2VsZWN0ZWRub2Rlc1tub2RlXS5pZF0gPT09IDApXG4gICAgICAgICAgICAgICAgICAgICBpc0V4aXRlZC5wdXNoKCRzY29wZS5tb2RlbC5zZWxlY3RlZG5vZGVzW25vZGVdKTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGlzTm90RXhpdGVkLmxlbmd0aCA+MCApe1xuICAgICAgICAgICAgICAgdmFyIHN0ciA9IFwi5Lul5LiL5pWw5o2u5paH5Lu25LiN5a2Y5ZyoOlxcblxccuaWh+S7tuWQjTpcXG5cIjtcbiAgICAgICAgICAgICAgIGZvcih2YXIgaXRlbSBpbiBpc05vdEV4aXRlZClcbiAgICAgICAgICAgICAgICAgIHN0ciArPSBpc05vdEV4aXRlZFtpdGVtXS5pZCtcIlxcblwiO1xuICAgICAgICAgICAgICAgYWxlcnQoc3RyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaXNFeGl0ZWQubGVuZ3RoIDw9MCl7XG4gICAgICAgICAgICAgICBhbGVydChcIuaVsOaNruaWh+S7tuS4reayoeacieWPr+eUqOS4iuS8oOeahOaWh+S7tiFcIik7XG4gICAgICAgICAgICB9ZWxzZXtcblx0XHRcdCAgIHZhciBpc3VwbG9hYWQgPSAxLGkgPSAwO1xuXHRcdFx0ICAgdmFyIHRpbWVyRm9yVXBsb2FkID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXtcblx0XHRcdFx0ICBpZihpID49IGlzRXhpdGVkLmxlbmd0aCl7XG5cdFx0XHRcdFx0IGNsZWFySW50ZXJ2YWwodGltZXJGb3JVcGxvYWQpO1xuXHRcdFx0XHQgIH1cblx0XHRcdFx0ICBpZihpc3VwbG9hYWQgPT0gMSl7XG5cdFx0XHRcdFx0IHZhciByID0gbmV3IFJlc3VtYWJsZSh7XG5cdFx0XHRcdFx0XHR0YXJnZXQ6Jy91cGxvYWRmaWxlcycsXG5cdFx0XHRcdFx0XHRjaHVua1NpemU6NTAqMTAyNCoxMDI0LFxuXHRcdFx0XHRcdFx0c2ltdWx0YW5lb3VzVXBsb2Fkczo0MDAsXG5cdFx0XHRcdFx0XHR0ZXN0Q2h1bmtzOnRydWUsXG5cdFx0XHRcdFx0XHR0aHJvdHRsZVByb2dyZXNzQ2FsbGJhY2tzOjFcblx0XHRcdFx0XHR9KTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHhoci5vcGVuKFwiR0VUXCIsXCIvZ2V0Y2xpZW50aXBcIix0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgICAgICAgIGlmKHhoci5yZWFkeVN0YXRlPT00KXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHhoci5zdGF0dXM9PTIwMCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHIuc2V0aXAoeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHhoci5zZW5kKG51bGwpO1xuXG5cdFx0XHRcdFx0ci5vbignZmlsZUFkZGVkJywgZnVuY3Rpb24oZmlsZSl7XG5cdFx0XHRcdFx0XHRyLnVwbG9hZCgpO1xuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdFx0JHNjb3BlLm1vZGVsLnJlc3VtYWJsZWpzLnB1c2goe1xuXHRcdFx0XHRcdCAgIGRpcm5hbWUgOiBpc0V4aXRlZFtpXS5pZCxcblx0XHRcdFx0XHQgICByZXN1bWFibGUgOiByXG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRyLnNldFJvb3RQYXRoKGlzRXhpdGVkW2ldLnR5cGUrXCIvXCIraXNFeGl0ZWRbaV0uYmF0Y2grXCIvXCIraXNFeGl0ZWRbaV0uaWQrXCIvXCIraXNFeGl0ZWRbaV0udmVyc2lvbitcIi9cIik7XG5cblx0XHRcdFx0XHRyLm15TG9hZEZpbGVzKCRzY29wZS5tb2RlbC5mb2xkZXJMaXN0W2lzRXhpdGVkW2ldLmlkXSk7XG5cdFx0XHRcdFx0ci51cGxvYWQoKTtcblxuXHRcdFx0XHRcdHIub24oJ2ZpbGVQcm9ncmVzcycsZnVuY3Rpb24oZmlsZSl7XG5cdFx0XHRcdFx0XHR2YXIgZmlsZV9pZD1maWxlLnJlbGF0aXZlUGF0aC5yZXBsYWNlKC9eW2Etel0qXFwvJC8sJycpO1xuXHRcdFx0XHRcdFx0dmFyIGZpbGVzdHIgPSBcIlwiO1xuXHRcdFx0XHRcdFx0dmFyIHJlZyA9IC9cXC9bMC05XSpfKlswLTldKlxcLy9nO1xuXHRcdFx0XHRcdFx0dmFyIHJlc3VsdHN0cjtcblx0XHRcdFx0XHRcdHdoaWxlKCAocmVzdWx0c3RyID0gcmVnLmV4ZWMoZmlsZV9pZCkpICE9IG51bGwpe1xuXHRcdFx0XHRcdFx0XHRmaWxlc3RyID0gcmVzdWx0c3RyWzBdO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZmlsZV9pZCA9IGZpbGVzdHIucmVwbGFjZSgvXFwvKi9nLCcnKTtcblx0XHRcdFx0XHRcdHIuc2V0RmlsZUlkKGZpbGVfaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8kc2NvcGUuJGFwcGx5KGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwudXBsb2FkcHJvY2Vzc1tmaWxlX2lkXSA9IE1hdGguZmxvb3Ioci5wcm9ncmVzcygpKjk4KTtcblx0XHRcdFx0XHRcdC8vfSk7XG5cblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdHIub24oJ2NvbXBsZXRlJywgZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRcdHZhciB0aW1lckZvcmNobW9kID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRcdFx0dmFyIHBhdGhqc29uID0gXCJcXFwicGF0aFxcXCI6XFxcIlwiK3IuZ2V0cm9vdFBhdGgoKStcIlxcXCJcIlxuXHRcdFx0XHRcdFx0XHR2YXIgZGF0YW1lc3NhZ2UgPSB7XCJwYXRoXCI6ci5nZXRyb290UGF0aCgpLFwiZmlsZW51bVwiOiRzY29wZS5tb2RlbC5mb2xkZXJMaXN0W2lzRXhpdGVkW2ktMV0uaWRdLmxlbmd0aH07XG5cdFx0XHRcdFx0XHRcdCRzY29wZS5tb2RlbC51cGxvYWRwcm9jZXNzW3IuZ2V0RmlsZUlkKCldID0gTWF0aC5yb3VuZChyLnByb2dyZXNzKCkqOTkpO1xuXG5cdFx0XHRcdFx0XHRcdCRodHRwKHtcblx0XHRcdFx0XHRcdFx0ICB1cmw6Jy9zZXRjaG1vZDJkaXInLFxuXHRcdFx0XHRcdFx0XHQgIG1ldGhvZDonR0VUJyxcblx0XHRcdFx0XHRcdFx0ICBwYXJhbXM6ZGF0YW1lc3NhZ2Vcblx0XHRcdFx0XHRcdFx0fSkuc3VjY2VzcyhmdW5jdGlvbihkYXRhLGhlYWRlcixjb25maWcsc3RhdHVzKXtcblx0XHRcdFx0XHRcdFx0ICBpZihkYXRhKXtcblx0XHRcdFx0XHRcdFx0XHRcdC8vY29uc29sZS5sb2coZGF0YSk7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgY2xpZW50ZGF0YSA9IGRhdGE7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZihjbGllbnRkYXRhID09IFwiY2htb2RcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZERhdGVNZXNzYWdlKGlzRXhpdGVkW2ktMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHIuc2V0aXNub3djaGVjayhcIjFcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgci5ta1JldGZpbGVVcGxvYWRTdWNjZWVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aW1lckZvcmNobW9kKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdCAgfVxuXG5cdFx0XHRcdFx0XHRcdH0pLmVycm9yKGZ1bmN0aW9uKGRhdGEsaGVhZGVyLGNvbmZpZyxzdGF0dXMpe1xuXHRcdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKFwiLS0tLS1zZW5kRGF0ZU1lc3NhZ2UtLS0tLS0tLS0tLS0tXCIrc3RhdHVzKTtcblx0XHRcdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRcdH0sNTAwMCk7XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRpKys7XG5cdFx0XHRcdFx0aXN1cGxvYWFkID0gMDtcblxuICAgICAgICAgICAgICAgICAgICByLm9uKCdmaWxldXBsb2FkZW5kc3VjY2VlZCcsIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5tb2RlbC51cGxvYWRwcm9jZXNzW3IuZ2V0RmlsZUlkKCldID0gTWF0aC5mbG9vcihyLnByb2dyZXNzKCkqMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgJHRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAkaHR0cCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDonL3htbGZvcm1zZXJ2ZXInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q6J1Bvc3QnXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pLnN1Y2Nlc3MoZnVuY3Rpb24oZGF0YSxoZWFkZXIsY29uZmlnLHN0YXR1cyl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoZGF0YSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLm1vZGVsLnNlcnZlcmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuZXJyb3IoZnVuY3Rpb24oZGF0YSxoZWFkZXIsY29uZmlnLHN0YXR1cyl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcImVycm9yXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgfSwyMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgaXN1cGxvYWFkID0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG5cdFx0XHQgICB9LDIwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICBhbGVydChcIuaCqOayoeaciemAieaLqemcgOimgeS4iuS8oOeahOaVsOaNruaWh+S7tu+8jOaIluS9oOmAieaLqeeahOaWh+S7tuS4reS4jeWtmOWcqOaMh+WumuagvOW8j+eahOaVsOaNruaWh+S7tiFcIik7XG4gICAgICAgICB9XG5cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gc2VuZERhdGVNZXNzYWdlKGRhdGFtZXNzYWdlKXtcbiAgICAgICAgICAkaHR0cCh7XG4gICAgICAgICAgICAgdXJsOicvc2VuZERhdGVNZXNzYWdlJyxcbiAgICAgICAgICAgICBtZXRob2Q6J0dFVCcsXG4gICAgICBcdCAgICAgcGFyYW1zOmRhdGFtZXNzYWdlXG4gICAgICAgICAgfSkuc3VjY2VzcyhmdW5jdGlvbihkYXRhLGhlYWRlcixjb25maWcsc3RhdHVzKXtcbiAgICAgICAgICAgICBpZihkYXRhKVxuICAgICAgICAgICAgIHZhciBjbGllbnRkYXRhID0gZGF0YTtcbiAgICAgICAgICB9KS5lcnJvcihmdW5jdGlvbihkYXRhLGhlYWRlcixjb25maWcsc3RhdHVzKXtcblxuICAgICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAkc2NvcGUuZG93bkxvYWRGaWxlcyA9ICgpPT57XG4gICAgICAgICAgS3ViZXJuZXRlcy5jb25uZWN0T3JhY2xlKCRodHRwLCAkdGltZW91dCwgXCIxOTIuMTY4LjAuMTAzOjY0MTgyXCIsIFwiMzIwNjE0LTU0LTFcIiwgNTAwKTtcbiAgICAgIH1cblxuICAgICAgJHNjb3BlLmlzU2VsZWN0ZWQ9IChub2RlKT0+e1xuICAgICAgICAgdmFyIGluZGV4ID0gJHNjb3BlLm1vZGVsLmZpbmRJdGVtSW5kZXgobm9kZSk7XG4gICAgICAgICBpZihpbmRleCAhPT0gLTEpe1xuICAgICAgICAgICAgJHNjb3BlLm1vZGVsLnNlbGVjdGVkaXRlbXMuc3BsaWNlKGluZGV4LDEpO1xuICAgICAgICAgfVxuICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICRzY29wZS5tb2RlbC5zZWxlY3RlZGl0ZW1zLnB1c2gobm9kZSk7XG4gICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgICRzY29wZS5zaG93U2VsZWN0ZWRMb2NhbCA9IChub2RlLHNlbGVjdGVkKSA9PiB7XG4gICAgICAgICB2YXIgaW5kZXggPSAkc2NvcGUubW9kZWwuZmluZE5vZGVzKG5vZGUpO1xuICAgICAgICAgaWYoaW5kZXggIT09IFwiLTFcIil7XG4gICAgICAgICAgICBpZigkc2NvcGUubW9kZWwudXBsb2FkcHJvY2Vzc1tub2RlLmlkXSA9PT0wKVxuICAgICAgICAgICAgICAgJHNjb3BlLm1vZGVsLnNlbGVjdGVkbm9kZXMuc3BsaWNlKGluZGV4LDEpO1xuICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAkc2NvcGUubW9kZWwudXBsb2FkcHJvY2Vzc1tub2RlLmlkXSA9MDtcbiAgICAgICAgICAgICRzY29wZS5tb2RlbC5zZWxlY3RlZG5vZGVzLnB1c2gobm9kZSk7XG4gICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgICRzY29wZS5zdGFydE9yYWNsZSA9ICgpPT4ge1xuICAgICAgICAgaWYoJHNjb3BlLm1vZGVsLnNlbGVjdGVkaXRlbXMubGVuZ3RoID4wKXtcbiAgICAgICAgICAgIGZvcih2YXIgaWQgaW4gJHNjb3BlLm1vZGVsLnNlbGVjdGVkaXRlbXMpe1xuICAgICAgICAgICAgICAgdmFyIE9iaiA9IGNyZWF0ZVJDT2JqKCRzY29wZS5tb2RlbC5zZWxlY3RlZGl0ZW1zW2lkXSk7XG4gICAgICAgICAgICAgICBpZighY2hlY2tJc1J1bm5pbmcoS3ViZXJuZXRlc01vZGVsLnJlcGxpY2F0aW9uQ29udHJvbGxlcnMsT2JqKSl7XG4gICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLmNyZWF0ZVJDKE9iaiwgKHJjKSA9PntcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhyYy5tZXRhZGF0YS5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLmNvbm5lY3RPcmFjbGUoJGh0dHAsICR0aW1lb3V0LCBcIi9jb25uZWN0VG9PcmFjbGVcIiwgXCJcIiwgcmMubWV0YWRhdGEubmFtZSwgMCk7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gY2hlY2tJc1J1bm5pbmcocmVwbGljYXRpb25Db250cm9sbGVycyxpdGVtKXtcbiAgICAgICAgIGZvcih2YXIgcmMgaW4gcmVwbGljYXRpb25Db250cm9sbGVycyl7XG4gICAgICAgICAgICBpZihpdGVtLm5hbWUgPT09IHJlcGxpY2F0aW9uQ29udHJvbGxlcnNbcmNdLm1ldGFkYXRhLm5hbWUpXG4gICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgIH1cbiAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gY3JlYXRlUkNPYmooaXRlbTogT2JqZWN0KXtcbiAgICAgICAgIHZhciBhcnJheSA9aXRlbS5pZC5zcGxpdChcIl9cIik7XG4gICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgXCJuYW1lXCI6IGFycmF5WzJdICsgXCItXCIgKyBhcnJheVszXSArIFwiLVwiICsgYXJyYXlbNF0sXG4gICAgICAgICAgICBcImxhYmVsc1wiOiB7XG4gICAgICAgICAgICAgICBcInR5cGVcIjogYXJyYXlbMF0sXG4gICAgICAgICAgICAgICBcImJhdGNoXCI6IGFycmF5WzFdLFxuICAgICAgICAgICAgICAgXCJyZWdpb25cIjogYXJyYXlbMl0sXG4gICAgICAgICAgICAgICBcInN5c3RlbVwiOiBhcnJheVszXSxcbiAgICAgICAgICAgICAgIFwidmVyc2lvblwiOiBhcnJheVs0XVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwicGF0aFwiOiBpdGVtLnBhdGggK1wiYXBwL1wiXG4gICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHNldGNobW9kMmRpcihkYXRhbWVzc2FnZSl7XG4gICAgICAgICAkaHR0cCh7XG4gICAgICAgICAgICB1cmw6Jy9zZXRjaG1vZDJkaXInLFxuICAgICAgICAgICAgbWV0aG9kOidHRVQnLFxuICAgICAgICAgICAgcGFyYW1zOmRhdGFtZXNzYWdlXG4gICAgICAgICB9KS5zdWNjZXNzKGZ1bmN0aW9uKGRhdGEsaGVhZGVyLGNvbmZpZyxzdGF0dXMpe1xuICAgICAgICAgICAgaWYoZGF0YSlcbiAgICAgICAgICAgICAgdmFyIGNsaWVudGRhdGEgPSBkYXRhO1xuICAgICAgICAgfSkuZXJyb3IoZnVuY3Rpb24oZGF0YSxoZWFkZXIsY29uZmlnLHN0YXR1cyl7XG4gICAgICAgICAgICAgY29uc29sZS5sb2coXCItLS0tLXNlbmREYXRlTWVzc2FnZS0tLS0tLS0tLS0tLS1cIitzdGF0dXMpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdXBkYXRlKCl7XG4gICAgICAgICBmb3IodmFyIGk9MDsgaTwkc2NvcGUubW9kZWwucmVzdW1hYmxlanMubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgdmFyIGRpcklkID0gJHNjb3BlLm1vZGVsLnJlc3VtYWJsZWpzW2ldLmRpcm5hbWU7XG4gICAgICAgICAgICB2YXIgciA9ICRzY29wZS5tb2RlbC5yZXN1bWFibGVqc1tpXS5yZXN1bWFibGU7XG4gICAgICAgICAgICByLm9uKCdmaWxlUHJvZ3Jlc3MnLCAoZmlsZSkgPT57XG4gICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUubW9kZWwudXBsb2FkcHJvY2Vzc1tkaXJJZF0gPSBNYXRoLmZsb29yKHIucHJvZ3Jlc3MoKSoxMDApO1xuICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZGlySWQrXCI6XCIrTWF0aC5mbG9vcihyLnByb2dyZXNzKCkqMTAwKSlcbiAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICB9XG4gICAgICB9XG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG4gIFxuICBleHBvcnQgdmFyIEFwcHMgPSBjb250cm9sbGVyKFwiQXBwc1wiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTZXJ2aWNlc1wiLCBcIkt1YmVybmV0ZXNSZXBsaWNhdGlvbkNvbnRyb2xsZXJzXCIsIFwiS3ViZXJuZXRlc1BvZHNcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiRkaWFsb2dcIiwgXCIkdGltZW91dFwiLCBcbiAgICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDogS3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU2VydmljZXM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1JlcGxpY2F0aW9uQ29udHJvbGxlcnM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1BvZHM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICRkaWFsb2csICR0aW1lb3V0KSA9PiB7XG5cbiAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG5cbiAgICAkc2NvcGUuYXBwcyA9IFtdO1xuICAgICRzY29wZS5hbGxBcHBzID0gW107XG4gICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgJHNjb3BlLmZldGNoZWQgPSBmYWxzZTtcbiAgICAkc2NvcGUuanNvbiA9ICcnO1xuICAgIENvbnRyb2xsZXJIZWxwZXJzLmJpbmRNb2RlbFRvU2VhcmNoUGFyYW0oJHNjb3BlLCAkbG9jYXRpb24sICdpZCcsICdfaWQnLCB1bmRlZmluZWQpO1xuICAgIENvbnRyb2xsZXJIZWxwZXJzLmJpbmRNb2RlbFRvU2VhcmNoUGFyYW0oJHNjb3BlLCAkbG9jYXRpb24sICdhcHBTZWxlY3RvclNob3cnLCAnb3BlbkFwcCcsIHVuZGVmaW5lZCk7XG4gICAgQ29udHJvbGxlckhlbHBlcnMuYmluZE1vZGVsVG9TZWFyY2hQYXJhbSgkc2NvcGUsICRsb2NhdGlvbiwgJ21vZGUnLCAnbW9kZScsICdkZXRhaWwnKTtcblxuICAgIHZhciBicmFuY2ggPSAkc2NvcGUuYnJhbmNoIHx8IFwibWFzdGVyXCI7XG4gICAgdmFyIG5hbWVzcGFjZSA9IG51bGw7XG5cbiAgICBmdW5jdGlvbiBhcHBNYXRjaGVzKGFwcCkge1xuICAgICAgdmFyIGZpbHRlclRleHQgPSAkc2NvcGUuYXBwU2VsZWN0b3IuZmlsdGVyVGV4dDtcbiAgICAgIGlmIChmaWx0ZXJUZXh0KSB7XG4gICAgICAgIHJldHVybiBDb3JlLm1hdGNoRmlsdGVySWdub3JlQ2FzZShhcHAuZ3JvdXBJZCwgZmlsdGVyVGV4dCkgfHxcbiAgICAgICAgICBDb3JlLm1hdGNoRmlsdGVySWdub3JlQ2FzZShhcHAuYXJ0aWZhY3RJZCwgZmlsdGVyVGV4dCkgfHxcbiAgICAgICAgICBDb3JlLm1hdGNoRmlsdGVySWdub3JlQ2FzZShhcHAubmFtZSwgZmlsdGVyVGV4dCkgfHxcbiAgICAgICAgICBDb3JlLm1hdGNoRmlsdGVySWdub3JlQ2FzZShhcHAuZGVzY3JpcHRpb24sIGZpbHRlclRleHQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXBwUnVubmluZyhhcHApIHtcbiAgICAgIHJldHVybiAkc2NvcGUubW9kZWwuYXBwcy5hbnkoKHJ1bm5pbmcpID0+IHJ1bm5pbmcuYXBwUGF0aCA9PT0gYXBwLmFwcFBhdGgpO1xuICAgIH1cblxuICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgIGRhdGE6ICdtb2RlbC5hcHBzJyxcbiAgICAgIHNob3dTZWxlY3Rpb25DaGVja2JveDogdHJ1ZSxcbiAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgIG11bHRpU2VsZWN0OiB0cnVlLFxuICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgIGZpbHRlclRleHQ6ICRsb2NhdGlvbi5zZWFyY2goKVtcInFcIl0gfHwgJydcbiAgICAgIH0sXG4gICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgIHsgZmllbGQ6ICckbmFtZScsIGRpc3BsYXlOYW1lOiAnQXBwJywgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoVXJsSGVscGVycy5qb2luKHRlbXBsYXRlUGF0aCwgXCJhcHBJY29uVGVtbGF0ZS5odG1sXCIpKSB9LFxuICAgICAgICB7IGZpZWxkOiAnJHNlcnZpY2VzVGV4dCcsIGRpc3BsYXlOYW1lOiAnU2VydmljZXMnLCBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChVcmxIZWxwZXJzLmpvaW4odGVtcGxhdGVQYXRoLCBcImFwcFNlcnZpY2VzVGVtcGxhdGUuaHRtbFwiKSkgfSxcbiAgICAgICAgeyBmaWVsZDogJyRyZXBsaWNhdGlvbkNvbnRyb2xsZXJzVGV4dCcsIGRpc3BsYXlOYW1lOiAnQ29udHJvbGxlcnMnLCBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChVcmxIZWxwZXJzLmpvaW4odGVtcGxhdGVQYXRoLCBcImFwcFJlcGxpY2F0aW9uQ29udHJvbGxlclRlbXBsYXRlLmh0bWxcIikpIH0sXG4gICAgICAgIHsgZmllbGQ6ICckcG9kQ291bnQnLCBkaXNwbGF5TmFtZTogJ1BvZHMnLCBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChVcmxIZWxwZXJzLmpvaW4odGVtcGxhdGVQYXRoLCBcImFwcFBvZENvdW50c0FuZExpbmtUZW1wbGF0ZS5odG1sXCIpKSB9LFxuICAgICAgICB7IGZpZWxkOiAnJGNyZWF0aW9uRGF0ZScsIGRpc3BsYXlOYW1lOiAnRGVwbG95ZWQnLCBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChVcmxIZWxwZXJzLmpvaW4odGVtcGxhdGVQYXRoLCBcImFwcERlcGxveWVkVGVtcGxhdGUuaHRtbFwiKSkgfVxuICAgICAgXVxuICAgIH07XG5cbiAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG5cblxuICAgICRzY29wZS5leHBhbmRlZFBvZHMgPSBbXTtcblxuICAgICRzY29wZS4kb24oJ2RvLXJlc2l6ZScsICgkZXZlbnQsIGNvbnRyb2xsZXIpID0+IHtcbiAgICAgICRzY29wZS5yZXNpemVEaWFsb2cub3Blbihjb250cm9sbGVyKTtcbiAgICB9KTtcblxuICAgICAgICBcbiAgICAkc2NvcGUucG9kRXhwYW5kZWQgPSAocG9kKSA9PiB7XG4gICAgICB2YXIgaWQgPSBnZXROYW1lKHBvZClcbiAgICAgIHJldHVybiBpZCAmJiAoJHNjb3BlLmV4cGFuZGVkUG9kcyB8fCBbXSkuaW5kZXhPZihpZCkgPj0gMDtcbiAgICB9O1xuXG4gICAgJHNjb3BlLmV4cGFuZFBvZCA9IChwb2QpID0+IHtcbiAgICAgIHZhciBpZCA9IGdldE5hbWUocG9kKTtcbiAgICAgIGlmIChpZCkge1xuICAgICAgICAkc2NvcGUuZXhwYW5kZWRQb2RzLnB1c2goaWQpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICAkc2NvcGUuY29sbGFwc2VQb2QgPSAocG9kKSA9PiB7XG4gICAgICB2YXIgaWQgPSBnZXROYW1lKHBvZCk7XG4gICAgICBpZiAoaWQpIHtcbiAgICAgICAgXy5yZW1vdmUoJHNjb3BlLmV4cGFuZGVkUG9kcywgKHYpID0+IGlkID09PSB2KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgS3ViZXJuZXRlcy5zZXRKc29uKCRzY29wZSwgJGxvY2F0aW9uLnNlYXJjaCgpWydfaWQnXSwgJHNjb3BlLm1vZGVsLmFwcHMpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gZGVsZXRlQXBwKGFwcCwgb25Db21wbGV0ZUZuKSB7XG4gICAgICBmdW5jdGlvbiBkZWxldGVTZXJ2aWNlcyhzZXJ2aWNlcywgc2VydmljZSwgb25Db21wbGV0ZWRGbikge1xuICAgICAgICBpZiAoIXNlcnZpY2UgfHwgIXNlcnZpY2VzKSB7XG4gICAgICAgICAgcmV0dXJuIG9uQ29tcGxldGVkRm4oKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaWQgPSBnZXROYW1lKHNlcnZpY2UpO1xuICAgICAgICBpZiAoIWlkKSB7XG4gICAgICAgICAgbG9nLndhcm4oXCJObyBJRCBmb3Igc2VydmljZSBcIiArIGFuZ3VsYXIudG9Kc29uKHNlcnZpY2UpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBLdWJlcm5ldGVzU2VydmljZXMuZGVsZXRlKHtcbiAgICAgICAgICAgIGlkOiBpZFxuICAgICAgICAgIH0sIHVuZGVmaW5lZCwgKCkgPT4ge1xuICAgICAgICAgICAgbG9nLmRlYnVnKFwiRGVsZXRlZCBzZXJ2aWNlOiBcIiwgaWQpO1xuICAgICAgICAgICAgZGVsZXRlU2VydmljZXMoc2VydmljZXMsIHNlcnZpY2VzLnNoaWZ0KCksIG9uQ29tcGxldGVkRm4pO1xuICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgbG9nLmRlYnVnKFwiRXJyb3IgZGVsZXRpbmcgc2VydmljZTogXCIsIGVycm9yKTtcbiAgICAgICAgICAgIGRlbGV0ZVNlcnZpY2VzKHNlcnZpY2VzLCBzZXJ2aWNlcy5zaGlmdCgpLCBvbkNvbXBsZXRlZEZuKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZWxldGVSZXBsaWNhdGlvbkNvbnRyb2xsZXJzKHJlcGxpY2F0aW9uQ29udHJvbGxlcnMsIHJlcGxpY2F0aW9uQ29udHJvbGxlciwgb25Db21wbGV0ZWRGbikge1xuICAgICAgICBpZiAoIXJlcGxpY2F0aW9uQ29udHJvbGxlciB8fCAhcmVwbGljYXRpb25Db250cm9sbGVycykge1xuICAgICAgICAgIHJldHVybiBvbkNvbXBsZXRlZEZuKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGlkID0gZ2V0TmFtZShyZXBsaWNhdGlvbkNvbnRyb2xsZXIpO1xuICAgICAgICBpZiAoIWlkKSB7XG4gICAgICAgICAgbG9nLndhcm4oXCJObyBJRCBmb3IgcmVwbGljYXRpb25Db250cm9sbGVyIFwiICsgYW5ndWxhci50b0pzb24ocmVwbGljYXRpb25Db250cm9sbGVyKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgS3ViZXJuZXRlc1JlcGxpY2F0aW9uQ29udHJvbGxlcnMuZGVsZXRlKHtcbiAgICAgICAgICAgIGlkOiBpZFxuICAgICAgICAgIH0sIHVuZGVmaW5lZCwgKCkgPT4ge1xuICAgICAgICAgICAgbG9nLmRlYnVnKFwiRGVsZXRlZCByZXBsaWNhdGlvbkNvbnRyb2xsZXI6IFwiLCBpZCk7XG4gICAgICAgICAgICBkZWxldGVSZXBsaWNhdGlvbkNvbnRyb2xsZXJzKHJlcGxpY2F0aW9uQ29udHJvbGxlcnMsIHJlcGxpY2F0aW9uQ29udHJvbGxlcnMuc2hpZnQoKSwgb25Db21wbGV0ZWRGbik7XG4gICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICBsb2cuZGVidWcoXCJFcnJvciBkZWxldGluZyByZXBsaWNhdGlvbkNvbnRyb2xsZXI6IFwiLCBlcnJvcik7XG4gICAgICAgICAgICBkZWxldGVSZXBsaWNhdGlvbkNvbnRyb2xsZXJzKHJlcGxpY2F0aW9uQ29udHJvbGxlcnMsIHJlcGxpY2F0aW9uQ29udHJvbGxlcnMuc2hpZnQoKSwgb25Db21wbGV0ZWRGbik7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gZGVsZXRlUG9kcyhwb2RzLCBwb2QsIG9uQ29tcGxldGVkRm4pIHtcbiAgICAgICAgaWYgKCFwb2QgfHwgIXBvZHMpIHtcbiAgICAgICAgICByZXR1cm4gb25Db21wbGV0ZWRGbigpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpZCA9IGdldE5hbWUocG9kKTtcbiAgICAgICAgaWYgKCFpZCkge1xuICAgICAgICAgIGxvZy53YXJuKFwiTm8gSUQgZm9yIHBvZCBcIiArIGFuZ3VsYXIudG9Kc29uKHBvZCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIEt1YmVybmV0ZXNQb2RzLmRlbGV0ZSh7XG4gICAgICAgICAgICBpZDogaWRcbiAgICAgICAgICB9LCB1bmRlZmluZWQsICgpID0+IHtcbiAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkRlbGV0ZWQgcG9kOiBcIiwgaWQpO1xuICAgICAgICAgICAgZGVsZXRlUG9kcyhwb2RzLCBwb2RzLnNoaWZ0KCksIG9uQ29tcGxldGVkRm4pO1xuICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgbG9nLmRlYnVnKFwiRXJyb3IgZGVsZXRpbmcgcG9kOiBcIiwgZXJyb3IpO1xuICAgICAgICAgICAgZGVsZXRlUG9kcyhwb2RzLCBwb2RzLnNoaWZ0KCksIG9uQ29tcGxldGVkRm4pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBzZXJ2aWNlcyA9IFtdLmNvbmNhdChhcHAuc2VydmljZXMpO1xuICAgICAgZGVsZXRlU2VydmljZXMoc2VydmljZXMsIHNlcnZpY2VzLnNoaWZ0KCksICgpID0+IHtcblxuICAgICAgICB2YXIgcmVwbGljYXRpb25Db250cm9sbGVycyA9IFtdLmNvbmNhdChhcHAucmVwbGljYXRpb25Db250cm9sbGVycyk7XG4gICAgICAgIGRlbGV0ZVJlcGxpY2F0aW9uQ29udHJvbGxlcnMocmVwbGljYXRpb25Db250cm9sbGVycywgcmVwbGljYXRpb25Db250cm9sbGVycy5zaGlmdCgpLCAoKSA9PiB7XG5cbiAgICAgICAgICB2YXIgcG9kcyA9IFtdLmNvbmNhdChhcHAucG9kcyk7XG4gICAgICAgICAgZGVsZXRlUG9kcyhwb2RzLCBwb2RzLnNoaWZ0KCksIG9uQ29tcGxldGVGbik7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgJHNjb3BlLmRlbGV0ZVNpbmdsZUFwcCA9IChhcHApID0+IHtcbiAgICAgICRzY29wZS5kZWxldGVQcm9tcHQoW2FwcF0pO1xuICAgIH1cblxuICAgICRzY29wZS5kZWxldGVQcm9tcHQgPSAoc2VsZWN0ZWQpID0+IHtcbiAgICAgIGlmIChhbmd1bGFyLmlzU3RyaW5nKHNlbGVjdGVkKSkge1xuICAgICAgICBzZWxlY3RlZCA9IFt7XG4gICAgICAgICAgaWQ6IHNlbGVjdGVkXG4gICAgICAgIH1dO1xuICAgICAgfVxuICAgICAgVUkubXVsdGlJdGVtQ29uZmlybUFjdGlvbkRpYWxvZyg8VUkuTXVsdGlJdGVtQ29uZmlybUFjdGlvbk9wdGlvbnM+e1xuICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgaW5kZXg6ICckbmFtZScsXG4gICAgICAgIG9uQ2xvc2U6IChyZXN1bHQ6Ym9vbGVhbikgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBuZXh0KSB7XG4gICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGlkID0gbmV4dC5uYW1lO1xuICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcImRlbGV0aW5nOiBcIiwgaWQpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZUFwcChuZXh0LCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICBsb2cuZGVidWcoXCJkZWxldGVkOiBcIiwgaWQpO1xuICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlOiAnRGVsZXRlIEFwcHM/JyxcbiAgICAgICAgYWN0aW9uOiAnVGhlIGZvbGxvd2luZyBBcHBzIHdpbGwgYmUgZGVsZXRlZDonLFxuICAgICAgICBva1RleHQ6ICdEZWxldGUnLFxuICAgICAgICBva0NsYXNzOiAnYnRuLWRhbmdlcicsXG4gICAgICAgIGN1c3RvbTogXCJUaGlzIG9wZXJhdGlvbiBpcyBwZXJtYW5lbnQgb25jZSBjb21wbGV0ZWQhXCIsXG4gICAgICAgIGN1c3RvbUNsYXNzOiBcImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIlxuICAgICAgfSkub3BlbigpO1xuICAgIH07XG5cbiAgICAkc2NvcGUuYXBwU2VsZWN0b3IgPSB7XG4gICAgICBmaWx0ZXJUZXh0OiBcIlwiLFxuICAgICAgZm9sZGVyczogW10sXG4gICAgICBzZWxlY3RlZEFwcHM6IFtdLFxuXG4gICAgICBpc09wZW46IChmb2xkZXIpID0+IHtcbiAgICAgICAgaWYgKCRzY29wZS5hcHBTZWxlY3Rvci5maWx0ZXJUZXh0ICE9PSAnJyB8fCBmb2xkZXIuZXhwYW5kZWQpIHtcbiAgICAgICAgICByZXR1cm4gXCJvcGVuZWRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gXCJjbG9zZWRcIjtcbiAgICAgIH0sXG5cbiAgICAgIGdldFNlbGVjdGVkQ2xhc3M6IChhcHApID0+IHtcbiAgICAgICAgaWYgKGFwcC5hYnN0cmFjdCkge1xuICAgICAgICAgIHJldHVybiBcImFic3RyYWN0XCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFwcC5zZWxlY3RlZCkge1xuICAgICAgICAgIHJldHVybiBcInNlbGVjdGVkXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9LFxuXG4gICAgICBzaG93QXBwOiAoYXBwKSA9PiB7XG4gICAgICAgIHJldHVybiBhcHBNYXRjaGVzKGFwcCkgJiYgIWFwcFJ1bm5pbmcoYXBwKTtcbiAgICAgIH0sXG5cbiAgICAgIHNob3dGb2xkZXI6IChmb2xkZXIpID0+IHtcbiAgICAgICAgcmV0dXJuICEkc2NvcGUuYXBwU2VsZWN0b3IuZmlsdGVyVGV4dCB8fCBmb2xkZXIuYXBwcy5zb21lKChhcHApID0+IGFwcE1hdGNoZXMoYXBwKSAmJiAhYXBwUnVubmluZyhhcHApKTtcbiAgICAgIH0sXG5cbiAgICAgIGNsZWFyU2VsZWN0ZWQ6ICgpID0+IHtcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKCRzY29wZS5tb2RlbC5hcHBGb2xkZXJzLCAoZm9sZGVyKSA9PiB7XG4gICAgICAgICAgYW5ndWxhci5mb3JFYWNoKGZvbGRlci5hcHBzLCAoYXBwKSA9PiB7XG4gICAgICAgICAgICBhcHAuc2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgICRzY29wZS5hcHBTZWxlY3Rvci5zZWxlY3RlZEFwcHMgPSBbXTtcbiAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgIH0sXG5cbiAgICAgIHVwZGF0ZVNlbGVjdGVkOiAoKSA9PiB7XG4gICAgICAgIC8vIGxldHMgdXBkYXRlIHRoZSBzZWxlY3RlZCBhcHBzXG4gICAgICAgIHZhciBzZWxlY3RlZEFwcHMgPSBbXTtcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKCRzY29wZS5tb2RlbC5hcHBGb2xkZXJzLCAoZm9sZGVyKSA9PiB7XG4gICAgICAgICAgdmFyIGFwcHMgPSBmb2xkZXIuYXBwcy5maWx0ZXIoKGFwcCkgPT4gYXBwLnNlbGVjdGVkKTtcbiAgICAgICAgICBpZiAoYXBwcykge1xuICAgICAgICAgICAgc2VsZWN0ZWRBcHBzID0gc2VsZWN0ZWRBcHBzLmNvbmNhdChhcHBzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAkc2NvcGUuYXBwU2VsZWN0b3Iuc2VsZWN0ZWRBcHBzID0gXy5zb3J0Qnkoc2VsZWN0ZWRBcHBzLCBcIm5hbWVcIik7XG4gICAgICB9LFxuXG4gICAgICBzZWxlY3Q6IChhcHAsIGZsYWcpID0+IHtcbiAgICAgICAgYXBwLnNlbGVjdGVkID0gZmxhZztcbiAgICAgICAgJHNjb3BlLmFwcFNlbGVjdG9yLnVwZGF0ZVNlbGVjdGVkKCk7XG4gICAgICB9LFxuXG4gICAgICBoYXNTZWxlY3Rpb246ICgpID0+IHtcbiAgICAgICAgcmV0dXJuICRzY29wZS5tb2RlbC5hcHBGb2xkZXJzLmFueSgoZm9sZGVyKSA9PiBmb2xkZXIuYXBwcy5hbnkoKGFwcCkgPT4gYXBwLnNlbGVjdGVkKSk7XG4gICAgICB9LFxuXG5cbiAgICAgIHJ1blNlbGVjdGVkQXBwczogKCkgPT4ge1xuICAgICAgICAvLyBsZXRzIHJ1biBhbGwgdGhlIHNlbGVjdGVkIGFwcHNcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKCRzY29wZS5hcHBTZWxlY3Rvci5zZWxlY3RlZEFwcHMsIChhcHApID0+IHtcbiAgICAgICAgICB2YXIgbmFtZSA9IGFwcC5uYW1lO1xuICAgICAgICAgIHZhciBtZXRhZGF0YVBhdGggPSBhcHAubWV0YWRhdGFQYXRoO1xuICAgICAgICAgIGlmIChtZXRhZGF0YVBhdGgpIHtcbiAgICAgICAgICAgIC8vIGxldHMgbG9hZCB0aGUganNvbi95YW1sXG4gICAgICAgICAgICAvL3ZhciB1cmwgPSBnaXRQYXRoVG9VcmwoV2lraS5naXRSZWxhdGl2ZVVSTChicmFuY2gsIG1ldGFkYXRhUGF0aCkpO1xuICAgICAgICAgICAgdmFyIHVybCA9IGdpdFBhdGhUb1VybChtZXRhZGF0YVBhdGgsIGJyYW5jaCk7XG4gICAgICAgICAgICBpZiAodXJsKSB7XG4gICAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBsZXRzIGNvbnZlcnQgdGhlIGpzb24gb2JqZWN0IHN0cnVjdHVyZSBpbnRvIGEgc3RyaW5nXG4gICAgICAgICAgICAgICAgICAgIHZhciBqc29uID0gYW5ndWxhci50b0pzb24oZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmbiA9ICgpID0+IHt9O1xuICAgICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLnJ1bkFwcCgkbG9jYXRpb24sICRzY29wZSwgJGh0dHAsIEt1YmVybmV0ZXNBcGlVUkwsIGpzb24sIG5hbWUsIGZuLCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgICAgJHNjb3BlLnN1bW1hcnlIdG1sID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gbGV0cyBnbyBiYWNrIHRvIHRoZSBhcHBzIHZpZXdcbiAgICAgICAgJHNjb3BlLmFwcFNlbGVjdG9yLmNsZWFyU2VsZWN0ZWQoKTtcbiAgICAgICAgJHNjb3BlLmFwcFNlbGVjdG9yU2hvdyA9IGZhbHNlO1xuICAgICAgfVxuICAgIH07XG5cbiAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBfbW9kdWxlLmRpcmVjdGl2ZShcImhhd3Rpb0JyZWFkY3J1bWJzXCIsIFsnSGF3dGlvQnJlYWRjcnVtYnMnLCAoSGF3dGlvQnJlYWRjcnVtYnMpID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgLypcbiAgICAgIHRlbXBsYXRlVXJsOiBLdWJlcm5ldGVzLnRlbXBsYXRlUGF0aCArICdicmVhZGNydW1icy5odG1sJ1xuICAgICAgKi9cbiAgICAgIGxpbms6IChzY29wZSwgZWxlbWVudCwgYXR0cnMpID0+IHtcbiAgICAgICAgSGF3dGlvQnJlYWRjcnVtYnMuYXBwbHkoc2NvcGUuJGV2YWwoJ2JyZWFkY3J1bWJDb25maWcnKSk7XG4gICAgICB9XG4gICAgfTtcbiAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIEJ1aWxkQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJCdWlsZENvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJLdWJlcm5ldGVzU2NoZW1hXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG4gICAgICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICAgICAkc2NvcGUuY29uZmlnID0gS3ViZXJuZXRlc1NjaGVtYS5kZWZpbml0aW9ucy5vc19idWlsZF9CdWlsZDtcblxuICAgICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gICAgICAgICRzY29wZS5icmVhZGNydW1iQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RCcmVhZGNydW1icygkc2NvcGUuaWQpO1xuICAgICAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RTdWJOYXZCYXJzKCRzY29wZS5pZCwgbnVsbCwgJHNjb3BlKTtcblxuICAgICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdXBkYXRlRGF0YSgpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgICAgJHNjb3BlLml0ZW0gPSBudWxsO1xuICAgICAgICAgIGlmICgkc2NvcGUuaWQpIHtcbiAgICAgICAgICAgIHZhciB1cmwgPSBidWlsZFJlc3RVcmwoJHNjb3BlLmlkKTtcbiAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUuZW50aXR5ID0gZW5yaWNoQnVpbGQoZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRzY29wZS5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgICB9KS5cbiAgICAgICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRzY29wZS5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIGV4cG9ydCB2YXIgQnVpbGRDb25maWdDb250cm9sbGVyID0gY29udHJvbGxlcihcIkJ1aWxkQ29uZmlnQ29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIkt1YmVybmV0ZXNTY2hlbWFcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6S3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNTY2hlbWEsXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAgICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICAgICAkc2NvcGUuaWQgPSAkcm91dGVQYXJhbXNbXCJpZFwiXTtcbiAgICAgICAgJHNjb3BlLnNjaGVtYSA9IEt1YmVybmV0ZXNTY2hlbWE7XG4gICAgICAgICRzY29wZS5jb25maWcgPSBLdWJlcm5ldGVzU2NoZW1hLmRlZmluaXRpb25zLm9zX2J1aWxkX0J1aWxkQ29uZmlnO1xuXG4gICAgICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcbiAgICAgICAgJHNjb3BlLmJyZWFkY3J1bWJDb25maWcgPSBEZXZlbG9wZXIuY3JlYXRlUHJvamVjdEJyZWFkY3J1bWJzKCRzY29wZS5pZCk7XG4gICAgICAgICRzY29wZS5zdWJUYWJDb25maWcgPSBEZXZlbG9wZXIuY3JlYXRlUHJvamVjdFN1Yk5hdkJhcnMoJHNjb3BlLmlkKTtcblxuICAgICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdXBkYXRlRGF0YSgpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgICAgJHNjb3BlLml0ZW0gPSBudWxsO1xuICAgICAgICAgIGlmICgkc2NvcGUuaWQpIHtcbiAgICAgICAgICAgIHZhciB1cmwgPSBidWlsZENvbmZpZ1Jlc3RVcmwoJHNjb3BlLmlkKTtcbiAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUuZW50aXR5ID0gZGF0YTtcbiAgICAgICAgICAgICAgICAgIHZhciBzb3J0ZWRCdWlsZHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgZW5yaWNoQnVpbGRDb25maWcoZGF0YSwgc29ydGVkQnVpbGRzKTtcbiAgICAgICAgICAgICAgICAgICRzY29wZS5tb2RlbC5zZXRQcm9qZWN0KCRzY29wZS5lbnRpdHkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgICAgfSkuXG4gICAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIEJ1aWxkQ29uZmlnRWRpdENvbnRyb2xsZXIgPSBfbW9kdWxlLmNvbnRyb2xsZXIoXCJLdWJlcm5ldGVzLkJ1aWxkQ29uZmlnRWRpdENvbnRyb2xsZXJcIiwgKCRzY29wZSwgJGVsZW1lbnQsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSwgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwsIEs4U0NsaWVudEZhY3RvcnksIFNjaGVtYVJlZ2lzdHJ5Okhhd3Rpb0Zvcm1zLlNjaGVtYVJlZ2lzdHJ5KSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wicHJvamVjdFwiXSB8fCAkcm91dGVQYXJhbXNbXCJpZFwiXTtcbiAgICAgICAgJHNjb3BlLnNjaGVtYSA9IEt1YmVybmV0ZXNTY2hlbWE7XG5cbiAgICAgICAgdmFyIG1vZGUgPSAkc2NvcGUuJGV2YWwoJ21vZGUnKSB8fCAnZWRpdCc7XG5cbiAgICAgICAgbG9nLmRlYnVnKFwiTW9kZTogXCIsIG1vZGUpO1xuXG5cbiAgICAgICAgdmFyIHNwZWNDb25maWcgPSBTY2hlbWFSZWdpc3RyeS5nZXRTY2hlbWEoJ2lvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZENvbmZpZ1NwZWMnKTtcbiAgICAgICAgdmFyIGdpdEJ1aWxkU291cmNlID0gU2NoZW1hUmVnaXN0cnkuZ2V0U2NoZW1hKCdpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuR2l0QnVpbGRTb3VyY2UnKTtcbiAgICAgICAgdmFyIGJ1aWxkU291cmNlID0gU2NoZW1hUmVnaXN0cnkuZ2V0U2NoZW1hKCdpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTb3VyY2UnKTtcbiAgICAgICAgdmFyIGJ1aWxkT3V0cHV0ID0gU2NoZW1hUmVnaXN0cnkuZ2V0U2NoZW1hKCdpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRPdXRwdXQnKTtcbiAgICAgICAgdmFyIHJlc291cmNlcyA9IFNjaGVtYVJlZ2lzdHJ5LmdldFNjaGVtYSgnaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXNvdXJjZVJlcXVpcmVtZW50cycpO1xuICAgICAgICB2YXIgcmV2aXNpb24gPSBTY2hlbWFSZWdpc3RyeS5nZXRTY2hlbWEoJ2lvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Tb3VyY2VSZXZpc2lvbicpO1xuICAgICAgICB2YXIgc3RyYXRlZ3kgPSBTY2hlbWFSZWdpc3RyeS5nZXRTY2hlbWEoJ2lvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZFN0cmF0ZWd5Jyk7XG4gICAgICAgIHZhciBjdXN0b21TdHJhdGVneSA9IFNjaGVtYVJlZ2lzdHJ5LmdldFNjaGVtYSgnaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkN1c3RvbUJ1aWxkU3RyYXRlZ3knKTtcbiAgICAgICAgdmFyIGJ1aWxkVHJpZ2dlclBvbGljeSA9IFNjaGVtYVJlZ2lzdHJ5LmdldFNjaGVtYSgnaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkVHJpZ2dlclBvbGljeScpO1xuXG4gICAgICAgIHZhciBnZXRTZWNyZXRzID0gKCkgPT4ge1xuICAgICAgICAgIHJldHVybiAkc2NvcGUuc2VjcmV0cztcbiAgICAgICAgfTtcblxuXG4gICAgICAgIHZhciBzZWNyZXRTY2hlbWFUeXBlID0gXCJmYWJyaWM4X1NlY3JldFJlZmVyZW5jZVwiO1xuICAgICAgICB2YXIgc2VjcmV0U2NoZW1hUmVmID0gXCIjL2RlZmluaXRpb25zL1wiICsgc2VjcmV0U2NoZW1hVHlwZTtcbiAgICAgICAgdmFyIHNlY3JldFNjaGVtYUphdmFUeXBlID0gXCJpby5mYWJyaWM4LmNvbnNvbGUuU2VjcmV0UmVmZXJlbmNlXCI7XG5cbiAgICAgICAgdmFyIHNlY3JldE5hbWVFbGVtZW50ID0gPEhhd3Rpb0Zvcm1zLkZvcm1FbGVtZW50PiB7XG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgXCJlbnVtXCI6IGdldFNlY3JldHMsXG4gICAgICAgICAgcmVxdWlyZWQ6IHRydWVcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgc2VjcmV0U2NoZW1hOiBIYXd0aW9Gb3Jtcy5Gb3JtQ29uZmlndXJhdGlvbiA9IDxhbnk+IHtcbiAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICBcIm5hbWVcIjogc2VjcmV0TmFtZUVsZW1lbnRcbiAgICAgICAgICB9LFxuICAgICAgICAgIGphdmFUeXBlOiBzZWNyZXRTY2hlbWFKYXZhVHlwZVxuICAgICAgICB9O1xuICAgICAgICBTY2hlbWFSZWdpc3RyeS5hZGRTY2hlbWEoc2VjcmV0U2NoZW1hVHlwZSwgc2VjcmV0U2NoZW1hKTtcblxuICAgICAgICAvLyBsZXRzIHN3aXRjaCB0byB0aGUgbmV3IHNlY3JldHMgdHlwZXM6XG4gICAgICAgIHZhciBzb3VyY2VTZWNyZXRQcm9wZXJ0eSA9IENvcmUucGF0aEdldChidWlsZFNvdXJjZSwgW1wicHJvcGVydGllc1wiLCBcInNvdXJjZVNlY3JldFwiXSk7XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChbXG4gICAgICAgICAgQ29yZS5wYXRoR2V0KGN1c3RvbVN0cmF0ZWd5LCBbXCJwcm9wZXJ0aWVzXCIsIFwicHVsbFNlY3JldFwiXSksXG4gICAgICAgICAgc291cmNlU2VjcmV0UHJvcGVydHksXG4gICAgICAgIF0sIChzY2hlbWFUeXBlKSA9PiB7XG4gICAgICAgICAgaWYgKHNjaGVtYVR5cGUpIHtcbiAgICAgICAgICAgIHNjaGVtYVR5cGVbXCJ0eXBlXCJdID0gc2VjcmV0U2NoZW1hVHlwZTtcbiAgICAgICAgICAgIHNjaGVtYVR5cGVbXCIkcmVmXCJdID0gc2VjcmV0U2NoZW1hUmVmO1xuICAgICAgICAgICAgc2NoZW1hVHlwZVtcImphdmFUeXBlXCJdID0gc2VjcmV0U2NoZW1hSmF2YVR5cGU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBsZXRzIHRyeSBtYWtlIHRoZSBidWlsZFNvdXJjZSdzIHNvdXJjZVNlY3JldCBtYW5kYXRvcnlcbiAgICAgICAgLy9zY2hlbWFTZXRSZXF1aXJlZChjdXN0b21TdHJhdGVneSwgJ3B1bGxTZWNyZXQnKTtcbiAgICAgICAgc2NoZW1hU2V0UmVxdWlyZWQoYnVpbGRTb3VyY2UsICdzb3VyY2VTZWNyZXQnKTtcbiAgICAgICAgaWYgKHNvdXJjZVNlY3JldFByb3BlcnR5KSB7XG4gICAgICAgICAgQ29yZS5wYXRoU2V0KHNvdXJjZVNlY3JldFByb3BlcnR5LCBbJ3Byb3BlcnRpZXMnLCAncmVxdWlyZWQnXSwgdHJ1ZSk7XG4gICAgICAgICAgQ29yZS5wYXRoU2V0KHNvdXJjZVNlY3JldFByb3BlcnR5LCBbJ3Byb3BlcnRpZXMnLCAnaW5wdXQtYXR0cmlidXRlcycsICdyZXF1aXJlZCddLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgICRzY29wZS5jdXN0b21TdHJhdGVneSA9IGN1c3RvbVN0cmF0ZWd5O1xuICAgICAgICAkc2NvcGUuYnVpbGRTb3VyY2UgPSBidWlsZFNvdXJjZTtcblxuICAgICAgICAkc2NvcGUuc2VjcmV0cyA9IFtdO1xuXG4gICAgICAgIC8vICRzY29wZS5jb25maWcgPSBLdWJlcm5ldGVzU2NoZW1hLmRlZmluaXRpb25zLm9zX2J1aWxkX0J1aWxkQ29uZmlnO1xuICAgICAgICAvLyRzY29wZS5zcGVjQ29uZmlnID0gS3ViZXJuZXRlc1NjaGVtYS5kZWZpbml0aW9ucy5vc19idWlsZF9CdWlsZENvbmZpZ1NwZWM7XG4gICAgICAgIC8vXG4gICAgICAgIHNwZWNDb25maWcuc3R5bGUgPSBIYXd0aW9Gb3Jtcy5Gb3JtU3R5bGUuU1RBTkRBUkQ7XG4gICAgICAgIHNwZWNDb25maWcucHJvcGVydGllc1sndHJpZ2dlcnMnXVsnbGFiZWwtYXR0cmlidXRlcyddID0ge1xuICAgICAgICAgIHN0eWxlOiAnZGlzcGxheTogbm9uZTsnXG4gICAgICAgIH07XG5cbiAgICAgICAgZ2l0QnVpbGRTb3VyY2UuY29udHJvbHMgPSBbJ3VyaScsICdyZWYnLCAnKiddO1xuICAgICAgICBidWlsZFNvdXJjZS5wcm9wZXJ0aWVzWyd0eXBlJ10udHlwZSA9ICdoaWRkZW4nO1xuICAgICAgICBidWlsZFNvdXJjZS5wcm9wZXJ0aWVzWyd0eXBlJ11bJ2RlZmF1bHQnXSA9ICdHaXQnO1xuICAgICAgICBidWlsZFNvdXJjZS5jb250cm9scyA9IFsnZ2l0JywgJ2NvbnRleHREaXInLCAnc291cmNlU2VjcmV0JywgJyonXTtcblxuICAgICAgICBnaXRCdWlsZFNvdXJjZVsnaGlkZUxlZ2VuZCddID0gdHJ1ZTtcbiAgICAgICAgYnVpbGRTb3VyY2VbJ2hpZGVMZWdlbmQnXSA9IHRydWU7XG4gICAgICAgIGJ1aWxkT3V0cHV0WydoaWRlTGVnZW5kJ10gPSB0cnVlO1xuICAgICAgICByZXNvdXJjZXNbJ2hpZGVMZWdlbmQnXSA9IHRydWU7XG4gICAgICAgIHJldmlzaW9uWydoaWRlTGVnZW5kJ10gPSB0cnVlO1xuICAgICAgICBzdHJhdGVneVsnaGlkZUxlZ2VuZCddID0gdHJ1ZTtcblxuICAgICAgICBzdHJhdGVneS5jb250cm9scyA9IFsndHlwZScsICcqJ107XG4gICAgICAgIHN0cmF0ZWd5LnByb3BlcnRpZXNbJ3R5cGUnXSA9IHtcbiAgICAgICAgICB0eXBlOiAndGV4dCcsXG4gICAgICAgICAgZW51bTogW3tcbiAgICAgICAgICAgICd2YWx1ZSc6ICdDdXN0b20nLFxuICAgICAgICAgICAgJ2xhYmVsJzogJ0N1c3RvbSdcbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAndmFsdWUnOiAnRG9ja2VyJyxcbiAgICAgICAgICAgICdsYWJlbCc6ICdEb2NrZXInXG4gICAgICAgICAgfSwge1xuICAgICAgICAgICAgJ3ZhbHVlJzogJ1NvdXJjZScsXG4gICAgICAgICAgICAnbGFiZWwnOiAnU291cmNlJ1xuICAgICAgICAgIH1dXG4gICAgICAgIH07XG4gICAgICAgIGN1c3RvbVN0cmF0ZWd5Wydjb250cm9sLWdyb3VwLWF0dHJpYnV0ZXMnXSA9IHtcbiAgICAgICAgICAnbmctc2hvdyc6IFwiZW50aXR5LnR5cGUgPT0gJ0N1c3RvbSdcIlxuICAgICAgICB9O1xuICAgICAgICBzdHJhdGVneS5wcm9wZXJ0aWVzWydkb2NrZXJTdHJhdGVneSddWydjb250cm9sLWdyb3VwLWF0dHJpYnV0ZXMnXSA9IHtcbiAgICAgICAgICAnbmctc2hvdyc6IFwiZW50aXR5LnR5cGUgPT0gJ0RvY2tlcidcIlxuICAgICAgICB9O1xuICAgICAgICBzdHJhdGVneS5wcm9wZXJ0aWVzWydzb3VyY2VTdHJhdGVneSddWydjb250cm9sLWdyb3VwLWF0dHJpYnV0ZXMnXSA9IHtcbiAgICAgICAgICAnbmctc2hvdyc6IFwiZW50aXR5LnR5cGUgPT0gJ1NvdXJjZSdcIlxuICAgICAgICB9O1xuXG4gICAgICAgIGJ1aWxkVHJpZ2dlclBvbGljeS5jb250cm9scyA9IFsndHlwZScsICcqJ107XG4gICAgICAgIGJ1aWxkVHJpZ2dlclBvbGljeS5wcm9wZXJ0aWVzWyd0eXBlJ10gPSB7XG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgZW51bTogW3tcbiAgICAgICAgICAgICd2YWx1ZSc6ICdHaXRodWInLFxuICAgICAgICAgICAgJ2xhYmVsJzogJ0dpdGh1YidcbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAndmFsdWUnOiAnSW1hZ2VDaGFuZ2UnLFxuICAgICAgICAgICAgJ2xhYmVsJzogJ0ltYWdlIENoYW5nZSdcbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAndmFsdWUnOiAnR2VuZXJpYycsXG4gICAgICAgICAgICAnbGFiZWwnOiAnR2VuZXJpYydcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgICAgICBidWlsZFRyaWdnZXJQb2xpY3kucHJvcGVydGllc1snZ2VuZXJpYyddWydjb250cm9sLWdyb3VwLWF0dHJpYnV0ZXMnXSA9IHtcbiAgICAgICAgICAnbmctc2hvdyc6IFwiZW50aXR5LnR5cGUgPT0gJ0dlbmVyaWMnXCJcbiAgICAgICAgfTtcbiAgICAgICAgYnVpbGRUcmlnZ2VyUG9saWN5LnByb3BlcnRpZXNbJ2dpdGh1YiddWydjb250cm9sLWdyb3VwLWF0dHJpYnV0ZXMnXSA9IHtcbiAgICAgICAgICAnbmctc2hvdyc6IFwiZW50aXR5LnR5cGUgPT0gJ0dpdGh1YidcIlxuICAgICAgICB9O1xuICAgICAgICBidWlsZFRyaWdnZXJQb2xpY3kucHJvcGVydGllc1snaW1hZ2VDaGFuZ2UnXVsnY29udHJvbC1ncm91cC1hdHRyaWJ1dGVzJ10gPSB7XG4gICAgICAgICAgJ25nLXNob3cnOiBcImVudGl0eS50eXBlID09ICdJbWFnZUNoYW5nZSdcIlxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHJlLWFycmFuZ2luZyB0aGUgY29udHJvbHNcbiAgICAgICAgLy9zcGVjQ29uZmlnLmNvbnRyb2xzID0gWydzb3VyY2UnLCAnKiddO1xuICAgICAgICBcbiAgICAgICAgLy8gdGFic1xuICAgICAgICBzcGVjQ29uZmlnLnRhYnMgPSB7XG4gICAgICAgICAgXCJTb3VyY2VcIjogW1wic291cmNlXCJdLFxuICAgICAgICAgIFwiUmV2aXNpb25cIjogW1wicmV2aXNpb25cIl0sXG4gICAgICAgICAgXCJPdXRwdXRcIjogW1wib3V0cHV0XCJdLFxuICAgICAgICAgIFwiUmVzb3VyY2VzXCI6IFtcInJlc291cmNlc1wiXSxcbiAgICAgICAgICBcIlN0cmF0ZWd5XCI6IFtcInN0cmF0ZWd5XCJdLFxuICAgICAgICAgIFwiVHJpZ2dlcnNcIjogW1widHJpZ2dlcnNcIl0sXG4gICAgICAgICAgXCJTZXJ2aWNlIEFjY291bnRcIjogW1wic2VydmljZUFjY291bnRcIl1cbiAgICAgICAgfTtcbiAgICAgICAgLypcbiAgICAgICAgICogd2l6YXJkLCBuZWVkcyBhbiAnb25GaW5pc2gnIGZ1bmN0aW9uIGluIHRoZSBzY29wZVxuICAgICAgICBzcGVjQ29uZmlnLndpemFyZCA9IDxhbnk+e1xuICAgICAgICAgIHBhZ2VzOiB7XG4gICAgICAgICAgICBTb3VyY2U6IHtcbiAgICAgICAgICAgICAgY29udHJvbHM6IFtcInNvdXJjZVwiXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFJldmlzaW9uOiB7XG4gICAgICAgICAgICAgIGNvbnRyb2xzOiBbXCJyZXZpc2lvblwiXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIE91dHB1dDoge1xuICAgICAgICAgICAgICBjb250cm9sczogW1wib3V0cHV0XCJdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgICAgICAgIGNvbnRyb2xzOiBbXCJyZXNvdXJjZXNcIl1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBTdHJhdGVneToge1xuICAgICAgICAgICAgICBjb250cm9sczogW1wic3RyYXRlZ3lcIl1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBUcmlnZ2Vyczoge1xuICAgICAgICAgICAgICBjb250cm9sczogW1widHJpZ2dlcnNcIl1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcIlNlcnZpY2UgQWNjb3VudFwiOiB7XG4gICAgICAgICAgICAgIGNvbnRyb2xzOiBbXCJzZXJ2aWNlQWNjb3VudFwiXVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgKi9cblxuICAgICAgICAkc2NvcGUuZW50aXR5ID0ge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiBcInYxXCIsXG4gICAgICAgICAgXCJraW5kXCI6IFwiQnVpbGRDb25maWdcIixcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwibmFtZVwiOiBcIlwiLFxuICAgICAgICAgICAgXCJsYWJlbHNcIjoge1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwic291cmNlXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwiR2l0XCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcInN0cmF0ZWd5XCI6IHtcbiAgICAgICAgICAgICAgICBcInR5cGVcIjogXCJDdXN0b21cIixcbiAgICAgICAgICAgICAgICBcImN1c3RvbVN0cmF0ZWd5XCI6IHtcbiAgICAgICAgICAgICAgICAgICAgXCJmcm9tXCI6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwia2luZFwiOiBcIkRvY2tlckltYWdlXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcIm5hbWVcIjogXCJmYWJyaWM4L29wZW5zaGlmdC1zMmktamVua2lucy10cmlnZ2VyXCJcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgXCJlbnZcIjogW1xuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibmFtZVwiOiBcIkJBU0VfVVJJXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ2YWx1ZVwiOiBqZW5raW5zVXJsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibmFtZVwiOiBcIkpPQl9OQU1FXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ2YWx1ZVwiOiBqb2JOYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS4kd2F0Y2goJ2VudGl0eS5zcGVjLnNvdXJjZS5naXQudXJpJywgKHZhbCkgPT4ge1xuICAgICAgICAgIGlmICghdmFsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBsYXN0Qml0ID0gdmFsLm1hdGNoKC9bXlxcL10rJC8pWzBdO1xuICAgICAgICAgIGlmIChsYXN0Qml0KSB7XG4gICAgICAgICAgICB2YXIgbmFtZSA9IGxhc3RCaXQucmVwbGFjZSgvXFwuZ2l0JC8sICcnKTtcbiAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIm5hbWU6IFwiLCBuYW1lKTtcbiAgICAgICAgICAgIGlmICghQ29yZS5pc0JsYW5rKG5hbWUpIFxuICAgICAgICAgICAgICAmJiBDb3JlLmlzQmxhbmsoQ29yZS5wYXRoR2V0KCRzY29wZS5lbnRpdHksIFsnbWV0YWRhdGEnLCAnbmFtZSddKSkpIHtcbiAgICAgICAgICAgICAgQ29yZS5wYXRoU2V0KCRzY29wZS5lbnRpdHksIFsnbWV0YWRhdGEnLCAnbmFtZSddLCBuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcbiAgICAgICAgJHNjb3BlLmJyZWFkY3J1bWJDb25maWcgPSBEZXZlbG9wZXIuY3JlYXRlUHJvamVjdFNldHRpbmdzQnJlYWRjcnVtYnMoJHNjb3BlLnByb2plY3RJZCk7XG4gICAgICAgICRzY29wZS5zdWJUYWJDb25maWcgPSBEZXZlbG9wZXIuY3JlYXRlUHJvamVjdFN1Yk5hdkJhcnMoJHNjb3BlLnByb2plY3RJZCk7XG4gICAgICAgICRzY29wZS50YWJzID0gRGV2ZWxvcGVyLmNyZWF0ZVByb2plY3RTZXR0aW5nc1N1Yk5hdkJhcnMoJHNjb3BlLnByb2plY3RJZCk7XG5cbiAgICAgICAgd2F0Y2goJHNjb3BlLCAkZWxlbWVudCwgXCJzZWNyZXRzXCIsICRzY29wZS5uYW1lc3BhY2UsIG9uU2VjcmV0cyk7XG5cblxuICAgICAgICAkc2NvcGUuYnVpbGRDb25maWdDbGllbnQgPSBLOFNDbGllbnRGYWN0b3J5LmNyZWF0ZShcImJ1aWxkY29uZmlnc1wiLCAkc2NvcGUubmFtZXNwYWNlKTtcblxuICAgICAgICAkZWxlbWVudC5vbignJGRlc3Ryb3knLCAoKSA9PiB7XG4gICAgICAgICAgJHNjb3BlLiRkZXN0cm95KCk7XG4gICAgICAgIH0pO1xuICAgICAgICAkc2NvcGUuJG9uKCckZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgICBLOFNDbGllbnRGYWN0b3J5LmRlc3Ryb3koJHNjb3BlLmJ1aWxkQ29uZmlnQ2xpZW50KTtcbiAgICAgICAgfSk7XG5cbi8qXG4gICAgICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuKi9cbiAgICAgICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHNjb3BlLnNhdmUgPSAoKSA9PiB7XG4gICAgICAgICAgbG9nLmluZm8oXCJTYXZpbmchXCIpO1xuXG5cbiAgICAgICAgICB2YXIgZW50aXR5ID0gJHNjb3BlLmVudGl0eTtcbiAgICAgICAgICB2YXIgc3BlYyA9IChlbnRpdHkgfHwge30pLnNwZWMgfHwge307XG5cbiAgICAgICAgICAvLyBUT0RPIHVwZGF0ZSB0aGUgamVua2lucyBqb2IgbmFtZSFcblxuICAgICAgICAgIC8vIGxldHMgZGVsZXRlIGxvdHMgb2YgY3J1ZnRcbiAgICAgICAgICB2YXIgc3RyYXRlZ3kgPSBzcGVjLnN0cmF0ZWd5IHx8IHt9O1xuICAgICAgICAgIGRlbGV0ZSBzdHJhdGVneVtcImRvY2tlclN0cmF0ZWd5XCJdO1xuICAgICAgICAgIGRlbGV0ZSBzdHJhdGVneVtcInNvdXJjZVN0cmF0ZWd5XCJdO1xuXG4gICAgICAgICAgZGVsZXRlIHNwZWNbXCJyZXZpc2lvblwiXTtcbiAgICAgICAgICBkZWxldGUgc3BlY1tcIm91dHB1dFwiXTtcbiAgICAgICAgICBkZWxldGUgc3BlY1tcInJlc291cmNlc1wiXTtcblxuICAgICAgICAgIHZhciBzdHJhdGVneVB1bGxTZWNyZXROYW1lID0gQ29yZS5wYXRoR2V0KHNwZWMsIFtcInN0cmF0ZWd5XCIsIFwiY3VzdG9tU3RyYXRlZ3lcIiwgXCJwdWxsU2VjcmV0XCIsIFwibmFtZVwiXSk7XG4gICAgICAgICAgdmFyIHNvdXJjZVNlY3JldE5hbWUgPSBDb3JlLnBhdGhHZXQoc3BlYywgW1wic291cmNlXCIsIFwic291cmNlU2VjcmV0XCIsIFwibmFtZVwiXSk7XG4gICAgICAgICAgbG9nLmluZm8oXCJzb3VyY2VTZWNyZXROYW1lOiBcIiArIHNvdXJjZVNlY3JldE5hbWUpO1xuICAgICAgICAgIGxvZy5pbmZvKFwic3RyYXRlZ3lQdWxsU2VjcmV0TmFtZTogXCIgKyBzdHJhdGVneVB1bGxTZWNyZXROYW1lKTtcbiAgICAgICAgICBpZiAoIXN0cmF0ZWd5UHVsbFNlY3JldE5hbWUgJiYgc291cmNlU2VjcmV0TmFtZSkge1xuICAgICAgICAgICAgQ29yZS5wYXRoU2V0KHNwZWMsIFtcInN0cmF0ZWd5XCIsIFwiY3VzdG9tU3RyYXRlZ3lcIiwgXCJwdWxsU2VjcmV0XCIsIFwibmFtZVwiXSwgc291cmNlU2VjcmV0TmFtZSk7XG4gICAgICAgICAgfVxuXG4vKlxuICAgICAgICAgIC8vIFRPRE8gaGFjayB1bnRpbCB0aGUgcHV0IGRlYWxzIHdpdGggdXBkYXRlc1xuICAgICAgICAgIHZhciBtZXRhZGF0YSA9IGVudGl0eS5tZXRhZGF0YTtcbiAgICAgICAgICBpZiAobWV0YWRhdGEpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBtZXRhZGF0YVtcInJlc291cmNlVmVyc2lvblwiXTtcbiAgICAgICAgICB9XG4qL1xuXG4gICAgICAgICAgbG9nLmluZm8oYW5ndWxhci50b0pzb24oZW50aXR5LCB0cnVlKSk7XG5cbiAgICAgICAgICAkc2NvcGUuYnVpbGRDb25maWdDbGllbnQucHV0KGVudGl0eSwgKG9iaikgPT4ge1xuICAgICAgICAgICAgbG9nLmluZm8oXCJidWlsZCBjb25maWcgY3JlYXRlZCFcIik7XG5cbiAgICAgICAgICAgIHZhciBsaW5rID0gRGV2ZWxvcGVyLnByb2plY3RTZWNyZXRzTGluaygkc2NvcGUubmFtZXNwYWNlLCBnZXROYW1lKGVudGl0eSkpO1xuICAgICAgICAgICAgaWYgKGxpbmspIHtcbiAgICAgICAgICAgICAgbG9nLmluZm8oXCJOYXZpZ2F0aW5nIHRvOiBcIisgbGluayk7XG4gICAgICAgICAgICAgICRsb2NhdGlvbi5wYXRoKGxpbmspO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbG9nLndhcm4oXCJDb3VsZCBub3QgZmluZCB0aGUgZWRpdCBwaXBlbGluZSBsaW5rIVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICB9O1xuXG4gICAgICAgIHVwZGF0ZURhdGEoKTtcblxuXG4gICAgICAgIHZhciBqZW5raW5zVXJsID0gRGV2ZWxvcGVyLmplbmtpbnNMaW5rKCk7XG4gICAgICAgIHZhciBqb2JOYW1lID0gXCJcIjtcblxuICAgICAgICBmdW5jdGlvbiB1cGRhdGVEYXRhKCkge1xuICAgICAgICAgICRzY29wZS5pdGVtID0gbnVsbDtcbiAgICAgICAgICBpZiAoJHNjb3BlLmlkKSB7XG4gICAgICAgICAgICB2YXIgdXJsID0gYnVpbGRDb25maWdSZXN0VXJsKCRzY29wZS5pZCk7XG4gICAgICAgICAgICAkaHR0cC5nZXQodXJsKS5cbiAgICAgICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgJHNjb3BlLmVudGl0eSA9IGRhdGE7XG5cbiAgICAgICAgICAgICAgICAgIHZhciBidWlsZENvbmZpZyA9IGFuZ3VsYXIuY29weShkYXRhKTtcbiAgICAgICAgICAgICAgICAgIHZhciBzb3J0ZWRCdWlsZHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgS3ViZXJuZXRlcy5lbnJpY2hCdWlsZENvbmZpZyhidWlsZENvbmZpZywgc29ydGVkQnVpbGRzKTtcbiAgICAgICAgICAgICAgICAgICRzY29wZS5idWlsZENvbmZpZyA9IGJ1aWxkQ29uZmlnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkc2NvcGUuc3BlYyA9ICgkc2NvcGUuZW50aXR5IHx8IHt9KS5zcGVjIHx8IHt9O1xuICAgICAgICAgICAgICAgICRzY29wZS5mZXRjaGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIC8vIGxldHMgdXBkYXRlIHRoZSB0YWJzXG4gICAgICAgICAgICAgICAgJHNjb3BlLnN1YlRhYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0U3ViTmF2QmFycygkc2NvcGUucHJvamVjdElkLCBudWxsLCAkc2NvcGUpO1xuICAgICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAkc2NvcGUuc3BlYyA9ICRzY29wZS5lbnRpdHkuc3BlYztcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gb25TZWNyZXRzKHNlY3JldHMpIHtcbiAgICAgICAgICB2YXIgYXJyYXkgPSBbXTtcbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2goc2VjcmV0cywgKHNlY3JldCkgPT4ge1xuICAgICAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHNlY3JldCk7XG4gICAgICAgICAgICBpZiAobmFtZSkge1xuICAgICAgICAgICAgICBhcnJheS5wdXNoKHtcbiAgICAgICAgICAgICAgICBsYWJlbDogbmFtZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogbmFtZSxcbiAgICAgICAgICAgICAgICBcImF0dHJpYnV0ZXNcIjoge1xuICAgICAgICAgICAgICAgICAgXCJ0aXRsZVwiOiBuYW1lXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAkc2VjcmV0OiBzZWNyZXRcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJHNjb3BlLnNlY3JldHMgPSBfLnNvcnRCeShhcnJheSwgXCJsYWJlbFwiKTtcblxuICAgICAgICAgIHZhciBzcGVjU291cmNlU2VjcmV0TmFtZVBhdGggPSBbJ3NwZWMnLCAnc291cmNlJywgJ3NvdXJjZVNlY3JldCcsICduYW1lJ107XG4gICAgICAgICAgaWYgKCRzY29wZS5lbnRpdHkgJiYgIUNvcmUucGF0aEdldCgkc2NvcGUuZW50aXR5LCBzcGVjU291cmNlU2VjcmV0TmFtZVBhdGgpKSB7XG4gICAgICAgICAgICB2YXIgZGVmYXVsdFNlY3JldE5hbWUgPSBmaW5kRGVmYXVsdEltcG9ydFNlY3JldE5hbWUoc2VjcmV0cyk7XG4gICAgICAgICAgICBDb3JlLnBhdGhTZXQoJHNjb3BlLmVudGl0eSwgc3BlY1NvdXJjZVNlY3JldE5hbWVQYXRoLCBkZWZhdWx0U2VjcmV0TmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZmluZERlZmF1bHRJbXBvcnRTZWNyZXROYW1lKHNlY3JldHMpIHtcbiAgICAgICAgICB2YXIgYW5zd2VyID0gbnVsbDtcbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2goc2VjcmV0cywgKHNlY3JldCkgPT4ge1xuICAgICAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHNlY3JldCk7XG4gICAgICAgICAgICBpZiAoIWFuc3dlciAmJiBuYW1lICYmIG5hbWUuc3RhcnRzV2l0aChcImplbmtpbnMtbG9naW5cIikpIHtcbiAgICAgICAgICAgICAgYW5zd2VyID0gbmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAoIWFuc3dlcikge1xuICAgICAgICAgICAgYW5ndWxhci5mb3JFYWNoKHNlY3JldHMsIChzZWNyZXQpID0+IHtcbiAgICAgICAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHNlY3JldCk7XG4gICAgICAgICAgICAgIGlmICghYW5zd2VyICYmIG5hbWUgJiYgbmFtZS5zdGFydHNXaXRoKFwiamVua2lucy10b2tlblwiKSkge1xuICAgICAgICAgICAgICAgIGFuc3dlciA9IG5hbWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYW5zd2VyO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICAgICAgY2FzZSAnY3JlYXRlJzpcbiAgICAgICAgICAgIGRlbGV0ZSBzcGVjQ29uZmlnLnRhYnM7XG4gICAgICAgICAgICBfLmZvckluKGJ1aWxkU291cmNlLnByb3BlcnRpZXMsIChwcm9wZXJ0eTphbnksIG5hbWU6c3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChuYW1lICE9PSAnZ2l0Jykge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiSGlkaW5nIHByb3BlcnR5OiBcIiwgbmFtZSk7XG4gICAgICAgICAgICAgICAgcHJvcGVydHkuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBfLmZvckluKGdpdEJ1aWxkU291cmNlLnByb3BlcnRpZXMsIChwcm9wZXJ0eTphbnksIG5hbWU6c3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChuYW1lICE9PSAndXJpJykge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiSGlkaW5nIHByb3BlcnR5OiBcIiwgbmFtZSk7XG4gICAgICAgICAgICAgICAgcHJvcGVydHkuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eS5sYWJlbCA9IFwiR2l0IFVSTFwiO1xuICAgICAgICAgICAgICAgIHByb3BlcnR5WydpbnB1dC1hdHRyaWJ1dGVzJ10gPSB7XG4gICAgICAgICAgICAgICAgICAncmVxdWlyZWQnOiB0cnVlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTsgXG4gICAgICAgICAgICBfLmZvckluKHNwZWNDb25maWcucHJvcGVydGllcywgKHByb3BlcnR5OmFueSwgbmFtZTpzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgaWYgKG5hbWUgIT09ICdzb3VyY2UnKSB7XG4gICAgICAgICAgICAgICAgbG9nLmluZm8oXCJIaWRpbmcgcHJvcGVydHk6IFwiLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eS5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2VkaXQnOlxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgIH1cblxuICAgICAgICAkc2NvcGUuc3BlY0NvbmZpZyA9IHNwZWNDb25maWc7XG4gIH0pO1xuXG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIGV4cG9ydCB2YXIgQnVpbGRDb25maWdzQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJCdWlsZENvbmZpZ3NDb250cm9sbGVyXCIsIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIiRkaWFsb2dcIiwgXCIkd2luZG93XCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkbG9jYXRpb25cIiwgXCJsb2NhbFN0b3JhZ2VcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgJGRpYWxvZywgJHdpbmRvdywgJHRlbXBsYXRlQ2FjaGUsICRyb3V0ZVBhcmFtcywgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsIGxvY2FsU3RvcmFnZSwgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuXG4gICAgICAkc2NvcGUudGFibGVDb25maWcgPSB7XG4gICAgICAgIGRhdGE6ICdtb2RlbC5idWlsZGNvbmZpZ3MnLFxuICAgICAgICBzaG93U2VsZWN0aW9uQ2hlY2tib3g6IHRydWUsXG4gICAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgbXVsdGlTZWxlY3Q6IHRydWUsXG4gICAgICAgIHNlbGVjdGVkSXRlbXM6IFtdLFxuICAgICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgICAgZmlsdGVyVGV4dDogJGxvY2F0aW9uLnNlYXJjaCgpW1wicVwiXSB8fCAnJ1xuICAgICAgICB9LFxuICAgICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdtZXRhZGF0YS5uYW1lJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTmFtZScsXG4gICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImJ1aWxkQ29uZmlnTGlua1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuLypcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3NwZWMuc291cmNlLnR5cGUnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdTb3VyY2UnXG4gICAgICAgICAgfSxcbiovXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLnNvdXJjZS5naXQudXJpJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUmVwb3NpdG9yeSdcbiAgICAgICAgICB9LFxuLypcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3NwZWMuc3RyYXRlZ3kudHlwZScsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ1N0cmF0ZWd5J1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLnN0cmF0ZWd5LnN0aVN0cmF0ZWd5LmltYWdlJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnU291cmNlIEltYWdlJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLm91dHB1dC5pbWFnZVRhZycsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ091dHB1dCBJbWFnZSdcbiAgICAgICAgICB9LFxuKi9cbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJyRmYWJyaWM4Q29kZVZpZXdzJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnQ29kZScsXG4gICAgICAgICAgICB3aWR0aDogXCIqKipcIixcbiAgICAgICAgICAgIG1pbldpZHRoOiA1MDAsXG4gICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImJ1aWxkQ29uZmlnQ29kZVZpZXdzVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckZmFicmljOEJ1aWxkVmlld3MnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdCdWlsZHMnLFxuICAgICAgICAgICAgd2lkdGg6IFwiKioqXCIsXG4gICAgICAgICAgICBtaW5XaWR0aDogNTAwLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJidWlsZENvbmZpZ0J1aWxkVmlld3NUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJyRmYWJyaWM4RW52aXJvbm1lbnRWaWV3cycsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ0Vudmlyb25tZW50cycsXG4gICAgICAgICAgICB3aWR0aDogXCIqKipcIixcbiAgICAgICAgICAgIG1pbldpZHRoOiA1MDAsXG4gICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImJ1aWxkQ29uZmlnRW52aXJvbm1lbnRWaWV3c1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnJGZhYnJpYzhUZWFtVmlld3MnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdQZW9wbGUnLFxuICAgICAgICAgICAgd2lkdGg6IFwiKioqXCIsXG4gICAgICAgICAgICBtaW5XaWR0aDogNTAwLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJidWlsZENvbmZpZ1RlYW1WaWV3c1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9XG4gICAgICAgIF1cbiAgICAgIH07XG5cbiAgICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICAgLy8gVE9ET1xuICAgICAgLy8gJHNjb3BlLmlzTG9nZ2VkSW50b0dvZ3MgPSBGb3JnZS5pc0xvZ2dlZEludG9Hb2dzO1xuXG4gICAgICAkc2NvcGUuZGVsZXRlUHJvbXB0ID0gKHNlbGVjdGVkKSA9PiB7XG4gICAgICAgIFVJLm11bHRpSXRlbUNvbmZpcm1BY3Rpb25EaWFsb2coPFVJLk11bHRpSXRlbUNvbmZpcm1BY3Rpb25PcHRpb25zPntcbiAgICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgICBpbmRleDogJyRuYW1lJyxcbiAgICAgICAgICBvbkNsb3NlOiAocmVzdWx0OmJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgZnVuY3Rpb24gZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIG5leHQpIHtcbiAgICAgICAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgICAgICAgZGVsZXRlRW50aXR5KG5leHQsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICB0aXRsZTogJ0RlbGV0ZSBCdWlsZCBDb25maWdzPycsXG4gICAgICAgICAgYWN0aW9uOiAnVGhlIGZvbGxvd2luZyBCdWlsZCBDb25maWdzIHdpbGwgYmUgZGVsZXRlZDonLFxuICAgICAgICAgIG9rVGV4dDogJ0RlbGV0ZScsXG4gICAgICAgICAgb2tDbGFzczogJ2J0bi1kYW5nZXInLFxuICAgICAgICAgIGN1c3RvbTogXCJUaGlzIG9wZXJhdGlvbiBpcyBwZXJtYW5lbnQgb25jZSBjb21wbGV0ZWQhXCIsXG4gICAgICAgICAgY3VzdG9tQ2xhc3M6IFwiYWxlcnQgYWxlcnQtd2FybmluZ1wiXG4gICAgICAgIH0pLm9wZW4oKTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIGRlbGV0ZUVudGl0eShzZWxlY3Rpb24sIG5leHRDYWxsYmFjaykge1xuICAgICAgICB2YXIgbmFtZSA9IChzZWxlY3Rpb24gfHwge30pLiRuYW1lO1xuICAgICAgICBpZiAobmFtZSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQWJvdXQgdG8gZGVsZXRlIGJ1aWxkIGNvbmZpZzogXCIgKyBuYW1lKTtcbiAgICAgICAgICB2YXIgdXJsID0gYnVpbGRDb25maWdSZXN0VXJsKG5hbWUpO1xuICAgICAgICAgICRodHRwLmRlbGV0ZSh1cmwpLlxuICAgICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgbmV4dENhbGxiYWNrKCk7XG4gICAgICAgICAgICB9KS5cbiAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBkZWxldGUgYnVpbGQgY29uZmlnIG9uIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJ3YXJuaW5nOiBubyBuYW1lIGZvciBzZWxlY3Rpb246IFwiICsgYW5ndWxhci50b0pzb24oc2VsZWN0aW9uKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgIH1cblxuICAgICAgdXBkYXRlRGF0YSgpO1xuICAgIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBCdWlsZExvZ3NDb250cm9sbGVyID0gY29udHJvbGxlcihcIkJ1aWxkTG9nc0NvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJLdWJlcm5ldGVzU2NoZW1hXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG4gICAgICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICAgICAkc2NvcGUuY29uZmlnID0gS3ViZXJuZXRlc1NjaGVtYS5kZWZpbml0aW9ucy5vc19idWlsZF9CdWlsZDtcblxuICAgICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG5cbiAgICAgICAgJHNjb3BlLiRvbigna3ViZXJuZXRlc01vZGVsVXBkYXRlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB1cGRhdGVEYXRhKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgICAgICB1cGRhdGVEYXRhKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS5sb2dzVGV4dCA9IFwiTG9hZGluZyBsb2dzLi4uXCI7XG5cbiAgICAgICAgdXBkYXRlRGF0YSgpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgICAgJHNjb3BlLml0ZW0gPSBudWxsO1xuICAgICAgICAgIGlmICgkc2NvcGUuaWQpIHtcbiAgICAgICAgICAgIHZhciB1cmwgPSBidWlsZFJlc3RVcmwoJHNjb3BlLmlkKTtcbiAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUuZW50aXR5ID0gZW5yaWNoQnVpbGQoZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRzY29wZS5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgICB9KS5cbiAgICAgICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHVybCA9IGJ1aWxkTG9nc1Jlc3RVcmwoJHNjb3BlLmlkKTtcbiAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMpIHtcbiAgICAgICAgICAgICAgICAkc2NvcGUubG9nc1RleHQgPSBkYXRhO1xuICAgICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgJHNjb3BlLmxvZ3NUZXh0ID0gXCJGYWlsZWQgdG8gbG9hZCBsb2dzIGZyb206IFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgc3RhdHVzOiBcIiArIHN0YXR1cztcbiAgICAgICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgICB9KS5cbiAgICAgICAgICAgICAgY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgJHNjb3BlLmxvZ3NUZXh0ID0gXCJGYWlsZWQgdG8gbG9hZCBsb2dzOiBcIiArIGFuZ3VsYXIudG9Kc29uKGVycm9yLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBCdWlsZHNDb250cm9sbGVyID0gY29udHJvbGxlcihcIkJ1aWxkc0NvbnRyb2xsZXJcIiwgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiJGRpYWxvZ1wiLCBcIiR3aW5kb3dcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRsb2NhdGlvblwiLCBcImxvY2FsU3RvcmFnZVwiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCAkZGlhbG9nLCAkd2luZG93LCAkdGVtcGxhdGVDYWNoZSwgJHJvdXRlUGFyYW1zLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgbG9jYWxTdG9yYWdlLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgICAkc2NvcGUuYnVpbGRDb25maWdJZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuXG4gICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgfSk7XG5cbiAgICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgICAgZGF0YTogJ21vZGVsLmJ1aWxkcycsXG4gICAgICAgIHNob3dTZWxlY3Rpb25DaGVja2JveDogdHJ1ZSxcbiAgICAgICAgZW5hYmxlUm93Q2xpY2tTZWxlY3Rpb246IGZhbHNlLFxuICAgICAgICBtdWx0aVNlbGVjdDogdHJ1ZSxcbiAgICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICAgIGZpbHRlck9wdGlvbnM6IHtcbiAgICAgICAgICBmaWx0ZXJUZXh0OiAkbG9jYXRpb24uc2VhcmNoKClbXCJxXCJdIHx8ICcnXG4gICAgICAgIH0sXG4gICAgICAgIGNvbHVtbkRlZnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ21ldGFkYXRhLm5hbWUnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdOYW1lJyxcbiAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiYnVpbGRMaW5rVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckY3JlYXRpb25EYXRlJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnVGltZScsXG4gICAgICAgICAgICBkZWZhdWx0U29ydDogdHJ1ZSxcbiAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiYnVpbGRUaW1lVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzdGF0dXMnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdTdGF0dXMnLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJidWlsZFN0YXR1c1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnJGxvZ3NMaW5rJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTG9ncycsXG4gICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImJ1aWxkTG9nc1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnJHBvZExpbmsnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdCdWlsZCBQb2QnLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJidWlsZFBvZFRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuLypcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3BhcmFtZXRlcnMuc291cmNlLnR5cGUnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdTb3VyY2UnXG4gICAgICAgICAgfSxcbiovXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLnNvdXJjZS5naXQudXJpJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUmVwb3NpdG9yeScsXG4gICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImJ1aWxkUmVwb3NpdG9yeVRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnc3BlYy5zdHJhdGVneS50eXBlJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnU3RyYXRlZ3knXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3NwZWMuc3RyYXRlZ3kuc291cmNlU3RyYXRlZ3kuZnJvbS5uYW1lJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnU291cmNlIEltYWdlJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdzcGVjLm91dHB1dC50by5uYW1lJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnT3V0cHV0IEltYWdlJ1xuICAgICAgICAgIH1dXG4gICAgICB9O1xuXG4gICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gICAgICAkc2NvcGUuYnJlYWRjcnVtYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0QnJlYWRjcnVtYnMoJHNjb3BlLmJ1aWxkQ29uZmlnSWQpO1xuICAgICAgJHNjb3BlLnN1YlRhYkNvbmZpZyA9IERldmVsb3Blci5jcmVhdGVQcm9qZWN0U3ViTmF2QmFycygkc2NvcGUuYnVpbGRDb25maWdJZCwgbnVsbCwgJHNjb3BlKTtcblxuICAgICAgJHNjb3BlLiRvbigna3ViZXJuZXRlc01vZGVsVXBkYXRlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgfSk7XG5cbiAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgIGlmICgkc2NvcGUubW9kZWwpIHtcbiAgICAgICAgICB2YXIgYnVpbGRzID0gJHNjb3BlLm1vZGVsLmJ1aWxkcztcbiAgICAgICAgICB2YXIgYnVpbGRDb25maWdJZCA9ICRzY29wZS5idWlsZENvbmZpZ0lkO1xuXG4gICAgICAgICAgZW5yaWNoQnVpbGRzKGJ1aWxkcyk7XG4gICAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuXG4gICAgICAgICAgaWYgKGJ1aWxkQ29uZmlnSWQpIHtcbiAgICAgICAgICAgICRzY29wZS5idWlsZENvbmZpZyA9ICRzY29wZS5tb2RlbC5nZXRCdWlsZENvbmZpZyhidWlsZENvbmZpZ0lkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdXBkYXRlRGF0YSgpO1xuXG5cbiAgICAgIC8qXG4gICAgICAkc2NvcGUuJGtlZXBQb2xsaW5nID0gKCkgPT4ga2VlcFBvbGxpbmdNb2RlbDtcbiAgICAgICRzY29wZS5mZXRjaCA9IFBvbGxIZWxwZXJzLnNldHVwUG9sbGluZygkc2NvcGUsIChuZXh0OigpID0+IHZvaWQpID0+IHtcbiAgICAgICAgdmFyIHVybCA9IGJ1aWxkc1Jlc3RVUkwoKTtcbiAgICAgICAgJGh0dHAuZ2V0KHVybCkuXG4gICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJnb3QgZGF0YSBcIiArIGFuZ3VsYXIudG9Kc29uKGRhdGEsIHRydWUpKTtcbiAgICAgICAgICAgICAgJHNjb3BlLmJ1aWxkcyA9IGVucmljaEJ1aWxkcyhkYXRhLml0ZW1zKTtcbiAgICAgICAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAgIGlmICgkc2NvcGUubW9kZWwpIHtcbiAgICAgICAgICAgICAgICAkc2NvcGUuYnVpbGRDb25maWcgPSAkc2NvcGUubW9kZWwuZ2V0QnVpbGRDb25maWcoJHNjb3BlLmJ1aWxkQ29uZmlnSWQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgIH0pLlxuICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICBuZXh0KCk7XG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgJHNjb3BlLmZldGNoKCk7XG4gICAgICAqL1xuICAgIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgLy8gY29udHJvbGxlciBmb3IgY29ubmVjdGluZyB0byBhIHJlbW90ZSBjb250YWluZXIgdmlhIGpvbG9raWFcbiAgZXhwb3J0IHZhciBDb25uZWN0Q29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJDb25uZWN0Q29udHJvbGxlclwiLCBbXG4gICAgXCIkc2NvcGVcIiwgXCJsb2NhbFN0b3JhZ2VcIiwgXCJ1c2VyRGV0YWlsc1wiLCBcIkNvbm5lY3REaWFsb2dTZXJ2aWNlXCIsIFwiJGJyb3dzZXJcIixcbiAgICAoJHNjb3BlLCBsb2NhbFN0b3JhZ2UsIHVzZXJEZXRhaWxzLCBDb25uZWN0RGlhbG9nU2VydmljZSwgJGJyb3dzZXI6bmcuSUJyb3dzZXJTZXJ2aWNlKSA9PiB7XG5cbiAgICAgICRzY29wZS5kb0Nvbm5lY3QgPSAoZW50aXR5KSA9PiB7XG4gICAgICAgIHZhciBjb25uZWN0VXJsOmFueSA9IG5ldyBVUkkoKS5wYXRoKFVybEhlbHBlcnMuam9pbihIYXd0aW9Db3JlLmRvY3VtZW50QmFzZSgpLCAnL2phdmEvaW5kZXguaHRtbCcpKTtcbiAgICAgICAgdmFyIHJldHVyblRvID0gbmV3IFVSSSgpLnRvU3RyaW5nKCk7XG4gICAgICAgIHZhciB0aXRsZSA9IGVudGl0eS5tZXRhZGF0YS5uYW1lIHx8ICdVbnRpdGxlZCBDb250YWluZXInO1xuICAgICAgICB2YXIgdG9rZW4gPSB1c2VyRGV0YWlscy50b2tlbiB8fCAnJztcbiAgICAgICAgY29ubmVjdFVybC5oYXNoKHRva2VuKS5xdWVyeSh7XG4gICAgICAgICAgam9sb2tpYVVybDogZW50aXR5LiRqb2xva2lhVXJsLFxuICAgICAgICAgIHRpdGxlOiB0aXRsZSxcbiAgICAgICAgICByZXR1cm5UbzogcmV0dXJuVG9cbiAgICAgICAgfSk7XG4gICAgICAgIGxvZy5kZWJ1ZyhcIkNvbm5lY3QgVVJJOiBcIiwgY29ubmVjdFVybC50b1N0cmluZygpKTtcbiAgICAgICAgd2luZG93Lm9wZW4oY29ubmVjdFVybC50b1N0cmluZygpKTtcbiAgICAgIH07XG5cbiAgICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXN7XG4gICBleHBvcnQgY2xhc3MgZGF0YUluZm9Nb2RlbFNlcnZpY2V7XG4gICAgICBwdWJsaWMgc2VydmVyZGF0YSA9IHt9O1xuICAgICAgcHVibGljIHByb21pc2VvYmplY3QgPSB7fTtcbiAgICAgIHB1YmxpYyBsb2NhbGRhdGEgPSB7fTtcbiAgICAgIHB1YmxpYyBzZWxlY3RlZG5vZGVzID0gW107XG4gICAgICBwdWJsaWMgcmVzdW1hYmxlanMgPSBbXTtcbiAgICAgIHB1YmxpYyBzZWxlY3RlZGl0ZW1zID0gW107XG4gICAgICBwdWJsaWMgc2VydmVyaXRlbXMgPSBbXTtcbiAgICAgIHB1YmxpYyB1cGxvYWRwcm9jZXNzID17fTtcbiAgICAgIHB1YmxpYyB1cGxvYWRlZFN0YXR1cyA9IFwiXCI7XG5cbiAgICAgIHB1YmxpYyBnZXQgdXBsb2FkUHJvY2VzcygpOk9iamVjdCB7XG4gICAgICAgICByZXR1cm4gdGhpcy51cGxvYWRwcm9jZXNzXG4gICAgICB9XG5cbiAgICAgIHB1YmxpYyBzZXQgdXBsb2FkUHJvY2Vzcyh1cGxvYWRQcm9jZXNzOk9iamVjdCl7XG4gICAgICAgICB0aGlzLnVwbG9hZHByb2Nlc3MgPSB1cGxvYWRQcm9jZXNzO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgZm9sZGVyTGlzdCA9IHtcbiAgICAgICAgICBsZW5ndGg6MFxuICAgICAgfTtcblxuICAgICAgcHVibGljIGdldCBzZXJ2ZXJJdGVtcygpOkFycmF5PGFueT4ge1xuICAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyaXRlbXM7XG4gICAgICB9XG5cbiAgICAgIHB1YmxpYyBzZXQgc2VydmVySXRlbXMoc2VydmVySXRlbXM6IEFycmF5PGFueT4pe1xuICAgICAgICAgdGhpcy5zZXJ2ZXJpdGVtcyA9IHNlcnZlckl0ZW1zO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgZ2V0IHJlc3VtYWJsZUpzKCk6QXJyYXk8YW55PiB7XG4gICAgICAgICByZXR1cm4gdGhpcy5yZXN1bWFibGVKcztcbiAgICAgIH1cblxuICAgICAgcHVibGljIHNldCByZXN1bWFibGVKcyhyZXN1bWFibGVKczogQXJyYXk8YW55Pil7XG4gICAgICAgICB0aGlzLnJlc3VtYWJsZWpzID0gcmVzdW1hYmxlSnM7XG4gICAgICB9XG5cbiAgICAgIHB1YmxpYyBnZXQgc2VsZWN0ZWRJdGVtcygpOkFycmF5PGFueT4ge1xuICAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRpdGVtcztcbiAgICAgIH1cblxuICAgICAgcHVibGljIHNldCBzZWxlY3RlZEl0ZW1zKHNlbGVjdGVkSXRlbXM6IEFycmF5PGFueT4pe1xuICAgICAgICAgdGhpcy5zZWxlY3RlZGl0ZW1zID0gc2VsZWN0ZWRJdGVtcztcbiAgICAgIH1cblxuICAgICAgcHVibGljIGdldCBzZWxlY3RlZE5vZGVzKCk6QXJyYXk8YW55PiB7XG4gICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RlZG5vZGVzO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgc2V0IHNlbGVjdGVkTm9kZXMoc2VsZWN0ZWROb2RlczogQXJyYXk8YW55Pil7XG4gICAgICAgICB0aGlzLnNlbGVjdGVkbm9kZXMgPSBzZWxlY3RlZE5vZGVzO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgaXNDb250YWluc05vZGVzKG5vZGU6IE9iamVjdCl7XG4gICAgICAgICBmb3IodmFyIGl0ZW0gaW4gdGhpcy5zZWxlY3RlZG5vZGVzKXtcbiAgICAgICAgICAgIGlmKHRoaXMuc2VsZWN0ZWRub2Rlc1tpdGVtXS5pZCA9PT0gbm9kZS5pZClcbiAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgfVxuICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgZmluZE5vZGVzKG5vZGU6IGFueSkge1xuICAgICAgICAgdmFyIGlkID0gXCItMVwiO1xuICAgICAgICAgaWYodHlwZW9mKG5vZGUpID09PSBcIm9iamVjdFwiICl7XG4gICAgICAgICAgICBpZCA9IG5vZGUuaWQ7XG4gICAgICAgICB9ZWxzZSBpZih0eXBlb2Yobm9kZSkgPT09IFwibnVtYmVyXCIpe1xuICAgICAgICAgICAgaWQgPW5vZGUudG9TdHJpbmcoKTtcbiAgICAgICAgIH1lbHNlIGlmKHR5cGVvZihub2RlKSA9PT0gXCJzdHJpbmdcIil7XG4gICAgICAgICAgICBpZCA9IG5vZGU7XG4gICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgIHJldHVybiBcIi0xXCI7XG4gICAgICAgICB9XG5cbiAgICAgICAgIGZvcih2YXIgaXRlbSBpbiB0aGlzLnNlbGVjdGVkbm9kZXMpe1xuICAgICAgICAgICAgaWYodGhpcy5zZWxlY3RlZG5vZGVzW2l0ZW1dLmlkID09PSBpZClcbiAgICAgICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICAgfVxuICAgICAgICAgcmV0dXJuIFwiLTFcIjtcbiAgICAgIH1cblxuICAgICAgcHVibGljIGZpbmRJdGVtSW5kZXgoaXRlbTogYW55KXtcbiAgICAgICAgIHZhciBpZCA9IC0xO1xuICAgICAgICAgaWYodHlwZW9mKGl0ZW0pID09PSBcIm9iamVjdFwiICl7XG4gICAgICAgICAgICBpZCA9IGl0ZW0uaWQ7XG4gICAgICAgICB9ZWxzZSBpZih0eXBlb2YoaXRlbSkgPT09IFwibnVtYmVyXCIpe1xuICAgICAgICAgICAgaWQgPWl0ZW0udG9TdHJpbmcoKTtcbiAgICAgICAgIH1lbHNlIGlmKHR5cGVvZihpdGVtKSA9PT0gXCJzdHJpbmdcIil7XG4gICAgICAgICAgICBpZCA9IGl0ZW07XG4gICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgIH1cblxuICAgICAgICAgZm9yKHZhciBpdCBpbiB0aGlzLnNlbGVjdGVkaXRlbXMpe1xuICAgICAgICAgICAgaWYodGhpcy5zZWxlY3RlZGl0ZW1zW2l0XS5pZCA9PT0gaWQpXG4gICAgICAgICAgICAgICByZXR1cm4gaXQ7XG4gICAgICAgICB9XG4gICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIHB1YmxpYyBjcmVhdGVGb2xkZXJMaXN0KGZpbGVzOiBPYmplY3QgLHJvb3RQYXRoOiBzdHJpbmcpe1xuICAgICAgICAgZm9yKHZhciBpPTA7IGk8IGZpbGVzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIHZhciByZWxhdGl2ZVBhdGggPSAgZmlsZXNbaV0ud2Via2l0UmVsYXRpdmVQYXRoLnJlcGxhY2UoUmVnRXhwKFwiXlwiK3Jvb3RQYXRoK1wiL1wiKSxcIlwiKTtcbiAgICAgICAgICAgIHZhciBwYXRocz1yZWxhdGl2ZVBhdGguc3BsaXQoXCIvXCIpO1xuICAgICAgICAgICAgaWYoIXRoaXMuZm9sZGVyTGlzdC5oYXNPd25Qcm9wZXJ0eShwYXRoc1swXSkpe1xuICAgICAgICAgICAgICAgdGhpcy5mb2xkZXJMaXN0W3BhdGhzWzBdXT17XG4gICAgICAgICAgICAgICAgIGxlbmd0aDowXG4gICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB0aGlzLmZvbGRlckxpc3QubGVuZ3RoKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgT2JqID0gdGhpcy5mb2xkZXJMaXN0W3BhdGhzWzBdXTtcbiAgICAgICAgICAgIE9ialtPYmoubGVuZ3RoXSA9IGZpbGVzW2ldO1xuICAgICAgICAgICAgT2JqLmxlbmd0aCsrO1xuICAgICAgICAgICAgdGhpcy5mb2xkZXJMaXN0W3BhdGhzWzBdXSA9IE9iajtcbiAgICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcHVibGljIHVwZGF0ZU5vZGVCeUlkKG5vZGVJZCxrZXksdmFsdWUpe1xuICAgICAgICAgZm9yKHZhciBpdGVtIGluIHRoaXMuc2VsZWN0ZWRub2Rlcyl7XG4gICAgICAgICAgICB2YXIgbm9kZSA9IHRoaXMuc2VsZWN0ZWRub2Rlc1tpdGVtXTtcbiAgICAgICAgICAgIGlmKG5vZGUuaWQgPT09IG5vZGVJZCl7XG4gICAgICAgICAgICAgICBub2RlW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBwdWJsaWMgZ2V0IHNlcnZlckRhdGEoKTpPYmplY3Qge1xuICAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyRGF0YTtcbiAgICAgIH1cblxuICAgICAgcHVibGljIHNldCBzZXJ2ZXJEYXRhKHNlcnZlckRhdGE6T2JqZWN0KXtcbiAgICAgICAgIHRoaXMuc2VydmVyZGF0YT1zZXJ2ZXJEYXRhO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgZ2V0IHByb21pc2VPYmplY3QoKTpPYmplY3Qge1xuICAgICAgICAgcmV0dXJuIHRoaXMucHJvbWlzZW9iamVjdDtcbiAgICAgIH1cblxuICAgICAgcHVibGljIHNldCBwcm9taXNlKHByb21pc2VPYmplY3Q6T2JqZWN0KXtcbiAgICAgICAgIHRoaXMucHJvbWlzZW9iamVjdCA9IHByb21pc2VPYmplY3Q7XG4gICAgICB9XG5cbiAgICAgIHB1YmxpYyBnZXQgbG9jYWxEYXRhKCk6T2JqZWN0IHtcbiAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZGF0YTtcbiAgICAgIH1cblxuICAgICAgcHVibGljIHNldCBsb2NhbERhdGEobG9jYWxEYXRhOk9iamVjdCl7XG4gICAgICAgICB0aGlzLmxvY2FsZGF0YSA9IGxvY2FsRGF0YTtcbiAgICAgIH1cblxuICAgICAgcHVibGljIHVwZGF0YURhdGFNb2RlbCgpe1xuICAgICAgICAgdGhpcy5wcm9taXNlb2JqZWN0LnN1Y2Nlc3MoZnVuY3Rpb24oZGF0YSxoZWFkZXIsY29uZmlnLHN0YXR1cyl7XG4gICAgICAgICAgICB0aGlzLnNlcnZlcmRhdGEgPWRhdGE7XG4gICAgICAgICB9KTtcblxuICAgICAgICAgdGhpcy5wcm9taXNlb2JqZWN0LmVycm9yKGZ1bmN0aW9uKGRhdGEsc3RhdHVzLGhlZGFlcnMsY29uZmlnKXtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyZGF0YSA9IHt9O1xuICAgICAgICAgfSk7XG4gICAgICB9XG4gICB9XG4gIF9tb2R1bGUuZmFjdG9yeSgnRGF0YUluZm9Nb2RlbCcsIFsnJGh0dHAnLCAoJGh0dHApID0+IHtcbiAgICAgIHZhciAkc2NvcGUgPW5ldyBkYXRhSW5mb01vZGVsU2VydmljZSgpO1xuXG4gICAgICAkc2NvcGUucHJvbWlzZW9iamVjdD0kaHR0cCh7XG4gICAgICAgICB1cmw6Jy94bWxmb3Jtc2VydmVyJyxcbiAgICAgICAgIG1ldGhvZDonUE9TVCdcbiAgICAgIH0pO1xuXG4gICAgICB1cGRhdGVEYXRhRnJvbVNlcnZlcigkc2NvcGUuc2VydmVyZGF0YSwgKGRhdGEsaGVhZGVyLGNvbmZpZyxzdGF0dXMpID0+IHtcbiAgICAgICAgICRzY29wZS5zZXJ2ZXJkYXRhID0gZGF0YTtcbiAgICAgIH0pO1xuXG4gICAgICBmdW5jdGlvbiB1cGRhdGVEYXRhRnJvbVNlcnZlcihkYXRhLGNhbGxiYWNrKXtcbiAgICAgICAgICRodHRwKHtcbiAgICAgICAgICAgIHVybDonL3htbGZvcm1zZXJ2ZXInLFxuICAgICAgICAgICAgbWV0aG9kOidQT1NUJ1xuICAgICAgICAgfSkuc3VjY2VzcyhmdW5jdGlvbihkYXRhLGhlYWRlcixjb25maWcsc3RhdHVzKXtcbiAgICAgICAgICAgaWYoZGF0YSlcbiAgICAgICAgICAgICBjYWxsYmFjayhkYXRhLGhlYWRlcixjb25maWcsc3RhdHVzKTtcbiAgICAgICAgIH0pLmVycm9yKGZ1bmN0aW9uKGRhdGEsaGVhZGVyLGNvbmZpZyxzdGF0dXMpe1xuICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiZXJyb3JcIik7XG4gICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gJHNjb3BlO1xuICB9XSk7XG59IiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIERlcGxveW1lbnRDb25maWdDb250cm9sbGVyID0gY29udHJvbGxlcihcIkRlcGxveW1lbnRDb25maWdDb250cm9sbGVyXCIsXG4gICAgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc1NjaGVtYVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIixcbiAgICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSxcbiAgICAgICAkdGVtcGxhdGVDYWNoZTpuZy5JVGVtcGxhdGVDYWNoZVNlcnZpY2UsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCAkcm91dGVQYXJhbXMsICRodHRwLCAkdGltZW91dCwgS3ViZXJuZXRlc0FwaVVSTCkgPT4ge1xuXG4gICAgICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICAgICAkc2NvcGUuc2NoZW1hID0gS3ViZXJuZXRlc1NjaGVtYTtcbiAgICAgICAgJHNjb3BlLmNvbmZpZyA9IEt1YmVybmV0ZXNTY2hlbWEuZGVmaW5pdGlvbnMub3NfZGVwbG95X0RlcGxveW1lbnRDb25maWc7XG5cbiAgICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuXG4gICAgICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkc2NvcGUuJG9uKCckcm91dGVVcGRhdGUnLCAoJGV2ZW50KSA9PiB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB1cGRhdGVEYXRhKCk7XG5cbiAgICAgICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgICAgICAkc2NvcGUuaXRlbSA9IG51bGw7XG4gICAgICAgICAgaWYgKCRzY29wZS5pZCkge1xuICAgICAgICAgICAgdmFyIHVybCA9IGRlcGxveW1lbnRDb25maWdSZXN0VXJsKCRzY29wZS5pZCk7XG4gICAgICAgICAgICAkaHR0cC5nZXQodXJsKS5cbiAgICAgICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgJHNjb3BlLmVudGl0eSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICBlbnJpY2hEZXBsb3ltZW50Q29uZmlnKGRhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICAgICAgfSkuXG4gICAgICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIERlcGxveW1lbnRDb25maWdzQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJEZXBsb3ltZW50Q29uZmlnc0NvbnRyb2xsZXJcIiwgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiJGRpYWxvZ1wiLCBcIiR3aW5kb3dcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRsb2NhdGlvblwiLCBcImxvY2FsU3RvcmFnZVwiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCAkZGlhbG9nLCAkd2luZG93LCAkdGVtcGxhdGVDYWNoZSwgJHJvdXRlUGFyYW1zLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgbG9jYWxTdG9yYWdlLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgfSk7XG4gICAgICAkc2NvcGUubGFiZWxDbGFzcyA9IGNvbnRhaW5lckxhYmVsQ2xhc3M7XG5cbiAgICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgICAgZGF0YTogJ2RlcGxveW1lbnRDb25maWdzJyxcbiAgICAgICAgc2hvd1NlbGVjdGlvbkNoZWNrYm94OiB0cnVlLFxuICAgICAgICBlbmFibGVSb3dDbGlja1NlbGVjdGlvbjogZmFsc2UsXG4gICAgICAgIG11bHRpU2VsZWN0OiB0cnVlLFxuICAgICAgICBzZWxlY3RlZEl0ZW1zOiBbXSxcbiAgICAgICAgZmlsdGVyT3B0aW9uczoge1xuICAgICAgICAgIGZpbHRlclRleHQ6ICRsb2NhdGlvbi5zZWFyY2goKVtcInFcIl0gfHwgJydcbiAgICAgICAgfSxcbiAgICAgICAgY29sdW1uRGVmczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnbWV0YWRhdGEubmFtZScsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ05hbWUnLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJkZXBsb3ltZW50Q29uZmlnTGlua1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnbWV0YWRhdGEubmFtZXNwYWNlJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTmFtZXNwYWNlJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckaW1hZ2VDaGFuZ2VQYXJhbXMuYXV0b21hdGljJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnQXV0b21hdGljJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckaW1hZ2VDaGFuZ2VQYXJhbXMuJGNvbnRhaW5lck5hbWVzJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnQ29udGFpbmVyIE5hbWVzJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICckaW1hZ2VDaGFuZ2VQYXJhbXMuZnJvbS5uYW1lJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnRnJvbSBpbWFnZSdcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAnJGltYWdlQ2hhbmdlUGFyYW1zLnRhZycsXG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogJ1RhZydcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZpZWxkOiAndGVtcGxhdGUuY29udHJvbGxlclRlbXBsYXRlLnBvZFRlbXBsYXRlLnRhZ3MnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdMYWJlbHMnLFxuICAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJkZXBsb3ltZW50Q29uZmlnTGFiZWxUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICAgfVxuICAgICAgICBdXG4gICAgICB9O1xuXG4gICAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG5cbiAgICAgICRzY29wZS5kZWxldGVQcm9tcHQgPSAoc2VsZWN0ZWQpID0+IHtcbiAgICAgICAgVUkubXVsdGlJdGVtQ29uZmlybUFjdGlvbkRpYWxvZyg8VUkuTXVsdGlJdGVtQ29uZmlybUFjdGlvbk9wdGlvbnM+e1xuICAgICAgICAgIGNvbGxlY3Rpb246IHNlbGVjdGVkLFxuICAgICAgICAgIGluZGV4OiAnJG5hbWUnLFxuICAgICAgICAgIG9uQ2xvc2U6IChyZXN1bHQ6Ym9vbGVhbikgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICBmdW5jdGlvbiBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgbmV4dCkge1xuICAgICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgICBkZWxldGVFbnRpdHkobmV4dCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIHRpdGxlOiAnRGVsZXRlIERlcGxveW1lbnQ/JyxcbiAgICAgICAgICBhY3Rpb246ICdUaGUgZm9sbG93aW5nIERlcGxveW1lbnRzIHdpbGwgYmUgZGVsZXRlZDonLFxuICAgICAgICAgIG9rVGV4dDogJ0RlbGV0ZScsXG4gICAgICAgICAgb2tDbGFzczogJ2J0bi1kYW5nZXInLFxuICAgICAgICAgIGN1c3RvbTogXCJUaGlzIG9wZXJhdGlvbiBpcyBwZXJtYW5lbnQgb25jZSBjb21wbGV0ZWQhXCIsXG4gICAgICAgICAgY3VzdG9tQ2xhc3M6IFwiYWxlcnQgYWxlcnQtd2FybmluZ1wiXG4gICAgICAgIH0pLm9wZW4oKTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIGRlbGV0ZUVudGl0eShzZWxlY3Rpb24sIG5leHRDYWxsYmFjaykge1xuICAgICAgICB2YXIgbmFtZSA9IChzZWxlY3Rpb24gfHwge30pLiRuYW1lO1xuICAgICAgICBpZiAobmFtZSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQWJvdXQgdG8gZGVsZXRlIGRlcGxveW1lbnQgY29uZmlnOiBcIiArIG5hbWUpO1xuICAgICAgICAgIHZhciB1cmwgPSBkZXBsb3ltZW50Q29uZmlnUmVzdFVybChuYW1lKTtcbiAgICAgICAgICAkaHR0cC5kZWxldGUodXJsKS5cbiAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgIG5leHRDYWxsYmFjaygpO1xuICAgICAgICAgICAgfSkuXG4gICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gZGVsZXRlIGRlcGxveW1lbnQgY29uZmlnIG9uIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJ3YXJuaW5nOiBubyBuYW1lIGZvciBzZWxlY3Rpb246IFwiICsgYW5ndWxhci50b0pzb24oc2VsZWN0aW9uKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgICAgdmFyIHVybCA9IGRlcGxveW1lbnRDb25maWdzUmVzdFVSTCgpO1xuICAgICAgICAkaHR0cC5nZXQodXJsKS5cbiAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcImdvdCBkYXRhIFwiICsgYW5ndWxhci50b0pzb24oZGF0YSwgdHJ1ZSkpO1xuICAgICAgICAgICAgICAkc2NvcGUuZGVwbG95bWVudENvbmZpZ3MgPSBlbnJpY2hEZXBsb3ltZW50Q29uZmlncyhkYXRhLml0ZW1zKTtcbiAgICAgICAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLlxuICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgdXBkYXRlRGF0YSgpO1xuICAgIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBFdmVudHNDb250cm9sbGVyID0gY29udHJvbGxlcihcIkV2ZW50c0NvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU2VydmljZXNcIiwgXCJLdWJlcm5ldGVzUG9kc1wiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIixcbiAgICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDogS3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU2VydmljZXM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1BvZHM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1N0YXRlLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG5cbiAgICBDb250cm9sbGVySGVscGVycy5iaW5kTW9kZWxUb1NlYXJjaFBhcmFtKCRzY29wZSwgJGxvY2F0aW9uLCAnbW9kZScsICdtb2RlJywgJ2xpc3QnKTtcblxuICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgIGRhdGE6ICdtb2RlbC5ldmVudHMnLFxuICAgICAgc2hvd1NlbGVjdGlvbkNoZWNrYm94OiB0cnVlLFxuICAgICAgZW5hYmxlUm93Q2xpY2tTZWxlY3Rpb246IGZhbHNlLFxuICAgICAgbXVsdGlTZWxlY3Q6IHRydWUsXG4gICAgICBzZWxlY3RlZEl0ZW1zOiBbXSxcbiAgICAgIGZpbHRlck9wdGlvbnM6IHtcbiAgICAgICAgZmlsdGVyVGV4dDogJGxvY2F0aW9uLnNlYXJjaCgpW1wicVwiXSB8fCAnJ1xuICAgICAgfSxcbiAgICAgIGNvbHVtbkRlZnM6IFtcbiAgICAgICAgeyBmaWVsZDogJyRmaXJzdFRpbWVzdGFtcCcsXG4gICAgICAgICAgZGlzcGxheU5hbWU6ICdGaXJzdCBTZWVuJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImZpcnN0VGltZXN0YW1wVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgICB7IGZpZWxkOiAnJGxhc3RUaW1lc3RhbXAnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTGFzdCBTZWVuJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImxhc3RUaW1lc3RhbXBUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHsgZmllbGQ6ICdjb3VudCcsXG4gICAgICAgICAgZGlzcGxheU5hbWU6ICdDb3VudCdcbiAgICAgICAgfSxcbiAgICAgICAgeyBmaWVsZDogJ2ludm9sdmVkT2JqZWN0Lm5hbWUnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTmFtZScsXG4gICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJldmVudE5hbWVUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHsgZmllbGQ6ICdpbnZvbHZlZE9iamVjdC5raW5kJyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ0tpbmQnLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiZXZlbnRLaW5kVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgICB7IGZpZWxkOiAnaW52b2x2ZWRPYmplY3QuZmllbGRQYXRoJyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ1N1YmplY3QnXG4gICAgICAgIH0sXG4gICAgICAgIHsgZmllbGQ6ICdyZWFzb24nLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUmVhc29uJ1xuICAgICAgICB9LFxuICAgICAgICB7IGZpZWxkOiAnc291cmNlJyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ1NvdXJjZScsXG4gICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJldmVudFNvdXJjZVRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgfSxcbiAgICAgICAgeyBmaWVsZDogJ21lc3NhZ2UnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTWVzc2FnZSdcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH07XG5cbiAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNNb2RlbC50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIGV4cG9ydCB2YXIgSG9zdENvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiSG9zdENvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6S3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAgICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICAgICAkc2NvcGUucmF3TW9kZWwgPSBudWxsO1xuXG4gICAgICAgICRzY29wZS5pdGVtQ29uZmlnID0ge1xuICAgICAgICAgIHByb3BlcnRpZXM6IHt9XG4gICAgICAgIH07XG5cbiAgICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuXG4gICAgICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkc2NvcGUuJG9uKCckcm91dGVVcGRhdGUnLCAoJGV2ZW50KSA9PiB7XG4gICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAkc2NvcGUuZmxpcFJhdyA9ICgpID0+IHtcbiAgICAgICAgICAkc2NvcGUucmF3TW9kZSA9ICEkc2NvcGUucmF3TW9kZTtcbiAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHVwZGF0ZURhdGEoKTtcblxuICAgICAgICBmdW5jdGlvbiB1cGRhdGVEYXRhKCkge1xuICAgICAgICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICAgICAgICRzY29wZS5pdGVtID0gbnVsbDtcbiAgICAgICAgICBpZiAoJHNjb3BlLmlkKSB7XG4gICAgICAgICAgICB2YXIgdXJsID0gVXJsSGVscGVycy5qb2luKEt1YmVybmV0ZXNBcGlVUkwsIFwibm9kZXNcIiwgJHNjb3BlLmlkKTtcbiAgICAgICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAkc2NvcGUuaXRlbSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgkc2NvcGUuaXRlbSkge1xuICAgICAgICAgICAgICAgICAgJHNjb3BlLnJhd01vZGVsID0gdG9SYXdZYW1sKCRzY29wZS5pdGVtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgIGxvZy53YXJuKFwiRmFpbGVkIHRvIGxvYWQgXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHNjb3BlLnJhd01vZGVsID0gbnVsbDtcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG5tb2R1bGUgS3ViZXJuZXRlcyB7XG4gIGV4cG9ydCB2YXIgaG9zdFBvcnRzID1bXTtcblxuICAvKipcbiAgICogU29ydHMgdGhlIHRoZSBpcCBmaWVsZFxuICAgKlxuICAgKiBAcGFyYW0gaXAgdGhlIGlwIHN1Y2ggYXMgJzEwLjEuMi4xMydcbiAgICogQHJldHVybnMge2FueX1cbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBzb3J0QnlQb2RJcChpcCkgOiBhbnkge1xuICAgIC8vIGkgZ3Vlc3MgdGhlcmUgaXMgbWF5YmUgbmljZXIgd2F5cyBvZiBzb3J0IHRoaXMgd2l0aG91dCBwYXJzaW5nIGFuZCBzbGljaW5nXG4gICAgdmFyIHJlZ2V4ID0gLyhcXGR7MSwzfSlcXC4oXFxkezEsM30pXFwuKFxcZHsxLDN9KVxcLihcXGR7MSwzfSkvO1xuICAgIHZhciBncm91cHMgPSByZWdleC5leGVjKGlwKTtcbiAgICBpZiAoYW5ndWxhci5pc0RlZmluZWQoZ3JvdXBzKSkge1xuICAgICAgdmFyIGcxID0gKFwiMDBcIiArIGdyb3Vwc1sxXSkuc2xpY2UoLTMpO1xuICAgICAgdmFyIGcyID0gKFwiMDBcIiArIGdyb3Vwc1syXSkuc2xpY2UoLTMpO1xuICAgICAgdmFyIGczID0gKFwiMDBcIiArIGdyb3Vwc1szXSkuc2xpY2UoLTMpO1xuICAgICAgdmFyIGc0ID0gKFwiMDBcIiArIGdyb3Vwc1s0XSkuc2xpY2UoLTMpO1xuICAgICAgdmFyIGFuc3dlciA9IGcxICsgZzIgKyBnMyArIGc0O1xuICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHJhbWRvbVBvcnQoKTogbnVtYmVye1xuICAgICB2YXIgaG9zdFBvcnQ9TWF0aC5mbG9vcigzMDAwMCtNYXRoLnJhbmRvbSgpKig2NTUzNS0zMDAwMCkpO1xuICAgICB3aGlsZShob3N0UG9ydHMuaW5kZXhPZihob3N0UG9ydCkgPT09IDApe1xuICAgICAgICBob3N0UG9ydCA9IE1hdGguZmxvb3IoMzAwMDArTWF0aC5yYW5kb20oKSooNjU1MzUtMzAwMDApKTtcbiAgICAgfVxuICAgICBob3N0UG9ydHMucHVzaChob3N0UG9ydCk7XG4gICAgIHJldHVybiBob3N0UG9ydFxuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldFJhbmRvbVN0cmluZyhsZW4gOiBudW1iZXIpIDogc3RyaW5ne1xuICAgICAgbGVuID0gbGVuIHx8IDMyO1xuICAgICAgdmFyICRjaGFycyA9ICdhYmNkZWZoaWprbW5wcnN0d3h5eic7IC8vIOm7mOiupOWOu+aOieS6huWuueaYk+a3t+a3hueahOWtl+espm9PTGwsOWdxLFZ2LFV1LEkxXG4gICAgICB2YXIgbWF4UG9zID0gJGNoYXJzLmxlbmd0aDtcbiAgICAgIHZhciBwd2QgPSAnJztcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICBwd2QgKz0gJGNoYXJzLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBtYXhQb3MpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwd2Q7XG4gIH1cblxuICBleHBvcnQgY2xhc3MgcmVzb3VyY2VSQ1RlbXBsYXRle1xuXG4gICAgIHB1YmxpYyBpbWFnZT1cInMxOmxhdGVzdFwiO1xuICAgICBwdWJsaWMgbmFtZXMgPSBbXCJhZG1pblwiLFwiY2ZndG9vbGxvZ3NcIixcImNoZWNrcG9pbnRzXCIsXCJkaWFnXCIsXCJmbGFzaC1yZWNvdmVyeS1hcmVhXCIsXCJvcmFkYXRhXCJdO1xuXG4gICAgIHB1YmxpYyBjcmVhdGVSQyhPYmope1xuICAgICAgICB2YXIgbGFiZWxzID0ge1xuICAgICAgICAgICBcInN0eWxlXCI6IFwib3JhY2xlXCIsXG4gICAgICAgICAgIFwic3RhdHVzXCI6IFwiY3JlYXRlZFwiXG4gICAgICAgIH07XG4gICAgICAgIGZvcih2YXIgaXRlbSBpbiBPYmoubGFiZWxzKVxuICAgICAgICAgICBsYWJlbHNbaXRlbV0gPSBPYmoubGFiZWxzW2l0ZW1dO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgIFwiYXBpVmVyc2lvblwiIDogIEt1YmVybmV0ZXMuZGVmYXVsdEFwaVZlcnNpb24sXG4gICAgICAgICAgIFwia2luZFwiIDogXCJSZXBsaWNhdGlvbkNvbnRyb2xsZXJcIixcbiAgICAgICAgICAgXCJtZXRhZGF0YVwiIDoge1xuICAgICAgICAgICAgICBcIm5hbWVcIiA6IE9iai5uYW1lLFxuICAgICAgICAgICAgICBcImxhYmVsc1wiIDogbGFiZWxzXG4gICAgICAgICAgIH0sXG4gICAgICAgICAgIFwic3BlY1wiIDoge1xuICAgICAgICAgICAgICByZXBsaWNhcyA6IE9iai5yZXBsaWNhcyB8fCAxLFxuICAgICAgICAgICAgICBcInRlbXBsYXRlXCIgOiB0aGlzLmNyZWF0ZVRlbXBsYXRlKE9iailcbiAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgIH1cblxuICAgICBwdWJsaWMgY3JlYXRlVm9sdW1lTW91bnRzKCl7XG4gICAgICAgIHZhciB2b2x1bWVNb3VudHMgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpdGVtIGluIHRoaXMubmFtZXMpe1xuICAgICAgICAgICBpZih0aGlzLm5hbWVzW2l0ZW1dID09PSAnZmxhc2gtcmVjb3ZlcnktYXJlYScpXG4gICAgICAgICAgICAgIHZvbHVtZU1vdW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgXCJuYW1lXCIgOiB0aGlzLm5hbWVzW2l0ZW1dLFxuICAgICAgICAgICAgICAgICBcIm1vdW50UGF0aFwiIDogXCIvb3B0L29yYWNsZS9hcHAvZmxhc2hfcmVjb3ZlcnlfYXJlYVwiXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgIHZvbHVtZU1vdW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgXCJuYW1lXCIgOiB0aGlzLm5hbWVzW2l0ZW1dLFxuICAgICAgICAgICAgICAgICBcIm1vdW50UGF0aFwiIDogXCIvb3B0L29yYWNsZS9hcHAvXCIgKyB0aGlzLm5hbWVzW2l0ZW1dXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2b2x1bWVNb3VudHM7XG4gICAgIH1cblxuICAgICBwdWJsaWMgY3JlYXRlVm9sdW1lcyhyb290UGF0aCA6c3RyaW5nKXtcbiAgICAgICAgdmFyIHZvbHVtZXMgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpdGVtIGluIHRoaXMubmFtZXMpe1xuICAgICAgICAgICAgaWYodGhpcy5uYW1lc1tpdGVtXSA9PT0gJ2ZsYXNoLXJlY292ZXJ5LWFyZWEnKVxuICAgICAgICAgICAgICAgdm9sdW1lcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgIFwibmFtZVwiIDogdGhpcy5uYW1lc1tpdGVtXSxcbiAgICAgICAgICAgICAgICAgIFwiaG9zdFBhdGhcIiA6e1xuICAgICAgICAgICAgICAgICAgICAgIFwicGF0aFwiIDogcm9vdFBhdGggKyBcImZsYXNoX3JlY292ZXJ5X2FyZWFcIlxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICB2b2x1bWVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgXCJuYW1lXCIgOiB0aGlzLm5hbWVzW2l0ZW1dLFxuICAgICAgICAgICAgICAgICAgXCJob3N0UGF0aFwiIDp7XG4gICAgICAgICAgICAgICAgICAgICAgXCJwYXRoXCIgOiByb290UGF0aCArIHRoaXMubmFtZXNbaXRlbV1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2b2x1bWVzO1xuICAgICB9XG5cbiAgICAgcHVibGljIGNyZWF0ZUNvbnRhaW5lcnMoT2JqKXtcbiAgICAgICAgdmFyIGNvbnRhaW5lcnMgPSBbXTtcbiAgICAgICAgY29udGFpbmVycy5wdXNoKFxuICAgICAgICB7XG4gICAgICAgICAgIFwibmFtZVwiIDogXCJvcmFjbGVcIixcbiAgICAgICAgICAgXCJpbWFnZVwiOiB0aGlzLmltYWdlLFxuICAgICAgICAgICBcImltYWdlUHVsbFBvbGljeVwiOiBcIklmTm90UHJlc2VudFwiLFxuICAgICAgICAgICBcImNvbW1hbmRcIjpbXCIvYXNzZXRzL2VudHJ5cG9pbnQuc2hcIl0sXG4gICAgICAgICAgIFwicG9ydHNcIjogW1xuICAgICAgICAgICB7XG4gICAgICAgICAgICAgXCJjb250YWluZXJQb3J0XCI6IDE1MjEsXG4gICAgICAgICAgICAgXCJob3N0UG9ydFwiOiBPYmoucG9ydCB8fCByYW1kb21Qb3J0KClcbiAgICAgICAgICAgfV0sXG4gICAgICAgICAgIFwidm9sdW1lTW91bnRzXCIgOiB0aGlzLmNyZWF0ZVZvbHVtZU1vdW50cygpXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29udGFpbmVyc1xuICAgICB9XG5cbiAgICAgcHVibGljIGNyZWF0ZVRlbXBsYXRlKE9iail7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBcIm1ldGFkYXRhXCI6XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAvL1wibmFtZVwiOiBPYmoubmFtZSxcbiAgICAgICAgICAgICAgIFwibGFiZWxzXCI6IE9iai5sYWJlbHNcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcInNwZWNcIiA6IHtcbiAgICAgICAgICAgICAgICBcInRlcm1pbmF0aW9uR3JhY2VQZXJpb2RTZWNvbmRzXCIgOiAwLFxuICAgICAgICAgICAgICAgIFwiY29udGFpbmVyc1wiIDogIHRoaXMuY3JlYXRlQ29udGFpbmVycyhPYmopLFxuICAgICAgICAgICAgICAgIFwidm9sdW1lc1wiIDogIHRoaXMuY3JlYXRlVm9sdW1lcyhPYmoucGF0aClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICB9XG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gZmluZExhYmVsVmFsdWUodmFsdWU6c3RyaW5nLCBrZXk6IHN0cmluZyk6c3RyaW5nIHtcbiAgICAgdmFyIHRydWVWYWx1ZSA9ICcnO1xuICAgICBzd2l0Y2godmFsdWUpe1xuICAgICAgICBjYXNlICcwMSc6XG4gICAgICAgICAgIHRydWVWYWx1ZSA9ICfotKLmlL8nO1xuICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnMDInOlxuICAgICAgICAgICB0cnVlVmFsdWUgPSAn56S+5L+dJztcbiAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0EnOlxuICAgICAgICAgICB0cnVlVmFsdWUgPSAn5om55qyhQSc7XG4gICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdCJzpcbiAgICAgICAgICAgdHJ1ZVZhbHVlID0gJ+aJueasoUInO1xuICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGlmKGtleSA9PT0gXCJ2ZXJzaW9uXCIpe1xuICAgICAgICAgICAgICAgIHZhciByZWc9IG5ldyBSZWdFeHAoJ15bMC05XSQnKS5leGVjKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZihyZWcpXG4gICAgICAgICAgICAgICAgICAgdHJ1ZVZhbHVlID0gJ+eJiOacrCcgKyByZWdbMF07XG4gICAgICAgICAgICAgICAgZWxzZSB0cnVlVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0cnVlVmFsdWUgPSB2YWx1ZTtcbiAgICAgfVxuICAgICByZXR1cm4gdHJ1ZVZhbHVlXG4gIH1cblxuICBleHBvcnQgZnVuY3Rpb24gbGFiZWxUb0NoaW5lc2UobGFiZWxzKXtcbiAgICAgdmFyIGFuc3dlciA9IHt9O1xuICAgICBhbmd1bGFyLmZvckVhY2gobGFiZWxzLCh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgIGFuc3dlcltrZXldID0gZmluZExhYmVsVmFsdWUodmFsdWUsIGtleSk7XG4gICAgIH0pO1xuICAgICByZXR1cm4gYW5zd2VyXG4gIH1cbn0iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzTW9kZWwudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwidXRpbEhlbHBlcnMudHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIEhvc3RzQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJIb3N0c0NvbnRyb2xsZXJcIiwgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1BvZHNcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJTZXJ2aWNlUmVnaXN0cnlcIiwgXCIkZGlhbG9nXCIsIFwiJHdpbmRvd1wiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGxvY2F0aW9uXCIsIFwibG9jYWxTdG9yYWdlXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIixcbiAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6IEt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1BvZHM6bmcuSVByb21pc2U8bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55Pj4sIEt1YmVybmV0ZXNTdGF0ZSwgU2VydmljZVJlZ2lzdHJ5LCAkZGlhbG9nLCAkd2luZG93LCAkdGVtcGxhdGVDYWNoZSwgJHJvdXRlUGFyYW1zLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgbG9jYWxTdG9yYWdlLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICB9KTtcblxuICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgIGRhdGE6ICdtb2RlbC5ob3N0cycsXG4gICAgICBzaG93U2VsZWN0aW9uQ2hlY2tib3g6IGZhbHNlLFxuICAgICAgZW5hYmxlUm93Q2xpY2tTZWxlY3Rpb246IGZhbHNlLFxuICAgICAgbXVsdGlTZWxlY3Q6IGZhbHNlLFxuICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgIGZpbHRlclRleHQ6ICRsb2NhdGlvbi5zZWFyY2goKVtcInFcIl0gfHwgJydcbiAgICAgIH0sXG4gICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJ2lkJyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ05hbWUnLFxuICAgICAgICAgIGRlZmF1bHRTb3J0OiB0cnVlLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiaWRUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJ2hvc3RJUCcsXG4gICAgICAgICAgZGlzcGxheU5hbWU6ICdJUCcsXG4gICAgICAgICAgY3VzdG9tU29ydEZpZWxkOiAoZmllbGQpID0+IHtcbiAgICAgICAgICAgIC8vIHVzZSBhIGN1c3RvbSBzb3J0IHRvIHNvcnQgaXAgYWRkcmVzc1xuICAgICAgICAgICAgcmV0dXJuIEt1YmVybmV0ZXMuc29ydEJ5UG9kSXAoZmllbGQuaG9zdElQKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHsgZmllbGQ6ICckcG9kc0xpbmsnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUG9kcycsXG4gICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJwb2RDb3VudHNBbmRMaW5rVGVtcGxhdGUuaHRtbFwiKSxcbiAgICAgICAgICBjdXN0b21Tb3J0RmllbGQ6IChmaWVsZCkgPT4ge1xuICAgICAgICAgICAgLy8gbmVlZCB0byBjb25jYXQgYWxsIHRoZSBwb2QgY291bnRlcnNcbiAgICAgICAgICAgIHZhciByZWFkeSA9IGZpZWxkLiRwb2RDb3VudGVycy5yZWFkeSB8fCAwO1xuICAgICAgICAgICAgdmFyIHZhbGlkID0gZmllbGQuJHBvZENvdW50ZXJzLnZhbGlkIHx8IDA7XG4gICAgICAgICAgICB2YXIgd2FpdGluZyA9IGZpZWxkLiRwb2RDb3VudGVycy53YWl0aW5nIHx8IDA7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSBmaWVsZC4kcG9kQ291bnRlcnMuZXJyb3IgfHwgMDtcbiAgICAgICAgICAgIHJldHVybiByZWFkeSArIHZhbGlkICsgd2FpdGluZyArIGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXVxuICAgIH07XG5cbiAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBJbWFnZVJlcG9zaXRvcmllc0NvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiSW1hZ2VSZXBvc2l0b3JpZXNDb250cm9sbGVyXCIsIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIiRkaWFsb2dcIiwgXCIkd2luZG93XCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkbG9jYXRpb25cIiwgXCJsb2NhbFN0b3JhZ2VcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDpLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgJGRpYWxvZywgJHdpbmRvdywgJHRlbXBsYXRlQ2FjaGUsICRyb3V0ZVBhcmFtcywgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsIGxvY2FsU3RvcmFnZSwgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICAgJHNjb3BlLiRvbigna3ViZXJuZXRlc01vZGVsVXBkYXRlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgIH0pO1xuXG4gICAgICAkc2NvcGUudGFibGVDb25maWcgPSB7XG4gICAgICAgIGRhdGE6ICdpbWFnZVJlcG9zaXRvcmllcycsXG4gICAgICAgIHNob3dTZWxlY3Rpb25DaGVja2JveDogdHJ1ZSxcbiAgICAgICAgZW5hYmxlUm93Q2xpY2tTZWxlY3Rpb246IGZhbHNlLFxuICAgICAgICBtdWx0aVNlbGVjdDogdHJ1ZSxcbiAgICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICAgIGZpbHRlck9wdGlvbnM6IHtcbiAgICAgICAgICBmaWx0ZXJUZXh0OiAkbG9jYXRpb24uc2VhcmNoKClbXCJxXCJdIHx8ICcnXG4gICAgICAgIH0sXG4gICAgICAgIGNvbHVtbkRlZnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ21ldGFkYXRhLm5hbWUnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdOYW1lJ1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgZmllbGQ6ICdtZXRhZGF0YS5uYW1lc3BhY2UnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdOYW1lc3BhY2UnXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3N0YXR1cy5kb2NrZXJJbWFnZVJlcG9zaXRvcnknLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdEb2NrZXIgUmVnaXN0cnknXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmaWVsZDogJ3RhZ3MnLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6ICdUYWdzJyxcbiAgICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KCdpbWFnZVJlZ2lzdHJ5TGFiZWxUZW1wbGF0ZS5odG1sJylcbiAgICAgICAgICB9XG4gICAgICAgIF1cbiAgICAgIH07XG5cbiAgICAgIHZhciBsYWJlbENvbG9ycyA9IHtcbiAgICAgICAgJ3Byb2QnOiAnYmFja2dyb3VuZC1ibHVlJyxcbiAgICAgICAgJ3ZhbGlkJzogJ2JhY2tncm91bmQtbGlnaHQtZ3JlZW4nLFxuICAgICAgICAndGVzdCc6ICdiYWNrZ3JvdW5kLWxpZ2h0LWdyZXknXG4gICAgICB9O1xuICAgICAgJHNjb3BlLmxhYmVsQ2xhc3MgPSAobGFiZWxUeXBlOnN0cmluZykgPT4ge1xuICAgICAgICBpZiAoIShsYWJlbFR5cGUgaW4gbGFiZWxDb2xvcnMpKSB7XG4gICAgICAgICAgcmV0dXJuICdtb3VzZS1wb2ludGVyJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHJldHVybiBsYWJlbENvbG9yc1tsYWJlbFR5cGVdICsgJyBtb3VzZS1wb2ludGVyJztcbiAgICAgIH1cblxuICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuXG4gICAgICAkc2NvcGUuZGVsZXRlUHJvbXB0ID0gKHNlbGVjdGVkKSA9PiB7XG4gICAgICAgIFVJLm11bHRpSXRlbUNvbmZpcm1BY3Rpb25EaWFsb2coPFVJLk11bHRpSXRlbUNvbmZpcm1BY3Rpb25PcHRpb25zPntcbiAgICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgICBpbmRleDogJyRuYW1lJyxcbiAgICAgICAgICBvbkNsb3NlOiAocmVzdWx0OmJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgZnVuY3Rpb24gZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIG5leHQpIHtcbiAgICAgICAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgICAgICAgZGVsZXRlRW50aXR5KG5leHQsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICB0aXRsZTogJ0RlbGV0ZSBJbWFnZSBSZXBvc2l0b3J5PycsXG4gICAgICAgICAgYWN0aW9uOiAnVGhlIGZvbGxvd2luZyBJbWFnZSBSZXBvc2l0b3JpZXMgd2lsbCBiZSBkZWxldGVkOicsXG4gICAgICAgICAgb2tUZXh0OiAnRGVsZXRlJyxcbiAgICAgICAgICBva0NsYXNzOiAnYnRuLWRhbmdlcicsXG4gICAgICAgICAgY3VzdG9tOiBcIlRoaXMgb3BlcmF0aW9uIGlzIHBlcm1hbmVudCBvbmNlIGNvbXBsZXRlZCFcIixcbiAgICAgICAgICBjdXN0b21DbGFzczogXCJhbGVydCBhbGVydC13YXJuaW5nXCJcbiAgICAgICAgfSkub3BlbigpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gZGVsZXRlRW50aXR5KHNlbGVjdGlvbiwgbmV4dENhbGxiYWNrKSB7XG4gICAgICAgIHZhciBuYW1lID0gKHNlbGVjdGlvbiB8fCB7fSkuJG5hbWU7XG4gICAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBYm91dCB0byBkZWxldGUgaW1hZ2UgcmVwb3NpdG9yeTogXCIgKyBuYW1lKTtcbiAgICAgICAgICB2YXIgdXJsID0gaW1hZ2VSZXBvc2l0b3J5UmVzdFVybChuYW1lKTtcbiAgICAgICAgICAkaHR0cC5kZWxldGUodXJsKS5cbiAgICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICAgIG5leHRDYWxsYmFjaygpO1xuICAgICAgICAgICAgfSkuXG4gICAgICAgICAgICBlcnJvcihmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gZGVsZXRlIGltYWdlIHJlcG9zaXRvcnkgb24gXCIgKyB1cmwgKyBcIiBcIiArIGRhdGEgKyBcIiBcIiArIHN0YXR1cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIndhcm5pbmc6IG5vIG5hbWUgZm9yIHNlbGVjdGlvbjogXCIgKyBhbmd1bGFyLnRvSnNvbihzZWxlY3Rpb24pKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB1cGRhdGVEYXRhKCkge1xuICAgICAgICB2YXIgdXJsID0gaW1hZ2VSZXBvc2l0b3JpZXNSZXN0VVJMKCk7XG4gICAgICAgICRodHRwLmdldCh1cmwpLlxuICAgICAgICAgIHN1Y2Nlc3MoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiZ290IGRhdGEgXCIgKyBhbmd1bGFyLnRvSnNvbihkYXRhLCB0cnVlKSk7XG4gICAgICAgICAgICAgICRzY29wZS5pbWFnZVJlcG9zaXRvcmllcyA9IGVucmljaEltYWdlUmVwb3NpdG9yaWVzKGRhdGEuaXRlbXMpO1xuICAgICAgICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkuXG4gICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB1cGRhdGVEYXRhKCk7XG4gICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIGV4cG9ydCBmdW5jdGlvbiBzZWxlY3RTdWJOYXZCYXIoJHNjb3BlLCB0YWJOYW1lLCBuZXdTdWJUYWJMYWJlbCkge1xuICAgIHZhciBmb3VuZFRhYiA9IG51bGw7XG4gICAgYW5ndWxhci5mb3JFYWNoKCRzY29wZS5zdWJUYWJDb25maWcsICh0YWIpID0+IHtcbiAgICAgIGlmICh0YWJOYW1lID09PSB0YWIubGFiZWwgfHwgdGFiTmFtZSA9PT0gdGFiLmlkKSB7XG4gICAgICAgIGZvdW5kVGFiID0gdGFiO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHZhciBicmVhZGNydW1iQ29uZmlnID0gJHNjb3BlLmJyZWFkY3J1bWJDb25maWc7XG4gICAgaWYgKGZvdW5kVGFiICYmIGJyZWFkY3J1bWJDb25maWcpIHtcbiAgICAgIGJyZWFkY3J1bWJDb25maWcucHVzaChmb3VuZFRhYik7XG4gICAgICAkc2NvcGUuc3ViVGFiQ29uZmlnID0gW1xuICAgICAgICB7XG4gICAgICAgICAgbGFiZWw6IG5ld1N1YlRhYkxhYmVsXG4gICAgICAgIH1cbiAgICAgIF07XG4gICAgfVxuXG4gIH1cblxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG4gXG4gIGV4cG9ydCB2YXIgc2NoZW1hID0gXG4gIHtcbiAgICBcImlkXCI6IFwiaHR0cDovL2ZhYnJpYzguaW8vZmFicmljOC92Mi9TY2hlbWEjXCIsXG4gICAgXCIkc2NoZW1hXCI6IFwiaHR0cDovL2pzb24tc2NoZW1hLm9yZy9zY2hlbWEjXCIsXG4gICAgXCJkZWZpbml0aW9uc1wiOiB7XG4gICAgICBcImFwaV9Sb290UGF0aHNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicGF0aHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJvb3RQYXRoc1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0FXU0VsYXN0aWNCbG9ja1N0b3JlVm9sdW1lU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImZzVHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJmaWxlIHN5c3RlbSB0eXBlIHRvIG1vdW50XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicGFydGl0aW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwYXJ0aXRpb24gb24gdGhlIGRpc2sgdG8gbW91bnQgKGUuZy5cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFkT25seVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmVhZC1vbmx5IGlmIHRydWVcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ2b2x1bWVJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1bmlxdWUgaWQgb2YgdGhlIFBEIHJlc291cmNlIGluIEFXUzsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvdm9sdW1lcy5tZCNhd3NlbGFzdGljYmxvY2tzdG9yZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkFXU0VsYXN0aWNCbG9ja1N0b3JlVm9sdW1lU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfQ2FwYWJpbGl0aWVzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFkZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFkZGVkIGNhcGFiaWxpdGllc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWRkZWQgY2FwYWJpbGl0aWVzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZHJvcFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImRyb3BlZCBjYXBhYmlsaXRpZXNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImRyb3BlZCBjYXBhYmlsaXRpZXNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5DYXBhYmlsaXRpZXNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19DZXBoRlNWb2x1bWVTb3VyY2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwibW9uaXRvcnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhIGNvbGxlY3Rpb24gb2YgQ2VwaCBtb25pdG9yc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYSBjb2xsZWN0aW9uIG9mIENlcGggbW9uaXRvcnNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFkT25seVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiQ2VwaCBmcyB0byBiZSBtb3VudGVkIHdpdGggcmVhZC1vbmx5IHBlcm1pc3Npb25zXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2VjcmV0RmlsZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwYXRoIHRvIHNlY3JldCBmb3IgcmFkb3MgdXNlcjsgZGVmYXVsdCBpcyAvZXRjL2NlcGgvdXNlci5zZWNyZXQ7IG9wdGlvbmFsXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2VjcmV0UmVmXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Mb2NhbE9iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTG9jYWxPYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInJhZG9zIHVzZXIgbmFtZTsgZGVmYXVsdCBpcyBhZG1pbjsgb3B0aW9uYWxcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5DZXBoRlNWb2x1bWVTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Db250YWluZXJcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXJnc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImNvbW1hbmQgYXJyYXk7IHRoZSBkb2NrZXIgaW1hZ2UncyBjbWQgaXMgdXNlZCBpZiB0aGlzIGlzIG5vdCBwcm92aWRlZDsgYXJndW1lbnRzIHRvIHRoZSBlbnRyeXBvaW50OyBjYW5ub3QgYmUgdXBkYXRlZDsgdmFyaWFibGUgcmVmZXJlbmNlcyAkKFZBUl9OQU1FKSBhcmUgZXhwYW5kZWQgdXNpbmcgdGhlIGNvbnRhaW5lcidzIGVudmlyb25tZW50IHZhcmlhYmxlczsgaWYgYSB2YXJpYWJsZSBjYW5ub3QgYmUgcmVzb2x2ZWRcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImNvbW1hbmQgYXJyYXk7IHRoZSBkb2NrZXIgaW1hZ2UncyBjbWQgaXMgdXNlZCBpZiB0aGlzIGlzIG5vdCBwcm92aWRlZDsgYXJndW1lbnRzIHRvIHRoZSBlbnRyeXBvaW50OyBjYW5ub3QgYmUgdXBkYXRlZDsgdmFyaWFibGUgcmVmZXJlbmNlcyAkKFZBUl9OQU1FKSBhcmUgZXhwYW5kZWQgdXNpbmcgdGhlIGNvbnRhaW5lcidzIGVudmlyb25tZW50IHZhcmlhYmxlczsgaWYgYSB2YXJpYWJsZSBjYW5ub3QgYmUgcmVzb2x2ZWRcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjb21tYW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZW50cnlwb2ludCBhcnJheTsgbm90IGV4ZWN1dGVkIHdpdGhpbiBhIHNoZWxsOyB0aGUgZG9ja2VyIGltYWdlJ3MgZW50cnlwb2ludCBpcyB1c2VkIGlmIHRoaXMgaXMgbm90IHByb3ZpZGVkOyBjYW5ub3QgYmUgdXBkYXRlZDsgdmFyaWFibGUgcmVmZXJlbmNlcyAkKFZBUl9OQU1FKSBhcmUgZXhwYW5kZWQgdXNpbmcgdGhlIGNvbnRhaW5lcidzIGVudmlyb25tZW50IHZhcmlhYmxlczsgaWYgYSB2YXJpYWJsZSBjYW5ub3QgYmUgcmVzb2x2ZWRcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImVudHJ5cG9pbnQgYXJyYXk7IG5vdCBleGVjdXRlZCB3aXRoaW4gYSBzaGVsbDsgdGhlIGRvY2tlciBpbWFnZSdzIGVudHJ5cG9pbnQgaXMgdXNlZCBpZiB0aGlzIGlzIG5vdCBwcm92aWRlZDsgY2Fubm90IGJlIHVwZGF0ZWQ7IHZhcmlhYmxlIHJlZmVyZW5jZXMgJChWQVJfTkFNRSkgYXJlIGV4cGFuZGVkIHVzaW5nIHRoZSBjb250YWluZXIncyBlbnZpcm9ubWVudCB2YXJpYWJsZXM7IGlmIGEgdmFyaWFibGUgY2Fubm90IGJlIHJlc29sdmVkXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZW52XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gc2V0IGluIHRoZSBjb250YWluZXI7IGNhbm5vdCBiZSB1cGRhdGVkXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VudlZhclwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbnZWYXJcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbWFnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJEb2NrZXIgaW1hZ2UgbmFtZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvaW1hZ2VzLm1kXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaW1hZ2VQdWxsUG9saWN5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImltYWdlIHB1bGwgcG9saWN5OyBvbmUgb2YgQWx3YXlzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGlmZWN5Y2xlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaWZlY3ljbGVcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpZmVjeWNsZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImxpdmVuZXNzUHJvYmVcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1Byb2JlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qcm9iZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGUgY29udGFpbmVyOyBtdXN0IGJlIGEgRE5TX0xBQkVMIGFuZCB1bmlxdWUgd2l0aGluIHRoZSBwb2Q7IGNhbm5vdCBiZSB1cGRhdGVkXCIsXG4gICAgICAgICAgICBcIm1heExlbmd0aFwiOiA2MyxcbiAgICAgICAgICAgIFwicGF0dGVyblwiOiBcIl5bYS16MC05XShbLWEtejAtOV0qW2EtejAtOV0pPyRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwb3J0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgcG9ydHMgdG8gZXhwb3NlIGZyb20gdGhlIGNvbnRhaW5lcjsgY2Fubm90IGJlIHVwZGF0ZWRcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfQ29udGFpbmVyUG9ydFwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJQb3J0XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVhZGluZXNzUHJvYmVcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1Byb2JlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qcm9iZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc291cmNlc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUmVzb3VyY2VSZXF1aXJlbWVudHNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlc291cmNlUmVxdWlyZW1lbnRzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2VjdXJpdHlDb250ZXh0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TZWN1cml0eUNvbnRleHRcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3VyaXR5Q29udGV4dFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0ZGluXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJXaGV0aGVyIHRoaXMgY29udGFpbmVyIHNob3VsZCBhbGxvY2F0ZSBhIGJ1ZmZlciBmb3Igc3RkaW4gaW4gdGhlIGNvbnRhaW5lciBydW50aW1lOyBkZWZhdWx0IGlzIGZhbHNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidGVybWluYXRpb25NZXNzYWdlUGF0aFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwYXRoIGF0IHdoaWNoIHRoZSBmaWxlIHRvIHdoaWNoIHRoZSBjb250YWluZXIncyB0ZXJtaW5hdGlvbiBtZXNzYWdlIHdpbGwgYmUgd3JpdHRlbiBpcyBtb3VudGVkIGludG8gdGhlIGNvbnRhaW5lcidzIGZpbGVzeXN0ZW07IG1lc3NhZ2Ugd3JpdHRlbiBpcyBpbnRlbmRlZCB0byBiZSBicmllZiBmaW5hbCBzdGF0dXNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0dHlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIldoZXRoZXIgdGhpcyBjb250YWluZXIgc2hvdWxkIGFsbG9jYXRlIGEgVFRZIGZvciBpdHNlbGZcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ2b2x1bWVNb3VudHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwb2Qgdm9sdW1lcyB0byBtb3VudCBpbnRvIHRoZSBjb250YWluZXIncyBmaWxlc3lzdGU7IGNhbm5vdCBiZSB1cGRhdGVkXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1ZvbHVtZU1vdW50XCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlZvbHVtZU1vdW50XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwid29ya2luZ0RpclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJjb250YWluZXIncyB3b3JraW5nIGRpcmVjdG9yeTsgZGVmYXVsdHMgdG8gaW1hZ2UncyBkZWZhdWx0OyBjYW5ub3QgYmUgdXBkYXRlZFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNvbnRhaW5lclwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0NvbnRhaW5lclBvcnRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY29udGFpbmVyUG9ydFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibnVtYmVyIG9mIHBvcnQgdG8gZXhwb3NlIG9uIHRoZSBwb2QncyBJUCBhZGRyZXNzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaG9zdElQXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImhvc3QgSVAgdG8gYmluZCB0aGUgcG9ydCB0b1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImhvc3RQb3J0XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJudW1iZXIgb2YgcG9ydCB0byBleHBvc2Ugb24gdGhlIGhvc3Q7IG1vc3QgY29udGFpbmVycyBkbyBub3QgbmVlZCB0aGlzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIGZvciB0aGUgcG9ydCB0aGF0IGNhbiBiZSByZWZlcnJlZCB0byBieSBzZXJ2aWNlczsgbXVzdCBiZSBhbiBJQU5BX1NWQ19OQU1FIGFuZCB1bmlxdWUgd2l0aGluIHRoZSBwb2RcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwcm90b2NvbFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwcm90b2NvbCBmb3IgcG9ydDsgbXVzdCBiZSBVRFAgb3IgVENQOyBUQ1AgaWYgdW5zcGVjaWZpZWRcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJQb3J0XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfQ29udGFpbmVyU3RhdGVcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicnVubmluZ1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfQ29udGFpbmVyU3RhdGVSdW5uaW5nXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJTdGF0ZVJ1bm5pbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0ZXJtaW5hdGVkXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Db250YWluZXJTdGF0ZVRlcm1pbmF0ZWRcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNvbnRhaW5lclN0YXRlVGVybWluYXRlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIndhaXRpbmdcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0NvbnRhaW5lclN0YXRlV2FpdGluZ1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ29udGFpbmVyU3RhdGVXYWl0aW5nXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ29udGFpbmVyU3RhdGVcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Db250YWluZXJTdGF0ZVJ1bm5pbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwic3RhcnRlZEF0XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRpbWUgYXQgd2hpY2ggdGhlIGNvbnRhaW5lciB3YXMgbGFzdCAocmUtKXN0YXJ0ZWRcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJTdGF0ZVJ1bm5pbmdcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Db250YWluZXJTdGF0ZVRlcm1pbmF0ZWRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY29udGFpbmVySURcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiY29udGFpbmVyJ3MgSUQgaW4gdGhlIGZvcm1hdCAnZG9ja2VyOi8vXFx1MDAzY2NvbnRhaW5lcl9pZFxcdTAwM2UnXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZXhpdENvZGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImV4aXQgc3RhdHVzIGZyb20gdGhlIGxhc3QgdGVybWluYXRpb24gb2YgdGhlIGNvbnRhaW5lclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImZpbmlzaGVkQXRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGltZSBhdCB3aGljaCB0aGUgY29udGFpbmVyIGxhc3QgdGVybWluYXRlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1lc3NhZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibWVzc2FnZSByZWdhcmRpbmcgdGhlIGxhc3QgdGVybWluYXRpb24gb2YgdGhlIGNvbnRhaW5lclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlYXNvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCIoYnJpZWYpIHJlYXNvbiBmcm9tIHRoZSBsYXN0IHRlcm1pbmF0aW9uIG9mIHRoZSBjb250YWluZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzaWduYWxcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInNpZ25hbCBmcm9tIHRoZSBsYXN0IHRlcm1pbmF0aW9uIG9mIHRoZSBjb250YWluZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdGFydGVkQXRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGltZSBhdCB3aGljaCBwcmV2aW91cyBleGVjdXRpb24gb2YgdGhlIGNvbnRhaW5lciBzdGFydGVkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ29udGFpbmVyU3RhdGVUZXJtaW5hdGVkXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfQ29udGFpbmVyU3RhdGVXYWl0aW5nXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcInJlYXNvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCIoYnJpZWYpIHJlYXNvbiB0aGUgY29udGFpbmVyIGlzIG5vdCB5ZXQgcnVubmluZ1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNvbnRhaW5lclN0YXRlV2FpdGluZ1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0NvbnRhaW5lclN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJjb250YWluZXJJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJjb250YWluZXIncyBJRCBpbiB0aGUgZm9ybWF0ICdkb2NrZXI6Ly9cXHUwMDNjY29udGFpbmVyX2lkXFx1MDAzZSc7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL2NvbnRhaW5lci1lbnZpcm9ubWVudC5tZCNjb250YWluZXItaW5mb3JtYXRpb25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbWFnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJpbWFnZSBvZiB0aGUgY29udGFpbmVyOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9pbWFnZXMubWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbWFnZUlEXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIklEIG9mIHRoZSBjb250YWluZXIncyBpbWFnZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImxhc3RTdGF0ZVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfQ29udGFpbmVyU3RhdGVcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNvbnRhaW5lclN0YXRlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSBjb250YWluZXI7IG11c3QgYmUgYSBETlNfTEFCRUwgYW5kIHVuaXF1ZSB3aXRoaW4gdGhlIHBvZDsgY2Fubm90IGJlIHVwZGF0ZWRcIixcbiAgICAgICAgICAgIFwibWF4TGVuZ3RoXCI6IDYzLFxuICAgICAgICAgICAgXCJwYXR0ZXJuXCI6IFwiXlthLXowLTldKFstYS16MC05XSpbYS16MC05XSk/JFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlYWR5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzcGVjaWZpZXMgd2hldGhlciB0aGUgY29udGFpbmVyIGhhcyBwYXNzZWQgaXRzIHJlYWRpbmVzcyBwcm9iZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc3RhcnRDb3VudFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIG51bWJlciBvZiB0aW1lcyB0aGUgY29udGFpbmVyIGhhcyBiZWVuIHJlc3RhcnRlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXRlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Db250YWluZXJTdGF0ZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ29udGFpbmVyU3RhdGVcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19FbXB0eURpclZvbHVtZVNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJtZWRpdW1cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidHlwZSBvZiBzdG9yYWdlIHVzZWQgdG8gYmFjayB0aGUgdm9sdW1lOyBtdXN0IGJlIGFuIGVtcHR5IHN0cmluZyAoZGVmYXVsdCkgb3IgTWVtb3J5OyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS92b2x1bWVzLm1kI2VtcHR5ZGlyXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW1wdHlEaXJWb2x1bWVTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19FbmRwb2ludEFkZHJlc3NcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiaXBcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiSVAgYWRkcmVzcyBvZiB0aGUgZW5kcG9pbnRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0YXJnZXRSZWZcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW5kcG9pbnRBZGRyZXNzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfRW5kcG9pbnRQb3J0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGlzIHBvcnRcIixcbiAgICAgICAgICAgIFwibWF4TGVuZ3RoXCI6IDYzLFxuICAgICAgICAgICAgXCJwYXR0ZXJuXCI6IFwiXlthLXowLTldKFstYS16MC05XSpbYS16MC05XSk/JFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBvcnRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInBvcnQgbnVtYmVyIG9mIHRoZSBlbmRwb2ludFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInByb3RvY29sXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInByb3RvY29sIGZvciB0aGlzIHBvcnQ7IG11c3QgYmUgVURQIG9yIFRDUDsgVENQIGlmIHVuc3BlY2lmaWVkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW5kcG9pbnRQb3J0XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfRW5kcG9pbnRTdWJzZXRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYWRkcmVzc2VzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiSVAgYWRkcmVzc2VzIHdoaWNoIG9mZmVyIHRoZSByZWxhdGVkIHBvcnRzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VuZHBvaW50QWRkcmVzc1wiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbmRwb2ludEFkZHJlc3NcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwb3J0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInBvcnQgbnVtYmVycyBhdmFpbGFibGUgb24gdGhlIHJlbGF0ZWQgSVAgYWRkcmVzc2VzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VuZHBvaW50UG9ydFwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbmRwb2ludFBvcnRcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbmRwb2ludFN1YnNldFwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0VuZHBvaW50c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiRW5kcG9pbnRzXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdWJzZXRzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic2V0cyBvZiBhZGRyZXNzZXMgYW5kIHBvcnRzIHRoYXQgY29tcHJpc2UgYSBzZXJ2aWNlXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VuZHBvaW50U3Vic2V0XCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkVuZHBvaW50U3Vic2V0XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW5kcG9pbnRzXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfRW5kcG9pbnRzTGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgZW5kcG9pbnRzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VuZHBvaW50c1wiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbmRwb2ludHNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiRW5kcG9pbnRzTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbmRwb2ludHNMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfRW52VmFyXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGU7IG11c3QgYmUgYSBDX0lERU5USUZJRVJcIixcbiAgICAgICAgICAgIFwicGF0dGVyblwiOiBcIl5bQS1aYS16X11bQS1aYS16MC05X10qJFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInZhbHVlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInZhbHVlIG9mIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZTsgZGVmYXVsdHMgdG8gZW1wdHkgc3RyaW5nOyB2YXJpYWJsZSByZWZlcmVuY2VzICQoVkFSX05BTUUpIGFyZSBleHBhbmRlZCB1c2luZyB0aGUgcHJldmlvdXNseSBkZWZpbmVkIGVudmlyb25tZW50IHZhcmlibGVzIGluIHRoZSBjb250YWluZXIgYW5kIGFueSBzZXJ2aWNlIGVudmlyb25tZW50IHZhcmlhYmxlczsgaWYgYSB2YXJpYWJsZSBjYW5ub3QgYmUgcmVzb2x2ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ2YWx1ZUZyb21cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VudlZhclNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW52VmFyU291cmNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW52VmFyXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfRW52VmFyU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImZpZWxkUmVmXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RGaWVsZFNlbGVjdG9yXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RGaWVsZFNlbGVjdG9yXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW52VmFyU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfRXZlbnRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY291bnRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBudW1iZXIgb2YgdGltZXMgdGhpcyBldmVudCBoYXMgb2NjdXJyZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJmaXJzdFRpbWVzdGFtcFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgdGltZSBhdCB3aGljaCB0aGUgZXZlbnQgd2FzIGZpcnN0IHJlY29yZGVkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaW52b2x2ZWRPYmplY3RcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkV2ZW50XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGFzdFRpbWVzdGFtcFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgdGltZSBhdCB3aGljaCB0aGUgbW9zdCByZWNlbnQgb2NjdXJyZW5jZSBvZiB0aGlzIGV2ZW50IHdhcyByZWNvcmRlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1lc3NhZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb24gb2YgdGhlIHN0YXR1cyBvZiB0aGlzIG9wZXJhdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVhc29uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInNob3J0XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic291cmNlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19FdmVudFNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRXZlbnRTb3VyY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FdmVudFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0V2ZW50TGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgZXZlbnRzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0V2ZW50XCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkV2ZW50XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkV2ZW50TGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FdmVudExpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19FdmVudFNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJjb21wb25lbnRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiY29tcG9uZW50IHRoYXQgZ2VuZXJhdGVkIHRoZSBldmVudFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImhvc3RcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGUgaG9zdCB3aGVyZSB0aGUgZXZlbnQgaXMgZ2VuZXJhdGVkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRXZlbnRTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19FeGVjQWN0aW9uXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNvbW1hbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJjb21tYW5kIGxpbmUgdG8gZXhlY3V0ZSBpbnNpZGUgdGhlIGNvbnRhaW5lcjsgd29ya2luZyBkaXJlY3RvcnkgZm9yIHRoZSBjb21tYW5kIGlzIHJvb3QgKCcvJykgaW4gdGhlIGNvbnRhaW5lcidzIGZpbGUgc3lzdGVtOyB0aGUgY29tbWFuZCBpcyBleGVjJ2RcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImNvbW1hbmQgbGluZSB0byBleGVjdXRlIGluc2lkZSB0aGUgY29udGFpbmVyOyB3b3JraW5nIGRpcmVjdG9yeSBmb3IgdGhlIGNvbW1hbmQgaXMgcm9vdCAoJy8nKSBpbiB0aGUgY29udGFpbmVyJ3MgZmlsZSBzeXN0ZW07IHRoZSBjb21tYW5kIGlzIGV4ZWMnZFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkV4ZWNBY3Rpb25cIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19HQ0VQZXJzaXN0ZW50RGlza1ZvbHVtZVNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmc1R5cGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZmlsZSBzeXN0ZW0gdHlwZSB0byBtb3VudFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBhcnRpdGlvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicGFydGl0aW9uIG9uIHRoZSBkaXNrIHRvIG1vdW50IChlLmcuXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicGROYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInVuaXF1ZSBuYW1lIG9mIHRoZSBQRCByZXNvdXJjZSBpbiBHQ0U7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3ZvbHVtZXMubWQjZ2NlcGVyc2lzdGVudGRpc2tcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFkT25seVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmVhZC1vbmx5IGlmIHRydWVcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5HQ0VQZXJzaXN0ZW50RGlza1ZvbHVtZVNvdXJjZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0dpdFJlcG9Wb2x1bWVTb3VyY2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicmVwb3NpdG9yeVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZXBvc2l0b3J5IFVSTFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJldmlzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImNvbW1pdCBoYXNoIGZvciB0aGUgc3BlY2lmaWVkIHJldmlzaW9uXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuR2l0UmVwb1ZvbHVtZVNvdXJjZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0dsdXN0ZXJmc1ZvbHVtZVNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJlbmRwb2ludHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZ2x1c3RlciBob3N0cyBlbmRwb2ludHMgbmFtZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9leGFtcGxlcy9nbHVzdGVyZnMvUkVBRE1FLm1kI2NyZWF0ZS1hLXBvZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBhdGhcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicGF0aCB0byBnbHVzdGVyIHZvbHVtZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9leGFtcGxlcy9nbHVzdGVyZnMvUkVBRE1FLm1kI2NyZWF0ZS1hLXBvZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlYWRPbmx5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJnbHVzdGVyZnMgdm9sdW1lIHRvIGJlIG1vdW50ZWQgd2l0aCByZWFkLW9ubHkgcGVybWlzc2lvbnM7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZXhhbXBsZXMvZ2x1c3RlcmZzL1JFQURNRS5tZCNjcmVhdGUtYS1wb2RcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5HbHVzdGVyZnNWb2x1bWVTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19IVFRQR2V0QWN0aW9uXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImhvc3RcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaG9zdG5hbWUgdG8gY29ubmVjdCB0bzsgZGVmYXVsdHMgdG8gcG9kIElQXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicGF0aFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwYXRoIHRvIGFjY2VzcyBvbiB0aGUgSFRUUCBzZXJ2ZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwb3J0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc191dGlsX0ludE9yU3RyaW5nXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5JbnRPclN0cmluZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNjaGVtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzY2hlbWUgdG8gY29ubmVjdCB3aXRoXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSFRUUEdldEFjdGlvblwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0hhbmRsZXJcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiZXhlY1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfRXhlY0FjdGlvblwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRXhlY0FjdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImh0dHBHZXRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0hUVFBHZXRBY3Rpb25cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhUVFBHZXRBY3Rpb25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0Y3BTb2NrZXRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1RDUFNvY2tldEFjdGlvblwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuVENQU29ja2V0QWN0aW9uXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFuZGxlclwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0hvc3RQYXRoVm9sdW1lU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcInBhdGhcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicGF0aCBvZiB0aGUgZGlyZWN0b3J5IG9uIHRoZSBob3N0OyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS92b2x1bWVzLm1kI2hvc3RwYXRoXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSG9zdFBhdGhWb2x1bWVTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19JU0NTSVZvbHVtZVNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmc1R5cGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZmlsZSBzeXN0ZW0gdHlwZSB0byBtb3VudFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImlxblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJpU0NTSSBRdWFsaWZpZWQgTmFtZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImx1blwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaXNjc2kgdGFyZ2V0IGx1biBudW1iZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFkT25seVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmVhZC1vbmx5IGlmIHRydWVcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0YXJnZXRQb3J0YWxcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaVNDU0kgdGFyZ2V0IHBvcnRhbFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLklTQ1NJVm9sdW1lU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTGlmZWN5Y2xlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcInBvc3RTdGFydFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfSGFuZGxlclwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFuZGxlclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInByZVN0b3BcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0hhbmRsZXJcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhbmRsZXJcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaWZlY3ljbGVcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19MaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBvYmplY3RzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX3J1bnRpbWVfUmF3RXh0ZW5zaW9uXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQmFzZUt1YmVybmV0ZXNMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTGlzdE1ldGFcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicmVzb3VyY2VWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhlIGludGVybmFsIHZlcnNpb24gb2YgdGhpcyBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCBieSBjbGllbnRzIHRvIGRldGVybWluZSB3aGVuIG9iamVjdHMgaGF2ZSBjaGFuZ2VkOyBwb3B1bGF0ZWQgYnkgdGhlIHN5c3RlbVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlbGZMaW5rXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlVSTCBmb3IgdGhlIG9iamVjdDsgcG9wdWxhdGVkIGJ5IHRoZSBzeXN0ZW1cIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX0xvYWRCYWxhbmNlckluZ3Jlc3NcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiaG9zdG5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaG9zdG5hbWUgb2YgaW5ncmVzcyBwb2ludFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImlwXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIklQIGFkZHJlc3Mgb2YgaW5ncmVzcyBwb2ludFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxvYWRCYWxhbmNlckluZ3Jlc3NcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Mb2FkQmFsYW5jZXJTdGF0dXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiaW5ncmVzc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxvYWQtYmFsYW5jZXIgaW5ncmVzcyBwb2ludHNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTG9hZEJhbGFuY2VySW5ncmVzc1wiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Mb2FkQmFsYW5jZXJJbmdyZXNzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTG9hZEJhbGFuY2VyU3RhdHVzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTG9jYWxPYmplY3RSZWZlcmVuY2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSByZWZlcmVudDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvaWRlbnRpZmllcnMubWQjbmFtZXNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Mb2NhbE9iamVjdFJlZmVyZW5jZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX01ldGFkYXRhRmlsZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmaWVsZFJlZlwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0RmllbGRTZWxlY3RvclwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0RmllbGRTZWxlY3RvclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIG5hbWUgb2YgdGhlIGZpbGUgdG8gYmUgY3JlYXRlZFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk1ldGFkYXRhRmlsZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX01ldGFkYXRhVm9sdW1lU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBtZXRhZGF0YSBmaWxlc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19NZXRhZGF0YUZpbGVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTWV0YWRhdGFGaWxlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTWV0YWRhdGFWb2x1bWVTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19ORlNWb2x1bWVTb3VyY2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicGF0aFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgcGF0aCB0aGF0IGlzIGV4cG9ydGVkIGJ5IHRoZSBORlMgc2VydmVyOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS92b2x1bWVzLm1kI25mc1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlYWRPbmx5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJmb3JjZXMgdGhlIE5GUyBleHBvcnQgdG8gYmUgbW91bnRlZCB3aXRoIHJlYWQtb25seSBwZXJtaXNzaW9uczsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvdm9sdW1lcy5tZCNuZnNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzZXJ2ZXJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIGhvc3RuYW1lIG9yIElQIGFkZHJlc3Mgb2YgdGhlIE5GUyBzZXJ2ZXI7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3ZvbHVtZXMubWQjbmZzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTkZTVm9sdW1lU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTmFtZXNwYWNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJOYW1lc3BhY2VcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNwZWNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05hbWVzcGFjZVNwZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5hbWVzcGFjZVNwZWNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdGF0dXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05hbWVzcGFjZVN0YXR1c1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZXNwYWNlU3RhdHVzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZXNwYWNlXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTmFtZXNwYWNlTGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIml0ZW1zIGlzIHRoZSBsaXN0IG9mIE5hbWVzcGFjZSBvYmplY3RzIGluIHRoZSBsaXN0OyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9uYW1lc3BhY2VzLm1kXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05hbWVzcGFjZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5OYW1lc3BhY2VcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiTmFtZXNwYWNlTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5OYW1lc3BhY2VMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTmFtZXNwYWNlU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmaW5hbGl6ZXJzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYW4gb3BhcXVlIGxpc3Qgb2YgdmFsdWVzIHRoYXQgbXVzdCBiZSBlbXB0eSB0byBwZXJtYW5lbnRseSByZW1vdmUgb2JqZWN0IGZyb20gc3RvcmFnZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL2Rlc2lnbi9uYW1lc3BhY2VzLm1kI2ZpbmFsaXplcnNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFuIG9wYXF1ZSBsaXN0IG9mIHZhbHVlcyB0aGF0IG11c3QgYmUgZW1wdHkgdG8gcGVybWFuZW50bHkgcmVtb3ZlIG9iamVjdCBmcm9tIHN0b3JhZ2U7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy9kZXNpZ24vbmFtZXNwYWNlcy5tZCNmaW5hbGl6ZXJzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZXNwYWNlU3BlY1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX05hbWVzcGFjZVN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJwaGFzZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwaGFzZSBpcyB0aGUgY3VycmVudCBsaWZlY3ljbGUgcGhhc2Ugb2YgdGhlIG5hbWVzcGFjZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL2Rlc2lnbi9uYW1lc3BhY2VzLm1kI3BoYXNlc1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5hbWVzcGFjZVN0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX05vZGVcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIk5vZGVcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNwZWNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05vZGVTcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Ob2RlU3BlY1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXR1c1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTm9kZVN0YXR1c1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTm9kZVN0YXR1c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5vZGVcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Ob2RlQWRkcmVzc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhZGRyZXNzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBub2RlIGFkZHJlc3NcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5vZGUgYWRkcmVzcyB0eXBlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTm9kZUFkZHJlc3NcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Ob2RlQ29uZGl0aW9uXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImxhc3RIZWFydGJlYXRUaW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxhc3QgdGltZSB3ZSBnb3QgYW4gdXBkYXRlIG9uIGEgZ2l2ZW4gY29uZGl0aW9uXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGFzdFRyYW5zaXRpb25UaW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxhc3QgdGltZSB0aGUgY29uZGl0aW9uIHRyYW5zaXQgZnJvbSBvbmUgc3RhdHVzIHRvIGFub3RoZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXNzYWdlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImh1bWFuIHJlYWRhYmxlIG1lc3NhZ2UgaW5kaWNhdGluZyBkZXRhaWxzIGFib3V0IGxhc3QgdHJhbnNpdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlYXNvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCIoYnJpZWYpIHJlYXNvbiBmb3IgdGhlIGNvbmRpdGlvbidzIGxhc3QgdHJhbnNpdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXR1c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzdGF0dXMgb2YgdGhlIGNvbmRpdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInR5cGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidHlwZSBvZiBub2RlIGNvbmRpdGlvblwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5vZGVDb25kaXRpb25cIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Ob2RlTGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2Ygbm9kZXNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTm9kZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Ob2RlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIk5vZGVMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5vZGVMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTm9kZVNwZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiZXh0ZXJuYWxJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJkZXByZWNhdGVkLiBFeHRlcm5hbCBJRCBhc3NpZ25lZCB0byB0aGUgbm9kZSBieSBzb21lIG1hY2hpbmUgZGF0YWJhc2UgKGUuZy4gYSBjbG91ZCBwcm92aWRlcikuIERlZmF1bHRzIHRvIG5vZGUgbmFtZSB3aGVuIGVtcHR5LlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBvZENJRFJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicG9kIElQIHJhbmdlIGFzc2lnbmVkIHRvIHRoZSBub2RlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicHJvdmlkZXJJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJJRCBvZiB0aGUgbm9kZSBhc3NpZ25lZCBieSB0aGUgY2xvdWQgcHJvdmlkZXIgaW4gdGhlIGZvcm1hdDogXFx1MDAzY1Byb3ZpZGVyTmFtZVxcdTAwM2U6Ly9cXHUwMDNjUHJvdmlkZXJTcGVjaWZpY05vZGVJRFxcdTAwM2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1bnNjaGVkdWxhYmxlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJkaXNhYmxlIHBvZCBzY2hlZHVsaW5nIG9uIHRoZSBub2RlOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvYWRtaW4vbm9kZS5tZCNtYW51YWwtbm9kZS1hZG1pbmlzdHJhdGlvblwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5vZGVTcGVjXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfTm9kZVN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhZGRyZXNzZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGFkZHJlc3NlcyByZWFjaGFibGUgdG8gdGhlIG5vZGU7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy9hZG1pbi9ub2RlLm1kI25vZGUtYWRkcmVzc2VzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05vZGVBZGRyZXNzXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5vZGVBZGRyZXNzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY2FwYWNpdHlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiY29tcHV0ZSByZXNvdXJjZSBjYXBhY2l0eSBvZiB0aGUgbm9kZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvY29tcHV0ZS1yZXNvdXJjZXMubWRcIixcbiAgICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfcmVzb3VyY2VfUXVhbnRpdHlcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJqYXZhLnV0aWwuTWFwXFx1MDAzY1N0cmluZyxpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlF1YW50aXR5XFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNvbmRpdGlvbnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIG5vZGUgY29uZGl0aW9ucyBvYnNlcnZlZDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL2FkbWluL25vZGUubWQjbm9kZS1jb25kaXRpb25cIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTm9kZUNvbmRpdGlvblwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Ob2RlQ29uZGl0aW9uXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibm9kZUluZm9cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05vZGVTeXN0ZW1JbmZvXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Ob2RlU3lzdGVtSW5mb1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBoYXNlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm1vc3QgcmVjZW50bHkgb2JzZXJ2ZWQgbGlmZWN5Y2xlIHBoYXNlIG9mIHRoZSBub2RlOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvYWRtaW4vbm9kZS5tZCNub2RlLXBoYXNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTm9kZVN0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX05vZGVTeXN0ZW1JbmZvXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImJvb3RJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJib290IGlkIGlzIHRoZSBib290LWlkIHJlcG9ydGVkIGJ5IHRoZSBub2RlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY29udGFpbmVyUnVudGltZVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiQ29udGFpbmVyIHJ1bnRpbWUgdmVyc2lvbiByZXBvcnRlZCBieSB0aGUgbm9kZSB0aHJvdWdoIHJ1bnRpbWUgcmVtb3RlIEFQSSAoZS5nLiBkb2NrZXI6Ly8xLjUuMClcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJrZXJuZWxWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIktlcm5lbCB2ZXJzaW9uIHJlcG9ydGVkIGJ5IHRoZSBub2RlIGZyb20gJ3VuYW1lIC1yJyAoZS5nLiAzLjE2LjAtMC5icG8uNC1hbWQ2NClcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJrdWJlUHJveHlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIkt1YmUtcHJveHkgdmVyc2lvbiByZXBvcnRlZCBieSB0aGUgbm9kZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImt1YmVsZXRWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIkt1YmVsZXQgdmVyc2lvbiByZXBvcnRlZCBieSB0aGUgbm9kZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1hY2hpbmVJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJtYWNoaW5lLWlkIHJlcG9ydGVkIGJ5IHRoZSBub2RlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwib3NJbWFnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJPUyBpbWFnZSB1c2VkIHJlcG9ydGVkIGJ5IHRoZSBub2RlIGZyb20gL2V0Yy9vcy1yZWxlYXNlIChlLmcuIERlYmlhbiBHTlUvTGludXggNyAod2hlZXp5KSlcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzeXN0ZW1VVUlEXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInN5c3RlbS11dWlkIHJlcG9ydGVkIGJ5IHRoZSBub2RlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTm9kZVN5c3RlbUluZm9cIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19PYmplY3RGaWVsZFNlbGVjdG9yXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidmVyc2lvbiBvZiB0aGUgc2NoZW1hIHRoYXQgZmllbGRQYXRoIGlzIHdyaXR0ZW4gaW4gdGVybXMgb2Y7IGRlZmF1bHRzIHRvIHYxXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZmllbGRQYXRoXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInBhdGggb2YgdGhlIGZpZWxkIHRvIHNlbGVjdCBpbiB0aGUgc3BlY2lmaWVkIEFQSSB2ZXJzaW9uXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0RmllbGRTZWxlY3RvclwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX09iamVjdE1ldGFcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYW5ub3RhdGlvbnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibWFwIG9mIHN0cmluZyBrZXlzIGFuZCB2YWx1ZXMgdGhhdCBjYW4gYmUgdXNlZCBieSBleHRlcm5hbCB0b29saW5nIHRvIHN0b3JlIGFuZCByZXRyaWV2ZSBhcmJpdHJhcnkgbWV0YWRhdGEgYWJvdXQgb2JqZWN0czsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvYW5ub3RhdGlvbnMubWRcIixcbiAgICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm1hcCBvZiBzdHJpbmcga2V5cyBhbmQgdmFsdWVzIHRoYXQgY2FuIGJlIHVzZWQgYnkgZXh0ZXJuYWwgdG9vbGluZyB0byBzdG9yZSBhbmQgcmV0cmlldmUgYXJiaXRyYXJ5IG1ldGFkYXRhIGFib3V0IG9iamVjdHM7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL2Fubm90YXRpb25zLm1kXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiamF2YS51dGlsLk1hcFxcdTAwM2NTdHJpbmcsU3RyaW5nXFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNyZWF0aW9uVGltZXN0YW1wXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlJGQyAzMzM5IGRhdGUgYW5kIHRpbWUgYXQgd2hpY2ggdGhlIG9iamVjdCB3YXMgY3JlYXRlZDsgcG9wdWxhdGVkIGJ5IHRoZSBzeXN0ZW1cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkZWxldGlvblRpbWVzdGFtcFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJSRkMgMzMzOSBkYXRlIGFuZCB0aW1lIGF0IHdoaWNoIHRoZSBvYmplY3Qgd2lsbCBiZSBkZWxldGVkOyBwb3B1bGF0ZWQgYnkgdGhlIHN5c3RlbSB3aGVuIGEgZ3JhY2VmdWwgZGVsZXRpb24gaXMgcmVxdWVzdGVkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZ2VuZXJhdGVOYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFuIG9wdGlvbmFsIHByZWZpeCB0byB1c2UgdG8gZ2VuZXJhdGUgYSB1bmlxdWUgbmFtZTsgaGFzIHRoZSBzYW1lIHZhbGlkYXRpb24gcnVsZXMgYXMgbmFtZTsgb3B0aW9uYWxcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJnZW5lcmF0aW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhIHNlcXVlbmNlIG51bWJlciByZXByZXNlbnRpbmcgYSBzcGVjaWZpYyBnZW5lcmF0aW9uIG9mIHRoZSBkZXNpcmVkIHN0YXRlOyBwb3B1bGF0ZWQgYnkgdGhlIHN5c3RlbTsgcmVhZC1vbmx5XCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiTG9uZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImxhYmVsc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJtYXAgb2Ygc3RyaW5nIGtleXMgYW5kIHZhbHVlcyB0aGF0IGNhbiBiZSB1c2VkIHRvIG9yZ2FuaXplIGFuZCBjYXRlZ29yaXplIG9iamVjdHM7IG1heSBtYXRjaCBzZWxlY3RvcnMgb2YgcmVwbGljYXRpb24gY29udHJvbGxlcnMgYW5kIHNlcnZpY2VzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9sYWJlbHMubWRcIixcbiAgICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm1hcCBvZiBzdHJpbmcga2V5cyBhbmQgdmFsdWVzIHRoYXQgY2FuIGJlIHVzZWQgdG8gb3JnYW5pemUgYW5kIGNhdGVnb3JpemUgb2JqZWN0czsgbWF5IG1hdGNoIHNlbGVjdG9ycyBvZiByZXBsaWNhdGlvbiBjb250cm9sbGVycyBhbmQgc2VydmljZXM7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL2xhYmVscy5tZFwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLFN0cmluZ1xcdTAwM2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInN0cmluZyB0aGF0IGlkZW50aWZpZXMgYW4gb2JqZWN0LiBNdXN0IGJlIHVuaXF1ZSB3aXRoaW4gYSBuYW1lc3BhY2U7IGNhbm5vdCBiZSB1cGRhdGVkOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9pZGVudGlmaWVycy5tZCNuYW1lc1wiLFxuICAgICAgICAgICAgXCJtYXhMZW5ndGhcIjogNjMsXG4gICAgICAgICAgICBcInBhdHRlcm5cIjogXCJeW2EtejAtOV0oWy1hLXowLTldKlthLXowLTldKT8kXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZXNwYWNlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5hbWVzcGFjZSBvZiB0aGUgb2JqZWN0OyBtdXN0IGJlIGEgRE5TX0xBQkVMOyBjYW5ub3QgYmUgdXBkYXRlZDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvbmFtZXNwYWNlcy5tZFwiLFxuICAgICAgICAgICAgXCJtYXhMZW5ndGhcIjogMjUzLFxuICAgICAgICAgICAgXCJwYXR0ZXJuXCI6IFwiXlthLXowLTldKFstYS16MC05XSpbYS16MC05XSk/KFxcXFwuW2EtejAtOV0oWy1hLXowLTldKlthLXowLTldKT8pKiRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGUgaW50ZXJuYWwgdmVyc2lvbiBvZiB0aGlzIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIGJ5IGNsaWVudHMgdG8gZGV0ZXJtaW5lIHdoZW4gb2JqZWN0cyBoYXZlIGNoYW5nZWQ7IHBvcHVsYXRlZCBieSB0aGUgc3lzdGVtXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2VsZkxpbmtcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiVVJMIGZvciB0aGUgb2JqZWN0OyBwb3B1bGF0ZWQgYnkgdGhlIHN5c3RlbVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVpZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1bmlxdWUgVVVJRCBhY3Jvc3Mgc3BhY2UgYW5kIHRpbWU7IHBvcHVsYXRlZCBieSB0aGUgc3lzdGVtOyByZWFkLW9ubHk7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL2lkZW50aWZpZXJzLm1kI3VpZHNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiQVBJIHZlcnNpb24gb2YgdGhlIHJlZmVyZW50XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZmllbGRQYXRoXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImlmIHJlZmVycmluZyB0byBhIHBpZWNlIG9mIGFuIG9iamVjdCBpbnN0ZWFkIG9mIGFuIGVudGlyZSBvYmplY3RcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImtpbmQgb2YgdGhlIHJlZmVyZW50OyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvZGV2ZWwvYXBpLWNvbnZlbnRpb25zLm1kI3R5cGVzLWtpbmRzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSByZWZlcmVudDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvaWRlbnRpZmllcnMubWQjbmFtZXNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuYW1lc3BhY2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZXNwYWNlIG9mIHRoZSByZWZlcmVudDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvbmFtZXNwYWNlcy5tZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc291cmNlVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzcGVjaWZpYyByZXNvdXJjZVZlcnNpb24gdG8gd2hpY2ggdGhpcyByZWZlcmVuY2UgaXMgbWFkZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVpZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1aWQgb2YgdGhlIHJlZmVyZW50OyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9pZGVudGlmaWVycy5tZCN1aWRzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUGVyc2lzdGVudFZvbHVtZVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3BlY1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZVNwZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBlcnNpc3RlbnRWb2x1bWVTcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19QZXJzaXN0ZW50Vm9sdW1lU3RhdHVzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5QZXJzaXN0ZW50Vm9sdW1lU3RhdHVzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUGVyc2lzdGVudFZvbHVtZUNsYWltXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19QZXJzaXN0ZW50Vm9sdW1lQ2xhaW1TcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5QZXJzaXN0ZW50Vm9sdW1lQ2xhaW1TcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19QZXJzaXN0ZW50Vm9sdW1lQ2xhaW1TdGF0dXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBlcnNpc3RlbnRWb2x1bWVDbGFpbVN0YXR1c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBlcnNpc3RlbnRWb2x1bWVDbGFpbVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbUxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhIGxpc3Qgb2YgcGVyc2lzdGVudCB2b2x1bWUgY2xhaW1zOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wZXJzaXN0ZW50LXZvbHVtZXMubWQjcGVyc2lzdGVudHZvbHVtZWNsYWltc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19QZXJzaXN0ZW50Vm9sdW1lQ2xhaW1cIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlBlcnNpc3RlbnRWb2x1bWVDbGFpbUxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltTGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbVNwZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYWNjZXNzTW9kZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgZGVzaXJlZCBhY2Nlc3MgbW9kZXMgdGhlIHZvbHVtZSBzaG91bGQgaGF2ZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvcGVyc2lzdGVudC12b2x1bWVzLm1kI2FjY2Vzcy1tb2Rlcy0xXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgZGVzaXJlZCBhY2Nlc3MgbW9kZXMgdGhlIHZvbHVtZSBzaG91bGQgaGF2ZTsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvcGVyc2lzdGVudC12b2x1bWVzLm1kI2FjY2Vzcy1tb2Rlcy0xXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVzb3VyY2VzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SZXNvdXJjZVJlcXVpcmVtZW50c1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUmVzb3VyY2VSZXF1aXJlbWVudHNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ2b2x1bWVOYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBiaW5kaW5nIHJlZmVyZW5jZSB0byB0aGUgcGVyc2lzdGVudCB2b2x1bWUgYmFja2luZyB0aGlzIGNsYWltXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltU3BlY1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbVN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhY2Nlc3NNb2Rlc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBhY3R1YWwgYWNjZXNzIG1vZGVzIHRoZSB2b2x1bWUgaGFzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wZXJzaXN0ZW50LXZvbHVtZXMubWQjYWNjZXNzLW1vZGVzLTFcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBhY3R1YWwgYWNjZXNzIG1vZGVzIHRoZSB2b2x1bWUgaGFzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wZXJzaXN0ZW50LXZvbHVtZXMubWQjYWNjZXNzLW1vZGVzLTFcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjYXBhY2l0eVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgYWN0dWFsIHJlc291cmNlcyB0aGUgdm9sdW1lIGhhc1wiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19yZXNvdXJjZV9RdWFudGl0eVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5RdWFudGl0eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLGlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcXHUwMDNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicGhhc2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIGN1cnJlbnQgcGhhc2Ugb2YgdGhlIGNsYWltXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltU3RhdHVzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZUNsYWltVm9sdW1lU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNsYWltTmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgbmFtZSBvZiB0aGUgY2xhaW0gaW4gdGhlIHNhbWUgbmFtZXNwYWNlIHRvIGJlIG1vdW50ZWQgYXMgYSB2b2x1bWU7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3BlcnNpc3RlbnQtdm9sdW1lcy5tZCNwZXJzaXN0ZW50dm9sdW1lY2xhaW1zXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVhZE9ubHlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm1vdW50IHZvbHVtZSBhcyByZWFkLW9ubHkgd2hlbiB0cnVlOyBkZWZhdWx0IGZhbHNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltVm9sdW1lU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZUxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHBlcnNpc3RlbnQgdm9sdW1lczsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvcGVyc2lzdGVudC12b2x1bWVzLm1kXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJQZXJzaXN0ZW50Vm9sdW1lTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5QZXJzaXN0ZW50Vm9sdW1lTGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVTb3VyY2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXdzRWxhc3RpY0Jsb2NrU3RvcmVcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0FXU0VsYXN0aWNCbG9ja1N0b3JlVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5BV1NFbGFzdGljQmxvY2tTdG9yZVZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNlcGhmc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfQ2VwaEZTVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5DZXBoRlNWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJnY2VQZXJzaXN0ZW50RGlza1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfR0NFUGVyc2lzdGVudERpc2tWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkdDRVBlcnNpc3RlbnREaXNrVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZ2x1c3RlcmZzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HbHVzdGVyZnNWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkdsdXN0ZXJmc1ZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImhvc3RQYXRoXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Ib3N0UGF0aFZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSG9zdFBhdGhWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpc2NzaVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfSVNDU0lWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLklTQ1NJVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmZzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19ORlNWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5GU1ZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJiZFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUkJEVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SQkRWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5QZXJzaXN0ZW50Vm9sdW1lU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZVNwZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYWNjZXNzTW9kZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGwgd2F5cyB0aGUgdm9sdW1lIGNhbiBiZSBtb3VudGVkOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wZXJzaXN0ZW50LXZvbHVtZXMubWQjYWNjZXNzLW1vZGVzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGwgd2F5cyB0aGUgdm9sdW1lIGNhbiBiZSBtb3VudGVkOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wZXJzaXN0ZW50LXZvbHVtZXMubWQjYWNjZXNzLW1vZGVzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiYXdzRWxhc3RpY0Jsb2NrU3RvcmVcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0FXU0VsYXN0aWNCbG9ja1N0b3JlVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5BV1NFbGFzdGljQmxvY2tTdG9yZVZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNhcGFjaXR5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImEgZGVzY3JpcHRpb24gb2YgdGhlIHBlcnNpc3RlbnQgdm9sdW1lJ3MgcmVzb3VyY2VzIGFuZCBjYXBhY2l0eXI7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3BlcnNpc3RlbnQtdm9sdW1lcy5tZCNjYXBhY2l0eVwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19yZXNvdXJjZV9RdWFudGl0eVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5RdWFudGl0eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLGlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcXHUwMDNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY2VwaGZzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19DZXBoRlNWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNlcGhGU1ZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNsYWltUmVmXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdjZVBlcnNpc3RlbnREaXNrXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HQ0VQZXJzaXN0ZW50RGlza1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuR0NFUGVyc2lzdGVudERpc2tWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJnbHVzdGVyZnNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0dsdXN0ZXJmc1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuR2x1c3RlcmZzVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaG9zdFBhdGhcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0hvc3RQYXRoVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Ib3N0UGF0aFZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImlzY3NpXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19JU0NTSVZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSVNDU0lWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuZnNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05GU1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTkZTVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicGVyc2lzdGVudFZvbHVtZVJlY2xhaW1Qb2xpY3lcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwid2hhdCBoYXBwZW5zIHRvIGEgdm9sdW1lIHdoZW4gcmVsZWFzZWQgZnJvbSBpdHMgY2xhaW07IFZhbGlkIG9wdGlvbnMgYXJlIFJldGFpbiAoZGVmYXVsdCkgYW5kIFJlY3ljbGUuICBSZWN5bGluZyBtdXN0IGJlIHN1cHBvcnRlZCBieSB0aGUgdm9sdW1lIHBsdWdpbiB1bmRlcmx5aW5nIHRoaXMgcGVyc2lzdGVudCB2b2x1bWUuIFNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3BlcnNpc3RlbnQtdm9sdW1lcy5tZCNyZWN5Y2xpbmctcG9saWN5XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmJkXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SQkRWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJCRFZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBlcnNpc3RlbnRWb2x1bWVTcGVjXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZVN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJtZXNzYWdlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImh1bWFuLXJlYWRhYmxlIG1lc3NhZ2UgaW5kaWNhdGluZyBkZXRhaWxzIGFib3V0IHdoeSB0aGUgdm9sdW1lIGlzIGluIHRoaXMgc3RhdGVcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwaGFzZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgY3VycmVudCBwaGFzZSBvZiBhIHBlcnNpc3RlbnQgdm9sdW1lOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wZXJzaXN0ZW50LXZvbHVtZXMubWQjcGhhc2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFzb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiKGJyaWVmKSByZWFzb24gdGhlIHZvbHVtZSBpcyBub3QgaXMgbm90IGF2YWlsYWJsZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBlcnNpc3RlbnRWb2x1bWVTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Qb2RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlBvZFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3BlY1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUG9kU3BlY1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUG9kU3BlY1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXR1c1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUG9kU3RhdHVzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RTdGF0dXNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Qb2RDb25kaXRpb25cIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInN0YXR1cyBvZiB0aGUgY29uZGl0aW9uXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJraW5kIG9mIHRoZSBjb25kaXRpb25cIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RDb25kaXRpb25cIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Qb2RMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBwb2RzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wb2RzLm1kXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BvZFwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUG9kTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUG9kU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhY3RpdmVEZWFkbGluZVNlY29uZHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcIkxvbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjb250YWluZXJzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBjb250YWluZXJzIGJlbG9uZ2luZyB0byB0aGUgcG9kOyBjYW5ub3QgYmUgdXBkYXRlZDsgY29udGFpbmVycyBjYW5ub3QgY3VycmVudGx5IGJlIGFkZGVkIG9yIHJlbW92ZWQ7IHRoZXJlIG11c3QgYmUgYXQgbGVhc3Qgb25lIGNvbnRhaW5lciBpbiBhIFBvZDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvY29udGFpbmVycy5tZFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Db250YWluZXJcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ29udGFpbmVyXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZG5zUG9saWN5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIkROUyBwb2xpY3kgZm9yIGNvbnRhaW5lcnMgd2l0aGluIHRoZSBwb2Q7IG9uZSBvZiAnQ2x1c3RlckZpcnN0JyBvciAnRGVmYXVsdCdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJob3N0XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImRlcHJlY2F0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJob3N0TmV0d29ya1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaG9zdCBuZXR3b3JraW5nIHJlcXVlc3RlZCBmb3IgdGhpcyBwb2RcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbWFnZVB1bGxTZWNyZXRzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiByZWZlcmVuY2VzIHRvIHNlY3JldHMgaW4gdGhlIHNhbWUgbmFtZXNwYWNlIGF2YWlsYWJsZSBmb3IgcHVsbGluZyB0aGUgY29udGFpbmVyIGltYWdlczsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvaW1hZ2VzLm1kI3NwZWNpZnlpbmctaW1hZ2VwdWxsc2VjcmV0cy1vbi1hLXBvZFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Mb2NhbE9iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Mb2NhbE9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5vZGVOYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5vZGUgcmVxdWVzdGVkIGZvciB0aGlzIHBvZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5vZGVTZWxlY3RvclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzZWxlY3RvciB3aGljaCBtdXN0IG1hdGNoIGEgbm9kZSdzIGxhYmVscyBmb3IgdGhlIHBvZCB0byBiZSBzY2hlZHVsZWQgb24gdGhhdCBub2RlOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9ub2RlLXNlbGVjdGlvbi9SRUFETUUubWRcIixcbiAgICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInNlbGVjdG9yIHdoaWNoIG11c3QgbWF0Y2ggYSBub2RlJ3MgbGFiZWxzIGZvciB0aGUgcG9kIHRvIGJlIHNjaGVkdWxlZCBvbiB0aGF0IG5vZGU7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL25vZGUtc2VsZWN0aW9uL1JFQURNRS5tZFwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLFN0cmluZ1xcdTAwM2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXN0YXJ0UG9saWN5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInJlc3RhcnQgcG9saWN5IGZvciBhbGwgY29udGFpbmVycyB3aXRoaW4gdGhlIHBvZDsgb25lIG9mIEFsd2F5c1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlcnZpY2VBY2NvdW50XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImRlcHJlY2F0ZWQ7IHVzZSBzZXJ2aWNlQWNjb3VudE5hbWUgaW5zdGVhZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlcnZpY2VBY2NvdW50TmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSBTZXJ2aWNlQWNjb3VudCB0byB1c2UgdG8gcnVuIHRoaXMgcG9kOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvZGVzaWduL3NlcnZpY2VfYWNjb3VudHMubWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0ZXJtaW5hdGlvbkdyYWNlUGVyaW9kU2Vjb25kc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib3B0aW9uYWwgZHVyYXRpb24gaW4gc2Vjb25kcyB0aGUgcG9kIG5lZWRzIHRvIHRlcm1pbmF0ZSBncmFjZWZ1bGx5OyBtYXkgYmUgZGVjcmVhc2VkIGluIGRlbGV0ZSByZXF1ZXN0OyB2YWx1ZSBtdXN0IGJlIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyOyB0aGUgdmFsdWUgemVybyBpbmRpY2F0ZXMgZGVsZXRlIGltbWVkaWF0ZWx5OyBpZiB0aGlzIHZhbHVlIGlzIG5vdCBzZXRcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJMb25nXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidm9sdW1lc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2Ygdm9sdW1lcyB0aGF0IGNhbiBiZSBtb3VudGVkIGJ5IGNvbnRhaW5lcnMgYmVsb25naW5nIHRvIHRoZSBwb2Q7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3ZvbHVtZXMubWRcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfVm9sdW1lXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlZvbHVtZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBvZFNwZWNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Qb2RTdGF0dXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY29uZGl0aW9uc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImN1cnJlbnQgc2VydmljZSBzdGF0ZSBvZiBwb2Q7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3BvZC1zdGF0ZXMubWQjcG9kLWNvbmRpdGlvbnNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUG9kQ29uZGl0aW9uXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBvZENvbmRpdGlvblwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNvbnRhaW5lclN0YXR1c2VzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBjb250YWluZXIgc3RhdHVzZXM7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3BvZC1zdGF0ZXMubWQjY29udGFpbmVyLXN0YXR1c2VzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0NvbnRhaW5lclN0YXR1c1wiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJTdGF0dXNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJob3N0SVBcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiSVAgYWRkcmVzcyBvZiB0aGUgaG9zdCB0byB3aGljaCB0aGUgcG9kIGlzIGFzc2lnbmVkOyBlbXB0eSBpZiBub3QgeWV0IHNjaGVkdWxlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1lc3NhZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaHVtYW4gcmVhZGFibGUgbWVzc2FnZSBpbmRpY2F0aW5nIGRldGFpbHMgYWJvdXQgd2h5IHRoZSBwb2QgaXMgaW4gdGhpcyBjb25kaXRpb25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwaGFzZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJjdXJyZW50IGNvbmRpdGlvbiBvZiB0aGUgcG9kOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wb2Qtc3RhdGVzLm1kI3BvZC1waGFzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBvZElQXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIklQIGFkZHJlc3MgYWxsb2NhdGVkIHRvIHRoZSBwb2Q7IHJvdXRhYmxlIGF0IGxlYXN0IHdpdGhpbiB0aGUgY2x1c3RlcjsgZW1wdHkgaWYgbm90IHlldCBhbGxvY2F0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFzb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiKGJyaWVmLUNhbWVsQ2FzZSkgcmVhc29uIGluZGljYXRpbmcgZGV0YWlscyBhYm91dCB3aHkgdGhlIHBvZCBpcyBpbiB0aGlzIGNvbmRpdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXJ0VGltZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJSRkMgMzMzOSBkYXRlIGFuZCB0aW1lIGF0IHdoaWNoIHRoZSBvYmplY3Qgd2FzIGFja25vd2xlZGdlZCBieSB0aGUgS3ViZWxldC4gIFRoaXMgaXMgYmVmb3JlIHRoZSBLdWJlbGV0IHB1bGxlZCB0aGUgY29udGFpbmVyIGltYWdlKHMpIGZvciB0aGUgcG9kLlwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBvZFN0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1BvZFRlbXBsYXRlU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNwZWNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BvZFNwZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBvZFNwZWNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RUZW1wbGF0ZVNwZWNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Qcm9iZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJleGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19FeGVjQWN0aW9uXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FeGVjQWN0aW9uXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaHR0cEdldFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfSFRUUEdldEFjdGlvblwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSFRUUEdldEFjdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImluaXRpYWxEZWxheVNlY29uZHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm51bWJlciBvZiBzZWNvbmRzIGFmdGVyIHRoZSBjb250YWluZXIgaGFzIHN0YXJ0ZWQgYmVmb3JlIGxpdmVuZXNzIHByb2JlcyBhcmUgaW5pdGlhdGVkOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9wb2Qtc3RhdGVzLm1kI2NvbnRhaW5lci1wcm9iZXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJMb25nXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidGNwU29ja2V0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19UQ1BTb2NrZXRBY3Rpb25cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlRDUFNvY2tldEFjdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInRpbWVvdXRTZWNvbmRzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJudW1iZXIgb2Ygc2Vjb25kcyBhZnRlciB3aGljaCBsaXZlbmVzcyBwcm9iZXMgdGltZW91dDsgZGVmYXVsdHMgdG8gMSBzZWNvbmQ7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3BvZC1zdGF0ZXMubWQjY29udGFpbmVyLXByb2Jlc1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcIkxvbmdcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qcm9iZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1JCRFZvbHVtZVNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmc1R5cGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZmlsZSBzeXN0ZW0gdHlwZSB0byBtb3VudFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImltYWdlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInJhZG9zIGltYWdlIG5hbWU7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZXhhbXBsZXMvcmJkL1JFQURNRS5tZCNob3ctdG8tdXNlLWl0XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2V5cmluZ1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJrZXlyaW5nIGlzIHRoZSBwYXRoIHRvIGtleSByaW5nIGZvciByYWRvcyB1c2VyOyBkZWZhdWx0IGlzIC9ldGMvY2VwaC9rZXlyaW5nOyBvcHRpb25hbDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9leGFtcGxlcy9yYmQvUkVBRE1FLm1kI2hvdy10by11c2UtaXRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtb25pdG9yc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImEgY29sbGVjdGlvbiBvZiBDZXBoIG1vbml0b3JzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2V4YW1wbGVzL3JiZC9SRUFETUUubWQjaG93LXRvLXVzZS1pdFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYSBjb2xsZWN0aW9uIG9mIENlcGggbW9uaXRvcnM7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZXhhbXBsZXMvcmJkL1JFQURNRS5tZCNob3ctdG8tdXNlLWl0XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicG9vbFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyYWRvcyBwb29sIG5hbWU7IGRlZmF1bHQgaXMgcmJkOyBvcHRpb25hbDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9leGFtcGxlcy9yYmQvUkVBRE1FLm1kI2hvdy10by11c2UtaXRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFkT25seVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmJkIHZvbHVtZSB0byBiZSBtb3VudGVkIHdpdGggcmVhZC1vbmx5IHBlcm1pc3Npb25zOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2V4YW1wbGVzL3JiZC9SRUFETUUubWQjaG93LXRvLXVzZS1pdFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlY3JldFJlZlwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTG9jYWxPYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxvY2FsT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyYWRvcyB1c2VyIG5hbWU7IGRlZmF1bHQgaXMgYWRtaW47IG9wdGlvbmFsOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2V4YW1wbGVzL3JiZC9SRUFETUUubWQjaG93LXRvLXVzZS1pdFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJCRFZvbHVtZVNvdXJjZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1JlcGxpY2F0aW9uQ29udHJvbGxlclwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUmVwbGljYXRpb25Db250cm9sbGVyXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SZXBsaWNhdGlvbkNvbnRyb2xsZXJTcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXBsaWNhdGlvbkNvbnRyb2xsZXJTcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SZXBsaWNhdGlvbkNvbnRyb2xsZXJTdGF0dXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlcGxpY2F0aW9uQ29udHJvbGxlclN0YXR1c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlcGxpY2F0aW9uQ29udHJvbGxlclwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1JlcGxpY2F0aW9uQ29udHJvbGxlckxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHJlcGxpY2F0aW9uIGNvbnRyb2xsZXJzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9yZXBsaWNhdGlvbi1jb250cm9sbGVyLm1kXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1JlcGxpY2F0aW9uQ29udHJvbGxlclwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXBsaWNhdGlvbkNvbnRyb2xsZXJcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUmVwbGljYXRpb25Db250cm9sbGVyTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXBsaWNhdGlvbkNvbnRyb2xsZXJMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUmVwbGljYXRpb25Db250cm9sbGVyU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJyZXBsaWNhc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibnVtYmVyIG9mIHJlcGxpY2FzIGRlc2lyZWQ7IGRlZmF1bHRzIHRvIDE7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3JlcGxpY2F0aW9uLWNvbnRyb2xsZXIubWQjd2hhdC1pcy1hLXJlcGxpY2F0aW9uLWNvbnRyb2xsZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzZWxlY3RvclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsYWJlbCBrZXlzIGFuZCB2YWx1ZXMgdGhhdCBtdXN0IG1hdGNoIGluIG9yZGVyIHRvIGJlIGNvbnRyb2xsZWQgYnkgdGhpcyByZXBsaWNhdGlvbiBjb250cm9sbGVyXCIsXG4gICAgICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsYWJlbCBrZXlzIGFuZCB2YWx1ZXMgdGhhdCBtdXN0IG1hdGNoIGluIG9yZGVyIHRvIGJlIGNvbnRyb2xsZWQgYnkgdGhpcyByZXBsaWNhdGlvbiBjb250cm9sbGVyXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiamF2YS51dGlsLk1hcFxcdTAwM2NTdHJpbmcsU3RyaW5nXFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInRlbXBsYXRlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Qb2RUZW1wbGF0ZVNwZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBvZFRlbXBsYXRlU3BlY1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlcGxpY2F0aW9uQ29udHJvbGxlclNwZWNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19SZXBsaWNhdGlvbkNvbnRyb2xsZXJTdGF0dXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwib2JzZXJ2ZWRHZW5lcmF0aW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZWZsZWN0cyB0aGUgZ2VuZXJhdGlvbiBvZiB0aGUgbW9zdCByZWNlbnRseSBvYnNlcnZlZCByZXBsaWNhdGlvbiBjb250cm9sbGVyXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiTG9uZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlcGxpY2FzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJtb3N0IHJlY2VudGx5IG9iZXJ2ZWQgbnVtYmVyIG9mIHJlcGxpY2FzOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9yZXBsaWNhdGlvbi1jb250cm9sbGVyLm1kI3doYXQtaXMtYS1yZXBsaWNhdGlvbi1jb250cm9sbGVyXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUmVwbGljYXRpb25Db250cm9sbGVyU3RhdHVzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUmVzb3VyY2VRdW90YVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUmVzb3VyY2VRdW90YVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3BlY1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUmVzb3VyY2VRdW90YVNwZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlc291cmNlUXVvdGFTcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SZXNvdXJjZVF1b3RhU3RhdHVzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXNvdXJjZVF1b3RhU3RhdHVzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUmVzb3VyY2VRdW90YVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1Jlc291cmNlUXVvdGFMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaXRlbXMgaXMgYSBsaXN0IG9mIFJlc291cmNlUXVvdGEgb2JqZWN0czsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL2Rlc2lnbi9hZG1pc3Npb25fY29udHJvbF9yZXNvdXJjZV9xdW90YS5tZCNhZG1pc3Npb25jb250cm9sLXBsdWdpbi1yZXNvdXJjZXF1b3RhXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1Jlc291cmNlUXVvdGFcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUmVzb3VyY2VRdW90YVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJSZXNvdXJjZVF1b3RhTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXNvdXJjZVF1b3RhTGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1Jlc291cmNlUXVvdGFTcGVjXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImhhcmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaGFyZCBpcyB0aGUgc2V0IG9mIGRlc2lyZWQgaGFyZCBsaW1pdHMgZm9yIGVhY2ggbmFtZWQgcmVzb3VyY2U7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy9kZXNpZ24vYWRtaXNzaW9uX2NvbnRyb2xfcmVzb3VyY2VfcXVvdGEubWQjYWRtaXNzaW9uY29udHJvbC1wbHVnaW4tcmVzb3VyY2VxdW90YVwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19yZXNvdXJjZV9RdWFudGl0eVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5RdWFudGl0eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLGlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcXHUwMDNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUmVzb3VyY2VRdW90YVNwZWNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19SZXNvdXJjZVF1b3RhU3RhdHVzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImhhcmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaGFyZCBpcyB0aGUgc2V0IG9mIGVuZm9yY2VkIGhhcmQgbGltaXRzIGZvciBlYWNoIG5hbWVkIHJlc291cmNlOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvZGVzaWduL2FkbWlzc2lvbl9jb250cm9sX3Jlc291cmNlX3F1b3RhLm1kI2FkbWlzc2lvbmNvbnRyb2wtcGx1Z2luLXJlc291cmNlcXVvdGFcIixcbiAgICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfcmVzb3VyY2VfUXVhbnRpdHlcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJqYXZhLnV0aWwuTWFwXFx1MDAzY1N0cmluZyxpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlF1YW50aXR5XFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVzZWRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidXNlZCBpcyB0aGUgY3VycmVudCBvYnNlcnZlZCB0b3RhbCB1c2FnZSBvZiB0aGUgcmVzb3VyY2UgaW4gdGhlIG5hbWVzcGFjZVwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19yZXNvdXJjZV9RdWFudGl0eVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5RdWFudGl0eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLGlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcXHUwMDNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUmVzb3VyY2VRdW90YVN0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1Jlc291cmNlUmVxdWlyZW1lbnRzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImxpbWl0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJNYXhpbXVtIGFtb3VudCBvZiBjb21wdXRlIHJlc291cmNlcyBhbGxvd2VkOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvZGVzaWduL3Jlc291cmNlcy5tZCNyZXNvdXJjZS1zcGVjaWZpY2F0aW9uc1wiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19yZXNvdXJjZV9RdWFudGl0eVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5RdWFudGl0eVwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImphdmEudXRpbC5NYXBcXHUwMDNjU3RyaW5nLGlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcXHUwMDNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVxdWVzdHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiTWluaW11bSBhbW91bnQgb2YgcmVzb3VyY2VzIHJlcXVlc3RlZDsgaWYgUmVxdWVzdHMgaXMgb21pdHRlZCBmb3IgYSBjb250YWluZXJcIixcbiAgICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfcmVzb3VyY2VfUXVhbnRpdHlcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUXVhbnRpdHlcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJqYXZhLnV0aWwuTWFwXFx1MDAzY1N0cmluZyxpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlF1YW50aXR5XFx1MDAzZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlc291cmNlUmVxdWlyZW1lbnRzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfUnVuQXNVc2VyU3RyYXRlZ3lPcHRpb25zXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcInR5cGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic3RyYXRlZ3kgdXNlZCB0byBnZW5lcmF0ZSBSdW5Bc1VzZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1aWRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSB1aWQgdG8gYWx3YXlzIHJ1biBhczsgcmVxdWlyZWQgZm9yIE11c3RSdW5Bc1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcIkxvbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1aWRSYW5nZU1heFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibWF4IHZhbHVlIGZvciByYW5nZSBiYXNlZCBhbGxvY2F0b3JzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiTG9uZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVpZFJhbmdlTWluXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJtaW4gdmFsdWUgZm9yIHJhbmdlIGJhc2VkIGFsbG9jYXRvcnNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJMb25nXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUnVuQXNVc2VyU3RyYXRlZ3lPcHRpb25zXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU0VMaW51eENvbnRleHRTdHJhdGVneU9wdGlvbnNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwic2VMaW51eE9wdGlvbnNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1NFTGludXhPcHRpb25zXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TRUxpbnV4T3B0aW9uc1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInR5cGVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic3RyYXRlZ3kgdXNlZCB0byBnZW5lcmF0ZSB0aGUgU0VMaW51eCBjb250ZXh0XCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU0VMaW51eENvbnRleHRTdHJhdGVneU9wdGlvbnNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TRUxpbnV4T3B0aW9uc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJsZXZlbFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgbGV2ZWwgbGFiZWwgdG8gYXBwbHkgdG8gdGhlIGNvbnRhaW5lcjsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvbGFiZWxzLm1kXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicm9sZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgcm9sZSBsYWJlbCB0byBhcHBseSB0byB0aGUgY29udGFpbmVyOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9sYWJlbHMubWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSB0eXBlIGxhYmVsIHRvIGFwcGx5IHRvIHRoZSBjb250YWluZXI7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL2xhYmVscy5tZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVzZXJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIHVzZXIgbGFiZWwgdG8gYXBwbHkgdG8gdGhlIGNvbnRhaW5lcjsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvbGFiZWxzLm1kXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU0VMaW51eE9wdGlvbnNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TZWNyZXRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZGF0YVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJkYXRhIGNvbnRhaW5zIHRoZSBzZWNyZXQgZGF0YS4gIEVhY2gga2V5IG11c3QgYmUgYSB2YWxpZCBETlNfU1VCRE9NQUlOIG9yIGxlYWRpbmcgZG90IGZvbGxvd2VkIGJ5IHZhbGlkIEROU19TVUJET01BSU4uICBFYWNoIHZhbHVlIG11c3QgYmUgYSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgYXMgZGVzY3JpYmVkIGluIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM0NjQ4I3NlY3Rpb24tNFwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZGF0YSBjb250YWlucyB0aGUgc2VjcmV0IGRhdGEuICBFYWNoIGtleSBtdXN0IGJlIGEgdmFsaWQgRE5TX1NVQkRPTUFJTiBvciBsZWFkaW5nIGRvdCBmb2xsb3dlZCBieSB2YWxpZCBETlNfU1VCRE9NQUlOLiAgRWFjaCB2YWx1ZSBtdXN0IGJlIGEgYmFzZTY0IGVuY29kZWQgc3RyaW5nIGFzIGRlc2NyaWJlZCBpbiBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNDY0OCNzZWN0aW9uLTRcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJqYXZhLnV0aWwuTWFwXFx1MDAzY1N0cmluZyxTdHJpbmdcXHUwMDNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlNlY3JldFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0eXBlIGZhY2lsaXRhdGVzIHByb2dyYW1tYXRpYyBoYW5kbGluZyBvZiBzZWNyZXQgZGF0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3JldFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1NlY3JldExpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJpdGVtcyBpcyBhIGxpc3Qgb2Ygc2VjcmV0IG9iamVjdHM7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3NlY3JldHMubWRcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VjcmV0XCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3JldFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJTZWNyZXRMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3JldExpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TZWNyZXRWb2x1bWVTb3VyY2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwic2VjcmV0TmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzZWNyZXROYW1lIGlzIHRoZSBuYW1lIG9mIGEgc2VjcmV0IGluIHRoZSBwb2QncyBuYW1lc3BhY2U7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3ZvbHVtZXMubWQjc2VjcmV0c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3JldFZvbHVtZVNvdXJjZVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1NlY3VyaXR5Q29udGV4dFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJjYXBhYmlsaXRpZXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0NhcGFiaWxpdGllc1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ2FwYWJpbGl0aWVzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicHJpdmlsZWdlZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicnVuIHRoZSBjb250YWluZXIgaW4gcHJpdmlsZWdlZCBtb2RlOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvZGVzaWduL3NlY3VyaXR5X2NvbnRleHQubWQjc2VjdXJpdHktY29udGV4dFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJ1bkFzTm9uUm9vdFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaW5kaWNhdGVzIHRoZSBjb250YWluZXIgbXVzdCBiZSBydW4gYXMgYSBub24tcm9vdCB1c2VyIGVpdGhlciBieSBzcGVjaWZ5aW5nIHRoZSBydW5Bc1VzZXIgb3IgaW4gdGhlIGltYWdlIHNwZWNpZmljYXRpb25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJydW5Bc1VzZXJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSB1c2VyIGlkIHRoYXQgcnVucyB0aGUgZmlyc3QgcHJvY2VzcyBpbiB0aGUgY29udGFpbmVyOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvZGVzaWduL3NlY3VyaXR5X2NvbnRleHQubWQjc2VjdXJpdHktY29udGV4dFwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcIkxvbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzZUxpbnV4T3B0aW9uc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU0VMaW51eE9wdGlvbnNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNFTGludXhPcHRpb25zXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VjdXJpdHlDb250ZXh0XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU2VjdXJpdHlDb250ZXh0Q29uc3RyYWludHNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYWxsb3dIb3N0RGlyVm9sdW1lUGx1Z2luXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGxvdyB0aGUgdXNlIG9mIHRoZSBob3N0IGRpciB2b2x1bWUgcGx1Z2luXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiYWxsb3dIb3N0TmV0d29ya1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWxsb3cgdGhlIHVzZSBvZiB0aGUgaG9zdE5ldHdvcmsgaW4gdGhlIHBvZCBzcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiYWxsb3dIb3N0UG9ydHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFsbG93IHRoZSB1c2Ugb2YgdGhlIGhvc3QgcG9ydHMgaW4gdGhlIGNvbnRhaW5lcnNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJhbGxvd1ByaXZpbGVnZWRDb250YWluZXJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFsbG93IGNvbnRhaW5lcnMgdG8gcnVuIGFzIHByaXZpbGVnZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJhbGxvd2VkQ2FwYWJpbGl0aWVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiY2FwYWJpbGl0aWVzIHRoYXQgYXJlIGFsbG93ZWQgdG8gYmUgYWRkZWRcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImNhcGFiaWxpdGllcyB0aGF0IGFyZSBhbGxvd2VkIHRvIGJlIGFkZGVkXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZ3JvdXBzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZ3JvdXBzIGFsbG93ZWQgdG8gdXNlIHRoaXMgU2VjdXJpdHlDb250ZXh0Q29uc3RyYWludHNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImdyb3VwcyBhbGxvd2VkIHRvIHVzZSB0aGlzIFNlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlNlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJydW5Bc1VzZXJcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1J1bkFzVXNlclN0cmF0ZWd5T3B0aW9uc1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUnVuQXNVc2VyU3RyYXRlZ3lPcHRpb25zXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2VMaW51eENvbnRleHRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1NFTGludXhDb250ZXh0U3RyYXRlZ3lPcHRpb25zXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TRUxpbnV4Q29udGV4dFN0cmF0ZWd5T3B0aW9uc1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVzZXJzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidXNlcnMgYWxsb3dlZCB0byB1c2UgdGhpcyBTZWN1cml0eUNvbnRleHRDb25zdHJhaW50c1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidXNlcnMgYWxsb3dlZCB0byB1c2UgdGhpcyBTZWN1cml0eUNvbnRleHRDb25zdHJhaW50c1wiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU2VjdXJpdHlDb250ZXh0Q29uc3RyYWludHNMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1NlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlNlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZWN1cml0eUNvbnRleHRDb25zdHJhaW50c0xpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TZXJ2aWNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJTZXJ2aWNlXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TZXJ2aWNlU3BlY1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VydmljZVNwZWNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdGF0dXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1NlcnZpY2VTdGF0dXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlcnZpY2VTdGF0dXNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZXJ2aWNlXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU2VydmljZUFjY291bnRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaW1hZ2VQdWxsU2VjcmV0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgcmVmZXJlbmNlcyB0byBzZWNyZXRzIGluIHRoZSBzYW1lIG5hbWVzcGFjZSBhdmFpbGFibGUgZm9yIHB1bGxpbmcgY29udGFpbmVyIGltYWdlczsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvc2VjcmV0cy5tZCNtYW51YWxseS1zcGVjaWZ5aW5nLWFuLWltYWdlcHVsbHNlY3JldFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Mb2NhbE9iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Mb2NhbE9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJTZXJ2aWNlQWNjb3VudFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2VjcmV0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2Ygc2VjcmV0cyB0aGF0IGNhbiBiZSB1c2VkIGJ5IHBvZHMgcnVubmluZyBhcyB0aGlzIHNlcnZpY2UgYWNjb3VudDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvc2VjcmV0cy5tZFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VydmljZUFjY291bnRcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TZXJ2aWNlQWNjb3VudExpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIFNlcnZpY2VBY2NvdW50czsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL2Rlc2lnbi9zZXJ2aWNlX2FjY291bnRzLm1kI3NlcnZpY2UtYWNjb3VudHNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VydmljZUFjY291bnRcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VydmljZUFjY291bnRcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiU2VydmljZUFjY291bnRMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlcnZpY2VBY2NvdW50TGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1NlcnZpY2VMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBzZXJ2aWNlc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TZXJ2aWNlXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlcnZpY2VcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiU2VydmljZUxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VydmljZUxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TZXJ2aWNlUG9ydFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBuYW1lIG9mIHRoaXMgcG9ydDsgb3B0aW9uYWwgaWYgb25seSBvbmUgcG9ydCBpcyBkZWZpbmVkXCIsXG4gICAgICAgICAgICBcIm1heExlbmd0aFwiOiA2MyxcbiAgICAgICAgICAgIFwicGF0dGVyblwiOiBcIl5bYS16MC05XShbLWEtejAtOV0qW2EtejAtOV0pPyRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJub2RlUG9ydFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIHBvcnQgb24gZWFjaCBub2RlIG9uIHdoaWNoIHRoaXMgc2VydmljZSBpcyBleHBvc2VkIHdoZW4gdHlwZT1Ob2RlUG9ydCBvciBMb2FkQmFsYW5jZXI7IHVzdWFsbHkgYXNzaWduZWQgYnkgdGhlIHN5c3RlbTsgaWYgc3BlY2lmaWVkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicG9ydFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIHBvcnQgbnVtYmVyIHRoYXQgaXMgZXhwb3NlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInByb3RvY29sXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBwcm90b2NvbCB1c2VkIGJ5IHRoaXMgcG9ydDsgbXVzdCBiZSBVRFAgb3IgVENQOyBUQ1AgaWYgdW5zcGVjaWZpZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0YXJnZXRQb3J0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc191dGlsX0ludE9yU3RyaW5nXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5JbnRPclN0cmluZ1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlcnZpY2VQb3J0XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU2VydmljZVNwZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY2x1c3RlcklQXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIklQIGFkZHJlc3Mgb2YgdGhlIHNlcnZpY2U7IHVzdWFsbHkgYXNzaWduZWQgYnkgdGhlIHN5c3RlbTsgaWYgc3BlY2lmaWVkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZGVwcmVjYXRlZFB1YmxpY0lQc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImRlcHJlY2F0ZWQuIGV4dGVybmFsbHkgdmlzaWJsZSBJUHMgKGUuZy4gbG9hZCBiYWxhbmNlcnMpIHRoYXQgc2hvdWxkIGJlIHByb3hpZWQgdG8gdGhpcyBzZXJ2aWNlXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJkZXByZWNhdGVkLiBleHRlcm5hbGx5IHZpc2libGUgSVBzIChlLmcuIGxvYWQgYmFsYW5jZXJzKSB0aGF0IHNob3VsZCBiZSBwcm94aWVkIHRvIHRoaXMgc2VydmljZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBvcnRhbElQXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImRlcHJlY2F0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwb3J0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInBvcnRzIGV4cG9zZWQgYnkgdGhlIHNlcnZpY2U7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy91c2VyLWd1aWRlL3NlcnZpY2VzLm1kI3ZpcnR1YWwtaXBzLWFuZC1zZXJ2aWNlLXByb3hpZXNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VydmljZVBvcnRcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VydmljZVBvcnRcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzZWxlY3RvclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsYWJlbCBrZXlzIGFuZCB2YWx1ZXMgdGhhdCBtdXN0IG1hdGNoIGluIG9yZGVyIHRvIHJlY2VpdmUgdHJhZmZpYyBmb3IgdGhpcyBzZXJ2aWNlOyBpZiBlbXB0eVwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGFiZWwga2V5cyBhbmQgdmFsdWVzIHRoYXQgbXVzdCBtYXRjaCBpbiBvcmRlciB0byByZWNlaXZlIHRyYWZmaWMgZm9yIHRoaXMgc2VydmljZTsgaWYgZW1wdHlcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJqYXZhLnV0aWwuTWFwXFx1MDAzY1N0cmluZyxTdHJpbmdcXHUwMDNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2Vzc2lvbkFmZmluaXR5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImVuYWJsZSBjbGllbnQgSVAgYmFzZWQgc2Vzc2lvbiBhZmZpbml0eTsgbXVzdCBiZSBDbGllbnRJUCBvciBOb25lOyBkZWZhdWx0cyB0byBOb25lOyBzZWUgaHR0cDovL3JlbGVhc2VzLms4cy5pby9IRUFEL2RvY3MvdXNlci1ndWlkZS9zZXJ2aWNlcy5tZCN2aXJ0dWFsLWlwcy1hbmQtc2VydmljZS1wcm94aWVzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0eXBlIG9mIHRoaXMgc2VydmljZTsgbXVzdCBiZSBDbHVzdGVySVBcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZXJ2aWNlU3BlY1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1NlcnZpY2VTdGF0dXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwibG9hZEJhbGFuY2VyXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Mb2FkQmFsYW5jZXJTdGF0dXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxvYWRCYWxhbmNlclN0YXR1c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlcnZpY2VTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19TdGF0dXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY29kZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic3VnZ2VzdGVkIEhUVFAgcmV0dXJuIGNvZGUgZm9yIHRoaXMgc3RhdHVzOyAwIGlmIG5vdCBzZXRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkZXRhaWxzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TdGF0dXNEZXRhaWxzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TdGF0dXNEZXRhaWxzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlN0YXR1c1wiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1lc3NhZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb24gb2YgdGhlIHN0YXR1cyBvZiB0aGlzIG9wZXJhdGlvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFzb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibWFjaGluZS1yZWFkYWJsZSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhpcyBvcGVyYXRpb24gaXMgaW4gdGhlICdGYWlsdXJlJyBzdGF0dXM7IGlmIHRoaXMgdmFsdWUgaXMgZW1wdHkgdGhlcmUgaXMgbm8gaW5mb3JtYXRpb24gYXZhaWxhYmxlOyBhIHJlYXNvbiBjbGFyaWZpZXMgYW4gSFRUUCBzdGF0dXMgY29kZSBidXQgZG9lcyBub3Qgb3ZlcnJpZGUgaXRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdGF0dXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic3RhdHVzIG9mIHRoZSBvcGVyYXRpb247IGVpdGhlciBTdWNjZXNzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU3RhdHVzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU3RhdHVzQ2F1c2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiZmllbGRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZmllbGQgb2YgdGhlIHJlc291cmNlIHRoYXQgaGFzIGNhdXNlZCB0aGlzIGVycm9yXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWVzc2FnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJodW1hbi1yZWFkYWJsZSBkZXNjcmlwdGlvbiBvZiB0aGUgY2F1c2Ugb2YgdGhlIGVycm9yOyB0aGlzIGZpZWxkIG1heSBiZSBwcmVzZW50ZWQgYXMtaXMgdG8gYSByZWFkZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFzb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibWFjaGluZS1yZWFkYWJsZSBkZXNjcmlwdGlvbiBvZiB0aGUgY2F1c2Ugb2YgdGhlIGVycm9yOyBpZiB0aGlzIHZhbHVlIGlzIGVtcHR5IHRoZXJlIGlzIG5vIGluZm9ybWF0aW9uIGF2YWlsYWJsZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlN0YXR1c0NhdXNlXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfU3RhdHVzRGV0YWlsc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJjYXVzZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgQ2F1c2VzIGFycmF5IGluY2x1ZGVzIG1vcmUgZGV0YWlscyBhc3NvY2lhdGVkIHdpdGggdGhlIFN0YXR1c1JlYXNvbiBmYWlsdXJlOyBub3QgYWxsIFN0YXR1c1JlYXNvbnMgbWF5IHByb3ZpZGUgZGV0YWlsZWQgY2F1c2VzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1N0YXR1c0NhdXNlXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlN0YXR1c0NhdXNlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUga2luZCBhdHRyaWJ1dGUgb2YgdGhlIHJlc291cmNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3RhdHVzIFN0YXR1c1JlYXNvbjsgb24gc29tZSBvcGVyYXRpb25zIG1heSBkaWZmZXIgZnJvbSB0aGUgcmVxdWVzdGVkIHJlc291cmNlIEtpbmQ7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy9kZXZlbC9hcGktY29udmVudGlvbnMubWQjdHlwZXMta2luZHNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBuYW1lIGF0dHJpYnV0ZSBvZiB0aGUgcmVzb3VyY2UgYXNzb2NpYXRlZCB3aXRoIHRoZSBzdGF0dXMgU3RhdHVzUmVhc29uICh3aGVuIHRoZXJlIGlzIGEgc2luZ2xlIG5hbWUgd2hpY2ggY2FuIGJlIGRlc2NyaWJlZClcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXRyeUFmdGVyU2Vjb25kc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIG51bWJlciBvZiBzZWNvbmRzIGJlZm9yZSB0aGUgY2xpZW50IHNob3VsZCBhdHRlbXB0IHRvIHJldHJ5IHRoaXMgb3BlcmF0aW9uXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU3RhdHVzRGV0YWlsc1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1RDUFNvY2tldEFjdGlvblwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJwb3J0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc191dGlsX0ludE9yU3RyaW5nXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5JbnRPclN0cmluZ1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlRDUFNvY2tldEFjdGlvblwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX1R5cGVNZXRhXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidmVyc2lvbiBvZiB0aGUgc2NoZW1hIHRoZSBvYmplY3Qgc2hvdWxkIGhhdmU7IHNlZSBodHRwOi8vcmVsZWFzZXMuazhzLmlvL0hFQUQvZG9jcy9kZXZlbC9hcGktY29udmVudGlvbnMubWQjcmVzb3VyY2VzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJraW5kIG9mIG9iamVjdFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlR5cGVNZXRhXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfVm9sdW1lXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImF3c0VsYXN0aWNCbG9ja1N0b3JlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19BV1NFbGFzdGljQmxvY2tTdG9yZVZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQVdTRWxhc3RpY0Jsb2NrU3RvcmVWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjZXBoZnNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0NlcGhGU1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ2VwaEZTVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZW1wdHlEaXJcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VtcHR5RGlyVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbXB0eURpclZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdjZVBlcnNpc3RlbnREaXNrXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HQ0VQZXJzaXN0ZW50RGlza1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuR0NFUGVyc2lzdGVudERpc2tWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJnaXRSZXBvXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HaXRSZXBvVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5HaXRSZXBvVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZ2x1c3RlcmZzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HbHVzdGVyZnNWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkdsdXN0ZXJmc1ZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImhvc3RQYXRoXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Ib3N0UGF0aFZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSG9zdFBhdGhWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpc2NzaVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfSVNDU0lWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLklTQ1NJVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX01ldGFkYXRhVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5NZXRhZGF0YVZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidm9sdW1lIG5hbWU7IG11c3QgYmUgYSBETlNfTEFCRUwgYW5kIHVuaXF1ZSB3aXRoaW4gdGhlIHBvZDsgc2VlIGh0dHA6Ly9yZWxlYXNlcy5rOHMuaW8vSEVBRC9kb2NzL3VzZXItZ3VpZGUvaWRlbnRpZmllcnMubWQjbmFtZXNcIixcbiAgICAgICAgICAgIFwibWF4TGVuZ3RoXCI6IDYzLFxuICAgICAgICAgICAgXCJwYXR0ZXJuXCI6IFwiXlthLXowLTldKFstYS16MC05XSpbYS16MC05XSk/JFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5mc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTkZTVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5ORlNWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwZXJzaXN0ZW50Vm9sdW1lQ2xhaW1cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbVZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmJkXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SQkRWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJCRFZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlY3JldFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VjcmV0Vm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZWNyZXRWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Wb2x1bWVcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19Wb2x1bWVNb3VudFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJtb3VudFBhdGhcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicGF0aCB3aXRoaW4gdGhlIGNvbnRhaW5lciBhdCB3aGljaCB0aGUgdm9sdW1lIHNob3VsZCBiZSBtb3VudGVkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSB2b2x1bWUgdG8gbW91bnRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWFkT25seVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibW91bnRlZCByZWFkLW9ubHkgaWYgdHJ1ZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlZvbHVtZU1vdW50XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfVm9sdW1lU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImF3c0VsYXN0aWNCbG9ja1N0b3JlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19BV1NFbGFzdGljQmxvY2tTdG9yZVZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQVdTRWxhc3RpY0Jsb2NrU3RvcmVWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjZXBoZnNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0NlcGhGU1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQ2VwaEZTVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZW1wdHlEaXJcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VtcHR5RGlyVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbXB0eURpclZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdjZVBlcnNpc3RlbnREaXNrXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HQ0VQZXJzaXN0ZW50RGlza1ZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuR0NFUGVyc2lzdGVudERpc2tWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJnaXRSZXBvXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HaXRSZXBvVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5HaXRSZXBvVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZ2x1c3RlcmZzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19HbHVzdGVyZnNWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkdsdXN0ZXJmc1ZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImhvc3RQYXRoXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Ib3N0UGF0aFZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSG9zdFBhdGhWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpc2NzaVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfSVNDU0lWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLklTQ1NJVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX01ldGFkYXRhVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5NZXRhZGF0YVZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5mc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTkZTVm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5ORlNWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwZXJzaXN0ZW50Vm9sdW1lQ2xhaW1cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbVZvbHVtZVNvdXJjZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltVm9sdW1lU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmJkXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19SQkRWb2x1bWVTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJCRFZvbHVtZVNvdXJjZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlY3JldFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VjcmV0Vm9sdW1lU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZWNyZXRWb2x1bWVTb3VyY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Wb2x1bWVTb3VyY2VcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19jb25maWdfQXV0aEluZm9cIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY2xpZW50LWNlcnRpZmljYXRlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNsaWVudC1jZXJ0aWZpY2F0ZS1kYXRhXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNsaWVudC1rZXlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY2xpZW50LWtleS1kYXRhXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImV4dGVuc2lvbnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfY29uZmlnX05hbWVkRXh0ZW5zaW9uXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5hbWVkRXh0ZW5zaW9uXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicGFzc3dvcmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidG9rZW5cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlcm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuQXV0aEluZm9cIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19jb25maWdfQ2x1c3RlclwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGktdmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjZXJ0aWZpY2F0ZS1hdXRob3JpdHlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGFcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZXh0ZW5zaW9uc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19jb25maWdfTmFtZWRFeHRlbnNpb25cIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRFeHRlbnNpb25cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbnNlY3VyZS1za2lwLXRscy12ZXJpZnlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlcnZlclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5DbHVzdGVyXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfY29uZmlnX0NvbmZpZ1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNsdXN0ZXJzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX2NvbmZpZ19OYW1lZENsdXN0ZXJcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRDbHVzdGVyXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY29udGV4dHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfY29uZmlnX05hbWVkQ29udGV4dFwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5OYW1lZENvbnRleHRcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjdXJyZW50LWNvbnRleHRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZXh0ZW5zaW9uc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19jb25maWdfTmFtZWRFeHRlbnNpb25cIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRFeHRlbnNpb25cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInByZWZlcmVuY2VzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19jb25maWdfUHJlZmVyZW5jZXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlByZWZlcmVuY2VzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlcnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfY29uZmlnX05hbWVkQXV0aEluZm9cIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRBdXRoSW5mb1wiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNvbmZpZ1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX2NvbmZpZ19Db250ZXh0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNsdXN0ZXJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZXh0ZW5zaW9uc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19jb25maWdfTmFtZWRFeHRlbnNpb25cIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRFeHRlbnNpb25cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuYW1lc3BhY2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250ZXh0XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfY29uZmlnX05hbWVkQXV0aEluZm9cIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19jb25maWdfQXV0aEluZm9cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkF1dGhJbmZvXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRBdXRoSW5mb1wiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX2NvbmZpZ19OYW1lZENsdXN0ZXJcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY2x1c3RlclwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfY29uZmlnX0NsdXN0ZXJcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNsdXN0ZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5hbWVkQ2x1c3RlclwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX2NvbmZpZ19OYW1lZENvbnRleHRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY29udGV4dFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfY29uZmlnX0NvbnRleHRcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkNvbnRleHRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5hbWVkQ29udGV4dFwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX2NvbmZpZ19OYW1lZEV4dGVuc2lvblwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJleHRlbnNpb25cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX3J1bnRpbWVfUmF3RXh0ZW5zaW9uXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZWRFeHRlbnNpb25cIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc19jb25maWdfUHJlZmVyZW5jZXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY29sb3JzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJleHRlbnNpb25zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX2NvbmZpZ19OYW1lZEV4dGVuc2lvblwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5OYW1lZEV4dGVuc2lvblwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlByZWZlcmVuY2VzXCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfcmVzb3VyY2VfUXVhbnRpdHlcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiQW1vdW50XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvc3BldGVyX2luZl9EZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiRm9ybWF0XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlF1YW50aXR5XCJcbiAgICAgIH0sXG4gICAgICBcImt1YmVybmV0ZXNfcnVudGltZV9SYXdFeHRlbnNpb25cIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiUmF3SlNPTlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICB9LFxuICAgICAgXCJrdWJlcm5ldGVzX3V0aWxfSW50T3JTdHJpbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiSW50VmFsXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJLaW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJTdHJWYWxcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSW50T3JTdHJpbmdcIlxuICAgICAgfSxcbiAgICAgIFwia3ViZXJuZXRlc193YXRjaF9XYXRjaEV2ZW50XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcIm9iamVjdFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfcnVudGltZV9SYXdFeHRlbnNpb25cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgdHlwZSBvZiB3YXRjaCBldmVudDsgbWF5IGJlIEFEREVEXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuV2F0Y2hFdmVudFwiXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX0F1dGhvcml6YXRpb25BdHRyaWJ1dGVzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNvbnRlbnRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX3J1bnRpbWVfUmF3RXh0ZW5zaW9uXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVzcGFjZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lc3BhY2Ugb2YgdGhlIGFjdGlvbiBiZWluZyByZXF1ZXN0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvbmUgb2YgdGhlIGV4aXN0aW5nIHJlc291cmNlIHR5cGVzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVzb3VyY2VOYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5hbWUgb2YgdGhlIHJlc291cmNlIGJlaW5nIHJlcXVlc3RlZCBmb3IgYSBnZXQgb3IgZGVsZXRlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidmVyYlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvbmUgb2YgZ2V0XCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5BdXRob3JpemF0aW9uQXR0cmlidXRlc1wiXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX0NsdXN0ZXJQb2xpY3lcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkNsdXN0ZXJQb2xpY3lcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJsYXN0TW9kaWZpZWRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGFzdCB0aW1lIGFueSBwYXJ0IG9mIHRoZSBvYmplY3Qgd2FzIGNyZWF0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWxsIHRoZSByb2xlcyBoZWxkIGJ5IHRoaXMgcG9saWN5XCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX05hbWVkQ2x1c3RlclJvbGVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZENsdXN0ZXJSb2xlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5DbHVzdGVyUG9saWN5XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fQ2x1c3RlclBvbGljeUJpbmRpbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkNsdXN0ZXJQb2xpY3lCaW5kaW5nXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGFzdE1vZGlmaWVkXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxhc3QgdGltZSBhbnkgcGFydCBvZiB0aGUgb2JqZWN0IHdhcyBjcmVhdGVkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwb2xpY3lSZWZcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicm9sZUJpbmRpbmdzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWxsIHRoZSByb2xlIGJpbmRpbmdzIGhlbGQgYnkgdGhpcyBwb2xpY3lcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fTmFtZWRDbHVzdGVyUm9sZUJpbmRpbmdcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZENsdXN0ZXJSb2xlQmluZGluZ1wiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclBvbGljeUJpbmRpbmdcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUG9saWN5QmluZGluZ0xpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGNsdXN0ZXIgcG9saWN5IGJpbmRpbmdzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX0NsdXN0ZXJQb2xpY3lCaW5kaW5nXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclBvbGljeUJpbmRpbmdcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiQ2x1c3RlclBvbGljeUJpbmRpbmdMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclBvbGljeUJpbmRpbmdMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fQ2x1c3RlclBvbGljeUxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGNsdXN0ZXIgcG9saWNpZXNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fQ2x1c3RlclBvbGljeVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkNsdXN0ZXJQb2xpY3lcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiQ2x1c3RlclBvbGljeUxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5DbHVzdGVyUG9saWN5TGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX0NsdXN0ZXJSb2xlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJDbHVzdGVyUm9sZVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicnVsZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHBvbGljeSBydWxlc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9Qb2xpY3lSdWxlXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUG9saWN5UnVsZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclJvbGVcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUm9sZUJpbmRpbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZ3JvdXBOYW1lc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFsbCB0aGUgZ3JvdXBzIGRpcmVjdGx5IGJvdW5kIHRvIHRoZSByb2xlXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGwgdGhlIGdyb3VwcyBkaXJlY3RseSBib3VuZCB0byB0aGUgcm9sZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJDbHVzdGVyUm9sZUJpbmRpbmdcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVSZWZcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3ViamVjdHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZWZlcmVuY2VzIHRvIHN1YmplY3RzIGJvdW5kIHRvIHRoZSByb2xlLiAgT25seSBVc2VyXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyTmFtZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGwgdXNlciBuYW1lcyBkaXJlY3RseSBib3VuZCB0byB0aGUgcm9sZVwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWxsIHVzZXIgbmFtZXMgZGlyZWN0bHkgYm91bmQgdG8gdGhlIHJvbGVcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkNsdXN0ZXJSb2xlQmluZGluZ1wiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX0NsdXN0ZXJSb2xlQmluZGluZ0xpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGNsdXN0ZXIgcm9sZSBiaW5kaW5nc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUm9sZUJpbmRpbmdcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5DbHVzdGVyUm9sZUJpbmRpbmdcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiQ2x1c3RlclJvbGVCaW5kaW5nTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkNsdXN0ZXJSb2xlQmluZGluZ0xpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9Mb2NhbFN1YmplY3RBY2Nlc3NSZXZpZXdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiVHlwZU1ldGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1R5cGVNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5UeXBlTWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNvbnRlbnRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX3J1bnRpbWVfUmF3RXh0ZW5zaW9uXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdyb3Vwc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9wdGlvbmFsXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVzcGFjZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lc3BhY2Ugb2YgdGhlIGFjdGlvbiBiZWluZyByZXF1ZXN0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvbmUgb2YgdGhlIGV4aXN0aW5nIHJlc291cmNlIHR5cGVzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVzb3VyY2VOYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5hbWUgb2YgdGhlIHJlc291cmNlIGJlaW5nIHJlcXVlc3RlZCBmb3IgYSBnZXQgb3IgZGVsZXRlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlclwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInZlcmJcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib25lIG9mIGdldFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuTG9jYWxTdWJqZWN0QWNjZXNzUmV2aWV3XCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fTmFtZWRDbHVzdGVyUm9sZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5hbWUgb2YgdGhlIGNsdXN0ZXIgcm9sZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX0NsdXN0ZXJSb2xlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkNsdXN0ZXJSb2xlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZENsdXN0ZXJSb2xlXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fTmFtZWRDbHVzdGVyUm9sZUJpbmRpbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSBjbHVzdGVyIHJvbGUgYmluZGluZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVCaW5kaW5nXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUm9sZUJpbmRpbmdcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclJvbGVCaW5kaW5nXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZENsdXN0ZXJSb2xlQmluZGluZ1wiXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX05hbWVkUm9sZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5hbWUgb2YgdGhlIHJvbGVcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyb2xlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9Sb2xlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvbGVcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLk5hbWVkUm9sZVwiXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX05hbWVkUm9sZUJpbmRpbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRoZSByb2xlQmluZGluZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVCaW5kaW5nXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9Sb2xlQmluZGluZ1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb2xlQmluZGluZ1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuTmFtZWRSb2xlQmluZGluZ1wiXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX1BvbGljeVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUG9saWN5XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGFzdE1vZGlmaWVkXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxhc3QgdGltZSB0aGF0IGFueSBwYXJ0IG9mIHRoZSBwb2xpY3kgd2FzIGNyZWF0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicm9sZXMgaGVsZCBieSB0aGlzIHBvbGljeVwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9OYW1lZFJvbGVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZFJvbGVcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlBvbGljeVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX1BvbGljeUJpbmRpbmdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlBvbGljeUJpbmRpbmdcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJsYXN0TW9kaWZpZWRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGFzdCB0aW1lIHRoYXQgYW55IHBhcnQgb2YgdGhlIG9iamVjdCB3YXMgY3JlYXRlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicG9saWN5UmVmXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVCaW5kaW5nc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFsbCByb2xlQmluZGluZ3MgaGVsZCBieSB0aGlzIHBvbGljeUJpbmRpbmdcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fTmFtZWRSb2xlQmluZGluZ1wiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLk5hbWVkUm9sZUJpbmRpbmdcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlBvbGljeUJpbmRpbmdcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9Qb2xpY3lCaW5kaW5nTGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgcG9saWN5IGJpbmRpbmdzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX1BvbGljeUJpbmRpbmdcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qb2xpY3lCaW5kaW5nXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlBvbGljeUJpbmRpbmdMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUG9saWN5QmluZGluZ0xpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9Qb2xpY3lMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBwb2xpY2llc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9Qb2xpY3lcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qb2xpY3lcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUG9saWN5TGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlBvbGljeUxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9Qb2xpY3lSdWxlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImF0dHJpYnV0ZVJlc3RyaWN0aW9uc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfcnVudGltZV9SYXdFeHRlbnNpb25cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibm9uUmVzb3VyY2VVUkxzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic2V0IG9mIHBhcnRpYWwgdXJscyB0aGF0IGEgdXNlciBzaG91bGQgaGF2ZSBhY2Nlc3MgdG8uICpzIGFyZSBhbGxvd2VkXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzZXQgb2YgcGFydGlhbCB1cmxzIHRoYXQgYSB1c2VyIHNob3VsZCBoYXZlIGFjY2VzcyB0by4gKnMgYXJlIGFsbG93ZWRcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZU5hbWVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib3B0aW9uYWwgd2hpdGUgbGlzdCBvZiBuYW1lcyB0aGF0IHRoZSBydWxlIGFwcGxpZXMgdG8uICBBbiBlbXB0eSBzZXQgbWVhbnMgdGhhdCBldmVyeXRoaW5nIGlzIGFsbG93ZWQuXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbCB3aGl0ZSBsaXN0IG9mIG5hbWVzIHRoYXQgdGhlIHJ1bGUgYXBwbGllcyB0by4gIEFuIGVtcHR5IHNldCBtZWFucyB0aGF0IGV2ZXJ5dGhpbmcgaXMgYWxsb3dlZC5cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHJlc291cmNlcyB0aGlzIHJ1bGUgYXBwbGllcyB0by4gICogcmVwcmVzZW50cyBhbGwgcmVzb3VyY2VzLlwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiByZXNvdXJjZXMgdGhpcyBydWxlIGFwcGxpZXMgdG8uICAqIHJlcHJlc2VudHMgYWxsIHJlc291cmNlcy5cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ2ZXJic1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgdmVyYnMgdGhhdCBhcHBseSB0byBBTEwgdGhlIHJlc291cmNlS2luZHMgYW5kIGF0dHJpYnV0ZVJlc3RyaWN0aW9ucyBjb250YWluZWQgaW4gdGhpcyBydWxlLiAgVGhlIHZlcmIgKiByZXByZXNlbnRzIGFsbCBraW5kcy5cIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgdmVyYnMgdGhhdCBhcHBseSB0byBBTEwgdGhlIHJlc291cmNlS2luZHMgYW5kIGF0dHJpYnV0ZVJlc3RyaWN0aW9ucyBjb250YWluZWQgaW4gdGhpcyBydWxlLiAgVGhlIHZlcmIgKiByZXByZXNlbnRzIGFsbCBraW5kcy5cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlBvbGljeVJ1bGVcIlxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9Sb2xlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJSb2xlXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJydWxlc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFsbCB0aGUgcnVsZXMgZm9yIHRoaXMgcm9sZVwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9Qb2xpY3lSdWxlXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUG9saWN5UnVsZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUm9sZVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19hdXRob3JpemF0aW9uX1JvbGVCaW5kaW5nXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdyb3VwTmFtZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGwgdGhlIGdyb3VwcyBkaXJlY3RseSBib3VuZCB0byB0aGUgcm9sZVwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWxsIHRoZSBncm91cHMgZGlyZWN0bHkgYm91bmQgdG8gdGhlIHJvbGVcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUm9sZUJpbmRpbmdcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGVSZWZcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3ViamVjdHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZWZlcmVuY2VzIHRvIHN1YmplY3RzIGJvdW5kIHRvIHRoZSByb2xlLiAgT25seSBVc2VyXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyTmFtZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbGwgdGhlIHVzZXJuYW1lcyBkaXJlY3RseSBib3VuZCB0byB0aGUgcm9sZVwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYWxsIHRoZSB1c2VybmFtZXMgZGlyZWN0bHkgYm91bmQgdG8gdGhlIHJvbGVcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvbGVCaW5kaW5nXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fUm9sZUJpbmRpbmdMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiByb2xlIGJpbmRpbmdzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX1JvbGVCaW5kaW5nXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUm9sZUJpbmRpbmdcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiUm9sZUJpbmRpbmdMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUm9sZUJpbmRpbmdMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fUm9sZUxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHJvbGVzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX1JvbGVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb2xlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlJvbGVMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUm9sZUxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYXV0aG9yaXphdGlvbl9TdWJqZWN0QWNjZXNzUmV2aWV3XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNvbnRlbnRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX3J1bnRpbWVfUmF3RXh0ZW5zaW9uXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdyb3Vwc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9wdGlvbmFsXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJTdWJqZWN0QWNjZXNzUmV2aWV3XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZXNwYWNlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm5hbWVzcGFjZSBvZiB0aGUgYWN0aW9uIGJlaW5nIHJlcXVlc3RlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc291cmNlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9uZSBvZiB0aGUgZXhpc3RpbmcgcmVzb3VyY2UgdHlwZXNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZU5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGUgcmVzb3VyY2UgYmVpbmcgcmVxdWVzdGVkIGZvciBhIGdldCBvciBkZWxldGVcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9wdGlvbmFsXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidmVyYlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvbmUgb2YgZ2V0XCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5TdWJqZWN0QWNjZXNzUmV2aWV3XCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2F1dGhvcml6YXRpb25fU3ViamVjdEFjY2Vzc1Jldmlld1Jlc3BvbnNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFsbG93ZWRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRydWUgaWYgdGhlIGFjdGlvbiB3b3VsZCBiZSBhbGxvd2VkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlN1YmplY3RBY2Nlc3NSZXZpZXdSZXNwb25zZVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVzcGFjZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgbmFtZXNwYWNlIHVzZWQgZm9yIHRoZSBhY2Nlc3MgcmV2aWV3XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVhc29uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInJlYXNvbiBpcyBvcHRpb25hbFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuU3ViamVjdEFjY2Vzc1Jldmlld1Jlc3BvbnNlXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0J1aWxkXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJCdWlsZFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3BlY1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkU3BlY1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZFNwZWNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdGF0dXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9CdWlsZFN0YXR1c1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZFN0YXR1c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfQnVpbGRDb25maWdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkJ1aWxkQ29uZmlnXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYnVpbGRfQnVpbGRDb25maWdTcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkQ29uZmlnU3BlY1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXR1c1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkQ29uZmlnU3RhdHVzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkQ29uZmlnU3RhdHVzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZENvbmZpZ1wiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9CdWlsZENvbmZpZ0xpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGJ1aWxkIGNvbmZpZ3NcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkQ29uZmlnXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRDb25maWdcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiQnVpbGRDb25maWdMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRDb25maWdMaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0J1aWxkQ29uZmlnU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJvdXRwdXRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9CdWlsZE91dHB1dFwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZE91dHB1dFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc291cmNlc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUmVzb3VyY2VSZXF1aXJlbWVudHNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlc291cmNlUmVxdWlyZW1lbnRzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmV2aXNpb25cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9Tb3VyY2VSZXZpc2lvblwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Tb3VyY2VSZXZpc2lvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlcnZpY2VBY2NvdW50XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBuYW1lIG9mIHRoZSBzZXJ2aWNlIGFjY291bnQgdG8gdXNlIHRvIHJ1biBwb2RzIGNyZWF0ZWQgYnkgdGhlIGJ1aWxkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic291cmNlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYnVpbGRfQnVpbGRTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdHJhdGVneVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkU3RyYXRlZ3lcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTdHJhdGVneVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInRyaWdnZXJzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZGV0ZXJtaW5lcyBob3cgbmV3IGJ1aWxkcyBjYW4gYmUgbGF1bmNoZWQgZnJvbSBhIGJ1aWxkIGNvbmZpZy4gIGlmIG5vIHRyaWdnZXJzIGFyZSBkZWZpbmVkXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9CdWlsZFRyaWdnZXJQb2xpY3lcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZFRyaWdnZXJQb2xpY3lcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkQ29uZmlnU3BlY1wiXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9CdWlsZENvbmZpZ1N0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJsYXN0VmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidXNlZCB0byBpbmZvcm0gYWJvdXQgbnVtYmVyIG9mIGxhc3QgdHJpZ2dlcmVkIGJ1aWxkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZENvbmZpZ1N0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9CdWlsZExpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGJ1aWxkc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYnVpbGRfQnVpbGRcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJCdWlsZExpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZExpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfQnVpbGRPdXRwdXRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicHVzaFNlY3JldFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTG9jYWxPYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxvY2FsT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidG9cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZE91dHB1dFwiXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9CdWlsZFJlcXVlc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZnJvbVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiQnVpbGRSZXF1ZXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGFzdFZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIkxhc3RWZXJzaW9uIG9mIHRoZSBCdWlsZENvbmZpZyB0aGF0IHRyaWdnZXJlZCB0aGlzIGJ1aWxkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXZpc2lvblwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX1NvdXJjZVJldmlzaW9uXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlNvdXJjZVJldmlzaW9uXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHJpZ2dlcmVkQnlJbWFnZVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkUmVxdWVzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9CdWlsZFNvdXJjZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJjb250ZXh0RGlyXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInNwZWNpZmllcyBzdWItZGlyZWN0b3J5IHdoZXJlIHRoZSBzb3VyY2UgY29kZSBmb3IgdGhlIGFwcGxpY2F0aW9uIGV4aXN0c1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdpdFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0dpdEJ1aWxkU291cmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkdpdEJ1aWxkU291cmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic291cmNlU2VjcmV0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Mb2NhbE9iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTG9jYWxPYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInR5cGUgb2Ygc291cmNlIGNvbnRyb2wgbWFuYWdlbWVudCBzeXN0ZW1cIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0J1aWxkU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJvdXRwdXRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9CdWlsZE91dHB1dFwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5CdWlsZE91dHB1dFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc291cmNlc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUmVzb3VyY2VSZXF1aXJlbWVudHNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlc291cmNlUmVxdWlyZW1lbnRzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmV2aXNpb25cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9Tb3VyY2VSZXZpc2lvblwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Tb3VyY2VSZXZpc2lvblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlcnZpY2VBY2NvdW50XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBuYW1lIG9mIHRoZSBzZXJ2aWNlIGFjY291bnQgdG8gdXNlIHRvIHJ1biBwb2RzIGNyZWF0ZWQgYnkgdGhlIGJ1aWxkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic291cmNlXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYnVpbGRfQnVpbGRTb3VyY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTb3VyY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzdHJhdGVneVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkU3RyYXRlZ3lcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTdHJhdGVneVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTcGVjXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0J1aWxkU3RhdHVzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNhbmNlbGxlZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZGVzY3JpYmVzIGlmIGEgY2FuY2VsaW5nIGV2ZW50IHdhcyB0cmlnZ2VyZWQgZm9yIHRoZSBidWlsZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNvbXBsZXRpb25UaW1lc3RhbXBcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic2VydmVyIHRpbWUgd2hlbiB0aGUgcG9kIHJ1bm5pbmcgdGhpcyBidWlsZCBzdG9wcGVkIHJ1bm5pbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjb25maWdcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZHVyYXRpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFtb3VudCBvZiB0aW1lIHRoZSBidWlsZCBoYXMgYmVlbiBydW5uaW5nXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiTG9uZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1lc3NhZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaHVtYW4tcmVhZGFibGUgbWVzc2FnZSBpbmRpY2F0aW5nIGRldGFpbHMgYWJvdXQgd2h5IHRoZSBidWlsZCBoYXMgdGhpcyBzdGF0dXNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwaGFzZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvYnNlcnZlZCBwb2ludCBpbiB0aGUgYnVpbGQgbGlmZWN5Y2xlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhcnRUaW1lc3RhbXBcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic2VydmVyIHRpbWUgd2hlbiB0aGlzIGJ1aWxkIHN0YXJ0ZWQgcnVubmluZyBpbiBhIHBvZFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQnVpbGRTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfQnVpbGRTdHJhdGVneVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJjdXN0b21TdHJhdGVneVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0N1c3RvbUJ1aWxkU3RyYXRlZ3lcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ3VzdG9tQnVpbGRTdHJhdGVneVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImRvY2tlclN0cmF0ZWd5XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYnVpbGRfRG9ja2VyQnVpbGRTdHJhdGVneVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Eb2NrZXJCdWlsZFN0cmF0ZWd5XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic291cmNlU3RyYXRlZ3lcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9Tb3VyY2VCdWlsZFN0cmF0ZWd5XCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlNvdXJjZUJ1aWxkU3RyYXRlZ3lcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImlkZW50aWZpZXMgdGhlIHR5cGUgb2YgYnVpbGQgc3RyYXRlZ3lcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkU3RyYXRlZ3lcIlxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfQnVpbGRUcmlnZ2VyUG9saWN5XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImdlbmVyaWNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9XZWJIb29rVHJpZ2dlclwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5XZWJIb29rVHJpZ2dlclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImdpdGh1YlwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX1dlYkhvb2tUcmlnZ2VyXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLldlYkhvb2tUcmlnZ2VyXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaW1hZ2VDaGFuZ2VcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9JbWFnZUNoYW5nZVRyaWdnZXJcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VDaGFuZ2VUcmlnZ2VyXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0eXBlIG9mIGJ1aWxkIHRyaWdnZXJcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkVHJpZ2dlclBvbGljeVwiXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9DdXN0b21CdWlsZFN0cmF0ZWd5XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImVudlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFkZGl0aW9uYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzIHlvdSB3YW50IHRvIHBhc3MgaW50byBhIGJ1aWxkZXIgY29udGFpbmVyXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VudlZhclwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbnZWYXJcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJleHBvc2VEb2NrZXJTb2NrZXRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFsbG93IHJ1bm5pbmcgRG9ja2VyIGNvbW1hbmRzIChhbmQgYnVpbGQgRG9ja2VyIGltYWdlcykgZnJvbSBpbnNpZGUgdGhlIGNvbnRhaW5lclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImZvcmNlUHVsbFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZm9yY2VzIHB1bGxpbmcgb2YgYnVpbGRlciBpbWFnZSBmcm9tIHJlbW90ZSByZWdpc3RyeSBpZiB0cnVlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZnJvbVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwdWxsU2VjcmV0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Mb2NhbE9iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTG9jYWxPYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkN1c3RvbUJ1aWxkU3RyYXRlZ3lcIlxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfRG9ja2VyQnVpbGRTdHJhdGVneVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJlbnZcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhZGRpdGlvbmFsIGVudmlyb25tZW50IHZhcmlhYmxlcyB5b3Ugd2FudCB0byBwYXNzIGludG8gYSBidWlsZGVyIGNvbnRhaW5lclwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19FbnZWYXJcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW52VmFyXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZm9yY2VQdWxsXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJmb3JjZXMgdGhlIHNvdXJjZSBidWlsZCB0byBwdWxsIHRoZSBpbWFnZSBpZiB0cnVlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZnJvbVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJub0NhY2hlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJpZiB0cnVlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicHVsbFNlY3JldFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTG9jYWxPYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxvY2FsT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Eb2NrZXJCdWlsZFN0cmF0ZWd5XCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0dpdEJ1aWxkU291cmNlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImh0dHBQcm94eVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzcGVjaWZpZXMgYSBodHRwIHByb3h5IHRvIGJlIHVzZWQgZHVyaW5nIGdpdCBjbG9uZSBvcGVyYXRpb25zXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaHR0cHNQcm94eVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzcGVjaWZpZXMgYSBodHRwcyBwcm94eSB0byBiZSB1c2VkIGR1cmluZyBnaXQgY2xvbmUgb3BlcmF0aW9uc1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlZlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJpZGVudGlmaWVzIHRoZSBicmFuY2gvdGFnL3JlZiB0byBidWlsZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVyaVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwb2ludHMgdG8gdGhlIHNvdXJjZSB0aGF0IHdpbGwgYmUgYnVpbHRcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkdpdEJ1aWxkU291cmNlXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0dpdFNvdXJjZVJldmlzaW9uXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImF1dGhvclwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX1NvdXJjZUNvbnRyb2xVc2VyXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlNvdXJjZUNvbnRyb2xVc2VyXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY29tbWl0XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImhhc2ggaWRlbnRpZnlpbmcgYSBzcGVjaWZpYyBjb21taXRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjb21taXR0ZXJcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19idWlsZF9Tb3VyY2VDb250cm9sVXNlclwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Tb3VyY2VDb250cm9sVXNlclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1lc3NhZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZGVzY3JpcHRpb24gb2YgYSBzcGVjaWZpYyBjb21taXRcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkdpdFNvdXJjZVJldmlzaW9uXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX0ltYWdlQ2hhbmdlVHJpZ2dlclwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmcm9tXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImxhc3RUcmlnZ2VyZWRJbWFnZUlEXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInVzZWQgaW50ZXJuYWxseSB0byBzYXZlIGxhc3QgdXNlZCBpbWFnZSBJRCBmb3IgYnVpbGRcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkltYWdlQ2hhbmdlVHJpZ2dlclwiXG4gICAgICB9LFxuICAgICAgXCJvc19idWlsZF9Tb3VyY2VCdWlsZFN0cmF0ZWd5XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImVudlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFkZGl0aW9uYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzIHlvdSB3YW50IHRvIHBhc3MgaW50byBhIGJ1aWxkZXIgY29udGFpbmVyXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VudlZhclwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbnZWYXJcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJmb3JjZVB1bGxcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImZvcmNlcyB0aGUgc291cmNlIGJ1aWxkIHRvIHB1bGwgdGhlIGltYWdlIGlmIHRydWVcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJmcm9tXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImluY3JlbWVudGFsXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJmb3JjZXMgdGhlIHNvdXJjZSBidWlsZCB0byBkbyBpbmNyZW1lbnRhbCBidWlsZHMgaWYgdHJ1ZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInB1bGxTZWNyZXRcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xvY2FsT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Mb2NhbE9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNjcmlwdHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibG9jYXRpb24gb2YgdGhlIHNvdXJjZSBzY3JpcHRzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Tb3VyY2VCdWlsZFN0cmF0ZWd5XCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2J1aWxkX1NvdXJjZUNvbnRyb2xVc2VyXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImVtYWlsXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImUtbWFpbCBvZiB0aGUgc291cmNlIGNvbnRyb2wgdXNlclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGUgc291cmNlIGNvbnRyb2wgdXNlclwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuU291cmNlQ29udHJvbFVzZXJcIlxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfU291cmNlUmV2aXNpb25cIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiZ2l0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYnVpbGRfR2l0U291cmNlUmV2aXNpb25cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuR2l0U291cmNlUmV2aXNpb25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInR5cGUgb2YgdGhlIGJ1aWxkIHNvdXJjZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuU291cmNlUmV2aXNpb25cIlxuICAgICAgfSxcbiAgICAgIFwib3NfYnVpbGRfV2ViSG9va1RyaWdnZXJcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwic2VjcmV0XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInNlY3JldCB1c2VkIHRvIHZhbGlkYXRlIHJlcXVlc3RzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5XZWJIb29rVHJpZ2dlclwiXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfQ3VzdG9tRGVwbG95bWVudFN0cmF0ZWd5UGFyYW1zXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNvbW1hbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbGx5IG92ZXJyaWRlcyB0aGUgY29udGFpbmVyIGNvbW1hbmQgKGRlZmF1bHQgaXMgc3BlY2lmaWVkIGJ5IHRoZSBpbWFnZSlcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9wdGlvbmFsbHkgb3ZlcnJpZGVzIHRoZSBjb250YWluZXIgY29tbWFuZCAoZGVmYXVsdCBpcyBzcGVjaWZpZWQgYnkgdGhlIGltYWdlKVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImVudmlyb25tZW50XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZW52aXJvbm1lbnQgdmFyaWFibGVzIHByb3ZpZGVkIHRvIHRoZSBkZXBsb3ltZW50IHByb2Nlc3MgY29udGFpbmVyXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0VudlZhclwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbnZWYXJcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbWFnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhIERvY2tlciBpbWFnZSB3aGljaCBjYW4gY2Fycnkgb3V0IGEgZGVwbG95bWVudFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ3VzdG9tRGVwbG95bWVudFN0cmF0ZWd5UGFyYW1zXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2RlcGxveV9EZXBsb3ltZW50Q2F1c2VcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiaW1hZ2VUcmlnZ2VyXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfZGVwbG95X0RlcGxveW1lbnRDYXVzZUltYWdlVHJpZ2dlclwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50Q2F1c2VJbWFnZVRyaWdnZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSB0eXBlIG9mIHRyaWdnZXIgdGhhdCByZXN1bHRlZCBpbiBhIG5ldyBkZXBsb3ltZW50XCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50Q2F1c2VcIlxuICAgICAgfSxcbiAgICAgIFwib3NfZGVwbG95X0RlcGxveW1lbnRDYXVzZUltYWdlVHJpZ2dlclwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJmcm9tXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RSZWZlcmVuY2VcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdFJlZmVyZW5jZVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVwbG95bWVudENhdXNlSW1hZ2VUcmlnZ2VyXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2RlcGxveV9EZXBsb3ltZW50Q29uZmlnXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJEZXBsb3ltZW50Q29uZmlnXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfZGVwbG95X0RlcGxveW1lbnRDb25maWdTcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRDb25maWdTcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfZGVwbG95X0RlcGxveW1lbnRDb25maWdTdGF0dXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVwbG95bWVudENvbmZpZ1N0YXR1c1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVwbG95bWVudENvbmZpZ1wiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfRGVwbG95bWVudENvbmZpZ0xpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhIGxpc3Qgb2YgZGVwbG95bWVudCBjb25maWdzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19kZXBsb3lfRGVwbG95bWVudENvbmZpZ1wiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRDb25maWdcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiRGVwbG95bWVudENvbmZpZ0xpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50Q29uZmlnTGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfRGVwbG95bWVudENvbmZpZ1NwZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicmVwbGljYXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBkZXNpcmVkIG51bWJlciBvZiByZXBsaWNhc1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlbGVjdG9yXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImEgbGFiZWwgcXVlcnkgb3ZlciBwb2RzIHRoYXQgc2hvdWxkIG1hdGNoIHRoZSByZXBsaWNhcyBjb3VudFwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiYSBsYWJlbCBxdWVyeSBvdmVyIHBvZHMgdGhhdCBzaG91bGQgbWF0Y2ggdGhlIHJlcGxpY2FzIGNvdW50XCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiamF2YS51dGlsLk1hcFxcdTAwM2NTdHJpbmcsU3RyaW5nXFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0cmF0ZWd5XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfZGVwbG95X0RlcGxveW1lbnRTdHJhdGVneVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50U3RyYXRlZ3lcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0ZW1wbGF0ZVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUG9kVGVtcGxhdGVTcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Qb2RUZW1wbGF0ZVNwZWNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0cmlnZ2Vyc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImhvdyBuZXcgZGVwbG95bWVudHMgYXJlIHRyaWdnZXJlZFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfZGVwbG95X0RlcGxveW1lbnRUcmlnZ2VyUG9saWN5XCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVwbG95bWVudFRyaWdnZXJQb2xpY3lcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRDb25maWdTcGVjXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2RlcGxveV9EZXBsb3ltZW50Q29uZmlnU3RhdHVzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImRldGFpbHNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19kZXBsb3lfRGVwbG95bWVudERldGFpbHNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVwbG95bWVudERldGFpbHNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJsYXRlc3RWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImludGVnZXJcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIHRoZSBjdXJyZW50IGRlcGxveW1lbnQgaXMgb3V0IG9mIHN5bmNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRDb25maWdTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwib3NfZGVwbG95X0RlcGxveW1lbnREZXRhaWxzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNhdXNlc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImV4dGVuZGVkIGRhdGEgYXNzb2NpYXRlZCB3aXRoIGFsbCB0aGUgY2F1c2VzIGZvciBjcmVhdGluZyBhIG5ldyBkZXBsb3ltZW50XCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19kZXBsb3lfRGVwbG95bWVudENhdXNlXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVwbG95bWVudENhdXNlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWVzc2FnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhIHVzZXIgc3BlY2lmaWVkIGNoYW5nZSBtZXNzYWdlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50RGV0YWlsc1wiXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfRGVwbG95bWVudFN0cmF0ZWd5XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImN1c3RvbVBhcmFtc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2RlcGxveV9DdXN0b21EZXBsb3ltZW50U3RyYXRlZ3lQYXJhbXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ3VzdG9tRGVwbG95bWVudFN0cmF0ZWd5UGFyYW1zXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVjcmVhdGVQYXJhbXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19kZXBsb3lfUmVjcmVhdGVEZXBsb3ltZW50U3RyYXRlZ3lQYXJhbXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUmVjcmVhdGVEZXBsb3ltZW50U3RyYXRlZ3lQYXJhbXNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZXNvdXJjZXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1Jlc291cmNlUmVxdWlyZW1lbnRzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXNvdXJjZVJlcXVpcmVtZW50c1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJvbGxpbmdQYXJhbXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19kZXBsb3lfUm9sbGluZ0RlcGxveW1lbnRTdHJhdGVneVBhcmFtc1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb2xsaW5nRGVwbG95bWVudFN0cmF0ZWd5UGFyYW1zXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgbmFtZSBvZiBhIGRlcGxveW1lbnQgc3RyYXRlZ3lcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRTdHJhdGVneVwiXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfRGVwbG95bWVudFRyaWdnZXJJbWFnZUNoYW5nZVBhcmFtc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhdXRvbWF0aWNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIndoZXRoZXIgZGV0ZWN0aW9uIG9mIGEgbmV3IHRhZyB2YWx1ZSBzaG91bGQgdHJpZ2dlciBhIGRlcGxveW1lbnRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjb250YWluZXJOYW1lc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInJlc3RyaWN0cyB0YWcgdXBkYXRlcyB0byBhIHNldCBvZiBjb250YWluZXIgbmFtZXMgaW4gdGhlIHBvZFwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmVzdHJpY3RzIHRhZyB1cGRhdGVzIHRvIGEgc2V0IG9mIGNvbnRhaW5lciBuYW1lcyBpbiB0aGUgcG9kXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZnJvbVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJsYXN0VHJpZ2dlcmVkSW1hZ2VcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIGxhc3QgaW1hZ2UgdG8gYmUgdHJpZ2dlcmVkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50VHJpZ2dlckltYWdlQ2hhbmdlUGFyYW1zXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2RlcGxveV9EZXBsb3ltZW50VHJpZ2dlclBvbGljeVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJpbWFnZUNoYW5nZVBhcmFtc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2RlcGxveV9EZXBsb3ltZW50VHJpZ2dlckltYWdlQ2hhbmdlUGFyYW1zXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRUcmlnZ2VySW1hZ2VDaGFuZ2VQYXJhbXNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSB0eXBlIG9mIHRoZSB0cmlnZ2VyXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5EZXBsb3ltZW50VHJpZ2dlclBvbGljeVwiXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfRXhlY05ld1BvZEhvb2tcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY29tbWFuZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBob29rIGNvbW1hbmQgYW5kIGl0cyBhcmd1bWVudHNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBob29rIGNvbW1hbmQgYW5kIGl0cyBhcmd1bWVudHNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjb250YWluZXJOYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBuYW1lIG9mIGEgY29udGFpbmVyIGZyb20gdGhlIHBvZCB0ZW1wbGF0ZSB3aG9zZSBpbWFnZSB3aWxsIGJlIHVzZWQgZm9yIHRoZSBob29rIGNvbnRhaW5lclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImVudlwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImVudmlyb25tZW50IHZhcmlhYmxlcyBwcm92aWRlZCB0byB0aGUgaG9vayBjb250YWluZXJcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfRW52VmFyXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkVudlZhclwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRXhlY05ld1BvZEhvb2tcIlxuICAgICAgfSxcbiAgICAgIFwib3NfZGVwbG95X0xpZmVjeWNsZUhvb2tcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiZXhlY05ld1BvZFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2RlcGxveV9FeGVjTmV3UG9kSG9va1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5FeGVjTmV3UG9kSG9va1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImZhaWx1cmVQb2xpY3lcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwid2hhdCBhY3Rpb24gdG8gdGFrZSBpZiB0aGUgaG9vayBmYWlsc1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuTGlmZWN5Y2xlSG9va1wiXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfUmVjcmVhdGVEZXBsb3ltZW50U3RyYXRlZ3lQYXJhbXNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwicG9zdFwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2RlcGxveV9MaWZlY3ljbGVIb29rXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkxpZmVjeWNsZUhvb2tcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwcmVcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19kZXBsb3lfTGlmZWN5Y2xlSG9va1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5MaWZlY3ljbGVIb29rXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5SZWNyZWF0ZURlcGxveW1lbnRTdHJhdGVneVBhcmFtc1wiXG4gICAgICB9LFxuICAgICAgXCJvc19kZXBsb3lfUm9sbGluZ0RlcGxveW1lbnRTdHJhdGVneVBhcmFtc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJpbnRlcnZhbFNlY29uZHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSB0aW1lIHRvIHdhaXQgYmV0d2VlbiBwb2xsaW5nIGRlcGxveW1lbnQgc3RhdHVzIGFmdGVyIHVwZGF0ZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcIkxvbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwb3N0XCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfZGVwbG95X0xpZmVjeWNsZUhvb2tcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuTGlmZWN5Y2xlSG9va1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInByZVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2RlcGxveV9MaWZlY3ljbGVIb29rXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkxpZmVjeWNsZUhvb2tcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0aW1lb3V0U2Vjb25kc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIHRpbWUgdG8gd2FpdCBmb3IgdXBkYXRlcyBiZWZvcmUgZ2l2aW5nIHVwXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiTG9uZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVwZGF0ZVBlcmNlbnRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBwZXJjZW50YWdlIG9mIHJlcGxpY2FzIHRvIHNjYWxlIHVwIG9yIGRvd24gZWFjaCBpbnRlcnZhbCAobmVnYXRpdmUgdmFsdWUgc3dpdGNoZXMgc2NhbGUgb3JkZXIgdG8gZG93bi91cCBpbnN0ZWFkIG9mIHVwL2Rvd24pXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXBkYXRlUGVyaW9kU2Vjb25kc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidGhlIHRpbWUgdG8gd2FpdCBiZXR3ZWVuIGluZGl2aWR1YWwgcG9kIHVwZGF0ZXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJMb25nXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb2xsaW5nRGVwbG95bWVudFN0cmF0ZWd5UGFyYW1zXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2ltYWdlX0ltYWdlXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImRvY2tlckltYWdlTWFuaWZlc3RcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmF3IEpTT04gb2YgdGhlIG1hbmlmZXN0XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZG9ja2VySW1hZ2VNZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfcnVudGltZV9SYXdFeHRlbnNpb25cIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZG9ja2VySW1hZ2VNZXRhZGF0YVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiY29udmV5cyB2ZXJzaW9uIG9mIHRoZSBvYmplY3RcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkb2NrZXJJbWFnZVJlZmVyZW5jZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJzdHJpbmcgdGhhdCBjYW4gYmUgdXNlZCB0byBwdWxsIHRoaXMgaW1hZ2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiSW1hZ2VcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfaW1hZ2VfSW1hZ2VMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBpbWFnZSBvYmplY3RzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19pbWFnZV9JbWFnZVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkltYWdlXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIkltYWdlTGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkltYWdlTGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19pbWFnZV9JbWFnZVN0cmVhbVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiSW1hZ2VTdHJlYW1cIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNwZWNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19pbWFnZV9JbWFnZVN0cmVhbVNwZWNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VTdHJlYW1TcGVjXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic3RhdHVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfaW1hZ2VfSW1hZ2VTdHJlYW1TdGF0dXNcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VTdHJlYW1TdGF0dXNcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkltYWdlU3RyZWFtXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2ltYWdlX0ltYWdlU3RyZWFtTGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgaW1hZ2Ugc3RyZWFtIG9iamVjdHNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2ltYWdlX0ltYWdlU3RyZWFtXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VTdHJlYW1cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiSW1hZ2VTdHJlYW1MaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VTdHJlYW1MaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX2ltYWdlX0ltYWdlU3RyZWFtU3BlY1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJkb2NrZXJJbWFnZVJlcG9zaXRvcnlcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib3B0aW9uYWwgZmllbGQgaWYgc3BlY2lmaWVkIHRoaXMgc3RyZWFtIGlzIGJhY2tlZCBieSBhIERvY2tlciByZXBvc2l0b3J5IG9uIHRoaXMgc2VydmVyXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidGFnc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm1hcCBhcmJpdHJhcnkgc3RyaW5nIHZhbHVlcyB0byBzcGVjaWZpYyBpbWFnZSBsb2NhdG9yc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfaW1hZ2VfTmFtZWRUYWdSZWZlcmVuY2VcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZFRhZ1JlZmVyZW5jZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuSW1hZ2VTdHJlYW1TcGVjXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2ltYWdlX0ltYWdlU3RyZWFtU3RhdHVzXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImRvY2tlckltYWdlUmVwb3NpdG9yeVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZXByZXNlbnRzIHRoZSBlZmZlY3RpdmUgbG9jYXRpb24gdGhpcyBzdHJlYW0gbWF5IGJlIGFjY2Vzc2VkIGF0XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidGFnc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImhpc3RvcmljYWwgcmVjb3JkIG9mIGltYWdlcyBhc3NvY2lhdGVkIHdpdGggZWFjaCB0YWdcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2ltYWdlX05hbWVkVGFnRXZlbnRMaXN0XCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuTmFtZWRUYWdFdmVudExpc3RcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkltYWdlU3RyZWFtU3RhdHVzXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX2ltYWdlX05hbWVkVGFnRXZlbnRMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiB0YWcgZXZlbnRzIHJlbGF0ZWQgdG8gdGhlIHRhZ1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfaW1hZ2VfVGFnRXZlbnRcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UYWdFdmVudFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInRhZ1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgdGFnXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5OYW1lZFRhZ0V2ZW50TGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJvc19pbWFnZV9OYW1lZFRhZ1JlZmVyZW5jZVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhbm5vdGF0aW9uc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbm5vdGF0aW9ucyBhc3NvY2lhdGVkIHdpdGggaW1hZ2VzIHVzaW5nIHRoaXMgdGFnXCIsXG4gICAgICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJhbm5vdGF0aW9ucyBhc3NvY2lhdGVkIHdpdGggaW1hZ2VzIHVzaW5nIHRoaXMgdGFnXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiamF2YS51dGlsLk1hcFxcdTAwM2NTdHJpbmcsU3RyaW5nXFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImZyb21cIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJuYW1lIG9mIHRhZ1wiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuTmFtZWRUYWdSZWZlcmVuY2VcIlxuICAgICAgfSxcbiAgICAgIFwib3NfaW1hZ2VfVGFnRXZlbnRcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY3JlYXRlZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ3aGVuIHRoZSBldmVudCB3YXMgY3JlYXRlZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImRvY2tlckltYWdlUmVmZXJlbmNlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInRoZSBzdHJpbmcgdGhhdCBjYW4gYmUgdXNlZCB0byBwdWxsIHRoaXMgaW1hZ2VcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpbWFnZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ0aGUgaW1hZ2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlRhZ0V2ZW50XCJcbiAgICAgIH0sXG4gICAgICBcIm9zX29hdXRoX09BdXRoQWNjZXNzVG9rZW5cIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiYXV0aG9yaXplVG9rZW5cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiY29udGFpbnMgdGhlIHRva2VuIHRoYXQgYXV0aG9yaXplZCB0aGlzIHRva2VuXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiY2xpZW50TmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZWZlcmVuY2VzIHRoZSBjbGllbnQgdGhhdCBjcmVhdGVkIHRoaXMgdG9rZW5cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJleHBpcmVzSW5cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImlzIHRoZSBzZWNvbmRzIGZyb20gY3JlYXRpb24gdGltZSBiZWZvcmUgdGhpcyB0b2tlbiBleHBpcmVzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiTG9uZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJPQXV0aEFjY2Vzc1Rva2VuXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJyZWRpcmVjdFVSSVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJyZWRpcmVjdGlvbiBVUkkgYXNzb2NpYXRlZCB3aXRoIHRoZSB0b2tlblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlZnJlc2hUb2tlblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbCB2YWx1ZSBieSB3aGljaCB0aGlzIHRva2VuIGNhbiBiZSByZW5ld2VkXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwic2NvcGVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiByZXF1ZXN0ZWQgc2NvcGVzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHJlcXVlc3RlZCBzY29wZXNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyTmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1c2VyIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdG9rZW5cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ1c2VyVUlEXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInVuaXF1ZSBVSUQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdG9rZW5cIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLk9BdXRoQWNjZXNzVG9rZW5cIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3Nfb2F1dGhfT0F1dGhBY2Nlc3NUb2tlbkxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIG9hdXRoIGFjY2VzcyB0b2tlbnNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX29hdXRoX09BdXRoQWNjZXNzVG9rZW5cIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aEFjY2Vzc1Rva2VuXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIk9BdXRoQWNjZXNzVG9rZW5MaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhBY2Nlc3NUb2tlbkxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3Nfb2F1dGhfT0F1dGhBdXRob3JpemVUb2tlblwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjbGllbnROYW1lXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInJlZmVyZW5jZXMgdGhlIGNsaWVudCB0aGF0IGNyZWF0ZWQgdGhpcyB0b2tlblwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImV4cGlyZXNJblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic2Vjb25kcyBmcm9tIGNyZWF0aW9uIHRpbWUgYmVmb3JlIHRoaXMgdG9rZW4gZXhwaXJlc1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcIkxvbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiT0F1dGhBdXRob3JpemVUb2tlblwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVkaXJlY3RVUklcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmVkaXJlY3Rpb24gVVJJIGFzc29jaWF0ZWQgd2l0aCB0aGUgdG9rZW5cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzY29wZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHJlcXVlc3RlZCBzY29wZXNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgcmVxdWVzdGVkIHNjb3Blc1wiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXRlXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInN0YXRlIGRhdGEgZnJvbSByZXF1ZXN0XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlck5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidXNlciBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRva2VuXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlclVJRFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1bmlxdWUgVUlEIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRva2VuLiAgdXNlclVJRCBhbmQgdXNlck5hbWUgbXVzdCBib3RoIG1hdGNoIGZvciB0aGlzIHRva2VuIHRvIGJlIHZhbGlkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aEF1dGhvcml6ZVRva2VuXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX29hdXRoX09BdXRoQXV0aG9yaXplVG9rZW5MaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBvYXV0aCBhdXRob3JpemF0aW9uIHRva2Vuc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfb2F1dGhfT0F1dGhBdXRob3JpemVUb2tlblwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLk9BdXRoQXV0aG9yaXplVG9rZW5cIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiT0F1dGhBdXRob3JpemVUb2tlbkxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aEF1dGhvcml6ZVRva2VuTGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19vYXV0aF9PQXV0aENsaWVudFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiT0F1dGhDbGllbnRcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlZGlyZWN0VVJJc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInZhbGlkIHJlZGlyZWN0aW9uIFVSSXMgYXNzb2NpYXRlZCB3aXRoIGEgY2xpZW50XCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ2YWxpZCByZWRpcmVjdGlvbiBVUklzIGFzc29jaWF0ZWQgd2l0aCBhIGNsaWVudFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInJlc3BvbmRXaXRoQ2hhbGxlbmdlc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaW5kaWNhdGVzIHdoZXRoZXIgdGhlIGNsaWVudCB3YW50cyBhdXRoZW50aWNhdGlvbiBuZWVkZWQgcmVzcG9uc2VzIG1hZGUgaW4gdGhlIGZvcm0gb2YgY2hhbGxlbmdlcyBpbnN0ZWFkIG9mIHJlZGlyZWN0c1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInNlY3JldFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1bmlxdWUgc2VjcmV0IGFzc29jaWF0ZWQgd2l0aCBhIGNsaWVudFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhDbGllbnRcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkhhc01ldGFkYXRhXCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3Nfb2F1dGhfT0F1dGhDbGllbnRBdXRob3JpemF0aW9uXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImNsaWVudE5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwicmVmZXJlbmNlcyB0aGUgY2xpZW50IHRoYXQgY3JlYXRlZCB0aGlzIGF1dGhvcml6YXRpb25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiT0F1dGhDbGllbnRBdXRob3JpemF0aW9uXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzY29wZXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGdyYW50ZWQgc2NvcGVzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGdyYW50ZWQgc2NvcGVzXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidXNlck5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidXNlciBuYW1lIHRoYXQgYXV0aG9yaXplZCB0aGlzIGNsaWVudFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVzZXJVSURcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwidW5pcXVlIFVJRCBhc3NvY2lhdGVkIHdpdGggdGhpcyBhdXRob3JpemF0aW9uLiB1c2VyVUlEIGFuZCB1c2VyTmFtZSBtdXN0IGJvdGggbWF0Y2ggZm9yIHRoaXMgYXV0aG9yaXphdGlvbiB0byBiZSB2YWxpZFwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhDbGllbnRBdXRob3JpemF0aW9uXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX29hdXRoX09BdXRoQ2xpZW50QXV0aG9yaXphdGlvbkxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIG9hdXRoIGNsaWVudCBhdXRob3JpemF0aW9uc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfb2F1dGhfT0F1dGhDbGllbnRBdXRob3JpemF0aW9uXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhDbGllbnRBdXRob3JpemF0aW9uXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIk9BdXRoQ2xpZW50QXV0aG9yaXphdGlvbkxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aENsaWVudEF1dGhvcml6YXRpb25MaXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VcIixcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlTGlzdFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX29hdXRoX09BdXRoQ2xpZW50TGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2Ygb2F1dGggY2xpZW50c1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfb2F1dGhfT0F1dGhDbGllbnRcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aENsaWVudFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJPQXV0aENsaWVudExpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aENsaWVudExpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfcHJvamVjdF9Qcm9qZWN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJQcm9qZWN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfcHJvamVjdF9Qcm9qZWN0U3BlY1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qcm9qZWN0U3BlY1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXR1c1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3Byb2plY3RfUHJvamVjdFN0YXR1c1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qcm9qZWN0U3RhdHVzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qcm9qZWN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX3Byb2plY3RfUHJvamVjdExpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHByb2plY3RzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19wcm9qZWN0X1Byb2plY3RcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qcm9qZWN0XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlByb2plY3RMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUHJvamVjdExpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfcHJvamVjdF9Qcm9qZWN0UmVxdWVzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJkZXNjcmlwdGlvbiB0byBhcHBseSB0byBhIHByb2plY3RcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkaXNwbGF5TmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJkaXNwbGF5IG5hbWUgdG8gYXBwbHkgdG8gYSBwcm9qZWN0XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlByb2plY3RSZXF1ZXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlByb2plY3RSZXF1ZXN0XCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX3Byb2plY3RfUHJvamVjdFNwZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiZmluYWxpemVyc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFuIG9wYXF1ZSBsaXN0IG9mIHZhbHVlcyB0aGF0IG11c3QgYmUgZW1wdHkgdG8gcGVybWFuZW50bHkgcmVtb3ZlIG9iamVjdCBmcm9tIHN0b3JhZ2VcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImFuIG9wYXF1ZSBsaXN0IG9mIHZhbHVlcyB0aGF0IG11c3QgYmUgZW1wdHkgdG8gcGVybWFuZW50bHkgcmVtb3ZlIG9iamVjdCBmcm9tIHN0b3JhZ2VcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlByb2plY3RTcGVjXCJcbiAgICAgIH0sXG4gICAgICBcIm9zX3Byb2plY3RfUHJvamVjdFN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJwaGFzZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwaGFzZSBpcyB0aGUgY3VycmVudCBsaWZlY3ljbGUgcGhhc2Ugb2YgdGhlIHByb2plY3RcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlByb2plY3RTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwib3Nfcm91dGVfUm91dGVcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlJvdXRlXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJzcGVjXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfcm91dGVfUm91dGVTcGVjXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvdXRlU3BlY1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInN0YXR1c1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3JvdXRlX1JvdXRlU3RhdHVzXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvdXRlU3RhdHVzXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb3V0ZVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc19yb3V0ZV9Sb3V0ZUxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHJvdXRlc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfcm91dGVfUm91dGVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb3V0ZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJSb3V0ZUxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb3V0ZUxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3Nfcm91dGVfUm91dGVTcGVjXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImhvc3RcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib3B0aW9uYWw6IGFsaWFzL2RucyB0aGF0IHBvaW50cyB0byB0aGUgc2VydmljZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBhdGhcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib3B0aW9uYWw6IHBhdGggdGhhdCB0aGUgcm91dGVyIHdhdGNoZXMgdG8gcm91dGUgdHJhZmZpYyB0byB0aGUgc2VydmljZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInRsc1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3JvdXRlX1RMU0NvbmZpZ1wiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UTFNDb25maWdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0b1wiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0UmVmZXJlbmNlXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RSZWZlcmVuY2VcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvdXRlU3BlY1wiXG4gICAgICB9LFxuICAgICAgXCJvc19yb3V0ZV9Sb3V0ZVN0YXR1c1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb3V0ZVN0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJvc19yb3V0ZV9UTFNDb25maWdcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiY2FDZXJ0aWZpY2F0ZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwcm92aWRlcyB0aGUgY2VydCBhdXRob3JpdHkgY2VydGlmaWNhdGUgY29udGVudHNcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJjZXJ0aWZpY2F0ZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwcm92aWRlcyBjZXJ0aWZpY2F0ZSBjb250ZW50c1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImRlc3RpbmF0aW9uQ0FDZXJ0aWZpY2F0ZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJwcm92aWRlcyB0aGUgY29udGVudHMgb2YgdGhlIGNhIGNlcnRpZmljYXRlIG9mIHRoZSBmaW5hbCBkZXN0aW5hdGlvbi4gIFdoZW4gdXNpbmcgcmUtZW5jcnlwdCB0ZXJtaW5hdGlvbiB0aGlzIGZpbGUgc2hvdWxkIGJlIHByb3ZpZGVkIGluIG9yZGVyIHRvIGhhdmUgcm91dGVycyB1c2UgaXQgZm9yIGhlYWx0aCBjaGVja3Mgb24gdGhlIHNlY3VyZSBjb25uZWN0aW9uXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2V5XCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcInByb3ZpZGVzIGtleSBmaWxlIGNvbnRlbnRzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidGVybWluYXRpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaW5kaWNhdGVzIHRlcm1pbmF0aW9uIHR5cGUuICBpZiBub3Qgc2V0XCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UTFNDb25maWdcIlxuICAgICAgfSxcbiAgICAgIFwib3NfdGVtcGxhdGVfUGFyYW1ldGVyXCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9wdGlvbmFsOiBkZXNjcmliZXMgdGhlIHBhcmFtZXRlclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImZyb21cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiaW5wdXQgdmFsdWUgZm9yIHRoZSBnZW5lcmF0b3JcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJnZW5lcmF0ZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbDogZ2VuZXJhdGUgc3BlY2lmaWVzIHRoZSBnZW5lcmF0b3IgdG8gYmUgdXNlZCB0byBnZW5lcmF0ZSByYW5kb20gc3RyaW5nIGZyb20gYW4gaW5wdXQgdmFsdWUgc3BlY2lmaWVkIGJ5IHRoZSBmcm9tIGZpZWxkLiAgdGhlIHJlc3VsdCBzdHJpbmcgaXMgc3RvcmVkIGluIHRoZSB2YWx1ZSBmaWVsZC4gaWYgbm90IHNwZWNpZmllZFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibmFtZSBvZiB0aGUgcGFyYW1ldGVyXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicmVxdWlyZWRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYm9vbGVhblwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImluZGljYXRlcyB0aGUgcGFyYW1ldGVyIG11c3QgaGF2ZSBhIG5vbi1lbXB0eSB2YWx1ZSBvciBiZSBnZW5lcmF0ZWRcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ2YWx1ZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbDogaG9sZHMgdGhlIHBhcmFtZXRlciBkYXRhLiAgaWYgc3BlY2lmaWVkXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5QYXJhbWV0ZXJcIlxuICAgICAgfSxcbiAgICAgIFwib3NfdGVtcGxhdGVfVGVtcGxhdGVcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlRlbXBsYXRlXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibGFiZWxzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIm9wdGlvbmFsOiBsaXN0IG9mIGxhYmxlcyB0aGF0IGFyZSBhcHBsaWVkIHRvIGV2ZXJ5IG9iamVjdCBkdXJpbmcgdGhlIHRlbXBsYXRlIHRvIGNvbmZpZyB0cmFuc2Zvcm1hdGlvblwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwib3B0aW9uYWw6IGxpc3Qgb2YgbGFibGVzIHRoYXQgYXJlIGFwcGxpZWQgdG8gZXZlcnkgb2JqZWN0IGR1cmluZyB0aGUgdGVtcGxhdGUgdG8gY29uZmlnIHRyYW5zZm9ybWF0aW9uXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiamF2YS51dGlsLk1hcFxcdTAwM2NTdHJpbmcsU3RyaW5nXFx1MDAzZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwib2JqZWN0c1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2Ygb2JqZWN0cyB0byBpbmNsdWRlIGluIHRoZSB0ZW1wbGF0ZVwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19ydW50aW1lX1Jhd0V4dGVuc2lvblwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInBhcmFtZXRlcnNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJvcHRpb25hbDogbGlzdCBvZiBwYXJhbWV0ZXJzIHVzZWQgZHVyaW5nIHRlbXBsYXRlIHRvIGNvbmZpZyB0cmFuc2Zvcm1hdGlvblwiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdGVtcGxhdGVfUGFyYW1ldGVyXCIsXG4gICAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUGFyYW1ldGVyXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UZW1wbGF0ZVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc190ZW1wbGF0ZV9UZW1wbGF0ZUxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHRlbXBsYXRlc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdGVtcGxhdGVfVGVtcGxhdGVcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UZW1wbGF0ZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJUZW1wbGF0ZUxpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UZW1wbGF0ZUxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfdXNlcl9Hcm91cFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiR3JvdXBcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfT2JqZWN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVzZXJzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiB1c2VycyBpbiB0aGlzIGdyb3VwXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHVzZXJzIGluIHRoaXMgZ3JvdXBcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkdyb3VwXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX3VzZXJfR3JvdXBMaXN0XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImFwaVZlcnNpb25cIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJ2MVwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgICAgICAgXCJ2MVwiXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBncm91cHNcIixcbiAgICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3VzZXJfR3JvdXBcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Hcm91cFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImtpbmRcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgICAgICBcImRlZmF1bHRcIjogXCJHcm91cExpc3RcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJtZXRhZGF0YVwiOiB7XG4gICAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTGlzdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkxpc3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Hcm91cExpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwib3NfdXNlcl9JZGVudGl0eVwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJleHRyYVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJleHRyYSBpbmZvcm1hdGlvbiBmb3IgdGhpcyBpZGVudGl0eVwiLFxuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZXh0cmEgaW5mb3JtYXRpb24gZm9yIHRoaXMgaWRlbnRpdHlcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJqYXZhLnV0aWwuTWFwXFx1MDAzY1N0cmluZyxTdHJpbmdcXHUwMDNlXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIklkZW50aXR5XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk9iamVjdE1ldGFcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJwcm92aWRlck5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwic291cmNlIG9mIGlkZW50aXR5IGluZm9ybWF0aW9uXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwicHJvdmlkZXJVc2VyTmFtZVwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJ1bmlxdWVseSByZXByZXNlbnRzIHRoaXMgaWRlbnRpdHkgaW4gdGhlIHNjb3BlIG9mIHRoZSBwcm92aWRlclwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInVzZXJcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdFJlZmVyZW5jZVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0UmVmZXJlbmNlXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5JZGVudGl0eVwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuSGFzTWV0YWRhdGFcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc191c2VyX0lkZW50aXR5TGlzdFwiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiXCIsXG4gICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgXCJhcGlWZXJzaW9uXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwidjFcIixcbiAgICAgICAgICAgIFwicmVxdWlyZWRcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgICAgICAgIFwidjFcIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcImxpc3Qgb2YgaWRlbnRpdGllc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdXNlcl9JZGVudGl0eVwiLFxuICAgICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLklkZW50aXR5XCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIklkZW50aXR5TGlzdFwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0TWV0YVwiLFxuICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTGlzdE1ldGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB0cnVlLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLklkZW50aXR5TGlzdFwiLFxuICAgICAgICBcImphdmFJbnRlcmZhY2VzXCI6IFtcbiAgICAgICAgICBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuS3ViZXJuZXRlc1Jlc291cmNlXCIsXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZUxpc3RcIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJvc191c2VyX1VzZXJcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZnVsbE5hbWVcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiZnVsbCBuYW1lIG9mIHVzZXJcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJncm91cHNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGdyb3Vwc1wiLFxuICAgICAgICAgICAgXCJpdGVtc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBncm91cHNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJpZGVudGl0aWVzXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwibGlzdCBvZiBpZGVudGl0aWVzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIGlkZW50aXRpZXNcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJraW5kXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICAgICAgXCJkZWZhdWx0XCI6IFwiVXNlclwiLFxuICAgICAgICAgICAgXCJyZXF1aXJlZFwiOiB0cnVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19PYmplY3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5PYmplY3RNZXRhXCJcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZSxcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Vc2VyXCIsXG4gICAgICAgIFwiamF2YUludGVyZmFjZXNcIjogW1xuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5IYXNNZXRhZGF0YVwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcIm9zX3VzZXJfVXNlckxpc3RcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwiYXBpVmVyc2lvblwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcInYxXCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWUsXG4gICAgICAgICAgICBcImVudW1cIjogW1xuICAgICAgICAgICAgICBcInYxXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJsaXN0IG9mIHVzZXJzXCIsXG4gICAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc191c2VyX1VzZXJcIixcbiAgICAgICAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Vc2VyXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFwia2luZFwiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJcIixcbiAgICAgICAgICAgIFwiZGVmYXVsdFwiOiBcIlVzZXJMaXN0XCIsXG4gICAgICAgICAgICBcInJlcXVpcmVkXCI6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwibWV0YWRhdGFcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0xpc3RNZXRhXCIsXG4gICAgICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5MaXN0TWV0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuVXNlckxpc3RcIixcbiAgICAgICAgXCJqYXZhSW50ZXJmYWNlc1wiOiBbXG4gICAgICAgICAgXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkt1YmVybmV0ZXNSZXNvdXJjZVwiLFxuICAgICAgICAgIFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5LdWJlcm5ldGVzUmVzb3VyY2VMaXN0XCJcbiAgICAgICAgXVxuICAgICAgfSxcbiAgICAgIFwic3BldGVyX2luZl9EZWNcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlwiLFxuICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHRydWUsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuRGVjXCJcbiAgICAgIH1cbiAgICB9LFxuICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICBcIkJhc2VLdWJlcm5ldGVzTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19MaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLkJhc2VLdWJlcm5ldGVzTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJCdWlsZENvbmZpZ0xpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkQ29uZmlnTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkQ29uZmlnTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJCdWlsZExpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJCdWlsZFJlcXVlc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2J1aWxkX0J1aWxkUmVxdWVzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkJ1aWxkUmVxdWVzdFwiXG4gICAgICB9LFxuICAgICAgXCJDbHVzdGVyUG9saWN5XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX0NsdXN0ZXJQb2xpY3lcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5DbHVzdGVyUG9saWN5XCJcbiAgICAgIH0sXG4gICAgICBcIkNsdXN0ZXJQb2xpY3lCaW5kaW5nXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX0NsdXN0ZXJQb2xpY3lCaW5kaW5nXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclBvbGljeUJpbmRpbmdcIlxuICAgICAgfSxcbiAgICAgIFwiQ2x1c3RlclBvbGljeUJpbmRpbmdMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX0NsdXN0ZXJQb2xpY3lCaW5kaW5nTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkNsdXN0ZXJQb2xpY3lCaW5kaW5nTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJDbHVzdGVyUG9saWN5TGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUG9saWN5TGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkNsdXN0ZXJQb2xpY3lMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIkNsdXN0ZXJSb2xlQmluZGluZ1wiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUm9sZUJpbmRpbmdcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5DbHVzdGVyUm9sZUJpbmRpbmdcIlxuICAgICAgfSxcbiAgICAgIFwiQ2x1c3RlclJvbGVCaW5kaW5nTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9DbHVzdGVyUm9sZUJpbmRpbmdMaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuQ2x1c3RlclJvbGVCaW5kaW5nTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJDb25maWdcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfY29uZmlnX0NvbmZpZ1wiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db25maWdcIlxuICAgICAgfSxcbiAgICAgIFwiQ29udGFpbmVyU3RhdHVzXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX0NvbnRhaW5lclN0YXR1c1wiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Db250YWluZXJTdGF0dXNcIlxuICAgICAgfSxcbiAgICAgIFwiRGVwbG95bWVudENvbmZpZ0xpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2RlcGxveV9EZXBsb3ltZW50Q29uZmlnTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkRlcGxveW1lbnRDb25maWdMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIkVuZHBvaW50c1wiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19FbmRwb2ludHNcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW5kcG9pbnRzXCJcbiAgICAgIH0sXG4gICAgICBcIkVuZHBvaW50c0xpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfRW5kcG9pbnRzTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5FbmRwb2ludHNMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIkVudlZhclwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19FbnZWYXJcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRW52VmFyXCJcbiAgICAgIH0sXG4gICAgICBcIkV2ZW50TGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19FdmVudExpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuRXZlbnRMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIkdyb3VwXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc191c2VyX0dyb3VwXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuR3JvdXBcIlxuICAgICAgfSxcbiAgICAgIFwiR3JvdXBMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc191c2VyX0dyb3VwTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkdyb3VwTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJJZGVudGl0eVwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdXNlcl9JZGVudGl0eVwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLklkZW50aXR5XCJcbiAgICAgIH0sXG4gICAgICBcIklkZW50aXR5TGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdXNlcl9JZGVudGl0eUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5JZGVudGl0eUxpc3RcIlxuICAgICAgfSxcbiAgICAgIFwiSW1hZ2VMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19pbWFnZV9JbWFnZUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5JbWFnZUxpc3RcIlxuICAgICAgfSxcbiAgICAgIFwiSW1hZ2VTdHJlYW1MaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19pbWFnZV9JbWFnZVN0cmVhbUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5JbWFnZVN0cmVhbUxpc3RcIlxuICAgICAgfSxcbiAgICAgIFwiTG9jYWxTdWJqZWN0QWNjZXNzUmV2aWV3XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX0xvY2FsU3ViamVjdEFjY2Vzc1Jldmlld1wiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLkxvY2FsU3ViamVjdEFjY2Vzc1Jldmlld1wiXG4gICAgICB9LFxuICAgICAgXCJOYW1lc3BhY2VcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfTmFtZXNwYWNlXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLk5hbWVzcGFjZVwiXG4gICAgICB9LFxuICAgICAgXCJOYW1lc3BhY2VMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05hbWVzcGFjZUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTmFtZXNwYWNlTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJOb2RlXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX05vZGVcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuTm9kZVwiXG4gICAgICB9LFxuICAgICAgXCJOb2RlTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19Ob2RlTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5Ob2RlTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aEFjY2Vzc1Rva2VuXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19vYXV0aF9PQXV0aEFjY2Vzc1Rva2VuXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhBY2Nlc3NUb2tlblwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aEFjY2Vzc1Rva2VuTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfb2F1dGhfT0F1dGhBY2Nlc3NUb2tlbkxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aEFjY2Vzc1Rva2VuTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aEF1dGhvcml6ZVRva2VuXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19vYXV0aF9PQXV0aEF1dGhvcml6ZVRva2VuXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhBdXRob3JpemVUb2tlblwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aEF1dGhvcml6ZVRva2VuTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfb2F1dGhfT0F1dGhBdXRob3JpemVUb2tlbkxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aEF1dGhvcml6ZVRva2VuTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aENsaWVudFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3Nfb2F1dGhfT0F1dGhDbGllbnRcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5PQXV0aENsaWVudFwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aENsaWVudEF1dGhvcml6YXRpb25cIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX29hdXRoX09BdXRoQ2xpZW50QXV0aG9yaXphdGlvblwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLk9BdXRoQ2xpZW50QXV0aG9yaXphdGlvblwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aENsaWVudEF1dGhvcml6YXRpb25MaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19vYXV0aF9PQXV0aENsaWVudEF1dGhvcml6YXRpb25MaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuT0F1dGhDbGllbnRBdXRob3JpemF0aW9uTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJPQXV0aENsaWVudExpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX29hdXRoX09BdXRoQ2xpZW50TGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLk9BdXRoQ2xpZW50TGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJPYmplY3RNZXRhXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX09iamVjdE1ldGFcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuT2JqZWN0TWV0YVwiXG4gICAgICB9LFxuICAgICAgXCJQZXJzaXN0ZW50Vm9sdW1lXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZVwiXG4gICAgICB9LFxuICAgICAgXCJQZXJzaXN0ZW50Vm9sdW1lQ2xhaW1cIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUGVyc2lzdGVudFZvbHVtZUNsYWltXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlBlcnNpc3RlbnRWb2x1bWVDbGFpbVwiXG4gICAgICB9LFxuICAgICAgXCJQZXJzaXN0ZW50Vm9sdW1lQ2xhaW1MaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BlcnNpc3RlbnRWb2x1bWVDbGFpbUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUGVyc2lzdGVudFZvbHVtZUNsYWltTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJQZXJzaXN0ZW50Vm9sdW1lTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19QZXJzaXN0ZW50Vm9sdW1lTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5QZXJzaXN0ZW50Vm9sdW1lTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJQb2RMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1BvZExpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUG9kTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJQb2xpY3lcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fUG9saWN5XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUG9saWN5XCJcbiAgICAgIH0sXG4gICAgICBcIlBvbGljeUJpbmRpbmdcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fUG9saWN5QmluZGluZ1wiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlBvbGljeUJpbmRpbmdcIlxuICAgICAgfSxcbiAgICAgIFwiUG9saWN5QmluZGluZ0xpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fUG9saWN5QmluZGluZ0xpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qb2xpY3lCaW5kaW5nTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJQb2xpY3lMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX1BvbGljeUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qb2xpY3lMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIlByb2plY3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3Byb2plY3RfUHJvamVjdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlByb2plY3RcIlxuICAgICAgfSxcbiAgICAgIFwiUHJvamVjdExpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3Byb2plY3RfUHJvamVjdExpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Qcm9qZWN0TGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJQcm9qZWN0UmVxdWVzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfcHJvamVjdF9Qcm9qZWN0UmVxdWVzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlByb2plY3RSZXF1ZXN0XCJcbiAgICAgIH0sXG4gICAgICBcIlF1YW50aXR5XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX3Jlc291cmNlX1F1YW50aXR5XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlF1YW50aXR5XCJcbiAgICAgIH0sXG4gICAgICBcIlJlcGxpY2F0aW9uQ29udHJvbGxlckxpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUmVwbGljYXRpb25Db250cm9sbGVyTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXBsaWNhdGlvbkNvbnRyb2xsZXJMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIlJlc291cmNlUXVvdGFcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfUmVzb3VyY2VRdW90YVwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXNvdXJjZVF1b3RhXCJcbiAgICAgIH0sXG4gICAgICBcIlJlc291cmNlUXVvdGFMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1Jlc291cmNlUXVvdGFMaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJlc291cmNlUXVvdGFMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIlJvbGVcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fUm9sZVwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvbGVcIlxuICAgICAgfSxcbiAgICAgIFwiUm9sZUJpbmRpbmdcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fUm9sZUJpbmRpbmdcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5Sb2xlQmluZGluZ1wiXG4gICAgICB9LFxuICAgICAgXCJSb2xlQmluZGluZ0xpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2F1dGhvcml6YXRpb25fUm9sZUJpbmRpbmdMaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUm9sZUJpbmRpbmdMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIlJvbGVMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX1JvbGVMaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuUm9sZUxpc3RcIlxuICAgICAgfSxcbiAgICAgIFwiUm9vdFBhdGhzXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9hcGlfUm9vdFBhdGhzXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlJvb3RQYXRoc1wiXG4gICAgICB9LFxuICAgICAgXCJSb3V0ZUxpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3JvdXRlX1JvdXRlTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlJvdXRlTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJTZWNyZXRcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VjcmV0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3JldFwiXG4gICAgICB9LFxuICAgICAgXCJTZWNyZXRMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9rdWJlcm5ldGVzX1NlY3JldExpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuU2VjcmV0TGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJTZWN1cml0eUNvbnRleHRDb25zdHJhaW50c1wiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TZWN1cml0eUNvbnRleHRDb25zdHJhaW50c1wiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZWN1cml0eUNvbnRleHRDb25zdHJhaW50c1wiXG4gICAgICB9LFxuICAgICAgXCJTZWN1cml0eUNvbnRleHRDb25zdHJhaW50c0xpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VjdXJpdHlDb250ZXh0Q29uc3RyYWludHNMaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlY3VyaXR5Q29udGV4dENvbnN0cmFpbnRzTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJTZXJ2aWNlQWNjb3VudFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TZXJ2aWNlQWNjb3VudFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZXJ2aWNlQWNjb3VudFwiXG4gICAgICB9LFxuICAgICAgXCJTZXJ2aWNlQWNjb3VudExpc3RcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU2VydmljZUFjY291bnRMaXN0XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlNlcnZpY2VBY2NvdW50TGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJTZXJ2aWNlTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMva3ViZXJuZXRlc19TZXJ2aWNlTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZXJ2aWNlTGlzdFwiXG4gICAgICB9LFxuICAgICAgXCJTdGF0dXNcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfU3RhdHVzXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lmt1YmVybmV0ZXMuYXBpLm1vZGVsLlN0YXR1c1wiXG4gICAgICB9LFxuICAgICAgXCJTdWJqZWN0QWNjZXNzUmV2aWV3XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc19hdXRob3JpemF0aW9uX1N1YmplY3RBY2Nlc3NSZXZpZXdcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5TdWJqZWN0QWNjZXNzUmV2aWV3XCJcbiAgICAgIH0sXG4gICAgICBcIlN1YmplY3RBY2Nlc3NSZXZpZXdSZXNwb25zZVwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfYXV0aG9yaXphdGlvbl9TdWJqZWN0QWNjZXNzUmV2aWV3UmVzcG9uc2VcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5TdWJqZWN0QWNjZXNzUmV2aWV3UmVzcG9uc2VcIlxuICAgICAgfSxcbiAgICAgIFwiVGFnRXZlbnRcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX2ltYWdlX1RhZ0V2ZW50XCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuVGFnRXZlbnRcIlxuICAgICAgfSxcbiAgICAgIFwiVGVtcGxhdGVcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL29zX3RlbXBsYXRlX1RlbXBsYXRlXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuVGVtcGxhdGVcIlxuICAgICAgfSxcbiAgICAgIFwiVGVtcGxhdGVMaXN0XCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9vc190ZW1wbGF0ZV9UZW1wbGF0ZUxpc3RcIixcbiAgICAgICAgXCJqYXZhVHlwZVwiOiBcImlvLmZhYnJpYzgub3BlbnNoaWZ0LmFwaS5tb2RlbC5UZW1wbGF0ZUxpc3RcIlxuICAgICAgfSxcbiAgICAgIFwiVXNlclwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdXNlcl9Vc2VyXCIsXG4gICAgICAgIFwiamF2YVR5cGVcIjogXCJpby5mYWJyaWM4Lm9wZW5zaGlmdC5hcGkubW9kZWwuVXNlclwiXG4gICAgICB9LFxuICAgICAgXCJVc2VyTGlzdFwiOiB7XG4gICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvb3NfdXNlcl9Vc2VyTGlzdFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5vcGVuc2hpZnQuYXBpLm1vZGVsLlVzZXJMaXN0XCJcbiAgICAgIH0sXG4gICAgICBcIldhdGNoRXZlbnRcIjoge1xuICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL2t1YmVybmV0ZXNfd2F0Y2hfV2F0Y2hFdmVudFwiLFxuICAgICAgICBcImphdmFUeXBlXCI6IFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5XYXRjaEV2ZW50XCJcbiAgICAgIH1cbiAgICB9LFxuICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogdHJ1ZVxuICB9XG5cblxufSIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJzY2hlbWEudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcbiAgXG4gIFxuICB2YXIgaGlkZGVuUHJvcGVydGllcyA9IFsnc3RhdHVzJywgJ2RlbGV0aW9uVGltZXN0YW1wJ107XG5cbiAgZnVuY3Rpb24gd2l0aFByb3BlcnR5KHNjaGVtYTphbnksIG5hbWU6c3RyaW5nLCBhY3Rpb246KGFueSkgPT4gdm9pZCkge1xuICAgIGlmIChzY2hlbWEucHJvcGVydGllc1tuYW1lXSkge1xuICAgICAgYWN0aW9uKHNjaGVtYS5wcm9wZXJ0aWVzW25hbWVdKTtcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGhpZGVQcm9wZXJ0aWVzKHNjaGVtYSkge1xuICAgIF8uZm9yRWFjaChoaWRkZW5Qcm9wZXJ0aWVzLCAocHJvcGVydHkpID0+IHtcbiAgICAgIHdpdGhQcm9wZXJ0eShzY2hlbWEsIHByb3BlcnR5LCAocHJvcGVydHkpID0+IHtcbiAgICAgICAgcHJvcGVydHkuaGlkZGVuID0gdHJ1ZTtcbiAgICAgIH0pXG4gICAgfSk7XG4gIH1cbiAgXG4gIF9tb2R1bGUuZmFjdG9yeSgnS3ViZXJuZXRlc1NjaGVtYScsIFsnU2NoZW1hUmVnaXN0cnknLCAoc2NoZW1hczpIYXd0aW9Gb3Jtcy5TY2hlbWFSZWdpc3RyeSkgPT4ge1xuICAgIGNvbmZpZ3VyZVNjaGVtYSgpO1xuICAgIFxuICAgIHNjaGVtYXMuYWRkTGlzdGVuZXIoXCJrOHMgc2NoZW1hIGN1c3RvbWl6ZXJcIiwgKG5hbWUsIHNjaGVtYSkgPT4ge1xuICAgICAgaWYgKHNjaGVtYS5wcm9wZXJ0aWVzKSB7XG4gICAgICAgIGlmIChzY2hlbWEucHJvcGVydGllcy5uYW1lKSB7XG4gICAgICAgICAgc2NoZW1hLmNvbnRyb2xzID0gWyduYW1lJywgJyonXTtcbiAgICAgICAgfVxuICAgICAgICB3aXRoUHJvcGVydHkoc2NoZW1hLCAncG9ydGFsSVAnLCAocHJvcGVydHkpID0+IHtcbiAgICAgICAgICBwcm9wZXJ0eS5sYWJlbCA9IFwiUG9ydGFsIElQXCJcbiAgICAgICAgfSk7XG4gICAgICAgIHdpdGhQcm9wZXJ0eShzY2hlbWEsICdwdWJsaWNJUHMnLCAocHJvcGVydHkpID0+IHtcbiAgICAgICAgICBwcm9wZXJ0eS5sYWJlbCA9IFwiUHVibGljIElQc1wiXG4gICAgICAgIH0pO1xuICAgICAgICB3aXRoUHJvcGVydHkoc2NoZW1hLCAnU3BlYycsIChwcm9wZXJ0eSkgPT4ge1xuICAgICAgICAgIHByb3BlcnR5LmxhYmVsID0gJ2ZhbHNlJztcbiAgICAgICAgfSk7XG4gICAgICAgIHdpdGhQcm9wZXJ0eShzY2hlbWEsICdNZXRhZGF0YScsIChwcm9wZXJ0eSkgPT4ge1xuICAgICAgICAgIHByb3BlcnR5LmxhYmVsID0gJ2ZhbHNlJztcbiAgICAgICAgfSk7XG4gICAgICAgIGhpZGVQcm9wZXJ0aWVzKHNjaGVtYSk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmIChfLmVuZHNXaXRoKG5hbWUsIFwiU2VydmljZVNwZWNcIikpIHtcbiAgICAgICAgc2NoZW1hLmNvbnRyb2xzID0gW1wicG9ydGFsSVBcIiwgXCJjcmVhdGVFeHRlcm5hbExvYWRCYWxhbmNlclwiLCBcInNlc3Npb25BZmZpbml0eVwiLCBcInB1YmxpY0lQc1wiLCBcInBvcnRzXCIsIFwic2VsZWN0b3JcIiwgXCIqXCJdO1xuICAgICAgICB3aXRoUHJvcGVydHkoc2NoZW1hLCAnc2Vzc2lvbkFmZmluaXR5JywgKHByb3BlcnR5KSA9PiB7XG4gICAgICAgICAgbG9nLmRlYnVnKFwiU2NoZW1hOiBcIiwgc2NoZW1hKTtcbiAgICAgICAgICBwcm9wZXJ0eS5lbnVtID0gWydOb25lJywgJ0NsaWVudElQJ107XG4gICAgICAgICAgcHJvcGVydHkuZGVmYXVsdCA9ICdOb25lJztcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmIChfLmVuZHNXaXRoKG5hbWUsIFwiU2VydmljZVwiKSkge1xuICAgICAgICBzY2hlbWEuY29udHJvbHMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHNjaGVtYS50YWJzID0ge1xuICAgICAgICAgICdCYXNpYyBJbmZvcm1hdGlvbic6IFsnbWV0YWRhdGEnXSxcbiAgICAgICAgICAnRGV0YWlscyc6IFsnKiddXG4gICAgICAgIH1cbiAgICAgICAgbG9nLmRlYnVnKFwiTmFtZTogXCIsIG5hbWUsIFwiIFNjaGVtYTogXCIsIHNjaGVtYSk7XG4gICAgICB9XG4gICAgIFxuICAgIH0pO1xuICAgIFxuICAgIFxuICAgIHNjaGVtYXMuYWRkU2NoZW1hKCdrdWJlcm5ldGVzJywgPGFueT4gc2NoZW1hKTtcbiAgICAvLyBub3cgbGV0cyBpdGVyYXRlIGFuZCBhZGQgYWxsIHRoZSBkZWZpbml0aW9ucyB0b29cbiAgICBhbmd1bGFyLmZvckVhY2goc2NoZW1hLmRlZmluaXRpb25zLCAoZGVmaW5pdGlvbiwgdHlwZU5hbWUpID0+IHtcbiAgICAgIC8vc2NoZW1hcy5hZGRTY2hlbWEodHlwZU5hbWUsIGRlZmluaXRpb24pO1xuICAgICAgc2NoZW1hcy5hZGRTY2hlbWEoXCIjL2RlZmluaXRpb25zL1wiICsgdHlwZU5hbWUsIGRlZmluaXRpb24pO1xuICAgIH0pO1xuICAgIHJldHVybiBzY2hlbWE7XG4gIH1dKTtcblxuXG4gIFxufSIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgLy8gZmFjYWRlIHRoaXMgdG8gdGhlIHdhdGNoZXIgc2VydmljZVxuICBjbGFzcyBLdWJlcm5ldGVzU3RhdGVJbXBsIGltcGxlbWVudHMgS3ViZXJuZXRlc1N0YXRlIHtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHdhdGNoZXI6V2F0Y2hlclNlcnZpY2UpIHtcbiAgICB9XG4gICAgZ2V0IG5hbWVzcGFjZXMoKTpBcnJheTxzdHJpbmc+IHtcbiAgICAgIHJldHVybiBfLm1hcCh0aGlzLndhdGNoZXIuZ2V0T2JqZWN0cyhXYXRjaFR5cGVzLk5BTUVTUEFDRVMpLCAobmFtZXNwYWNlKSA9PiB7XG4gICAgICAgIHJldHVybiBuYW1lc3BhY2UubWV0YWRhdGEubmFtZTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBnZXQgc2VsZWN0ZWROYW1lc3BhY2UoKTpzdHJpbmcge1xuICAgICAgcmV0dXJuIHRoaXMud2F0Y2hlci5nZXROYW1lc3BhY2UoKTtcbiAgICB9XG4gICAgc2V0IHNlbGVjdGVkTmFtZXNwYWNlKG5hbWVzcGFjZTpzdHJpbmcpIHtcbiAgICAgIHRoaXMud2F0Y2hlci5zZXROYW1lc3BhY2UobmFtZXNwYWNlKTtcbiAgICB9XG4gIH1cblxuICBfbW9kdWxlLmZhY3RvcnkoJ0t1YmVybmV0ZXNTdGF0ZScsIFsnV2F0Y2hlclNlcnZpY2UnLCAod2F0Y2hlcjpXYXRjaGVyU2VydmljZSkgPT4ge1xuICAgIHJldHVybiBuZXcgS3ViZXJuZXRlc1N0YXRlSW1wbCh3YXRjaGVyKTtcbiAgfV0pO1xuXG4gIC8vIFRPRE8gdGhpcyBkb2Vzbid0IG5lZWQgdG8gYmUgYSBzZXJ2aWNlIHJlYWxseVxuICBfbW9kdWxlLmZhY3RvcnkoJ0t1YmVybmV0ZXNBcGlVUkwnLCAoKSA9PiBrdWJlcm5ldGVzQXBpVXJsKCkpO1xuXG4gIC8vIFRPRE8gd2UnbGwgZ2V0IHJpZCBvZiB0aGlzLi4uXG4gIF9tb2R1bGUuZmFjdG9yeSgnS3ViZXJuZXRlc1ZlcnNpb24nLCBbKCkgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICBxdWVyeTogKCkgPT4gbnVsbFxuICAgIH1cbiAgfV0pO1xuXG4gIC8vIFRPRE8gbGV0J3MgbW92ZSB0aGVzZSBpbnRvIEt1YmVybmV0ZXNNb2RlbCBzbyBjb250cm9sbGVycyBkb24ndCBoYXZlIHRvIGluamVjdCB0aGVtIHNlcGFyYXRlbHlcbiAgX21vZHVsZS5mYWN0b3J5KCdLdWJlcm5ldGVzUG9kcycsIFsnS3ViZXJuZXRlc01vZGVsJywgKEt1YmVybmV0ZXNNb2RlbCkgPT4ge1xuICAgIHJldHVybiBLdWJlcm5ldGVzTW9kZWxbJ3BvZHNSZXNvdXJjZSddO1xuICB9XSk7XG5cbiAgX21vZHVsZS5mYWN0b3J5KCdLdWJlcm5ldGVzUmVwbGljYXRpb25Db250cm9sbGVycycsIFsnS3ViZXJuZXRlc01vZGVsJywgKEt1YmVybmV0ZXNNb2RlbCkgPT4ge1xuICAgIHJldHVybiBLdWJlcm5ldGVzTW9kZWxbJ3JlcGxpY2F0aW9uY29udHJvbGxlcnNSZXNvdXJjZSddO1xuICB9XSk7XG5cbiAgX21vZHVsZS5mYWN0b3J5KCdLdWJlcm5ldGVzU2VydmljZXMnLCBbJ0t1YmVybmV0ZXNNb2RlbCcsIChLdWJlcm5ldGVzTW9kZWwpID0+IHtcbiAgICByZXR1cm4gS3ViZXJuZXRlc01vZGVsWydzZXJ2aWNlc1Jlc291cmNlJ107XG4gIH1dKTtcblxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc01vZGVsLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBGaWxlRHJvcENvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiRmlsZURyb3BDb250cm9sbGVyXCIsIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkZpbGVVcGxvYWRlclwiLCAnJGh0dHAnLCAoJHNjb3BlLCBtb2RlbDpLdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBGaWxlVXBsb2FkZXIsICRodHRwOm5nLklIdHRwU2VydmljZSkgPT4ge1xuXG4gICAgICB2YXIgbG9nID0gTG9nZ2VyLmdldCgna3ViZXJuZXRlcy1maWxlLXVwbG9hZGVyJyk7XG5cbiAgICAgIHZhciB1cGxvYWRlciA9ICRzY29wZS51cGxvYWRlciA9IDxGaWxlVXBsb2FkLkZpbGVVcGxvYWRlcj4gbmV3IEZpbGVVcGxvYWRlcig8RmlsZVVwbG9hZC5JT3B0aW9ucz57XG4gICAgICAgIGF1dG9VcGxvYWQ6IGZhbHNlLFxuICAgICAgICByZW1vdmVBZnRlclVwbG9hZDogdHJ1ZSxcbiAgICAgICAgdXJsOiBrdWJlcm5ldGVzQXBpVXJsKClcbiAgICAgIH0pO1xuXG4gICAgICAkc2NvcGUudXBsb2FkZXIub25BZnRlckFkZGluZ0ZpbGUgPSAoZmlsZSkgPT4ge1xuICAgICAgICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgICAgICAgcmVhZGVyLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICBpZiAocmVhZGVyLnJlYWR5U3RhdGUgPT09IDIpIHtcbiAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZpbGUgYWRkZWQ6IFwiLCBmaWxlKTsgICAgICAgIFxuICAgICAgICAgICAgdmFyIGRhdGEgPSByZWFkZXIucmVzdWx0O1xuICAgICAgICAgICAgdmFyIG9iaiA9IG51bGw7XG4gICAgICAgICAgICBpZiAoXy5lbmRzV2l0aChmaWxlLl9maWxlLm5hbWUsICcuanNvbicpKSB7XG4gICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIlBhcnNpbmcgSlNPTiBmaWxlXCIpO1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIG9iaiA9IGFuZ3VsYXIuZnJvbUpzb24oZGF0YSk7XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZhaWxlZCB0byByZWFkIGRyb3BwZWQgZmlsZSBcIiwgZmlsZS5fZmlsZS5uYW1lLCBcIjogXCIsIGVycik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKF8uZW5kc1dpdGgoZmlsZS5fZmlsZS5uYW1lLCAnLnlhbWwnKSkge1xuICAgICAgICAgICAgICBsb2cuZGVidWcoXCJQYXJzaW5nIFlBTUwgZmlsZVwiKTtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBvYmogPSBqc3lhbWwubG9hZChkYXRhKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRmFpbGVkIHRvIHJlYWQgZHJvcHBlZCBmaWxlIFwiLCBmaWxlLl9maWxlLm5hbWUsIFwiOiBcIiwgZXJyKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIlVua25vd24gZmlsZSB0eXBlIGZvciBmaWxlOiBcIiwgZmlsZS5fZmlsZS5uYW1lKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9nLmRlYnVnKFwiRHJvcHBlZCBvYmplY3Q6IFwiLCBvYmopO1xuICAgICAgICAgICAgaWYgKCFLdWJlcm5ldGVzQVBJLmdldE5hbWVzcGFjZShvYmopKSB7XG4gICAgICAgICAgICAgIG9iai5tZXRhZGF0YS5uYW1lc3BhY2UgPSBtb2RlbC5jdXJyZW50TmFtZXNwYWNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBLdWJlcm5ldGVzQVBJLnB1dCh7XG4gICAgICAgICAgICAgIG9iamVjdDogb2JqLFxuICAgICAgICAgICAgICBzdWNjZXNzOiAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIENvcmUubm90aWZpY2F0aW9uKFwic3VjY2Vzc1wiLCBcIkFwcGxpZWQgXCIgKyBmaWxlLl9maWxlLm5hbWUpO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBlcnJvcjogKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiR290IGVycm9yIGFwcGx5aW5nXCIsIGZpbGUuX2ZpbGUubmFtZSwgXCI6IFwiLCBlcnIpO1xuICAgICAgICAgICAgICAgIENvcmUubm90aWZpY2F0aW9uKFwid2FybmluZ1wiLCBcIkZhaWxlZCB0byBhcHBseSBcIiArIGZpbGUuX2ZpbGUubmFtZSArIFwiLCBlcnJvcjogXCIgKyBlcnIubWVzc2FnZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZWFkZXIucmVhZEFzVGV4dChmaWxlLl9maWxlKTtcbiAgICAgIH07XG5cbiAgICAgICRzY29wZS51cGxvYWRlci5vbkJlZm9yZVVwbG9hZEl0ZW0gPSAoaXRlbSkgPT4ge1xuICAgICAgICBsb2cuZGVidWcoXCJVcGxvYWRpbmc6IFwiLCBpdGVtKTtcbiAgICAgICAgLy9Db3JlLm5vdGlmaWNhdGlvbignaW5mbycsICdVcGxvYWRpbmcgJyArIGl0ZW0pO1xuICAgICAgfTtcblxuICAgICAgJHNjb3BlLnVwbG9hZGVyLm9uU3VjY2Vzc0l0ZW0gPSAoaXRlbTpGaWxlVXBsb2FkLklGaWxlSXRlbSkgPT4ge1xuICAgICAgICBsb2cuZGVidWcoXCJvblN1Y2Nlc3NJdGVtOiBcIiwgaXRlbSk7XG4gICAgICB9O1xuXG4gICAgICAkc2NvcGUudXBsb2FkZXIub25FcnJvckl0ZW0gPSAoaXRlbSwgcmVzcG9uc2UsIHN0YXR1cykgPT4ge1xuICAgICAgICBsb2cuZGVidWcoXCJGYWlsZWQgdG8gYXBwbHksIHJlc3BvbnNlOiBcIiwgcmVzcG9uc2UsIFwiIHN0YXR1czogXCIsIHN0YXR1cyk7XG4gICAgICB9XG5cbiAgfV0pO1xuXHRcblx0ZXhwb3J0IHZhciBOYW1lc3BhY2VDb250cm9sbGVyID0gY29udHJvbGxlcignTmFtZXNwYWNlQ29udHJvbGxlcicsIFsnJHNjb3BlJywgJ1dhdGNoZXJTZXJ2aWNlJywgKCRzY29wZSwgd2F0Y2hlcjpXYXRjaGVyU2VydmljZSkgPT4ge1xuXHRcdCRzY29wZS5uYW1lc3BhY2VzID0gd2F0Y2hlci5nZXRPYmplY3RzKCduYW1lc3BhY2VzJyk7XG5cdFx0JHNjb3BlLiR3YXRjaENvbGxlY3Rpb24oJ25hbWVzcGFjZXMnLCAobmV3VmFsdWUsIG9sZFZhbHVlKSA9PiB7XG5cdFx0XHRpZiAobmV3VmFsdWUgIT09IG9sZFZhbHVlKSB7XG5cdFx0XHRcdCRzY29wZS5uYW1lc3BhY2UgPSB3YXRjaGVyLmdldE5hbWVzcGFjZSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdCRzY29wZS4kd2F0Y2goJ25hbWVzcGFjZScsIChuZXdWYWx1ZSwgb2xkVmFsdWUpID0+IHtcblx0XHRcdGlmIChuZXdWYWx1ZSAhPT0gb2xkVmFsdWUpIHtcblx0XHRcdFx0aWYgKG5ld1ZhbHVlICE9PSBvbGRWYWx1ZSkge1xuXHRcdFx0XHRcdHdhdGNoZXIuc2V0TmFtZXNwYWNlKG5ld1ZhbHVlKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XSk7XG5cbiAgZXhwb3J0IHZhciBUb3BMZXZlbCA9IGNvbnRyb2xsZXIoXCJUb3BMZXZlbFwiLCBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzVmVyc2lvblwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCAoJHNjb3BlLCBLdWJlcm5ldGVzVmVyc2lvbjpuZy5yZXNvdXJjZS5JUmVzb3VyY2VDbGFzczxhbnk+LCBLdWJlcm5ldGVzU3RhdGUpID0+IHtcblxuICAgICRzY29wZS52ZXJzaW9uID0gdW5kZWZpbmVkO1xuXG4gICAgJHNjb3BlLnNob3dBcHBWaWV3ID0gaXNBcHBWaWV3KCk7XG5cbiAgICAkc2NvcGUuaXNBY3RpdmUgPSAoaHJlZikgPT4ge1xuICAgICAgcmV0dXJuIGlzTGlua0FjdGl2ZShocmVmKTtcbiAgICB9O1xuXG4gICAgJHNjb3BlLm1vZGUgPSAneWFtbCc7XG4gICAgJHNjb3BlLnJhd01vZGUgPSB0cnVlO1xuICAgICRzY29wZS5kaXJ0eSA9IGZhbHNlO1xuICAgICRzY29wZS5yZWFkT25seSA9IHRydWU7XG4gICAgJHNjb3BlLnJhd01vZGVsID0gbnVsbDtcblxuICAgICRzY29wZS4kb24oJ2hhd3Rpb0VkaXRvcl9kZWZhdWx0X2RpcnR5JywgKCRldmVudCwgZGlydHkpID0+IHtcbiAgICAgICRzY29wZS5kaXJ0eSA9IGRpcnR5O1xuICAgIH0pO1xuXG4gICAgJHNjb3BlLnNhdmUgPSAocmF3TW9kZWwpID0+IHtcbiAgICAgIHZhciBvYmo6YW55ID0gbnVsbDtcbiAgICAgIHZhciBzdHIgPSByYXdNb2RlbC5yZXBsYWNlKC9cXHQvZywgXCIgICAgXCIpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgb2JqID0ganN5YW1sLmxvYWQoc3RyKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBDb3JlLm5vdGlmaWNhdGlvbihcIndhcm5pbmdcIiwgXCJGYWlsZWQgdG8gc2F2ZSBvYmplY3QsIGVycm9yOiBcXFwiXCIgKyBlcnIgKyBcIlxcXCJcIik7XG4gICAgICB9XG4gICAgICBpZiAoIW9iaikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAkc2NvcGUucmVhZE9ubHkgPSB0cnVlO1xuICAgICAgS3ViZXJuZXRlc0FQSS5wdXQoe1xuICAgICAgICBvYmplY3Q6IG9iaixcbiAgICAgICAgc3VjY2VzczogKGRhdGEpID0+IHtcbiAgICAgICAgICAkc2NvcGUuZGlydHkgPSBmYWxzZTtcbiAgICAgICAgICBDb3JlLm5vdGlmaWNhdGlvbihcInN1Y2Nlc3NcIiwgXCJTYXZlZCBvYmplY3QgXCIgKyBnZXROYW1lKG9iaikpO1xuICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yOiAoZXJyKSA9PiB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJHb3QgZXJyb3I6IFwiLCBlcnIpO1xuICAgICAgICAgIENvcmUubm90aWZpY2F0aW9uKFwid2FybmluZ1wiLCBcIkZhaWxlZCB0byBzYXZlIG9iamVjdCwgZXJyb3I6IFxcXCJcIiArIGVyci5tZXNzYWdlICsgXCJcXFwiXCIpO1xuICAgICAgICAgICRzY29wZS5kaXJ0eSA9IGZhbHNlO1xuICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuXG4gICAgS3ViZXJuZXRlc1ZlcnNpb24ucXVlcnkoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAkc2NvcGUudmVyc2lvbiA9IHJlc3BvbnNlO1xuICAgIH0pO1xuXG4gIH1dKTtcblxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cdFxuXHRleHBvcnQgdmFyIE5hbWVzcGFjZUNvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiTmFtZXNwYWNlQ29udHJvbGxlclwiLCBbXCIkc2NvcGVcIiwgXCJXYXRjaGVyU2VydmljZVwiLCAoJHNjb3BlLCB3YXRjaGVyOldhdGNoZXJTZXJ2aWNlKSA9PiB7XG5cdFx0JHNjb3BlLndhdGNoZXIgPSB3YXRjaGVyO1xuXHRcdCRzY29wZS5uYW1lc3BhY2VPYmplY3RzID0gd2F0Y2hlci5nZXRPYmplY3RzKCduYW1lc3BhY2VzJyk7XG5cdFx0JHNjb3BlLm5hbWVzcGFjZSA9IHdhdGNoZXIuZ2V0TmFtZXNwYWNlKCk7XG5cdFx0JHNjb3BlLm5hbWVzcGFjZXMgPSBbXTtcblx0XHQkc2NvcGUuJHdhdGNoKCduYW1lc3BhY2UnLCAobmV3VmFsdWUsIG9sZFZhbHVlKSA9PiB7XG5cdFx0XHRpZiAobmV3VmFsdWUgIT09IG9sZFZhbHVlKSB7XG5cdFx0XHRcdHdhdGNoZXIuc2V0TmFtZXNwYWNlKG5ld1ZhbHVlKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHQkc2NvcGUuJHdhdGNoKCd3YXRjaGVyLmdldE5hbWVzcGFjZSgpJywgKG5ld1ZhbHVlLCBvbGRWYWx1ZSkgPT4ge1xuXHRcdFx0aWYgKG5ld1ZhbHVlICE9PSBvbGRWYWx1ZSkge1xuXHRcdFx0XHQkc2NvcGUubmFtZXNwYWNlID0gbmV3VmFsdWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0JHNjb3BlLiR3YXRjaENvbGxlY3Rpb24oJ25hbWVzcGFjZU9iamVjdHMnLCAobmFtZXNwYWNlT2JqZWN0cykgPT4ge1xuXHRcdFx0JHNjb3BlLm5hbWVzcGFjZXMgPSBfLm1hcChuYW1lc3BhY2VPYmplY3RzLCAobmFtZXNwYWNlOmFueSkgPT4gbmFtZXNwYWNlLm1ldGFkYXRhLm5hbWUpO1xuXHRcdH0pXHRcdFxuXHR9XSk7XG5cdFxufSIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlc3tcblxuICAgIGV4cG9ydCBjbGFzcyBvcmFjbGVNb2RlbFNlcnZpY2V7XG4gICAgICAgcHVibGljIG9yYWNsZWNvbnRyb2xsZXJzID0gW10gO1xuXG4gICAgICAgcHVibGljIGdldCBvcmFjbGVDb250cm9sbGVycygpOiBBcnJheTxhbnk+e1xuICAgICAgICAgIHJldHVybiB0aGlzLm9yYWNsZWNvbnRyb2xsZXJzO1xuICAgICAgIH1cblxuICAgICAgIHB1YmxpYyBzZXQgb3JhY2xlQ29udHJvbGxlcnMob3JhY2xlQ29udHJvbGxlcnM6IEFycmF5PGFueT4pe1xuICAgICAgICAgIHRoaXMub3JhY2xlY29udHJvbGxlcnMgPSBvcmFjbGVDb250cm9sbGVycztcbiAgICAgICB9XG5cbiAgICAgICBwdWJsaWMgZmluZEluZGV4T2ZPcmFjbGVDb250cm9sbGVycyhvcmFjbGVDb250cm9sbGVyczogQXJyYXk8YW55PiwgbmFtZTogc3RyaW5nKTogbnVtYmVye1xuICAgICAgICAgIGZvcih2YXIgaW5kZXggaW4gb3JhY2xlQ29udHJvbGxlcnMpXG4gICAgICAgICAgICAgaWYob3JhY2xlQ29udHJvbGxlcnNbaW5kZXhdLm5hbWUgPT09IG5hbWUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICB9XG4gICAgfVxuXG4gICAgX21vZHVsZS5mYWN0b3J5KCdPcmFjbGVTdGF0dXNNb2RlbCcsIFsoKSA9PiB7XG4gICAgICAgIHJldHVybiBuZXcgb3JhY2xlTW9kZWxTZXJ2aWNlKCk7XG4gICAgfV0pO1xufSIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgdmFyIE92ZXJ2aWV3RGlyZWN0aXZlID0gX21vZHVsZS5kaXJlY3RpdmUoXCJrdWJlcm5ldGVzT3ZlcnZpZXdcIiwgW1wiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkY29tcGlsZVwiLCBcIiRpbnRlcnBvbGF0ZVwiLCBcIiR0aW1lb3V0XCIsIFwiJHdpbmRvd1wiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCAnS3ViZXJuZXRlc01vZGVsJywgKCR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGNvbXBpbGU6bmcuSUNvbXBpbGVTZXJ2aWNlLCAkaW50ZXJwb2xhdGU6bmcuSUludGVycG9sYXRlU2VydmljZSwgJHRpbWVvdXQ6bmcuSVRpbWVvdXRTZXJ2aWNlLCAkd2luZG93Om5nLklXaW5kb3dTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNNb2RlbCkgPT4ge1xuXG4gICAgdmFyIGxvZyA9IExvZ2dlci5nZXQoJ2t1YmVybmV0ZXMtb3ZlcnZpZXcnKTtcbiAgICB2YXIgbW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgdmFyIHN0YXRlID0gS3ViZXJuZXRlc1N0YXRlO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3RyaWN0OiAnRScsXG4gICAgICByZXBsYWNlOiB0cnVlLFxuICAgICAgbGluazogKHNjb3BlLCBlbGVtZW50LCBhdHRyKSA9PiB7XG4gICAgICAgIHNjb3BlLm1vZGVsID0gbW9kZWw7XG4gICAgICAgIGVsZW1lbnQuY3NzKHt2aXNpYmlsaXR5OiAnaGlkZGVuJ30pO1xuICAgICAgICBzY29wZS5nZXRFbnRpdHkgPSAodHlwZTpzdHJpbmcsIGtleTpzdHJpbmcpID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2hvc3QnOlxuICAgICAgICAgICAgICByZXR1cm4gbW9kZWwucG9kc0J5SG9zdFtrZXldO1xuICAgICAgICAgICAgY2FzZSAncG9kJzpcbiAgICAgICAgICAgICAgcmV0dXJuIG1vZGVsLnBvZHNCeUtleVtrZXldO1xuICAgICAgICAgICAgY2FzZSAncmVwbGljYXRpb25Db250cm9sbGVyJzpcbiAgICAgICAgICAgICAgcmV0dXJuIG1vZGVsLnJlcGxpY2F0aW9uQ29udHJvbGxlcnNCeUtleVtrZXldO1xuICAgICAgICAgICAgY2FzZSAnc2VydmljZSc6XG4gICAgICAgICAgICAgIHJldHVybiBtb2RlbC5zZXJ2aWNlc0J5S2V5W2tleV07XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBzY29wZS5rdWJlcm5ldGVzID0gc3RhdGU7XG5cbiAgICAgICAgc2NvcGUuY3VzdG9taXplRGVmYXVsdE9wdGlvbnMgPSAob3B0aW9ucykgPT4ge1xuICAgICAgICAgIG9wdGlvbnMuRW5kcG9pbnQgPSBbJ0JsYW5rJywge31dO1xuICAgICAgICB9O1xuICAgICAgICBzY29wZS5tb3VzZUVudGVyID0gKCRldmVudCkgPT4ge1xuICAgICAgICAgIGlmIChzY29wZS5qc1BsdW1iKSB7XG4gICAgICAgICAgICBhbmd1bGFyLmVsZW1lbnQoJGV2ZW50LmN1cnJlbnRUYXJnZXQpLmFkZENsYXNzKFwiaG92ZXJlZFwiKTtcbiAgICAgICAgICAgIHNjb3BlLmpzUGx1bWIuZ2V0RW5kcG9pbnRzKCRldmVudC5jdXJyZW50VGFyZ2V0KS5mb3JFYWNoKChlbmRwb2ludCkgPT4ge1xuICAgICAgICAgICAgICBlbmRwb2ludC5jb25uZWN0aW9ucy5mb3JFYWNoKChjb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFjb25uZWN0aW9uLmlzSG92ZXIoKSkge1xuICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5zZXRIb3Zlcih0cnVlKTtcbiAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uZW5kcG9pbnRzLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc2NvcGUubW91c2VFbnRlcih7XG4gICAgICAgICAgICAgICAgICAgICAgY3VycmVudFRhcmdldDogZS5lbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzY29wZS5tb3VzZUxlYXZlID0gKCRldmVudCkgPT4ge1xuICAgICAgICAgIGlmIChzY29wZS5qc1BsdW1iKSB7XG4gICAgICAgICAgICBhbmd1bGFyLmVsZW1lbnQoJGV2ZW50LmN1cnJlbnRUYXJnZXQpLnJlbW92ZUNsYXNzKFwiaG92ZXJlZFwiKTtcbiAgICAgICAgICAgIHNjb3BlLmpzUGx1bWIuZ2V0RW5kcG9pbnRzKCRldmVudC5jdXJyZW50VGFyZ2V0KS5mb3JFYWNoKChlbmRwb2ludCkgPT4ge1xuICAgICAgICAgICAgICBlbmRwb2ludC5jb25uZWN0aW9ucy5mb3JFYWNoKChjb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbm5lY3Rpb24uaXNIb3ZlcigpKSB7XG4gICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnNldEhvdmVyKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uZW5kcG9pbnRzLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc2NvcGUubW91c2VMZWF2ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgY3VycmVudFRhcmdldDogZS5lbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKlxuICAgICAgICBzY29wZS5jdXN0b21pemVFbmRwb2ludE9wdGlvbnMgPSAoanNQbHVtYiwgbm9kZSwgb3B0aW9ucykgPT4ge1xuICAgICAgICAgIHZhciB0eXBlID0gbm9kZS5lbC5hdHRyKCdkYXRhLXR5cGUnKTtcbiAgICAgICAgICAvLyBsb2cuZGVidWcoXCJlbmRwb2ludCB0eXBlOiBcIiwgdHlwZSk7XG4gICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdwb2QnOlxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NlcnZpY2UnOlxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3JlcGxpY2F0aW9uQ29udHJvbGxlcic6XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgKi9cbiAgICAgICAgc2NvcGUuY3VzdG9taXplQ29ubmVjdGlvbk9wdGlvbnMgPSAoanNQbHVtYiwgZWRnZSwgcGFyYW1zLCBvcHRpb25zKSA9PiB7XG4gICAgICAgICAgdmFyIHR5cGUgPSBlZGdlLnNvdXJjZS5lbC5hdHRyKCdkYXRhLXR5cGUnKTtcbiAgICAgICAgICBvcHRpb25zLmNvbm5lY3RvciA9IFsgXCJCZXppZXJcIiwgeyBjdXJ2aW5lc3M6IDUwLCBzdHViOiAyNSwgYWx3YXlzUmVzcGVjdFN0dWJzOiB0cnVlIH0gXTtcbiAgICAgICAgICBwYXJhbXMucGFpbnRTdHlsZSA9IHtcbiAgICAgICAgICAgIGxpbmVXaWR0aDogMixcbiAgICAgICAgICAgIHN0cm9rZVN0eWxlOiAnIzU1NTVjYydcbiAgICAgICAgICB9O1xuICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSAncG9kJzpcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzZXJ2aWNlJzpcbiAgICAgICAgICAgICAgcGFyYW1zLmFuY2hvcnMgPSBbXG4gICAgICAgICAgICAgICAgWyBcIkNvbnRpbnVvdXNcIiwgeyBmYWNlczogW1wicmlnaHRcIl0gfSBdLFxuICAgICAgICAgICAgICAgIFsgXCJDb250aW51b3VzXCIsIHsgZmFjZXM6IFtcImxlZnRcIl0gfSBdIFxuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgWzEsIDAuNSwgMCwgMCwgLTEwLCAtOTBdLFxuICAgICAgICAgICAgICAgIFswLCAwLjUsIDAsIDAsIC0xMCwgLTkwXVxuICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncmVwbGljYXRpb25Db250cm9sbGVyJzpcbiAgICAgICAgICAgICAgcGFyYW1zLmFuY2hvcnMgPSBbXG4gICAgICAgICAgICAgICAgWyBcIlBlcmltZXRlclwiLCB7IHNoYXBlOiBcIkNpcmNsZVwiIH0gXSxcbiAgICAgICAgICAgICAgICBbIFwiQ29udGludW91c1wiLCB7IGZhY2VzOiBbXCJyaWdodFwiXSB9IF1cbiAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgIFswLCAwLjUsIDAsIDAsIC0xMCwgLTkwXSxcbiAgICAgICAgICAgICAgICBbMSwgMC41LCAwLCAwLCAtMTAsIC05MF1cbiAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgLy9sb2cuZGVidWcoXCJjb25uZWN0aW9uIHNvdXJjZSB0eXBlOiBcIiwgdHlwZSk7XG4gICAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgICAgIH07XG4gICAgICAgIGZ1bmN0aW9uIGludGVycG9sYXRlKHRlbXBsYXRlLCBjb25maWcpIHtcbiAgICAgICAgICByZXR1cm4gJGludGVycG9sYXRlKHRlbXBsYXRlKShjb25maWcpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGVtcGxhdGUsIHRoaW5nTmFtZSwgdGhpbmcpIHtcbiAgICAgICAgICB2YXIgY29uZmlnID0ge307XG4gICAgICAgICAgY29uZmlnW3RoaW5nTmFtZV0gPSB0aGluZztcbiAgICAgICAgICByZXR1cm4gaW50ZXJwb2xhdGUodGVtcGxhdGUsIGNvbmZpZyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudHModGVtcGxhdGUsIHRoaW5nTmFtZSwgdGhpbmdzKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaW5ncy5tYXAoKHRoaW5nKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRWxlbWVudCh0ZW1wbGF0ZSwgdGhpbmdOYW1lLCB0aGluZyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYXBwZW5kTmV3RWxlbWVudHMocGFyZW50RWwsIHRlbXBsYXRlLCB0aGluZ05hbWUsIHRoaW5ncykge1xuICAgICAgICAgIHRoaW5ncy5mb3JFYWNoKCh0aGluZykgPT4ge1xuICAgICAgICAgICAgdmFyIGtleSA9IHRoaW5nWydfa2V5J10gfHwgdGhpbmdbJ2VsZW1lbnRJZCddIHx8IHRoaW5nWydpZCddXG4gICAgICAgICAgICB2YXIgZXhpc3RpbmcgPSBwYXJlbnRFbC5maW5kKFwiI1wiICsga2V5ICk7XG4gICAgICAgICAgICBpZiAoIWV4aXN0aW5nLmxlbmd0aCkge1xuICAgICAgICAgICAgICBsb2cuZGVidWcoXCJleGlzdGluZzogXCIsIGV4aXN0aW5nLCBcIiBrZXk6IFwiLCBrZXkpO1xuICAgICAgICAgICAgICBwYXJlbnRFbC5hcHBlbmQoJGNvbXBpbGUoY3JlYXRlRWxlbWVudCh0ZW1wbGF0ZSwgdGhpbmdOYW1lLCB0aGluZykpKHNjb3BlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gbmFtZXNwYWNlRmlsdGVyKGl0ZW0pIHtcbiAgICAgICAgICAgIHJldHVybiBnZXROYW1lc3BhY2UoaXRlbSkgPT09IHNjb3BlLmt1YmVybmV0ZXMuc2VsZWN0ZWROYW1lc3BhY2U7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZmlyc3REcmF3KCkge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZpcnN0IGRyYXdcIik7XG4gICAgICAgICAgZWxlbWVudC5lbXB0eSgpO1xuICAgICAgICAgIHZhciBzZXJ2aWNlcyA9IG1vZGVsLnNlcnZpY2VzO1xuICAgICAgICAgIHZhciByZXBsaWNhdGlvbkNvbnRyb2xsZXJzID0gbW9kZWwucmVwbGljYXRpb25Db250cm9sbGVycztcbiAgICAgICAgICB2YXIgcG9kcyA9IG1vZGVsLnBvZHM7XG4gICAgICAgICAgdmFyIGhvc3RzID0gbW9kZWwuaG9zdHM7XG4gICAgICAgICAgLy8gbG9nLmRlYnVnKFwiaG9zdHM6IFwiLCBtb2RlbC5ob3N0cyk7XG4gICAgICAgICAgdmFyIHBhcmVudEVsID0gYW5ndWxhci5lbGVtZW50KCR0ZW1wbGF0ZUNhY2hlLmdldChcIm92ZXJ2aWV3VGVtcGxhdGUuaHRtbFwiKSk7XG4gICAgICAgICAgdmFyIHNlcnZpY2VzRWwgPSBwYXJlbnRFbC5maW5kKFwiLnNlcnZpY2VzXCIpO1xuICAgICAgICAgIHZhciBob3N0c0VsID0gcGFyZW50RWwuZmluZChcIi5ob3N0c1wiKTtcbiAgICAgICAgICB2YXIgcmVwbGljYXRpb25Db250cm9sbGVyc0VsID0gcGFyZW50RWwuZmluZChcIi5yZXBsaWNhdGlvbkNvbnRyb2xsZXJzXCIpO1xuXG4gICAgICAgICAgc2VydmljZXNFbC5hcHBlbmQoY3JlYXRlRWxlbWVudHMoJHRlbXBsYXRlQ2FjaGUuZ2V0KFwic2VydmljZVRlbXBsYXRlLmh0bWxcIiksICdzZXJ2aWNlJywgc2VydmljZXMuZmlsdGVyKG5hbWVzcGFjZUZpbHRlcikpKTtcbiAgICAgICAgICByZXBsaWNhdGlvbkNvbnRyb2xsZXJzRWwuYXBwZW5kKGNyZWF0ZUVsZW1lbnRzKCR0ZW1wbGF0ZUNhY2hlLmdldChcInJlcGxpY2F0aW9uQ29udHJvbGxlclRlbXBsYXRlLmh0bWxcIiksICdyZXBsaWNhdGlvbkNvbnRyb2xsZXInLCByZXBsaWNhdGlvbkNvbnRyb2xsZXJzLmZpbHRlcihuYW1lc3BhY2VGaWx0ZXIpKSk7XG5cbiAgICAgICAgICBob3N0cy5mb3JFYWNoKChob3N0KSA9PiB7XG4gICAgICAgICAgICB2YXIgaG9zdEVsID0gYW5ndWxhci5lbGVtZW50KGNyZWF0ZUVsZW1lbnQoJHRlbXBsYXRlQ2FjaGUuZ2V0KFwib3ZlcnZpZXdIb3N0VGVtcGxhdGUuaHRtbFwiKSwgJ2hvc3QnLCBob3N0KSk7XG4gICAgICAgICAgICB2YXIgcG9kQ29udGFpbmVyID0gYW5ndWxhci5lbGVtZW50KGhvc3RFbC5maW5kKCcucG9kLWNvbnRhaW5lcicpKTtcbiAgICAgICAgICAgIHBvZENvbnRhaW5lci5hcHBlbmQoY3JlYXRlRWxlbWVudHMoJHRlbXBsYXRlQ2FjaGUuZ2V0KFwicG9kVGVtcGxhdGUuaHRtbFwiKSwgXCJwb2RcIiwgaG9zdC5wb2RzKSk7XG4gICAgICAgICAgICBob3N0c0VsLmFwcGVuZChob3N0RWwpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIC8vcGFyZW50RWwuYXBwZW5kKGNyZWF0ZUVsZW1lbnRzKCR0ZW1wbGF0ZUNhY2hlLmdldChcInBvZFRlbXBsYXRlLmh0bWxcIiksICdwb2QnLCBwb2RzKSk7XG4gICAgICAgICAgZWxlbWVudC5hcHBlbmQoJGNvbXBpbGUocGFyZW50RWwpKHNjb3BlKSk7XG4gICAgICAgICAgJHRpbWVvdXQoKCkgPT4geyBlbGVtZW50LmNzcyh7dmlzaWJpbGl0eTogJ3Zpc2libGUnfSk7IH0sIDI1MCk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiB1cGRhdGUoKSB7XG4gICAgICAgICAgc2NvcGUuJGVtaXQoJ2pzcGx1bWJEb1doaWxlU3VzcGVuZGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgbG9nLmRlYnVnKFwiVXBkYXRlXCIpO1xuICAgICAgICAgICAgdmFyIHNlcnZpY2VzID0gbW9kZWwuc2VydmljZXM7XG4gICAgICAgICAgICB2YXIgcmVwbGljYXRpb25Db250cm9sbGVycyA9IG1vZGVsLnJlcGxpY2F0aW9uQ29udHJvbGxlcnM7XG4gICAgICAgICAgICB2YXIgcG9kcyA9IG1vZGVsLnBvZHM7XG4gICAgICAgICAgICB2YXIgaG9zdHMgPSBtb2RlbC5ob3N0cztcbiAgICAgICAgICAgIHZhciBwYXJlbnRFbCA9IGVsZW1lbnQuZmluZCgnW2hhd3Rpby1qc3BsdW1iXScpO1xuICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gcGFyZW50RWwuZmluZCgnLmpzcGx1bWItbm9kZScpO1xuICAgICAgICAgICAgY2hpbGRyZW4uZWFjaCgoaW5kZXgsIGMpID0+IHtcbiAgICAgICAgICAgICAgdmFyIGNoaWxkID0gYW5ndWxhci5lbGVtZW50KGMpO1xuICAgICAgICAgICAgICB2YXIga2V5ID0gY2hpbGQuYXR0cignaWQnKTtcbiAgICAgICAgICAgICAgbG9nLmRlYnVnKCdrZXk6ICcsIGtleSk7XG4gICAgICAgICAgICAgIGlmIChDb3JlLmlzQmxhbmsoa2V5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB2YXIgdHlwZSA9IGNoaWxkLmF0dHIoJ2RhdGEtdHlwZScpO1xuICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdob3N0JzpcbiAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gbW9kZWwucG9kc0J5SG9zdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzZXJ2aWNlJzpcbiAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gbW9kZWwuc2VydmljZXNCeUtleSAmJiBnZXROYW1lc3BhY2UobW9kZWwuc2VydmljZXNCeUtleVtrZXldKSA9PSBzY29wZS5rdWJlcm5ldGVzLnNlbGVjdGVkTmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzZXJ2aWNlID0gbW9kZWwuc2VydmljZXNCeUtleVtrZXldO1xuICAgICAgICAgICAgICAgICAgICBjaGlsZC5hdHRyKCdjb25uZWN0LXRvJywgc2VydmljZS5jb25uZWN0VG8pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdwb2QnOlxuICAgICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgIGlmIChoYXNJZChwb2RzLCBpZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gbW9kZWwucG9kc0J5S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JlcGxpY2F0aW9uQ29udHJvbGxlcic6XG4gICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIG1vZGVsLnJlcGxpY2F0aW9uQ29udHJvbGxlcnNCeUtleSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVwbGljYXRpb25Db250cm9sbGVyID0gbW9kZWwucmVwbGljYXRpb25Db250cm9sbGVyc0J5S2V5W2tleV07XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkLmF0dHIoJ2Nvbm5lY3QtdG8nLCByZXBsaWNhdGlvbkNvbnRyb2xsZXIuY29ubmVjdFRvKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIklnbm9yaW5nIGVsZW1lbnQgd2l0aCB1bmtub3duIHR5cGVcIik7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiUmVtb3Zpbmc6IFwiLCBrZXkpO1xuICAgICAgICAgICAgICBjaGlsZC5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIHNlcnZpY2VzRWwgPSBlbGVtZW50LmZpbmQoXCIuc2VydmljZXNcIik7XG4gICAgICAgICAgICB2YXIgcmVwbGljYXRpb25Db250cm9sbGVyc0VsID0gZWxlbWVudC5maW5kKFwiLnJlcGxpY2F0aW9uQ29udHJvbGxlcnNcIik7XG4gICAgICAgICAgICB2YXIgaG9zdHNFbCA9IGVsZW1lbnQuZmluZChcIi5ob3N0c1wiKTtcblxuICAgICAgICAgICAgYXBwZW5kTmV3RWxlbWVudHMoc2VydmljZXNFbCwgJHRlbXBsYXRlQ2FjaGUuZ2V0KFwic2VydmljZVRlbXBsYXRlLmh0bWxcIiksIFwic2VydmljZVwiLCBzZXJ2aWNlcyk7XG4gICAgICAgICAgICBhcHBlbmROZXdFbGVtZW50cyhyZXBsaWNhdGlvbkNvbnRyb2xsZXJzRWwsICR0ZW1wbGF0ZUNhY2hlLmdldChcInJlcGxpY2F0aW9uQ29udHJvbGxlclRlbXBsYXRlLmh0bWxcIiksIFwicmVwbGljYXRpb25Db250cm9sbGVyXCIsIHJlcGxpY2F0aW9uQ29udHJvbGxlcnMpO1xuICAgICAgICAgICAgYXBwZW5kTmV3RWxlbWVudHMoaG9zdHNFbCwgJHRlbXBsYXRlQ2FjaGUuZ2V0KFwib3ZlcnZpZXdIb3N0VGVtcGxhdGUuaHRtbFwiKSwgXCJob3N0XCIsIGhvc3RzKTtcbiAgICAgICAgICAgIGhvc3RzLmZvckVhY2goKGhvc3QpID0+IHtcbiAgICAgICAgICAgICAgdmFyIGhvc3RFbCA9IGFuZ3VsYXIuZWxlbWVudChob3N0c0VsLmZpbmQoXCIjXCIgKyBob3N0LmVsZW1lbnRJZCkpO1xuICAgICAgICAgICAgICB2YXIgcG9kQ29udGFpbmVyID0gYW5ndWxhci5lbGVtZW50KGhvc3RFbC5maW5kKCcucG9kLWNvbnRhaW5lcicpKTtcbiAgICAgICAgICAgICAgYXBwZW5kTmV3RWxlbWVudHMocG9kQ29udGFpbmVyLCAkdGVtcGxhdGVDYWNoZS5nZXQoXCJwb2RUZW1wbGF0ZS5odG1sXCIpLCBcInBvZFwiLCBob3N0LnBvZHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiByZWZyZXNoRHJhd2luZygpIHtcbiAgICAgICAgICBsb2cuZGVidWcoXCJSZWZyZXNoaW5nIGRyYXdpbmdcIik7XG4gICAgICAgICAgaWYgKGVsZW1lbnQuY2hpbGRyZW4oKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGZpcnN0RHJhdygpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cGRhdGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgQ29yZS4kYXBwbHkoc2NvcGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgXy5kZWJvdW5jZShyZWZyZXNoRHJhd2luZywgNTAwLCB7IHRyYWlsaW5nOiB0cnVlfSkpO1xuICAgICAgICBzZXRUaW1lb3V0KHJlZnJlc2hEcmF3aW5nLCAxMDApO1xuICAgICAgfVxuICAgIH07XG4gIH1dKTtcblxuICB2YXIgT3ZlcnZpZXdCb3hDb250cm9sbGVyID0gY29udHJvbGxlcihcIk92ZXJ2aWV3Qm94Q29udHJvbGxlclwiLCBbXCIkc2NvcGVcIiwgXCIkbG9jYXRpb25cIiwgKCRzY29wZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UpID0+IHtcbiAgICAkc2NvcGUudmlld0RldGFpbHMgPSAoZW50aXR5LCBwYXRoOnN0cmluZykgPT4ge1xuICAgICAgaWYgKGVudGl0eSkge1xuICAgICAgICB2YXIgbmFtZXNwYWNlID0gZ2V0TmFtZXNwYWNlKGVudGl0eSk7XG4gICAgICAgIHZhciBpZCA9IGdldE5hbWUoZW50aXR5KTtcbiAgICAgICAgJGxvY2F0aW9uLnBhdGgoVXJsSGVscGVycy5qb2luKCcva3ViZXJuZXRlcy9uYW1lc3BhY2UnLCBuYW1lc3BhY2UsIHBhdGgsIGlkKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2cud2FybihcIk5vIGVudGl0eSBmb3Igdmlld0RldGFpbHMhXCIpO1xuICAgICAgfVxuICAgIH1cbiAgfV0pO1xuXG4gIHZhciBzY29wZU5hbWUgPSBcIk92ZXJ2aWV3Q29udHJvbGxlclwiO1xuXG4gIHZhciBPdmVydmlld0NvbnRyb2xsZXIgPSBjb250cm9sbGVyKHNjb3BlTmFtZSwgW1wiJHNjb3BlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLCAoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCkgPT4ge1xuICAgICRzY29wZS5uYW1lID0gc2NvcGVOYW1lO1xuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcblxuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgIC8vJHNjb3BlLnN1YlRhYkNvbmZpZyA9IFtdO1xuICB9XSk7XG5cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBQaXBlbGluZXNDb250cm9sbGVyID0gY29udHJvbGxlcihcIlBpcGVsaW5lc0NvbnRyb2xsZXJcIiwgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiJGRpYWxvZ1wiLCBcIiR3aW5kb3dcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRsb2NhdGlvblwiLCBcImxvY2FsU3RvcmFnZVwiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCAkZGlhbG9nLCAkd2luZG93LCAkdGVtcGxhdGVDYWNoZSwgJHJvdXRlUGFyYW1zLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgbG9jYWxTdG9yYWdlLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG5cbiAgICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICAgLyoqXG4gICAgICAgKiBMZXRzIHVwZGF0ZSB0aGUgdmFyaW91cyBkYXRhIHRvIGpvaW4gdGhlbSB0b2dldGhlciB0byBhIHBpcGVsaW5lIG1vZGVsXG4gICAgICAgKi9cbiAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgIHZhciBwaXBlbGluZVN0ZXBzID0ge307XG4gICAgICAgIGlmICgkc2NvcGUuYnVpbGRDb25maWdzICYmICRzY29wZS5idWlsZHMgJiYgJHNjb3BlLmRlcGxveW1lbnRDb25maWdzKSB7XG4gICAgICAgICAgZW5yaWNoQnVpbGRDb25maWdzKCRzY29wZS5idWlsZENvbmZpZ3MsICRzY29wZS5idWlsZHMpO1xuICAgICAgICAgICRzY29wZS5mZXRjaGVkID0gdHJ1ZTtcblxuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaCgkc2NvcGUuYnVpbGRDb25maWdzLCAoYnVpbGRDb25maWcpID0+IHtcbiAgICAgICAgICAgIHZhciBwaXBlbGluZUtleSA9IGNyZWF0ZVBpcGVsaW5lS2V5KGJ1aWxkQ29uZmlnKTtcbiAgICAgICAgICAgIGlmIChwaXBlbGluZUtleSkge1xuICAgICAgICAgICAgICBwaXBlbGluZVN0ZXBzW3BpcGVsaW5lS2V5XSA9IHtcbiAgICAgICAgICAgICAgICBidWlsZENvbmZpZzogYnVpbGRDb25maWcsXG4gICAgICAgICAgICAgICAgYnVpbGRzOiBbXSxcbiAgICAgICAgICAgICAgICB0cmlnZ2VyZWRCeTogbnVsbCxcbiAgICAgICAgICAgICAgICB0cmlnZ2Vyc1N0ZXBzOiBbXSxcbiAgICAgICAgICAgICAgICAkY2xhc3M6ICdwaXBlbGluZS1idWlsZCdcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaCgkc2NvcGUuYnVpbGRzLCAoYnVpbGQpID0+IHtcbiAgICAgICAgICAgIHZhciBwaXBlbGluZUtleSA9IGNyZWF0ZVBpcGVsaW5lS2V5KGJ1aWxkKTtcbiAgICAgICAgICAgIGlmIChwaXBlbGluZUtleSkge1xuICAgICAgICAgICAgICB2YXIgcGlwZWxpbmUgPSBwaXBlbGluZVN0ZXBzW3BpcGVsaW5lS2V5XTtcbiAgICAgICAgICAgICAgaWYgKCFwaXBlbGluZSkge1xuICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJ3YXJuaW5nIG5vIHBpcGVsaW5lIGdlbmVyYXRlZCBmb3IgYnVpbGRDb25maWcgZm9yIGtleSBcIiArIHBpcGVsaW5lS2V5ICsgXCIgZm9yIGJ1aWxkIFwiICsgYW5ndWxhci50b0pzb24oYnVpbGQsIHRydWUpKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIndhcm5pbmcgbm8gcGlwZWxpbmUgZ2VuZXJhdGVkIGZvciBidWlsZENvbmZpZyBmb3Iga2V5IFwiICsgcGlwZWxpbmVLZXkgKyBcIiBmb3IgYnVpbGQgXCIgKyBidWlsZC4kbmFtZSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGlwZWxpbmUuYnVpbGRzLnB1c2goYnVpbGQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBUT0RPIG5vdyB3ZSBuZWVkIHRvIGxvb2sgYXQgdGhlIHRyaWdnZXJzIHRvIGZpZ3VyZSBvdXQgd2hpY2ggcGlwZWxpbmVTdGVwcyB0cmlnZ2VycyBlYWNoIHBpcGVsaW5lU3RlcFxuXG5cbiAgICAgICAgICAvLyBub3cgbGV0cyBjcmVhdGUgYW4gYXJyYXkgb2YgYWxsIHBpcGVsaW5lcywgc3RhcnRpbmcgZnJvbSB0aGUgZmlyc3Qga25vd24gc3RlcCB3aXRoIGEgbGlzdCBvZiB0aGUgc3RlcHNcblxuICAgICAgICAgIHZhciBwaXBlbGluZXMgPSBbXTtcbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2gocGlwZWxpbmVTdGVwcywgKHBpcGVsaW5lU3RlcCwga2V5KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXBpcGVsaW5lU3RlcC50cmlnZ2VyZWRCeSkge1xuICAgICAgICAgICAgICAvLyB3ZSBhcmUgYSByb290IHN0ZXAuLi4uXG4gICAgICAgICAgICAgIHBpcGVsaW5lcy5wdXNoKHBpcGVsaW5lU3RlcCk7XG4gICAgICAgICAgICAgIC8vIG5vdyBsZXRzIGFkZCBhbGwgdGhlIHN0ZXBzIGZvciB0aGlzIGtleS4uLlxuICAgICAgICAgICAgICBwaXBlbGluZVN0ZXAudHJpZ2dlcnNTdGVwcy5wdXNoKHBpcGVsaW5lU3RlcCk7XG4gICAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChwaXBlbGluZVN0ZXBzLCAoc3RlcCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChzdGVwLnRyaWdnZXJlZEJ5ID09PSBrZXkpIHtcbiAgICAgICAgICAgICAgICAgIHBpcGVsaW5lU3RlcC50cmlnZ2Vyc1N0ZXBzLnB1c2goc3RlcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaCgkc2NvcGUuZGVwbG95bWVudENvbmZpZ3MsIChkZXBsb3ltZW50Q29uZmlnKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWRlcGxveW1lbnRDb25maWcua2luZCkge1xuICAgICAgICAgICAgICBkZXBsb3ltZW50Q29uZmlnLmtpbmQgPSBcIkRlcGxveW1lbnRDb25maWdcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChkZXBsb3ltZW50Q29uZmlnLnRyaWdnZXJzLCAodHJpZ2dlcikgPT4ge1xuICAgICAgICAgICAgICB2YXIgdHlwZSA9IHRyaWdnZXIudHlwZTtcbiAgICAgICAgICAgICAgdmFyIGltYWdlQ2hhbmdlUGFyYW1zID0gdHJpZ2dlci5pbWFnZUNoYW5nZVBhcmFtcztcbiAgICAgICAgICAgICAgaWYgKGltYWdlQ2hhbmdlUGFyYW1zICYmIHR5cGUgPT09IFwiSW1hZ2VDaGFuZ2VcIikge1xuICAgICAgICAgICAgICAgIHZhciBmcm9tID0gaW1hZ2VDaGFuZ2VQYXJhbXMuZnJvbTtcbiAgICAgICAgICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgICAgICAgICAgdmFyIG5hbWUgPSBmcm9tLm5hbWU7XG4gICAgICAgICAgICAgICAgICBpZiAoZnJvbS5raW5kID09PSBcIkltYWdlUmVwb3NpdG9yeVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0YWcgPSBpbWFnZUNoYW5nZVBhcmFtcy50YWcgfHwgXCJsYXRlc3RcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBub3cgbGV0cyBmaW5kIGEgcGlwZWxpbmUgc3RlcCB3aGljaCBmaXJlcyBmcm9tIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyLmZvckVhY2gocGlwZWxpbmVTdGVwcywgKHBpcGVsaW5lU3RlcCwga2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG8gPSBDb3JlLnBhdGhHZXQocGlwZWxpbmVTdGVwLCBbXCJidWlsZENvbmZpZ1wiLCBcInBhcmFtZXRlcnNcIiwgXCJvdXRwdXRcIiwgXCJ0b1wiXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodG8gJiYgKHRvLmtpbmQgPT09IFwiSW1hZ2VSZXBvc2l0b3J5XCIgfHwgdG8ua2luZCA9PT0gXCJJbWFnZVN0cmVhbVwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG9OYW1lID0gdG8ubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRvTmFtZSA9PT0gbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3RvciA9IENvcmUucGF0aEdldChkZXBsb3ltZW50Q29uZmlnLCBbXCJ0ZW1wbGF0ZVwiLCBcImNvbnRyb2xsZXJUZW1wbGF0ZVwiLCBcInNlbGVjdG9yXCJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG9kcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkcG9kQ291bnRlcnMgPSBzZWxlY3RvciA/IGNyZWF0ZVBvZENvdW50ZXJzKHNlbGVjdG9yLCBLdWJlcm5ldGVzTW9kZWwucG9kc0Zvck5hbWVzcGFjZSgpLCBwb2RzKSA6IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlcGxveVBpcGVsaW5lU3RlcCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1aWxkQ29uZmlnOiBkZXBsb3ltZW50Q29uZmlnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGNsYXNzOiAncGlwZWxpbmUtZGVwbG95JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwb2RDb3VudGVyczogJHBvZENvdW50ZXJzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHBvZHM6IHBvZHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpcGVsaW5lU3RlcC50cmlnZ2Vyc1N0ZXBzLnB1c2goZGVwbG95UGlwZWxpbmVTdGVwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAkc2NvcGUucGlwZWxpbmVzID0gcGlwZWxpbmVzO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8qKlxuICAgICAgICogTGV0cyBjcmVhdGUgYSB1bmlxdWUga2V5IGZvciBidWlsZCAvIGNvbmZpZyB3ZSBjYW4gdXNlIHRvIGRvIGxpbmtpbmcgb2YgYnVpbGRzIC8gY29uZmlncyAvIHRyaWdnZXJzXG4gICAgICAgKi9cbiAgICAgIGZ1bmN0aW9uIGNyZWF0ZVBpcGVsaW5lS2V5KGJ1aWxkQ29uZmlnKSB7XG4gICAgICAgIHJldHVybiBDb3JlLnBhdGhHZXQoYnVpbGRDb25maWcsIFtcInBhcmFtZXRlcnNcIiwgXCJzb3VyY2VcIiwgXCJnaXRcIiwgXCJ1cmlcIl0pO1xuICAgICAgfVxuXG4gICAgICAkc2NvcGUuJGtlZXBQb2xsaW5nID0gKCkgPT4ga2VlcFBvbGxpbmdNb2RlbDtcbiAgICAgICRzY29wZS5mZXRjaCA9IFBvbGxIZWxwZXJzLnNldHVwUG9sbGluZygkc2NvcGUsIChuZXh0OigpID0+IHZvaWQpID0+IHtcbiAgICAgICAgdmFyIHJlYWR5ID0gMDtcbiAgICAgICAgdmFyIG51bVNlcnZpY2VzID0gMztcblxuICAgICAgICBmdW5jdGlvbiBtYXliZU5leHQoKSB7XG4gICAgICAgICAgaWYgKCsrcmVhZHkgPj0gbnVtU2VydmljZXMpIHtcbiAgICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdXJsID0gYnVpbGRzUmVzdFVSTCgpO1xuICAgICAgICAkaHR0cC5nZXQodXJsKS5cbiAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgJHNjb3BlLmJ1aWxkcyA9IGVucmljaEJ1aWxkcyhkYXRhLml0ZW1zKTtcbiAgICAgICAgICAgICAgdXBkYXRlRGF0YSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWF5YmVOZXh0KCk7XG4gICAgICAgICAgfSkuXG4gICAgICAgICAgZXJyb3IoZnVuY3Rpb24gKGRhdGEsIHN0YXR1cywgaGVhZGVycywgY29uZmlnKSB7XG4gICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBsb2FkIFwiICsgdXJsICsgXCIgXCIgKyBkYXRhICsgXCIgXCIgKyBzdGF0dXMpO1xuICAgICAgICAgICAgbWF5YmVOZXh0KCk7XG5cbiAgICAgICAgICB9KTtcbiAgICAgICAgdXJsID0gYnVpbGRDb25maWdzUmVzdFVSTCgpO1xuICAgICAgICAkaHR0cC5nZXQodXJsKS5cbiAgICAgICAgICBzdWNjZXNzKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgJHNjb3BlLmJ1aWxkQ29uZmlncyA9IGRhdGEuaXRlbXM7XG4gICAgICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1heWJlTmV4dCgpO1xuICAgICAgICAgIH0pLlxuICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgIG1heWJlTmV4dCgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB1cmwgPSBkZXBsb3ltZW50Q29uZmlnc1Jlc3RVUkwoKTtcbiAgICAgICAgJGh0dHAuZ2V0KHVybCkuXG4gICAgICAgICAgc3VjY2VzcyhmdW5jdGlvbiAoZGF0YSwgc3RhdHVzLCBoZWFkZXJzLCBjb25maWcpIHtcbiAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICRzY29wZS5kZXBsb3ltZW50Q29uZmlncyA9IGRhdGEuaXRlbXM7XG4gICAgICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1heWJlTmV4dCgpO1xuICAgICAgICAgIH0pLlxuICAgICAgICAgIGVycm9yKGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMsIGhlYWRlcnMsIGNvbmZpZykge1xuICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gbG9hZCBcIiArIHVybCArIFwiIFwiICsgZGF0YSArIFwiIFwiICsgc3RhdHVzKTtcbiAgICAgICAgICAgIG1heWJlTmV4dCgpO1xuICAgICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgICRzY29wZS5mZXRjaCgpO1xuICAgIH1dKTtcblxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIFBvZENvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiUG9kQ29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIlNlcnZpY2VSZWdpc3RyeVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIiR3aW5kb3dcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6IEt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBTZXJ2aWNlUmVnaXN0cnksXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsICR3aW5kb3csIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAkc2NvcGUucmF3TW9kZWwgPSBudWxsO1xuXG4gICAgJHNjb3BlLml0ZW1Db25maWcgPSB7XG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICdjb250YWluZXJzL2ltYWdlJCc6IHtcbiAgICAgICAgICB0ZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KCdpbWFnZVRlbXBsYXRlLmh0bWwnKVxuICAgICAgICB9LFxuICAgICAgICAnc3RhdHVzL3BoYXNlJzoge1xuICAgICAgICAgIHRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoJ3N0YXR1c1RlbXBsYXRlLmh0bWwnKVxuICAgICAgICB9LFxuICAgICAgICAnXFxcXC9FbnZcXFxcLyc6IHtcbiAgICAgICAgICB0ZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KCdlbnZJdGVtVGVtcGxhdGUuaHRtbCcpXG4gICAgICAgIH0sXG4gICAgICAgICdeXFxcXC9sYWJlbHMkJzoge1xuICAgICAgICAgIHRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoJ2xhYmVsVGVtcGxhdGUuaHRtbCcpXG4gICAgICAgIH0sXG4gICAgICAgICdcXFxcL2VudlxcXFwva2V5JCc6IHtcbiAgICAgICAgICBoaWRkZW46IHRydWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG5cbiAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgdXBkYXRlRGF0YSgpO1xuICAgIH0pO1xuXG4gICAgJHNjb3BlLiRvbignJHJvdXRlVXBkYXRlJywgKCRldmVudCkgPT4ge1xuICAgICAgdXBkYXRlRGF0YSgpO1xuICAgIH0pO1xuXG4gICAgJHNjb3BlLiR3YXRjaCgnbW9kZWwucG9kcycsIChuZXdWYWx1ZSwgb2xkVmFsdWUpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9LCB0cnVlKTtcblxuICAgICRzY29wZS5mbGlwUmF3ID0gKCkgPT4ge1xuICAgICAgJHNjb3BlLnJhd01vZGUgPSAhJHNjb3BlLnJhd01vZGU7XG4gICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgIH07XG5cbiAgICAkc2NvcGUub3BlbkxvZ3MgPSAoKSA9PiB7XG4gICAgICB2YXIgcG9kcyA9IFskc2NvcGUuaXRlbV07XG4gICAgICBvcGVuTG9nc0ZvclBvZHMoU2VydmljZVJlZ2lzdHJ5LCAkd2luZG93LCBLdWJlcm5ldGVzTW9kZWwuY3VycmVudE5hbWVzcGFjZSgpLCBwb2RzKTtcbiAgICB9O1xuXG4gICAgdXBkYXRlRGF0YSgpO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICAgJHNjb3BlLml0ZW0gPSAkc2NvcGUubW9kZWwuZ2V0UG9kKEt1YmVybmV0ZXNTdGF0ZS5zZWxlY3RlZE5hbWVzcGFjZSwgJHNjb3BlLmlkKTtcbiAgICAgIGlmICgkc2NvcGUuaXRlbSkge1xuICAgICAgICAkc2NvcGUucmF3TW9kZWwgPSB0b1Jhd1lhbWwoJHNjb3BlLml0ZW0pO1xuICAgICAgfVxuICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICB9XG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBQb2RFZGl0Q29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJQb2RFZGl0Q29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIkt1YmVybmV0ZXNTY2hlbWFcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsIFwiU2NoZW1hUmVnaXN0cnlcIixcbiAgICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDogS3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNTY2hlbWEsXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwsIHNjaGVtYXM6SGF3dGlvRm9ybXMuU2NoZW1hUmVnaXN0cnkpID0+IHtcblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAkc2NvcGUuaWQgPSAkcm91dGVQYXJhbXNbXCJpZFwiXTtcbiAgICAkc2NvcGUuc2NoZW1hID0gS3ViZXJuZXRlc1NjaGVtYTtcbiAgICAkc2NvcGUuY29uZmlnID0gc2NoZW1hcy5jbG9uZVNjaGVtYShcImlvLmZhYnJpYzgua3ViZXJuZXRlcy5hcGkubW9kZWwuUG9kXCIpO1xuICAgIC8vJHNjb3BlLmNvbmZpZyA9IEt1YmVybmV0ZXNTY2hlbWEuZGVmaW5pdGlvbnMua3ViZXJuZXRlc192MWJldGEyX1BvZDtcblxuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9KTtcblxuICAgIHVwZGF0ZURhdGEoKTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICBpZiAoJHNjb3BlLmlkKSB7XG4gICAgICAgICRzY29wZS5lbnRpdHkgPSAkc2NvcGUubW9kZWwuZ2V0UG9kKEt1YmVybmV0ZXNTdGF0ZS5zZWxlY3RlZE5hbWVzcGFjZSwgJHNjb3BlLmlkKTtcbiAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgICRzY29wZS5zYXZlID0gKCk9PntcbiAgICAgIGNvbnNvbGUubG9nKCRzY29wZS5lbnRpdHkpO1xuICAgIH1cbiAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcbiAgdmFyIGxvZyA9IExvZ2dlci5nZXQoJ2t1YmVybmV0ZXMtd2F0Y2hlcicpO1xuXG4gIHZhciBrOHNUeXBlcyA9IEt1YmVybmV0ZXNBUEkuTmFtZXNwYWNlZFR5cGVzLms4c1R5cGVzO1xuICB2YXIgb3NUeXBlcyAgPSBLdWJlcm5ldGVzQVBJLk5hbWVzcGFjZWRUeXBlcy5vc1R5cGVzO1xuXG4gIHZhciBzZWxmID0gPGFueT4ge307XG5cbiAgdmFyIHVwZGF0ZUZ1bmN0aW9uID0gKCkgPT4ge1xuICAgIFxuICAgIGxvZy5kZWJ1ZyhcIk9iamVjdHMgY2hhbmdlZCwgZmlyaW5nIGxpc3RlbmVyc1wiKTtcbiAgICB2YXIgb2JqZWN0cyA9IDxPYmplY3RNYXA+e307XG4gICAgXy5mb3JFYWNoKHNlbGYuZ2V0VHlwZXMoKSwgKHR5cGU6c3RyaW5nKSA9PiB7XG4gICAgICBvYmplY3RzW3R5cGVdID0gc2VsZi5nZXRPYmplY3RzKHR5cGUpO1xuICAgIH0pO1xuICAgIF8uZm9yRWFjaChzZWxmLmxpc3RlbmVycywgKGxpc3RlbmVyOihPYmplY3RNYXApID0+IHZvaWQpID0+IHtcbiAgICAgIGxpc3RlbmVyKG9iamVjdHMpO1xuICAgIH0pO1xuICB9O1xuICB2YXIgZGVib3VuY2VkVXBkYXRlID0gXy5kZWJvdW5jZSh1cGRhdGVGdW5jdGlvbiwgNzUsIHsgdHJhaWxpbmc6IHRydWUgfSk7XG5cbiAgdmFyIG5hbWVzcGFjZVdhdGNoID0ge1xuICAgIHNlbGVjdGVkOiB1bmRlZmluZWQsXG4gICAgd2F0Y2g6IHVuZGVmaW5lZCxcbiAgICBvYmplY3RzOiBbXSxcbiAgICBvYmplY3RNYXA6IHt9LFxuICAgIHdhdGNoZXM6IHt9XG4gIH07XG5cbiAgaGF3dGlvUGx1Z2luTG9hZGVyLnJlZ2lzdGVyUHJlQm9vdHN0cmFwVGFzayh7XG4gICAgbmFtZTogJ0t1YmVybmV0ZXNXYXRjaGVySW5pdCcsXG4gICAgZGVwZW5kczogWydLdWJlcm5ldGVzQXBpRGlzY292ZXJ5J10sXG4gICAgdGFzazogKG5leHQpID0+IHtcbiAgICAgIHZhciBib290ZWQgPSBmYWxzZTtcbiAgICAgIGlmIChpc09wZW5TaGlmdCkge1xuICAgICAgICBsb2cuaW5mbyhcIkJhY2tlbmQgaXMgYW4gT3BlbnNoaWZ0IGluc3RhbmNlXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nLmluZm8oXCJCYWNrZW5kIGlzIGEgdmFuaWxsYSBLdWJlcm5ldGVzIGluc3RhbmNlXCIpO1xuICAgICAgfVxuICAgICAgbmFtZXNwYWNlV2F0Y2gud2F0Y2ggPSBLdWJlcm5ldGVzQVBJLndhdGNoKHtcbiAgICAgICAga2luZDogS3ViZXJuZXRlc0FQSS5XYXRjaFR5cGVzLk5BTUVTUEFDRVMsXG4gICAgICAgIHN1Y2Nlc3M6IChvYmplY3RzKSA9PiB7XG4gICAgICAgICAgbmFtZXNwYWNlV2F0Y2gub2JqZWN0cyA9IG9iamVjdHM7XG4gICAgICAgICAgaWYgKCFib290ZWQpIHtcbiAgICAgICAgICAgIGJvb3RlZCA9IHRydWU7XG4gICAgICAgICAgICBzZWxmLnNldE5hbWVzcGFjZShsb2NhbFN0b3JhZ2VbQ29uc3RhbnRzLk5BTUVTUEFDRV9TVE9SQUdFX0tFWV0gfHwgZGVmYXVsdE5hbWVzcGFjZSk7XG4gICAgICAgICAgICBuZXh0KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxvZy5kZWJ1ZyhcIkdvdCBuYW1lc3BhY2VzOiBcIiwgbmFtZXNwYWNlV2F0Y2gub2JqZWN0cyk7XG4gICAgICAgIH0sIGVycm9yOiAoZXJyb3I6YW55KSA9PiB7XG4gICAgICAgICAgbG9nLndhcm4oXCJFcnJvciBmZXRjaGluZyBuYW1lc3BhY2VzOiBcIiwgZXJyb3IpO1xuICAgICAgICAgIC8vIFRPRE8gaXMgdGhpcyBuZWNlc3Nhcnk/XG4gICAgICAgICAgLy9IYXd0aW9PQXV0aC5kb0xvZ291dCgpO1xuICAgICAgICAgIGlmICghYm9vdGVkKSB7XG4gICAgICAgICAgICBib290ZWQgPSB0cnVlO1xuICAgICAgICAgICAgbmV4dCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9KTtcblxuICBoYXd0aW9QbHVnaW5Mb2FkZXIucmVnaXN0ZXJQcmVCb290c3RyYXBUYXNrKHtcbiAgICBuYW1lOiAnS3ViZXJuZXRlc0FwaURpc2NvdmVyeScsXG4gICAgZGVwZW5kczogWydoYXd0aW8tb2F1dGgnXSxcbiAgICB0YXNrOiAobmV4dCkgPT4ge1xuICAgICAgaXNPcGVuU2hpZnQgPSBmYWxzZTtcblxuICAgICAgdmFyIHVzZXJQcm9maWxlID0gSGF3dGlvT0F1dGguZ2V0VXNlclByb2ZpbGUoKTtcbiAgICAgIGxvZy5kZWJ1ZyhcIlVzZXIgcHJvZmlsZTogXCIsIHVzZXJQcm9maWxlKTtcbiAgICAgIGlmICh1c2VyUHJvZmlsZSAmJiB1c2VyUHJvZmlsZS5wcm92aWRlciA9PT0gXCJoYXd0aW8tZ29vZ2xlLW9hdXRoXCIpIHtcbiAgICAgICAgbG9nLmRlYnVnKFwiUG9zc2libHkgcnVubmluZyBvbiBHQ0VcIik7XG4gICAgICAgIC8vIGFwaSBtYXN0ZXIgaXMgb24gR0NFXG4gICAgICAgICQuYWpheCh7XG4gICAgICAgICAgdXJsOiBVcmxIZWxwZXJzLmpvaW4obWFzdGVyQXBpVXJsKCksICdhcGknLCAndjEnLCAnbmFtZXNwYWNlcycpLFxuICAgICAgICAgIGNvbXBsZXRlOiAoanFYSFIsIHRleHRTdGF0dXMpID0+IHtcbiAgICAgICAgICAgIGlmICh0ZXh0U3RhdHVzID09PSBcInN1Y2Nlc3NcIikge1xuICAgICAgICAgICAgICBsb2cuZGVidWcoXCJqcVhIUjogXCIsIGpxWEhSKTtcbiAgICAgICAgICAgICAgdXNlclByb2ZpbGUub2xkVG9rZW4gPSB1c2VyUHJvZmlsZS50b2tlbjtcbiAgICAgICAgICAgICAgdXNlclByb2ZpbGUudG9rZW4gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICQuYWpheFNldHVwKHtcbiAgICAgICAgICAgICAgICBiZWZvcmVTZW5kOiAocmVxdWVzdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJlZm9yZVNlbmQ6IChyZXF1ZXN0KSA9PiB7XG5cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nLmRlYnVnKFwiTm90IHJ1bm5pbmcgb24gR0NFXCIpO1xuICAgICAgICAvLyBkb3VibGUtY2hlY2sgaWYgd2UncmUgb24gdmFuaWxsYSBrOHMgb3Igb3BlbnNoaWZ0XG4gICAgICAgIHZhciByb290VXJpID0gbmV3IFVSSShtYXN0ZXJBcGlVcmwoKSkucGF0aChcIi9vYXBpXCIpLnF1ZXJ5KFwiXCIpLnRvU3RyaW5nKCk7XG4gICAgICAgIGxvZy5kZWJ1ZyhcIkNoZWNraW5nIGZvciBhbiBvcGVuc2hpZnQgYmFja2VuZFwiKTtcbiAgICAgICAgSGF3dGlvT0F1dGguYXV0aGVudGljYXRlZEh0dHBSZXF1ZXN0KHtcbiAgICAgICAgICB1cmw6IHJvb3RVcmksXG4gICAgICAgICAgc3VjY2VzczogKGRhdGEpID0+IHtcbiAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgIGlzT3BlblNoaWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGVycm9yOiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSA9PiB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSBLdWJlcm5ldGVzQVBJLmdldEVycm9yT2JqZWN0KGpxWEhSKTtcbiAgICAgICAgICAgIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRmFpbGVkIHRvIGZpbmQgcm9vdCBwYXRoczogXCIsIHRleHRTdGF0dXMsIFwiOiBcIiwgZXJyb3JUaHJvd24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRmFpbGVkIHRvIGZpbmQgcm9vdCBwYXRoczogXCIsIGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzT3BlblNoaWZ0ID0gZmFsc2U7XG4gICAgICAgICAgICBuZXh0KCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHZhciBjdXN0b21VcmxIYW5kbGVycyA9IHt9O1xuXG4gIHNlbGYuc2V0TmFtZXNwYWNlID0gKG5hbWVzcGFjZTogc3RyaW5nKSA9PiB7XG4gICAgaWYgKG5hbWVzcGFjZSA9PT0gbmFtZXNwYWNlV2F0Y2guc2VsZWN0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG5hbWVzcGFjZVdhdGNoLnNlbGVjdGVkKSB7XG4gICAgICBsb2cuZGVidWcoXCJTdG9wcGluZyBjdXJyZW50IHdhdGNoZXNcIik7XG4gICAgICBfLmZvck93bihuYW1lc3BhY2VXYXRjaC53YXRjaGVzLCAod2F0Y2gsIGtleSkgPT4ge1xuICAgICAgICBpZiAoIUt1YmVybmV0ZXNBUEkubmFtZXNwYWNlZChrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGxvZy5kZWJ1ZyhcIkRpc2Nvbm5lY3Rpbmcgd2F0Y2g6IFwiLCBrZXkpO1xuICAgICAgICB3YXRjaC5kaXNjb25uZWN0KCk7XG4gICAgICB9KTtcbiAgICAgIF8uZm9yRWFjaChfLmtleXMobmFtZXNwYWNlV2F0Y2gud2F0Y2hlcyksIChrZXkpID0+IHtcbiAgICAgICAgaWYgKCFLdWJlcm5ldGVzQVBJLm5hbWVzcGFjZWQoa2V5KSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsb2cuZGVidWcoXCJEZWxldGluZyBraW5kOiBcIiwga2V5KTtcbiAgICAgICAgZGVsZXRlIG5hbWVzcGFjZVdhdGNoLndhdGNoZXNba2V5XTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBuYW1lc3BhY2VXYXRjaC5zZWxlY3RlZCA9IG5hbWVzcGFjZTtcbiAgICBpZiAobmFtZXNwYWNlKSB7XG4gICAgICBfLmZvckVhY2goc2VsZi5nZXRUeXBlcygpLCAoa2luZDpzdHJpbmcpID0+IHtcbiAgICAgICAgaWYgKGtpbmQgPT09IEt1YmVybmV0ZXNBUEkuV2F0Y2hUeXBlcy5OQU1FU1BBQ0VTKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbmFtZXNwYWNlV2F0Y2gud2F0Y2hlc1traW5kXSkge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcIkNyZWF0aW5nIHdhdGNoIGZvciBraW5kOiBcIiwga2luZCk7XG4gICAgICAgICAgdmFyIGNvbmZpZyA9IDxhbnk+IHtcbiAgICAgICAgICAgIGtpbmQ6IGtpbmQsXG4gICAgICAgICAgICBuYW1lc3BhY2U6IEt1YmVybmV0ZXNBUEkubmFtZXNwYWNlZChraW5kKSA/IG5hbWVzcGFjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IChvYmplY3RzKSA9PiB7XG4gICAgICAgICAgICAgIHdhdGNoLm9iamVjdHMgPSBvYmplY3RzO1xuICAgICAgICAgICAgICBkZWJvdW5jZWRVcGRhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmIChraW5kIGluIGN1c3RvbVVybEhhbmRsZXJzKSB7XG4gICAgICAgICAgICBjb25maWcudXJsRnVuY3Rpb24gPSBjdXN0b21VcmxIYW5kbGVyc1traW5kXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHdhdGNoID0gPGFueT4gS3ViZXJuZXRlc0FQSS53YXRjaChjb25maWcpO1xuICAgICAgICAgIHdhdGNoLmNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgICBuYW1lc3BhY2VXYXRjaC53YXRjaGVzW2tpbmRdID0gd2F0Y2g7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICBzZWxmLmhhc1dlYlNvY2tldCA9IHRydWU7XG5cbiAgc2VsZi5nZXROYW1lc3BhY2UgPSAoKSA9PiBuYW1lc3BhY2VXYXRjaC5zZWxlY3RlZDtcblxuICBzZWxmLnJlZ2lzdGVyQ3VzdG9tVXJsRnVuY3Rpb24gPSAoa2luZDpzdHJpbmcsIHVybDoob3B0aW9uczpLdWJlcm5ldGVzQVBJLks4U09wdGlvbnMpID0+IHN0cmluZykgPT4ge1xuICAgIGN1c3RvbVVybEhhbmRsZXJzW2tpbmRdID0gdXJsO1xuICAgIGlmIChraW5kIGluIG5hbWVzcGFjZVdhdGNoLndhdGNoZXMpIHtcbiAgICAgIHZhciB3YXRjaCA9IG5hbWVzcGFjZVdhdGNoLndhdGNoZXNba2luZF07XG4gICAgICB2YXIgY29uZmlnID0gd2F0Y2guY29uZmlnO1xuICAgICAgY29uZmlnLnVybEZ1bmN0aW9uID0gdXJsO1xuICAgICAgd2F0Y2guZGlzY29ubmVjdCgpO1xuICAgICAgZGVsZXRlIG5hbWVzcGFjZVdhdGNoLndhdGNoZXNba2luZF07XG4gICAgICBjb25maWcuc3VjY2VzcyA9IChvYmplY3RzKSA9PiB7XG4gICAgICAgIHdhdGNoLm9iamVjdHMgPSBvYmplY3RzO1xuICAgICAgICBkZWJvdW5jZWRVcGRhdGUoKTtcbiAgICAgIH1cbiAgICAgIHdhdGNoID0gPGFueT4gS3ViZXJuZXRlc0FQSS53YXRjaChjb25maWcpO1xuICAgICAgd2F0Y2guY29uZmlnID0gY29uZmlnO1xuICAgICAgbmFtZXNwYWNlV2F0Y2gud2F0Y2hlc1traW5kXSA9IHdhdGNoO1xuICAgIH1cbiAgfVxuXG4gIHNlbGYuZ2V0VHlwZXMgPSAoKSA9PiB7XG4gICAgdmFyIGZpbHRlciA9IChraW5kOnN0cmluZykgPT4ge1xuICAgICAgLy8gZmlsdGVyIG91dCBzdHVmZiB3ZSBkb24ndCBjYXJlIGFib3V0IHlldFxuICAgICAgc3dpdGNoKGtpbmQpIHtcbiAgICAgICAgY2FzZSBLdWJlcm5ldGVzQVBJLldhdGNoVHlwZXMuT0FVVEhfQ0xJRU5UUzpcbiAgICAgICAgY2FzZSBLdWJlcm5ldGVzQVBJLldhdGNoVHlwZXMuSU1BR0VfU1RSRUFNUzpcbiAgICAgICAgY2FzZSBLdWJlcm5ldGVzQVBJLldhdGNoVHlwZXMuUE9MSUNJRVM6XG4gICAgICAgIGNhc2UgS3ViZXJuZXRlc0FQSS5XYXRjaFR5cGVzLlJPTEVTOlxuICAgICAgICBjYXNlIEt1YmVybmV0ZXNBUEkuV2F0Y2hUeXBlcy5ST0xFX0JJTkRJTkdTOlxuICAgICAgICBjYXNlIEt1YmVybmV0ZXNBUEkuV2F0Y2hUeXBlcy5QT0xJQ1lfQklORElOR1M6XG4gICAgICAgIGNhc2UgS3ViZXJuZXRlc0FQSS5XYXRjaFR5cGVzLlBFUlNJU1RFTlRfVk9MVU1FX0NMQUlNUzpcbiAgICAgICAgY2FzZSBLdWJlcm5ldGVzQVBJLldhdGNoVHlwZXMuUEVSU0lTVEVOVF9WT0xVTUVTOlxuICAgICAgICBjYXNlIEt1YmVybmV0ZXNBUEkuV2F0Y2hUeXBlcy5FTkRQT0lOVFM6XG4gICAgICAgIGNhc2UgS3ViZXJuZXRlc0FQSS5XYXRjaFR5cGVzLlJFU09VUkNFX1FVT1RBUzpcbiAgICAgICAgY2FzZSBLdWJlcm5ldGVzQVBJLldhdGNoVHlwZXMuU0VSVklDRV9BQ0NPVU5UUzpcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIGFuc3dlciA9IGs4c1R5cGVzLmNvbmNhdChbV2F0Y2hUeXBlcy5OQU1FU1BBQ0VTXSk7XG4gICAgaWYgKGlzT3BlblNoaWZ0KSB7XG4gICAgICBhbnN3ZXIgPSBhbnN3ZXIuY29uY2F0KG9zVHlwZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbnN3ZXIgPSBhbnN3ZXIuY29uY2F0KEt1YmVybmV0ZXNBUEkuV2F0Y2hUeXBlcy5URU1QTEFURVMpO1xuICAgICAgYW5zd2VyID0gYW5zd2VyLmNvbmNhdChLdWJlcm5ldGVzQVBJLldhdGNoVHlwZXMuQlVJTERfQ09ORklHUyk7XG4gICAgfVxuICAgIHJldHVybiBfLmZpbHRlcihhbnN3ZXIsIGZpbHRlcik7XG4gIH1cblxuICBzZWxmLmdldE9iamVjdHMgPSAoa2luZDogc3RyaW5nKSA9PiB7XG4gICAgaWYgKGtpbmQgPT09IFdhdGNoVHlwZXMuTkFNRVNQQUNFUykge1xuICAgICAgcmV0dXJuIG5hbWVzcGFjZVdhdGNoLm9iamVjdHM7XG4gICAgfVxuICAgIGlmIChraW5kIGluIG5hbWVzcGFjZVdhdGNoLndhdGNoZXMpIHtcbiAgICAgIHJldHVybiBuYW1lc3BhY2VXYXRjaC53YXRjaGVzW2tpbmRdLm9iamVjdHM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgc2VsZi5saXN0ZW5lcnMgPSA8QXJyYXk8KE9iamVjdE1hcCkgPT4gdm9pZD4+IFtdO1xuXG4gIC8vIGxpc3RlbmVyIGdldHMgbm90aWZpZWQgYWZ0ZXIgYSBidW5jaCBvZiBjaGFuZ2VzIGhhdmUgb2NjdXJyZWRcbiAgc2VsZi5yZWdpc3Rlckxpc3RlbmVyID0gKGZuOihvYmplY3RzOk9iamVjdE1hcCkgPT4gdm9pZCkgPT4ge1xuICAgIHNlbGYubGlzdGVuZXJzLnB1c2goZm4pO1xuICB9XG5cbiAgdmFyIHByb2plY3RzSGFuZGxlID0gPGFueT4gdW5kZWZpbmVkO1xuXG4gIC8vIGtpY2sgb2ZmIHRoZSBwcm9qZWN0IHdhdGNoZXIgYSBiaXQgc29vbmVyIGFsc29cbiAgaGF3dGlvUGx1Z2luTG9hZGVyLnJlZ2lzdGVyUHJlQm9vdHN0cmFwVGFzayh7XG4gICAgbmFtZTogJ1Byb2plY3RzV2F0Y2hlcicsXG4gICAgZGVwZW5kczogWydLdWJlcm5ldGVzQXBpRGlzY292ZXJ5J10sXG4gICAgdGFzazogKG5leHQpID0+IHtcbiAgICAgIGlmIChpc09wZW5TaGlmdCkge1xuXG4gICAgICAgIHByb2plY3RzSGFuZGxlID0gS3ViZXJuZXRlc0FQSS53YXRjaCh7XG4gICAgICAgICAga2luZDogS3ViZXJuZXRlc0FQSS5XYXRjaFR5cGVzLlBST0pFQ1RTLFxuICAgICAgICAgIG5hbWVzcGFjZTogdW5kZWZpbmVkLFxuICAgICAgICAgIHN1Y2Nlc3M6IChvYmplY3RzKSA9PiB7XG4gICAgICAgICAgICBpZiAoc2VsZi5saXN0ZW5lcnMgJiYgc2VsZi5saXN0ZW5lcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcImdvdCBwcm9qZWN0czogXCIsIG9iamVjdHMpO1xuICAgICAgICAgICAgICBfLmZvckVhY2goc2VsZi5saXN0ZW5lcnMsIChsaXN0ZW5lcjoob2JqZWN0czpPYmplY3RNYXApID0+IHZvaWQpID0+IHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcih7XG4gICAgICAgICAgICAgICAgICBwcm9qZWN0czogb2JqZWN0c1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgbmV4dCgpO1xuICAgIH1cbiAgfSk7XG5cblxuX21vZHVsZS5zZXJ2aWNlKCdXYXRjaGVyU2VydmljZScsIFsndXNlckRldGFpbHMnLCAnJHJvb3RTY29wZScsICckdGltZW91dCcsICh1c2VyRGV0YWlscywgJHJvb3RTY29wZSwgJHRpbWVvdXQpID0+IHtcbiAgICByZXR1cm4gc2VsZjtcbn1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIndhdGNoZXIudHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICB2YXIgbG9nID0gTG9nZ2VyLmdldChcImt1YmVybmV0ZXMtdGVybS13aW5kb3dzXCIpO1xuXG4gIF9tb2R1bGUuY29uZmlnKChrdWJlcm5ldGVzQ29udGFpbmVyU29ja2V0UHJvdmlkZXIpID0+IHtcbiAgICBrdWJlcm5ldGVzQ29udGFpbmVyU29ja2V0UHJvdmlkZXIuV2ViU29ja2V0RmFjdG9yeSA9IFwiQ3VzdG9tV2ViU29ja2V0c1wiO1xuICB9KTtcblxuICBfbW9kdWxlLmZhY3RvcnkoJ0N1c3RvbVdlYlNvY2tldHMnLCAodXNlckRldGFpbHM6YW55KSA9PiB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIEN1c3RvbVdlYlNvY2tldCh1cmwsIHByb3RvY29scykge1xuICAgICAgdmFyIHBhdGhzID0gdXJsLnNwbGl0KCc/Jyk7XG4gICAgICBpZiAoIV8uc3RhcnRzV2l0aChwYXRoc1swXSwgbWFzdGVyQXBpVXJsKCkpKSB7XG4gICAgICAgIHBhdGhzWzBdID0gVXJsSGVscGVycy5qb2luKG1hc3RlckFwaVVybCgpLCBwYXRoc1swXSk7XG4gICAgICB9XG4gICAgICB1cmwgPSBLdWJlcm5ldGVzQVBJLndzVXJsKHBhdGhzWzBdKTtcbiAgICAgIHVybC5zZWFyY2gocGF0aHNbMV0gKyAnJmFjY2Vzc190b2tlbj0nICsgdXNlckRldGFpbHMudG9rZW4pO1xuICAgICAgbG9nLmRlYnVnKFwiVXNpbmcgd3MgdXJsOiBcIiwgdXJsLnRvU3RyaW5nKCkpO1xuICAgICAgcmV0dXJuIG5ldyBXZWJTb2NrZXQodXJsLnRvU3RyaW5nKCksIHByb3RvY29scyk7XG4gICAgfTtcbiAgfSk7XG5cbiAgX21vZHVsZS5zZXJ2aWNlKCdUZXJtaW5hbFNlcnZpY2UnLCAoJHJvb3RTY29wZSwgJGRvY3VtZW50LCAkY29tcGlsZSwgJHRlbXBsYXRlQ2FjaGUpID0+IHtcbiAgICB2YXIgYm9keSA9ICRkb2N1bWVudC5maW5kKCdib2R5Jyk7XG4gICAgZnVuY3Rpb24gcG9zaXRpb25UZXJtaW5hbHModGVybWluYWxzKSB7XG4gICAgICB2YXIgdG90YWwgPSBfLmtleXModGVybWluYWxzKS5sZW5ndGg7XG4gICAgICB2YXIgZGlzdCA9IChib2R5LndpZHRoKCkgLSAyMjUpIC8gdG90YWw7XG4gICAgICB2YXIgcG9zaXRpb24gPSA1O1xuICAgICAgYW5ndWxhci5mb3JFYWNoKHRlcm1pbmFscywgKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKCF2YWx1ZS5zY29wZS5kb2NrZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFsdWUuZWwuY3NzKCdsZWZ0JywgcG9zaXRpb24gKyAncHgnKTtcbiAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbiArIGRpc3Q7XG4gICAgICB9KTtcbiAgICB9XG4gICAgdmFyIGRlZmF1bHRUZW1wbGF0ZSA9ICR0ZW1wbGF0ZUNhY2hlLmdldChVcmxIZWxwZXJzLmpvaW4odGVtcGxhdGVQYXRoLCAndGVybVNoZWxsLmh0bWwnKSk7XG4gICAgdmFyIHNlbGYgPSB7XG4gICAgICBwb3NpdGlvblRlcm1pbmFsczogKCkgPT4ge1xuICAgICAgICBwb3NpdGlvblRlcm1pbmFscyhzZWxmLnRlcm1pbmFscyk7XG4gICAgICB9LFxuICAgICAgdGVybWluYWxzOiB7fSxcbiAgICAgIG5ld1Rlcm1pbmFsOiAocG9kTGluaywgY29udGFpbmVyTmFtZSwgdGVtcGxhdGUgPSBkZWZhdWx0VGVtcGxhdGUpID0+IHtcbiAgICAgICAgdmFyIHRlcm1pbmFsSWQgPSBVcmxIZWxwZXJzLmpvaW4ocG9kTGluaywgY29udGFpbmVyTmFtZSk7XG4gICAgICAgIGlmICh0ZXJtaW5hbElkIGluIHNlbGYudGVybWluYWxzKSB7XG4gICAgICAgICAgbG9nLmRlYnVnKFwiQWxyZWFkeSBhIHRlcm1pbmFsIHdpdGggaWQ6IFwiLCB0ZXJtaW5hbElkKTtcbiAgICAgICAgICBzZWxmLnJhaXNlVGVybWluYWwodGVybWluYWxJZCk7XG4gICAgICAgICAgcmV0dXJuIHRlcm1pbmFsSWQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNjb3BlID0gJHJvb3RTY29wZS4kbmV3KCk7XG4gICAgICAgIHNjb3BlLnBvZExpbmsgPSBwb2RMaW5rO1xuICAgICAgICBzY29wZS5jb250YWluZXJOYW1lID0gY29udGFpbmVyTmFtZTtcbiAgICAgICAgc2NvcGUuaWQgPSB0ZXJtaW5hbElkO1xuICAgICAgICBzY29wZS5kb2NrZWQgPSB0cnVlO1xuICAgICAgICB2YXIgZWwgPSAkKCRjb21waWxlKHRlbXBsYXRlKShzY29wZSkpO1xuICAgICAgICB2YXIgdGVybSA9IHtcbiAgICAgICAgICBzY29wZTogc2NvcGUsXG4gICAgICAgICAgZWw6IGVsXG4gICAgICAgIH07XG4gICAgICAgIGJvZHkuYXBwZW5kKGVsKTtcbiAgICAgICAgc2VsZi50ZXJtaW5hbHNbdGVybWluYWxJZF0gPSB0ZXJtO1xuICAgICAgICBwb3NpdGlvblRlcm1pbmFscyhzZWxmLnRlcm1pbmFscyk7XG4gICAgICAgIHJldHVybiB0ZXJtaW5hbElkO1xuICAgICAgfSxcbiAgICAgIGNsb3NlVGVybWluYWw6IChpZCkgPT4ge1xuICAgICAgICB2YXIgdGVybSA9IHNlbGYudGVybWluYWxzW2lkXTtcbiAgICAgICAgaWYgKHRlcm0pIHtcbiAgICAgICAgICB0ZXJtLmVsLnJlbW92ZSgpO1xuICAgICAgICAgIGRlbGV0ZSBzZWxmLnRlcm1pbmFsc1tpZF07XG4gICAgICAgICAgcG9zaXRpb25UZXJtaW5hbHMoc2VsZi50ZXJtaW5hbHMpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgcmFpc2VUZXJtaW5hbDogKGlkKSA9PiB7XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChzZWxmLnRlcm1pbmFscywgKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICBpZiAoa2V5ID09PSBpZCkge1xuICAgICAgICAgICAgdmFsdWUuZWwuY3NzKCd6LWluZGV4JywgJzQwMDAnKTtcbiAgICAgICAgICAgIHZhbHVlLmVsLmZpbmQoJy50ZXJtaW5hbCcpLmZvY3VzKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlLmVsLmNzcygnei1pbmRleCcsICczMDAwJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBzZWxmO1xuICB9KTtcblxuICBleHBvcnQgZnVuY3Rpb24gYWRkV2luZG93QWN0aW9ucyhzY29wZSwgZWxlbWVudCwgVGVybWluYWxTZXJ2aWNlKSB7XG4gICAgdmFyIG1vdmVkID0gZmFsc2U7XG4gICAgdmFyIGxhc3RYID0gMDtcbiAgICB2YXIgbGFzdFkgPSAwO1xuICAgIHZhciBoZWFkZXIgPSBlbGVtZW50LmZpbmQoJy50ZXJtaW5hbC10aXRsZScpO1xuICAgIHZhciBib2R5ID0gZWxlbWVudC5maW5kKCcudGVybWluYWwtYm9keScpO1xuICAgIGVsZW1lbnQub24oJyRkZXN0cm95JywgKCkgPT4ge1xuICAgICAgJCgnI21haW4nKS5jc3MoeyBkaXNwbGF5OiAnaW5oZXJpdCcgfSk7XG4gICAgfSk7XG5cbiAgICB2YXIgSEVJR0hUID0gMzQ4O1xuICAgIHZhciBXSURUSCA9IDYwMDtcbiAgICB2YXIgVElUTEVfSEVJR0hUID0gMzU7XG4gICAgdmFyIE5BVl9PRkZTRVQgPSA0NjtcblxuICAgIGVsZW1lbnQuY3NzKHtcbiAgICAgIGhlaWdodDogSEVJR0hULFxuICAgICAgd2lkdGg6IFdJRFRIXG4gICAgfSk7XG4gICAgaGVhZGVyLmNzcyh7XG4gICAgICBoZWlnaHQ6IFRJVExFX0hFSUdIVFxuICAgIH0pO1xuICAgIGJvZHkuY3NzKHtcbiAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgdG9wOiAzNSxcbiAgICAgIGxlZnQ6IDAsXG4gICAgICByaWdodDogMCwgXG4gICAgICBib3R0b206IDBcbiAgICB9KTtcbiAgICBzY29wZS5jbG9zZSA9ICgpID0+IHtcbiAgICAgIFRlcm1pbmFsU2VydmljZS5jbG9zZVRlcm1pbmFsKHNjb3BlLmlkKTtcbiAgICB9O1xuICAgIHNjb3BlLnJhaXNlID0gKCkgPT4ge1xuICAgICAgVGVybWluYWxTZXJ2aWNlLnJhaXNlVGVybWluYWwoc2NvcGUuaWQpO1xuICAgIH07XG4gICAgc2NvcGUuJHdhdGNoKCdkb2NrZWQnLCAoZG9ja2VkKSA9PiB7XG4gICAgICBpZiAoZG9ja2VkKSB7XG4gICAgICAgIGVsZW1lbnQud2lkdGgoV0lEVEgpO1xuICAgICAgICBpZiAoIWVsZW1lbnQuaGFzQ2xhc3MoJ21pbmltaXplZCcpKSB7XG4gICAgICAgICAgZWxlbWVudC5oZWlnaHQoSEVJR0hUKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHNjb3BlLnN0YXJ0UmVzaXplID0gKGUpID0+IHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGxvZy5kZWJ1ZyhcIlN0YXJ0IHJlc2l6ZVwiKTtcbiAgICAgIHNjb3BlLnJlc2l6aW5nID0gdHJ1ZTtcbiAgICAgIGVsZW1lbnQub24oJ21vdXNldXAnLCBzY29wZS5zdG9wUmVzaXplKTtcbiAgICAgICQoZG9jdW1lbnQpLm9uKCdtb3VzZW1vdmUnLCBzY29wZS5kb1Jlc2l6ZSk7XG4gICAgICAkKGRvY3VtZW50KS5vbignbW91c2VsZWF2ZScsIHNjb3BlLnN0b3BSZXNpemUpO1xuICAgIH07XG4gICAgc2NvcGUuZG9SZXNpemUgPSAoZSkgPT4ge1xuICAgICAgaWYgKHNjb3BlLnJlc2l6aW5nKSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhcIlJlc2l6aW5nLCBlOiBcIiwgZSk7XG4gICAgICAgIGlmICghbW92ZWQpIHtcbiAgICAgICAgICBsYXN0WCA9IGUuY2xpZW50WDtcbiAgICAgICAgICBsYXN0WSA9IGUuY2xpZW50WTtcbiAgICAgICAgICBtb3ZlZCA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoZWlnaHQgPSBlbGVtZW50LmhlaWdodCgpO1xuICAgICAgICB2YXIgd2lkdGggPSBlbGVtZW50LndpZHRoKCk7XG4gICAgICAgIHZhciBkZWx0YVggPSBlLmNsaWVudFggLSBsYXN0WDtcbiAgICAgICAgdmFyIGRlbHRhWSA9IGUuY2xpZW50WSAtIGxhc3RZO1xuICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gaGVpZ2h0ICsgZGVsdGFZO1xuICAgICAgICB2YXIgbmV3V2lkdGggPSB3aWR0aCArIGRlbHRhWDtcbiAgICAgICAgaWYgKG5ld0hlaWdodCA+IDM1ICYmIG5ld1dpZHRoID4gODApIHtcbiAgICAgICAgICBlbGVtZW50LmhlaWdodChoZWlnaHQgKyBkZWx0YVkpO1xuICAgICAgICAgIGVsZW1lbnQud2lkdGgod2lkdGggKyBkZWx0YVgpO1xuICAgICAgICB9XG4gICAgICAgIGxhc3RYID0gZS5jbGllbnRYO1xuICAgICAgICBsYXN0WSA9IGUuY2xpZW50WTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHNjb3BlLnN0b3BSZXNpemUgPSAoZSkgPT4ge1xuICAgICAgc2NvcGUucmVzaXppbmcgPSBmYWxzZTtcbiAgICAgIG1vdmVkID0gZmFsc2U7XG4gICAgICBlbGVtZW50Lm9mZignbW91c2V1cCcsIHNjb3BlLnN0b3BSZXNpemUpO1xuICAgICAgJChkb2N1bWVudCkub2ZmKCdtb3VzZW1vdmUnLCBzY29wZS5kb1Jlc2l6ZSk7XG4gICAgICAkKGRvY3VtZW50KS5vZmYoJ21vdXNlbGVhdmUnLCBzY29wZS5zdG9wUmVzaXplKTtcbiAgICB9XG4gICAgc2NvcGUubW91c2VEb3duID0gKGUpID0+IHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGlmIChlbGVtZW50Lmhhc0NsYXNzKCdtaW5pbWl6ZWQnKSB8fCBlbGVtZW50Lmhhc0NsYXNzKCdtYXhpbWl6ZWQnKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzY29wZS5kcmFnZ2luZyA9IHRydWU7XG4gICAgICBlbGVtZW50Lm9uKCdtb3VzZXVwJywgc2NvcGUubW91c2VVcCk7XG4gICAgICAkKGRvY3VtZW50KS5vbignbW91c2Vtb3ZlJywgc2NvcGUubW91c2VNb3ZlKTtcbiAgICAgICQoZG9jdW1lbnQpLm9uKCdtb3VzZWxlYXZlJywgc2NvcGUubW91c2VVcCk7XG4gICAgfTtcbiAgICBzY29wZS5tb3VzZVVwID0gKGUpID0+IHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHNjb3BlLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgICBtb3ZlZCA9IGZhbHNlO1xuICAgICAgdmFyIGhlaWdodCA9IGVsZW1lbnQuaGVpZ2h0KCk7XG4gICAgICB2YXIgb2Zmc2V0ID0gZWxlbWVudC5vZmZzZXQoKTtcbiAgICAgIHZhciB3aW5IZWlnaHQgPSAkKHdpbmRvdykuaGVpZ2h0KCk7XG4gICAgICBpZiAob2Zmc2V0LnRvcCA+ICh3aW5IZWlnaHQgLSBoZWlnaHQgLSAyMCkpIHtcbiAgICAgICAgZWxlbWVudC5jc3MoeyB0b3A6IFwiaW5oZXJpdFwiLCBsZWZ0OiBcImluaGVyaXRcIiB9KTtcbiAgICAgICAgc2NvcGUuZG9ja2VkID0gdHJ1ZTtcbiAgICAgICAgVGVybWluYWxTZXJ2aWNlLnBvc2l0aW9uVGVybWluYWxzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzY29wZS5kb2NrZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGVsZW1lbnQub2ZmKCdtb3VzZXVwJywgc2NvcGUubW91c2VVcCk7XG4gICAgICAkKGRvY3VtZW50KS5vZmYoJ21vdXNlbW92ZScsIHNjb3BlLm1vdXNlTW92ZSk7XG4gICAgICAkKGRvY3VtZW50KS5vZmYoJ21vdXNlbGVhdmUnLCBzY29wZS5tb3VzZVVwKTtcbiAgICB9O1xuICAgIHNjb3BlLm1vdXNlTW92ZSA9IChlKSA9PiB7XG4gICAgICBpZiAoc2NvcGUuZHJhZ2dpbmcpIHtcbiAgICAgICAgaWYgKCFtb3ZlZCkge1xuICAgICAgICAgIGxhc3RYID0gZS5jbGllbnRYO1xuICAgICAgICAgIGxhc3RZID0gZS5jbGllbnRZO1xuICAgICAgICAgIG1vdmVkID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRlbHRhWCA9IGUuY2xpZW50WCAtIGxhc3RYO1xuICAgICAgICB2YXIgZGVsdGFZID0gZS5jbGllbnRZIC0gbGFzdFk7XG4gICAgICAgIHZhciBlbE9mZnNldCA9IGVsZW1lbnQub2Zmc2V0KCk7XG4gICAgICAgIGVsZW1lbnQub2Zmc2V0KHsgdG9wOiBlbE9mZnNldC50b3AgKyBkZWx0YVksIGxlZnQ6IGVsT2Zmc2V0LmxlZnQgKyBkZWx0YVggfSk7XG4gICAgICAgIGxhc3RYID0gZS5jbGllbnRYO1xuICAgICAgICBsYXN0WSA9IGUuY2xpZW50WTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXN0b3JlV2luZG93KHNjb3BlLCBlbGVtZW50KSB7XG4gICAgICBpZiAoc2NvcGUub2Zmc2V0KSB7XG4gICAgICAgIGVsZW1lbnQub2Zmc2V0KHNjb3BlLm9mZnNldCk7XG4gICAgICAgIHNjb3BlLmRvY2tlZCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKHNjb3BlLmhlaWdodCkge1xuICAgICAgICBlbGVtZW50LmhlaWdodChzY29wZS5oZWlnaHQpO1xuICAgICAgfVxuICAgICAgaWYgKHNjb3BlLndpZHRoKSB7XG4gICAgICAgIGVsZW1lbnQud2lkdGgoc2NvcGUud2lkdGgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNhdmVXaW5kb3coc2NvcGUsIGVsZW1lbnQpIHtcbiAgICAgIHNjb3BlLm9mZnNldCA9IGVsZW1lbnQub2Zmc2V0KCk7XG4gICAgICBzY29wZS5oZWlnaHQgPSBlbGVtZW50LmhlaWdodCgpO1xuICAgICAgc2NvcGUud2lkdGggPSBlbGVtZW50LndpZHRoKCk7XG4gICAgfVxuXG4gICAgc2NvcGUubWF4aW1pemVkID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIGVsZW1lbnQuaGFzQ2xhc3MoJ21heGltaXplZCcpO1xuICAgIH1cblxuICAgIHNjb3BlLm1heGltaXplID0gKCRlKSA9PiB7XG4gICAgICAkZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKGVsZW1lbnQuaGFzQ2xhc3MoJ21pbmltaXplZCcpKSB7XG4gICAgICAgIHNjb3BlLm1pbmltaXplKCk7XG4gICAgICB9XG4gICAgICBpZiAoZWxlbWVudC5oYXNDbGFzcygnbWF4aW1pemVkJykpIHtcbiAgICAgICAgcmVzdG9yZVdpbmRvdyhzY29wZSwgZWxlbWVudCk7XG4gICAgICAgICQoJyNtYWluJykuY3NzKHsgZGlzcGxheTogJ2luaGVyaXQnIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2F2ZVdpbmRvdyhzY29wZSwgZWxlbWVudCk7XG4gICAgICAgICQoJyNtYWluJykuY3NzKHsgZGlzcGxheTogJ25vbmUnIH0pO1xuICAgICAgICBlbGVtZW50LmNzcyh7IFxuICAgICAgICAgIGhlaWdodDogJ2luaGVyaXQnLCBcbiAgICAgICAgICBib3R0b206IDAsIFxuICAgICAgICAgIHdpZHRoOiAnMTAwJScsIFxuICAgICAgICAgIHRvcDogTkFWX09GRlNFVCwgXG4gICAgICAgICAgbGVmdDogMCBcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBlbGVtZW50LnRvZ2dsZUNsYXNzKCdtYXhpbWl6ZWQnKTtcbiAgICB9XG4gICAgc2NvcGUubWluaW1pemUgPSAoJGUpID0+IHtcbiAgICAgICRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBpZiAoZWxlbWVudC5oYXNDbGFzcygnbWF4aW1pemVkJykpIHtcbiAgICAgICAgc2NvcGUubWF4aW1pemUoKTtcbiAgICAgIH1cbiAgICAgIGlmIChlbGVtZW50Lmhhc0NsYXNzKCdtaW5pbWl6ZWQnKSkge1xuICAgICAgICByZXN0b3JlV2luZG93KHNjb3BlLCBlbGVtZW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNhdmVXaW5kb3coc2NvcGUsIGVsZW1lbnQpO1xuICAgICAgICBzY29wZS5kb2NrZWQgPSB0cnVlO1xuICAgICAgICBlbGVtZW50LmNzcyh7IGhlaWdodDogVElUTEVfSEVJR0hULCB0b3A6IFwiaW5oZXJpdFwiLCBsZWZ0OiBcImluaGVyaXRcIiB9KTtcbiAgICAgICAgVGVybWluYWxTZXJ2aWNlLnBvc2l0aW9uVGVybWluYWxzKCk7XG4gICAgICB9XG4gICAgICBlbGVtZW50LnRvZ2dsZUNsYXNzKCdtaW5pbWl6ZWQnKTtcbiAgICB9O1xuICB9XG5cbiAgX21vZHVsZS5kaXJlY3RpdmUoJ3Rlcm1pbmFsV2luZG93JywgKCRjb21waWxlLCBUZXJtaW5hbFNlcnZpY2UpID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVzdHJpY3Q6ICdBJyxcbiAgICAgIHNjb3BlOiBmYWxzZSxcbiAgICAgIGxpbms6IChzY29wZTphbnksIGVsZW1lbnQsIGF0dHIpID0+IHtcbiAgICAgICAgYWRkV2luZG93QWN0aW9ucyhzY29wZSwgZWxlbWVudCwgVGVybWluYWxTZXJ2aWNlKTtcbiAgICAgICAgdmFyIGJvZHkgPSBlbGVtZW50LmZpbmQoJy50ZXJtaW5hbC1ib2R5Jyk7XG4gICAgICAgIGJvZHkuYXBwZW5kKCRjb21waWxlKCc8a3ViZXJuZXRlcy1jb250YWluZXItdGVybWluYWwgcG9kPVwicG9kTGlua1wiIGNvbnRhaW5lcj1cImNvbnRhaW5lck5hbWVcIiBjb21tYW5kPVwiYmFzaFwiPjwva3ViZXJuZXRlcy1jb250YWluZXItdGVybWluYWw+Jykoc2NvcGUpKTtcbiAgICAgIH1cbiAgICB9O1xuICB9KTtcbn1cblxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwidGVybS50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIHZhciBsb2cgPSBMb2dnZXIuZ2V0KFwia3ViZXJuZXRlcy1wb2QtbG9nc1wiKTtcblxuICBfbW9kdWxlLnNlcnZpY2UoXCJQb2RMb2dSZXBsYWNlbWVudHNcIiwgKCkgPT4ge1xuICAgIHJldHVybiBbXTtcbiAgfSk7XG5cbiAgX21vZHVsZS5ydW4oKFBvZExvZ1JlcGxhY2VtZW50cykgPT4ge1xuICAgIHZhciBsb2cgPSBMb2dnZXIuZ2V0KFwicG9kLWxvZy1yZXBsYWNlcnNcIik7XG4gICAgLy8gQWRkIEFOU0kgZXNjYXBlIGNoYXJhY3RlciByZXBsYWNlclxuICAgIC8vIGFkYXB0ZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbW1hbGVja2kvYW5zaXNwYW5cbiAgICB2YXIgY29sb3JzID0ge1xuICAgICAgJzMwJzogJ2JsYWNrJyxcbiAgICAgICczMSc6ICdyZWQnLFxuICAgICAgJzMyJzogJ2dyZWVuJyxcbiAgICAgICczMyc6ICd5ZWxsb3cnLFxuICAgICAgJzM0JzogJ2JsdWUnLFxuICAgICAgJzM1JzogJ3B1cnBsZScsXG4gICAgICAnMzYnOiAnY3lhbicsXG4gICAgICAnMzcnOiAnd2hpdGUnIFxuICAgIH1cbiAgICBQb2RMb2dSZXBsYWNlbWVudHMucHVzaCgobXNnKSA9PiB7XG4gICAgICBpZiAoIW1zZykge1xuICAgICAgICByZXR1cm4gbXNnO1xuICAgICAgfVxuICAgICAgdmFyIGVuZCA9IFwiPC9zcGFuPlwiO1xuICAgICAgXy5mb3JPd24oY29sb3JzLCAoY29sb3IsIGNvZGUpID0+IHtcbiAgICAgICAgdmFyIHN0YXJ0ID0gYDxzcGFuIGNsYXNzPVwiYCArIGNvbG9yICsgYFwiPmA7XG4gICAgICAgIG1zZyA9IG1zZy5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcMDMzXFxcXFsnICsgY29kZSArICdtJywgJ2cnKSwgc3RhcnQpXG4gICAgICAgIG1zZyA9IG1zZy5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcMDMzXFxcXFswOycgKyBjb2RlICsgJ20nLCAnZycpLCBzdGFydCk7XG4gICAgICB9KTtcbiAgICAgIG1zZyA9IG1zZy5yZXBsYWNlKC9cXDAzM1xcWzFtL2csICc8Yj4nKS5yZXBsYWNlKC9cXDAzM1xcWzIybS9nLCAnPC9iPicpO1xuICAgICAgbXNnID0gbXNnLnJlcGxhY2UoL1xcMDMzXFxbM20vZywgJzxpPicpLnJlcGxhY2UoL1xcMDMzXFxbMjNtL2csICc8L2k+Jyk7XG4gICAgICBtc2cgPSBtc2cucmVwbGFjZSgvXFwwMzNcXFttL2csIGVuZCk7XG4gICAgICBtc2cgPSBtc2cucmVwbGFjZSgvXFwwMzNcXFswbS9nLCBlbmQpO1xuICAgICAgbXNnID0gbXNnLnJlcGxhY2UoL1xcMDMzXFxbMzltL2csIGVuZCk7XG4gICAgICBtc2cgPSBtc2cucmVwbGFjZSgvXFwwMzNcXFsybS9nLCAnPHNwYW4+Jyk7XG4gICAgICBtc2cgPSBtc2cucmVwbGFjZSgvXFwwMzNcXFswOzM5bS9nLCBlbmQpO1xuICAgICAgbG9nLmRlYnVnKFwiUnVubmluZyByZXBsYWNlbWVudCBvbiBtZXNzYWdlOiBcIiwgbXNnKTtcbiAgICAgIHJldHVybiBtc2c7XG4gICAgfSk7XG4gIH0pO1xuXG4gIF9tb2R1bGUuY29udHJvbGxlcihcIkt1YmVybmV0ZXMuUG9kTG9nTGlua0NvbnRyb2xsZXJcIiwgKCRzY29wZSwgVGVybWluYWxTZXJ2aWNlLCAkdGVtcGxhdGVDYWNoZSkgPT4ge1xuXG4gICAgJHNjb3BlLm9wZW5Mb2dzID0gKGVudGl0eSkgPT4ge1xuICAgICAgbG9nLmRlYnVnKFwiT3BlbiBsb2dzOiBcIiwgZW50aXR5KTtcbiAgICAgIFRlcm1pbmFsU2VydmljZS5uZXdUZXJtaW5hbChlbnRpdHkubWV0YWRhdGEuc2VsZkxpbmssIGVudGl0eS5tZXRhZGF0YS5uYW1lLCAkdGVtcGxhdGVDYWNoZS5nZXQoVXJsSGVscGVycy5qb2luKHRlbXBsYXRlUGF0aCwgJ2xvZ1NoZWxsLmh0bWwnKSkpO1xuICAgIH1cblxuICB9KTtcblxuICBfbW9kdWxlLmRpcmVjdGl2ZSgncG9kTG9nRGlzcGxheScsICh1c2VyRGV0YWlscywgUG9kTG9nUmVwbGFjZW1lbnRzKSA9PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3RyaWN0OiAnRScsXG4gICAgICB0ZW1wbGF0ZTogYFxuICAgICAgICA8ZGl2IGNsYXNzPVwicG9kLWxvZy1saW5lc1wiPlxuICAgICAgICAgIDxwIG5nLWhpZGU9XCJmZXRjaGVkXCI+UGxlYXNlIHdhaXQsIGZldGNoaW5nIGxvZ3MuLi48L3A+XG4gICAgICAgICAgPHAgbmctaGlkZT1cIm1lc3NhZ2VzLmxlbmd0aCB8fCBwcmV2aW91c1wiPlZpZXcgPGEgaHJlZj1cIlwiIG5nLWNsaWNrPVwicHJldmlvdXM9IXByZXZpb3VzXCI+cHJldmlvdXMgY29udGFpbmVyIGxvZ3M8L2E+PzwvcD5cbiAgICAgICAgICA8cCBuZy1yZXBlYXQ9XCJtZXNzYWdlIGluIG1lc3NhZ2VzIHRyYWNrIGJ5ICRpbmRleFwiIG5nLWJpbmQtaHRtbD1cIm1lc3NhZ2VcIj48L3A+XG4gICAgICAgIDwvZGl2PlxuICAgICAgYCxcbiAgICAgIGxpbms6IChzY29wZTphbnksIGVsZW1lbnQsIGF0dHIpID0+IHtcbiAgICAgICAgdmFyIGxpbmsgPSBzY29wZS4kZXZhbCgncG9kTGluaycpO1xuICAgICAgICB2YXIgbmFtZSA9IHNjb3BlLiRldmFsKCdjb250YWluZXJOYW1lJyk7XG5cbiAgICAgICAgaWYgKCFsaW5rKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgc2NvcGUuZmV0Y2hlZCA9IGZhbHNlO1xuICAgICAgICBzY29wZS5wcmV2aW91cyA9IGZhbHNlO1xuICAgICAgICBzY29wZS5tZXNzYWdlcyA9IFtdO1xuXG4gICAgICAgIGxpbmsgPSBVcmxIZWxwZXJzLmpvaW4obWFzdGVyQXBpVXJsKCksIGxpbmssICdsb2cnKTtcbiAgICAgICAgbGluayA9IEt1YmVybmV0ZXNBUEkud3NVcmwobGluayk7XG4gICAgICAgIGxpbmsuc2VhcmNoKHtcbiAgICAgICAgICBmb2xsb3c6IHRydWUsXG4gICAgICAgICAgdGFpbExpbmVzOiAxMDAwLFxuICAgICAgICAgIGFjY2Vzc190b2tlbjogdXNlckRldGFpbHMudG9rZW5cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIG1lc3NhZ2VzID0gW107XG5cbiAgICAgICAgdmFyIHB1bGxNZXNzYWdlcyA9IF8uZGVib3VuY2UoKCkgPT4ge1xuICAgICAgICAgIHNjb3BlLm1lc3NhZ2VzID0gc2NvcGUubWVzc2FnZXMuY29uY2F0KF8ucmVtb3ZlKG1lc3NhZ2VzLCAoKSA9PiB0cnVlKS5tYXAoKG1zZykgPT4ge1xuICAgICAgICAgICAgUG9kTG9nUmVwbGFjZW1lbnRzLmZvckVhY2goKHJlcGxGdW5jOmFueSkgPT4ge1xuICAgICAgICAgICAgICBpZiAoYW5ndWxhci5pc0Z1bmN0aW9uKHJlcGxGdW5jKSkge1xuICAgICAgICAgICAgICAgIG1zZyA9IHJlcGxGdW5jKG1zZyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIG1zZztcbiAgICAgICAgICB9KSk7XG4gICAgICAgICAgaWYgKCFzY29wZS5mZXRjaGVkKSB7XG4gICAgICAgICAgICBzY29wZS5mZXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgQ29yZS4kYXBwbHkoc2NvcGUpO1xuICAgICAgICB9LCAxMDAwKTtcblxuICAgICAgICBmdW5jdGlvbiBpbml0U29ja2V0KGxpbmspIHtcbiAgICAgICAgICBzY29wZS5mZXRjaGVkID0gZmFsc2U7XG4gICAgICAgICAgbWVzc2FnZXMubGVuZ3RoID0gMDtcbiAgICAgICAgICBzY29wZS5tZXNzYWdlcy5sZW5ndGggPSAwO1xuICAgICAgICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXQobGluay50b1N0cmluZygpLCAnYmFzZTY0LmJpbmFyeS5rOHMuaW8nKTtcbiAgICAgICAgICB3cy5vbm1lc3NhZ2UgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHZhciBtZXNzYWdlID0gd2luZG93LmF0b2IoZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICAgIG1lc3NhZ2VzLnB1c2gobWVzc2FnZSk7XG4gICAgICAgICAgICAgIHB1bGxNZXNzYWdlcygpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIC8vIHdlJ2xsIGp1c3QgaWdub3JlIHRoZXNlXG4gICAgICAgICAgICAgIC8vbG9nLmRlYnVnKFwiRmFpbGVkIHRvIGRlY29kZSBtZXNzYWdlOiBcIiwgZXZlbnQuZGF0YSwgXCIgZXJyb3I6IFwiLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gd3M7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgd3MgPSBpbml0U29ja2V0KGxpbmspO1xuXG4gICAgICAgIHNjb3BlLiR3YXRjaCgncHJldmlvdXMnLCAodmFsdWUsIG9sZCkgPT4ge1xuICAgICAgICAgIGlmICh2YWx1ZSAhPT0gb2xkKSB7XG4gICAgICAgICAgICBpZiAobGluay5oYXNTZWFyY2goJ3ByZXZpb3VzJykpIHtcbiAgICAgICAgICAgICAgbGluay5yZW1vdmVTZWFyY2goJ3ByZXZpb3VzJykuYWRkU2VhcmNoKCdwcmV2aW91cycsIHNjb3BlLnByZXZpb3VzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGxpbmsuYWRkU2VhcmNoKCdwcmV2aW91cycsIHNjb3BlLnByZXZpb3VzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB3cyA9IGluaXRTb2NrZXQobGluayk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBlbGVtZW50Lm9uKCckZGVzdHJveScsICgpID0+IHtcbiAgICAgICAgICBpZiAod3MpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgLy8gbm90aGluZyB0byBkb1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIHdzO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBfbW9kdWxlLmRpcmVjdGl2ZSgncG9kTG9nV2luZG93JywgKCRjb21waWxlLCBUZXJtaW5hbFNlcnZpY2UpID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVzdHJpY3Q6ICdBJyxcbiAgICAgIHNjb3BlOiBmYWxzZSxcbiAgICAgIGxpbms6IChzY29wZTphbnksIGVsZW1lbnQsIGF0dHIpID0+IHtcbiAgICAgICAgYWRkV2luZG93QWN0aW9ucyhzY29wZSwgZWxlbWVudCwgVGVybWluYWxTZXJ2aWNlKTtcbiAgICAgICAgc2NvcGUuYXRCb3R0b20gPSB0cnVlO1xuICAgICAgICBzY29wZS4kd2F0Y2goJ2F0Qm90dG9tJywgKHZhbCkgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiYXRCb3R0b206IFwiLCB2YWwpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICB9KTtcblxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwidXRpbEhlbHBlcnMudHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIEVudkl0ZW0gPSBjb250cm9sbGVyKFwiRW52SXRlbVwiLCBbXCIkc2NvcGVcIiwgKCRzY29wZSkgPT4ge1xuICAgIHZhciBwYXJ0cyA9ICRzY29wZS5kYXRhLnNwbGl0KCc9Jyk7XG4gICAgJHNjb3BlLmtleSA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgJHNjb3BlLnZhbHVlID0gcGFydHMuam9pbignPScpO1xuICB9XSk7XG5cbiAgLy8gbWFpbiBjb250cm9sbGVyIGZvciB0aGUgcGFnZVxuICBleHBvcnQgdmFyIFBvZHMgPSBjb250cm9sbGVyKFwiUG9kc1wiLCBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzUG9kc1wiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIlNlcnZpY2VSZWdpc3RyeVwiLCBcIiRkaWFsb2dcIiwgXCIkd2luZG93XCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkbG9jYXRpb25cIiwgXCJsb2NhbFN0b3JhZ2VcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbDogS3ViZXJuZXRlcy5LdWJlcm5ldGVzTW9kZWxTZXJ2aWNlLCBLdWJlcm5ldGVzUG9kczpuZy5yZXNvdXJjZS5JUmVzb3VyY2VDbGFzczxhbnk+LCBLdWJlcm5ldGVzU3RhdGUsIFNlcnZpY2VSZWdpc3RyeSwgJGRpYWxvZywgJHdpbmRvdywgJHRlbXBsYXRlQ2FjaGUsICRyb3V0ZVBhcmFtcywgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsIGxvY2FsU3RvcmFnZSwgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgJHNjb3BlLiRvbigna3ViZXJuZXRlc01vZGVsVXBkYXRlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgfSk7XG5cbiAgICAkc2NvcGUuaXRlbVNjaGVtYSA9IEZvcm1zLmNyZWF0ZUZvcm1Db25maWd1cmF0aW9uKCk7XG5cbiAgICAkc2NvcGUudGFibGVDb25maWcgPSB7XG4gICAgICBkYXRhOiAnbW9kZWwucG9kcycsXG4gICAgICBzaG93U2VsZWN0aW9uQ2hlY2tib3g6IHRydWUsXG4gICAgICBlbmFibGVSb3dDbGlja1NlbGVjdGlvbjogZmFsc2UsXG4gICAgICBtdWx0aVNlbGVjdDogdHJ1ZSxcbiAgICAgIHNlbGVjdGVkSXRlbXM6IFtdLFxuICAgICAgZmlsdGVyT3B0aW9uczoge1xuICAgICAgICBmaWx0ZXJUZXh0OiAkbG9jYXRpb24uc2VhcmNoKClbXCJxXCJdIHx8ICcnXG4gICAgICB9LFxuICAgICAgY29sdW1uRGVmczogW1xuICAgICAgICB7XG4gICAgICAgICAgZmllbGQ6ICdfa2V5JyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ05hbWUnLFxuICAgICAgICAgIGRlZmF1bHRTb3J0OiB0cnVlLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiaWRUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJyRzdGF0dXNDc3MnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnU3RhdHVzJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcInN0YXR1c1RlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgfSxcbiAgICAgICAgeyBmaWVsZDogJyRldmVudENvdW50JyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ0V2ZW50cycsXG4gICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJldmVudFN1bW1hcnlUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJyRyZXN0YXJ0Q291bnQnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUmVzdGFydHMnXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJyRjcmVhdGVkVGltZScsXG4gICAgICAgICAgZGlzcGxheU5hbWU6ICdBZ2UnLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiYWdlVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgZmllbGQ6ICckaW1hZ2VOYW1lcycsXG4gICAgICAgICAgZGlzcGxheU5hbWU6ICdJbWFnZXMnLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiaW1hZ2VUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJyRob3N0JyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ0hvc3QnLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiaG9zdFRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGZpZWxkOiAnJGxhYmVsc1RleHQnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTGFiZWxzJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImxhYmVsVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgZmllbGQ6ICckcG9kSVAnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnUG9kIElQJyxcbiAgICAgICAgICBjdXN0b21Tb3J0RmllbGQ6IChmaWVsZCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIEt1YmVybmV0ZXMuc29ydEJ5UG9kSXAoZmllbGQuJHBvZElQKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIF1cbiAgICB9O1xuXG4gICAgJHNjb3BlLm9wZW5Mb2dzID0gKCkgPT4ge1xuICAgICAgdmFyIHBvZHMgPSAkc2NvcGUudGFibGVDb25maWcuc2VsZWN0ZWRJdGVtcztcbiAgICAgIGlmICghcG9kcyB8fCAhcG9kcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKCRzY29wZS5pZCkge1xuICAgICAgICAgIHZhciBpdGVtID0gJHNjb3BlLml0ZW07XG4gICAgICAgICAgaWYgKGl0ZW0pIHtcbiAgICAgICAgICAgIHBvZHMgPSBbaXRlbV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBvcGVuTG9nc0ZvclBvZHMoU2VydmljZVJlZ2lzdHJ5LCAkd2luZG93LCBLdWJlcm5ldGVzTW9kZWwuY3VycmVudE5hbWVzcGFjZSgpLCBwb2RzKTtcbiAgICB9O1xuXG4gICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuXG4gICAgJHNjb3BlLmRlbGV0ZVByb21wdCA9IChzZWxlY3RlZCkgPT4ge1xuICAgICAgaWYgKGFuZ3VsYXIuaXNTdHJpbmcoc2VsZWN0ZWQpKSB7XG4gICAgICAgIHNlbGVjdGVkID0gW3tcbiAgICAgICAgICBpZDogc2VsZWN0ZWRcbiAgICAgICAgfV07XG4gICAgICB9XG4gICAgICBVSS5tdWx0aUl0ZW1Db25maXJtQWN0aW9uRGlhbG9nKDxVSS5NdWx0aUl0ZW1Db25maXJtQWN0aW9uT3B0aW9ucz57XG4gICAgICAgIGNvbGxlY3Rpb246IHNlbGVjdGVkLFxuICAgICAgICBpbmRleDogJ21ldGFkYXRhLm5hbWUnLFxuICAgICAgICBvbkNsb3NlOiAocmVzdWx0OmJvb2xlYW4pID0+IHtcbiAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBkZWxldGVTZWxlY3RlZChzZWxlY3RlZDpBcnJheTxLdWJlUG9kPiwgbmV4dDpLdWJlUG9kKSB7XG4gICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiZGVsZXRpbmc6IFwiLCBnZXROYW1lKG5leHQpKTtcbiAgICAgICAgICAgICAgICBLdWJlcm5ldGVzUG9kcy5kZWxldGUoe1xuICAgICAgICAgICAgICAgICAgaWQ6IGdldE5hbWUobmV4dClcbiAgICAgICAgICAgICAgICB9LCB1bmRlZmluZWQsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcImRlbGV0ZWQ6IFwiLCBnZXROYW1lKG5leHQpKTtcbiAgICAgICAgICAgICAgICAgIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkVycm9yIGRlbGV0aW5nOiBcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB0aXRsZTogJ0RlbGV0ZSBwb2RzPycsXG4gICAgICAgIGFjdGlvbjogJ1RoZSBmb2xsb3dpbmcgcG9kcyB3aWxsIGJlIGRlbGV0ZWQ6JyxcbiAgICAgICAgb2tUZXh0OiAnRGVsZXRlJyxcbiAgICAgICAgb2tDbGFzczogJ2J0bi1kYW5nZXInLFxuICAgICAgICBjdXN0b206IFwiVGhpcyBvcGVyYXRpb24gaXMgcGVybWFuZW50IG9uY2UgY29tcGxldGVkIVwiLFxuICAgICAgICBjdXN0b21DbGFzczogXCJhbGVydCBhbGVydC13YXJuaW5nXCJcbiAgICAgIH0pLm9wZW4oKTtcbiAgICB9O1xuXG4gICAgJHNjb3BlLmNyZWF0ZVBvZHM9ICgpID0+IHtcbiAgICAgIHZhciB4aHI9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09IDQpIHsvLzTooajnpLrmlbDmja7lt7Lnu4/osIPnlKjlrozmiJBcbiAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PSAyMDApIHsvL0hUVFDnmoTnirbmgIHnoIFcbiAgICAgICAgICAgIHZhciBvYmo9SlNPTi5wYXJzZSh4aHIucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7XG4gICAgICAgICAgICAgICBcIm5hbWVcIjogXCJuZXdwb2RcIixcbiAgICAgICAgICAgICAgIFwibGFiZWxzXCI6IHtcbiAgICAgICAgICAgICAgICAgXCJhaW1cIjogXCJ0ZXN0XCIsXG4gICAgICAgICAgICAgICAgIFwiYXBwXCI6IFwib3JhY2xlXCJcbiAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICBcInBhdGhcIjogJy9ob21lLycsXG4gICAgICAgICAgICAgICBcInBvcnRcIjogMTUyNVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgS3ViZXJuZXRlcy5jcmVhdGVSQyhvYmplY3QpO1xuXG4gICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgLy9hbHRlcihcInNoaWJhaVwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICB4aHIub3BlbihcIlBPU1RcIiwgXCIvb3JhY2xlQXBwUGF0aFwiLCBmYWxzZSk7Ly/kuI7mnI3liqHlmajov57mjqXlubblj5HpgIFcbiAgICAgIHhoci5zZW5kKG51bGwpO1xuICAgIH07XG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBSZXBsaWNhdGlvbkNvbnRyb2xsZXJDb250cm9sbGVyID0gY29udHJvbGxlcihcIlJlcGxpY2F0aW9uQ29udHJvbGxlckNvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6IEt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgJHNjb3BlLnJhd01vZGVsID0gbnVsbFxuXG4gICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuXG4gICAgJHNjb3BlLml0ZW1Db25maWcgPSB7XG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICdeXFxcXC9sYWJlbHMkJzoge1xuICAgICAgICAgIHRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoJ2xhYmVsVGVtcGxhdGUuaHRtbCcpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgJHNjb3BlLiRvbigna3ViZXJuZXRlc01vZGVsVXBkYXRlZCcsICgpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9KTtcblxuICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9KTtcblxuICAgICRzY29wZS4kd2F0Y2goJ21vZGVsLnBvZHMnLCAobmV3VmFsdWUsIG9sZFZhbHVlKSA9PiB7XG4gICAgICB1cGRhdGVEYXRhKCk7XG4gICAgfSwgdHJ1ZSk7XG5cbiAgICAkc2NvcGUuZmxpcFJhdyA9ICgpID0+IHtcbiAgICAgICRzY29wZS5yYXdNb2RlID0gISRzY29wZS5yYXdNb2RlO1xuICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICB9O1xuXG4gICAgdXBkYXRlRGF0YSgpO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlRGF0YSgpIHtcbiAgICAgIGlmICgkc2NvcGUuZGlydHkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG4gICAgICAkc2NvcGUuaXRlbSA9ICRzY29wZS5tb2RlbC5nZXRSZXBsaWNhdGlvbkNvbnRyb2xsZXIoS3ViZXJuZXRlc1N0YXRlLnNlbGVjdGVkTmFtZXNwYWNlLCAkc2NvcGUuaWQpO1xuICAgICAgaWYgKCRzY29wZS5pdGVtKSB7XG4gICAgICAgICRzY29wZS5yYXdNb2RlbCA9IHRvUmF3WWFtbCgkc2NvcGUuaXRlbSk7XG4gICAgICB9XG4gICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgIH1cbiAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIFJlcGxpY2F0aW9uQ29udHJvbGxlckVkaXRDb250cm9sbGVyID0gY29udHJvbGxlcihcIlJlcGxpY2F0aW9uQ29udHJvbGxlckVkaXRDb250cm9sbGVyXCIsXG4gICAgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc1NjaGVtYVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIiwgXCJTY2hlbWFSZWdpc3RyeVwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOiBLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSxcbiAgICAgICAkdGVtcGxhdGVDYWNoZTpuZy5JVGVtcGxhdGVDYWNoZVNlcnZpY2UsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCAkcm91dGVQYXJhbXMsICRodHRwLCAkdGltZW91dCwgS3ViZXJuZXRlc0FwaVVSTCwgc2NoZW1hczpIYXd0aW9Gb3Jtcy5TY2hlbWFSZWdpc3RyeSkgPT4ge1xuXG4gICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgIGxvZy5kZWJ1ZyhcIlNjaGVtYTogXCIsICRzY29wZS5zY2hlbWEpO1xuICAgICRzY29wZS5jb25maWcgPSBzY2hlbWFzLmNsb25lU2NoZW1hKFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5SZXBsaWNhdGlvbkNvbnRyb2xsZXJcIik7XG4gICAgLy8kJHNjb3BlLmNvbmZpZyA9IEt1YmVybmV0ZXNTY2hlbWEuZGVmaW5pdGlvbnMua3ViZXJuZXRlc192MWJldGEzX1JlcGxpY2F0aW9uQ29udHJvbGxlcjtcblxuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9KTtcblxuICAgIHVwZGF0ZURhdGEoKTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICBpZiAoJHNjb3BlLmlkKSB7XG4gICAgICAgICRzY29wZS5lbnRpdHkgPSAkc2NvcGUubW9kZWwuZ2V0UmVwbGljYXRpb25Db250cm9sbGVyKEt1YmVybmV0ZXNTdGF0ZS5zZWxlY3RlZE5hbWVzcGFjZSwgJHNjb3BlLmlkKTtcbiAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIFJlcGxpY2F0aW9uQ29udHJvbGxlcnMgPSBjb250cm9sbGVyKFwiUmVwbGljYXRpb25Db250cm9sbGVyc1wiLFxuICAgIFtcIiRzY29wZVwiLCBcIk9yYWNsZVN0YXR1c01vZGVsXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1JlcGxpY2F0aW9uQ29udHJvbGxlcnNcIiwgXCJLdWJlcm5ldGVzUG9kc1wiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIixcbiAgICAgICgkc2NvcGUsIE9yYWNsZVN0YXR1c01vZGVsLCBLdWJlcm5ldGVzTW9kZWw6IEt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1JlcGxpY2F0aW9uQ29udHJvbGxlcnM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1BvZHM6bmcucmVzb3VyY2UuSVJlc291cmNlQ2xhc3M8YW55PiwgS3ViZXJuZXRlc1N0YXRlLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcblxuICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgIGRhdGE6ICdtb2RlbC5yZXBsaWNhdGlvbkNvbnRyb2xsZXJzJyxcbiAgICAgIHNob3dTZWxlY3Rpb25DaGVja2JveDogdHJ1ZSxcbiAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgIG11bHRpU2VsZWN0OiB0cnVlLFxuICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgIGZpbHRlclRleHQ6ICRsb2NhdGlvbi5zZWFyY2goKVtcInFcIl0gfHwgJydcbiAgICAgIH0sXG4gICAgIGNvbHVtbkRlZnM6IFtcbiAgICAgICAgIHsgZmllbGQ6ICdfa2V5JyxcbiAgICAgICAgICAgZGlzcGxheU5hbWU6ICfmnI3liqHlkI3np7AnLFxuICAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImlkVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgfSxcbiAgICAgICAgIC8veyBmaWVsZDogJyRyZXBsaWNhcycsXG4gICAgICAgICAvLyAgZGlzcGxheU5hbWU6ICdTY2FsZScsXG4gICAgICAgICAvLyAgY2VsbFRlbXBsYXRlOiR0ZW1wbGF0ZUNhY2hlLmdldChcImRlc2lyZWRSZXBsaWNhcy5odG1sXCIpXG4gICAgICAgICAvL30sXG4gICAgICAgICB7IGZpZWxkOiAnJHBvZHMuYWdlJyxcbiAgICAgICAgICAgZGlzcGxheU5hbWU6ICflkK/liqjml7bpl7QnLFxuICAgICAgICAgICBjZWxsVGVtcGxhdGU6JHRlbXBsYXRlQ2FjaGUuZ2V0KFwiYWdlVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgfSxcbiAgICAgICAgIHsgZmllbGQ6ICckbGFiZWxzVGV4dCcsXG4gICAgICAgICAgIGRpc3BsYXlOYW1lOiAn5pWw5o2u5qCH562+JyxcbiAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJsYWJlbFRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgIH0sXG4gICAgICAgICB7IGZpZWxkOiAnJHBvZHMnLFxuICAgICAgICAgICBkaXNwbGF5TmFtZTogJ+i/nuaOpeWPguaVsCcsXG4gICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiY29ubmVjdFBhcmFtVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICAgfSxcbiAgICAgICAgIHsgZmllbGQ6ICckcG9kc1swXS4kZXZlbnRDb3VudCcsXG4gICAgICAgICAgIGRpc3BsYXlOYW1lOiAn5pyN5Yqh5ZCv5Yqo5pel5b+XJyxcbiAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJldmVudFN1bW1hcnlUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgICB9LFxuICAgICAgICAgeyBmaWVsZDogJyRwb2RDb3VudGVycycsXG4gICAgICAgICAgIGRpc3BsYXlOYW1lOiAn5pyN5Yqh54q25oCBJyxcbiAgICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJwb2RDb3VudHNBbmRMaW5rVGVtcGxhdGUuaHRtbFwiKSxcbiAgICAgICAgICAgY3VzdG9tU29ydEZpZWxkOiAoZmllbGQpID0+IHtcbiAgICAgICAgICAgICBpZihmaWVsZC4kcG9kQ291bnRlcnMucmVhZHkgKXtcbiAgICAgICAgICAgICAgICByZXR1cm4gMztcbiAgICAgICAgICAgICB9ZWxzZSBpZihmaWVsZC4kcG9kQ291bnRlcnMudmFsaWQgfHwgZmllbGQuJHBvZENvdW50ZXJzLndhaXRpbmcpe1xuICAgICAgICAgICAgICAgIHJldHVybiAyO1xuICAgICAgICAgICAgIH1lbHNlIGlmKGZpZWxkLiRwb2RDb3VudGVycy5lcnJvcil7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICAgfVxuICAgICAgICAgICB9XG4gICAgICAgICB9XG4gICAgICAgXVxuICAgIH1cblxuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICRzY29wZS5kZWxldGVQcm9tcHQgPSAoc2VsZWN0ZWQpID0+IHtcbiAgICAgIGlmIChhbmd1bGFyLmlzU3RyaW5nKHNlbGVjdGVkKSkge1xuICAgICAgICBzZWxlY3RlZCA9IFt7XG4gICAgICAgICAgaWQ6IHNlbGVjdGVkXG4gICAgICAgIH1dO1xuICAgICAgfVxuICAgICAgVUkubXVsdGlJdGVtQ29uZmlybUFjdGlvbkRpYWxvZyg8VUkuTXVsdGlJdGVtQ29uZmlybUFjdGlvbk9wdGlvbnM+e1xuICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgaW5kZXg6ICdtZXRhZGF0YS5uYW1lJyxcbiAgICAgICAgb25DbG9zZTogKHJlc3VsdDpib29sZWFuKSA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgZnVuY3Rpb24gZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQ6QXJyYXk8S3ViZVBvZD4sIG5leHQ6S3ViZVBvZCkge1xuICAgICAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcImRlbGV0aW5nOiBcIiwgZ2V0TmFtZShuZXh0KSk7XG4gICAgICAgICAgICAgICAgS3ViZXJuZXRlcy5yZXNpemVDb250cm9sbGVyKCRodHRwLCBLdWJlcm5ldGVzQXBpVVJMLCBuZXh0LCAwLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcInVwZGF0ZWQgbnVtYmVyIG9mIHJlcGxpY2FzXCIpO1xuICAgICAgICAgICAgICAgICAgIEt1YmVybmV0ZXNSZXBsaWNhdGlvbkNvbnRyb2xsZXJzLmRlbGV0ZSh7XG4gICAgICAgICAgICAgICAgICAgICBpZDogZ2V0TmFtZShuZXh0KVxuICAgICAgICAgICAgICAgICAgIH0sIHVuZGVmaW5lZCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiZGVsZXRlZDogXCIsIGdldE5hbWUobmV4dCkpO1xuICAgICAgICAgICAgICAgICAgICAgaWYobmV4dC5tZXRhZGF0YS5sYWJlbHMuc3R5bGUgPT09IFwib3JhY2xlXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLmNvbm5lY3RPcmFjbGUoJGh0dHAsICR0aW1lb3V0LCBcIi9jYW5jZWxPcmFjbGVDb25lY3Rpb25cIiwgXCJcIiwgZ2V0TmFtZShuZXh0KSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICBsb2cuZGVidWcoXCJFcnJvciBkZWxldGluZzogXCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvKkt1YmVybmV0ZXNSZXBsaWNhdGlvbkNvbnRyb2xsZXJzLmRlbGV0ZSh7XG4gICAgICAgICAgICAgICAgICBpZDogZ2V0TmFtZShuZXh0KVxuICAgICAgICAgICAgICAgIH0sIHVuZGVmaW5lZCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiZGVsZXRlZDogXCIsIGdldE5hbWUobmV4dCkpO1xuICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRXJyb3IgZGVsZXRpbmc6IFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICAgfSk7Ki9cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdGl0bGU6ICfmmK/lkKbpnIDopoHliKDpmaRvcmFjbGXmnI3liqHvvJ8nLFxuICAgICAgICBhY3Rpb246ICfku6XkuIvnmoRvcmFjbGXmnI3liqHlsIbkvJrooqvliKDpmaQ6JyxcbiAgICAgICAgb2tUZXh0OiAn5Yig6ZmkJyxcbiAgICAgICAgb2tDbGFzczogJ2J0bi1kYW5nZXInLFxuICAgICAgICBjdXN0b206IFwi6K+l5pyN5Yqh5Yig6Zmk5ZCO5bCG5Lya5riF6Zmkb3JhY2xl5a+55bqU5pyN5Yqh55qE56uv5Y+j562J6LWE5rqQ5Y2g55So77yM5L2G5LiN5Yig6Zmk5pWw5o2u5paH5Lu277yM5piv5ZCm5Yig6Zmk77yM6K+356Gu6K6k77yBXCIsXG4gICAgICAgIGN1c3RvbUNsYXNzOiBcImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIixcbiAgICAgICAgY2FuY2VsVGV4dDogXCLlj5bmtohcIlxuICAgICAgfSkub3BlbigpO1xuICAgIH1cblxuICAgICRzY29wZS5jcmVhdGVSQ3M9ICgpID0+IHtcbiAgICAgIHZhciB4aHI9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09IDQpIHsvLzTooajnpLrmlbDmja7lt7Lnu4/osIPnlKjlrozmiJBcbiAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PSAyMDApIHsvL0hUVFDnmoTnirbmgIHnoIFcbiAgICAgICAgICAgIHZhciBvYmo9SlNPTi5wYXJzZSh4aHIucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKG9iai5wYXRoKTtcbiAgICAgICAgICAgIHZhciBuYW1lID0gS3ViZXJuZXRlcy5nZXRSYW5kb21TdHJpbmcoOCk7XG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKG5hbWUgKyBcIj09PT09XCIgK3BvcnQpO1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHtcbiAgICAgICAgICAgICAgIFwibmFtZVwiOiBuYW1lLFxuICAgICAgICAgICAgICAgXCJsYWJlbHNcIjoge1xuICAgICAgICAgICAgICAgICAgXCJuYW1lXCIgOiBuYW1lXG4gICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgXCJwYXRoXCI6IG9iai5wYXRoLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgS3ViZXJuZXRlcy5jcmVhdGVSQyhvYmplY3QsIChyYykgPT57XG4gICAgICAgICAgICAgICBLdWJlcm5ldGVzLmNvbm5lY3RPcmFjbGUoJGh0dHAsICR0aW1lb3V0LCBcIi9jb25uZWN0VG9PcmFjbGVcIiwgXCJcIiwgZ2V0TmFtZShyYyksIDApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfWVsc2UgaWYoeGhyLnN0YXR1cyA9PSA0MDMpe1xuICAgICAgICAgICAgIGFsZXJ0KFwi5Lik5qyh5Yib5bu6b3JhY2xl5pyN5Yqh5pe26Ze06Ze06ZqU6ZyA6KaB6LaF6L+HMeWIhumSnyFcIik7XG4gICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgeGhyLm9wZW4oXCJQT1NUXCIsIFwiL29yYWNsZUFwcFBhdGhcIiwgZmFsc2UpOy8v5LiO5pyN5Yqh5Zmo6L+e5o6l5bm25Y+R6YCBXG4gICAgICB4aHIuc2VuZChudWxsKTtcbiAgICB9XG5cbiAgICAkc2NvcGUuc3RvcFByb21wdCA9IChzZWxlY3RlZCkgPT57XG4gICAgICBpZiAoYW5ndWxhci5pc1N0cmluZyhzZWxlY3RlZCkpIHtcbiAgICAgICAgc2VsZWN0ZWQgPSBbe1xuICAgICAgICAgIGlkOiBzZWxlY3RlZFxuICAgICAgICB9XTtcbiAgICAgIH1cblxuICAgICAgVUkubXVsdGlJdGVtQ29uZmlybUFjdGlvbkRpYWxvZyg8VUkuTXVsdGlJdGVtQ29uZmlybUFjdGlvbk9wdGlvbnM+e1xuICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgaW5kZXg6ICdtZXRhZGF0YS5uYW1lJyxcbiAgICAgICAgb25DbG9zZTogKHJlc3VsdDpib29sZWFuKSA9PiB7XG4gICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgZnVuY3Rpb24gc3RvcFNlbGVjdGVkKHNlbGVjdGVkOkFycmF5PEt1YmVQb2Q+LCBuZXh0Okt1YmVQb2QpIHtcbiAgICAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgICAgS3ViZXJuZXRlcy5yZXNpemVDb250cm9sbGVyKCRodHRwLCBLdWJlcm5ldGVzQXBpVVJMLCBuZXh0LCAwLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgIGlmKG5leHQubWV0YWRhdGEubGFiZWxzLnN0eWxlID09PSBcIm9yYWNsZVwiKVxuICAgICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLmNvbm5lY3RPcmFjbGUoJGh0dHAsICR0aW1lb3V0LCBcIi9jYW5jZWxPcmFjbGVDb25lY3Rpb25cIiwgXCJcIiwgZ2V0TmFtZShuZXh0KSwgMCk7XG4gICAgICAgICAgICAgICAgIHN0b3BTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICB9XG4gICAgICAgICAgIH1cbiAgICAgICAgICAgc3RvcFNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB0aXRsZTogJ+aYr+WQpumcgOimgeWBnOatom9yYWNsZeacjeWKoe+8nycsXG4gICAgICBhY3Rpb246ICfku6XkuIvnmoRvcmFjbGXmnI3liqHlsIbkvJrooqvlgZzmraI6JyxcbiAgICAgIG9rVGV4dDogJ+WBnOatoicsXG4gICAgICBva0NsYXNzOiAnYnRuLWRhbmdlcicsXG4gICAgICBjdXN0b206IFwi6K+l5pyN5Yqh5YGc5q2i5ZCO5bCG5peg5rOV57un57ut5o+Q5L6b6L+e5o6l6K6/6Zeu5pyN5Yqh77yM5L2G5Y+v6YCa6L+H5ZCv5Yqo5oyJ6ZKu6YeN5paw5ZCv5Yqo6K+l5pyN5Yqh5Lul6L+b6KGM6K6/6Zeu44CC5piv5ZCm5YGc5q2i77yM6K+356Gu6K6kXCIsXG4gICAgICBjdXN0b21DbGFzczogXCJhbGVydCBhbGVydC13YXJuaW5nXCIsXG4gICAgICBjYW5jZWxUZXh0OiBcIuWPlua2iFwiXG4gICAgfSkub3BlbigpO1xuICAgfVxuXG4gICAkc2NvcGUucmVTdGFydFByb21wdCA9IChzZWxlY3RlZCkgPT4ge1xuICAgICAgZnVuY3Rpb24gc3RhcnRTZWxlY3RlZChzZWxlY3RlZDpBcnJheTxLdWJlUG9kPiwgbmV4dDpLdWJlUG9kKXtcbiAgICAgICAgIGlmKG5leHQpe1xuICAgICAgICAgICAgaWYobmV4dC4kcmVwbGljYXMgPT09IDApXG4gICAgICAgICAgICAgICBLdWJlcm5ldGVzLnJlc2l6ZUNvbnRyb2xsZXIoJGh0dHAsIEt1YmVybmV0ZXNBcGlVUkwsIG5leHQsIDEsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLmNvbm5lY3RPcmFjbGUoJGh0dHAsICR0aW1lb3V0LCBcIi9jb25uZWN0VG9PcmFjbGVcIiwgXCJcIiwgZ2V0TmFtZShuZXh0KSwgMCk7XG4gICAgICAgICAgICAgICAgICAgc3RhcnRTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICB9KTtcbiAgICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YXJ0U2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgfVxuXG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSW50ZXJmYWNlcy50c1wiLz5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgZnVuY3Rpb24gc2NoZW1hU2V0UmVxdWlyZWQoc2NoZW1hLCBwcm9wZXJ0eU5hbWUsIGlzUmVxdWlyZWQgPSB0cnVlKSB7XG4gICAgaWYgKHNjaGVtYSAmJiBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgIHZhciByZXF1aXJlZCA9IHNjaGVtYS5yZXF1aXJlZDtcbiAgICAgIGlmIChpc1JlcXVpcmVkKSB7XG4gICAgICAgIGlmICghcmVxdWlyZWQpIHtcbiAgICAgICAgICByZXF1aXJlZCA9IFtdO1xuICAgICAgICAgIHNjaGVtYS5yZXF1aXJlZCA9IHJlcXVpcmVkO1xuICAgICAgICB9XG4gICAgICAgIGlmICghXy5jb250YWlucyhyZXF1aXJlZCwgcHJvcGVydHlOYW1lKSkge1xuICAgICAgICAgIHJlcXVpcmVkLnB1c2gocHJvcGVydHlOYW1lKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHJlcXVpcmVkKSB7XG4gICAgICAgICAgdmFyIGlkeCA9IHJlcXVpcmVkLmluZGV4T2YocHJvcGVydHlOYW1lKTtcbiAgICAgICAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgICAgICAgIHJlcXVpcmVkLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNIZWxwZXJzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBleHBvcnQgdmFyIFNlY3JldENvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiU2VjcmV0Q29udHJvbGxlclwiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTdGF0ZVwiLCBcIkt1YmVybmV0ZXNTY2hlbWFcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsIFwiSzhTQ2xpZW50RmFjdG9yeVwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOkt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzU2NoZW1hLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMLCBLOFNDbGllbnRGYWN0b3J5KSA9PiB7XG5cbiAgICAgICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG5cbiAgICAgICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuICAgICAgICBzZWxlY3RTdWJOYXZCYXIoJHNjb3BlLCBcIlNlY3JldHNcIiwgJHNjb3BlLmlkID8gXCJFZGl0IFNlY3JldDogXCIgKyAkc2NvcGUuaWQgOiBcIkNyZWF0ZSBTZWNyZXRcIik7XG5cbiAgICAgICAgdmFyIGt1YmVDbGllbnQgPSBjcmVhdGVLdWJlcm5ldGVzQ2xpZW50KFwic2VjcmV0c1wiKTtcblxuICAgICAgICB2YXIgb25TYXZlVXJsID0gJGxvY2F0aW9uLnNlYXJjaCgpW1wic2F2ZWRVcmxcIl07XG4gICAgICAgIHZhciBjcmVhdGVLaW5kID0gJGxvY2F0aW9uLnNlYXJjaCgpW1wia2luZFwiXTtcblxuICAgICAgICAkc2NvcGUuc3NoS2V5cyA9IHNzaFNlY3JldERhdGFLZXlzO1xuICAgICAgICAkc2NvcGUuaHR0cHNLZXlzID0gaHR0cHNTZWNyZXREYXRhS2V5cztcblxuICAgICAgICB2YXIgc2VjcmV0TGFiZWxzID0ge1xuICAgICAgICAgIFwic3NoLWtleVwiOiBcIlNTSCBwcml2YXRlIGtleVwiLFxuICAgICAgICAgIFwic3NoLWtleS5wdWJcIjogXCJTU0ggcHVibGljIGtleVwiLFxuICAgICAgICAgIFwiY2EuY3J0XCI6IFwiQ0EgQ2VydGlmaWNhdGVcIixcbiAgICAgICAgICBcIi5kb2NrZXJjZmdcIjogXCJEb2NrZXIgY29uZmlnXCIsXG4gICAgICAgICAgXCJ1c2VybmFtZVwiOiBcIlVzZXIgbmFtZVwiXG4gICAgICAgIH07XG4gICAgICAgIHZhciBzZWNyZXRUb29sdGlwcyA9IHtcbiAgICAgICAgICBcInNzaC1rZXlcIjogXCJTU0ggcHJpdmF0ZSBrZXkgdGV4dCBjb250ZW50c1wiLFxuICAgICAgICAgIFwiY2EuY3J0XCI6IFwiQ2VydGlmaWNhdGUgQXV0aG9yaXR5IChDQSkgQ2VydGlmaWNhdGVcIixcbiAgICAgICAgICBcIi5kb2NrZXJjZmdcIjogXCJEb2NrZXIgY29uZmlndXJhdGlvbiB0b2tlblwiXG4gICAgICAgIH07XG5cblxuICAgICAgICAkc2NvcGUuJG9uKCdrdWJlcm5ldGVzTW9kZWxVcGRhdGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmICgkc2NvcGUuaWQgJiYgISRzY29wZS5zZWNyZXQpIHtcbiAgICAgICAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgICAgICB1cGRhdGVEYXRhKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRzY29wZS5wcm9wZXJ0eUtleXMgPSAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIF8ua2V5cyhzZWNyZXRMYWJlbHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS5jaGVja05hbWVVbmlxdWUgPSAodmFsdWUpID0+IHtcbiAgICAgICAgICB2YXIgYW5zd2VyID0gdHJ1ZTtcbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2goJHNjb3BlLm1vZGVsLnNlY3JldHMsIChzZWNyZXQpID0+IHtcbiAgICAgICAgICAgIHZhciBuYW1lID0gZ2V0TmFtZShzZWNyZXQpO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09PSBuYW1lKSB7XG4gICAgICAgICAgICAgIGFuc3dlciA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBhbnN3ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgJHNjb3BlLmNoZWNrRmllbGRVbmlxdWUgPSAoa2V5KSA9PiB7XG4gICAgICAgICAgcmV0dXJuICRzY29wZS5lbnRpdHkucHJvcGVydGllc1trZXldID8gZmFsc2UgOiB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS5oYXNBbGxLZXlzID0gKGtleXMpID0+IHtcbiAgICAgICAgICB2YXIgYW5zd2VyID0ga2V5cyAmJiBrZXlzLmxlbmd0aDtcbiAgICAgICAgICBhbmd1bGFyLmZvckVhY2goa2V5cywgKGtleSkgPT4ge1xuICAgICAgICAgICAgaWYgKCEkc2NvcGUuZW50aXR5LnByb3BlcnRpZXNba2V5XSkge1xuICAgICAgICAgICAgICBhbnN3ZXIgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gYW5zd2VyO1xuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS5hZGRGaWVsZERpYWxvZyA9IHtcbiAgICAgICAgICBjb250cm9sbGVyOiBudWxsLFxuICAgICAgICAgIG5ld1JlcGxpY2FzOiAwLFxuICAgICAgICAgIGRpYWxvZzogbmV3IFVJLkRpYWxvZygpLFxuICAgICAgICAgIG9uT2s6ICgpID0+IHtcbiAgICAgICAgICAgICRzY29wZS5hZGRGaWVsZERpYWxvZy5kaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgICRzY29wZS5hZGREYXRhRmllbGQoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9wZW46IChjb250cm9sbGVyKSA9PiB7XG4gICAgICAgICAgICB2YXIgYWRkRmllbGREaWFsb2cgPSAkc2NvcGUuYWRkRmllbGREaWFsb2c7XG4gICAgICAgICAgICBhZGRGaWVsZERpYWxvZy5kaWFsb2cub3BlbigpO1xuXG4gICAgICAgICAgICAkdGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICQoJyNuZXdEYXRhTmFtZScpLmZvY3VzKCk7XG4gICAgICAgICAgICB9LCA1MCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBjbG9zZTogKCkgPT4ge1xuICAgICAgICAgICAgJHNjb3BlLmFkZEZpZWxkRGlhbG9nLmRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuXG5cbiAgICAgICAgJHNjb3BlLmVudGl0eUNoYW5nZWQgPSAoKSA9PiB7XG4gICAgICAgICAgJHNjb3BlLmNoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS5hZGRGaWVsZHMgPSAoa2V5cykgPT4ge1xuICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChrZXlzLCAoa2V5KSA9PiBhZGRGaWVsZChrZXkpKTtcbiAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGZ1bmN0aW9uIGFkZEZpZWxkKGtleSkge1xuICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IGNyZWF0ZVByb3BlcnR5KGtleSwgXCJcIik7XG4gICAgICAgICAgJHNjb3BlLmVudGl0eS5wcm9wZXJ0aWVzW2tleV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAkc2NvcGUuZW50aXR5Lm5ld0RhdGFLZXkgPSBcIlwiO1xuICAgICAgICAgICRzY29wZS5zaG93QWRkRGF0YUZpZWxkRm9ybSA9IGZhbHNlO1xuICAgICAgICAgICRzY29wZS5lbnRpdHlDaGFuZ2VkKCk7XG4gICAgICAgIH1cblxuICAgICAgICAkc2NvcGUuYWRkRGF0YUZpZWxkID0gKCkgPT4ge1xuICAgICAgICAgIHZhciBrZXkgPSAkc2NvcGUuZW50aXR5Lm5ld0RhdGFLZXk7XG4gICAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgYWRkRmllbGQoa2V5KTtcbiAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgICRzY29wZS5kZWxldGVQcm9wZXJ0eSA9IChrZXkpID0+IHtcbiAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICBkZWxldGUgJHNjb3BlLmVudGl0eS5wcm9wZXJ0aWVzW2tleV07XG4gICAgICAgICAgICAkc2NvcGUuZW50aXR5Q2hhbmdlZCgpO1xuICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgJHNjb3BlLmNhbmNlbCA9ICgpID0+IHtcbiAgICAgICAgICB1cGRhdGVEYXRhKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgJHNjb3BlLnNhdmUgPSAoKSA9PiB7XG4gICAgICAgICAgdmFyIGVudGl0eSA9ICRzY29wZS5lbnRpdHkgfHwge307XG4gICAgICAgICAgdmFyIG5hbWUgPSBlbnRpdHkubmFtZTtcbiAgICAgICAgICBpZiAobmFtZSkge1xuICAgICAgICAgICAgaWYgKCEkc2NvcGUuc2VjcmV0KSB7XG4gICAgICAgICAgICAgICRzY29wZS5zZWNyZXQgPSB7XG4gICAgICAgICAgICAgICAgYXBpVmVyc2lvbjogS3ViZXJuZXRlcy5kZWZhdWx0QXBpVmVyc2lvbixcbiAgICAgICAgICAgICAgICBraW5kOiBcIlNlY3JldFwiLFxuICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgICAgICBuYW1lOiBcIlwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBkYXRhOiB7fVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGF0YSA9IHt9O1xuICAgICAgICAgICAgYW5ndWxhci5mb3JFYWNoKGVudGl0eS5wcm9wZXJ0aWVzLCAocHJvcGVydHkpID0+IHtcbiAgICAgICAgICAgICAgdmFyIGtleSA9IHByb3BlcnR5LmtleTtcbiAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcGVydHkudmFsdWUgfHwgXCJcIjtcbiAgICAgICAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgICAgIGRhdGFba2V5XSA9IHdpbmRvdy5idG9hKHZhbHVlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkc2NvcGUuc2VjcmV0Lm1ldGFkYXRhLm5hbWUgPSBuYW1lO1xuICAgICAgICAgICAgJHNjb3BlLnNlY3JldC5kYXRhID0gZGF0YTtcblxuICAgICAgICAgICAgQ29yZS5ub3RpZmljYXRpb24oJ2luZm8nLCBcIlNhdmluZyBzZWNyZXQgXCIgKyBuYW1lKTtcblxuICAgICAgICAgICAga3ViZUNsaWVudC5wdXQoJHNjb3BlLnNlY3JldCxcbiAgICAgICAgICAgICAgKGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICB2YXIgc2VjcmV0c0xpbmsgPSBvblNhdmVVcmwgfHwgRGV2ZWxvcGVyLm5hbWVzcGFjZUxpbmsoJHNjb3BlLCAkcm91dGVQYXJhbXMsIFwic2VjcmV0c1wiKTtcbiAgICAgICAgICAgICAgICB2YXIgcGFyYW1zID0ge307XG4gICAgICAgICAgICAgICAgaWYgKG9uU2F2ZVVybCkge1xuICAgICAgICAgICAgICAgICAgcGFyYW1zWydzZWNyZXQnXSA9IG5hbWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRsb2NhdGlvbi5wYXRoKHNlY3JldHNMaW5rKTtcbiAgICAgICAgICAgICAgICAkbG9jYXRpb24uc2VhcmNoKHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgbG9nLmluZm8oXCJuYXZpZ2F0aW5nIHRvIFVSTDogXCIgKyBzZWNyZXRzTGluayArIFwiIHdpdGggcGFyYW1zIFwiICsgYW5ndWxhci50b0pzb24oJGxvY2F0aW9uLnNlYXJjaCgpKSk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBDb3JlLm5vdGlmaWNhdGlvbignZXJyb3InLCBcIkZhaWxlZCB0byBzZWNyZXQgXCIgKyBuYW1lICsgXCJcXG5cIiArIGVycik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB1cGRhdGVEYXRhKCk7XG5cbiAgICAgICAgZnVuY3Rpb24gY3JlYXRlUHJvcGVydHkoa2V5LCB0ZXh0KSB7XG4gICAgICAgICAgdmFyIGxhYmVsID0gc2VjcmV0TGFiZWxzW2tleV0gfHwgQ29yZS5odW1hbml6ZVZhbHVlKGtleSk7XG4gICAgICAgICAgdmFyIHRvb2x0aXAgPSBzZWNyZXRUb29sdGlwc1trZXldIHx8IFwiVmFsdWUgb2YgdGhlIFwiICsgbGFiZWw7XG5cbiAgICAgICAgICB2YXIgcm93cyA9IDU7XG4gICAgICAgICAgdmFyIGxpbmVzID0gdGV4dC5zcGxpdChcIlxcblwiKS5sZW5ndGggKyAxO1xuICAgICAgICAgIGlmIChsaW5lcyA+IHJvd3MpIHtcbiAgICAgICAgICAgIHJvd3MgPSBsaW5lcztcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHR5cGUgPSBcInRleHRhcmVhXCI7XG4gICAgICAgICAgaWYgKGtleSA9PT0gXCJ1c2VybmFtZVwiKSB7XG4gICAgICAgICAgICB0eXBlID0gXCJ0ZXh0XCI7XG4gICAgICAgICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgICAgICAgdGV4dCA9IGN1cnJlbnRVc2VyTmFtZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSBcInBhc3N3b3JkXCIpIHtcbiAgICAgICAgICAgIHR5cGUgPSBcInBhc3N3b3JkXCI7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHtcbiAgICAgICAgICAgIGtleToga2V5LFxuICAgICAgICAgICAgbGFiZWw6IGxhYmVsLFxuICAgICAgICAgICAgdG9vbHRpcDogdG9vbHRpcCxcbiAgICAgICAgICAgIHJvd3M6IHJvd3MsXG4gICAgICAgICAgICB2YWx1ZTogdGV4dCxcbiAgICAgICAgICAgIHR5cGU6IHR5cGVcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJldHVybiBwcm9wZXJ0eTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgICAgJHNjb3BlLml0ZW0gPSBudWxsO1xuICAgICAgICAgICRzY29wZS5jaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgICAgJHNjb3BlLmVudGl0eSA9IHtcbiAgICAgICAgICAgIG5hbWU6ICRzY29wZS5pZCxcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHt9XG4gICAgICAgICAgfTtcbiAgICAgICAgICBpZiAoJHNjb3BlLmlkKSB7XG4gICAgICAgICAgICBhbmd1bGFyLmZvckVhY2goJHNjb3BlLm1vZGVsLnNlY3JldHMsIChzZWNyZXQpID0+IHtcbiAgICAgICAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHNlY3JldCk7XG4gICAgICAgICAgICAgIGlmIChuYW1lID09PSAkc2NvcGUuaWQpIHtcbiAgICAgICAgICAgICAgICAkc2NvcGUuc2VjcmV0ID0gc2VjcmV0O1xuICAgICAgICAgICAgICAgIGFuZ3VsYXIuZm9yRWFjaChzZWNyZXQuZGF0YSwgKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgIGlmIChhbmd1bGFyLmlzU3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gd2luZG93LmF0b2IodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gY3JlYXRlUHJvcGVydHkoa2V5LCB0ZXh0KTtcbiAgICAgICAgICAgICAgICAgICRzY29wZS5lbnRpdHkucHJvcGVydGllc1trZXldID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgJHNjb3BlLmZldGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIENvcmUuJGFwcGx5KCRzY29wZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY3JlYXRlS2luZCA9PT0gXCJzc2hcIikge1xuICAgICAgICAgICAgICAkc2NvcGUuYWRkRmllbGRzKCRzY29wZS5zc2hLZXlzKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY3JlYXRlS2luZCA9PT0gXCJodHRwc1wiKSB7XG4gICAgICAgICAgICAgICRzY29wZS5hZGRGaWVsZHMoJHNjb3BlLmh0dHBzS2V5cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfV0pO1xufVxuIiwiLy8vIDxyZWZlcmVuY2UgcGF0aD1cIi4uLy4uL2luY2x1ZGVzLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cImt1YmVybmV0ZXNQbHVnaW4udHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc01vZGVsLnRzXCIvPlxuLy8vIDxyZWZlcmVuY2UgcGF0aD1cInV0aWxIZWxwZXJzLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBTZWNyZXRzQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJTZWNyZXRzQ29udHJvbGxlclwiLCBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCJTZXJ2aWNlUmVnaXN0cnlcIiwgXCIkZGlhbG9nXCIsIFwiJHdpbmRvd1wiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGxvY2F0aW9uXCIsIFwibG9jYWxTdG9yYWdlXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIixcbiAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6IEt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLCBTZXJ2aWNlUmVnaXN0cnksICRkaWFsb2csICR3aW5kb3csICR0ZW1wbGF0ZUNhY2hlLCAkcm91dGVQYXJhbXMsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCBsb2NhbFN0b3JhZ2UsICRodHRwLCAkdGltZW91dCwgS3ViZXJuZXRlc0FwaVVSTCkgPT4ge1xuXG4gICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgIH0pO1xuXG4gICAgJHNjb3BlLiRjcmVhdGVTZWNyZXRMaW5rID0gRGV2ZWxvcGVyLm5hbWVzcGFjZUxpbmsoJHNjb3BlLCAkcm91dGVQYXJhbXMsIFwic2VjcmV0Q3JlYXRlXCIpO1xuXG4gICAgdmFyIGt1YmVDbGllbnQgPSBjcmVhdGVLdWJlcm5ldGVzQ2xpZW50KFwic2VjcmV0c1wiKTtcblxuICAgICRzY29wZS50YWJsZUNvbmZpZyA9IHtcbiAgICAgIGRhdGE6ICdtb2RlbC5zZWNyZXRzJyxcbiAgICAgIHNob3dTZWxlY3Rpb25DaGVja2JveDogdHJ1ZSxcbiAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgIG11bHRpU2VsZWN0OiB0cnVlLFxuICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgIGZpbHRlclRleHQ6ICRsb2NhdGlvbi5zZWFyY2goKVtcInFcIl0gfHwgJydcbiAgICAgIH0sXG4gICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBmaWVsZDogJ19rZXknLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTmFtZScsXG4gICAgICAgICAgZGVmYXVsdFNvcnQ6IHRydWUsXG4gICAgICAgICAgY2VsbFRlbXBsYXRlOiAkdGVtcGxhdGVDYWNoZS5nZXQoXCJpZFRlbXBsYXRlLmh0bWxcIilcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGZpZWxkOiAnJGxhYmVsc1RleHQnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTGFiZWxzJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImxhYmVsVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgXVxuICAgIH07XG5cbiAgICAkc2NvcGUuZGVsZXRlUHJvbXB0ID0gKHNlbGVjdGVkKSA9PiB7XG4gICAgICAgVUkubXVsdGlJdGVtQ29uZmlybUFjdGlvbkRpYWxvZyg8VUkuTXVsdGlJdGVtQ29uZmlybUFjdGlvbk9wdGlvbnM+e1xuICAgICAgICAgY29sbGVjdGlvbjogc2VsZWN0ZWQsXG4gICAgICAgICBpbmRleDogJ21ldGFkYXRhLm5hbWUnLFxuICAgICAgICAgb25DbG9zZTogKHJlc3VsdDpib29sZWFuKSA9PiB7XG4gICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICBmdW5jdGlvbiBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgbmV4dCkge1xuICAgICAgICAgICAgICAgaWYgKG5leHQpIHtcbiAgICAgICAgICAgICAgICAga3ViZUNsaWVudC5kZWxldGUobmV4dCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAvLyBUT0RPXG4gICAgICAgICAgICAgICAgIC8vIHVwZGF0ZURhdGEoKTtcbiAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgIH1cbiAgICAgICAgIH0sXG4gICAgICAgICB0aXRsZTogJ0RlbGV0ZSBTZWNyZXRzJyxcbiAgICAgICAgIGFjdGlvbjogJ1RoZSBmb2xsb3dpbmcgU2VjcmV0cyB3aWxsIGJlIGRlbGV0ZWQ6JyxcbiAgICAgICAgIG9rVGV4dDogJ0RlbGV0ZScsXG4gICAgICAgICBva0NsYXNzOiAnYnRuLWRhbmdlcicsXG4gICAgICAgICBjdXN0b206IFwiVGhpcyBvcGVyYXRpb24gaXMgcGVybWFuZW50IG9uY2UgY29tcGxldGVkIVwiLFxuICAgICAgICAgY3VzdG9tQ2xhc3M6IFwiYWxlcnQgYWxlcnQtd2FybmluZ1wiXG4gICAgICAgfSkub3BlbigpO1xuICAgICB9O1xuXG4gICAgS3ViZXJuZXRlcy5pbml0U2hhcmVkKCRzY29wZSwgJGxvY2F0aW9uLCAkaHR0cCwgJHRpbWVvdXQsICRyb3V0ZVBhcmFtcywgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpO1xuICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIGV4cG9ydCB2YXIgU2VydmljZUNvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiU2VydmljZUNvbnRyb2xsZXJcIixcbiAgICBbXCIkc2NvcGVcIiwgXCJLdWJlcm5ldGVzTW9kZWxcIiwgXCJLdWJlcm5ldGVzU3RhdGVcIiwgXCIkdGVtcGxhdGVDYWNoZVwiLCBcIiRsb2NhdGlvblwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIiRodHRwXCIsIFwiJHRpbWVvdXRcIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsXG4gICAgICAoJHNjb3BlLCBLdWJlcm5ldGVzTW9kZWw6IEt1YmVybmV0ZXMuS3ViZXJuZXRlc01vZGVsU2VydmljZSwgS3ViZXJuZXRlc1N0YXRlLFxuICAgICAgICR0ZW1wbGF0ZUNhY2hlOm5nLklUZW1wbGF0ZUNhY2hlU2VydmljZSwgJGxvY2F0aW9uOm5nLklMb2NhdGlvblNlcnZpY2UsICRyb3V0ZVBhcmFtcywgJGh0dHAsICR0aW1lb3V0LCBLdWJlcm5ldGVzQXBpVVJMKSA9PiB7XG5cbiAgICAkc2NvcGUua3ViZXJuZXRlcyA9IEt1YmVybmV0ZXNTdGF0ZTtcbiAgICAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgJHNjb3BlLnJhd01vZGVsID0gbnVsbDtcblxuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICRzY29wZS5pdGVtQ29uZmlnID0ge1xuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAnXlxcXFwvbGFiZWxzJCc6IHtcbiAgICAgICAgICB0ZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KCdsYWJlbFRlbXBsYXRlLmh0bWwnKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgICRzY29wZS4kb24oJ2t1YmVybmV0ZXNNb2RlbFVwZGF0ZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB1cGRhdGVEYXRhKCk7XG4gICAgfSk7XG5cbiAgICAkc2NvcGUuJHdhdGNoKCdtb2RlbC5zZXJ2aWNlcycsIChuZXdWYWx1ZSwgb2xkVmFsdWUpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9LCB0cnVlKTtcblxuICAgICRzY29wZS4kb24oJyRyb3V0ZVVwZGF0ZScsICgkZXZlbnQpID0+IHtcbiAgICAgIHVwZGF0ZURhdGEoKTtcbiAgICB9KTtcblxuICAgICRzY29wZS5mbGlwUmF3ID0gKCkgPT4ge1xuICAgICAgJHNjb3BlLnJhd01vZGUgPSAhJHNjb3BlLnJhd01vZGU7XG4gICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgIH07XG5cbiAgICB1cGRhdGVEYXRhKCk7XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVEYXRhKCkge1xuICAgICAgJHNjb3BlLmlkID0gJHJvdXRlUGFyYW1zW1wiaWRcIl07XG4gICAgICAkc2NvcGUubmFtZXNwYWNlID0gJHJvdXRlUGFyYW1zW1wibmFtZXNwYWNlXCJdIHx8IEt1YmVybmV0ZXNTdGF0ZS5zZWxlY3RlZE5hbWVzcGFjZTtcbiAgICAgICRzY29wZS5pdGVtID0gJHNjb3BlLm1vZGVsLmdldFNlcnZpY2UoJHNjb3BlLm5hbWVzcGFjZSwgJHNjb3BlLmlkKTtcbiAgICAgIGlmICgkc2NvcGUuaXRlbSkge1xuICAgICAgICAkc2NvcGUucmF3TW9kZWwgPSB0b1Jhd1lhbWwoJHNjb3BlLml0ZW0pO1xuICAgICAgfVxuICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICB9XG4gIH1dKTtcbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBTZXJ2aWNlRWRpdENvbnRyb2xsZXIgPSBjb250cm9sbGVyKFwiU2VydmljZUVkaXRDb250cm9sbGVyXCIsXG4gICAgW1wiJHNjb3BlXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc1NjaGVtYVwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJHJvdXRlUGFyYW1zXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIkt1YmVybmV0ZXNBcGlVUkxcIiwgXCJTY2hlbWFSZWdpc3RyeVwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOiBLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc1NjaGVtYSxcbiAgICAgICAkdGVtcGxhdGVDYWNoZTpuZy5JVGVtcGxhdGVDYWNoZVNlcnZpY2UsICRsb2NhdGlvbjpuZy5JTG9jYXRpb25TZXJ2aWNlLCAkcm91dGVQYXJhbXMsICRodHRwLCAkdGltZW91dCwgS3ViZXJuZXRlc0FwaVVSTCwgc2NoZW1hczpIYXd0aW9Gb3Jtcy5TY2hlbWFSZWdpc3RyeSkgPT4ge1xuXG4gICAgJHNjb3BlLmt1YmVybmV0ZXMgPSBLdWJlcm5ldGVzU3RhdGU7XG4gICAgJHNjb3BlLm1vZGVsID0gS3ViZXJuZXRlc01vZGVsO1xuICAgICRzY29wZS5pZCA9ICRyb3V0ZVBhcmFtc1tcImlkXCJdO1xuICAgICRzY29wZS5zY2hlbWEgPSBLdWJlcm5ldGVzU2NoZW1hO1xuICAgICRzY29wZS5jb25maWcgPSBzY2hlbWFzLmNsb25lU2NoZW1hKFwiaW8uZmFicmljOC5rdWJlcm5ldGVzLmFwaS5tb2RlbC5TZXJ2aWNlXCIpO1xuICAgIC8vJHNjb3BlLmNvbmZpZyA9IEt1YmVybmV0ZXNTY2hlbWEuZGVmaW5pdGlvbnMua3ViZXJuZXRlc192MWJldGEyX1NlcnZpY2U7XG5cbiAgICBLdWJlcm5ldGVzLmluaXRTaGFyZWQoJHNjb3BlLCAkbG9jYXRpb24sICRodHRwLCAkdGltZW91dCwgJHJvdXRlUGFyYW1zLCBLdWJlcm5ldGVzTW9kZWwsIEt1YmVybmV0ZXNTdGF0ZSwgS3ViZXJuZXRlc0FwaVVSTCk7XG5cbiAgICAkc2NvcGUuJG9uKCckcm91dGVVcGRhdGUnLCAoJGV2ZW50KSA9PiB7XG4gICAgICB1cGRhdGVEYXRhKCk7XG4gICAgfSk7XG5cbiAgICB1cGRhdGVEYXRhKCk7XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVEYXRhKCkge1xuICAgICAgaWYgKCRzY29wZS5pZCkge1xuICAgICAgICAkc2NvcGUuZW50aXR5ID0gJHNjb3BlLm1vZGVsLmdldFNlcnZpY2UoS3ViZXJuZXRlc1N0YXRlLnNlbGVjdGVkTmFtZXNwYWNlLCAkc2NvcGUuaWQpO1xuICAgICAgICBDb3JlLiRhcHBseSgkc2NvcGUpO1xuICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkc2NvcGUuZmV0Y2hlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzTW9kZWwudHNcIi8+XG5cbm1vZHVsZSBLdWJlcm5ldGVzIHtcblxuICBfbW9kdWxlLmZhY3RvcnkoJ1NlcnZpY2VSZWdpc3RyeScsIFsoKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBTZXJ2aWNlUmVnaXN0cnlTZXJ2aWNlKCk7XG4gIH1dKTtcblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhIHNpbXBsZSBpbnRlcmZhY2UgdG8gc2VydmljZSBkaXNjb3ZlcnkgdGhhdCBjYW4gYmUgdXNlZCBlYXJseSBvbiBpbiB0aGUgYXBwbGljYXRpb24gbGlmZWN5Y2xlIGJlZm9yZSB0aGVcbiAgICogdW5kZXJseWluZyBtb2RlbCBoYXMgYmVlbiBjcmVhdGVkIHZpYSBkZXBlbmRlbmN5IGluamVjdGlvblxuICAgKi9cbiAgZXhwb3J0IGNsYXNzIFNlcnZpY2VSZWdpc3RyeVNlcnZpY2Uge1xuICAgIHByaXZhdGUgbW9kZWw6S3ViZXJuZXRlc01vZGVsU2VydmljZSA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlcmUgaXMgYSBzZXJ2aWNlIGF2YWlsYWJsZSBmb3IgdGhlIGdpdmVuIElEIG9yIGZhbHNlXG4gICAgICovXG4gICAgcHVibGljIGhhc1NlcnZpY2Uoc2VydmljZU5hbWU6IHN0cmluZykge1xuICAgICAgcmV0dXJuIHRoaXMuZmluZFNlcnZpY2Uoc2VydmljZU5hbWUpID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNlcnZpY2UgZm9yIHRoZSBnaXZlbiBzZXJ2aWNlIG5hbWUgKElEKSBvciBudWxsIGlmIGl0IGNhbm5vdCBiZSBmb3VuZFxuICAgICAqXG4gICAgICogQHBhcmFtIHNlcnZpY2VOYW1lIHRoZSBuYW1lIG9mIHRoZSBzZXJ2aWNlIHRvIGxvb2sgZm9yXG4gICAgICogQHJldHVybiB7bnVsbH1cbiAgICAgKi9cbiAgICBwdWJsaWMgZmluZFNlcnZpY2Uoc2VydmljZU5hbWU6IHN0cmluZykge1xuICAgICAgdmFyIGFuc3dlciA9IG51bGw7XG4gICAgICBpZiAoc2VydmljZU5hbWUpIHtcbiAgICAgICAgdmFyIG1vZGVsID0gdGhpcy5nZXRNb2RlbCgpO1xuICAgICAgICBpZiAobW9kZWwpIHtcbiAgICAgICAgICB2YXIgbmFtZXNwYWNlID0gbW9kZWwuY3VycmVudE5hbWVzcGFjZSgpO1xuICAgICAgICAgIHJldHVybiBtb2RlbC5nZXRTZXJ2aWNlKG5hbWVzcGFjZSAsc2VydmljZU5hbWUpO1xuLypcbiAgICAgICAgVE9ETyBsZXRzIG9ubHkgbG9vayBpbiB0aGUgY3VycmVudCBuYW1lc3BhY2VcbiAgICAgICAgYW5ndWxhci5mb3JFYWNoKG1vZGVsLnNlcnZpY2VzLCAoc2VydmljZSkgPT4ge1xuICAgICAgICAgIGlmIChzZXJ2aWNlTmFtZSA9PT0gZ2V0TmFtZShzZXJ2aWNlKSkge1xuICAgICAgICAgICAgYW5zd2VyID0gc2VydmljZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuKi9cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzZXJ2aWNlIGxpbmsgZm9yIHRoZSBnaXZlbiBzZXJ2aWNlIG5hbWVcbiAgICAgKlxuICAgICAqIEBwYXJhbSBzZXJ2aWNlTmFtZSB0aGUgbmFtZSBvZiB0aGUgc2VydmljZVxuICAgICAqIEByZXR1cm4ge251bGx9XG4gICAgICovXG4gICAgcHVibGljIHNlcnZpY2VMaW5rKHNlcnZpY2VOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgdmFyIHNlcnZpY2UgPSB0aGlzLmZpbmRTZXJ2aWNlKHNlcnZpY2VOYW1lKTtcbiAgICAgIHJldHVybiBzZXJ2aWNlTGlua1VybChzZXJ2aWNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzZXJ2aWNlIGxpbmsgZm9yIHRoZSBnaXZlbiBzZXJ2aWNlIG5hbWUgaWYgaXRzIHJlYWR5IChoYXMgYXQgbGVhc3Qgb25lIHJlYWR5IHBvZClcbiAgICAgKlxuICAgICAqIEBwYXJhbSBzZXJ2aWNlTmFtZSB0aGUgbmFtZSBvZiB0aGUgc2VydmljZVxuICAgICAqIEByZXR1cm4ge251bGx9XG4gICAgICovXG4gICAgcHVibGljIHNlcnZpY2VSZWFkeUxpbmsoc2VydmljZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICB2YXIgc2VydmljZSA9IHRoaXMuZmluZFNlcnZpY2Uoc2VydmljZU5hbWUpO1xuICAgICAgaWYgKHJlYWR5UG9kQ291bnQoc2VydmljZSkpIHtcbiAgICAgICAgcmV0dXJuIHNlcnZpY2VMaW5rVXJsKHNlcnZpY2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRNb2RlbCgpOkt1YmVybmV0ZXNNb2RlbFNlcnZpY2Uge1xuICAgICAgdmFyIGFuc3dlciA9IHRoaXMubW9kZWw7XG4gICAgICAvLyBsZXRzIGFsbG93IGxhenkgbG9hZCBzbyB3ZSBjYW4gYmUgaW52b2tlZCBiZWZvcmUgdGhlIGluamVjdG9yIGhhcyBiZWVuIGNyZWF0ZWRcbiAgICAgIGlmICghYW5zd2VyKSB7XG4gICAgICAgIHZhciBpbmplY3RvciA9IEhhd3Rpb0NvcmUuaW5qZWN0b3I7XG4gICAgICAgIGlmIChpbmplY3Rvcikge1xuICAgICAgICAgIHRoaXMubW9kZWwgPSBpbmplY3Rvci5nZXQ8S3ViZXJuZXRlc01vZGVsU2VydmljZT4oJ0t1YmVybmV0ZXNNb2RlbCcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBhbnN3ZXIgPSB0aGlzLm1vZGVsO1xuICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICB9XG4gIH1cbn1cbiIsIi8vLyA8cmVmZXJlbmNlIHBhdGg9XCIuLi8uLi9pbmNsdWRlcy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzSGVscGVycy50c1wiLz5cbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJrdWJlcm5ldGVzUGx1Z2luLnRzXCIvPlxuXG5tb2R1bGUgS3ViZXJuZXRlcyB7XG5cbiAgZXhwb3J0IHZhciBTZXJ2aWNlQXBwcyA9IF9tb2R1bGUuY29udHJvbGxlcignS3ViZXJuZXRlcy5TZXJ2aWNlQXBwcycsICgkc2NvcGUsIEt1YmVybmV0ZXNNb2RlbCkgPT4ge1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcbiAgfSk7XG5cbiAgZXhwb3J0IHZhciBTZXJ2aWNlcyA9IGNvbnRyb2xsZXIoXCJTZXJ2aWNlc1wiLFxuICAgIFtcIiRzY29wZVwiLCBcIkt1YmVybmV0ZXNNb2RlbFwiLCBcIkt1YmVybmV0ZXNTZXJ2aWNlc1wiLCBcIkt1YmVybmV0ZXNQb2RzXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiJHRlbXBsYXRlQ2FjaGVcIiwgXCIkbG9jYXRpb25cIiwgXCIkcm91dGVQYXJhbXNcIiwgXCIkaHR0cFwiLCBcIiR0aW1lb3V0XCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICAgKCRzY29wZSwgS3ViZXJuZXRlc01vZGVsOiBLdWJlcm5ldGVzLkt1YmVybmV0ZXNNb2RlbFNlcnZpY2UsIEt1YmVybmV0ZXNTZXJ2aWNlczpuZy5yZXNvdXJjZS5JUmVzb3VyY2VDbGFzczxhbnk+LCBLdWJlcm5ldGVzUG9kczpuZy5yZXNvdXJjZS5JUmVzb3VyY2VDbGFzczxhbnk+LCBLdWJlcm5ldGVzU3RhdGUsXG4gICAgICAgJHRlbXBsYXRlQ2FjaGU6bmcuSVRlbXBsYXRlQ2FjaGVTZXJ2aWNlLCAkbG9jYXRpb246bmcuSUxvY2F0aW9uU2VydmljZSwgJHJvdXRlUGFyYW1zLCAkaHR0cCwgJHRpbWVvdXQsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcblxuICAgICRzY29wZS5rdWJlcm5ldGVzID0gS3ViZXJuZXRlc1N0YXRlO1xuICAgICRzY29wZS5tb2RlbCA9IEt1YmVybmV0ZXNNb2RlbDtcblxuICAgIENvbnRyb2xsZXJIZWxwZXJzLmJpbmRNb2RlbFRvU2VhcmNoUGFyYW0oJHNjb3BlLCAkbG9jYXRpb24sICdtb2RlJywgJ21vZGUnLCAnbGlzdCcpO1xuXG4gICAgJHNjb3BlLnRhYmxlQ29uZmlnID0ge1xuICAgICAgZGF0YTogJ21vZGVsLnNlcnZpY2VzJyxcbiAgICAgIHNob3dTZWxlY3Rpb25DaGVja2JveDogdHJ1ZSxcbiAgICAgIGVuYWJsZVJvd0NsaWNrU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgIG11bHRpU2VsZWN0OiB0cnVlLFxuICAgICAgc2VsZWN0ZWRJdGVtczogW10sXG4gICAgICBmaWx0ZXJPcHRpb25zOiB7XG4gICAgICAgIGZpbHRlclRleHQ6ICRsb2NhdGlvbi5zZWFyY2goKVtcInFcIl0gfHwgJydcbiAgICAgIH0sXG4gICAgICBjb2x1bW5EZWZzOiBbXG4gICAgICAgIHsgZmllbGQ6ICdfa2V5JyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ05hbWUnLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwiaWRUZW1wbGF0ZS5odG1sXCIpXG4gICAgICAgIH0sXG4gICAgICAgIHsgZmllbGQ6ICckc2VydmljZVVybCcsXG4gICAgICAgICAgZGlzcGxheU5hbWU6ICdBZGRyZXNzJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcInBvcnRhbEFkZHJlc3MuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgICB7IGZpZWxkOiAnJHBvZENvdW50JyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ1BvZHMnLFxuICAgICAgICAgIGNlbGxUZW1wbGF0ZTogJHRlbXBsYXRlQ2FjaGUuZ2V0KFwicG9kQ291bnRzQW5kTGlua1RlbXBsYXRlLmh0bWxcIiksXG4gICAgICAgICAgY3VzdG9tU29ydEZpZWxkOiAoZmllbGQpID0+IHtcbiAgICAgICAgICAgIC8vIG5lZWQgdG8gY29uY2F0IGFsbCB0aGUgcG9kIGNvdW50ZXJzXG4gICAgICAgICAgICB2YXIgcmVhZHkgPSBmaWVsZC4kcG9kQ291bnRlcnMucmVhZHkgfHwgMDtcbiAgICAgICAgICAgIHZhciB2YWxpZCA9IGZpZWxkLiRwb2RDb3VudGVycy52YWxpZCB8fCAwO1xuICAgICAgICAgICAgdmFyIHdhaXRpbmcgPSBmaWVsZC4kcG9kQ291bnRlcnMud2FpdGluZyB8fCAwO1xuICAgICAgICAgICAgdmFyIGVycm9yID0gZmllbGQuJHBvZENvdW50ZXJzLmVycm9yIHx8IDA7XG4gICAgICAgICAgICByZXR1cm4gcmVhZHkgKyB2YWxpZCArIHdhaXRpbmcgKyBlcnJvcjtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHsgZmllbGQ6ICckc2VsZWN0b3JUZXh0JyxcbiAgICAgICAgICBkaXNwbGF5TmFtZTogJ1NlbGVjdG9yJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcInNlbGVjdG9yVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9LFxuICAgICAgICB7IGZpZWxkOiAnJGxhYmVsc1RleHQnLFxuICAgICAgICAgIGRpc3BsYXlOYW1lOiAnTGFiZWxzJyxcbiAgICAgICAgICBjZWxsVGVtcGxhdGU6ICR0ZW1wbGF0ZUNhY2hlLmdldChcImxhYmVsVGVtcGxhdGUuaHRtbFwiKVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfTtcblxuICAgIEt1YmVybmV0ZXMuaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICRzY29wZS5kZWxldGVQcm9tcHQgPSAoc2VsZWN0ZWQpID0+IHtcbiAgICAgIGlmIChhbmd1bGFyLmlzU3RyaW5nKHNlbGVjdGVkKSkge1xuICAgICAgICBzZWxlY3RlZCA9IFt7XG4gICAgICAgICAgaWQ6IHNlbGVjdGVkXG4gICAgICAgIH1dO1xuICAgICAgfVxuICAgICAgVUkubXVsdGlJdGVtQ29uZmlybUFjdGlvbkRpYWxvZyg8VUkuTXVsdGlJdGVtQ29uZmlybUFjdGlvbk9wdGlvbnM+e1xuICAgICAgICBjb2xsZWN0aW9uOiBzZWxlY3RlZCxcbiAgICAgICAgaW5kZXg6ICdtZXRhZGF0YS5uYW1lJyxcbiAgICAgICAgb25DbG9zZTogKHJlc3VsdDpib29sZWFuKSA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgZnVuY3Rpb24gZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQ6QXJyYXk8S3ViZVBvZD4sIG5leHQ6S3ViZVBvZCkge1xuICAgICAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcImRlbGV0aW5nOiBcIiwgZ2V0TmFtZShuZXh0KSk7XG4gICAgICAgICAgICAgICAgS3ViZXJuZXRlc1NlcnZpY2VzLmRlbGV0ZSh7XG4gICAgICAgICAgICAgICAgICBpZDogZ2V0TmFtZShuZXh0KVxuICAgICAgICAgICAgICAgIH0sIHVuZGVmaW5lZCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiZGVsZXRlZDogXCIsIGdldE5hbWUobmV4dCkpO1xuICAgICAgICAgICAgICAgICAgZGVsZXRlU2VsZWN0ZWQoc2VsZWN0ZWQsIHNlbGVjdGVkLnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRXJyb3IgZGVsZXRpbmc6IFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICBkZWxldGVTZWxlY3RlZChzZWxlY3RlZCwgc2VsZWN0ZWQuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZVNlbGVjdGVkKHNlbGVjdGVkLCBzZWxlY3RlZC5zaGlmdCgpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlOiAnRGVsZXRlIHNlcnZpY2VzPycsXG4gICAgICAgIGFjdGlvbjogJ1RoZSBmb2xsb3dpbmcgc2VydmljZXMgd2lsbCBiZSBkZWxldGVkOicsXG4gICAgICAgIG9rVGV4dDogJ0RlbGV0ZScsXG4gICAgICAgIG9rQ2xhc3M6ICdidG4tZGFuZ2VyJyxcbiAgICAgICAgY3VzdG9tOiBcIlRoaXMgb3BlcmF0aW9uIGlzIHBlcm1hbmVudCBvbmNlIGNvbXBsZXRlZCFcIixcbiAgICAgICAgY3VzdG9tQ2xhc3M6IFwiYWxlcnQgYWxlcnQtd2FybmluZ1wiXG4gICAgICB9KS5vcGVuKCk7XG4gICAgfTtcblxuICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIC8vIGNvbnRyb2xsZXIgZm9yIHRoZSBzdGF0dXMgaWNvbiBjZWxsXG4gIGV4cG9ydCB2YXIgUG9kU3RhdHVzID0gY29udHJvbGxlcihcIlBvZFN0YXR1c1wiLCBbXCIkc2NvcGVcIiwgKCRzY29wZSkgPT4ge1xuICAgICRzY29wZS5zdGF0dXNNYXBwaW5nID0gKHRleHQpID0+IHtcbiAgICAgIHJldHVybiBzdGF0dXNUZXh0VG9Dc3NDbGFzcyh0ZXh0KTtcbiAgICB9XG4gIH1dKTtcblxuICBfbW9kdWxlLmNvbnRyb2xsZXIoXCJLdWJlcm5ldGVzLlRlcm1Db250cm9sbGVyXCIsICgkc2NvcGUsIFRlcm1pbmFsU2VydmljZSkgPT4ge1xuICAgICRzY29wZS5jYW5Db25uZWN0VG8gPSAoY29udGFpbmVyKSA9PiB7XG4gICAgICBpZiAoY29udGFpbmVyLnNlY3VyaXR5Q29udGV4dCAmJiBjb250YWluZXIuc2VjdXJpdHlDb250ZXh0LnByaXZpbGVnZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgICRzY29wZS5vcGVuVGVybWluYWwgPSAoc2VsZkxpbmssIGNvbnRhaW5lck5hbWUpID0+IHtcbiAgICAgIHZhciBpZCA9IFRlcm1pbmFsU2VydmljZS5uZXdUZXJtaW5hbChzZWxmTGluaywgY29udGFpbmVyTmFtZSk7XG4gICAgICBsb2cuZGVidWcoXCJDcmVhdGVkIHRlcm1pbmFsLCBpZDogXCIsIGlkKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGNvbnRyb2xsZXIgdGhhdCBkZWFscyB3aXRoIHRoZSBsYWJlbHMgcGVyIHBvZFxuICBleHBvcnQgdmFyIExhYmVscyA9IGNvbnRyb2xsZXIoXCJMYWJlbHNcIiwgW1wiJHNjb3BlXCIsIFwiJGxvY2F0aW9uXCIsICgkc2NvcGUsICRsb2NhdGlvbikgPT4ge1xuICAgICRzY29wZS5sYWJlbHMgPSBbXTtcbiAgICB2YXIgbGFiZWxLZXlXZWlnaHRzID0ge1xuICAgICAgXCJuYW1lXCI6IDEsXG4gICAgICBcInJlcGxpY2F0aW9uQ29udHJvbGxlclwiOiAyLFxuICAgICAgXCJncm91cFwiOiAzXG4gICAgfTtcbiAgICAkc2NvcGUuJHdhdGNoKCdlbnRpdHknLCAobmV3VmFsdWUsIG9sZFZhbHVlKSA9PiB7XG4gICAgICBpZiAobmV3VmFsdWUpIHtcbiAgICAgICAgLy8gbG9nLmRlYnVnKFwibGFiZWxzOiBcIiwgbmV3VmFsdWUpO1xuICAgICAgICAvLyBtYXNzYWdlIHRoZSBsYWJlbHMgYSBiaXRcbiAgICAgICAgJHNjb3BlLmxhYmVscyA9IFtdO1xuICAgICAgICBhbmd1bGFyLmZvckVhY2goQ29yZS5wYXRoR2V0KCRzY29wZS5lbnRpdHksIFtcIm1ldGFkYXRhXCIsIFwibGFiZWxzXCJdKSwgKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICBpZiAoa2V5ID09PSAnZmFicmljOCcgfHwga2V5ID09PSAnc3R5bGUnIHx8IGtleSA9PT0gJ3N0YXR1cycpIHtcbiAgICAgICAgICAgIC8vIFRPRE8gbm90IHN1cmUgd2hhdCB0aGlzIGlzIGZvciwgdGhlIGNvbnRhaW5lciB0eXBlP1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICRzY29wZS5sYWJlbHMucHVzaCh7XG4gICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgIHRpdGxlOiB2YWx1ZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyAgbGV0cyBzb3J0IGJ5IGtleSBidXQgbGV0cyBtYWtlIHN1cmUgdGhhdCB3ZSB3ZWlnaHQgY2VydGFpbiBsYWJlbHMgc28gdGhleSBhcmUgZmlyc3RcbiAgICAgICAgJHNjb3BlLmxhYmVscyA9ICRzY29wZS5sYWJlbHMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgIGZ1bmN0aW9uIGdldFdlaWdodChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBsYWJlbEtleVdlaWdodHNba2V5XSB8fCAxMDAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgbjEgPSBhW1wia2V5XCJdO1xuICAgICAgICAgIHZhciBuMiA9IGJbXCJrZXlcIl07XG4gICAgICAgICAgdmFyIHcxID0gZ2V0V2VpZ2h0KG4xKTtcbiAgICAgICAgICB2YXIgdzIgPSBnZXRXZWlnaHQobjIpO1xuICAgICAgICAgIHZhciBkaWZmID0gdzEgLSB3MjtcbiAgICAgICAgICBpZiAoZGlmZiA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGRpZmYgPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG4xICYmIG4yKSB7XG4gICAgICAgICAgICBpZiAobjEgPiBuMikge1xuICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobjEgPCBuMikge1xuICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKG4xID09PSBuMikge1xuICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobjEpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgICRzY29wZS5oYW5kbGVDbGljayA9IChlbnRpdHksIGxhYmVsVHlwZTpzdHJpbmcsIHZhbHVlKSA9PiB7XG4gICAgICAvLyBsb2cuZGVidWcoXCJoYW5kbGVDbGljaywgZW50aXR5OiBcIiwgZW50aXR5LCBcIiBrZXk6IFwiLCBsYWJlbFR5cGUsIFwiIHZhbHVlOiBcIiwgdmFsdWUpO1xuICAgICAgJHNjb3BlLiRlbWl0KCdsYWJlbEZpbHRlclVwZGF0ZScsIHZhbHVlLnRpdGxlKVxuICAgIH1cblxuICAgICRzY29wZS5sYWJlbENsYXNzID0gY29udGFpbmVyTGFiZWxDbGFzcztcbiAgfV0pO1xuXG4gIC8v5pyN5Yqh54q25oCB6L+H5rukXG4gIGV4cG9ydCB2YXIgU3RhdHVzID0gY29udHJvbGxlcignU3RhdHVzJywgW1wiJHNjb3BlXCIsIFwiJGh0dHBcIiwgXCIkaW50ZXJ2YWxcIiwgXCIkbG9jYXRpb25cIiwgXCJLdWJlcm5ldGVzQXBpVVJMXCIsICgkc2NvcGUsICRodHRwLCAkaW50ZXJ2YWwsICRsb2NhdGlvbiwgS3ViZXJuZXRlc0FwaVVSTCkgPT4ge1xuICAgICAgJHNjb3BlLiR3YXRjaCgnZW50aXR5JywgKG5ld1ZhbHVlLCBvbGRWYWx1ZSkgPT4ge1xuICAgICAgICAgIGlmKG5ld1ZhbHVlKXtcbiAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygkc2NvcGUuZW50aXR5Lm1ldGFkYXRhLmxhYmVscyk7XG4gICAgICAgICAgICAgIGlmKCRzY29wZS5lbnRpdHkubWV0YWRhdGEubGFiZWxzLnN0YXR1cyA9PT0gXCIwXCIgJiYgJHNjb3BlLmVudGl0eS5tZXRhZGF0YS5sYWJlbHMubG9jayA9PT0gXCIwXCIpe1xuICAgICAgICAgICAgICAgICAgdmFyIGxhYmVscyA9XG4gICAgICAgICAgICAgICAgICBLdWJlcm5ldGVzLnVwZGF0ZVJlcGxpY2F0aW9uQ29udHJvbGxlckxhYmVscygkaHR0cCwgS3ViZXJuZXRlc0FwaVVSTCwgJHNjb3BlLmVudGl0eSwge1wic3R5bGVcIjogXCJvcmFjbGVcIiwgXCJzdGF0dXNcIjogXCIwXCIsIFwibG9ja1wiOiBcIjFcIn0pO1xuICAgICAgICAgICAgICAgICAgdmFyIGlwID0gJHNjb3BlLmVudGl0eS4kcG9kc1swXS4kaG9zdCArIFwiOlwiICsgJHNjb3BlLmVudGl0eS4kcG9kc1swXS5zcGVjLmNvbnRhaW5lcnNbMF0ucG9ydHNbMF0uaG9zdFBvcnQ7XG4gICAgICAgICAgICAgICAgICB2YXIgdGltZXIgPSAkaW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICRodHRwKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOicvY29ubmVjdFRvT3JhY2xlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOidQT1NUJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zOntwYXJhbTogaXB9XG4gICAgICAgICAgICAgICAgICAgICAgfSkuc3VjY2VzcyhmdW5jdGlvbihkYXRhLGhlYWRlcixjb25maWcsc3RhdHVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoaGVhZGVyID09PSAyMDApe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW50ZXJ2YWwuY2FuY2VsKHRpbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0pLmVycm9yKGZ1bmN0aW9uKGRhdGEsaGVhZGVyLGNvbmZpZyxzdGF0dXMpe1xuXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9LCA2MDAwMCwgMTApO1xuXG4gICAgICAgICAgICAgICAgICB0aW1lci50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkFsbCBDb25uZWN0IERvbmUhXCIpO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9LHRydWUpO1xuICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc0hlbHBlcnMudHNcIi8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuXG4gIF9tb2R1bGUuZGlyZWN0aXZlKFwiaGF3dGlvVGFic1wiLCBbJ0hhd3Rpb1N1YlRhYnMnLCAoSGF3dGlvU3ViVGFicykgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICBsaW5rOiAoc2NvcGUsIGVsZW1lbnQsIGF0dHJzKSA9PiB7XG4gICAgICAgIEhhd3Rpb1N1YlRhYnMuYXBwbHkoc2NvcGUuJGV2YWwoJ3N1YlRhYkNvbmZpZycpKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XSk7XG59XG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwia3ViZXJuZXRlc1BsdWdpbi50c1wiLz5cblxubW9kdWxlIEt1YmVybmV0ZXMge1xuICBleHBvcnQgdmFyIFRlbXBsYXRlQ29udHJvbGxlciA9IGNvbnRyb2xsZXIoXCJUZW1wbGF0ZUNvbnRyb2xsZXJcIiwgW1xuICAgIFwiJHNjb3BlXCIsIFwiJGxvY2F0aW9uXCIsIFwiJGh0dHBcIiwgXCIkdGltZW91dFwiLCBcIiRyb3V0ZVBhcmFtc1wiLCBcIm1hcmtlZFwiLCBcIiR0ZW1wbGF0ZUNhY2hlXCIsIFwiJG1vZGFsXCIsIFwiS3ViZXJuZXRlc01vZGVsXCIsIFwiS3ViZXJuZXRlc1N0YXRlXCIsIFwiS3ViZXJuZXRlc0FwaVVSTFwiLFxuICAgICgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIG1hcmtlZCwgJHRlbXBsYXRlQ2FjaGUsICRtb2RhbCwgS3ViZXJuZXRlc01vZGVsLCBLdWJlcm5ldGVzU3RhdGUsIEt1YmVybmV0ZXNBcGlVUkwpID0+IHtcbiAgICB2YXIgbW9kZWwgPSAkc2NvcGUubW9kZWwgPSBLdWJlcm5ldGVzTW9kZWw7XG4gICAgJHNjb3BlLmZpbHRlclRleHQgPSAkbG9jYXRpb24uc2VhcmNoKClbXCJxXCJdO1xuXG4gICAgJHNjb3BlLnRhcmdldE5hbWVzcGFjZSA9ICRyb3V0ZVBhcmFtcy50YXJnZXROYW1lc3BhY2U7XG4gICAgaW5pdFNoYXJlZCgkc2NvcGUsICRsb2NhdGlvbiwgJGh0dHAsICR0aW1lb3V0LCAkcm91dGVQYXJhbXMsIEt1YmVybmV0ZXNNb2RlbCwgS3ViZXJuZXRlc1N0YXRlLCBLdWJlcm5ldGVzQXBpVVJMKTtcblxuICAgICRzY29wZS4kd2F0Y2hDb2xsZWN0aW9uKCdtb2RlbC5uYW1lc3BhY2VzJywgKCkgPT4ge1xuICAgICAgaWYgKCEkc2NvcGUudGFyZ2V0TmFtZXNwYWNlKSB7XG4gICAgICAgICRzY29wZS50YXJnZXROYW1lc3BhY2UgPSBtb2RlbC5jdXJyZW50TmFtZXNwYWNlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB2YXIgcmV0dXJuVG8gPSBuZXcgVVJJKCRsb2NhdGlvbi5zZWFyY2goKVsncmV0dXJuVG8nXSB8fCAnL2t1YmVybmV0ZXMvYXBwcycpO1xuXG4gICAgZnVuY3Rpb24gZ29CYWNrKCkge1xuICAgICAgJGxvY2F0aW9uLnBhdGgocmV0dXJuVG8ucGF0aCgpKS5zZWFyY2gocmV0dXJuVG8ucXVlcnkodHJ1ZSkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEFubm90YXRpb25zKG9iaikge1xuICAgICAgcmV0dXJuIENvcmUucGF0aEdldChvYmosIFsnbWV0YWRhdGEnLCAnYW5ub3RhdGlvbnMnXSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0VmFsdWVGb3Iob2JqLCBrZXkpIHtcbiAgICAgIHZhciBhbm5vdGF0aW9ucyA9IGdldEFubm90YXRpb25zKG9iaik7XG4gICAgICBpZiAoIWFubm90YXRpb25zKSB7XG4gICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgfVxuICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKG9iaik7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICB2YXIgZnVsbEtleSA9IFwiZmFicmljOC5cIiArIG5hbWUgKyBcIi9cIiArIGtleTtcbiAgICAgICAgdmFyIGFuc3dlciA9IGFubm90YXRpb25zW2Z1bGxLZXldO1xuICAgICAgICBpZiAoYW5zd2VyKSB7XG4gICAgICAgICAgcmV0dXJuIGFuc3dlcjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIGtleTogYW55ID0gXy5maW5kKF8ua2V5cyhhbm5vdGF0aW9ucyksIChrOiBzdHJpbmcpID0+IF8uZW5kc1dpdGgoaywga2V5KSk7XG4gICAgICBpZiAoa2V5KSB7XG4gICAgICAgIHJldHVybiBhbm5vdGF0aW9uc1trZXldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgJHNjb3BlLmNhbmNlbCA9ICgpID0+IHtcbiAgICAgIGlmICgkc2NvcGUuZm9ybUNvbmZpZykge1xuICAgICAgICBkZWxldGUgJHNjb3BlLmZvcm1Db25maWc7XG4gICAgICAgIGRlbGV0ZSAkc2NvcGUuZW50aXR5O1xuICAgICAgICAkc2NvcGUub2JqZWN0cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZ29CYWNrKCk7XG4gICAgfVxuXG4gICAgLypcbiAgICAkc2NvcGUuJHdhdGNoKCdtb2RlbC50ZW1wbGF0ZXMubGVuZ3RoJywgKG5ld1ZhbHVlKSA9PiB7XG4gICAgICBpZiAobmV3VmFsdWUgPT09IDApIHtcbiAgICAgICAgZ29CYWNrKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgKi9cblxuICAgICRzY29wZS5maWx0ZXJUZW1wbGF0ZXMgPSAodGVtcGxhdGUpID0+IHtcbiAgICAgIGlmIChDb3JlLmlzQmxhbmsoJHNjb3BlLmZpbHRlclRleHQpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF8uY29udGFpbnMoYW5ndWxhci50b0pzb24odGVtcGxhdGUpLCAkc2NvcGUuZmlsdGVyVGV4dC50b0xvd2VyQ2FzZSgpKTtcbiAgICB9O1xuXG4gICAgJHNjb3BlLm9wZW5GdWxsRGVzY3JpcHRpb24gPSAodGVtcGxhdGUpID0+IHtcbiAgICAgIHZhciB0ZXh0ID0gbWFya2VkKGdldFZhbHVlRm9yKHRlbXBsYXRlLCAnZGVzY3JpcHRpb24nKSB8fCAnTm8gZGVzY3JpcHRpb24nKTtcbiAgICAgIHZhciBtb2RhbCA9ICRtb2RhbC5vcGVuKHtcbiAgICAgICAgdGVtcGxhdGVVcmw6IFVybEhlbHBlcnMuam9pbih0ZW1wbGF0ZVBhdGgsICd0ZW1wbGF0ZURlc2NyaXB0aW9uLmh0bWwnKSxcbiAgICAgICAgY29udHJvbGxlcjogWyckc2NvcGUnLCAnJG1vZGFsSW5zdGFuY2UnLCAoJHNjb3BlLCAkbW9kYWxJbnN0YW5jZSkgPT4ge1xuICAgICAgICAgICRzY29wZS50ZXh0ID0gdGV4dCxcbiAgICAgICAgICAkc2NvcGUub2sgPSAoKSA9PiB7XG4gICAgICAgICAgICBtb2RhbC5jbG9zZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfV1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAkc2NvcGUuZ2V0RGVzY3JpcHRpb24gPSAodGVtcGxhdGUpID0+IHtcbiAgICAgIHZhciBhbnN3ZXI6YW55ID0gJChtYXJrZWQoZ2V0VmFsdWVGb3IodGVtcGxhdGUsICdkZXNjcmlwdGlvbicpIHx8ICdObyBkZXNjcmlwdGlvbicpKTtcbiAgICAgIHZhciB0ZXh0RGVmYXVsdCA9IGFuc3dlci5odG1sKCk7XG4gICAgICB2YXIgbWF4TGVuZ3RoID0gMjAwO1xuICAgICAgaWYgKHRleHREZWZhdWx0Lmxlbmd0aCA+IG1heExlbmd0aCkge1xuICAgICAgICB2YXIgdHJ1bmNhdGVkID0gJC50cmltKHRleHREZWZhdWx0KS5zdWJzdHJpbmcoMCwgbWF4TGVuZ3RoKS5zcGxpdCgnICcpLnNsaWNlKDAsIC0xKS5qb2luKCcgJyk7XG4gICAgICAgIGFuc3dlci5odG1sKHRydW5jYXRlZCArICcuLi4nKTtcbiAgICAgICAgYW5zd2VyLmFwcGVuZCgkdGVtcGxhdGVDYWNoZS5nZXQoJ3RydW5jYXRlZERlc2NyaXB0aW9uVGFnLmh0bWwnKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYW5zd2VyLmh0bWwoKTtcbiAgICB9O1xuXG4gICAgJHNjb3BlLmdldEljb25VcmwgPSAodGVtcGxhdGUpID0+IHtcbiAgICAgIHJldHVybiBnZXRWYWx1ZUZvcih0ZW1wbGF0ZSwgJ2ljb25VcmwnKSB8fCBkZWZhdWx0SWNvblVybDtcbiAgICB9O1xuXG4gICAgJHNjb3BlLmRlcGxveVRlbXBsYXRlID0gKHRlbXBsYXRlKSA9PiB7XG4gICAgICBsb2cuZGVidWcoXCJUZW1wbGF0ZSBwYXJhbWV0ZXJzOiBcIiwgdGVtcGxhdGUucGFyYW1ldGVycyk7XG4gICAgICBsb2cuZGVidWcoXCJUZW1wbGF0ZSBvYmplY3RzOiBcIiwgdGVtcGxhdGUub2JqZWN0cyk7XG4gICAgICBsb2cuZGVidWcoXCJUZW1wbGF0ZSBhbm5vdGF0aW9uczogXCIsIHRlbXBsYXRlLm1ldGFkYXRhLmFubm90YXRpb25zKTtcbiAgICAgIHZhciB0ZW1wbGF0ZUFubm90YXRpb25zID0gdGVtcGxhdGUubWV0YWRhdGEuYW5ub3RhdGlvbnM7XG4gICAgICBpZiAodGVtcGxhdGVBbm5vdGF0aW9ucykge1xuICAgICAgICBfLmZvckVhY2godGVtcGxhdGUub2JqZWN0cywgKG9iamVjdDphbnkpID0+IHtcbiAgICAgICAgICB2YXIgYW5ub3RhdGlvbnMgPSBvYmplY3QubWV0YWRhdGEuYW5ub3RhdGlvbnMgfHwge307XG4gICAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKG9iamVjdCk7XG4gICAgICAgICAgdmFyIG1hdGNoZXMgPSBfLmZpbHRlcihfLmtleXModGVtcGxhdGVBbm5vdGF0aW9ucyksIChrZXkpID0+IGtleS5tYXRjaCgnLicgKyBuYW1lICsgJy8nKSk7XG4gICAgICAgICAgbWF0Y2hlcy5mb3JFYWNoKChtYXRjaCkgPT4ge1xuICAgICAgICAgICAgaWYgKCEobWF0Y2ggaW4gYW5ub3RhdGlvbnMpKSB7XG4gICAgICAgICAgICAgIGFubm90YXRpb25zW21hdGNoXSA9IHRlbXBsYXRlQW5ub3RhdGlvbnNbbWF0Y2hdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIG9iamVjdC5tZXRhZGF0YS5hbm5vdGF0aW9ucyA9IGFubm90YXRpb25zO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHZhciByb3V0ZVNlcnZpY2VOYW1lID0gPHN0cmluZz4gdW5kZWZpbmVkO1xuICAgICAgdmFyIHNlcnZpY2UgPSBfLmZpbmQodGVtcGxhdGUub2JqZWN0cywgKG9iaikgPT4ge1xuICAgICAgICBpZiAoZ2V0S2luZChvYmopID09PSBcIlNlcnZpY2VcIikge1xuICAgICAgICAgIHZhciBwb3J0cyA9IGdldFBvcnRzKG9iaik7XG4gICAgICAgICAgaWYgKHBvcnRzICYmIHBvcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAoc2VydmljZSkge1xuICAgICAgICByb3V0ZVNlcnZpY2VOYW1lID0gZ2V0TmFtZShzZXJ2aWNlKTtcbiAgICAgIH1cbiAgICAgIGxvZy5kZWJ1ZyhcIlNlcnZpY2U6IFwiLCBzZXJ2aWNlKTtcbiAgICAgIGlmICgoIXJvdXRlU2VydmljZU5hbWUgfHwgIWlzT3BlblNoaWZ0KSAmJiAoIXRlbXBsYXRlLnBhcmFtZXRlcnMgfHwgdGVtcGxhdGUucGFyYW1ldGVycy5sZW5ndGggPT09IDApKSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhcIk5vIHBhcmFtZXRlcnMgcmVxdWlyZWQsIGRlcGxveWluZyBvYmplY3RzXCIpO1xuICAgICAgICBhcHBseU9iamVjdHModGVtcGxhdGUub2JqZWN0cyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBmb3JtQ29uZmlnID0ge1xuICAgICAgICBzdHlsZTogSGF3dGlvRm9ybXMuRm9ybVN0eWxlLlNUQU5EQVJELFxuICAgICAgICBoaWRlTGVnZW5kOiB0cnVlLFxuICAgICAgICBwcm9wZXJ0aWVzOiA8YW55PiB7fVxuICAgICAgfTtcbiAgICAgIHZhciBwYXJhbXMgPSB0ZW1wbGF0ZS5wYXJhbWV0ZXJzO1xuICAgICAgXy5mb3JFYWNoKHBhcmFtcywgKHBhcmFtOmFueSkgPT4ge1xuICAgICAgICB2YXIgcHJvcGVydHkgPSA8YW55PiB7fTtcbiAgICAgICAgcHJvcGVydHkubGFiZWwgPSBfLnN0YXJ0Q2FzZShwYXJhbS5uYW1lKTtcbiAgICAgICAgcHJvcGVydHkuZGVzY3JpcHRpb24gPSBwYXJhbS5kZXNjcmlwdGlvbjtcbiAgICAgICAgcHJvcGVydHkuZGVmYXVsdCA9IHBhcmFtLnZhbHVlO1xuICAgICAgICAvLyBUT0RPLCBkbyBwYXJhbWV0ZXJzIHN1cHBvcnQgdHlwZXM/XG4gICAgICAgIHByb3BlcnR5LnR5cGUgPSAnc3RyaW5nJztcbiAgICAgICAgZm9ybUNvbmZpZy5wcm9wZXJ0aWVzW3BhcmFtLm5hbWVdID0gcHJvcGVydHk7XG4gICAgICB9KTtcbiAgICAgIGlmIChyb3V0ZVNlcnZpY2VOYW1lICYmIGlzT3BlblNoaWZ0KSB7XG4gICAgICAgIGZvcm1Db25maWcucHJvcGVydGllcy5jcmVhdGVSb3V0ZSA9IHtcbiAgICAgICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgZGVmYXVsdDogdHJ1ZSxcbiAgICAgICAgICBsYWJlbDogXCJDcmVhdGUgUm91dGVcIlxuICAgICAgICB9O1xuLypcbiAgICAgICAgZm9ybUNvbmZpZy5wcm9wZXJ0aWVzLnJvdXRlTmFtZSA9IHtcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICBsYWJlbDogJ1JvdXRlIE5hbWUnLFxuICAgICAgICAgIGRlZmF1bHQ6IHJvdXRlU2VydmljZU5hbWUsXG4gICAgICAgICAgJ2NvbnRyb2wtZ3JvdXAtYXR0cmlidXRlcyc6IHtcbiAgICAgICAgICAgICduZy1zaG93JzogJ2VudGl0eS5jcmVhdGVSb3V0ZSdcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4qL1xuICAgICAgICBmb3JtQ29uZmlnLnByb3BlcnRpZXMucm91dGVTZXJ2aWNlTmFtZSA9IHtcbiAgICAgICAgICB0eXBlOiAnaGlkZGVuJyxcbiAgICAgICAgICBkZWZhdWx0OiByb3V0ZVNlcnZpY2VOYW1lXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbmFtZXNwYWNlID0gY3VycmVudEt1YmVybmV0ZXNOYW1lc3BhY2UoKTtcbiAgICAgICAgLy8gVE9ETyBzdG9yZSB0aGlzIGluIGxvY2FsU3RvcmFnZSFcbiAgICAgICAgdmFyIGRvbWFpbiA9IFwidmFncmFudC5mOFwiO1xuICAgICAgICB2YXIgZGVmYXVsdFJvdXRlSG9zdFN1ZmZpeCA9ICcuJyArIChuYW1lc3BhY2UgPT09IFwiZGVmYXVsdFwiID8gXCJcIiA6IG5hbWVzcGFjZSArIFwiLlwiKSArIGRvbWFpbjtcbiAgICAgICAgZm9ybUNvbmZpZy5wcm9wZXJ0aWVzLnJvdXRlSG9zdG5hbWUgPSB7XG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgZGVmYXVsdDogZGVmYXVsdFJvdXRlSG9zdFN1ZmZpeCxcbiAgICAgICAgICBsYWJlbDogXCJSb3V0ZSBob3N0IG5hbWUgc3VmZml4XCIsXG4gICAgICAgICAgJ2NvbnRyb2wtZ3JvdXAtYXR0cmlidXRlcyc6IHtcbiAgICAgICAgICAgICduZy1zaG93JzogJ2VudGl0eS5jcmVhdGVSb3V0ZSdcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICAkc2NvcGUuZW50aXR5ID0gPGFueT4ge307XG4gICAgICAkc2NvcGUuZm9ybUNvbmZpZyA9IGZvcm1Db25maWc7XG4gICAgICAkc2NvcGUub2JqZWN0cyA9IHRlbXBsYXRlLm9iamVjdHM7XG4gICAgICBsb2cuZGVidWcoXCJGb3JtIGNvbmZpZzogXCIsIGZvcm1Db25maWcpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBzdWJzdGl0dXRlKHN0ciwgZGF0YSkge1xuICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9cXCR7XFx3Kn0vZywgKG1hdGNoKSA9PiB7XG4gICAgICAgIHZhciBrZXkgPSBtYXRjaC5yZXBsYWNlKC9cXCR7LywgJycpLnJlcGxhY2UoL30vLCAnJykudHJpbSgpO1xuICAgICAgICByZXR1cm4gZGF0YVtrZXldIHx8IG1hdGNoO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgICRzY29wZS5zdWJzdGl0dXRlQW5kRGVwbG95VGVtcGxhdGUgPSAoKSA9PiB7XG4gICAgICB2YXIgb2JqZWN0cyA9ICRzY29wZS5vYmplY3RzO1xuICAgICAgdmFyIG9iamVjdHNUZXh0ID0gYW5ndWxhci50b0pzb24ob2JqZWN0cywgdHJ1ZSk7XG4gICAgICAvLyBwdWxsIHRoZXNlIG91dCBvZiB0aGUgZW50aXR5IG9iamVjdCBzbyB0aGV5J3JlIG5vdCB1c2VkIGluIHN1YnN0aXR1dGlvbnNcbiAgICAgIHZhciBjcmVhdGVSb3V0ZSA9ICRzY29wZS5lbnRpdHkuY3JlYXRlUm91dGU7XG4gICAgICB2YXIgcm91dGVIb3N0bmFtZVN1ZmZpeCA9ICRzY29wZS5lbnRpdHkucm91dGVIb3N0bmFtZSB8fCBcIlwiO1xuICAgICAgdmFyIHJvdXRlTmFtZSA9ICRzY29wZS5lbnRpdHkucm91dGVOYW1lO1xuICAgICAgdmFyIHJvdXRlU2VydmljZU5hbWUgPSAkc2NvcGUuZW50aXR5LnJvdXRlU2VydmljZU5hbWU7XG4gICAgICBkZWxldGUgJHNjb3BlLmVudGl0eS5jcmVhdGVSb3V0ZTtcbiAgICAgIGRlbGV0ZSAkc2NvcGUuZW50aXR5LnJvdXRlSG9zdG5hbWU7XG4gICAgICBkZWxldGUgJHNjb3BlLmVudGl0eS5yb3V0ZU5hbWU7XG4gICAgICBkZWxldGUgJHNjb3BlLmVudGl0eS5yb3V0ZVNlcnZpY2VOYW1lO1xuICAgICAgb2JqZWN0c1RleHQgPSBzdWJzdGl0dXRlKG9iamVjdHNUZXh0LCAkc2NvcGUuZW50aXR5KTtcbiAgICAgIG9iamVjdHMgPSBhbmd1bGFyLmZyb21Kc29uKG9iamVjdHNUZXh0KTtcbiAgICAgIGlmIChjcmVhdGVSb3V0ZSkge1xuICAgICAgICB2YXIgcm91dGVzID0gW107XG4gICAgICAgIGFuZ3VsYXIuZm9yRWFjaChvYmplY3RzLCAob2JqZWN0KSA9PiB7XG4gICAgICAgICAgdmFyIGtpbmQgPSBvYmplY3Qua2luZDtcbiAgICAgICAgICB2YXIgbmFtZSA9IGdldE5hbWUob2JqZWN0KTtcbiAgICAgICAgICBpZiAobmFtZSAmJiBcIlNlcnZpY2VcIiA9PT0ga2luZCkge1xuICAgICAgICAgICAgdmFyIHJvdXRlSG9zdG5hbWUgPSBuYW1lICsgcm91dGVIb3N0bmFtZVN1ZmZpeDtcbiAgICAgICAgICAgIHZhciByb3V0ZSA9IHtcbiAgICAgICAgICAgICAga2luZDogXCJSb3V0ZVwiLFxuICAgICAgICAgICAgICBhcGlWZXJzaW9uOiBkZWZhdWx0T1NBcGlWZXJzaW9uLFxuICAgICAgICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHNwZWM6IHtcbiAgICAgICAgICAgICAgICBob3N0OiByb3V0ZUhvc3RuYW1lLFxuICAgICAgICAgICAgICAgIHRvOiB7XG4gICAgICAgICAgICAgICAgICBraW5kOiBcIlNlcnZpY2VcIixcbiAgICAgICAgICAgICAgICAgIG5hbWU6IG5hbWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByb3V0ZXMucHVzaChyb3V0ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgb2JqZWN0cyA9IG9iamVjdHMuY29uY2F0KHJvdXRlcyk7XG4gICAgICB9XG4gICAgICBpZiAoJHNjb3BlLnRhcmdldE5hbWVzcGFjZSAhPT0gbW9kZWwuY3VycmVudE5hbWVzcGFjZSgpKSB7XG4gICAgICAgICRzY29wZS4kb24oJ1dhdGNoZXJOYW1lc3BhY2VDaGFuZ2VkJywgKCkgPT4ge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcIk5hbWVzcGFjZSBjaGFuZ2VkXCIpO1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgYXBwbHlPYmplY3RzKG9iamVjdHMpO1xuICAgICAgICAgICAgQ29yZS4kYXBwbHkoJHNjb3BlKTtcbiAgICAgICAgICB9LCA1MDApO1xuICAgICAgICB9KTtcbiAgICAgICAgQ29yZS5ub3RpZmljYXRpb24oJ2luZm8nLCBcIlN3aXRjaGluZyB0byBuYW1lc3BhY2UgXCIgKyAkc2NvcGUudGFyZ2V0TmFtZXNwYWNlICsgXCIgYW5kIGRlcGxveWluZyB0ZW1wbGF0ZVwiKTtcbiAgICAgICAgbW9kZWwua3ViZXJuZXRlcy5zZWxlY3RlZE5hbWVzcGFjZSA9ICRzY29wZS50YXJnZXROYW1lc3BhY2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcHBseU9iamVjdHMob2JqZWN0cyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGFwcGx5T2JqZWN0cyhvYmplY3RzKSB7XG4gICAgICB2YXIgcHJvamVjdENsaWVudCA9IEt1YmVybmV0ZXMuY3JlYXRlS3ViZXJuZXRlc0NsaWVudChcInByb2plY3RzXCIpO1xuXG4gICAgICBfLmZvckVhY2gob2JqZWN0cywgKG9iamVjdDphbnkpID0+IHtcbiAgICAgICAgbG9nLmRlYnVnKFwiT2JqZWN0OiBcIiwgb2JqZWN0KTtcblxuICAgICAgICB2YXIga2luZCA9IGdldEtpbmQob2JqZWN0KTtcbiAgICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKG9iamVjdCk7XG4gICAgICAgIHZhciBucyA9IGdldE5hbWVzcGFjZShvYmplY3QpO1xuXG4gICAgICAgIGlmIChraW5kICYmIG5hbWUpIHtcbiAgICAgICAgICBpZiAobnMgJiYgbnMgIT09IGN1cnJlbnRLdWJlcm5ldGVzTmFtZXNwYWNlKCkpIHtcbiAgICAgICAgICAgIHZhciBwcm9qZWN0ID0ge1xuICAgICAgICAgICAgICBhcGlWZXJzaW9uOiBLdWJlcm5ldGVzLmRlZmF1bHRBcGlWZXJzaW9uLFxuICAgICAgICAgICAgICBraW5kOiBcIlByb2plY3RcIixcbiAgICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICBuYW1lOiBucyxcbiAgICAgICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBwcm9qZWN0Q2xpZW50LnB1dChwcm9qZWN0LFxuICAgICAgICAgICAgICAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFwiQ3JlYXRlZCBuYW1lc3BhY2U6IFwiICsgbnMpXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBsb2cud2FybihcIkZhaWxlZCB0byBjcmVhdGUgbmFtZXNwYWNlOiBcIiArIG5zICsgXCI6IFwiICsgYW5ndWxhci50b0pzb24oZXJyKSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBwbHVyYWxLaW5kID0ga2luZC50b0xvd2VyQ2FzZSgpICsgXCJzXCI7XG4gICAgICAgICAgdmFyIGt1YmVDbGllbnQgPSBLdWJlcm5ldGVzLmNyZWF0ZUt1YmVybmV0ZXNDbGllbnQocGx1cmFsS2luZCwgbnMpO1xuICAgICAgICAgIGt1YmVDbGllbnQucHV0KG9iamVjdCxcbiAgICAgICAgICAgIChkYXRhKSA9PiB7XG4gICAgICAgICAgICAgIGxvZy5pbmZvKFwidXBkYXRlZCBcIiArIGtpbmQgKyBcIiBuYW1lOiBcIiArIG5hbWUgKyAobnMgPyBcIiBuczogXCIgKyBuczogXCJcIikpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgbG9nLndhcm4oXCJGYWlsZWQgdG8gdXBkYXRlIFwiICsga2luZCArIFwiIG5hbWU6IFwiICsgbmFtZSArIChucyA/IFwiIG5zOiBcIiArIG5zOiBcIlwiKSArIFwiIGVycm9yOiBcIiArIGFuZ3VsYXIudG9Kc29uKGVycikpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgZ29CYWNrKCk7XG4gICAgfVxuXG4gICAgJHNjb3BlLmRlbGV0ZVRlbXBsYXRlID0gKHRlbXBsYXRlKSA9PiB7XG4gICAgICBVSS5tdWx0aUl0ZW1Db25maXJtQWN0aW9uRGlhbG9nKDxVSS5NdWx0aUl0ZW1Db25maXJtQWN0aW9uT3B0aW9ucz57XG4gICAgICAgIGNvbGxlY3Rpb246IFt0ZW1wbGF0ZV0sXG4gICAgICAgIGluZGV4OiAnbWV0YWRhdGEubmFtZScsXG4gICAgICAgIG9uQ2xvc2U6IChyZXN1bHQ6Ym9vbGVhbikgPT4ge1xuICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgIEt1YmVybmV0ZXNNb2RlbFsndGVtcGxhdGVzUmVzb3VyY2UnXS5kZWxldGUoe1xuICAgICAgICAgICAgICBpZDogdGVtcGxhdGUubWV0YWRhdGEubmFtZVxuICAgICAgICAgICAgfSwgdW5kZWZpbmVkLCAoKSA9PiB7XG4gICAgICAgICAgICAgIEt1YmVybmV0ZXNNb2RlbFsndGVtcGxhdGVzUmVzb3VyY2UnXS5xdWVyeSgoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIEt1YmVybmV0ZXNNb2RlbC50ZW1wbGF0ZXMgPSBkYXRhLml0ZW1zO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICBsb2cuZGVidWcoXCJFcnJvciBkZWxldGluZyB0ZW1wbGF0ZTogXCIsIGVycm9yKTsgXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlOiAnRGVsZXRlIFRlbXBsYXRlPycsXG4gICAgICAgIGFjdGlvbjogJ1RoZSBmb2xsb3dpbmcgdGVtcGxhdGUgd2lsbCBiZSBkZWxldGVkOicsXG4gICAgICAgIG9rVGV4dDogJ0RlbGV0ZScsXG4gICAgICAgIG9rQ2xhc3M6ICdidG4tZGFuZ2VyJyxcbiAgICAgICAgY3VzdG9tOiBcIlRoaXMgb3BlcmF0aW9uIGlzIHBlcm1hbmVudCBvbmNlIGNvbXBsZXRlZCFcIixcbiAgICAgICAgY3VzdG9tQ2xhc3M6IFwiYWxlcnQgYWxlcnQtd2FybmluZ1wiXG4gICAgICB9KS5vcGVuKCk7XG4gICAgfTtcbiAgfV0pO1xufVxuXG4iLCIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi4vLi4vaW5jbHVkZXMudHNcIi8+XG5tb2R1bGUgTmF2aWdhdGlvbiB7XG5cbiAgZXhwb3J0IHZhciBwbHVnaW5OYW1lID0gJ2hhd3Rpby1uYXZpZ2F0aW9uJztcbiAgZXhwb3J0IHZhciBsb2cgPSBMb2dnZXIuZ2V0KHBsdWdpbk5hbWUpO1xuICBleHBvcnQgdmFyIF9tb2R1bGUgPSBhbmd1bGFyLm1vZHVsZShwbHVnaW5OYW1lLCBbXSk7XG5cbiAgX21vZHVsZS5ydW4oKCkgPT4ge1xuICB9KTtcblxuICBfbW9kdWxlLnNlcnZpY2UoJ0hhd3Rpb0JyZWFkY3J1bWJzJywgKCkgPT4ge1xuICAgIHZhciBfY29uZmlnID0gW107XG4gICAgdmFyIHNlbGYgPSB7XG4gICAgICBhcHBseTogKGNvbmZpZykgPT4ge1xuICAgICAgICBfY29uZmlnLmxlbmd0aCA9IDA7XG4gICAgICAgIF8uZm9yRWFjaChjb25maWcsIChjcnVtYikgPT4ge1xuICAgICAgICAgIF9jb25maWcucHVzaChjcnVtYik7XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIGdldDogKCkgPT4ge1xuICAgICAgICByZXR1cm4gX2NvbmZpZztcbiAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBzZWxmO1xuICB9KTtcblxuICBfbW9kdWxlLnNlcnZpY2UoJ0hhd3Rpb1N1YlRhYnMnLCAoKSA9PiB7XG4gICAgdmFyIF9jb25maWcgPSBbXTtcbiAgICB2YXIgc2VsZiA9IHtcbiAgICAgIGFwcGx5OiAoY29uZmlnKSA9PiB7XG4gICAgICAgIF9jb25maWcubGVuZ3RoID0gMDtcbiAgICAgICAgXy5mb3JFYWNoKGNvbmZpZywgKGNydW1iKSA9PiB7XG4gICAgICAgICAgX2NvbmZpZy5wdXNoKGNydW1iKTtcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgZ2V0OiAoKSA9PiB7XG4gICAgICAgIHJldHVybiBfY29uZmlnO1xuICAgICAgfSBcbiAgICB9IFxuICAgIHJldHVybiBzZWxmO1xuICB9KTtcblxuICBfbW9kdWxlLmRpcmVjdGl2ZSgndmlld3BvcnRIZWlnaHQnLCBbJyR3aW5kb3cnLCAnJGRvY3VtZW50JywgKCR3aW5kb3csICRkb2N1bWVudCkgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICByZXN0cmljdDogJ0EnLFxuICAgICAgbGluazogKHNjb3BlLCBlbGVtZW50LCBhdHRyKSA9PiB7XG4gICAgICAgIC8vIGxvZy5kZWJ1ZyhcIldpbmRvdzogXCIsICR3aW5kb3cpO1xuICAgICAgICAvLyBsb2cuZGVidWcoXCJlbGVtZW50OiBcIiwgZWxlbWVudCk7XG4gICAgICAgIHZhciB3aW4gPSAkKCR3aW5kb3cpO1xuICAgICAgICB2YXIgcmVzaXplRnVuYyA9ICgpID0+IHtcbiAgICAgICAgICB2YXIgdmlld3BvcnRIZWlnaHQgPSB3aW4uaW5uZXJIZWlnaHQoKTtcbiAgICAgICAgICAvLyBsb2cuZGVidWcoXCJWaWV3cG9ydCBoZWlnaHQ6IFwiLCB2aWV3cG9ydEhlaWdodCk7XG4gICAgICAgICAgdmFyIGVsVG9wID0gZWxlbWVudC5vZmZzZXQoKS50b3A7XG4gICAgICAgICAgLy8gbG9nLmRlYnVnKFwiRWxlbWVudCB0b3A6IFwiLCBlbFRvcCk7XG4gICAgICAgICAgdmFyIGhlaWdodCA9IHZpZXdwb3J0SGVpZ2h0IC0gZWxUb3A7XG4gICAgICAgICAgZWxlbWVudC5jc3MoJ2hlaWdodCcsIGhlaWdodCk7XG4gICAgICAgIH07XG4gICAgICAgIHdpbi5vbigncmVzaXplJywgcmVzaXplRnVuYyk7XG4gICAgICAgIGVsZW1lbnQub24oJyRkZXN0cm95JywgKCkgPT4ge1xuICAgICAgICAgIHdpbi5vZmYoJ3Jlc2l6ZScsIHJlc2l6ZUZ1bmMpO1xuICAgICAgICB9KTtcbiAgICAgICAgc2V0VGltZW91dChyZXNpemVGdW5jLCA1MCk7XG4gICAgICB9XG4gICAgfVxuICB9XSk7XG5cbiAgX21vZHVsZS5kaXJlY3RpdmUoJ2hhd3Rpb01haW5PdXRsZXQnLCBbJ0hhd3Rpb1N1YlRhYnMnLCAoSGF3dGlvU3ViVGFicykgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICByZXN0cmljdDogJ0EnLFxuICAgICAgbGluazogKHNjb3BlLCBlbGVtZW50LCBhdHRycykgPT4ge1xuICAgICAgICBzY29wZS5IYXd0aW9TdWJUYWJzID0gSGF3dGlvU3ViVGFicztcbiAgICAgICAgc2NvcGUuJHdhdGNoQ29sbGVjdGlvbignSGF3dGlvU3ViVGFicy5nZXQoKScsIChzdWJUYWJDb25maWcpID0+IHtcbiAgICAgICAgICAvLyBsb2cuZGVidWcoXCJzdWJUYWJDb25maWc6IFwiLCBzdWJUYWJDb25maWcpO1xuICAgICAgICAgIGlmIChzdWJUYWJDb25maWcgJiYgc3ViVGFiQ29uZmlnLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGVsZW1lbnQucmVtb3ZlQ2xhc3MoJ2hpZGRlbi1uYXYnKTtcbiAgICAgICAgICAgIC8vZWxlbWVudC5jc3MoeyAnbWFyZ2luLWxlZnQnOiAnJyB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcygnaGlkZGVuLW5hdicpO1xuICAgICAgICAgICAgLy9lbGVtZW50LmNzcyh7ICdtYXJnaW4tbGVmdCc6ICdhdXRvJyB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgfV0pO1xuXG4gIF9tb2R1bGUuZGlyZWN0aXZlKCdoYXd0aW9UYWJzT3V0bGV0JywgWydIYXd0aW9TdWJUYWJzJywgKEhhd3Rpb1N1YlRhYnMpID0+IHtcbiAgICB2YXIgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgcmVzdHJpY3Q6ICdBRScsXG4gICAgICByZXBsYWNlOiB0cnVlLFxuICAgICAgdGVtcGxhdGU6IGBcbiAgICAgICAgPGRpdiBjbGFzcz1cIm5hdi1wZi12ZXJ0aWNhbCBuYXYtcGYtdmVydGljYWwtd2l0aC1zZWNvbmRhcnktbmF2XCIgbmctY29udHJvbGxlcj1cIkRldmVsb3Blci5OYXZCYXJDb250cm9sbGVyXCIgbmctY2xhc3M9XCJnZXRDbGFzcygpXCI+XG4gICAgICAgICAgPHVsIGNsYXNzPVwibGlzdC1ncm91cFwiPlxuICAgICAgICAgICAgPGxpIG5nLXJlcGVhdD1cInN1YlRhYiBpbiBzdWJUYWJDb25maWdcIiBuZy1zaG93PVwiaXNWYWxpZChzdWJUYWIpXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSB7e3N1YlRhYi5hY3RpdmUgPyAnYWN0aXZlJyA6ICcnfX1cIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwie3tzdWJUYWIudGl0bGV9fVwiPlxuICAgICAgICAgICAgICAgIDxhIG5nLWhpZGU9XCJzdWJUYWIudGVtcGxhdGVcIiBocmVmPVwie3tzdWJUYWIuaHJlZn19XCI+XG4gICAgICAgICAgICAgICAgICA8c3BhbiBuZy1zaG93PVwic3ViVGFiLmNsYXNzXCIgbmctY2xhc3M9XCJzdWJUYWIuY2xhc3NcIj48L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8aW1nIG5nLXNob3c9XCJzdWJUYWIuaWNvblwiIG5nLXNyYz1cInt7c3ViVGFiLmljb259fVwiIHN0eWxlPVwibWF4LXdpZHRoOiAxNnB4OyBtYXJnaW4tcmlnaHQ6IDEzcHg7XCI+XG4gICAgICAgICAgICAgICAgICB7e3N1YlRhYi5sYWJlbH19XG4gICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgIDxkaXYgbmctc2hvdz1cInN1YlRhYi50ZW1wbGF0ZVwiIGNvbXBpbGU9XCJzdWJUYWIudGVtcGxhdGVcIj48L2Rpdj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgPC91bD5cbiAgICAgICAgPC9kaXY+XG4gICAgICBgLFxuICAgICAgbGluazogKHNjb3BlLCBlbGVtZW50LCBhdHRycykgPT4ge1xuICAgICAgICBpZiAoIWluaXRpYWxpemVkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICg8YW55PiQpKCkuc2V0dXBWZXJ0aWNhbE5hdmlnYXRpb24oZmFsc2UpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgLy8gaWdub3JlIGlmIHdlIGhhdmVuJ3QgbG9hZGVkIHBhdHRlcm5mbHlcbiAgICAgICAgICB9XG4gICAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHNjb3BlLkhhd3Rpb1N1YlRhYnMgPSBIYXd0aW9TdWJUYWJzO1xuICAgICAgICB2YXIgY29sbGFwc2VkID0gZmFsc2U7XG4gICAgICAgIHNjb3BlLmdldENsYXNzID0gKCkgPT4ge1xuICAgICAgICAgIC8vbG9nLmRlYnVnKFwiTXkgY2xhc3M6IFwiLCBlbGVtZW50LmF0dHIoJ2NsYXNzJykpO1xuICAgICAgICAgIGlmICghc2NvcGUuc3ViVGFiQ29uZmlnIHx8ICFzY29wZS5zdWJUYWJDb25maWcubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2hpZGRlbic7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChjb2xsYXBzZWQpIHtcbiAgICAgICAgICAgIHJldHVybiAnY29sbGFwc2VkJztcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG4gICAgICAgIHNjb3BlLiRvbignaGF3dGlvQ29sbGFwc2VOYXYnLCAoKSA9PiB7XG4gICAgICAgICAgY29sbGFwc2VkID0gIWNvbGxhcHNlZDtcbiAgICAgICAgfSk7XG4gICAgICAgIHNjb3BlLiR3YXRjaCgnSGF3dGlvU3ViVGFicy5nZXQoKScsIChzdWJUYWJDb25maWcpID0+IHtcbiAgICAgICAgICBzY29wZS5zdWJUYWJDb25maWcgPSBzdWJUYWJDb25maWc7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG4gIH1dKTtcblxuICBfbW9kdWxlLmRpcmVjdGl2ZSgnaGF3dGlvQnJlYWRjcnVtYnNPdXRsZXQnLCBbJ0hhd3Rpb0JyZWFkY3J1bWJzJywgKEhhd3Rpb0JyZWFkY3J1bWJzKSA9PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3RyaWN0OiAnRScsXG4gICAgICBzY29wZToge30sXG4gICAgICB0ZW1wbGF0ZTogYFxuICAgICAgICA8ZGl2IG5nLXNob3c9XCJicmVhZGNydW1iQ29uZmlnXCIgbmctY29udHJvbGxlcj1cIkRldmVsb3Blci5OYXZCYXJDb250cm9sbGVyXCI+XG4gICAgICAgICAgPG9sIGNsYXNzPVwiYnJlYWRjcnVtYlwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcyA9ICdicic+PGJyPjwvZGl2PlxuICAgICAgICAgICAgPGxpIG5nLXJlcGVhdD1cImJyZWFkY3J1bWIgaW4gYnJlYWRjcnVtYkNvbmZpZ1wiIG5nLXNob3c9XCJpc1ZhbGlkKGJyZWFkY3J1bWIpXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cInt7YnJlYWRjcnVtYi5hY3RpdmUgPyAnYWN0aXZlJyA6ICcnfX1cIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwie3ticmVhZGNydW1iLnRpdGxlfX1cIj5cbiAgICAgICAgICAgICAgPGEgbmctc2hvdz1cImJyZWFkY3J1bWIuaHJlZiAmJiAhYnJlYWRjcnVtYi5hY3RpdmVcIiBocmVmPVwie3ticmVhZGNydW1iLmhyZWZ9fVwiPnt7YnJlYWRjcnVtYi5sYWJlbH19PC9hPlxuICAgICAgICAgICAgICA8c3BhbiBuZy1oaWRlPVwiYnJlYWRjcnVtYi5ocmVmICYmICFicmVhZGNydW1iLmFjdGl2ZVwiPnt7YnJlYWRjcnVtYi5sYWJlbH19PC9zcGFuPlxuICAgICAgICAgIDwvb2w+XG4gICAgICAgIDwvZGl2PlxuICAgICAgYCxcbiAgICAgIGxpbms6IChzY29wZSwgZWxlbWVudCwgYXR0cnMpID0+IHtcbiAgICAgICAgc2NvcGUuYnJlYWRjcnVtYnMgPSBIYXd0aW9CcmVhZGNydW1icztcbiAgICAgICAgc2NvcGUuJHdhdGNoQ29sbGVjdGlvbignYnJlYWRjcnVtYnMuZ2V0KCknLCAoYnJlYWRjcnVtYkNvbmZpZykgPT4ge1xuICAgICAgICAgIHNjb3BlLmJyZWFkY3J1bWJDb25maWcgPSBicmVhZGNydW1iQ29uZmlnO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XSk7XG5cbiAgLy9oYXd0aW9QbHVnaW5Mb2FkZXIuYWRkTW9kdWxlKCdwYXR0ZXJuZmx5Jyk7XG4gIGhhd3Rpb1BsdWdpbkxvYWRlci5hZGRNb2R1bGUocGx1Z2luTmFtZSk7XG5cbn1cblxuIl0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 + +angular.module("hawtio-kubernetes-templates", []).run(["$templateCache", function($templateCache) {$templateCache.put("plugins/developer/html/addDataFile.html","
\r\n
\r\n

江苏省审计厅数据汇总平台

\r\n
\r\n
\r\n
\r\n

本地文件列表

\r\n
    \r\n
  • 文件名
  • \r\n
  • \r\n
  • \r\n
  • \r\n
  • \r\n
  • \r\n
  • \r\n
\r\n
    \r\n
  • 文件属性
  • \r\n
  • \r\n
  • \r\n
\r\n
\r\n
\r\n \r\n
\r\n

服务器文件列表

\r\n
\r\n
\r\n employee: {{node.name}} age {{node.age}}\r\n
\r\n \r\n
\r\n
\r\n
    \r\n
  • 文件名
  • \r\n
  • \r\n
  • \r\n
  • \r\n
  • \r\n
  • \r\n
  • \r\n
\r\n
    \r\n
  • 文件属性
  • \r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n\r\n\r\n\r\n
"); +$templateCache.put("plugins/developer/html/code.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no tools currently available.

\n
\n
\n
\n

There are no tools currently available.

\n
\n \n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/environment.html","environment!!!!"); +$templateCache.put("plugins/developer/html/environmentPanel.html","
\n
\n
\n \n\n
\n
\n
\n
\n \n
\n \n \n Build #{{rc.$buildId}}\n \n  \n  \n  \n \n \n Commit {{rc.$gitCommit | limitTo:7}}\n \n \n \n Commit {{rc.$gitCommit | limitTo:7}}\n \n
\n
\n
\n\n\n
\n\n
\n
\n"); +$templateCache.put("plugins/developer/html/environments.html","
\n\n
\n
\n\n \n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n\n\n \n\n
\n
\n
\n
\n

Environments Overview

\n
\n
\n
\n
\n
\n

No Environment Available

\n

Environment is a logical place where deployments happen which maps to a kubernetes / openshift namespace. You will see environments here after you add a build.

\n New Build\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n

Active Pipelines

\n View All Pipelines >>\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n

Commits

\n View All Commits >>\n
\n
\n
\n
\n
\n
\n
\n\n
\n"); +$templateCache.put("plugins/developer/html/home.html","
\n
\n

Perspectives

\n\n

\n Please choose the perspective you would like to use:\n

\n
\n
\n\n
\n

\n \n \n  Develop »\n \n

\n\n

\n Work on projects and source code\n

\n
\n
\n

\n \n \n  Operate »\n \n

\n\n

\n Manage and run Pods and Services\n

\n
\n
\n
"); +$templateCache.put("plugins/developer/html/jenkinsApproveModal.html","
\n

{{operation}}?

\n
\n
\n Are you sure you wish to {{operation}}?\n
\n
\n \n \n
\n"); +$templateCache.put("plugins/developer/html/jenkinsJob.html","
\n \n \n \n \n\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n\n \n Trigger\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no builds in this job.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/jenkinsJobs.html","
\n \n \n \n \n \n \n\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n Trigger\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no jobs in this jenkins.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/jenkinsLog.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n Log in Jenkins\n \n  \n \n Build in Jenkins\n \n
\n
\n\n
\n
\n
\n
\n

\n
\n
\n\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/jenkinsMetrics.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no completed builds in this job.

\n
\n
\n \n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/logPanel.html","
\n
\n

\n
\n
\n\n\n"); +$templateCache.put("plugins/developer/html/pipeline.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no pipeline stages in this build.

\n
\n
\n\n

Pipeline for {{jobId}}

\n\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/pipelineView.html","
\n
\n
\n

\n \n Build {{build.displayName}}\n \n \n started {{build.$timestamp.relative()}}\n \n

\n
\n\n
\n
\n\n
\n
\n \n\n \n\n
\n
\n
\n \n
\n
\n
\n

Logs

\n View Full Log\n
\n
\n
\n\n
\n
\n\n\n
\n
\n"); +$templateCache.put("plugins/developer/html/pipelines.html","
\n
\n
\n\n
\n
\n \n \n \n
\n
\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no pipelines for this job.

\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/projectDetail.html","
\n
\n
\n  \n \n \n  \n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/projectSelector.html","\n"); +$templateCache.put("plugins/developer/html/projects.html","
\n \n \n \n \n \n \n\n
\n
\n
\n\n
\n
\n \n \n \n  \n \n\n \n\n  \n\n \n Create App\n \n\n\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no projects in this workspace.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/tools.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no tools currently available.

\n
\n
\n
\n

There are no tools currently available.

\n
\n \n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/workspace.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n  \n \n Configuration\n \n  \n \n Pod\n \n  \n \n View Log\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/developer/html/workspaces.html","
\n
\n
\n\n
\n
\n
\n
\n

江苏省审计厅数据汇总平台

\n
\n
\n
\n

本地文件列表

\n
    \n
  • 文件名
  • \n
    \n {{node.name}}\n
    \n
\n
    \n
  • 已选数据文件
  • \n
  • {{node.name}}
  • \n\n
\n
    \n
  • 采集时间
  • \n
  • {{node.date}}  \n {{model.uploadprocess[node.id]}}%
  • \n
\n
\n \n
\n
\n
\n

服务器文件列表

\n
\n
\n {{node.name}}\n
\n
\n
\n
    \n
  • 文件名
  • \n
  • {{item.name}}
  • \n
\n
    \n
  • 采集时间
  • \n
  • {{item.time}}
  • \n
\n
\n
\n \n
\n
\n
\n\n
\n\n
\n"); +$templateCache.put("plugins/kubernetes/html/appDeployedTemplate.html","
\n {{row.entity.$creationDate ? (row.entity.$creationDate | relativeTime) : \'\'}}\n
\n"); +$templateCache.put("plugins/kubernetes/html/appDetailTemplate.html","
\n
\n
\n \n \n \n \n \n \n \n {{view.appName}}\n \n \n
\n
\n \n \n {{view.service.$host}}\n \n {{view.service.$host}}\n \n
\n
\n \n
\n
\n\n
\n
\n
\n
\n deployed:\n {{view.createdDate | relativeTime}}\n
\n
\n not deployed\n
\n
\n
\n
\n pod template:\n {{view.controllerId}}\n
\n
\n no pod template\n
\n
\n
\n \n pods:\n \n {{view.podCount}}\n \n \n {{view.podCount}}\n \n \n
\n
\n\n
\n
\n
\n
\n \n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n IP:\n {{pod.status.podIP}}\n
\n
\n
\n ports: {{pod.$containerPorts.join(\", \")}}\n
\n
\n minion:\n \n {{pod.$host}}\n \n
\n
\n \n
\n \n
\n\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n IP:\n {{pod.status.podIP}}\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/appIconTemplate.html","\n"); +$templateCache.put("plugins/kubernetes/html/appPodCountsAndLinkTemplate.html","\n"); +$templateCache.put("plugins/kubernetes/html/appReplicationControllerTemplate.html","\n"); +$templateCache.put("plugins/kubernetes/html/appServicesTemplate.html","\n"); +$templateCache.put("plugins/kubernetes/html/apps.html","
\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n
\n \n \n \n \n
\n \n \n \n \n
\n
\n  \n \n  \n\n  \n \n  \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no apps currently available.

\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
    \n
  • \n
    \n
    \n {{folder.path.capitalize(true)}}Uncategorized\n
    \n
    \n \n
    \n
    \n
  • \n
\n
\n
\n
\n
\n \n  \n \n  \n \n
\n
\n \n\n
\n\n
    \n
  • \n \n {{app.name}}\n  \n \n
  • \n
\n
\n
\n
\n
\n \n
\n"); +$templateCache.put("plugins/kubernetes/html/breadcrumbs.html","
\n
    \n
  1. \n {{breadcrumb.label}}\n {{breadcrumb.label}}\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/build.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n  \n \n Configuration\n \n  \n \n Pod\n \n  \n \n View Log\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/buildConfig.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n  \n \n Edit\n \n \n  \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/buildConfigEdit.html","
\n
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n\n
\n
\n \n
\n
\n
\n \n \n\n

\n Project name must be a lower case DNS name with letters, numbers and dots or dashes such as `example.com`\n

\n
\n
\n
\n
\n
\n\n\n \n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/buildConfigs.html","
\n \n \n \n \n \n \n
\n
\n \n \n \n \n  \n Add Build\n  \n\n \n Create Project\n \n  \n\n \n Sign In\n \n  \n\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no build configurations available.

\n Add Build Configuration\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/buildLogs.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n \n
\n
\n
\n
\n
\n \n
\n
\n
\n

logs for {{entity.$configId}}

\n\n

\n

\n            \n              {{logsText}}\n            \n          
\n

\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/builds.html","
\n \n \n \n \n \n \n\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no builds currently running.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/deploymentConfig.html","
\n
\n
\n  \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/deploymentConfigs.html","
\n \n \n
\n
\n \n \n \n \n  \n Create\n  \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no deployment configurations available.

\n Create Deployment Configuration\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/events.html","
\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no events currently available.

\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n \n \n \n
\n
\n \n

\n
\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/host.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n  \n \n {{rawMode ? \'Form\' : \'Raw\'}}\n Edit\n  \n\n Save\n  \n\n  \n \n Pods\n \n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n"); +$templateCache.put("plugins/kubernetes/html/hosts.html","
\n \n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no hosts currently running.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/imageRepositories.html","
\n \n
\n
\n \n \n \n \n  \n Create\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no image repositories available.

\n Create Image Repository\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/importProject.html","
\n
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n\n

\n Create a project by entering or copy/pasting the Git URL for a repository, and give the project a name. By default the name will be based on the repository name.\n

\n\n
\n\n
\n
\n
\n
\n
\n \n \n\n

\n Project name must be a lower case DNS name with letters, numbers and dots or dashes such as `example.com`\n

\n

Name of this project

\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/kubernetesJsonDirective.html","
\n
\n
\n
\n\n
\n
\n  \n
\n
\n
\n

 {{displayName || appTitle}}

\n
\n
\n \n
\n
\n
\n
\n
\n\n
\n
\n\n
\n"); +$templateCache.put("plugins/kubernetes/html/layoutKubernetes.html","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/logShell.html","
\n
\n
\n \n
\n
\n
{{containerName}} logs
\n \n \n \n
\n
\n \n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/overview.html","
\n \n \n \n \n \n \n
\n
\n
\n\n
\n
\n
\n\n \n
\n"); +$templateCache.put("plugins/kubernetes/html/pendingPipelines.html","
\n
\n
\n
\n
\n
\n
\n
\n
\n

No Pipeline Available

\n

Pipeline is a kind of build which uses Jenkins Workflow internally which has multiple Stages. You will see the active pipelines here after you add a build to this project

\n
\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/pipelines.html","
\n \n
\n
\n \n \n \n Create Project\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no build pipelines available.

\n Create Build Configuration\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n
\n \n
\n
\n\n
\n \n \n \n {{step.buildConfig.metadata.name}}\n \n \n    \n \n \n \n build\n \n \n\n
\n
\n \n new: {{step.buildConfig.$lastBuild.$creationDate.relative()}}\n \n \n pending: {{step.buildConfig.$lastBuild.$creationDate.relative()}}\n \n \n running {{step.buildConfig.$lastBuild.$creationDate.relative()}}\n \n \n completed {{step.buildConfig.$lastBuild.$creationDate.relative()}}\n \n \n failed {{step.buildConfig.$lastBuild.$creationDate.relative()}}\n \n \n {{step.buildConfig.$lastBuild.status}}: {{step.buildConfig.$lastBuild.$creationDate.relative()}}\n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/pod.html","
\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n\n  {{item.metadata.name}}\n \n\n \n  \n\n \n  \n \n\n {{rawMode ? \'Form\' : \'Raw\'}}\n  \n\n Edit\n  \n\n Save\n  \n\n \n Events\n \n  \n\n
\n  \n \n Connect\n \n
\n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n
\n"); +$templateCache.put("plugins/kubernetes/html/podCreate.html","
\n
\n
\n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/podEdit.html","
\n
\n
\n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/pods.html","
\n \n \n \n\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n  \n \n  \n \n  \n 创建新服务\n  \n \n
\n
\n
\n
\n\n
\n
\n \n
\n
\n
\n
\n

There are no pods currently running.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/replicationController.html","
\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n  {{item.metadata.name}}\n \n\n \n  \n\n \n  \n\n {{rawMode ? \'Form\' : \'Raw\'}}\n  \n\n Edit\n  \n\n Save\n  \n\n \n Events\n \n\n    \n\n \n Scale\n \n\n Pods:\n \n {{item.$podCounters.ready}}\n {{item.$podCounters.valid}}\n {{item.$podCounters.waiting}}\n {{item.$podCounters.error}}\n \n \n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n \n
\n"); +$templateCache.put("plugins/kubernetes/html/replicationControllerCreate.html","
\n
\n
\n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/replicationControllerEdit.html","
\n
\n
\n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/replicationControllers.html","
\n \n \n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n  \n\n \n  \n\n \n  \n\n \n  \n 创建\n  \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

当前没有正在运行的oracle服务.

\n
\n
\n
\n
\n
\n
\n
\n \n
\n"); +$templateCache.put("plugins/kubernetes/html/secret.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n  \n \n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n \n\n
\n \n \n There is already a secret with that name!\n \n
\n
\n\n
\n \n\n
\n \n \n
\n\n
\n \n
\n
\n
\n\n\n
\n
\n
\n \n \n \n
\n
\n
\n
\n
\n
\n\n
\n
\n

Add New Data Field

\n
\n\n
\n \n\n
\n \n\n \n That field name is already in use!\n \n
\n
\n\n
\n\n
\n
\n \n Enter the name of the new data field to add to the secret\n \n
\n
\n
\n
\n \n\n \n
\n
\n
\n\n
\n"); +$templateCache.put("plugins/kubernetes/html/secrets.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n\n \n  \n \n Create\n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no secrets currently available.

\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/service.html","
\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n  {{item.metadata.name}}\n \n\n \n  \n\n \n\n {{rawMode ? \'Form\' : \'Raw\'}}\n  \n\n Edit\n  \n\n Save\n  \n\n \n Connect\n \n
\n
\n\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n
\n"); +$templateCache.put("plugins/kubernetes/html/serviceApps.html","
\n \n \n \n \n
\n"); +$templateCache.put("plugins/kubernetes/html/serviceCreate.html","
\n
\n
\n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/serviceEdit.html","
\n
\n
\n  \n \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/services.html","
\n\n
\n
\n
\n\n
\n
\n
\n\n
\n
\n \n \n \n \n
\n \n \n \n \n
\n
\n  \n \n  \n \n  \n Create\n  \n \n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n

There are no services currently available.

\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n \n \n \n
\n
\n \n

\n
\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/tabs.html","
\n \n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/templateDescription.html","
\n

Description

\n
\n
\n
\n
\n
\n \n
\n"); +$templateCache.put("plugins/kubernetes/html/templates.html","
\n \n\n
\n
\n
\n\n
\n
\n
\n\n\n
\n
\n \n \n \n\n \n  \n \n  \n \n Target namespace: \n\n \n
\n
\n
\n
\n
\n There are no templates currently available. Add templates by dragging and dropping template files into this area.\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n

\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n \n \n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n"); +$templateCache.put("plugins/kubernetes/html/termShell.html","
\n
\n
\n \n \n
\n
\n
\n
\n");}]); hawtioPluginLoader.addModule("hawtio-kubernetes-templates"); \ No newline at end of file diff --git a/dist/img/host.svg b/dist/img/host.svg new file mode 100644 index 0000000..431ea31 --- /dev/null +++ b/dist/img/host.svg @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + Server Cabinet CPU + 2007-09-03T13:59:19 + Represents a server in Network Diagrams + https://openclipart.org/detail/5159/server-cabinet-cpu-by-sagar_ns + + + sagar_ns + + + + + mainframe + server + + + + + + + + + + + diff --git a/dist/img/kubernetes.svg b/dist/img/kubernetes.svg new file mode 100644 index 0000000..52f8499 --- /dev/null +++ b/dist/img/kubernetes.svg @@ -0,0 +1,451 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..165cf9d --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,703 @@ +var gulp = require('gulp'), + wiredep = require('wiredep').stream, + eventStream = require('event-stream'), + gulpLoadPlugins = require('gulp-load-plugins'), + fs = require('fs'), + path = require('path'), + url = require('url'), + uri = require('urijs'), + urljoin = require('url-join'), + s = require('underscore.string'), + stringifyObject = require('stringify-object'), + hawtio = require('hawtio-node-backend'), + argv = require('yargs').argv, + del = require('del'), + xml2js = require('xml2js'), + multipart = require('connect-multiparty'), + resumable = require('./app/resumable-node.js')(__dirname + '/uploads'), + app = hawtio.app, + shellprocess = require('child_process'), + xmloperation = require('./app/xmloperation'), + rootdir = process.env.STORAGE_PATH || '/home/server_data/', + k8s = require('k8s'), + crontab = require('node-crontab'), + myjs=require('./app/my.js'); + +var oracledb = require('oracledb'); + +var plugins = gulpLoadPlugins({}); +var pkg = require('./package.json'); +var time =0; +var schedule = []; +var kubectl = k8s.kubectl({ + endpoint: process.env.KUBERNETES_MASTER + , binary: '/usr/bin/kubectl' +}); + +var config = { + main: '.', + ts: ['plugins/**/*.ts'], + less: ['plugins/**/*.less'], + templates: ['plugins/**/*.html'], + templateModule: pkg.name + '-templates', + dist: argv.out || './dist/', + js: pkg.name + '.js', + css: pkg.name + '.css', + tsProject: plugins.typescript.createProject({ + target: 'ES5', + module: 'commonjs', + declarationFiles: true, + noExternalResolve: false + }) +}; + +gulp.task('bower', function() { + return gulp.src('index.html') + .pipe(wiredep({})) + .pipe(gulp.dest('.')); +}); + +/** Adjust the reference path of any typescript-built plugin this project depends on */ +gulp.task('path-adjust', function() { + return gulp.src('libs/**/includes.d.ts') + .pipe(plugins.replace(/"\.\.\/libs/gm, '"../../../libs')) + .pipe(gulp.dest('libs')); +}); + +gulp.task('clean-defs', function() { + return del('defs.d.ts'); +}); + +gulp.task('tsc', ['clean-defs'], function() { + var cwd = process.cwd(); + var tsResult = gulp.src(config.ts) + .pipe(plugins.sourcemaps.init()) + .pipe(plugins.typescript(config.tsProject)) + .on('error', plugins.notify.onError({ + message: '<%= error.message =>', + title: 'Typescript compilation error' + })); + + return eventStream.merge( + tsResult.js + .pipe(plugins.concat('compiled.js')) + .pipe(plugins.sourcemaps.write()) + .pipe(gulp.dest('.')), + tsResult.dts + .pipe(gulp.dest('d.ts'))) + .pipe(plugins.filter('**/*.d.ts')) + .pipe(plugins.concatFilenames('defs.d.ts', { + root: cwd, + prepend: '/// ' + })) + .pipe(gulp.dest('.')); +}); + +gulp.task('less', function () { + return gulp.src(config.less) + .pipe(plugins.less({ + paths: [ path.join(__dirname, 'less', 'includes') ] + })) + .on('error', plugins.notify.onError({ + message: '<%= error.message %>', + title: 'less file compilation error' + })) + .pipe(plugins.concat(config.css)) + .pipe(gulp.dest(config.dist)); +}); + +gulp.task('template', ['tsc'], function() { + return gulp.src(config.templates) + .pipe(plugins.angularTemplatecache({ + filename: 'templates.js', + root: 'plugins/', + standalone: true, + module: config.templateModule, + templateFooter: '}]); hawtioPluginLoader.addModule("' + config.templateModule + '");' + })) + .pipe(gulp.dest('.')); +}); + +gulp.task('concat', ['template'], function() { + return gulp.src(['compiled.js', 'templates.js']) + .pipe(plugins.concat(config.js)) + .pipe(plugins.ngAnnotate()) + .pipe(gulp.dest(config.dist)); +}); + +gulp.task('clean', ['concat'], function() { + return del(['templates.js', 'compiled.js', './site/']); +}); + +gulp.task('watch-less', function() { + plugins.watch(config.less, function() { + gulp.start('less'); + }); +}); + +gulp.task('watch', ['build', 'watch-less'], function() { + plugins.watch(['libs/**/*.js', 'libs/**/*.css', 'index.html', config.dist + '/*'], function() { + gulp.start('reload'); + }); + plugins.watch(['libs/**/*.d.ts', config.ts, config.templates], function() { + gulp.start(['tsc', 'template', 'concat', 'clean']); + }); +}); + +gulp.task('connect', ['watch'], function() { + // lets disable unauthorised TLS issues with kube REST API + process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + + var kubeBase = process.env.KUBERNETES_MASTER || 'https://localhost:8443'; + console.log("==== using KUBERNETES URL: " + kubeBase); + var kube = uri(urljoin(kubeBase, 'api')); + var oapi = uri(urljoin(kubeBase, 'oapi')); + console.log("Connecting to Kubernetes on: " + kube); + + var staticAssets = [{ + path: '/', + dir: '.' + }]; + + var dirs = fs.readdirSync('./libs'); + dirs.forEach(function(dir) { + var dir = './libs/' + dir; + console.log("dir: ", dir); + if (fs.statSync(dir).isDirectory()) { + console.log("Adding directory to search path: ", dir); + staticAssets.push({ + path: '/', + dir: dir + }); + } + }); + + var localProxies = []; + if (process.env.LOCAL_APP_LIBRARY === "true") { + localProxies.push({ + proto: "http", + port: "8588", + hostname: "localhost", + path: '/api/v1/proxy/namespaces/default/services/app-library', + targetPath: "/" + }); + console.log("because of $LOCAL_APP_LIBRARY being true we are using a local proxy for /api/v1/proxy/namespaces/default/services/app-library" ); + } + if (process.env.LOCAL_FABRIC8_FORGE === "true") { + localProxies.push({ + proto: "http", + port: "8080", + hostname: "localhost", + path: '/api/v1/proxy/namespaces/default/services/fabric8-forge', + targetPath: "/" + }); + console.log("because of LOCAL_FABRIC8_FORGE being true we are using a local proxy for /api/v1/proxy/namespaces/default/services/fabric8-forge" ); + } + if (process.env.LOCAL_GOGS_HOST) { + var gogsPort = process.env.LOCAL_GOGS_PORT || "3000"; + //var gogsHostName = process.env.LOCAL_GOGS_HOST + ":" + gogsPort; + var gogsHostName = process.env.LOCAL_GOGS_HOST; + console.log("Using gogs host: " + gogsHostName); + localProxies.push({ + proto: "http", + port: gogsPort, + hostname: gogsHostName, + path: '/kubernetes/api/v1/proxy/services/gogs-http-service', + targetPath: "/" + }); + console.log("because of LOCAL_GOGS_HOST being set we are using a local proxy for /kubernetes/api/v1/proxy/services/gogs-http-service to point to http://" + + process.env.LOCAL_GOGS_HOST + ":" + gogsPort); + } + var defaultProxies = [{ + proto: kube.protocol(), + port: kube.port(), + hostname: kube.hostname(), + path: '/kubernetes/api', + targetPath: kube.path() + }, { + proto: oapi.protocol(), + port: oapi.port(), + hostname: oapi.hostname(), + path: '/kubernetes/oapi', + targetPath: oapi.path() + }, { + proto: kube.protocol(), + hostname: kube.hostname(), + port: kube.port(), + path: '/jolokia', + targetPath: '/hawtio/jolokia' + }, { + proto: kube.protocol(), + hostname: kube.hostname(), + port: kube.port(), + path: '/git', + targetPath: '/hawtio/git' + }]; + + var staticProxies = localProxies.concat(defaultProxies); + + hawtio.setConfig({ + port: process.env.DEV_PORT || 9000, + staticProxies: staticProxies, + staticAssets: staticAssets, + fallback: 'index.html', + liveReload: { + enabled: true + } + }); + var debugLoggingOfProxy = process.env.DEBUG_PROXY === "true"; + var useAuthentication = process.env.DISABLE_OAUTH !== "true"; + + var googleClientId = process.env.GOOGLE_OAUTH_CLIENT_ID; + var googleClientSecret = process.env.GOOGLE_OAUTH_CLIENT_SECRET; + + hawtio.use('/osconsole/config.js', function(req, res, next) { + var config = { + api: { + openshift: { + proto: oapi.protocol(), + hostPort: oapi.host(), + prefix: oapi.path() + }, + k8s: { + proto: kube.protocol(), + hostPort: kube.host(), + prefix: kube.path() + } + } + }; + if (googleClientId && googleClientSecret) { + config.master_uri = kubeBase; + config.google = { + clientId: googleClientId, + clientSecret: googleClientSecret, + authenticationURI: "https://accounts.google.com/o/oauth2/auth", + authorizationURI: "https://accounts.google.com/o/oauth2/auth", + scope: "profile", + redirectURI: "http://localhost:9000" + }; + + } else if (useAuthentication) { + config.master_uri = kubeBase; + config.openshift = { + oauth_authorize_uri: urljoin(kubeBase, '/oauth/authorize'), + oauth_client_id: 'fabric8' + }; + } + var answer = "window.OPENSHIFT_CONFIG = " + stringifyObject(config); + res.set('Content-Type', 'application/javascript'); + res.send(answer); + }); + + app.use(multipart()); + + hawtio.use('/', function(req, res, next) { + + // console.log(req.connection.remoteAddress); + var path = req.originalUrl; + // avoid returning these files, they should get pulled from js + if (s.startsWith(path, '/plugins/') && s.endsWith(path, 'html')) { + console.log("returning 404 for: ", path); + res.statusCode = 404; + res.end(); + } else { + if (debugLoggingOfProxy) { + console.log("allowing: ", path); + } + next(); + } + }); + hawtio.use('/xmlformserver',function(req,res,next){ + if(req.method=='POST') { + var data = []; + var parser = new xml2js.Parser(); + fs.readFile(rootdir + 'data.xml', function(err, xml) { + parser.parseString(xml, function (err, result) { + myjs.Recursion(result.node); + data.push(result.node); + res.send(data); + }); + }); + } + }); + + hawtio.use("/oracleAppPath",function(req,res){ + var dataPath = "/home/ubuntu/data/"; + var tmpPath = "/home/ubuntu/tmp/app"; + var appSource="/home/app"; + if(req.method="POST"){ + var timestamp=new Date().getTime(); + if((timestamp - time) >= 60*1000){ + time = timestamp; + var dirName= myjs.randomString(10); + dataPath = dataPath + dirName+"/"; + fs.mkdirSync(dataPath); + //path.exists(tmpPath,function(exists){if(exists) console.log("exists");}); + fs.renameSync(tmpPath, dataPath+"app"); + console.log("move 'home/ubuntu/tmp/app' to " + dataPath); + res.send(200,{path:dataPath+"app/"}); + res.end(); + shellprocess.exec("cp -rp " + appSource + " " + tmpPath); + }else{ + res.send(403,{}); + res.end(); + } + } + + //} + }); + + hawtio.use('/uploadfiles',function(req,res){ + if(req.method==="POST"){ + var relativePath = req.body.resumableRelativePath; + var fileName = req.body.resumableFilename; + var rootpath = req.body.resumableRootPath; + console.log("--------------------------req.body-----------------"); + if(req.body.resumableTotalSize == "0"){ + fs.writeFile("uploads/"+fileName,""); + + // 去掉系统路径(地区及系统编号):eg: 321100_1/ + relativePath = relativePath.replace(/^\w*\/*[0-9_]+\//, ""); + console.log("*************-----clean------*****************"); + var serverRelativePath = rootdir + rootpath + relativePath; + + console.log(serverRelativePath); + fileName = "uploads/"+fileName; + console.log(fileName); + + changefilename(fileName, serverRelativePath); + } + + resumable.post(req, function(status, filename, original_filename, identifier){ + if (status === 'done') { + var stream = fs.createWriteStream('./uploads/' + filename); + + console.log("//ºÏ²¢Îļþ"); + //ºÏ²¢Îļþ + resumable.write(identifier, stream); + stream.on('data', function(data){}); + stream.on('end', function(){}); + + //ɾ³ý·Ö¿é + //µÈ´ýÁ÷½áÊø + stream.on('finish', function() { + console.log("*************-----clean------*****************"); + // 去掉系统路径(地区及系统编号):eg: 321100_1/ + relativePath = relativePath.replace(/^\w*\/*[0-9_]+\//, ""); + relativePath = rootdir+ rootpath + relativePath; + console.log(relativePath); + fileName = "uploads/"+fileName; + console.log(fileName); + changefilename(fileName, relativePath); + resumable.clean(identifier); + }); + } + console.log(status + "---------------------"); + res.send(200, { + // NOTE: Uncomment this funciton to enable cross-domain request. + //'Access-Control-Allow-Origin': '*' + }); + }); + } + if(req.method==="GET"){ + resumable.get(req, function(status, filename, original_filename, identifier){ + console.log('GET',status); + res.send((status == 'found' ? 200 : 404), status); + }); + } + //next(); + }); + + hawtio.use('/download/:identifier', function(req, res){ + resumable.write(req.params.identifier, res); + }); + + app.get('/getclientip', function(req, res){ + + var ip = req.connection.remoteAddress; + + ip = ip.replace(/\./gim, ""); + ip = ip.replace(/\:/gim, ""); + res.send(ip); + }); + + app.get('/getversion', function(req, res){ + + var version = req.query; + var objid = version.id; + + var realversion = xmloperation.getVersionPath(objid); + res.send(200, {id:realversion}); + + }); + + app.get('/sendDateMessage', function(req, res){ + + var jsonobj = req.query; + console.log("---------------------------------------------------"); + console.log(jsonobj); + var objid = jsonobj.id; + var objname = jsonobj.name; + var objcity = jsonobj.city; + var objcounty = jsonobj.county; + var objsystem = jsonobj.system; + var objtype = jsonobj.type; + var objbatch = jsonobj.batch; + var province = jsonobj.province; + var code = jsonobj.code; + var character_set = jsonobj.character_set; + var sys_name_code = jsonobj.sys_name_code; + var contact = jsonobj.contact; + var phone = jsonobj.phone; + var collecttime = jsonobj.date; + + var realversion = xmloperation.getVersionPath(objid); + var realpath = objtype+"/"+objbatch+"/"+objid+"/"+realversion+"/" + realpath = rootdir + realpath; + + //saveByIdToXml("001001", "B", "321200_0", "泰州市_绩效管理系统2","江苏" , "泰州2", "市本级", "绩效管理系统", "321200_0", "0000", "lim", "13323225656",5); + xmloperation.saveByIdToXml(collecttime, objtype, objbatch, objid, objname, province, objcity, objcounty, objsystem, code, sys_name_code, contact, phone, realversion, realpath) + + xmloperation.mkdataForPage(collecttime, objtype, realpath, objbatch, objid, objname, realversion); + + res.send(200); + }); + + // 路径必须存在 + function changefilename(oldfilepath, newfilepath){ + fs.stat(oldfilepath,function(err,stats){ + if(err){ + changefilename(oldfilepath, newfilepath); + } + else{ + //console.log("-------------------------------changefilename----"); + if(stats.isFile()){ + // 修改文件名 + fs.rename(oldfilepath,newfilepath, function(err){ + if(err){ + var dirs = newfilepath.split("/"); + + var dirLength = dirs.length; + var dirpath = ""; + //var isSuccess = "false"; + for(var i=0; i < dirLength-1; i++){ + dirpath = dirpath + dirs[i] + "/"; + fs.mkdir(dirpath, 0777, function(err){ + if(err){ + //console.log("creat dir fail: "+dirpath); + } + }); + } + + changefilename(oldfilepath, newfilepath) + } + }); + }else if(stats.isDirectory()){ + var dirs = newfilepath.split("/"); + + var dirLength = dirs.length; + var dirpath = ""; + + for(var i=0; i < dirLength; i++){ + dirpath = dirpath + dirs[i] + "/"; + fs.mkdir(dirpath, 0777, function(err){ + if(err){ + //console.log("creat dir fail: "+dirpath); + } + }); + } + console.log(" fail: this is Directory"); + }else{ + console.log("unknow type of file"); + } + } + }); + } + + app.get('/setchmod2dir', function(req, res){ + console.log("----------- setchmod2dir -------------------") + console.log(req.query); + var path = rootdir + req.query.path; + var tempfilesNum = req.query.filenum; + var realfilesnum = geFileList(path); + if(tempfilesNum <= realfilesnum){ + shellprocess.exec("chmod -R 777 " + path); + console.log("------------------------------------------ "+path); + console.log(realfilesnum); + res.send(200,"chmod"); + } + else{ + console.log(realfilesnum); + res.send(200,"fail"); + } + + }); + + hawtio.use('/resumable.js',function(req,res){ + res.setHeader("content-type", "text/javascript"); + fs.createReadStream("./app/resumable.js").pipe(res); + }); + + /*hawtio.use('/style.css',function(req,res){ + res.setHeader("content-type", "text/css"); + fs.createReadStream("./app/style.css").pipe(res); + });*/ + + hawtio.use('/connectToOracle',function(req,res){ + var rcName = req.query.oracleName; + var connectParam = req.query.param; + var taskIndex = -1; + for(var index in schedule){ + var connectionTask = schedule[index]; + if(connectionTask.hasOwnProperty("taskName") && connectionTask.taskName === rcName){ + clearInterval(connectionTask[taskCrontab]); + taskIndex = index; + break; + } + } + if(taskIndex !== -1) + schedule.splice(taskIndex,1); + kubectl.rc.get(rcName,function(err, rc){ + console.log(rc); + if(err){ + console.log(err); + return + } + if(rc && rc.status.replicas === 1 && rc.metadata.labels.hasOwnProperty("style") && rc.metadata.labels.style === "oracle"){ + var selector = rc.spec.selector; + var task = { + taskName: rcName, + taskTime: 0, + taskCrontab: crontab.scheduleJob("*/1 * * * *", function(){ //This will call this function every 2 minutes + console.log(rcName + "it's been 1 minutes!"); + if(task.taskTime === 9){ + kubectl.command("label rc " +rcName + " status=2 --overwrite" ,function(err, data){ + if(err) + console.log(err); + crontab.cancelJob(task.taskCrontab); + }); + } + /*kubectl. + oracledb.getConnection( + { + user : "system", + password : "oracle", + connectString : connectParam+"/orcl" + },function(err, connection){ + if (err) { + console.log("connection failed! message" + err.message); + return; + } + console.log("connect success!"); + kubectl.command("label rc " +rcName + " status=1 --overwrite" ,function(err, data){ + if(err) + console.log(err); + crontab.cancelJob(task.taskCrontab); + }); + if(connection !== null){ + connection.close(function(err){ + if (err){ + console.error(err.message); + } + console.log("connection closed!"); + }); + } + });*/ + task.taskTime++; + }) + } + schedule.push(task); + } + res.send(200,"Ok"); + res.end(); + }); + }); + hawtio.use('/cancelOracleConection',function(req,res){ + var rcName = req.query.oracleName; + console.log(rcName); + var taskIndex = -1; + for(var index in schedule){ + var connectionTask = schedule[index]; + console.log(connectionTask.taskName); + if(connectionTask.hasOwnProperty("taskName") && connectionTask.taskName === rcName){ + console.log(connectionTask.taskCrontab); + clearInterval(connectionTask.taskCrontab); + console.log("connectionTask: " + rcName + "cancel"); + taskIndex = index; + break; + } + } + if(taskIndex !== -1) + schedule.splice(taskIndex,1); + res.send(200,"Ok"); + res.end(); + }); + + hawtio.listen(function(server) { + var host = server.address().address; + var port = server.address().port; + console.log("started from gulp file at ", host, ":", port); + }); +}); + +gulp.task('reload', function() { + gulp.src('.') + .pipe(hawtio.reload()); +}); + +gulp.task('build', ['bower', 'path-adjust', 'tsc', 'less', 'template', 'concat', 'clean']); + +gulp.task('site', ['clean', 'build'], function() { + gulp.src(['index.html', 'osconsole/config.js.tmpl', 'css/**', 'images/**', 'img/**', 'libs/**', 'dist/**'], {base: '.'}).pipe(gulp.dest('site')); + + var dirs = fs.readdirSync('./libs'); + dirs.forEach(function(dir) { + var path = './libs/' + dir + "/img"; + try { + if (fs.statSync(path).isDirectory()) { + console.log("found image dir: " + path); + var pattern = 'libs/' + dir + "/img/**"; + gulp.src([pattern]).pipe(gulp.dest('site/img')); + } + } catch (e) { + // ignore, file does not exist + } + }); +}); + +gulp.task('default', ['connect']); + + +function geFileList(path) +{ + var filesList = []; +  readFile(path,filesList); + return filesList.length; +} + +//遍历读取文件 +function readFile(path,filesList) +{ + files = fs.readdirSync(path);//需要用到同步读取 + files.forEach(walk); + function walk(file) + { + states = fs.statSync(path+'/'+file);   +    if(states.isDirectory()) +    { +    readFile(path+'/'+file,filesList); +    } + else{ +    //创建一个对象保存信息 +     var obj = new Object(); +     obj.size = states.size;//文件大小,以字节为单位 +     obj.name = file;//文件名 +     obj.path = path+'/'+file; //文件绝对路径 +     filesList.push(obj); +    } +  } +} + + + diff --git a/hawtio-kubernetes.iml b/hawtio-kubernetes.iml new file mode 100644 index 0000000..8021953 --- /dev/null +++ b/hawtio-kubernetes.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/img/host.svg b/img/host.svg new file mode 100644 index 0000000..431ea31 --- /dev/null +++ b/img/host.svg @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + Server Cabinet CPU + 2007-09-03T13:59:19 + Represents a server in Network Diagrams + https://openclipart.org/detail/5159/server-cabinet-cpu-by-sagar_ns + + + sagar_ns + + + + + mainframe + server + + + + + + + + + + + diff --git a/img/icons1.gif b/img/icons1.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b6bb344c8d75c5919aee924e60c8c1339963571 GIT binary patch literal 62 zcmZ?wbhEHbK5dDEpV J@pY^W)&M~C6PN%1 literal 0 HcmV?d00001 diff --git a/img/kubernetes.svg b/img/kubernetes.svg new file mode 100644 index 0000000..52f8499 --- /dev/null +++ b/img/kubernetes.svg @@ -0,0 +1,451 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..38c12ab --- /dev/null +++ b/index.html @@ -0,0 +1,168 @@ + + + + 数据管理平台 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+


+ +
+
+ +
+
+ + + + diff --git a/my.js b/my.js new file mode 100644 index 0000000..0c264c1 --- /dev/null +++ b/my.js @@ -0,0 +1,24 @@ +function Recursion(node){ + var count=0; + for (var key in node) { + count++; + var value = node[key]; + delete node[key]; + //如果node为叶子节点 + if (key.toString() == '$') { + for (var attr in value) + node[attr] = value[attr]; + } else { + if (value instanceof Array) { + if (value.length > 0) { + node["children"] = value; + for (var obj in value) + Recursion(value[obj]); + } + } + } + } + if(count==1) + node["children"]=[]; +} +exports.Recursion=Recursion; diff --git a/osconsole/config.js.tmpl b/osconsole/config.js.tmpl new file mode 100644 index 0000000..b07e81e --- /dev/null +++ b/osconsole/config.js.tmpl @@ -0,0 +1,7 @@ +window.OPENSHIFT_CONFIG = { + auth: { + oauth_authorize_uri: "{{ .Env.OAUTH_AUTHORIZE_URI }}", + oauth_client_id: "{{ .Env.OAUTH_CLIENT_ID }}", + logout_uri: "", + } +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..1d76c97 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "hawtio-kubernetes", + "version": "2.0.0", + "devDependencies": { + "bower": "^1.3.12", + "del": "^2.2.0", + "event-stream": "^3.1.7", + "gulp": "^3.8.10", + "gulp-angular-templatecache": "^1.5.0", + "gulp-concat": "^2.4.2", + "gulp-concat-filenames": "^1.0.0", + "gulp-filter": "^3.0.1", + "gulp-less": "^3.0.5", + "gulp-load-plugins": "^0.8.0", + "gulp-ng-annotate": "^1.1.0", + "gulp-notify": "^2.1.0", + "gulp-replace": "^0.5.4", + "gulp-sourcemaps": "^1.5.1", + "gulp-typescript": "^2.4.2", + "gulp-watch": "^3.0.0", + "hawtio-node-backend": "^2.0.5", + "stringify-object": "^2.0.0", + "through2": "^0.6.3", + "underscore.string": "^2.4.0", + "urijs": "^1.17.0", + "url-join": "^0.0.1", + "which": "^1.0.8", + "wiredep": "^2.2.2", + "yargs": "^3.32.0" + }, + "dependencies": { + "connect-multiparty": "^2.0.0", + "hawtio-node-backend": "^2.1.0", + "k8s": "^0.2.7", + "node-crontab": "0.0.8", + "oracledb": "^1.9.3", + "xml2js": "^0.4.16", + "xmldom": "^0.1.22", + "xpath.js": "^1.0.6" + } +} diff --git a/plugins/developer/html/addDataFile.html b/plugins/developer/html/addDataFile.html new file mode 100644 index 0000000..74fa1d3 --- /dev/null +++ b/plugins/developer/html/addDataFile.html @@ -0,0 +1,145 @@ +
+
+

江苏省审计厅数据汇总平台

+
+
+
+

本地文件列表

+
    +
  • 文件名
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
    +
  • 文件属性
  • +
  • +
  • +
+
+
+ +
+

服务器文件列表

+
+
+ employee: {{node.name}} age {{node.age}} +
+ +
+
+
    +
  • 文件名
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
    +
  • 文件属性
  • +
+
+
+
+
+ +
+ + + +
\ No newline at end of file diff --git a/plugins/developer/html/code.html b/plugins/developer/html/code.html new file mode 100644 index 0000000..c6a1153 --- /dev/null +++ b/plugins/developer/html/code.html @@ -0,0 +1,51 @@ +
+
+
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+
+ +
+
+
+
+

There are no tools currently available.

+
+
+
+

There are no tools currently available.

+
+ +
+
+
+
+
diff --git a/plugins/developer/html/environment.html b/plugins/developer/html/environment.html new file mode 100644 index 0000000..226a72a --- /dev/null +++ b/plugins/developer/html/environment.html @@ -0,0 +1 @@ +environment!!!! \ No newline at end of file diff --git a/plugins/developer/html/environmentPanel.html b/plugins/developer/html/environmentPanel.html new file mode 100644 index 0000000..256c213 --- /dev/null +++ b/plugins/developer/html/environmentPanel.html @@ -0,0 +1,87 @@ +
+
+
+ + +
+
+
+ +
+ + +
+ +
+
diff --git a/plugins/developer/html/environments.html b/plugins/developer/html/environments.html new file mode 100644 index 0000000..fef76b5 --- /dev/null +++ b/plugins/developer/html/environments.html @@ -0,0 +1,100 @@ +
+ +
+
+ + + +
+
+
+
+
+
+
+
+
+ +
+ + + + +
+
+
+
+

Environments Overview

+
+
+
+
+
+

No Environment Available

+

Environment is a logical place where deployments happen which maps to a kubernetes / openshift namespace. You will see environments here after you add a build.

+ New Build +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+

Active Pipelines

+ View All Pipelines >> +
+
+
+
+
+
+
+ +
+
+
+
+

Commits

+ View All Commits >> +
+
+
+
+
+
+
+ +
diff --git a/plugins/developer/html/home.html b/plugins/developer/html/home.html new file mode 100644 index 0000000..eb3db2f --- /dev/null +++ b/plugins/developer/html/home.html @@ -0,0 +1,38 @@ +
+
+

Perspectives

+ +

+ Please choose the perspective you would like to use: +

+
+
+ +
+

+ + +  Develop » + +

+ +

+ Work on projects and source code +

+
+
+

+ + +  Operate » + +

+ +

+ Manage and run Pods and Services +

+
+
+
\ No newline at end of file diff --git a/plugins/developer/html/jenkinsApproveModal.html b/plugins/developer/html/jenkinsApproveModal.html new file mode 100644 index 0000000..3a6c119 --- /dev/null +++ b/plugins/developer/html/jenkinsApproveModal.html @@ -0,0 +1,10 @@ + + + diff --git a/plugins/developer/html/jenkinsJob.html b/plugins/developer/html/jenkinsJob.html new file mode 100644 index 0000000..e912335 --- /dev/null +++ b/plugins/developer/html/jenkinsJob.html @@ -0,0 +1,79 @@ +
+ + + + + + +
+
+
+ +
+
+
+ +
+
+ + + + + + + Trigger + +
+
+
+
+
+
+ +
+
+
+
+

There are no builds in this job.

+
+
+
+
+
+
+
+
diff --git a/plugins/developer/html/jenkinsJobs.html b/plugins/developer/html/jenkinsJobs.html new file mode 100644 index 0000000..edd3e27 --- /dev/null +++ b/plugins/developer/html/jenkinsJobs.html @@ -0,0 +1,97 @@ +
+ + + + + + + + +
+
+
+ +
+
+
+ +
+
+ + + + + Trigger + +
+
+
+
+
+
+ +
+
+
+
+

There are no jobs in this jenkins.

+
+
+
+
+
+
+
+
diff --git a/plugins/developer/html/jenkinsLog.html b/plugins/developer/html/jenkinsLog.html new file mode 100644 index 0000000..6da0b61 --- /dev/null +++ b/plugins/developer/html/jenkinsLog.html @@ -0,0 +1,39 @@ +
+
+
+
+ +
+
+
+ +
+ +
+ +
+
+
+
+

+
+
+ +
+
+
diff --git a/plugins/developer/html/jenkinsMetrics.html b/plugins/developer/html/jenkinsMetrics.html new file mode 100644 index 0000000..bbb062c --- /dev/null +++ b/plugins/developer/html/jenkinsMetrics.html @@ -0,0 +1,27 @@ +
+
+
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+

There are no completed builds in this job.

+
+
+ +
+
+
+
+
diff --git a/plugins/developer/html/logPanel.html b/plugins/developer/html/logPanel.html new file mode 100644 index 0000000..3913474 --- /dev/null +++ b/plugins/developer/html/logPanel.html @@ -0,0 +1,7 @@ +
+
+

+
+
+ + diff --git a/plugins/developer/html/overview b/plugins/developer/html/overview new file mode 100644 index 0000000..e69de29 diff --git a/plugins/developer/html/pipeline.html b/plugins/developer/html/pipeline.html new file mode 100644 index 0000000..99ffc3a --- /dev/null +++ b/plugins/developer/html/pipeline.html @@ -0,0 +1,40 @@ +
+
+
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+
+ +
+
+
+
+

There are no pipeline stages in this build.

+
+
+ +

Pipeline for {{jobId}}

+ +
+
+
+
+
+
diff --git a/plugins/developer/html/pipelineView.html b/plugins/developer/html/pipelineView.html new file mode 100644 index 0000000..5c7fd2e --- /dev/null +++ b/plugins/developer/html/pipelineView.html @@ -0,0 +1,77 @@ +
+
+
+

+ + Build {{build.displayName}} + + + started {{build.$timestamp.relative()}} + +

+
+ +
+
+ + +
+ +
+
+
+

Logs

+ View Full Log +
+
+
+ +
+
+ + +
+
diff --git a/plugins/developer/html/pipelines.html b/plugins/developer/html/pipelines.html new file mode 100644 index 0000000..67148cc --- /dev/null +++ b/plugins/developer/html/pipelines.html @@ -0,0 +1,44 @@ +
+
+
+ +
+
+ + + +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+

There are no pipelines for this job.

+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/developer/html/projectDetail.html b/plugins/developer/html/projectDetail.html new file mode 100644 index 0000000..f8e9d7e --- /dev/null +++ b/plugins/developer/html/projectDetail.html @@ -0,0 +1,36 @@ +
+
+
+   + + +   + +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/developer/html/projectSelector.html b/plugins/developer/html/projectSelector.html new file mode 100644 index 0000000..d6c8d87 --- /dev/null +++ b/plugins/developer/html/projectSelector.html @@ -0,0 +1,13 @@ + diff --git a/plugins/developer/html/projects.html b/plugins/developer/html/projects.html new file mode 100644 index 0000000..2266a10 --- /dev/null +++ b/plugins/developer/html/projects.html @@ -0,0 +1,126 @@ +
+ + + + + + + +
+
+
+ +
+
+ + + +   + + + + +   + + + Create App + + + +
+
+
+
+
+
+ +
+
+
+
+

There are no projects in this workspace.

+
+
+
+
+
+
+
+
diff --git a/plugins/developer/html/tools.html b/plugins/developer/html/tools.html new file mode 100644 index 0000000..c6a1153 --- /dev/null +++ b/plugins/developer/html/tools.html @@ -0,0 +1,51 @@ +
+
+
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+
+ +
+
+
+
+

There are no tools currently available.

+
+
+
+

There are no tools currently available.

+
+ +
+
+
+
+
diff --git a/plugins/developer/html/workspace.html b/plugins/developer/html/workspace.html new file mode 100644 index 0000000..0e61f3a --- /dev/null +++ b/plugins/developer/html/workspace.html @@ -0,0 +1,46 @@ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/developer/html/workspaces.html b/plugins/developer/html/workspaces.html new file mode 100644 index 0000000..5d9f67a --- /dev/null +++ b/plugins/developer/html/workspaces.html @@ -0,0 +1,75 @@ +
+
+
+ +
+
+
+
+

江苏省审计厅数据汇总平台

+
+
+
+

本地文件列表

+
    +
  • 文件名
  • +
    + {{node.name}} +
    +
+
    +
  • 已选数据文件
  • +
  • {{node.name}}
  • + +
+
    +
  • 采集时间
  • +
  • {{node.date}}   + {{model.uploadprocess[node.id]}}%
  • +
+
+ +
+
+
+

服务器文件列表

+
+
+ {{node.name}} +
+
+
+
    +
  • 文件名
  • +
  • {{item.name}}
  • +
+
    +
  • 采集时间
  • +
  • {{item.time}}
  • +
+
+
+ +
+
+
+ +
+ +
diff --git a/plugins/developer/less/environmentPanel.less b/plugins/developer/less/environmentPanel.less new file mode 100644 index 0000000..b9078f8 --- /dev/null +++ b/plugins/developer/less/environmentPanel.less @@ -0,0 +1,66 @@ + +.environment-row a { + color: black; +} + +.environment-row { + + .panel { + min-width: 255px; + min-height: 160px; + } + + .panel-group { + margin-left: 10px; + margin-right: 10px; + } + + .panel-title > a:before { + display: none; + } + +} + +.environment-rows { + /* + background-color: rgb(238, 238, 238); + */ + padding-top: 5px; + vertical-align: top; +} + +.environment-name-block { + width: 200px; +} + +.environment-name-block, .environment-deploy-block { + background: white; + -moz-border-radius: 10px; + border-radius: 10px; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + margin-top: 10px; + margin-bottom: 10px; + margin-left: 20px; + margin-right: 20px; +} + +.environment-name-block { + padding-top: 0px; +} + +.environment-block { + vertical-align: top; +} + +.environment-deploy-block { + border:1px dashed; + border-color: silver; +} + +.environment-deploy-version-and-pods { + padding-bottom: 5px; +} + diff --git a/plugins/developer/less/environments.less b/plugins/developer/less/environments.less new file mode 100644 index 0000000..3a23da9 --- /dev/null +++ b/plugins/developer/less/environments.less @@ -0,0 +1,50 @@ +.project-dashboard { + + .page-header-row { + background: white; + margin-left: -20px; + margin-right: -20px; + margin-top: -20px; + border-bottom: 1px solid #d1d1d1; + margin-bottom: 13px; + padding-bottom: 7px; + } + + .card-pf-title { + margin-right: 1em; + } + + .no-border { + border: none; + margin-bottom: 0; + } + + .no-top-margin { + margin-top: 0; + } + + .full-card-width { + margin-left: -20px; + margin-right: -20px; + } + + .card-pf.pipeline { + .panel-group { + border-width: 0; + .panel { + box-shadow: none; + } + .panel.panel-default { + border-width: 0; + border-top-width: 1px; + + .log-panel { + border: 1px solid #d4d4d4; + } + } + } + } + + + +} diff --git a/plugins/developer/less/filterHeader.less b/plugins/developer/less/filterHeader.less new file mode 100644 index 0000000..60ad9fc --- /dev/null +++ b/plugins/developer/less/filterHeader.less @@ -0,0 +1,8 @@ +.filter-header { + + .btn, form { + margin-top: 1.05em; + margin-bottom: 1em; + } + +} diff --git a/plugins/developer/less/jenkinsLog.less b/plugins/developer/less/jenkinsLog.less new file mode 100644 index 0000000..853ed5a --- /dev/null +++ b/plugins/developer/less/jenkinsLog.less @@ -0,0 +1,25 @@ + +.log-window { + border-top: 1px solid #d4d4d4; + overflow: auto; +} + +.log-window-inner * { + font-family: "DroidSansMonoRegular", monospace; + line-height: 13px; +} + +.log-panel { + position: static; + height: 100%; + width: 100%; + overflow: auto; + border: none; + padding: 3px; +} + +.log-panel-inner * { + font-family: "DroidSansMonoRegular", monospace; + line-height: 13px; +} + diff --git a/plugins/developer/less/projectSelector.less b/plugins/developer/less/projectSelector.less new file mode 100644 index 0000000..5c36846 --- /dev/null +++ b/plugins/developer/less/projectSelector.less @@ -0,0 +1,14 @@ +.project-selector { + margin-top: 10px; + margin-bottom: 10px; + + list-style-type: none; + + a, a:hover { + color: #fff; + text-decoration: none; + font-size: 13px; + line-height: 21px; + } + +} diff --git a/plugins/developer/less/style.less b/plugins/developer/less/style.less new file mode 100644 index 0000000..fb3934b --- /dev/null +++ b/plugins/developer/less/style.less @@ -0,0 +1,224 @@ +/* 样式重置 */ +body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} +body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#fff;} +div,img,tr,td,table{ border:0;} +table,tr,td{border:0;cellspacing:0; cellpadding:0;} +ol,ul,li{ list-style-type:none} +a:link,a:visited{color:#7f7f7f;text-decoration:none;} +a:hover,a:active{color:#000;} +.fl{ float:left;} +.fr{ float:right;} +.cl{ clear:both; overflow:hidden;} + +/* 数据页面 */ +.data_container{ + width:100%; + margin:0 auto; +} +.data_heaer{ + height:66px; + width:100%; + background-color:#3499db; + text-align:center; +} +.data_heaer h2{ + font-size:30px; + font-weight:300; + color:#fff; + line-height:66px; +} +.data_content{ + width:1280px; + height:838px; + margin:0 auto; + background-color:#fff; + border:1px solid #e0dede; + border-top:none; +} +.data_leftside{ + width:611px; + border-right:1px solid #e0dede; +} +.data_h3{ + width:100%; + text-align:center; + height:50px; + font-size:18px; + color:#444; + line-height:50px; +} +.data_leftside_files{ + border-right:1px solid #e0dede; + border-bottom:1px solid #e0dede; + height:710px; + overflow :auto; +} +.data_leftside_files input{ + margin-top:15px; + width:15px; + height:15px; +} +.data_leftside_files li{ + height:40px; + line-height:40px; + border-bottom:1px solid #e0dede; + padding:0 10px; +} +.data_leftside_files li.data_title{ + width:210px; height:36px; + line-height:36px; + text-align:center; + background-color:#e9f3fb; + border:none; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; +} +.date_label{ + display:block; + width:168px; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; +} +.data_leftside_shu{ + border-right:none; +} +.data_leftside_shu li{ + border-bottom:none; +} +.data_conbar{ width:149px; + height:834px; + border-right:1px solid #e0dede; + border-left:1px solid #e0dede; +} +.date_btns{ + width:260px; + margin:20px auto; +} +.date_btns_w{ + width:390px; +} +.date_btns button{ + margin:10px 20px; +} +.data_btn{ + border:none; + width:108px; + height:35px; + line-height:35px; + text-align:center; + background-color:#3499db; + color:#fff; + font-size:14px; + -webkit-border-radius:5px; + -moz-border-radius:5px; + -o-border-radius:5px; + border-radius:5px; +} +.data_btn:hover{ + background-color:#2989da; +} +.data_rightside{ + width:667px; +} +.data_rightside_w{ + width:407px; +} +.data_leftside_files li.data_title_w{ + width:184px; +} +.date_label_w{ + width:150px; +} +.data_leftside_shu li{ + border-bottom:none; +} + +a.data_file_btn{ display:block; position:relative; width:108px; height:35px; margin:15px auto; line-height:35px; font-size:14px; color: #fff; text-align:center; + background-color: #79b4e7; + background-image: -webkit-linear-gradient(#79b4e7, #1377cf); + background-image: linear-gradient(#79b4e7, #1377cf); + border-color: #076bc2; + -webkit-border-radius:5px; + -moz-border-radius:5px; + -o-border-radius:5px; + border-radius:5px; + vertical-align: middle; + cursor: pointer; + margin:0 10px; +} +a:hover.data_file_btn{ + background-color: #076bc2; + background-image: -webkit-linear-gradient(#79b4e7, #076bc2); + background-image: linear-gradient(#79b4e7, #076bc2); + border-color: #076bc2;} +.data_file_btn input{ position:absolute; left:0px;opacity:0; filter:alpha(opacity=0); width:108px; height:35px;} + + +.data_conbox{ + width:407px; + height:709px; + border-top:1px solid #e0dede; + border-bottom:1px solid #e0dede; + overflow: auto; + } +.data_con_title{ + width:49.8%; + height:36px; + line-height:36px; + text-align:center; + background-color:#e9f3fb; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; + } + .data_con_line{ + border-right:1px solid #e0dede; + + } +.data_con_li{ + width:49.8%; + height:36px; + line-height:36px; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + white-space:nowrap; + border-bottom:1px solid #e0dede; + } +.mt15{ margin-top:15px;} + +#file-uploads{ + opacity: 0; + position: absolute; + z-index: 10; + width:118px; + height:35px; +} + + +/* 树形结构 */ +.data_rightside_tree{ + width:259px; + height:709px; + border-right:1px solid #e0dede; + border-top:1px solid #e0dede; + border-bottom:1px solid #e0dede; + overflow: auto; +} +.tree { min-height:20px;padding:15px;padding-left:30px;border-bottom:1px dashed #ccc;} +.tree li {list-style-type:none;margin:0; padding:10px 5px 0 20px; position:relative} +.tree li::before, .tree li::after { content:'';left:-30px;position:absolute; right:auto} +.tree li::before { border-left:1px solid #999; bottom:50px;height:100%; top:0; width:0px} +.tree li::after {border-top:1px solid #999;height:20px; top:25px; width:35px} +.tree li p {display:inline-block;padding:3px 10px;border:1px solid #fff; margin-left:-15px; width:150px; } +.tree li.parent_li>p {cursor:pointer} +.tree>ul>li::before, .tree>ul>li::after {border:0} +.tree li:last-child::before { height:30px} +.tree li.parent_li>p:hover, .tree li.parent_li>p:hover+ul li p { } +.icon-plus-sign{ margin-left:-15px; background:url(../img/icons1.gif) -5px 10px no-repeat; } +.icon-minus-sign{ margin-left:-15px; background:url(../img/icons2.gif) -6px 9px no-repeat;} \ No newline at end of file diff --git a/plugins/developer/ts/FileMode.ts b/plugins/developer/ts/FileMode.ts new file mode 100644 index 0000000..58a5928 --- /dev/null +++ b/plugins/developer/ts/FileMode.ts @@ -0,0 +1,40 @@ +/// +/// +/// +/// +/// + +module Developer { + /* export var DataOverView = controller("DataOverView", + ["$scope", "$location", "$routeParams", "$http", "$timeout", ($scope, $location:ng.ILocationService, $routeParams, $http, $timeout) => { + $scope.treeOptions = { + nodeChildren: "children", + dirSelectable: true, + injectClasses: { + ul: "a1", + li: "a2", + liSelected: "a7", + iExpanded: "a3", + iCollapsed: "a4", + iLeaf: "a5", + label: "a6", + labelSelected: "a8" + } + } + + $scope.dataForTheTree = + [ + { "name" : "Joe", "age" : "21", "children" : [ + { "name" : "Smith", "age" : "42", "children" : [] }, + { "name" : "Gary", "age" : "21", "children" : [ + { "name" : "Jenifer", "age" : "23", "children" : [ + { "name" : "Dani", "age" : "32", "children" : [] }, + { "name" : "Max", "age" : "34", "children" : [] } + ]} + ]} + ]}, + { "name" : "Albert", "age" : "33", "children" : [] }, + { "name" : "Ron", "age" : "29", "children" : [] } + ]; + }]);*/ +} diff --git a/plugins/developer/ts/developerEnrichers.ts b/plugins/developer/ts/developerEnrichers.ts new file mode 100644 index 0000000..df807fe --- /dev/null +++ b/plugins/developer/ts/developerEnrichers.ts @@ -0,0 +1,247 @@ +/// +module Developer { + + export function enrichWorkspaces(projects) { + angular.forEach(projects, (project) => { + enrichWorkspace(project); + }); + return projects; + } + + export function enrichWorkspace(build) { + if (build) { + var name = Kubernetes.getName(build); + build.$name = name; + build.$sortOrder = 0 - build.number; + + var nameArray = name.split("-"); + var nameArrayLength = nameArray.length; + build.$shortName = (nameArrayLength > 4) ? nameArray.slice(0, nameArrayLength - 4).join("-") : name.substring(0, 30); + + var labels = Kubernetes.getLabels(build); + build.$creationDate = asDate(Kubernetes.getCreationTimestamp(build)); + build.$labelsText = Kubernetes.labelsToString(labels); + + if (name) { + build.$projectsLink = UrlHelpers.join("workspaces", name); + build.$runtimeLink = UrlHelpers.join("kubernetes/namespace/", name, "/apps"); + build.$viewLink = build.$projectsLink; + } + } + return build; + } + + export function asDate(value) { + return value ? new Date(value) : null; + } + + export function enrichJenkinsJobs(jobsData, projectId, jobName) { + if (jobsData) { + angular.forEach(jobsData.jobs, (job) => { + enrichJenkinsJob(job, projectId, jobName); + }); + } + return jobsData; + } + + export function enrichJenkinsJob(job, projectId, jobName) { + if (job) { + jobName = jobName || job.name || projectId; + job.$jobId = jobName; + job.$project = projectId || jobName; + var lastBuild = job.lastBuild; + var lastBuildResult = lastBuild ? lastBuild.result : "NOT_STARTED"; + var $iconClass = createBuildStatusIconClass(lastBuildResult); + + job.$lastBuildNumber = enrichJenkinsBuild(job, lastBuild); + job.$lastSuccessfulBuildNumber = enrichJenkinsBuild(job, job.lastSuccessfulBuild); + job.$lastFailedlBuildNumber = enrichJenkinsBuild(job, job.lastFailedlBuild); + + if (lastBuild) { + job.$duration = lastBuild.duration; + job.$timestamp = asDate(lastBuild.timestamp); + } + var jobUrl = (job || {}).url; + if (!jobUrl || !jobUrl.startsWith("http")) { + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + jobUrl = UrlHelpers.join(jenkinsUrl, "job", jobName) + } + } + if (jobUrl) { + job.$jobLink = jobUrl; + var workspaceName = Kubernetes.currentKubernetesNamespace(); + job.$pipelinesLink = UrlHelpers.join("/workspaces", workspaceName, "projects", job.$project, "jenkinsJob", jobName, "pipelines"); + job.$buildsLink = UrlHelpers.join("/workspaces", workspaceName, "projects", job.$project, "jenkinsJob", jobName); + } + job.$iconClass = $iconClass; + + angular.forEach(job.builds, (build) => { + enrichJenkinsBuild(job, build); + }); + } + return job; + } + + export function createBuildStatusIconClass(result) { + var $iconClass = "fa fa-spinner fa-spin"; + if (result) { + if (result === "FAILURE" || result === "FAILED") { + // TODO not available yet + $iconClass = "fa fa-exclamation-circle red"; + } else if (result === "ABORTED" || result === "INTERUPTED") { + $iconClass = "fa fa-circle grey"; + } else if (result === "SUCCESS" || result === "COMPLETE" || result === "COMPLETED") { + $iconClass = "fa fa-check-circle green"; + } else if (result === "NOT_STARTED") { + $iconClass = "fa fa-circle-thin grey"; + } + } + return $iconClass; + } + + export function createBuildStatusBackgroundClass(result) { + var $iconClass = "build-pending"; + if (result) { + if (result === "FAILURE" || result === "FAILED") { + $iconClass = "build-fail"; + } else if (result === "ABORTED" || result === "INTERUPTED") { + $iconClass = "build-aborted"; + } else if (result === "SUCCESS" || result === "COMPLETE" || result === "COMPLETED") { + $iconClass = "build-success"; + } else if (result === "NOT_STARTED") { + $iconClass = "build-not-started"; + } + } + return $iconClass; + } + + export function enrichJenkinsBuild(job, build) { + var number = null; + if (build) { + build.$duration = build.duration; + build.$timestamp = asDate(build.timestamp); + var projectId = job.$project; + var jobName = job.$jobId || projectId; + var buildId = build.id; + number = build.number; + var workspaceName = Kubernetes.currentKubernetesNamespace(); + + var $iconClass = createBuildStatusIconClass(build.result); + var jobUrl = (job || {}).url; + if (!jobUrl || !jobUrl.startsWith("http")) { + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + jobUrl = UrlHelpers.join(jenkinsUrl, "job", jobName) + } + } + if (jobUrl) { + build.$jobLink = jobUrl; + if (buildId) { + //build.$logsLink = UrlHelpers.join(build.$buildLink, "console"); + build.$logsLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "log", buildId); + build.$pipelineLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "pipeline", buildId); + build.$buildsLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName); + //build.$buildLink = UrlHelpers.join(jobUrl, build.id); + build.$buildLink = build.$logsLink; + } + } + build.$iconClass = $iconClass; + } + return number; + } + + + export function jenkinsLink() { + var ServiceRegistry = Kubernetes.inject("ServiceRegistry"); + if (ServiceRegistry) { + return ServiceRegistry.serviceLink(jenkinsServiceName); + } + return null; + } + + export function forgeReadyLink() { + var ServiceRegistry = Kubernetes.inject("ServiceRegistry"); + if (ServiceRegistry) { + return ServiceRegistry.serviceReadyLink(Kubernetes.fabric8ForgeServiceName); + } + return null; + } + + export function enrichJenkinsPipelineJob(job, projectId, jobId) { + if (job) { + job.$project = projectId; + job.$jobId = jobId; + angular.forEach(job.builds, (build) => { + enrichJenkinsStages(build, projectId, jobId); + }); + } + } + + export function enrichJenkinsStages(build, projectId, jobName) { + if (build) { + build.$project = projectId; + build.$jobId = jobName; + build.$timestamp = asDate(build.timeInMillis); + build.$iconClass = createBuildStatusIconClass(build.result || "NOT_STARTED"); + + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var parameters = build.parameters; + var $parameterCount = 0; + var $parameterText = "No parameters"; + if (parameters) { + $parameterCount = _.keys(parameters).length || 0; + $parameterText = Kubernetes.labelsToString(parameters, " "); + } + build.$parameterCount = $parameterCount; + build.$parameterText = $parameterText; + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + var url = build.url; + if (url) { +/* + build.$viewLink = UrlHelpers.join(jenkinsUrl, url); + build.$logLink = UrlHelpers.join(build.$viewLink, "log"); +*/ + } + } + build.$logLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "log", build.id); + build.$viewLink = build.$logLink; + + angular.forEach(build.stages, (stage) => { + enrichJenkinsStage(stage, build); + }); + } + return build; + } + + export function enrichJenkinsStage(stage, build = null) { + if (stage) { + if (build) { + stage.$buildId = build.id; + stage.$project = build.$project; + } + var projectId = build.$project; + var jobName = build.$jobId || projectId; + var buildId = build.id; + var workspaceName = Kubernetes.currentKubernetesNamespace(); + stage.$backgroundClass = createBuildStatusBackgroundClass(stage.status); + stage.$iconClass = createBuildStatusIconClass(stage.status); + stage.$startTime = asDate(stage.startTime); + if (!stage.duration) { + stage.duration = 0; + } + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + var url = stage.url; + if (url) { + stage.$viewLink = UrlHelpers.join(jenkinsUrl, url); + stage.$logLink = UrlHelpers.join(stage.$viewLink, "log"); + if (projectId && buildId) { + stage.$logLink = UrlHelpers.join("/workspaces", workspaceName, "projects", projectId, "jenkinsJob", jobName, "log", buildId); + } + } + } + } + } +} diff --git a/plugins/developer/ts/developerHelpers.ts b/plugins/developer/ts/developerHelpers.ts new file mode 100644 index 0000000..356099b --- /dev/null +++ b/plugins/developer/ts/developerHelpers.ts @@ -0,0 +1,294 @@ +/// +module Developer { + + export var context = '/workspaces'; + export var hash = '#' + context; + export var pluginName = 'Developer'; + export var pluginPath = 'plugins/developer/'; + export var templatePath = pluginPath + 'html/'; + export var log:Logging.Logger = Logger.get(pluginName); + + export var jenkinsServiceName = "jenkins"; + export var jenkinsServiceNameAndPort = jenkinsServiceName + ":http"; + + export var jenkinsHttpConfig = { + headers: { + Accept: "application/json, text/x-json, text/plain" + } + }; + + /** + * Returns true if the value hasn't changed from the last cached JSON version of this object + */ + export function hasObjectChanged(value, state) { + var json = angular.toJson(value || ""); + var oldJson = state.json; + state.json = json; + return !oldJson || json !== oldJson; + } + + export function projectForScope($scope) { + if ($scope) { + return $scope.buildConfig || $scope.entity || ($scope.model || {}).project; + } + return null; + } + /** + * Lets load the project versions for the given namespace + */ + export function loadProjectVersions($scope, $element, project, env, ns, answer, caches) { + var projectAnnotation = "project"; + var versionAnnotation = "version"; + + var projectNamespace = project.$namespace; + var projectName = project.$name; + + var cache = caches[ns]; + if (!cache) { + cache = {}; + caches[ns] = cache; + } + + var status = { + rcs: [], + pods: [], + routes: [], + services: [] + }; + + var imageStreamTags = []; + + function updateModel() { + var projectInfos = {}; + var model = $scope.model || {}; + + angular.forEach(status.rcs, (item) => { + var metadata = item.metadata || {}; + var name = metadata.name; + var labels = metadata.labels || {}; + var annotations = metadata.annotations || {}; + var spec = item.spec || {}; + var selector = spec.selector; + + var project = labels[projectAnnotation]; + var version = labels[versionAnnotation]; + + // lets try the S2I defaults... + if (!project) { + project = labels["app"]; + } + if (!version) { + version = annotations["openshift.io/deployment-config.latest-version"] + } + if (project && version && project === projectName) { + var projects = projectInfos[project]; + if (!projects) { + projects = { + project: project, + versions: {} + }; + projectInfos[project] = projects; + } + var versionInfo = projects.versions[version]; + if (!versionInfo) { + versionInfo = { + replicationControllers: {} + }; + projects.versions[version] = versionInfo; + } + if (name) { + versionInfo.replicationControllers[name] = item; + item.$name = name; + if (projectNamespace && projectName) { + item.$viewLink = UrlHelpers.join("/workspaces/", projectNamespace, "projects", projectName, "namespace", ns, "replicationControllers", name); + } else { + log.warn("Missing project data! " + projectNamespace + " name " + projectName); + } + + item.$services = []; + var rcLink = null; + status.services.forEach((service) => { + var repSelector = Kubernetes.getSelector(item); + var serviceSelector = Kubernetes.getSelector(service); + if (serviceSelector && repSelector && + Kubernetes.selectorMatches(serviceSelector, repSelector) && + Kubernetes.getNamespace(service) === Kubernetes.getNamespace(item)) { + status.routes.forEach((route) => { + var serviceName = Kubernetes.getName(service); + if (serviceName === Kubernetes.getName(route)) { + service["$route"] = route; + service["$host"] = Core.pathGet(route, ["spec", "host"]); + item.$services.push(service); + if (!rcLink) { + var url = Kubernetes.serviceLinkUrl(service, true); + if (url) { + // TODO find icon etc? + rcLink = { + name: serviceName, + href: url + }; + } + } + } + }); + } + }); + item["$serviceLink"] = rcLink; + } + item.$buildId = annotations["fabric8.io/build-id"] || item.$buildId; + item.$buildUrl = annotations["fabric8.io/build-url"] || item.$buildUrl; + item.$gitCommit = annotations["fabric8.io/git-commit"] || item.$gitCommit; + item.$gitUrl = annotations["fabric8.io/git-url"] || item.$gitUrl; + item.$gitBranch = annotations["fabric8.io/git-branch"] || item.$gitBranch; + if (!item.$gitCommit) { + var image = getImage(item); + if (image) { + if (!$scope.$isWatchImages) { + $scope.$isWatchImages = true; + Kubernetes.watch($scope, $element, "images", null, (data) => { + imageStreamTags = data; + checkForMissingMetadata(); + }); + } else { + checkForMissingMetadata(); + } + } + + function getImage(item) { + var image = ""; + // lets see if we can find the commit id from a S2I image name + // TODO needs this issue fixed to find it via an OpenShift annotation: + // https://github.com/openshift/origin/issues/6241 + var containers = Core.pathGet(item, ["spec", "template", "spec", "containers"]); + if (containers && containers.length) { + var container = containers[0]; + if (container) { + image = container.image; + } + } + return image; + } + + function checkForMissingMetadata() { + angular.forEach(projects.versions, (vi) => { + angular.forEach(vi.replicationControllers, (item, name) => { + if (!item.$gitCommit) { + var image = getImage(item); + if (image) { + angular.forEach(imageStreamTags, (imageStreamTag) => { + var imageName = imageStreamTag.dockerImageReference; + if (imageName && imageName === image) { + var foundISTag = imageStreamTag; + var manifestJSON = imageStreamTag.dockerImageManifest; + if (manifestJSON) { + var manifest = angular.fromJson(manifestJSON) || {}; + var history = manifest.history; + if (history && history.length) { + var v1 = history[0].v1Compatibility; + if (v1) { + var data = angular.fromJson(v1); + var env = Core.pathGet(data, ["config", "Env"]); + angular.forEach(env, (envExp) => { + if (envExp) { + var values = envExp.split("="); + if (values.length === 2 && values[0] == "OPENSHIFT_BUILD_NAME") { + var buildName = values[1]; + if (buildName) { + item.$buildId = buildName; + item.$buildUrl = Developer.projectWorkspaceLink(ns, projectName, "buildLogs/" + buildName); + } + } + } + }); + var labels = Core.pathGet(data, ["config", "Labels"]); + if (labels) { + item.$gitCommit = labels["io.openshift.build.commit.id"] || item.$gitCommit; + item.$gitCommitAuthor = labels["io.openshift.build.commit.author"] || item.$gitCommitAuthor; + item.$gitCommitDate = labels["io.openshift.build.commit.date"] || item.$gitCommitDate; + item.$gitCommitMessage = labels["io.openshift.build.commit.message"] || item.$gitCommitMessage; + item.$gitBranch = labels["io.openshift.build.commit.ref"] || item.$gitBranch; + + if (!item.$gitUrl && item.$gitCommit) { + item.$gitUrl = Developer.projectWorkspaceLink(ns, projectName, "wiki/commitDetail///" + item.$gitCommit); + } + } + } + } + } + } + }); + } + } + }); + }); + } + } + + if (selector) { + var selectorText = Kubernetes.labelsToString(selector, ","); + var podLinkUrl = UrlHelpers.join(projectLink(projectName), "namespace", ns, "pods"); + item.pods = []; + item.$podCounters = Kubernetes.createPodCounters(selector, status.pods, item.pods, selectorText, podLinkUrl); + } + } + }); + + // lets check for a project name if we have lots of RCs with no pods, lets remove them! + angular.forEach(projectInfos, (project, projectName) => { + var rcsNoPods = []; + var rcsWithPods = []; + angular.forEach(project.versions, (versionInfo) => { + var rcs = versionInfo.replicationControllers; + angular.forEach(rcs, (item, name) => { + var count = Kubernetes.podCounterTotal(item.$podCounters); + if (count) { + rcsWithPods.push(name); + } else { + rcsNoPods.push(() => { + delete rcs[name]; + }); + } + }); + }); + if (rcsWithPods.length) { + // lets remove all the empty RCs + angular.forEach(rcsNoPods, (fn) => { + fn(); + }); + } + }); + + if (hasObjectChanged(projectInfos, cache)) { + log.debug("project versions has changed!"); + answer[ns] = projectInfos; + } + } + + Kubernetes.watch($scope, $element, "replicationcontrollers", ns, (data) => { + if (data) { + status.rcs = data; + updateModel(); + } + }); + Kubernetes.watch($scope, $element, "services", ns, (data) => { + if (data) { + status.services = data; + updateModel(); + } + }); + Kubernetes.watch($scope, $element, "routes", ns, (data) => { + if (data) { + status.routes = data; + updateModel(); + } + }); + Kubernetes.watch($scope, $element, "pods", ns, (data) => { + if (data) { + status.pods = data; + updateModel(); + } + }); + } + + +} \ No newline at end of file diff --git a/plugins/developer/ts/developerNavigation.ts b/plugins/developer/ts/developerNavigation.ts new file mode 100644 index 0000000..a30538b --- /dev/null +++ b/plugins/developer/ts/developerNavigation.ts @@ -0,0 +1,616 @@ +/// +module Developer { + +/* + function homeBreadcrumb() { + return { + href: "/home", + label: "Home", + title: "Go to the home page" + } + } +*/ + function developBreadcrumb() { + return { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces"), + label: "Develop", + title: "View all the apps for a project" + }; + } + function operateBreadcrumb() { + return { + href: UrlHelpers.join(HawtioCore.documentBase(), "/namespaces"), + label: "Manage", + title: "Manage the projects and resources inside them" + }; + } + + export function workspaceLink() { + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", Kubernetes.currentKubernetesNamespace()); + } + + export function projectLink(projectId) { + var link = workspaceLink(); + if (projectId) { + return UrlHelpers.join(link, "/projects", projectId); + } else { + return link; + } + } + + export function createWorkspacesBreadcrumbs(developPerspective) { +/* + if (developPerspective) { + return [ + //homeBreadcrumb(), + developBreadcrumb() + ]; + } else { + return [ + //homeBreadcrumb(), + operateBreadcrumb() + ]; + } +*/ + return []; + } + + + export function createWorkspacesSubNavBars(developPerspective) { + return activateCurrent([ + developBreadcrumb(), + operateBreadcrumb() + ]); + } + + export function createWorkspaceBreadcrumbs(children = null, workspaceName = null) { + var answer = [ + //homeBreadcrumb(), + developBreadcrumb() + ]; + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + if (workspaceName) { + answer.push( + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces/", workspaceName), + label: workspaceName, + title: "View the project: " + workspaceName + } + ); + return processChildren(answer, children); + } + return answer; + } + + + export function createEnvironmentBreadcrumbs($scope, $location, $routeParams) { + var ns = Kubernetes.currentKubernetesNamespace(); + var namespacesLink = UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes/namespace"); + var workspaceName = $routeParams.workspace; + var project = $routeParams.project; + if (workspaceName && project) { + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", project); + $scope.$projectLink = projectLink; + $scope.$projectNamespaceLink = UrlHelpers.join(projectLink, "namespace", ns); + namespacesLink = UrlHelpers.join(projectLink, "namespace"); + // TODO use the logical name? + var envName = ns; + var buildConfig = null; + if ($scope.model) { + buildConfig = $scope.model.getProject(project, workspaceName); + if (buildConfig) { + // lets find the label for the namespace + var env = _.find(buildConfig.environments, { namespace: ns}); + if (env) { + envName = env['label'] || envName; + } + log.info("env found: " + env + " for nameppace " + ns + " on buildConfig: " + buildConfig); + } + } + var children = [ + { + href: UrlHelpers.join(projectLink, "environments"), + label: "Environments", + title: "View the environments for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "apps"), + label: envName, + title: "View the runtime of the workspace: " + ns + } + ]; + return createProjectBreadcrumbs(project, children, workspaceName); + } else { + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + return activateCurrent([ + //homeBreadcrumb(), + operateBreadcrumb(), + { + href: UrlHelpers.join(namespacesLink, ns, "apps"), + label: workspaceName, + title: "View the runtime of the workspace: " + ns + } + ]); + } + } + + export function createProjectBreadcrumbs(projectName = null, children = null, workspaceName = null) { + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + var answer = createWorkspaceBreadcrumbs(null, workspaceName); + if (workspaceName) { + if (projectName) { + answer.push( + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects"), + label: "Apps", + title: "View all the apps in this project" + } + ); + + answer.push( + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName), + label: projectName, + title: "View the project: " + projectName + } + ); + } + return processChildren(answer, children); + } + return answer; + } + + + export function createProjectSettingsBreadcrumbs(projectName, workspaceName = null) { + var children = [{ + label: "Settings", + title: "View the settings of this app" + }]; + if (!projectName) { + var children = [{ + label: "New App", + title: "Lets make a new app" + }]; + } + return createProjectBreadcrumbs(projectName, children, workspaceName); + } + + export function createWorkspaceSubNavBars() { + var workspaceName = Kubernetes.currentKubernetesNamespace(); + return activateCurrent([ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName), + label: "Apps", + class: "fa fa-rocket", + title: "View the apps in this project" + }, + { + isValid: () => jenkinsLink(), + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "jenkinsJob"), + label: "Builds", + class: "fa fa-code", + title: "View the builds in this project" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes/namespace", workspaceName, "apps"), + label: "Runtime", + class: "fa fa-gears", + title: "View the runtime resources in this project" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "detail"), + label: "Details", + class: "fa fa-gear", + title: "View the project details" + } + ]); + } + + function createBuildsLink(workspaceName, projectName, jenkinsJobId) { + workspaceName = workspaceName || Kubernetes.currentKubernetesNamespace(); + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "jenkinsJob", jenkinsJobId); + } + + export function createProjectSubNavBars(projectName, jenkinsJobId = null, $scope = null) { + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName); + var buildsLink = UrlHelpers.join(projectLink, "builds"); + if (!jenkinsJobId) { + jenkinsJobId = projectName; + } + var jenkinsBuildLink = null; + var pipelinesLink = null; + if (projectName && jenkinsJobId) { + jenkinsBuildLink = createBuildsLink(workspaceName, projectName, jenkinsJobId); + pipelinesLink = UrlHelpers.join(jenkinsBuildLink, "pipelines"); + } + + function isJenkinsBuild() { + var answer = jenkinsLink() && jenkinsBuildLink; + if (answer && $scope) { + var entity = Developer.projectForScope($scope); + if (entity) { + return answer && entity.$jenkinsJob; + } + } + return answer; + } + + var answer = [ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName), + label: "All Apps", + class: 'fa fa-angle-double-left', + title: "View the apps in this project" + }, + { + template: `
` + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "environments"), + isActive: (subTab, path) => { + //console.log("subTab: ", subTab, " path: ", path); + if (path === subTab.href) { + return true; + } + var rootPath = subTab.href.replace(/\/environments/, ''); + if (path === rootPath) { + return true; + } + return false; + }, + //href: UrlHelpers.join("/workspaces", workspaceName, "projects", projectName), + label: "Dashboard", + class: "fa fa-tachometer", + title: "View the app dashboard for the activity, environments and pipelines" + }, + { + isValid: () => isJenkinsBuild() && pipelinesLink, + id: "pipelines", + href: pipelinesLink, + label: "Pipelines", + class: "fa fa-ellipsis-h", + title: "View the pipeline builds for this app" + }, + { + isValid: () => !isJenkinsBuild(), + href: buildsLink, + label: "Builds", + class: "fa fa-bars", + title: "View the builds for this app" + }, + { + isValid: () => isJenkinsBuild(), + id: "builds", + href: jenkinsBuildLink, + label: "Builds", + class: "fa fa-bars", + title: "View the Jenkins builds for this app" + }, + { + isValid: () => isJenkinsBuild(), + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "jenkinsJob", jenkinsJobId, "metrics"), + label: "Metrics", + class: "fa fa-bar-chart", + title: "View the metrics for this project" + }, +/* + { + href: UrlHelpers.join("/workspaces", workspaceName, "projects", projectName, "tools"), + label: "Tools", + title: "View the tools for this project" + }, +*/ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "buildConfigEdit"), + label: "Settings", + class: "fa fa-cog", + title: "View the app configuration", + isActive: (subTab, path) => { + if (_.endsWith(path, '/buildConfigEdit')) { + return true; + } + if (_.endsWith(path, '/forge/secrets')) { + return true; + } + if (_.endsWith(path, '/forge/command/devops-edit')) { + return true; + } + return false; + } + } + ]; + + var context = { + workspaceName: workspaceName, + projectName: projectName, + projectLink: projectLink, + jenkinsJobId: jenkinsJobId, + $scope: $scope + }; + angular.forEach(customProjectSubTabFactories, (fn) => { + if (angular.isFunction(fn)) { + var subtab = fn(context); + if (subtab) { + if (angular.isArray(subtab)) { + angular.forEach(subtab, (t) => { + answer.push(t); + }); + } else { + answer.push(subtab); + } + } + } + }); + + return activateCurrent(answer); + } + + export function createProjectSettingsSubNavBars(projectName, jenkinsJobId = null) { + if (!projectName) { + return []; + } + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName); + if (!jenkinsJobId) { + jenkinsJobId = projectName; + } + var answer = [ + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, "buildConfigEdit"), + label: "Core", + title: "View the core build configuration" + }, + { + href: projectSecretsLink(workspaceName, projectName), + label: "Secrets", + title: "View or change the secrets used to edit source code in the source control system" + }, + { + href: editPipelineLink(workspaceName, projectName), + label: "Pipeline", + title: "View the DevOps and pipeline configuration" + }, + { + isValid: () => forgeProjectHasBuilder("maven"), + href: editMavenBuildLink(workspaceName, projectName), + label: "Maven", + title: "View the Maven build configuration" + } + ]; + return activateCurrent(answer); + } + + export function forgeProjectHasBuilder(name) { + var forgeProject = Kubernetes.inject("ForgeProject"); + if (forgeProject) { + return forgeProject.hasBuilder(name); + } + return false; + } + + export function forgeProjectHasPerspective(name) { + var forgeProject = Kubernetes.inject("ForgeProject"); + if (forgeProject) { + return forgeProject.hasPerspective(name); + } + return false; + } + + export function editPipelineLinkScope($scope) { + return editPipelineLink($scope.namespace, $scope.projectId || $scope.projectName || $scope.project); + } + + export function createProjectLink(workspaceName = null) { + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "/forge/createProject"); + } + + export function editPipelineLink(workspaceName, projectName) { + return projectWorkspaceLink(workspaceName, projectName, "forge/command/devops-edit"); + } + + export function editMavenBuildLink(workspaceName, projectName) { + return projectWorkspaceLink(workspaceName, projectName, "forge/command/fabric8-setup"); + } + + export function projectSecretsLink(workspaceName, projectName) { + return projectWorkspaceLink(workspaceName, projectName, "forge/secrets", false); + } + + export function secretsNamespaceLink(workspaceName, projectName, secretsNamespace) { + var prefix = projectWorkspaceLink(workspaceName, projectName, "") || "kubernetes"; + return UrlHelpers.join(prefix, "namespace", secretsNamespace, "secrets"); + } + + export function projectWorkspaceLink(workspaceName, projectName, path, ignoreBlankProject = true) { + if (ignoreBlankProject && !projectName) { + return ""; + } + if (!workspaceName) { + workspaceName = Kubernetes.currentKubernetesNamespace(); + } + return UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", projectName, path); + } + + export var customProjectSubTabFactories = []; + + export function createJenkinsBreadcrumbs(projectName, jobId, buildId) { + var workspaceName = Kubernetes.currentKubernetesNamespace(); + var children = [ + { + id: "builds", + href: createBuildsLink(workspaceName, projectName, jobId), + label: "Builds", + title: "View the builds for this app" + } + ]; + if (buildId) { + children.push({ + id: "", + href: "", + label: "#" + buildId, + title: "Build #" + buildId + }); + } + return createProjectBreadcrumbs(projectName, children); + } + + export function createJenkinsSubNavBars(projectName, jenkinsJobId, buildId, extraOption: any = null) { + var answer = createProjectSubNavBars(projectName, jenkinsJobId); + if (extraOption) { + extraOption.active = true; + answer.push(extraOption); + } + return answer; + } + + + export function createEnvironmentSubNavBars($scope, $location, $routeParams) { + var ns = Kubernetes.currentKubernetesNamespace(); + var workspaceName = $routeParams.workspace; + var project = $routeParams.project; + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes"); + if (workspaceName && project) { + projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", project); + } + var namespacesLink = UrlHelpers.join(projectLink, "namespace"); + return activateCurrent([ + { + href: UrlHelpers.join(projectLink, "environments"), + label: "<< Back To App", + title: "Go back to the Dashboard for this App", + isValid: () => project + }, + { + href: UrlHelpers.join(namespacesLink, ns, "apps"), + label: "Overview", + class: "fa fa-list", + title: "Overview of all the apps for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "services"), + label: "Services", + class: "fa fa-plug", + title: "View the apps for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "replicationControllers"), + label: "Controllers", + class: "fa fa-clone", + title: "View the Replication Controllers for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "pods"), + label: "Pods", + class: "fa fa-puzzle-piece", + title: "View the pods for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "events"), + label: "Events", + class: "fa fa-newspaper-o", + title: "View the events for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "secrets"), + label: "Secrets", + class: "fa fa-key", + title: "View the secrets for this project" + }, + { + href: UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes/hosts"), + label: "Nodes", + class: "fa fa-server", + title: "View the nodes for this project" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "overview"), + label: "Diagram", + class: "fa fa-sitemap", + title: "View all the objects in this project and their relationship" + }, + { + href: UrlHelpers.join(namespacesLink, ns, "angryPods"), + label: "Angry Pods", + class: "fa fa-gamepad", + title: "Try the Angry Pods game!" + }, + ]); + } + + + export function namespaceLink($scope, $routeParams, path = null) { + var ns = Kubernetes.currentKubernetesNamespace(); + var workspaceName = $routeParams.workspace; + var project = $routeParams.project; + var projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/kubernetes"); + if (workspaceName && project) { + projectLink = UrlHelpers.join(HawtioCore.documentBase(), "/workspaces", workspaceName, "projects", project); + } + return UrlHelpers.join(projectLink, "namespace", ns, path); + } + + /** + * Removes the URL query string if its inside the given text + */ + function trimQuery(text) { + if (text) { + var idx = text.indexOf("?"); + if (idx >= 0) { + return text.substring(0, idx); + } + } + return text; + } + + function activateCurrent(navBarItems) { + navBarItems = _.compact(navBarItems); + var injector = HawtioCore.injector; + var $location = injector ? injector.get("$location") : null; + if ($location) { + var path = trimQuery($location.path()); + var found = false; + function makeActive(item) { + item.active = true; + found = true; + } + angular.forEach(navBarItems, (item) => { + if (item) { + if (angular.isFunction(item.isActive)) { + if (!found && item.isActive(item, path)) { + makeActive(item); + } + } else { + var href = item.href; + var trimHref = trimQuery(href); + if (!found && trimHref && trimHref === path) { + makeActive(item); + } + } + } + }); + } + return navBarItems; + } + + function processChildren(answer, children) { + if (children) { + if (angular.isArray(children)) { + answer = answer.concat(children); + } else { + answer.push(children); + } + } + activateCurrent(answer); + return answer; + } +} diff --git a/plugins/developer/ts/developerPlugin.ts b/plugins/developer/ts/developerPlugin.ts new file mode 100644 index 0000000..c5b175e --- /dev/null +++ b/plugins/developer/ts/developerPlugin.ts @@ -0,0 +1,78 @@ +/// +/// + +module Developer { + + export var _module = angular.module(pluginName, ['hawtio-core', 'hawtio-ui', 'ui.codemirror', 'nvd3', 'treeControl']); + export var controller = PluginHelpers.createControllerFunction(_module, pluginName); + export var route = PluginHelpers.createRoutingFunction(templatePath); + + _module.config(['$routeProvider', ($routeProvider:ng.route.IRouteProvider) => { + $routeProvider.when(context, route('workspaces.html', false)) + .when("/namespaces", route('workspaces.html', false)) + //.when("/home", route('home.html', false)) + .when(UrlHelpers.join(context, '/:namespace'), route('projects.html', false)) + .when(UrlHelpers.join(context, '/:namespace/detail'), route('workspace.html', false)) + .when(UrlHelpers.join(context, '/:namespace/jenkinsJob'), route('jenkinsJobs.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects'), route('projects.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id'), route('environments.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/detail'), Kubernetes.route('buildConfig.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/builds'), Kubernetes.route('builds.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/environments'), route('environments.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/jenkinsJob/:job'), route('jenkinsJob.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/jenkinsJob/:job/log/:build'), route('jenkinsLog.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/jenkinsJob/:job/pipelines'), route('pipelines.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/jenkinsJob/:job/pipeline/:build'), route('pipeline.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/jenkinsJob/:job/metrics'), route('jenkinsMetrics.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/jenkinsMetrics'), route('jenkinsMetrics.html', false)) + .when(UrlHelpers.join(context, '/:namespace/projects/:id/tools'), route('tools.html', false)) + .when(UrlHelpers.join(context, '/:workspace/projects/:project/environments/:namespace'), route('environment.html', false)) + .when(UrlHelpers.join(context, '/:workspace/projects/:project/environments/:namespace'), route('environment.html', false)) + .when(UrlHelpers.join(context, '/Aggregate/overview'), route('addDataFile.html', false)) + .otherwise("/workspaces"); + }]); + + + _module.run(['viewRegistry', 'ServiceRegistry', 'HawtioNav', 'KubernetesModel', '$templateCache', 'DataInfoModel',(viewRegistry, ServiceRegistry, HawtioNav, KubernetesModel, $templateCache, DataInfoModel) => { + log.debug("Running"); + viewRegistry['workspaces'] = Kubernetes.templatePath + 'layoutKubernetes.html'; + viewRegistry['namespaces'] = Kubernetes.templatePath + 'layoutKubernetes.html'; + + var builder = HawtioNav.builder(); + var workspaces = builder.id('workspaces') + .href(() => context) + .title(() => '查看') + .build(); +/* + var workspaceOverview = builder.id('workspaces') + .href(() => UrlHelpers.join(context, 'overview')) + .title(() => 'Workspace') + .build(); +*/ +/* var dataadd = builder.id('dataadd') + .href(() => context) + .title(() => '汇总') + .build(); +*/ + var Aggregate = builder.id('Aggregate;') + .rank(200) + .href(() => context) + .title(() => '数据汇总') + //.isValid(() => !Core.isRemoteConnection()) + .tabs(workspaces) + .build(); + + HawtioNav.add(Aggregate); + }]); + + _module.filter('asTrustedHtml', ['$sce', function ($sce) { + return function (text) { + return $sce.trustAsHtml(text); + }; + }]); + + hawtioPluginLoader.addModule(pluginName); + + // for scroll-glue directive + hawtioPluginLoader.addModule('luegg.directives'); +} diff --git a/plugins/developer/ts/environmentPanel.ts b/plugins/developer/ts/environmentPanel.ts new file mode 100644 index 0000000..69585d6 --- /dev/null +++ b/plugins/developer/ts/environmentPanel.ts @@ -0,0 +1,22 @@ +/// + +module Developer { + _module.controller('Developer.EnvironmentPanelController', ($scope, $element, $location, $routeParams, KubernetesModel:Kubernetes.KubernetesModelService, $http, $timeout, KubernetesState, KubernetesApiURL) => { + + $scope.envVersions = {}; + $scope.model = KubernetesModel; + $scope.env = $scope.$eval('env'); + $scope.buildConfig = $scope.$eval('entity'); + + $scope.open = true; + + $scope.toggle = () => $scope.open = !$scope.open; + + var caches = {}; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + loadProjectVersions($scope, $element, $scope.buildConfig, $scope.env, $scope.env.namespace, $scope.envVersions, caches); + + }); +} diff --git a/plugins/developer/ts/home.ts b/plugins/developer/ts/home.ts new file mode 100644 index 0000000..ee12c47 --- /dev/null +++ b/plugins/developer/ts/home.ts @@ -0,0 +1,17 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var HomeController = controller("HomeController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.namespace = Kubernetes.currentKubernetesNamespace(); + + }]); +} diff --git a/plugins/developer/ts/jenkinsJob.ts b/plugins/developer/ts/jenkinsJob.ts new file mode 100644 index 0000000..a8a7271 --- /dev/null +++ b/plugins/developer/ts/jenkinsJob.ts @@ -0,0 +1,94 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var JenkinsJobController = controller("JenkinsJobController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $routeParams["job"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.tableConfig = { + data: 'job.builds', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '$sortOrder', + displayName: 'Name', + cellTemplate: $templateCache.get("jenkinsBuildIdTemplate.html") + }, + { + field: '$buildLink', + displayName: 'Views', + cellTemplate: $templateCache.get("jenkinsBuildButtonsTemplate.html") + }, + { + field: '$duration', + displayName: 'Duration', + cellTemplate: $templateCache.get("jenkinsBuildDurationTemplate.html") + }, + { + field: '$timestamp', + displayName: 'Time Started', + cellTemplate: $templateCache.get("jenkinsBuildTimestampTemplate.html") + } + ] + }; + updateData(); + + + function updateData() { + if ($scope.jobId) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, UrlHelpers.join("job", $scope.jobId, "api/json?depth=1")); + if (url && (!$scope.job || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + enrichJenkinsJob(data, $scope.id, $scope.jobId); + if (hasObjectChanged(data, $scope.entityChangedCache)) { + log.info("entity has changed!"); + $scope.job = data; + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } else { + $scope.model.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/developer/ts/jenkinsJobs.ts b/plugins/developer/ts/jenkinsJobs.ts new file mode 100644 index 0000000..66dd4e2 --- /dev/null +++ b/plugins/developer/ts/jenkinsJobs.ts @@ -0,0 +1,101 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var JenkinsJobsController = controller("JenkinsJobsController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.jenkins = null; + $scope.entityChangedCache = {}; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = createProjectBreadcrumbs(); + $scope.subTabConfig = Developer.createWorkspaceSubNavBars(); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.tableConfig = { + data: 'jenkins.jobs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'name', + displayName: 'Name', + cellTemplate: $templateCache.get("jenkinsJobNameTemplate.html") + }, + { + field: '$buildLink', + displayName: 'Views', + cellTemplate: $templateCache.get("jenkinsJobButtonsTemplate.html") + }, + { + field: '$lastSuccessfulBuildNumber', + displayName: 'Last Success', + cellTemplate: $templateCache.get("jenkinsLastSuccessTemplate.html") + }, + { + field: '$lastFailedlBuildNumber', + displayName: 'Last Failure', + cellTemplate: $templateCache.get("jenkinsLastFailureTemplate.html") + }, + { + field: '$duration', + displayName: 'Last Duration', + cellTemplate: $templateCache.get("jenkinsBuildDurationTemplate.html") + }, + { + field: '$timestamp', + displayName: 'Time Started', + cellTemplate: $templateCache.get("jenkinsBuildTimestampTemplate.html") + } + ] + }; + updateData(); + + + function updateData() { + // TODO only need depth 2 to be able to fetch the lastBuild + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, "api/json?depth=2"); + log.info(""); + if (url && (!$scope.jenkins || Kubernetes.keepPollingModel)) { + $http.get(url, jenkinsHttpConfig). + success(function (data, status, headers, config) { + if (data) { + enrichJenkinsJobs(data, $scope.id, $scope.id); + if (hasObjectChanged(data, $scope.entityChangedCache)) { + log.info("entity has changed!"); + $scope.jenkins = data; + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + }]); +} diff --git a/plugins/developer/ts/jenkinsLog.ts b/plugins/developer/ts/jenkinsLog.ts new file mode 100644 index 0000000..38e58a9 --- /dev/null +++ b/plugins/developer/ts/jenkinsLog.ts @@ -0,0 +1,350 @@ +/// +/// +/// +/// +/// +/// +/// +/// + +module Developer { + + export function clickApprove(element, url) { + var $scope: any = angular.element(element).scope(); + if ($scope) { + $scope.approve(url, element.text); + } + } + + export var JenkinsLogController = _module.controller("Developer.JenkinsLogController", ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, $modal, KubernetesApiURL, ServiceRegistry, $element) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + $scope.selectedBuild = $scope.$eval('build') || $scope.$eval('selectedBuild'); + + $scope.id = $scope.$eval('build.id') || $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + + $element.on('$destroy', () => { + $scope.$destroy(); + }); + + $scope.log = { + html: "", + start: 0, + firstIdx: null + }; + + $scope.$on('kubernetesModelUpdated', function () { + updateJenkinsLink(); + Core.$apply($scope); + }); + + $scope.$on('jenkinsSelectedBuild', (event, build) => { + log.info("==== jenkins build selected! " + build.id + " " + build.$jobId); + $scope.selectedBuild = build; + }); + + + $scope.$watch('selectedBuild', (selectedBuild) => { + log.info("Selected build updated: ", selectedBuild); + $scope.fetch(); + }); + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = createJenkinsBreadcrumbs($scope.id, getJobId(), getBuildId()); + $scope.subTabConfig = createJenkinsSubNavBars($scope.id, getJobId(), getBuildId(), { + label: "Log", + title: "Views the logs of this build" + }); + + function getJobId() { + // lets allow the parent scope to be used too for when this is used as a panel + return $routeParams["job"] || ($scope.selectedBuild || {}).$jobId; + } + $scope.getJobId = getJobId; + + function getBuildId() { + // lets allow the parent scope to be used too for when this is used as a panel + return $routeParams["build"] || ($scope.selectedBuild || {}).id; + } + $scope.getBuildId = getBuildId; + + function updateJenkinsLink() { + var jenkinsUrl = jenkinsLink(); + if (jenkinsUrl) { + $scope.$viewJenkinsBuildLink = UrlHelpers.join(jenkinsUrl, "job", getJobId(), getBuildId()); + $scope.$viewJenkinsLogLink = UrlHelpers.join($scope.$viewJenkinsBuildLink, "console"); + } + } + + var querySize = 50000; + + $scope.approve = (url, operation) => { + var modal = $modal.open({ + templateUrl: UrlHelpers.join(templatePath, 'jenkinsApproveModal.html'), + controller: ['$scope', '$modalInstance', ($scope, $modalInstance) => { + $scope.operation = operation; + $scope.header = operation + "?"; + $scope.ok = () => { + modal.close(); + postToJenkins(url, operation); + }; + $scope.cancel = () => { + modal.dismiss(); + }; + }] + }); + }; + + function postToJenkins(uri, operation) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, uri); + if (url) { + var body = null; + var config = { + headers: { + } + }; + log.info("posting to jenkinsUrl: " + url); + $http.post(url, body, config). + success(function (data, status, headers, config) { + log.info("Managed to " + operation + " at " + url); + }). + error(function (data, status, headers, config) { + log.warn("Failed " + operation + " job at " + url + " " + data + " " + status); + }); + } else { + log.warn("Cannot post to jenkins URI: " + uri + " as no jenkins found!"); + } + } + + $scope.$keepPolling = () => Kubernetes.keepPollingModel; + + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + if ($scope.$eval('hideLogs && !build.building')) { + log.debug("Log hidden, not fetching logs"); + return; + } else { + log.debug("Fetching logs for build: ", $scope.$eval('build')); + } + var buildId = getBuildId(); + var jobId = getJobId(); + //log.info("=== jenkins log querying job " + jobId + " build " + buildId + " selected build " + $scope.selectedBuild); + if (jobId && buildId) { + if ($scope.buildId !== buildId || $scope.jobId !== jobId) { + // lets clear the query + $scope.log = { + html: "", + start: 0, + firstIdx: null + }; + } + $scope.buildId = buildId; + $scope.jobId = jobId; + + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, UrlHelpers.join("job", jobId, buildId, "fabric8/logHtml?tail=1&start=" + $scope.log.start + "&size=" + querySize)); + if ($scope.log.firstIdx !== null) { + url += "&first=" + $scope.log.firstIdx; + } + if (url && (!$scope.log.fetched || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + var replaceClusterIPsInHtml = replaceClusterIpFunction(); + + if (!$scope.log.logs) { + $scope.log.logs = []; + } + var lines = data.lines; + var returnedLength = data.returnedLength; + var logLength = data.logLength; + var returnedStart = data.start; + var earlierLog = false; + if (angular.isDefined(returnedStart)) { + earlierLog = returnedStart < $scope.log.start; + } + var lineSplit = data.lineSplit; + // log.info("start was: " + $scope.log.start + " first: " + $scope.log.firstIdx + " => returnedLength: " + returnedLength + " logLength: " + logLength + " returnedStart: " + returnedStart + " earlierLog: " + earlierLog + " lineSplit: " + lineSplit); + if (lines) { + var currentLogs = $scope.log.logs; + + // lets re-join split lines + if (lineSplit && currentLogs.length) { + var lastIndex; + var restOfLine; + if (earlierLog) { + lastIndex = 0; + restOfLine = lines.pop(); + if (restOfLine) { + currentLogs[lastIndex] = replaceClusterIPsInHtml(restOfLine + currentLogs[lastIndex]); + } + } else { + lastIndex = currentLogs.length - 1; + restOfLine = lines.shift(); + if (restOfLine) { + currentLogs[lastIndex] = replaceClusterIPsInHtml(currentLogs[lastIndex] + restOfLine); + } + } + } + for (var i = 0; i < lines.length; i++) { + lines[i] = replaceClusterIPsInHtml(lines[i]); + } + if (earlierLog) { + $scope.log.logs = lines.concat(currentLogs); + } else { + $scope.log.logs = currentLogs.concat(lines); + } + } + var moveForward = true; + if (angular.isDefined(returnedStart)) { + if (returnedStart > $scope.log.start && $scope.log.start === 0) { + // we've jumped to the end of the file to read the tail of it + $scope.log.start = returnedStart; + $scope.log.firstIdx = returnedStart; + } else if ($scope.log.firstIdx === null) { + // lets remember where the first request started + $scope.log.firstIdx = returnedStart; + } else if (returnedStart < $scope.log.firstIdx) { + // we've got an earlier bit of the log + // after starting at the tail + // so lets move firstIdx backwards and leave start as it is (at the end of the file) + $scope.log.firstIdx = returnedStart; + moveForward = false; + } + } + if (moveForward && returnedLength && !earlierLog) { + $scope.log.start += returnedLength; + if (logLength && $scope.log.start > logLength) { + $scope.log.start = logLength; + } + } + updateJenkinsLink(); + } + $scope.log.fetched = true; + // Core.$apply($scope); + next(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + next(); + }); + } + } else { + $scope.log.fetched = true; + Core.$apply($scope); + next(); + } + }); + + if (angular.isFunction($scope.fetch)) { + $scope.fetch(); + } + + + function replaceClusterIpFunction() { + function createReplaceFunction(from, to) { + return (text) => replaceText(text, from, to); + } + + var replacements = []; + angular.forEach($scope.model.services, (service) => { + var $portalIP = service.$portalIP; + var $serviceUrl = service.$serviceUrl; + var $portsText = service.$portsText; + if ($portalIP && $serviceUrl) { + var idx = $serviceUrl.indexOf("://"); + if (idx > 0) { + var replaceWith = $serviceUrl.substring(idx, $serviceUrl.length); + if (!replaceWith.endsWith("/")) { + replaceWith += "/"; + } + if (replaceWith.length > 4) { + replacements.push(createReplaceFunction( + "://" + $portalIP + "/", + replaceWith + )); + if ($portsText) { + var suffix = ":" + $portsText; + var serviceWithPort = replaceWith.substring(0, replaceWith.length - 1); + if (!serviceWithPort.endsWith(suffix)) { + serviceWithPort += suffix; + } + serviceWithPort += "/"; + replacements.push(createReplaceFunction( + "://" + $portalIP + ":" + $portsText + "/", + serviceWithPort + )); + } + } + } + } + }); + + function addReplaceFn(from, to) { + replacements.push((text) => { + return replaceText(text, from, to); + }); + + } + addReplaceFn("[INFO]", "[INFO]"); + addReplaceFn("[WARN]", "[WARN]"); + addReplaceFn("[WARNING]", "[WARNING]"); + addReplaceFn("[ERROR]", "[ERROR]"); + addReplaceFn("FAILURE", "FAILURE"); + addReplaceFn("SUCCESS", "SUCCESS"); + + // lets try convert the Proceed / Abort links + replacements.push((text) => { + var prefix = "= 0) { + idx = text.indexOf(prefix, idx); + if (idx >= 0) { + var start = idx + prefix.length; + var endQuote = text.indexOf("'", start + 1); + if (endQuote <= 0) { + break; + } + var endDoubleQuote = text.indexOf('"', endQuote + 1); + if (endDoubleQuote <= 0) { + break; + } + var url = text.substring(start, endQuote); + // TODO using $compile is a tad complex, for now lets cheat with a little onclick ;) + //text = text.substring(0, idx) + " { + answer = fn(answer); + }); + return answer; + } + } + + function replaceText(text, from, to) { + if (from && to && text) { + //log.info("Replacing '" + from + "' => '" + to + "'"); + var idx = 0; + while (true) { + idx = text.indexOf(from, idx); + if (idx >= 0) { + text = text.substring(0, idx) + to + text.substring(idx + from.length); + idx += to.length; + } else { + break; + } + } + } + return text; + } + }); + +} diff --git a/plugins/developer/ts/jenkinsMetrics.ts b/plugins/developer/ts/jenkinsMetrics.ts new file mode 100644 index 0000000..f3b426a --- /dev/null +++ b/plugins/developer/ts/jenkinsMetrics.ts @@ -0,0 +1,181 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var JenkinsMetricsController = controller("JenkinsMetricsController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $routeParams["job"]; + $scope.schema = KubernetesSchema; + $scope.jenkins = null; + $scope.entityChangedCache = {}; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.options = { + chart: { + type: 'discreteBarChart', + autorefresh: false, + height: 450, + margin: { + top: 20, + right: 20, + bottom: 60, + left: 45 + }, + clipEdge: true, + staggerLabels: false, + transitionDuration: 500, + stacked: false, + interactive: true, + tooltip: { + enabled: true, + contentGenerator: (args) => { + var data = args.data || {}; + return data.tooltip; + }, + }, + color: (d, i) => { + return d.color; + }, + xAxis: { + axisLabel: 'Builds', + showMaxMin: false, + tickFormat: function (d) { + return "#" + d; + } + }, + yAxis: { + axisLabel: 'Build Duration (seconds)', + tickFormat: function (d) { + return d3.format(',.1f')(d); + } + } + } + }; + + $scope.data = []; + + updateData(); + + function barColourForBuildResult(result) { + if (result) { + if (result === "FAILURE" || result === "FAILED") { + return "red"; + } else if (result === "ABORTED" || result === "INTERUPTED") { + return "tan"; + } else if (result === "SUCCESS") { + return "green"; + } else if (result === "NOT_STARTED") { + return "lightgrey" + } + } + return "darkgrey"; + } + + + function updateChartData() { + var useSingleSet = true; + var buildsSucceeded = []; + var buildsFailed = []; + var successBuildKey = "Succeeded builds"; + var failedBuildKey = "Failed builds"; + + if (useSingleSet) { + successBuildKey = "Builds"; + } + + var count = 0; + var builds = _.sortBy($scope.metrics.builds || [], "number"); + angular.forEach(builds, (build:any) => { + var x = build.number; + var y = build.duration / 1000; + var date = Developer.asDate(build.timeInMillis); + var result = build.result || "NOT_STARTED"; + var color = barColourForBuildResult(result); + var iconClass = createBuildStatusIconClass(result); + var tooltip = '

' + build.displayName + '

' + + '

duration: ' + y + ' seconds

'; + if (date) { + tooltip += '

started: ' + date + '

'; + } + if (result) { + tooltip += '

result: ' + result + '

'; + } + + if (x) { + var data = buildsSucceeded; + var key = successBuildKey; + if (!successBuildKey && (!result || !result.startsWith("SUCC"))) { + data = buildsFailed; + key = failedBuildKey; + } + data.push({ + tooltip: tooltip, + color: color, + x: x, y: y}); + } + }); + $scope.data = []; + if (buildsSucceeded.length) { + $scope.data.push({ + key: successBuildKey, + values: buildsSucceeded + }); + } + if (buildsFailed.length) { + $scope.data.push({ + key: failedBuildKey, + values: buildsFailed + }); + } + $scope.api.updateWithData($scope.data); + + $timeout(() => { + $scope.api.update(); + }, 50); + } + + function updateData() { + var metricsPath = $scope.jobId ? UrlHelpers.join("job", $scope.jobId, "fabric8/metrics") : "fabric8/metrics"; + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, metricsPath); + log.info(""); + if (url && (!$scope.jenkins || Kubernetes.keepPollingModel)) { + $http.get(url, jenkinsHttpConfig). + success(function (data, status, headers, config) { + if (data) { + if (hasObjectChanged(data, $scope.entityChangedCache)) { + log.info("entity has changed!"); + $scope.metrics = data; + updateChartData(); + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + }]); +} diff --git a/plugins/developer/ts/navbar.ts b/plugins/developer/ts/navbar.ts new file mode 100644 index 0000000..9d89c87 --- /dev/null +++ b/plugins/developer/ts/navbar.ts @@ -0,0 +1,25 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var NavBarController = controller("NavBarController", + ["$scope", "$location", "$routeParams", "$timeout", "KubernetesApiURL", + ($scope, $location:ng.ILocationService, $routeParams, $timeout) => { + + $scope.isValid = (item) => { + if (item) { + var value = item.isValid; + if (angular.isFunction(value)) { + return value(item) + } else { + return angular.isUndefined(value) || value; + } + } + return false; + } + }]); +} diff --git a/plugins/developer/ts/pipeline.ts b/plugins/developer/ts/pipeline.ts new file mode 100644 index 0000000..0ad6662 --- /dev/null +++ b/plugins/developer/ts/pipeline.ts @@ -0,0 +1,67 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var PipelineController = controller("PipelineController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "ServiceRegistry", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.kubeModel = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $routeParams["job"]; + $scope.buildId = $routeParams["build"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + + $scope.model = { + stages: null + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + if ($scope.jobId) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, UrlHelpers.join("job", $scope.jobId, $scope.buildId, "fabric8/stages/")); + if (url && (!$scope.model.stages || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + enrichJenkinsStages(data, $scope.id, $scope.jobId); + if (hasObjectChanged(data, $scope.entityChangedCache)) { + log.info("entity has changed!"); + $scope.build = data; + $scope.model.stages = data.stages; + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + $scope.model.fetched = true; + }); + } + } else { + $scope.model.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/developer/ts/pipelineDirective.ts b/plugins/developer/ts/pipelineDirective.ts new file mode 100644 index 0000000..ab5df1d --- /dev/null +++ b/plugins/developer/ts/pipelineDirective.ts @@ -0,0 +1,13 @@ +/// +/// +/// +/// +/// + +module Developer { + _module.directive("pipelineView", () => { + return { + templateUrl: templatePath + 'pipelineView.html' + }; + }); +} diff --git a/plugins/developer/ts/pipelines.ts b/plugins/developer/ts/pipelines.ts new file mode 100644 index 0000000..ebee92e --- /dev/null +++ b/plugins/developer/ts/pipelines.ts @@ -0,0 +1,165 @@ +/// +/// +/// +/// +/// +/// + +module Developer { + + export var PipelinesController = _module.controller("Developer.PipelinesController", ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, ServiceRegistry, $element) => { + + $scope.kubernetes = KubernetesState; + $scope.kubeModel = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.jobId = $scope.jobId || $routeParams["job"]; + $scope.schema = KubernetesSchema; + $scope.entityChangedCache = {}; + + $element.on('$destroy', () => { + $scope.$destroy(); + }); + + $scope.model = { + job: null, + pendingOnly: $scope.pendingPipelinesOnly + }; + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, $scope.jobId); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.$watch('model.pendingOnly', ($event) => { + updateData(); + }); + + $scope.selectBuild = (build) => { + var id = build.id; + if (id) { + if (id !== $scope.selectedBuildId) { + $scope.selectedBuildId = id; + $scope.$broadcast("jenkinsSelectedBuild", build); + } + } + }; + + var updateData = _.debounce(() => { + var entity = $scope.entity; + if ($scope.jobId) { + if ((!entity || entity.$jenkinsJob)) { + var queryPath = "fabric8/stages/"; + if ($scope.model.pendingOnly) { + queryPath = "fabric8/pendingStages/"; + } + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, UrlHelpers.join("job", $scope.jobId, queryPath)); + if (url && (!$scope.model.job || Kubernetes.keepPollingModel)) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + enrichJenkinsPipelineJob(data, $scope.id, $scope.jobId); + if (hasObjectChanged(data, $scope.entityChangedCache)) { + log.info("entity has changed!"); + $scope.model.job = data; + + var builds = data.builds; + if (builds && builds.length) { + $scope.selectBuild(builds[0]); + } + } + } + $scope.model.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + $scope.model.fetched = true; + }); + } + } else { + if ($scope.model) { + Kubernetes.enrichBuilds($scope.kubeModel.builds); + + var builds = []; + angular.forEach($scope.kubeModel.builds, (build) => { + var labels = Kubernetes.getLabels(build); + var app = labels["app"]; + if (app === $scope.projectId) { + builds.push(build); + } + }); + builds = _.sortBy(builds, "$creationDate").reverse(); + var allBuilds = builds; + if (allBuilds.length > 1) { + builds = _.filter(allBuilds, (b) => !b.$creationDate); + if (!builds.length) { + builds = [allBuilds[0]]; + } + } + var pipelines = []; + angular.forEach(builds, (build) => { + var buildStatus = build.status || {}; + var result = buildStatus.phase || ""; + var resultUpperCase = result.toUpperCase(); + + var description = ""; + var $viewLink = build.$viewLink; + var $logLink = build.$logsLink; + var $timestamp = build.$creationDate; + var duration = buildStatus.duration; + if (duration) { + // 17s = 17,000,000,000 on openshift + duration = duration / 1000000; + } + var displayName = Kubernetes.getName(build); + var $iconClass = createBuildStatusIconClass(resultUpperCase); + var $backgroundClass = createBuildStatusBackgroundClass(resultUpperCase); + var stage = { + stageName: "OpenShift Build", + $viewLink: $viewLink, + $logLink: $logLink, + $startTime: $timestamp, + duration: duration, + status: result, + $iconClass: $iconClass, + $backgroundClass: $backgroundClass + }; + var pipeline = { + description: description, + displayName: displayName, + $viewLink: $viewLink, + $logLink: $logLink, + $timestamp: $timestamp, + duration: duration, + stages: [stage] + }; + pipelines.push(pipeline); + }); + + // lets filter the OpenShift builds and make a pipeline from that + $scope.model.job = { + $jobId: $scope.jobId, + $project: $scope.projectId, + builds: pipelines + }; + } + $scope.model.fetched = true; + Core.$apply($scope); + } + } else { + $scope.model.fetched = true; + Core.$apply($scope); + } + }, 50); + + updateData(); + + }); +} diff --git a/plugins/developer/ts/project.ts b/plugins/developer/ts/project.ts new file mode 100644 index 0000000..af6930b --- /dev/null +++ b/plugins/developer/ts/project.ts @@ -0,0 +1,95 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var ProjectController = controller("ProjectController", + ["$scope", "$element", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, $element, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_BuildConfig; + $scope.entityChangedCache = {}; + $scope.envVersionsCache = {}; + $scope.envNSCaches = {}; + $scope.envVersions = {}; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = []; //Developer.createProjectBreadcrumbs($scope.id); + updateTabs(); + // this is used for the pendingPipelines view + $scope.jobId = $scope.id; + $scope.pendingPipelinesOnly = true; + + $scope.$on('jenkinsSelectedBuild', (event, build) => { + $scope.selectedBuild = build; + }); + + // TODO this should be unnecessary but seems sometiems this watch doesn't always trigger unless you hit reload on this page + if ($scope.model.buildconfigs) { + onBuildConfigs($scope.model.buildconfigs); + } + Kubernetes.watch($scope, $element, "buildconfigs", $scope.namespace, onBuildConfigs); + + function onBuildConfigs(buildConfigs) { + angular.forEach(buildConfigs, (data) => { + var name = Kubernetes.getName(data); + if (name === $scope.id) { + var sortedBuilds = null; + Kubernetes.enrichBuildConfig(data, sortedBuilds); + if (hasObjectChanged(data, $scope.entityChangedCache)) { + log.info("entity has changed!"); + $scope.entity = data; + $scope.entity.$build = (data.$fabric8CodeViews || {})['fabric8.link.browseGogs.view']; + $scope.model.setProject($scope.entity); + } + updateEnvironmentWatch(); + updateTabs(); + } + }); + $scope.model.fetched = true; + Core.$apply($scope); + } + + + /** + * We have updated the entity so lets make sure we are watching all the environments to find + * the project versions for each namespace + */ + function updateEnvironmentWatch() { + var project = $scope.entity; + if (project) { + var jenkinsJob = project.$jenkinsJob; + if (jenkinsJob) { + var buildsTab = _.find($scope.subTabConfig, {id: "builds"}); + if (buildsTab) { + buildsTab["href"] = UrlHelpers.join("/workspaces", Kubernetes.currentKubernetesNamespace(), "projects", $scope.id, "jenkinsJob", jenkinsJob); + } + } + + angular.forEach(project.environments, (env) => { + var ns = env.namespace; + var caches = $scope.envNSCaches[ns]; + if (!caches) { + caches = {}; + $scope.envNSCaches[ns] = caches; + loadProjectVersions($scope, $element, project, env, ns, $scope.envVersions, caches); + } + }); + } + } + + function updateTabs() { + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, null, $scope); + } + + }]); +} diff --git a/plugins/developer/ts/projectSelector.ts b/plugins/developer/ts/projectSelector.ts new file mode 100644 index 0000000..9f46543 --- /dev/null +++ b/plugins/developer/ts/projectSelector.ts @@ -0,0 +1,19 @@ +/// + +module Developer { + + _module.controller('Developer.ProjectSelector', ['$scope', '$routeParams', 'KubernetesModel', ($scope, $routeParams, KubernetesModel) => { + var projectId = $routeParams['projectId'] || $routeParams['project'] || $routeParams['id']; + if (projectId) { + $scope.projectId = projectId; + $scope.model = KubernetesModel + $scope.$watch('model.buildconfigs', (buildconfigs) => { + $scope.projects = buildconfigs; + }); + } else { + log.info("no project ID in routeParams: ", $routeParams); + } + }]); + +} + diff --git a/plugins/developer/ts/projects.ts b/plugins/developer/ts/projects.ts new file mode 100644 index 0000000..f85d78a --- /dev/null +++ b/plugins/developer/ts/projects.ts @@ -0,0 +1,171 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var ProjectsController = controller("ProjectsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + $scope.tableConfig = { + data: 'model.buildconfigs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '$name', + displayName: 'Name', + cellTemplate: $templateCache.get("idTemplate.html") + }, +/* + { + field: 'spec.source.type', + displayName: 'Source' + }, +*/ + { + field: 'spec.source.git.uri', + displayName: 'Repository' + }, +/* + { + field: 'spec.strategy.type', + displayName: 'Strategy' + }, + { + field: 'spec.strategy.stiStrategy.image', + displayName: 'Source Image' + }, + { + field: 'spec.output.imageTag', + displayName: 'Output Image' + }, +*/ + { + field: 'metadata.description', + displayName: 'Description' + }, + { + field: '$creationDate', + displayName: 'Created', + cellTemplate: $templateCache.get("creationTimeTemplate.html") + }, + { + field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.breadcrumbConfig = createProjectBreadcrumbs(); + $scope.subTabConfig = Developer.createWorkspaceSubNavBars(); + + // TODO + //$scope.isLoggedIntoGogs = Forge.isLoggedIntoGogs; + + $scope.deletePrompt = (selected) => { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, () => { + deleteSelected(selected, selected.shift()); + }); + } else { + // TODO + // updateData(); + } + } + + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Apps', + action: 'The following Apps will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + var jenkinsJob = selection.$jenkinsJob; + var publicJenkinsUrl = jenkinsLink(); + //var jenkinsUrl = Core.pathGet(selection, ["$fabric8Views", "fabric8.link.jenkins.job", "url"]); + if (name) { + console.log("About to delete build config: " + name); + var url = Kubernetes.buildConfigRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to delete build config on " + url + " " + data + " " + status); + nextCallback(); + }); + } else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + + if (jenkinsJob && publicJenkinsUrl) { + var url = Kubernetes.kubernetesProxyUrlForServiceCurrentNamespace(jenkinsServiceNameAndPort, UrlHelpers.join("job", jenkinsJob, "doDelete")); + var body = ""; + var config = { + headers: { + 'Content-Type': "text/plain" + } + }; + log.info("posting to jenkinsUrl: " + url); + $http.post(url, body, config). + success(function (data, status, headers, config) { + log.info("Managed to delete " + url); + }). + error(function (data, status, headers, config) { + log.warn("Failed to delete jenkins job at " + url + " " + data + " " + status); + }); + } + } + +/* + $scope.$keepPolling = () => Kubernetes.keepPollingModel; + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + var url = Kubernetes.buildConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + var sortedBuilds = null; + $scope.buildConfigs = Kubernetes.enrichBuildConfigs(data.items, sortedBuilds); + $scope.model.fetched = true; + Core.$apply($scope); + next(); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + next(); + }); + }); + + $scope.fetch(); +*/ + }]); +} diff --git a/plugins/developer/ts/workspace.ts b/plugins/developer/ts/workspace.ts new file mode 100644 index 0000000..af4e032 --- /dev/null +++ b/plugins/developer/ts/workspace.ts @@ -0,0 +1,53 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var WorkspaceController = controller("WorkspaceController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["namespace"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.kubernetes_Namespace; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = createWorkspaceBreadcrumbs(); + $scope.subTabConfig = Developer.createWorkspaceSubNavBars(); + + $scope.$keepPolling = () => Kubernetes.keepPollingModel; + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + $scope.item = null; + if ($scope.id) { + var url = UrlHelpers.join(Kubernetes.resourcesUriForKind("Projects"), $scope.id); + log.info("Loading url: " + url); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = enrichWorkspace(data); + } + $scope.model.fetched = true; + Core.$apply($scope); + next(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + next(); + }); + } else { + $scope.model.fetched = true; + Core.$apply($scope); + next(); + + } + }); + + $scope.fetch(); + }]); +} diff --git a/plugins/developer/ts/workspaces.ts b/plugins/developer/ts/workspaces.ts new file mode 100644 index 0000000..24d9b5e --- /dev/null +++ b/plugins/developer/ts/workspaces.ts @@ -0,0 +1,454 @@ +/// +/// +/// +/// +/// + +module Developer { + + export var WorkspacesController = controller("WorkspacesController", + ["$scope", "OracleStatusModel", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "DataInfoModel", "$interval", + ($scope, OracleStatusModel, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, DataInfoModel,$interval) => { + $scope.model = DataInfoModel; + $scope.items=[]; + + $scope.localitems=[]; + var rootPath=""; + var FilterList ={ + length:0 + }; + + update(); + + $scope.treeOptions = { + nodeChildren: "children", + dirSelectable: true, + multiSelection: false, + injectClasses: { + ul: "a1", + li: "a2", + liSelected: "a7", + iExpanded: "a3", + iCollapsed: "a4", + iLeaf: "a5", + label: "a6", + labelSelected: "a8" + } + }; + + $scope.treeOptionss = { + nodeChildren: "children", + dirSelectable: true, + multiSelection: true, + injectClasses: { + ul: "a1", + li: "a2", + liSelected: "a7", + iExpanded: "a3", + iCollapsed: "a4", + iLeaf: "a5", + label: "a6", + labelSelected: "a8" + } + }; + + $scope.showSelected = (node,selected)=>{ + + $scope.model.serveritems = []; + var array = new Array(); + if(selected){ + if(node.children.length > 0){ + array.unshift(node); + while(array.length > 0){ + var childNode=array.pop(); + if(childNode.children.length>0){ + for(var i=0;i { + FilterList.length=0; + if(files.length>0){ + var j=0; + for(var i=0;i"); + var provinceValue = provinceValueTemp[provinceValueTemp.length-1].split("")[0]; + //city + var cityValueTemp = itemvalue[0].split(""); + var cityValue = cityValueTemp[cityValueTemp.length-1].split("")[0]; + // county + var countyValueTemp = itemvalue[0].split(""); + var countyValue = countyValueTemp[countyValueTemp.length-1].split("")[0]; + // + var codeValueTemp = itemvalue[0].split(""); + var codeValue = codeValueTemp[codeValueTemp.length-1].split("")[0]; + // + var sys_nameValueTemp = itemvalue[0].split(""); + var sys_nameValue = sys_nameValueTemp[sys_nameValueTemp.length-1].split("")[0]; + // + var character_setValueTemp = itemvalue[0].split(""); + var character_setValue = character_setValueTemp[character_setValueTemp.length-1].split("")[0]; + // + var sys_name_codeValueTemp = itemvalue[0].split(""); + var sys_name_codeValue = sys_name_codeValueTemp[sys_name_codeValueTemp.length-1].split("")[0]; + // + var contactValueTemp = itemvalue[0].split(""); + var contactValue = contactValueTemp[contactValueTemp.length-1].split("")[0]; + // + var phoneValueTemp = itemvalue[0].split(""); + var phoneValue = phoneValueTemp[phoneValueTemp.length-1].split("")[0]; + // + var dateValueTemp = itemvalue[0].split(""); + var dateValue = dateValueTemp[dateValueTemp.length-1].split("")[0]; + + //id : + var itemId = codeValue + "_" + sys_name_codeValue; + // http get version + var rid = itemId//.replace(/\"/g, ""); + + // TODO typeValue 通过前端页面获取或者??,财政01或社保02 + var typeValue = "01"; + // TODO batchValue 通过前端页面获取或者??,批次A :大写的A,批次B :大写的B, + var batchValue = "A"; + + var itemname = cityValue + countyValue + sys_nameValue; + var versionid = 1; + var xhr = new XMLHttpRequest(); + + xhr.onreadystatechange=function(){ + if(xhr.readyState==4){ + if(xhr.status==200){ + versionid = xhr.responseText; + } + } + } + xhr.open("get","/getversion?id="+rid, false); + xhr.send(null); + + var jsobj = JSON.parse(versionid); + var xmlversion = jsobj.id; + + var properValue = "{\"id\":\""+itemId+"\", \"name\":\""+itemname+"\", \"city\":\""+ + cityValue + "\", \"county\":\""+countyValue+"\", \"system\":\""+ + sys_nameValue+"\", \"type\":\"" + typeValue + "\",\"batch\":\""+ + batchValue+"\",\"version\":\""+xmlversion+"\", \"province\":\""+ + provinceValue +"\", \"code\":\""+ + codeValue +"\", \"character_set\":\""+ + character_setValue +"\", \"sys_name_code\":\""+ + sys_name_codeValue +"\", \"contact\":\""+ + contactValue +"\", \"phone\":\""+ + phoneValue +"\", \"date\":\""+ + dateValue +"\"}"; + resultString = resultString + properValue; + if(k < itemsize-1){ + resultString =resultString+", " + } + } + resultString = resultString+"]}"; + } + $scope.$apply(function(){ + $scope.model.localdata = JSON.parse(resultString.toString()); + }); + + } + reader.readAsText(files[i],"utf-8"); + } + else{ + FilterList.length+=1; + var file_id=files[i].name.replace(/\.\w*$/,''); + // var file_id=file[i].webkitRelativePath.replace(/^[a-z]*\/$/,''); + // file_id = file_id.replace(/\/\w+$/,''); + FilterList[j++]=files[i]; + } + } + } + $scope.model.uploadprocess = {}; + } + + $scope.upLoadFiles = ()=>{ + if($scope.model.uploadedStatus == "once"){ + return; + } + $scope.model.uploadedStatus = "once"; + $scope.model.createFolderList(FilterList,rootPath); + if($scope.model.folderList.length >0 && $scope.model.selectednodes.length >0){ + var isNotExited = []; + var isExited = []; + for(var node in $scope.model.selectednodes){ + if(!$scope.model.folderList.hasOwnProperty($scope.model.selectednodes[node].id)){ + isNotExited.push($scope.model.selectednodes[node]); + }else{ + if($scope.model.uploadprocess[$scope.model.selectednodes[node].id] === 'undefined' || $scope.model.uploadprocess[$scope.model.selectednodes[node].id] === 0) + isExited.push($scope.model.selectednodes[node]); + } + } + if(isNotExited.length >0 ){ + var str = "以下数据文件不存在:\n\r文件名:\n"; + for(var item in isNotExited) + str += isNotExited[item].id+"\n"; + alert(str); + } + + if(isExited.length <=0){ + alert("数据文件中没有可用上传的文件!"); + }else{ + var isuploaad = 1,i = 0; + var timerForUpload = setInterval(function(){ + if(i >= isExited.length){ + clearInterval(timerForUpload); + } + if(isuploaad == 1){ + var r = new Resumable({ + target:'/uploadfiles', + chunkSize:50*1024*1024, + simultaneousUploads:400, + testChunks:true, + throttleProgressCallbacks:1 + }); + + var xhr = new XMLHttpRequest(); + xhr.open("GET","/getclientip",true); + xhr.onreadystatechange=function(){ + if(xhr.readyState==4){ + if(xhr.status==200){ + r.setip(xhr.responseText); + } + } + } + xhr.send(null); + + r.on('fileAdded', function(file){ + r.upload(); + }); + + $scope.model.resumablejs.push({ + dirname : isExited[i].id, + resumable : r + }); + + r.setRootPath(isExited[i].type+"/"+isExited[i].batch+"/"+isExited[i].id+"/"+isExited[i].version+"/"); + + r.myLoadFiles($scope.model.folderList[isExited[i].id]); + r.upload(); + + r.on('fileProgress',function(file){ + var file_id=file.relativePath.replace(/^[a-z]*\/$/,''); + var filestr = ""; + var reg = /\/[0-9]*_*[0-9]*\//g; + var resultstr; + while( (resultstr = reg.exec(file_id)) != null){ + filestr = resultstr[0]; + } + file_id = filestr.replace(/\/*/g,''); + r.setFileId(file_id); + //$scope.$apply(function(){ + $scope.model.uploadprocess[file_id] = Math.floor(r.progress()*98); + //}); + + }); + + r.on('complete', function(){ + var timerForchmod = setInterval(function(){ + var pathjson = "\"path\":\""+r.getrootPath()+"\"" + var datamessage = {"path":r.getrootPath(),"filenum":$scope.model.folderList[isExited[i-1].id].length}; + $scope.model.uploadprocess[r.getFileId()] = Math.round(r.progress()*99); + + $http({ + url:'/setchmod2dir', + method:'GET', + params:datamessage + }).success(function(data,header,config,status){ + if(data){ + //console.log(data); + var clientdata = data; + if(clientdata == "chmod"){ + sendDateMessage(isExited[i-1]); + r.setisnowcheck("1"); + r.mkRetfileUploadSucceed(); + clearInterval(timerForchmod); + } + } + + }).error(function(data,header,config,status){ + console.log("-----sendDateMessage-------------"+status); + }); + + },5000); + }); + + i++; + isuploaad = 0; + + r.on('fileuploadendsucceed', function(){ + $scope.model.uploadprocess[r.getFileId()] = Math.floor(r.progress()*100); + $timeout(() => { + $http({ + url:'/xmlformserver', + method:'Post' + }).success(function(data,header,config,status){ + if(data){ + $scope.model.serverdata = data; + } + }).error(function(data,header,config,status){ + console.log("error"); + }); + },2000); + isuploaad = 1; + }); + } + },2000); + } + }else{ + alert("您没有选择需要上传的数据文件,或你选择的文件中不存在指定格式的数据文件!"); + } + + } + + function sendDateMessage(datamessage){ + $http({ + url:'/sendDateMessage', + method:'GET', + params:datamessage + }).success(function(data,header,config,status){ + if(data) + var clientdata = data; + }).error(function(data,header,config,status){ + + }); + } + + $scope.downLoadFiles = ()=>{ + Kubernetes.connectOracle($http, $timeout, "192.168.0.103:64182", "320614-54-1", 500); + } + + $scope.isSelected= (node)=>{ + var index = $scope.model.findItemIndex(node); + if(index !== -1){ + $scope.model.selecteditems.splice(index,1); + } + else{ + $scope.model.selecteditems.push(node); + } + } + + $scope.showSelectedLocal = (node,selected) => { + var index = $scope.model.findNodes(node); + if(index !== "-1"){ + if($scope.model.uploadprocess[node.id] ===0) + $scope.model.selectednodes.splice(index,1); + }else{ + $scope.model.uploadprocess[node.id] =0; + $scope.model.selectednodes.push(node); + } + } + + $scope.startOracle = ()=> { + if($scope.model.selecteditems.length >0){ + for(var id in $scope.model.selecteditems){ + var Obj = createRCObj($scope.model.selecteditems[id]); + if(!checkIsRunning(KubernetesModel.replicationControllers,Obj)){ + Kubernetes.createRC(Obj, (rc) =>{ + console.log(rc.metadata.name); + Kubernetes.connectOracle($http, $timeout, "/connectToOracle", "", rc.metadata.name, 0); + }); + } + } + } + } + + function checkIsRunning(replicationControllers,item){ + for(var rc in replicationControllers){ + if(item.name === replicationControllers[rc].metadata.name) + return true; + } + return false; + } + + function createRCObj(item: Object){ + var array =item.id.split("_"); + return { + "name": array[2] + "-" + array[3] + "-" + array[4], + "labels": { + "type": array[0], + "batch": array[1], + "region": array[2], + "system": array[3], + "version": array[4] + }, + "path": item.path +"app/" + } + } + + function setchmod2dir(datamessage){ + $http({ + url:'/setchmod2dir', + method:'GET', + params:datamessage + }).success(function(data,header,config,status){ + if(data) + var clientdata = data; + }).error(function(data,header,config,status){ + console.log("-----sendDateMessage-------------"+status); + }); + } + + function update(){ + for(var i=0; i<$scope.model.resumablejs.length; i++){ + var dirId = $scope.model.resumablejs[i].dirname; + var r = $scope.model.resumablejs[i].resumable; + r.on('fileProgress', (file) =>{ + $scope.$apply(function(){ + $scope.model.uploadprocess[dirId] = Math.floor(r.progress()*100); + console.log(dirId+":"+Math.floor(r.progress()*100)) + }); + }); + } + } + }]); +} diff --git a/plugins/includes.ts b/plugins/includes.ts new file mode 100644 index 0000000..450f9ce --- /dev/null +++ b/plugins/includes.ts @@ -0,0 +1,9 @@ +/// +/// +/// +/// +/// + +declare var humandate; +declare var jsyaml:any; + diff --git a/plugins/kubernetes/html/appDeployedTemplate.html b/plugins/kubernetes/html/appDeployedTemplate.html new file mode 100644 index 0000000..b19b1a6 --- /dev/null +++ b/plugins/kubernetes/html/appDeployedTemplate.html @@ -0,0 +1,3 @@ +
+ {{row.entity.$creationDate ? (row.entity.$creationDate | relativeTime) : ''}} +
diff --git a/plugins/kubernetes/html/appDetailTemplate.html b/plugins/kubernetes/html/appDetailTemplate.html new file mode 100644 index 0000000..77b5aa3 --- /dev/null +++ b/plugins/kubernetes/html/appDetailTemplate.html @@ -0,0 +1,149 @@ +
diff --git a/plugins/kubernetes/html/appIconTemplate.html b/plugins/kubernetes/html/appIconTemplate.html new file mode 100644 index 0000000..193b5d5 --- /dev/null +++ b/plugins/kubernetes/html/appIconTemplate.html @@ -0,0 +1,10 @@ + diff --git a/plugins/kubernetes/html/appPodCountsAndLinkTemplate.html b/plugins/kubernetes/html/appPodCountsAndLinkTemplate.html new file mode 100644 index 0000000..cd84ac2 --- /dev/null +++ b/plugins/kubernetes/html/appPodCountsAndLinkTemplate.html @@ -0,0 +1,9 @@ + diff --git a/plugins/kubernetes/html/appReplicationControllerTemplate.html b/plugins/kubernetes/html/appReplicationControllerTemplate.html new file mode 100644 index 0000000..ee6ea83 --- /dev/null +++ b/plugins/kubernetes/html/appReplicationControllerTemplate.html @@ -0,0 +1,14 @@ + diff --git a/plugins/kubernetes/html/appServicesTemplate.html b/plugins/kubernetes/html/appServicesTemplate.html new file mode 100644 index 0000000..5607d95 --- /dev/null +++ b/plugins/kubernetes/html/appServicesTemplate.html @@ -0,0 +1,8 @@ + diff --git a/plugins/kubernetes/html/apps.html b/plugins/kubernetes/html/apps.html new file mode 100644 index 0000000..4b31d4a --- /dev/null +++ b/plugins/kubernetes/html/apps.html @@ -0,0 +1,175 @@ +
+ +
+
+
+ +
+
+
+ +
+
+
+ + + + +
+ + + + +
+
+   + +   + +   + +   + +
+
+
+
+
+
+ +
+
+
+
+

There are no apps currently available.

+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
    +
  • + +
  • +
+
+
+
+
+ +   + +   + +
+
+ + +
+ +
    +
  • + + {{app.name}} +   + +
  • +
+
+
+
+
+ +
diff --git a/plugins/kubernetes/html/breadcrumbs.html b/plugins/kubernetes/html/breadcrumbs.html new file mode 100644 index 0000000..836f177 --- /dev/null +++ b/plugins/kubernetes/html/breadcrumbs.html @@ -0,0 +1,10 @@ +
+ +
diff --git a/plugins/kubernetes/html/build.html b/plugins/kubernetes/html/build.html new file mode 100644 index 0000000..fb938e6 --- /dev/null +++ b/plugins/kubernetes/html/build.html @@ -0,0 +1,46 @@ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/buildConfig.html b/plugins/kubernetes/html/buildConfig.html new file mode 100644 index 0000000..9b70fac --- /dev/null +++ b/plugins/kubernetes/html/buildConfig.html @@ -0,0 +1,42 @@ +
+
+
+
+ +
+
+
+ +
+
+   + + Edit + + +   + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/buildConfigEdit.html b/plugins/kubernetes/html/buildConfigEdit.html new file mode 100644 index 0000000..58765d2 --- /dev/null +++ b/plugins/kubernetes/html/buildConfigEdit.html @@ -0,0 +1,62 @@ +
+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+
+ + + +

+ Project name must be a lower case DNS name with letters, numbers and dots or dashes such as `example.com` +

+
+
+
+
+
+ + + +
+
+
+
+
+
diff --git a/plugins/kubernetes/html/buildConfigs.html b/plugins/kubernetes/html/buildConfigs.html new file mode 100644 index 0000000..49d746e --- /dev/null +++ b/plugins/kubernetes/html/buildConfigs.html @@ -0,0 +1,122 @@ +
+ + + + + + +
+
+ + + + +   + Add Build +   + + + Create Project + +   + + + Sign In + +   + + +
+
+
+
+
+
+ +
+
+
+
+

There are no build configurations available.

+ Add Build Configuration +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/buildLogs.html b/plugins/kubernetes/html/buildLogs.html new file mode 100644 index 0000000..183788d --- /dev/null +++ b/plugins/kubernetes/html/buildLogs.html @@ -0,0 +1,45 @@ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+

logs for {{entity.$configId}}

+ +

+

+            
+              {{logsText}}
+            
+          
+

+
+
+
+
diff --git a/plugins/kubernetes/html/builds.html b/plugins/kubernetes/html/builds.html new file mode 100644 index 0000000..c2249e0 --- /dev/null +++ b/plugins/kubernetes/html/builds.html @@ -0,0 +1,111 @@ +
+ + + + + + + + +
+
+
+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+
+ +
+
+
+
+

There are no builds currently running.

+
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/deploymentConfig.html b/plugins/kubernetes/html/deploymentConfig.html new file mode 100644 index 0000000..860acea --- /dev/null +++ b/plugins/kubernetes/html/deploymentConfig.html @@ -0,0 +1,21 @@ +
+
+
+   + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/deploymentConfigs.html b/plugins/kubernetes/html/deploymentConfigs.html new file mode 100644 index 0000000..7cbfd24 --- /dev/null +++ b/plugins/kubernetes/html/deploymentConfigs.html @@ -0,0 +1,67 @@ +
+ + +
+
+ + + + +   + Create +   + +
+
+
+
+
+
+ +
+
+
+
+

There are no deployment configurations available.

+ Create Deployment Configuration +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/events.html b/plugins/kubernetes/html/events.html new file mode 100644 index 0000000..cd06da2 --- /dev/null +++ b/plugins/kubernetes/html/events.html @@ -0,0 +1,72 @@ +
+ +
+
+
+ +
+
+
+ +
+
+ + + +   + + +
+
+
+
+
+
+ +
+
+
+
+

There are no events currently available.

+
+
+
+
+
+ +
+
+
+
+ + + +
+
+ +

+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/host.html b/plugins/kubernetes/html/host.html new file mode 100644 index 0000000..5e9b2c6 --- /dev/null +++ b/plugins/kubernetes/html/host.html @@ -0,0 +1,61 @@ +
+
+
+
+ +
+
+
+ +
+
+   + + {{rawMode ? 'Form' : 'Raw'}} + Edit +   + + Save +   + +   + + Pods + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
diff --git a/plugins/kubernetes/html/hosts.html b/plugins/kubernetes/html/hosts.html new file mode 100644 index 0000000..7860fcd --- /dev/null +++ b/plugins/kubernetes/html/hosts.html @@ -0,0 +1,43 @@ +
+ + +
+
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+
+ +
+
+
+
+

There are no hosts currently running.

+
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/imageRepositories.html b/plugins/kubernetes/html/imageRepositories.html new file mode 100644 index 0000000..fe31642 --- /dev/null +++ b/plugins/kubernetes/html/imageRepositories.html @@ -0,0 +1,51 @@ +
+ +
+
+ + + + +   + Create +
+
+
+
+
+
+ +
+
+
+
+

There are no image repositories available.

+ Create Image Repository +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/importProject.html b/plugins/kubernetes/html/importProject.html new file mode 100644 index 0000000..c874c84 --- /dev/null +++ b/plugins/kubernetes/html/importProject.html @@ -0,0 +1,58 @@ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+ +

+ Create a project by entering or copy/pasting the Git URL for a repository, and give the project a name. By default the name will be based on the repository name. +

+ +
+ +
+
+
+
+
+ + + +

+ Project name must be a lower case DNS name with letters, numbers and dots or dashes such as `example.com` +

+

Name of this project

+
+
+
+
+
+ +
+
+
+
+
diff --git a/plugins/kubernetes/html/kubernetesJsonDirective.html b/plugins/kubernetes/html/kubernetesJsonDirective.html new file mode 100644 index 0000000..a33a6b7 --- /dev/null +++ b/plugins/kubernetes/html/kubernetesJsonDirective.html @@ -0,0 +1,32 @@ +
+
+
+
+ +
+ +
+
+

 {{displayName || appTitle}}

+
+
+ +
+
+
+
+
+ +
+
+ +
diff --git a/plugins/kubernetes/html/layoutKubernetes.html b/plugins/kubernetes/html/layoutKubernetes.html new file mode 100644 index 0000000..237cede --- /dev/null +++ b/plugins/kubernetes/html/layoutKubernetes.html @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
diff --git a/plugins/kubernetes/html/logShell.html b/plugins/kubernetes/html/logShell.html new file mode 100644 index 0000000..8ffbff8 --- /dev/null +++ b/plugins/kubernetes/html/logShell.html @@ -0,0 +1,15 @@ +
+
+
+ +
+
+
{{containerName}} logs
+ + + +
+
+ +
+
diff --git a/plugins/kubernetes/html/overview.html b/plugins/kubernetes/html/overview.html new file mode 100644 index 0000000..fe77e1c --- /dev/null +++ b/plugins/kubernetes/html/overview.html @@ -0,0 +1,117 @@ +
+ + + + + + +
+
+
+ +
+
+
+ + +
diff --git a/plugins/kubernetes/html/pendingPipelines.html b/plugins/kubernetes/html/pendingPipelines.html new file mode 100644 index 0000000..3724708 --- /dev/null +++ b/plugins/kubernetes/html/pendingPipelines.html @@ -0,0 +1,20 @@ +
+
+
+
+
+
+
+
+
+

No Pipeline Available

+

Pipeline is a kind of build which uses Jenkins Workflow internally which has multiple Stages. You will see the active pipelines here after you add a build to this project

+
+
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/pipelines.html b/plugins/kubernetes/html/pipelines.html new file mode 100644 index 0000000..7e05ba7 --- /dev/null +++ b/plugins/kubernetes/html/pipelines.html @@ -0,0 +1,131 @@ +
+ +
+
+ + + + Create Project +
+
+
+
+
+
+ +
+
+
+
+

There are no build pipelines available.

+ Create Build Configuration +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+ +
+ + + + {{step.buildConfig.metadata.name}} + + +     + + + + build + + + +
+
+ + new: {{step.buildConfig.$lastBuild.$creationDate.relative()}} + + + pending: {{step.buildConfig.$lastBuild.$creationDate.relative()}} + + + running {{step.buildConfig.$lastBuild.$creationDate.relative()}} + + + completed {{step.buildConfig.$lastBuild.$creationDate.relative()}} + + + failed {{step.buildConfig.$lastBuild.$creationDate.relative()}} + + + {{step.buildConfig.$lastBuild.status}}: {{step.buildConfig.$lastBuild.$creationDate.relative()}} + +
+
+ +
+
+ +
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/pod.html b/plugins/kubernetes/html/pod.html new file mode 100644 index 0000000..2dc30c9 --- /dev/null +++ b/plugins/kubernetes/html/pod.html @@ -0,0 +1,88 @@ +
+ +
+
+
+ +
+
+
+ +
+
+ + + +  {{item.metadata.name}} + + + +   + + +   + + + {{rawMode ? 'Form' : 'Raw'}} +   + + Edit +   + + Save +   + + + Events + +   + +
+   + + Connect + +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
diff --git a/plugins/kubernetes/html/podCreate.html b/plugins/kubernetes/html/podCreate.html new file mode 100644 index 0000000..dee5c90 --- /dev/null +++ b/plugins/kubernetes/html/podCreate.html @@ -0,0 +1,27 @@ +
+
+
+   + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/podEdit.html b/plugins/kubernetes/html/podEdit.html new file mode 100644 index 0000000..f28688c --- /dev/null +++ b/plugins/kubernetes/html/podEdit.html @@ -0,0 +1,27 @@ +
+
+
+   + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/pods.html b/plugins/kubernetes/html/pods.html new file mode 100644 index 0000000..061d9dc --- /dev/null +++ b/plugins/kubernetes/html/pods.html @@ -0,0 +1,87 @@ +
+ + + + + +
+
+
+ +
+
+
+ +
+
+ + + + +   + +   + +   + 创建新服务 +   + +
+
+
+
+ +
+
+ +
+
+
+
+

There are no pods currently running.

+
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/replicationController.html b/plugins/kubernetes/html/replicationController.html new file mode 100644 index 0000000..c28210c --- /dev/null +++ b/plugins/kubernetes/html/replicationController.html @@ -0,0 +1,89 @@ +
+ +
+
+
+ +
+
+
+ +
+
+ +  {{item.metadata.name}} + + + +   + + +   + + {{rawMode ? 'Form' : 'Raw'}} +   + + Edit +   + + Save +   + + + Events + + +     + + + Scale + + + Pods: + + {{item.$podCounters.ready}} + {{item.$podCounters.valid}} + {{item.$podCounters.waiting}} + {{item.$podCounters.error}} + + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + +
diff --git a/plugins/kubernetes/html/replicationControllerCreate.html b/plugins/kubernetes/html/replicationControllerCreate.html new file mode 100644 index 0000000..1e1d48a --- /dev/null +++ b/plugins/kubernetes/html/replicationControllerCreate.html @@ -0,0 +1,27 @@ +
+
+
+   + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/replicationControllerEdit.html b/plugins/kubernetes/html/replicationControllerEdit.html new file mode 100644 index 0000000..6b89264 --- /dev/null +++ b/plugins/kubernetes/html/replicationControllerEdit.html @@ -0,0 +1,27 @@ +
+
+
+   + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/replicationControllers.html b/plugins/kubernetes/html/replicationControllers.html new file mode 100644 index 0000000..ec7de3c --- /dev/null +++ b/plugins/kubernetes/html/replicationControllers.html @@ -0,0 +1,88 @@ +
+ + + +
+
+
+ +
+
+
+ +
+
+ + + + +   + + +   + + +   + + +   + 创建 +   + +
+
+
+
+
+
+ +
+
+
+
+

当前没有正在运行的oracle服务.

+
+
+
+
+
+
+
+ +
diff --git a/plugins/kubernetes/html/secret.html b/plugins/kubernetes/html/secret.html new file mode 100644 index 0000000..8d01f93 --- /dev/null +++ b/plugins/kubernetes/html/secret.html @@ -0,0 +1,157 @@ +
+
+
+
+ +
+
+
+ +
+
+ +   + +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ + +
+ + + There is already a secret with that name! + +
+
+ +
+ + +
+ + +
+ +
+ +
+
+
+ + +
+
+
+ + + +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
diff --git a/plugins/kubernetes/html/secrets.html b/plugins/kubernetes/html/secrets.html new file mode 100644 index 0000000..d372756 --- /dev/null +++ b/plugins/kubernetes/html/secrets.html @@ -0,0 +1,52 @@ +
+
+
+
+ +
+
+
+ +
+
+ + + + +   + + Create + + +
+
+
+
+
+
+ +
+
+
+
+

There are no secrets currently available.

+
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/service.html b/plugins/kubernetes/html/service.html new file mode 100644 index 0000000..923085d --- /dev/null +++ b/plugins/kubernetes/html/service.html @@ -0,0 +1,68 @@ +
+
+
+
+ +
+
+
+ +
+
+ +  {{item.metadata.name}} + + + +   + + + + {{rawMode ? 'Form' : 'Raw'}} +   + + Edit +   + + Save +   + + + Connect + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
diff --git a/plugins/kubernetes/html/serviceApps.html b/plugins/kubernetes/html/serviceApps.html new file mode 100644 index 0000000..0384b7c --- /dev/null +++ b/plugins/kubernetes/html/serviceApps.html @@ -0,0 +1,16 @@ + diff --git a/plugins/kubernetes/html/serviceCreate.html b/plugins/kubernetes/html/serviceCreate.html new file mode 100644 index 0000000..9c3a01d --- /dev/null +++ b/plugins/kubernetes/html/serviceCreate.html @@ -0,0 +1,27 @@ +
+
+
+   + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/serviceEdit.html b/plugins/kubernetes/html/serviceEdit.html new file mode 100644 index 0000000..cf3f2a2 --- /dev/null +++ b/plugins/kubernetes/html/serviceEdit.html @@ -0,0 +1,27 @@ +
+
+
+   + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/services.html b/plugins/kubernetes/html/services.html new file mode 100644 index 0000000..8e07006 --- /dev/null +++ b/plugins/kubernetes/html/services.html @@ -0,0 +1,93 @@ +
+ +
+
+
+ +
+
+
+ +
+
+ + + + +
+ + + + +
+
+   + +   + +   + Create +   + +
+
+
+
+
+
+ +
+
+
+
+

There are no services currently available.

+
+
+
+
+
+ +
+
+
+
+ + + +
+
+ +

+
+
+ +
+
+
+
+
+
+
+
diff --git a/plugins/kubernetes/html/tabs.html b/plugins/kubernetes/html/tabs.html new file mode 100644 index 0000000..0574b08 --- /dev/null +++ b/plugins/kubernetes/html/tabs.html @@ -0,0 +1,13 @@ + diff --git a/plugins/kubernetes/html/templateDescription.html b/plugins/kubernetes/html/templateDescription.html new file mode 100644 index 0000000..883c580 --- /dev/null +++ b/plugins/kubernetes/html/templateDescription.html @@ -0,0 +1,9 @@ + + + diff --git a/plugins/kubernetes/html/templates.html b/plugins/kubernetes/html/templates.html new file mode 100644 index 0000000..efcc1b3 --- /dev/null +++ b/plugins/kubernetes/html/templates.html @@ -0,0 +1,90 @@ +
+ + +
+
+
+ +
+
+
+ + +
+
+ + + + + +   + +   + + Target namespace: + + +
+
+
+
+
+ There are no templates currently available. Add templates by dragging and dropping template files into this area. +
+
+
+
+
+
+
+
+ +
+
+

+
+
+ +
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
diff --git a/plugins/kubernetes/html/termShell.html b/plugins/kubernetes/html/termShell.html new file mode 100644 index 0000000..c7d5553 --- /dev/null +++ b/plugins/kubernetes/html/termShell.html @@ -0,0 +1,9 @@ +
+
+
+ + +
+
+
+
diff --git a/plugins/kubernetes/less/appView.less b/plugins/kubernetes/less/appView.less new file mode 100644 index 0000000..6bf9c85 --- /dev/null +++ b/plugins/kubernetes/less/appView.less @@ -0,0 +1,108 @@ +/* This is for the 'Overview' page with all the rows of boxes */ +.service-view-rectangle { + position: relative; + margin-left: 0; + margin-right: 0px; + margin-bottom: 15px; + margin-top: 0; + background-color: #fafafa; + + border-width: 1px; + border-style: solid; + border-color: #eeeeee; + + .service-view-header { + margin-top: 5px; + margin-bottom: 5px; + line-height: 20px; + vertical-align: middle; + } + .service-view-detail-pod-box { + background-color: #eeeeee; + display: inline-block; + font-size: smaller; + } + .service-view-header-delete .red { + opacity: 0.5; + transition: opacity 1s; + font-size: larger; + } + .service-view-header-delete:hover .red { + opacity: 1; + } + .service-view-icon img { + width: 32px; + height: 32px; + margin-right: 6px; + } + .service-view-name { + font-size: larger; + font-weight: bold; + } + .service-view-detail-header { + padding-top: 5px; + padding-bottom: 5px; + line-height: 20px; + } + .service-view-detail-rectangle { + background-color: #eeeeee; + padding-left: 10px; + padding-right: 10px; + } + .service-view-detail-rectangle .value { + font-weight: bold; + } + .service-view-detail-pod-summary, + .service-view-detail-pod-summary-expand { + display: inline-block; + + padding-top: 2px; + padding-bottom: 2px; + padding-left: 20px; + padding-right: 20px; + + margin-right: 8px; + margin-bottom: 8px; + + background-color: #ffffff; + } + + .service-view-detail-pod-summary table td, + .service-view-detail-pod-summary-expand table td { + padding-left: 10px; + padding-right: 10px; + } + + .service-view-detail-pod-template { + } + + .service-view-detail-pod-counts { + } + + .service-view-detail-pod-status, .service-view-detail-pod-connect { + line-height: 36px; + padding-right: 20px; + } + + .service-view-detail-pod-status i, .service-view-detail-pod-connect i { + font-size: 36px; + display: inline-block; + vertical-align: middle; + } + + .service-view-detail-pod-expand { + color: #a0a0a0; + font-size: 18px; + padding-right: 0px; + } + + .service-view-detail-pod-id { + } + + +} + +.kubernetes-view .filter-header { + margin-bottom: 1em; +} + diff --git a/plugins/kubernetes/less/overview.less b/plugins/kubernetes/less/overview.less new file mode 100644 index 0000000..60bb7f2 --- /dev/null +++ b/plugins/kubernetes/less/overview.less @@ -0,0 +1,173 @@ +/* This is all for the diagram, not the 'Overview' page */ +.kubernetes-overview { + width: 100%; + height: 100%; + display: table; + table-layout: fixed; +} +.kubernetes-overview-row { + display: table-row; +} +.kubernetes-overview-cell { + display: table-cell; + text-align: center; + vertical-align: middle; + padding: 0; +} +.service-wrapper { + display: block; + vertical-align: middle; +} +.kubernetes-node { + margin-left: auto; + margin-right: auto; + cursor: pointer; + text-align: center; + vertical-align: middle; + border: 1px solid #d4d4d4; + background: white; + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + border-radius: 4px; + transition: background 0.5s; + z-index: 1000; +} + +.kubernetes-host-container { + margin-top: 5px; + margin-bottom: 5px; + margin-left: auto; + margin-right: auto; + text-align: center; + max-width: 600px; + min-width: 300px; + padding: 0; + border: 1px solid #d4d4d4; + background: white; + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + border-radius: 4px; +} + +.kubernetes-pod-node { + display: block; + margin: 0; + padding: 0; + min-height: 48px; + line-height: 48px; + border-radius: 0; + border: 1px solid transparent; + border-top: 1px solid #d4d4d4; + box-shadow: none; + vertical-align: middle; +} + +.css-table { + display: table; + width: 100%; + height: 100%; +} + +.css-table-row { + display: table-row; + + .pod-status-cell { + // width: 30%; + text-align: left; + padding-left: 5px; + padding-right: 5px; + + i { + margin-left: 3px; + margin-right: 3px; + } + .clickable { + width: auto !important; + } + } + // height: inherit; +} + +.css-table-cell { + display: table-cell; + vertical-align: middle; +} + +.kubernetes-pod-node i { + font-size: 24px; +} + +.kubernetes-overview-services { + width: 200px; +} + +.kubernetes-service-node { + display: block; + margin-bottom: 10px; + width: 200px; + min-height: 66px; + padding: 0; + line-height: 48px; + + .node-body { + display: inline; + padding-left: 10px; + line-height: 64px; + font-size: 20px; + float: left; + } + + .node-header { + display: inline; + float: right; + } + +} + +.node-header { + padding-right: 10px; + white-space: nowrap; + line-height: 64px; + overflow: hidden; + text-overflow: ellipsis; +} + +.kubernetes-replicationController-node { + border-radius: 64px; + display: block; + width: 64px; + height: 64px; + padding: 7px; + font-weight: bold; + vertical-align: middle; + overflow: hidden; + text-overflow: ellipsis; +} + +.kubernetes-overview-cell .app-icon-medium { + width: 48px; + height: 48px; +} + +.kubernetes-replicationController-node img { + width: 64px; +} + +.kubernetes-node:hover, +.kubernetes-node.hovered { + background: #ddddff; +} + +.pod-status-cell { + width: 80px; + line-height: 20px; +} + +.pod-label-cell { + float: right; + text-align: right; + min-height: 48px; +} + +.pod-label-cell .ngCellText { + white-space: normal; +} + diff --git a/plugins/kubernetes/less/podLog.less b/plugins/kubernetes/less/podLog.less new file mode 100644 index 0000000..5f426ad --- /dev/null +++ b/plugins/kubernetes/less/podLog.less @@ -0,0 +1,31 @@ +.pod-log-lines * { + padding-left: 5px; + padding-right: 5px; + font-family: monospace; + margin: 0; + line-height: 14px; + .black { + color: #222; + } + .red { + color: #f22; + } + .green { + color: #2f2; + } + .yellow { + color: #ff2; + } + .blue { + color: #22f; + } + .purple { + color: #f2f; + } + .cyan { + color: #2dd; + } + .white { + color: #ddd; + } +} diff --git a/plugins/kubernetes/less/terminalWindow.less b/plugins/kubernetes/less/terminalWindow.less new file mode 100644 index 0000000..2ff9d6b --- /dev/null +++ b/plugins/kubernetes/less/terminalWindow.less @@ -0,0 +1,84 @@ +.terminal-window { + position: fixed; + bottom: 0; + background: white; + border: 1px solid #d4d4d4; + overflow: hidden; + z-index: 1040; + + .resize-dot { + width: 16px; + height: 16px; + border: 1px solid #d4d4d4; + background: white; + position: absolute; + bottom: 10px; + right: 10px; + cursor: nwse-resize; + border-radius: 8px; + z-index: 10000; + } + + &.minimized .resize-dot, + &.maximized .resize-dot { + display: none; + } + + &.minimized .terminal-title, + &.maximized .terminal-title { + cursor: inherit; + } + + .terminal-body { + overflow: auto; + .terminal-wrapper > .terminal * { + font-family: 'DroidSansMonoRegular'; + } + } + .terminal-title { + cursor: move; + border-bottom: 1px solid #d4d4d4; + > h5 { + display: inline-block; + margin-left: 5px; + } + + > i { + font-size: 16px; + margin-right: 5px; + margin-top: 7px; + } + } +} + +kubernetes-container-terminal .terminal-wrapper { + display: block !important; +} + +kubernetes-container-terminal .terminal-actions { + position: absolute !important; +} + +.pod-log-window { + .scroll-indicator { + position: absolute; + bottom: 0; + line-height: 32px; + left: 20px; + right: 20px; + background-color: #ffffff; + border-top: 1px solid #d4d4d4; + border-left: 1px solid #d4d4d4; + border-right: 1px solid #d4d4d4; + border-radius: 4px 4px 0 0; + cursor: pointer; + z-index: 10000; + opacity: 0.7; + + } + .terminal-body { + overflow-y: auto; + overflow-x: hidden; + } +} + diff --git a/plugins/kubernetes/ts/apps.ts b/plugins/kubernetes/ts/apps.ts new file mode 100644 index 0000000..f7f09c0 --- /dev/null +++ b/plugins/kubernetes/ts/apps.ts @@ -0,0 +1,298 @@ +/// +/// + +module Kubernetes { + + export var Apps = controller("Apps", + ["$scope", "KubernetesModel", "KubernetesServices", "KubernetesReplicationControllers", "KubernetesPods", "KubernetesState", "KubernetesApiURL", "$templateCache", "$location", "$routeParams", "$http", "$dialog", "$timeout", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesServices:ng.resource.IResourceClass, KubernetesReplicationControllers:ng.resource.IResourceClass, KubernetesPods:ng.resource.IResourceClass, KubernetesState, KubernetesApiURL, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $dialog, $timeout) => { + + $scope.model = KubernetesModel; + + $scope.apps = []; + $scope.allApps = []; + $scope.kubernetes = KubernetesState; + $scope.fetched = false; + $scope.json = ''; + ControllerHelpers.bindModelToSearchParam($scope, $location, 'id', '_id', undefined); + ControllerHelpers.bindModelToSearchParam($scope, $location, 'appSelectorShow', 'openApp', undefined); + ControllerHelpers.bindModelToSearchParam($scope, $location, 'mode', 'mode', 'detail'); + + var branch = $scope.branch || "master"; + var namespace = null; + + function appMatches(app) { + var filterText = $scope.appSelector.filterText; + if (filterText) { + return Core.matchFilterIgnoreCase(app.groupId, filterText) || + Core.matchFilterIgnoreCase(app.artifactId, filterText) || + Core.matchFilterIgnoreCase(app.name, filterText) || + Core.matchFilterIgnoreCase(app.description, filterText); + } else { + return true; + } + } + + function appRunning(app) { + return $scope.model.apps.any((running) => running.appPath === app.appPath); + } + + $scope.tableConfig = { + data: 'model.apps', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '$name', displayName: 'App', cellTemplate: $templateCache.get(UrlHelpers.join(templatePath, "appIconTemlate.html")) }, + { field: '$servicesText', displayName: 'Services', cellTemplate: $templateCache.get(UrlHelpers.join(templatePath, "appServicesTemplate.html")) }, + { field: '$replicationControllersText', displayName: 'Controllers', cellTemplate: $templateCache.get(UrlHelpers.join(templatePath, "appReplicationControllerTemplate.html")) }, + { field: '$podCount', displayName: 'Pods', cellTemplate: $templateCache.get(UrlHelpers.join(templatePath, "appPodCountsAndLinkTemplate.html")) }, + { field: '$creationDate', displayName: 'Deployed', cellTemplate: $templateCache.get(UrlHelpers.join(templatePath, "appDeployedTemplate.html")) } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + + $scope.expandedPods = []; + + $scope.$on('do-resize', ($event, controller) => { + $scope.resizeDialog.open(controller); + }); + + + $scope.podExpanded = (pod) => { + var id = getName(pod) + return id && ($scope.expandedPods || []).indexOf(id) >= 0; + }; + + $scope.expandPod = (pod) => { + var id = getName(pod); + if (id) { + $scope.expandedPods.push(id); + } + }; + + $scope.collapsePod = (pod) => { + var id = getName(pod); + if (id) { + _.remove($scope.expandedPods, (v) => id === v); + } + }; + + $scope.$on('$routeUpdate', ($event) => { + Kubernetes.setJson($scope, $location.search()['_id'], $scope.model.apps); + }); + + function deleteApp(app, onCompleteFn) { + function deleteServices(services, service, onCompletedFn) { + if (!service || !services) { + return onCompletedFn(); + } + var id = getName(service); + if (!id) { + log.warn("No ID for service " + angular.toJson(service)); + } else { + KubernetesServices.delete({ + id: id + }, undefined, () => { + log.debug("Deleted service: ", id); + deleteServices(services, services.shift(), onCompletedFn); + }, (error) => { + log.debug("Error deleting service: ", error); + deleteServices(services, services.shift(), onCompletedFn); + }); + } + } + + function deleteReplicationControllers(replicationControllers, replicationController, onCompletedFn) { + if (!replicationController || !replicationControllers) { + return onCompletedFn(); + } + var id = getName(replicationController); + if (!id) { + log.warn("No ID for replicationController " + angular.toJson(replicationController)); + } else { + KubernetesReplicationControllers.delete({ + id: id + }, undefined, () => { + log.debug("Deleted replicationController: ", id); + deleteReplicationControllers(replicationControllers, replicationControllers.shift(), onCompletedFn); + }, (error) => { + log.debug("Error deleting replicationController: ", error); + deleteReplicationControllers(replicationControllers, replicationControllers.shift(), onCompletedFn); + }); + } + } + + function deletePods(pods, pod, onCompletedFn) { + if (!pod || !pods) { + return onCompletedFn(); + } + var id = getName(pod); + if (!id) { + log.warn("No ID for pod " + angular.toJson(pod)); + } else { + KubernetesPods.delete({ + id: id + }, undefined, () => { + log.debug("Deleted pod: ", id); + deletePods(pods, pods.shift(), onCompletedFn); + }, (error) => { + log.debug("Error deleting pod: ", error); + deletePods(pods, pods.shift(), onCompletedFn); + }); + } + } + + var services = [].concat(app.services); + deleteServices(services, services.shift(), () => { + + var replicationControllers = [].concat(app.replicationControllers); + deleteReplicationControllers(replicationControllers, replicationControllers.shift(), () => { + + var pods = [].concat(app.pods); + deletePods(pods, pods.shift(), onCompleteFn); + }); + }); + } + + $scope.deleteSingleApp = (app) => { + $scope.deletePrompt([app]); + } + + $scope.deletePrompt = (selected) => { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected, next) { + if (next) { + var id = next.name; + log.debug("deleting: ", id); + deleteApp(next, () => { + log.debug("deleted: ", id); + deleteSelected(selected, selected.shift()); + }); + } + } + + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Apps?', + action: 'The following Apps will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + $scope.appSelector = { + filterText: "", + folders: [], + selectedApps: [], + + isOpen: (folder) => { + if ($scope.appSelector.filterText !== '' || folder.expanded) { + return "opened"; + } + return "closed"; + }, + + getSelectedClass: (app) => { + if (app.abstract) { + return "abstract"; + } + if (app.selected) { + return "selected"; + } + return ""; + }, + + showApp: (app) => { + return appMatches(app) && !appRunning(app); + }, + + showFolder: (folder) => { + return !$scope.appSelector.filterText || folder.apps.some((app) => appMatches(app) && !appRunning(app)); + }, + + clearSelected: () => { + angular.forEach($scope.model.appFolders, (folder) => { + angular.forEach(folder.apps, (app) => { + app.selected = false; + }); + }); + $scope.appSelector.selectedApps = []; + Core.$apply($scope); + }, + + updateSelected: () => { + // lets update the selected apps + var selectedApps = []; + angular.forEach($scope.model.appFolders, (folder) => { + var apps = folder.apps.filter((app) => app.selected); + if (apps) { + selectedApps = selectedApps.concat(apps); + } + }); + $scope.appSelector.selectedApps = _.sortBy(selectedApps, "name"); + }, + + select: (app, flag) => { + app.selected = flag; + $scope.appSelector.updateSelected(); + }, + + hasSelection: () => { + return $scope.model.appFolders.any((folder) => folder.apps.any((app) => app.selected)); + }, + + + runSelectedApps: () => { + // lets run all the selected apps + angular.forEach($scope.appSelector.selectedApps, (app) => { + var name = app.name; + var metadataPath = app.metadataPath; + if (metadataPath) { + // lets load the json/yaml + //var url = gitPathToUrl(Wiki.gitRelativeURL(branch, metadataPath)); + var url = gitPathToUrl(metadataPath, branch); + if (url) { + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + // lets convert the json object structure into a string + var json = angular.toJson(data); + var fn = () => {}; + Kubernetes.runApp($location, $scope, $http, KubernetesApiURL, json, name, fn, namespace); + } + }). + error(function (data, status, headers, config) { + $scope.summaryHtml = null; + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + } + }); + // lets go back to the apps view + $scope.appSelector.clearSelected(); + $scope.appSelectorShow = false; + } + }; + + }]); +} diff --git a/plugins/kubernetes/ts/breadcrumbs.ts b/plugins/kubernetes/ts/breadcrumbs.ts new file mode 100644 index 0000000..e9c3a60 --- /dev/null +++ b/plugins/kubernetes/ts/breadcrumbs.ts @@ -0,0 +1,17 @@ +/// +/// +/// + +module Kubernetes { + + _module.directive("hawtioBreadcrumbs", ['HawtioBreadcrumbs', (HawtioBreadcrumbs) => { + return { + /* + templateUrl: Kubernetes.templatePath + 'breadcrumbs.html' + */ + link: (scope, element, attrs) => { + HawtioBreadcrumbs.apply(scope.$eval('breadcrumbConfig')); + } + }; + }]); +} diff --git a/plugins/kubernetes/ts/build.ts b/plugins/kubernetes/ts/build.ts new file mode 100644 index 0000000..166db3e --- /dev/null +++ b/plugins/kubernetes/ts/build.ts @@ -0,0 +1,53 @@ +/// +/// +/// + +module Kubernetes { + + export var BuildController = controller("BuildController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_Build; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id, null, $scope); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = buildRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = enrichBuild(data); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/kubernetes/ts/buildConfig.ts b/plugins/kubernetes/ts/buildConfig.ts new file mode 100644 index 0000000..1e135ce --- /dev/null +++ b/plugins/kubernetes/ts/buildConfig.ts @@ -0,0 +1,56 @@ +/// +/// +/// + +module Kubernetes { + + export var BuildConfigController = controller("BuildConfigController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_BuildConfig; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.id); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.id); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = buildConfigRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = data; + var sortedBuilds = null; + enrichBuildConfig(data, sortedBuilds); + $scope.model.setProject($scope.entity); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/kubernetes/ts/buildConfigEdit.ts b/plugins/kubernetes/ts/buildConfigEdit.ts new file mode 100644 index 0000000..d411c74 --- /dev/null +++ b/plugins/kubernetes/ts/buildConfigEdit.ts @@ -0,0 +1,429 @@ +/// +/// +/// + +module Kubernetes { + + export var BuildConfigEditController = _module.controller("Kubernetes.BuildConfigEditController", ($scope, $element, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, K8SClientFactory, SchemaRegistry:HawtioForms.SchemaRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["project"] || $routeParams["id"]; + $scope.schema = KubernetesSchema; + + var mode = $scope.$eval('mode') || 'edit'; + + log.debug("Mode: ", mode); + + + var specConfig = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildConfigSpec'); + var gitBuildSource = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.GitBuildSource'); + var buildSource = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildSource'); + var buildOutput = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildOutput'); + var resources = SchemaRegistry.getSchema('io.fabric8.kubernetes.api.model.ResourceRequirements'); + var revision = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.SourceRevision'); + var strategy = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildStrategy'); + var customStrategy = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.CustomBuildStrategy'); + var buildTriggerPolicy = SchemaRegistry.getSchema('io.fabric8.openshift.api.model.BuildTriggerPolicy'); + + var getSecrets = () => { + return $scope.secrets; + }; + + + var secretSchemaType = "fabric8_SecretReference"; + var secretSchemaRef = "#/definitions/" + secretSchemaType; + var secretSchemaJavaType = "io.fabric8.console.SecretReference"; + + var secretNameElement = { + "type": "string", + "enum": getSecrets, + required: true + }; + + var secretSchema: HawtioForms.FormConfiguration = { + "type": "object", + properties: { + "name": secretNameElement + }, + javaType: secretSchemaJavaType + }; + SchemaRegistry.addSchema(secretSchemaType, secretSchema); + + // lets switch to the new secrets types: + var sourceSecretProperty = Core.pathGet(buildSource, ["properties", "sourceSecret"]); + angular.forEach([ + Core.pathGet(customStrategy, ["properties", "pullSecret"]), + sourceSecretProperty, + ], (schemaType) => { + if (schemaType) { + schemaType["type"] = secretSchemaType; + schemaType["$ref"] = secretSchemaRef; + schemaType["javaType"] = secretSchemaJavaType; + } + }); + + // lets try make the buildSource's sourceSecret mandatory + //schemaSetRequired(customStrategy, 'pullSecret'); + schemaSetRequired(buildSource, 'sourceSecret'); + if (sourceSecretProperty) { + Core.pathSet(sourceSecretProperty, ['properties', 'required'], true); + Core.pathSet(sourceSecretProperty, ['properties', 'input-attributes', 'required'], true); + } + + $scope.customStrategy = customStrategy; + $scope.buildSource = buildSource; + + $scope.secrets = []; + + // $scope.config = KubernetesSchema.definitions.os_build_BuildConfig; + //$scope.specConfig = KubernetesSchema.definitions.os_build_BuildConfigSpec; + // + specConfig.style = HawtioForms.FormStyle.STANDARD; + specConfig.properties['triggers']['label-attributes'] = { + style: 'display: none;' + }; + + gitBuildSource.controls = ['uri', 'ref', '*']; + buildSource.properties['type'].type = 'hidden'; + buildSource.properties['type']['default'] = 'Git'; + buildSource.controls = ['git', 'contextDir', 'sourceSecret', '*']; + + gitBuildSource['hideLegend'] = true; + buildSource['hideLegend'] = true; + buildOutput['hideLegend'] = true; + resources['hideLegend'] = true; + revision['hideLegend'] = true; + strategy['hideLegend'] = true; + + strategy.controls = ['type', '*']; + strategy.properties['type'] = { + type: 'text', + enum: [{ + 'value': 'Custom', + 'label': 'Custom' + }, { + 'value': 'Docker', + 'label': 'Docker' + }, { + 'value': 'Source', + 'label': 'Source' + }] + }; + customStrategy['control-group-attributes'] = { + 'ng-show': "entity.type == 'Custom'" + }; + strategy.properties['dockerStrategy']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Docker'" + }; + strategy.properties['sourceStrategy']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Source'" + }; + + buildTriggerPolicy.controls = ['type', '*']; + buildTriggerPolicy.properties['type'] = { + type: 'string', + enum: [{ + 'value': 'Github', + 'label': 'Github' + }, { + 'value': 'ImageChange', + 'label': 'Image Change' + }, { + 'value': 'Generic', + 'label': 'Generic' + }] + }; + buildTriggerPolicy.properties['generic']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Generic'" + }; + buildTriggerPolicy.properties['github']['control-group-attributes'] = { + 'ng-show': "entity.type == 'Github'" + }; + buildTriggerPolicy.properties['imageChange']['control-group-attributes'] = { + 'ng-show': "entity.type == 'ImageChange'" + }; + + // re-arranging the controls + //specConfig.controls = ['source', '*']; + + // tabs + specConfig.tabs = { + "Source": ["source"], + "Revision": ["revision"], + "Output": ["output"], + "Resources": ["resources"], + "Strategy": ["strategy"], + "Triggers": ["triggers"], + "Service Account": ["serviceAccount"] + }; + /* + * wizard, needs an 'onFinish' function in the scope + specConfig.wizard = { + pages: { + Source: { + controls: ["source"] + }, + Revision: { + controls: ["revision"] + }, + Output: { + controls: ["output"] + }, + Resources: { + controls: ["resources"] + }, + Strategy: { + controls: ["strategy"] + }, + Triggers: { + controls: ["triggers"] + }, + "Service Account": { + controls: ["serviceAccount"] + } + } + }; + */ + + $scope.entity = { + "apiVersion": "v1", + "kind": "BuildConfig", + "metadata": { + "name": "", + "labels": { + } + }, + "spec": { + "source": { + "type": "Git" + }, + "strategy": { + "type": "Custom", + "customStrategy": { + "from": { + "kind": "DockerImage", + "name": "fabric8/openshift-s2i-jenkins-trigger" + }, + "env": [ + { + "name": "BASE_URI", + "value": jenkinsUrl + }, + { + "name": "JOB_NAME", + "value": jobName + } + ] + } + } + } + }; + + $scope.$watch('entity.spec.source.git.uri', (val) => { + if (!val) { + return; + } + var lastBit = val.match(/[^\/]+$/)[0]; + if (lastBit) { + var name = lastBit.replace(/\.git$/, ''); + log.debug("name: ", name); + if (!Core.isBlank(name) + && Core.isBlank(Core.pathGet($scope.entity, ['metadata', 'name']))) { + Core.pathSet($scope.entity, ['metadata', 'name'], name); + } + } + }); + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectSettingsBreadcrumbs($scope.projectId); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.projectId); + $scope.tabs = Developer.createProjectSettingsSubNavBars($scope.projectId); + + watch($scope, $element, "secrets", $scope.namespace, onSecrets); + + + $scope.buildConfigClient = K8SClientFactory.create("buildconfigs", $scope.namespace); + + $element.on('$destroy', () => { + $scope.$destroy(); + }); + $scope.$on('$destroy', () => { + K8SClientFactory.destroy($scope.buildConfigClient); + }); + +/* + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + +*/ + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.save = () => { + log.info("Saving!"); + + + var entity = $scope.entity; + var spec = (entity || {}).spec || {}; + + // TODO update the jenkins job name! + + // lets delete lots of cruft + var strategy = spec.strategy || {}; + delete strategy["dockerStrategy"]; + delete strategy["sourceStrategy"]; + + delete spec["revision"]; + delete spec["output"]; + delete spec["resources"]; + + var strategyPullSecretName = Core.pathGet(spec, ["strategy", "customStrategy", "pullSecret", "name"]); + var sourceSecretName = Core.pathGet(spec, ["source", "sourceSecret", "name"]); + log.info("sourceSecretName: " + sourceSecretName); + log.info("strategyPullSecretName: " + strategyPullSecretName); + if (!strategyPullSecretName && sourceSecretName) { + Core.pathSet(spec, ["strategy", "customStrategy", "pullSecret", "name"], sourceSecretName); + } + +/* + // TODO hack until the put deals with updates + var metadata = entity.metadata; + if (metadata) { + delete metadata["resourceVersion"]; + } +*/ + + log.info(angular.toJson(entity, true)); + + $scope.buildConfigClient.put(entity, (obj) => { + log.info("build config created!"); + + var link = Developer.projectSecretsLink($scope.namespace, getName(entity)); + if (link) { + log.info("Navigating to: "+ link); + $location.path(link); + } else { + log.warn("Could not find the edit pipeline link!"); + } + }) + }; + + updateData(); + + + var jenkinsUrl = Developer.jenkinsLink(); + var jobName = ""; + + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = buildConfigRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = data; + + var buildConfig = angular.copy(data); + var sortedBuilds = null; + Kubernetes.enrichBuildConfig(buildConfig, sortedBuilds); + $scope.buildConfig = buildConfig; + } + $scope.spec = ($scope.entity || {}).spec || {}; + $scope.fetched = true; + + // lets update the tabs + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.projectId, null, $scope); + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } else { + $scope.fetched = true; + + $scope.spec = $scope.entity.spec; + Core.$apply($scope); + } + } + + function onSecrets(secrets) { + var array = []; + angular.forEach(secrets, (secret) => { + var name = getName(secret); + if (name) { + array.push({ + label: name, + value: name, + "attributes": { + "title": name + }, + $secret: secret + }); + } + }); + $scope.secrets = _.sortBy(array, "label"); + + var specSourceSecretNamePath = ['spec', 'source', 'sourceSecret', 'name']; + if ($scope.entity && !Core.pathGet($scope.entity, specSourceSecretNamePath)) { + var defaultSecretName = findDefaultImportSecretName(secrets); + Core.pathSet($scope.entity, specSourceSecretNamePath, defaultSecretName); + } + } + + function findDefaultImportSecretName(secrets) { + var answer = null; + angular.forEach(secrets, (secret) => { + var name = getName(secret); + if (!answer && name && name.startsWith("jenkins-login")) { + answer = name; + } + }); + if (!answer) { + angular.forEach(secrets, (secret) => { + var name = getName(secret); + if (!answer && name && name.startsWith("jenkins-token")) { + answer = name; + } + }); + } + return answer; + } + + switch (mode) { + case 'create': + delete specConfig.tabs; + _.forIn(buildSource.properties, (property:any, name:string) => { + if (name !== 'git') { + log.info("Hiding property: ", name); + property.hidden = true; + } + }); + _.forIn(gitBuildSource.properties, (property:any, name:string) => { + if (name !== 'uri') { + log.info("Hiding property: ", name); + property.hidden = true; + } else { + property.label = "Git URL"; + property['input-attributes'] = { + 'required': true + } + } + }); + _.forIn(specConfig.properties, (property:any, name:string) => { + if (name !== 'source') { + log.info("Hiding property: ", name); + property.hidden = true; + } + }); + break; + case 'edit': + default: + } + + $scope.specConfig = specConfig; + }); + +} diff --git a/plugins/kubernetes/ts/buildConfigs.ts b/plugins/kubernetes/ts/buildConfigs.ts new file mode 100644 index 0000000..78f3999 --- /dev/null +++ b/plugins/kubernetes/ts/buildConfigs.ts @@ -0,0 +1,137 @@ +/// +/// + +module Kubernetes { + + export var BuildConfigsController = controller("BuildConfigsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + $scope.tableConfig = { + data: 'model.buildconfigs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name', + cellTemplate: $templateCache.get("buildConfigLinkTemplate.html") + }, +/* + { + field: 'spec.source.type', + displayName: 'Source' + }, +*/ + { + field: 'spec.source.git.uri', + displayName: 'Repository' + }, +/* + { + field: 'spec.strategy.type', + displayName: 'Strategy' + }, + { + field: 'spec.strategy.stiStrategy.image', + displayName: 'Source Image' + }, + { + field: 'spec.output.imageTag', + displayName: 'Output Image' + }, +*/ + { + field: '$fabric8CodeViews', + displayName: 'Code', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigCodeViewsTemplate.html") + }, + { + field: '$fabric8BuildViews', + displayName: 'Builds', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigBuildViewsTemplate.html") + }, + { + field: '$fabric8EnvironmentViews', + displayName: 'Environments', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigEnvironmentViewsTemplate.html") + }, + { + field: '$fabric8TeamViews', + displayName: 'People', + width: "***", + minWidth: 500, + cellTemplate: $templateCache.get("buildConfigTeamViewsTemplate.html") + } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + // TODO + // $scope.isLoggedIntoGogs = Forge.isLoggedIntoGogs; + + $scope.deletePrompt = (selected) => { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, () => { + deleteSelected(selected, selected.shift()); + }); + } else { + updateData(); + } + } + + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Build Configs?', + action: 'The following Build Configs will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + if (name) { + console.log("About to delete build config: " + name); + var url = buildConfigRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to delete build config on " + url + " " + data + " " + status); + }); + } else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + } + + function updateData() { + } + + updateData(); + }]); +} diff --git a/plugins/kubernetes/ts/buildLogs.ts b/plugins/kubernetes/ts/buildLogs.ts new file mode 100644 index 0000000..7ff39e4 --- /dev/null +++ b/plugins/kubernetes/ts/buildLogs.ts @@ -0,0 +1,68 @@ +/// +/// +/// + +module Kubernetes { + + export var BuildLogsController = controller("BuildLogsController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_build_Build; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.logsText = "Loading logs..."; + + updateData(); + + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = buildRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = enrichBuild(data); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + + url = buildLogsRestUrl($scope.id); + $http.get(url). + success(function (data, status) { + $scope.logsText = data; + Core.$apply($scope); + }). + error(function (data, status) { + $scope.logsText = "Failed to load logs from: " + url + " " + data + " status: " + status; + Core.$apply($scope); + }). + catch(function (error) { + $scope.logsText = "Failed to load logs: " + angular.toJson(error, true); + Core.$apply($scope); + }); + } else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/kubernetes/ts/builds.ts b/plugins/kubernetes/ts/builds.ts new file mode 100644 index 0000000..4680df2 --- /dev/null +++ b/plugins/kubernetes/ts/builds.ts @@ -0,0 +1,131 @@ +/// +/// + +module Kubernetes { + + export var BuildsController = controller("BuildsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.buildConfigId = $routeParams["id"]; + + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + + $scope.tableConfig = { + data: 'model.builds', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name', + cellTemplate: $templateCache.get("buildLinkTemplate.html") + }, + { + field: '$creationDate', + displayName: 'Time', + defaultSort: true, + cellTemplate: $templateCache.get("buildTimeTemplate.html") + }, + { + field: 'status', + displayName: 'Status', + cellTemplate: $templateCache.get("buildStatusTemplate.html") + }, + { + field: '$logsLink', + displayName: 'Logs', + cellTemplate: $templateCache.get("buildLogsTemplate.html") + }, + { + field: '$podLink', + displayName: 'Build Pod', + cellTemplate: $templateCache.get("buildPodTemplate.html") + }, +/* + { + field: 'parameters.source.type', + displayName: 'Source' + }, +*/ + { + field: 'spec.source.git.uri', + displayName: 'Repository', + cellTemplate: $templateCache.get("buildRepositoryTemplate.html") + }, + { + field: 'spec.strategy.type', + displayName: 'Strategy' + }, + { + field: 'spec.strategy.sourceStrategy.from.name', + displayName: 'Source Image' + }, + { + field: 'spec.output.to.name', + displayName: 'Output Image' + }] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.buildConfigId); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.buildConfigId, null, $scope); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + function updateData() { + if ($scope.model) { + var builds = $scope.model.builds; + var buildConfigId = $scope.buildConfigId; + + enrichBuilds(builds); + $scope.fetched = true; + + if (buildConfigId) { + $scope.buildConfig = $scope.model.getBuildConfig(buildConfigId); + } + } + } + + updateData(); + + + /* + $scope.$keepPolling = () => keepPollingModel; + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + var url = buildsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + $scope.builds = enrichBuilds(data.items); + $scope.fetched = true; + + if ($scope.model) { + $scope.buildConfig = $scope.model.getBuildConfig($scope.buildConfigId); + } + } + Core.$apply($scope); + next(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + Core.$apply($scope); + next(); + }); + }); + + $scope.fetch(); + */ + }]); +} diff --git a/plugins/kubernetes/ts/connect.ts b/plugins/kubernetes/ts/connect.ts new file mode 100644 index 0000000..8196a5d --- /dev/null +++ b/plugins/kubernetes/ts/connect.ts @@ -0,0 +1,27 @@ +/// +/// +/// + +module Kubernetes { + + // controller for connecting to a remote container via jolokia + export var ConnectController = controller("ConnectController", [ + "$scope", "localStorage", "userDetails", "ConnectDialogService", "$browser", + ($scope, localStorage, userDetails, ConnectDialogService, $browser:ng.IBrowserService) => { + + $scope.doConnect = (entity) => { + var connectUrl:any = new URI().path(UrlHelpers.join(HawtioCore.documentBase(), '/java/index.html')); + var returnTo = new URI().toString(); + var title = entity.metadata.name || 'Untitled Container'; + var token = userDetails.token || ''; + connectUrl.hash(token).query({ + jolokiaUrl: entity.$jolokiaUrl, + title: title, + returnTo: returnTo + }); + log.debug("Connect URI: ", connectUrl.toString()); + window.open(connectUrl.toString()); + }; + + }]); +} diff --git a/plugins/kubernetes/ts/dataInfnModel.ts b/plugins/kubernetes/ts/dataInfnModel.ts new file mode 100644 index 0000000..1f1672f --- /dev/null +++ b/plugins/kubernetes/ts/dataInfnModel.ts @@ -0,0 +1,192 @@ +/// +/// + +module Kubernetes{ + export class dataInfoModelService{ + public serverdata = {}; + public promiseobject = {}; + public localdata = {}; + public selectednodes = []; + public resumablejs = []; + public selecteditems = []; + public serveritems = []; + public uploadprocess ={}; + public uploadedStatus = ""; + + public get uploadProcess():Object { + return this.uploadprocess + } + + public set uploadProcess(uploadProcess:Object){ + this.uploadprocess = uploadProcess; + } + + public folderList = { + length:0 + }; + + public get serverItems():Array { + return this.serveritems; + } + + public set serverItems(serverItems: Array){ + this.serveritems = serverItems; + } + + public get resumableJs():Array { + return this.resumableJs; + } + + public set resumableJs(resumableJs: Array){ + this.resumablejs = resumableJs; + } + + public get selectedItems():Array { + return this.selecteditems; + } + + public set selectedItems(selectedItems: Array){ + this.selecteditems = selectedItems; + } + + public get selectedNodes():Array { + return this.selectednodes; + } + + public set selectedNodes(selectedNodes: Array){ + this.selectednodes = selectedNodes; + } + + public isContainsNodes(node: Object){ + for(var item in this.selectednodes){ + if(this.selectednodes[item].id === node.id) + return true; + } + return false; + } + + public findNodes(node: any) { + var id = "-1"; + if(typeof(node) === "object" ){ + id = node.id; + }else if(typeof(node) === "number"){ + id =node.toString(); + }else if(typeof(node) === "string"){ + id = node; + }else{ + return "-1"; + } + + for(var item in this.selectednodes){ + if(this.selectednodes[item].id === id) + return item; + } + return "-1"; + } + + public findItemIndex(item: any){ + var id = -1; + if(typeof(item) === "object" ){ + id = item.id; + }else if(typeof(item) === "number"){ + id =item.toString(); + }else if(typeof(item) === "string"){ + id = item; + }else{ + return -1; + } + + for(var it in this.selecteditems){ + if(this.selecteditems[it].id === id) + return it; + } + return -1; + } + + public createFolderList(files: Object ,rootPath: string){ + for(var i=0; i< files.length; i++){ + var relativePath = files[i].webkitRelativePath.replace(RegExp("^"+rootPath+"/"),""); + var paths=relativePath.split("/"); + if(!this.folderList.hasOwnProperty(paths[0])){ + this.folderList[paths[0]]={ + length:0 + }; + this.folderList.length++; + } + var Obj = this.folderList[paths[0]]; + Obj[Obj.length] = files[i]; + Obj.length++; + this.folderList[paths[0]] = Obj; + } + } + + public updateNodeById(nodeId,key,value){ + for(var item in this.selectednodes){ + var node = this.selectednodes[item]; + if(node.id === nodeId){ + node[key] = value; + break; + } + } + } + + public get serverData():Object { + return this.serverData; + } + + public set serverData(serverData:Object){ + this.serverdata=serverData; + } + + public get promiseObject():Object { + return this.promiseobject; + } + + public set promise(promiseObject:Object){ + this.promiseobject = promiseObject; + } + + public get localData():Object { + return this.localdata; + } + + public set localData(localData:Object){ + this.localdata = localData; + } + + public updataDataModel(){ + this.promiseobject.success(function(data,header,config,status){ + this.serverdata =data; + }); + + this.promiseobject.error(function(data,status,hedaers,config){ + this.serverdata = {}; + }); + } + } + _module.factory('DataInfoModel', ['$http', ($http) => { + var $scope =new dataInfoModelService(); + + $scope.promiseobject=$http({ + url:'/xmlformserver', + method:'POST' + }); + + updateDataFromServer($scope.serverdata, (data,header,config,status) => { + $scope.serverdata = data; + }); + + function updateDataFromServer(data,callback){ + $http({ + url:'/xmlformserver', + method:'POST' + }).success(function(data,header,config,status){ + if(data) + callback(data,header,config,status); + }).error(function(data,header,config,status){ + console.log("error"); + }); + }; + return $scope; + }]); +} \ No newline at end of file diff --git a/plugins/kubernetes/ts/deploymentConfig.ts b/plugins/kubernetes/ts/deploymentConfig.ts new file mode 100644 index 0000000..a4d7701 --- /dev/null +++ b/plugins/kubernetes/ts/deploymentConfig.ts @@ -0,0 +1,52 @@ +/// +/// +/// + +module Kubernetes { + + export var DeploymentConfigController = controller("DeploymentConfigController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = KubernetesSchema.definitions.os_deploy_DeploymentConfig; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + $scope.item = null; + if ($scope.id) { + var url = deploymentConfigRestUrl($scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.entity = data; + enrichDeploymentConfig(data); + } + $scope.fetched = true; + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } else { + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/kubernetes/ts/deploymentConfigs.ts b/plugins/kubernetes/ts/deploymentConfigs.ts new file mode 100644 index 0000000..413c378 --- /dev/null +++ b/plugins/kubernetes/ts/deploymentConfigs.ts @@ -0,0 +1,124 @@ +/// +/// + +module Kubernetes { + + export var DeploymentConfigsController = controller("DeploymentConfigsController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + $scope.labelClass = containerLabelClass; + + $scope.tableConfig = { + data: 'deploymentConfigs', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name', + cellTemplate: $templateCache.get("deploymentConfigLinkTemplate.html") + }, + { + field: 'metadata.namespace', + displayName: 'Namespace' + }, + { + field: '$imageChangeParams.automatic', + displayName: 'Automatic' + }, + { + field: '$imageChangeParams.$containerNames', + displayName: 'Container Names' + }, + { + field: '$imageChangeParams.from.name', + displayName: 'From image' + }, + { + field: '$imageChangeParams.tag', + displayName: 'Tag' + }, + { + field: 'template.controllerTemplate.podTemplate.tags', + displayName: 'Labels', + cellTemplate: $templateCache.get("deploymentConfigLabelTemplate.html") + } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.deletePrompt = (selected) => { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, () => { + deleteSelected(selected, selected.shift()); + }); + } else { + updateData(); + } + } + + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Deployment?', + action: 'The following Deployments will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + if (name) { + console.log("About to delete deployment config: " + name); + var url = deploymentConfigRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to delete deployment config on " + url + " " + data + " " + status); + }); + } else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + } + + function updateData() { + var url = deploymentConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + $scope.deploymentConfigs = enrichDeploymentConfigs(data.items); + $scope.fetched = true; + Core.$apply($scope); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + + updateData(); + }]); +} diff --git a/plugins/kubernetes/ts/events.ts b/plugins/kubernetes/ts/events.ts new file mode 100644 index 0000000..716297f --- /dev/null +++ b/plugins/kubernetes/ts/events.ts @@ -0,0 +1,64 @@ +/// +/// +/// + +module Kubernetes { + + export var EventsController = controller("EventsController", + ["$scope", "KubernetesModel", "KubernetesServices", "KubernetesPods", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesServices:ng.resource.IResourceClass, KubernetesPods:ng.resource.IResourceClass, KubernetesState, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + ControllerHelpers.bindModelToSearchParam($scope, $location, 'mode', 'mode', 'list'); + + $scope.tableConfig = { + data: 'model.events', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '$firstTimestamp', + displayName: 'First Seen', + cellTemplate: $templateCache.get("firstTimestampTemplate.html") + }, + { field: '$lastTimestamp', + displayName: 'Last Seen', + cellTemplate: $templateCache.get("lastTimestampTemplate.html") + }, + { field: 'count', + displayName: 'Count' + }, + { field: 'involvedObject.name', + displayName: 'Name', + cellTemplate: $templateCache.get("eventNameTemplate.html") + }, + { field: 'involvedObject.kind', + displayName: 'Kind', + cellTemplate: $templateCache.get("eventKindTemplate.html") + }, + { field: 'involvedObject.fieldPath', + displayName: 'Subject' + }, + { field: 'reason', + displayName: 'Reason' + }, + { field: 'source', + displayName: 'Source', + cellTemplate: $templateCache.get("eventSourceTemplate.html") + }, + { field: 'message', + displayName: 'Message' + } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + }]); +} diff --git a/plugins/kubernetes/ts/host.ts b/plugins/kubernetes/ts/host.ts new file mode 100644 index 0000000..d671e44 --- /dev/null +++ b/plugins/kubernetes/ts/host.ts @@ -0,0 +1,61 @@ +/// +/// +/// +/// + +module Kubernetes { + + export var HostController = controller("HostController", + ["$scope", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + + $scope.itemConfig = { + properties: {} + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.flipRaw = () => { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + + updateData(); + + function updateData() { + $scope.id = $routeParams["id"]; + $scope.item = null; + if ($scope.id) { + var url = UrlHelpers.join(KubernetesApiURL, "nodes", $scope.id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.item = data; + } + if ($scope.item) { + $scope.rawModel = toRawYaml($scope.item); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } else { + $scope.rawModel = null; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/kubernetes/ts/hosts.ts b/plugins/kubernetes/ts/hosts.ts new file mode 100644 index 0000000..dbc8aef --- /dev/null +++ b/plugins/kubernetes/ts/hosts.ts @@ -0,0 +1,58 @@ +/// +/// +/// +/// + +module Kubernetes { + + export var HostsController = controller("HostsController", ["$scope", "KubernetesModel", "KubernetesPods", "KubernetesState", "ServiceRegistry", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesPods:ng.IPromise>, KubernetesState, ServiceRegistry, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + + $scope.tableConfig = { + data: 'model.hosts', + showSelectionCheckbox: false, + enableRowClickSelection: false, + multiSelect: false, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'id', + displayName: 'Name', + defaultSort: true, + cellTemplate: $templateCache.get("idTemplate.html") + }, + { + field: 'hostIP', + displayName: 'IP', + customSortField: (field) => { + // use a custom sort to sort ip address + return Kubernetes.sortByPodIp(field.hostIP); + } + }, + { field: '$podsLink', + displayName: 'Pods', + cellTemplate: $templateCache.get("podCountsAndLinkTemplate.html"), + customSortField: (field) => { + // need to concat all the pod counters + var ready = field.$podCounters.ready || 0; + var valid = field.$podCounters.valid || 0; + var waiting = field.$podCounters.waiting || 0; + var error = field.$podCounters.error || 0; + return ready + valid + waiting + error; + } + } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + }]); +} diff --git a/plugins/kubernetes/ts/imageRepositories.ts b/plugins/kubernetes/ts/imageRepositories.ts new file mode 100644 index 0000000..d4180d4 --- /dev/null +++ b/plugins/kubernetes/ts/imageRepositories.ts @@ -0,0 +1,122 @@ +/// +/// + +module Kubernetes { + + export var ImageRepositoriesController = controller("ImageRepositoriesController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + + $scope.tableConfig = { + data: 'imageRepositories', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: 'metadata.name', + displayName: 'Name' + }, + { + field: 'metadata.namespace', + displayName: 'Namespace' + }, + { + field: 'status.dockerImageRepository', + displayName: 'Docker Registry' + }, + { + field: 'tags', + displayName: 'Tags', + cellTemplate: $templateCache.get('imageRegistryLabelTemplate.html') + } + ] + }; + + var labelColors = { + 'prod': 'background-blue', + 'valid': 'background-light-green', + 'test': 'background-light-grey' + }; + $scope.labelClass = (labelType:string) => { + if (!(labelType in labelColors)) { + return 'mouse-pointer'; + } + else return labelColors[labelType] + ' mouse-pointer'; + } + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.deletePrompt = (selected) => { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: '$name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected, next) { + if (next) { + deleteEntity(next, () => { + deleteSelected(selected, selected.shift()); + }); + } else { + updateData(); + } + } + + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Image Repository?', + action: 'The following Image Repositories will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + function deleteEntity(selection, nextCallback) { + var name = (selection || {}).$name; + if (name) { + console.log("About to delete image repository: " + name); + var url = imageRepositoryRestUrl(name); + $http.delete(url). + success(function (data, status, headers, config) { + nextCallback(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to delete image repository on " + url + " " + data + " " + status); + }); + } else { + console.log("warning: no name for selection: " + angular.toJson(selection)); + } + } + + function updateData() { + var url = imageRepositoriesRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + //console.log("got data " + angular.toJson(data, true)); + $scope.imageRepositories = enrichImageRepositories(data.items); + $scope.fetched = true; + Core.$apply($scope); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + + updateData(); + }]); +} diff --git a/plugins/kubernetes/ts/kubernetesHelpers.ts b/plugins/kubernetes/ts/kubernetesHelpers.ts new file mode 100644 index 0000000..9a95401 --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesHelpers.ts @@ -0,0 +1,1792 @@ +/// +/// +module Kubernetes { + + export var context = '/kubernetes'; + export var hash = '#' + context; + export var defaultRoute = hash + '/apps'; + export var pluginName = 'Kubernetes'; + export var pluginPath = 'plugins/kubernetes/'; + export var templatePath = pluginPath + 'html/'; + export var log:Logging.Logger = Logger.get(pluginName); + + export var keepPollingModel = true; + + export var defaultIconUrl = Core.url("/img/kubernetes.svg"); + export var hostIconUrl = Core.url("/img/host.svg"); + + // this gets set as a pre-bootstrap task + export var osConfig:KubernetesConfig = undefined; + export var masterUrl = ""; + + export var defaultApiVersion = "v1"; + export var defaultOSApiVersion = "v1"; + export var labelFilterTextSeparator = ","; + + export var defaultNamespace = "default"; + + export var appSuffix = ".app"; + + // kubernetes service names + export var kibanaServiceName = "kibana"; + export var fabric8ForgeServiceName = "fabric8-forge"; + export var gogsServiceName = "gogs"; + export var jenkinsServiceName = "jenkins"; + export var apimanServiceName = 'apiman'; + export var isOpenShift = true; + + export var sshSecretDataKeys = ["ssh-key", "ssh-key.pub"]; + export var httpsSecretDataKeys = ["username", "password"]; + + + export function kubernetesNamespacePath() { + var ns = currentKubernetesNamespace(); + if (ns) { + return "/namespaces/" + ns; + } else { + return ""; + } + } + + export function apiPrefix() { + var prefix = Core.pathGet(osConfig, ['api', 'k8s', 'prefix']); + if (!prefix) { + prefix = 'api'; + } + return Core.trimLeading(prefix, '/'); + } + + export function osApiPrefix() { + var prefix = Core.pathGet(osConfig, ['api', 'openshift', 'prefix']); + if (!prefix) { + prefix = 'oapi'; + } + var answer = Core.trimLeading(prefix, '/'); + if (!isOpenShift) { + return UrlHelpers.join(apiPrefix(), defaultOSApiVersion, "proxy", kubernetesNamespacePath(), "services/templates", answer); + } + return answer; + } + + export function masterApiUrl() { + return masterUrl || ""; + } + + /** WARNING - this excludes the host name - you probably want to use: kubernetesApiUrl() instead!! */ + export function kubernetesApiPrefix() { + return UrlHelpers.join(apiPrefix(), defaultApiVersion); + } + + export function openshiftApiPrefix() { + return UrlHelpers.join(osApiPrefix(), defaultOSApiVersion); + } + + export function prefixForType(type:string) { + if (type === WatchTypes.NAMESPACES) { + return kubernetesApiPrefix(); + } + if (_.any(NamespacedTypes.k8sTypes, (t) => t === type)) { + return kubernetesApiPrefix(); + } + if (_.any(NamespacedTypes.osTypes, (t) => t === type)) { + return openshiftApiPrefix(); + } + // lets assume its an OpenShift extension type + return openshiftApiPrefix(); + } + + export function kubernetesApiUrl() { + return UrlHelpers.join(masterApiUrl(), kubernetesApiPrefix()); + } + + export function openshiftApiUrl() { + return UrlHelpers.join(masterApiUrl(), openshiftApiPrefix()); + } + + export function resourcesUriForKind(type, ns = null) { + if (!ns) { + ns = currentKubernetesNamespace(); + } + return UrlHelpers.join(masterApiUrl(), prefixForType(type), namespacePathForKind(type, ns)); + } + + export function uriTemplateForKubernetesKind(type) { + var urlTemplate = ''; + switch (type) { + case WatchTypes.NAMESPACES: + case "Namespaces": + urlTemplate = UrlHelpers.join('namespaces'); + break; + case WatchTypes.OAUTH_CLIENTS: + case "OAuthClients": + case "OAuthClient": + return UrlHelpers.join('oauthclients'); + case WatchTypes.PROJECTS: + case "Projects": + urlTemplate = UrlHelpers.join('projects'); + break; + default: + urlTemplate = UrlHelpers.join('namespaces/:namespace', type, ':id'); + } + return urlTemplate; + } + + export function namespacePathForKind(type, ns) { + var urlTemplate = ''; + switch (type) { + case WatchTypes.NAMESPACES: + case "Namespaces": + case "Namespace": + return UrlHelpers.join('namespaces'); + case WatchTypes.NODES: + case "Nodes": + case "node": + return UrlHelpers.join('nodes'); + case WatchTypes.PROJECTS: + case "Projects": + case "Project": + return UrlHelpers.join('projects'); + case WatchTypes.OAUTH_CLIENTS: + case "OAuthClients": + case "OAuthClient": + return UrlHelpers.join('oauthclients'); + case WatchTypes.PERSISTENT_VOLUMES: + case "PersistentVolumes": + case "PersistentVolume": + return UrlHelpers.join('persistentvolumes'); + default: + return UrlHelpers.join('namespaces', ns, type); + } + } + + /** + * Returns thevalue from the injector if its available or null + */ + export function inject(name):T { + var injector = HawtioCore.injector; + return injector ? injector.get(name) : null; + } + + export function createResource(thing:string, urlTemplate:string, $resource: ng.resource.IResourceService, KubernetesModel) { + var prefix = prefixForType(thing); + if (!prefix) { + log.debug("Invalid type given: ", thing); + return null; + } + + var params = { + namespace: currentKubernetesNamespace + } + switch (thing) { + case WatchTypes.NAMESPACES: + case WatchTypes.OAUTH_CLIENTS: + case WatchTypes.NODES: + case WatchTypes.PROJECTS: + case WatchTypes.OAUTH_CLIENTS: + case WatchTypes.PERSISTENT_VOLUMES: + params = {}; + } + + var url = UrlHelpers.join(masterApiUrl(), prefix, urlTemplate); + log.debug("Url for ", thing, ": ", url); + var resource = $resource(url, null, { + query: { method: 'GET', isArray: false, params: params}, + create: { method: 'POST', params: params}, + save: { method: 'PUT', params: params}, + delete: { method: 'DELETE', params: _.extend({ + id: '@id' + }, params)} + }); + return resource; + } + + export function imageRepositoriesRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/imagestreams"); + } + + export function deploymentConfigsRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/deploymentconfigs"); + } + + export function buildsRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/builds"); + } + + export function buildConfigHooksRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/buildconfighooks"); + } + + export function buildConfigsRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/buildconfigs"); + } + + export function routesRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/routes"); + } + + export function templatesRestURL() { + return UrlHelpers.join(openshiftApiUrl(), kubernetesNamespacePath(), "/templates"); + } + + export function getNamespace(entity) { + var answer = Core.pathGet(entity, ["metadata", "namespace"]); + return answer ? answer : currentKubernetesNamespace(); + } + + export function getLabels(entity) { + var answer = Core.pathGet(entity, ["metadata", "labels"]); + return answer ? answer : {}; + } + + export function getName(entity) { + if (angular.isString(entity)) { + return entity; + } + return Core.pathGet(entity, ["metadata", "name"]) || Core.pathGet(entity, "name") || Core.pathGet(entity, "id"); + } + + export function getKind(entity) { + return Core.pathGet(entity, ["metadata", "kind"]) || Core.pathGet(entity, "kind"); + } + + export function getSelector(entity) { + return Core.pathGet(entity, ["spec", "selector"]); + } + + export function getHost(pod) { + return Core.pathGet(pod, ["spec", "host"]) || Core.pathGet(pod, ["spec", "nodeName"]) || Core.pathGet(pod, ["status", "hostIP"]); + } + + export function getStatus(pod) { + return Core.pathGet(pod, ["status", "phase"]); + } + + export function getPorts(service) { + return Core.pathGet(service, ["spec", "ports"]); + } + + export function getCreationTimestamp(entity) { + return Core.pathGet(entity, ["metadata", "creationTimestamp"]); + }; + + //var fabricDomain = Fabric.jmxDomain; + var fabricDomain = "io.fabric8"; + export var mbean = fabricDomain + ":type=Kubernetes"; + export var managerMBean = fabricDomain + ":type=KubernetesManager"; + export var appViewMBean = fabricDomain + ":type=AppView"; + + export function isKubernetes(workspace?) { + // return workspace.treeContainsDomainAndProperties(fabricDomain, {type: "Kubernetes"}); + return true; + } + + export function isKubernetesTemplateManager(workspace?) { + // return workspace.treeContainsDomainAndProperties(fabricDomain, {type: "KubernetesTemplateManager"}); + return true; + } + + export function isAppView(workspace?) { + // return workspace.treeContainsDomainAndProperties(fabricDomain, {type: "AppView"}); + return true; + } + + export function getStrippedPathName():string { + var pathName = Core.trimLeading((this.$location.path() || '/'), "#"); + pathName = pathName.replace(/^\//, ''); + return pathName; + } + + export function linkContains(...words:String[]):boolean { + var pathName = this.getStrippedPathName(); + return _.every(words, (word:string) => pathName.indexOf(word) !== 0); + } + + + /** + * Returns true if the given link is active. The link can omit the leading # or / if necessary. + * The query parameters of the URL are ignored in the comparison. + * @method isLinkActive + * @param {String} href + * @return {Boolean} true if the given link is active + */ + export function isLinkActive(href:string):boolean { + // lets trim the leading slash + var pathName = getStrippedPathName(); + + var link = Core.trimLeading(href, "#"); + link = link.replace(/^\//, ''); + // strip any query arguments + var idx = link.indexOf('?'); + if (idx >= 0) { + link = link.substring(0, idx); + } + if (!pathName.length) { + return link === pathName; + } else { + return _.startsWith(pathName, link); + } + } + + export function setJson($scope, id, collection) { + $scope.id = id; + if (!$scope.fetched) { + return; + } + if (!id) { + $scope.json = ''; + return; + } + if (!collection) { + return; + } + var item = collection.find((item) => { return getName(item) === id; }); + if (item) { + $scope.json = angular.toJson(item, true); + $scope.item = item; + } else { + $scope.id = undefined; + $scope.json = ''; + $scope.item = undefined; + } + } + + /** + * Returns the labels text string using the key1=value1,key2=value2,.... format + */ + export function labelsToString(labels, seperatorText = labelFilterTextSeparator) { + var answer = ""; + angular.forEach(labels, (value, key) => { + var separator = answer ? seperatorText : ""; + + answer += separator + key + "=" + value; + }); + return answer; + } + + + export function initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL) { + $scope.baseUri = Core.trimTrailing(Core.url("/") || "", "/") || ""; + + var injector = HawtioCore.injector; + + function hasService(name) { + if (injector) { + var ServiceRegistry = injector.get("ServiceRegistry"); + if (ServiceRegistry) { + return ServiceRegistry.hasService(name); + } + } + return false; + } + + $scope.hasServiceKibana = () => hasService(kibanaServiceName); + $scope.hasServiceGogs = () => hasService(gogsServiceName); + $scope.hasServiceForge = () => hasService(fabric8ForgeServiceName); + $scope.hasServiceApiman = () => hasService(apimanServiceName); + + $scope.viewTemplates = () => { + var returnTo = $location.url(); + $location.path('/kubernetes/templates').search({'returnTo': returnTo}); + }; + + $scope.namespace = $routeParams.namespace || $scope.namespace || KubernetesState.selectedNamespace || defaultNamespace; + if ($scope.namespace != KubernetesState.selectedNamespace) { + KubernetesState.selectedNamespace = $scope.namespace; + + // lets show page is going to reload + if ($scope.model) { + $scope.model.fetched = false; + } + } + Kubernetes.setCurrentKubernetesNamespace($scope.namespace); + + $scope.forgeEnabled = isForgeEnabled(); + + $scope.projectId = $routeParams["project"] || $scope.projectId || $scope.id; + var showProjectNavBars = false; + if ($scope.projectId && showProjectNavBars) { + $scope.breadcrumbConfig = Developer.createProjectBreadcrumbs($scope.projectId); + $scope.subTabConfig = Developer.createProjectSubNavBars($scope.projectId, null, $scope); + } else { + $scope.breadcrumbConfig = Developer.createEnvironmentBreadcrumbs($scope, $location, $routeParams); + $scope.subTabConfig = Developer.createEnvironmentSubNavBars($scope, $location, $routeParams); + } + + if ($scope.projectId) { + $scope.$projectLink = Developer.projectLink($scope.projectId); + } + + $scope.link = (href) => { + if (!href) { + return href; + } + if ($scope.$projectLink) { + return Developer.namespaceLink($scope, $routeParams, href.replace(/^\/kubernetes/, '')); + } else { + return href; + } + } + + $scope.codeMirrorOptions = { + lineWrapping : true, + lineNumbers: true, + readOnly: 'nocursor', + mode: {name: "javascript", json: true} + }; + + $scope.resizeDialog = { + controller: null, + newReplicas: 0, + dialog: new UI.Dialog(), + onOk: () => { + var resizeDialog = $scope.resizeDialog; + resizeDialog.dialog.close(); + resizeController($http, KubernetesApiURL, resizeDialog.controller, resizeDialog.newReplicas, () => { log.debug("updated number of replicas"); }) + }, + open: (controller) => { + var resizeDialog = $scope.resizeDialog; + resizeDialog.controller = controller; + resizeDialog.newReplicas = Core.pathGet(controller, ["status", "replicas"]); + resizeDialog.dialog.open(); + + $timeout(() => { + $('#replicas').focus(); + }, 50); + }, + close: () => { + $scope.resizeDialog.dialog.close(); + } + }; + + $scope.triggerBuild = (buildConfig) => { + var url = buildConfig.$triggerUrl; + console.log("triggering build at url: " + url); + if (url) { + //var data = {}; + var data = null; + var config = { + headers: { + 'Content-Type': "application/json" + } + }; + var name = Core.pathGet(buildConfig, ["metadata", "name"]); + Core.notification('info', "Triggering build " + name); + $http.post(url, data, config). + success(function (data, status, headers, config) { + console.log("trigger worked! got data " + angular.toJson(data, true)); + // TODO should we show some link to the build + Core.notification('info', "Building " + name); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + Core.notification('error', "Failed to trigger build for " + name + ". Returned code: " + status + " " + data); + }); + }; + } + + // update the URL if the filter is changed + $scope.$watch("tableConfig.filterOptions.filterText", (text) => { + //var filterText = Kubernetes.findValeOfLabels(text); + $location.search("q", text); + }); + + $scope.$on("labelFilterUpdate", ($event, text) => { + var filterOptions = ($scope.tableConfig || {}).filterOptions || {}; + var currentFilter = filterOptions.filterText; + if (Core.isBlank(currentFilter)) { + filterOptions.filterText = text; + }else{ + var expressions = currentFilter.split(/\s+/); + if (expressions.indexOf(text) !== -1) { + // lets exclude this filter expression + expressions = expressions.remove(text); + filterOptions.filterText = expressions.join(" "); + } else { + filterOptions.filterText = currentFilter + " " + text; + } + } + $scope.id = undefined; + }); + + } + + /** + * Returns the number of pods that are ready + */ + export function readyPodCount(service) { + var count = 0; + angular.forEach((service || {}).$pods, (pod)=> { + if (pod.$ready) { + count++; + } + }); + return count; + } + + /** + * Returns the service link URL for either the service name or the service object + */ + export function serviceLinkUrl(service, httpOnly = false) { + if (angular.isObject(service)) { + var portalIP = service.$host; + // lets assume no custom port for now for external routes + var port = null; + var protocol = "http://"; + var spec = service.spec; + if (spec) { + if (!portalIP) { + portalIP = spec.portalIP; + } + var hasHttps = false; + var hasHttp = false; + angular.forEach(spec.ports, (portSpec) => { + var p = portSpec.port; + if (p) { + if (p === 443) { + hasHttps = true; + } else if (p === 80) { + hasHttp = true; + } + if (!port) { + port = p; + } + } + }); + if (!hasHttps && !hasHttp && port) { + // lets treat 8080 as http which is a common service to export + if (port === 8080) { + hasHttp = true; + } else if (port === 8443) { + hasHttps = true; + } + } + } + if (portalIP) { + if (hasHttps) { + return "https://" + portalIP; + } else if (hasHttp) { + return "http://" + portalIP; + } else if (!httpOnly) { + if (port) { + return protocol + portalIP + ":" + port + "/"; + } else { + return protocol + portalIP; + } + } + } + } else if (service) { + var serviceId = service.toString(); + if (serviceId) { + var ServiceRegistry = getServiceRegistry(); + if (ServiceRegistry) { + return ServiceRegistry.serviceLink(serviceId) || ""; + } + } + } + return ""; + } + + + /** + * Returns the total number of counters for the podCounters object + */ + export function podCounterTotal($podCounters) { + var answer = 0; + if ($podCounters) { + angular.forEach(["ready", "valid", "waiting", "error"], (name) => { + var value = $podCounters[name] || 0; + answer += value; + }); + } + return answer; + } + + /** + * Given the list of pods lets iterate through them and find all pods matching the selector + * and return counters based on the status of the pod + */ + export function createPodCounters(selector, pods, outputPods = [], podLinkQuery = null, podLinkUrl = null) { + if (!podLinkUrl) { + podLinkUrl = "/kubernetes/pods"; + } + var filterFn; + if (angular.isFunction(selector)) { + filterFn = selector; + } else { + filterFn = (pod) => selectorMatches(selector, getLabels(pod)); + } + var answer = { + podsLink: "", + ready: 0, + valid: 0, + waiting: 0, + error: 0 + }; + if (selector) { + if (!podLinkQuery) { + podLinkQuery = Kubernetes.labelsToString(selector, " "); + } + answer.podsLink = podLinkUrl + "?q=" + encodeURIComponent(podLinkQuery); + angular.forEach(pods, pod => { + if (filterFn(pod)) { + outputPods.push(pod); + var status = getStatus(pod); + if (status) { + var lower = status.toLowerCase(); + if (lower.startsWith("run")) { + if (isReady(pod)) { + answer.ready += 1; + } else { + answer.valid += 1; + } + } else if (lower.startsWith("wait") || lower.startsWith("pend")) { + answer.waiting += 1; + } else if (lower.startsWith("term") || lower.startsWith("error") || lower.startsWith("fail")) { + answer.error += 1; + } + } else { + answer.error += 1; + } + } + }); + } + return answer; + } + + /** + * Converts the given json into an array of items. If the json contains a nested set of items then that is sorted; so that services + * are processed first; then turned into an array. Otherwise the json is put into an array so it can be processed polymorphically + */ + export function convertKubernetesJsonToItems(json) { + var items = json.items; + if (angular.isArray(items)) { + // TODO we could check for List or Config types here and warn if not + + // sort the services first + var answer = []; + items.forEach((item) => { + if (item.kind === "Service") { + answer.push(item); + } + }); + items.forEach((item) => { + if (item.kind !== "Service") { + answer.push(item); + } + }); + return answer; + } else { + return [json]; + } + } + + export function isV1beta1Or2() { + return defaultApiVersion === "v1beta1" || defaultApiVersion === "v1beta2"; + } + + /** + * Returns a link to the detail page for the given entity + */ + export function entityPageLink(obj) { + if (obj) { + function getLink(entity) { + var viewLink = entity["$viewLink"]; + if (viewLink) { + return viewLink; + } + var id = getName(entity); + var kind = getKind(entity); + if (kind && id) { + var path = kind.substring(0, 1).toLowerCase() + kind.substring(1) + "s"; + var namespace = getNamespace(entity); + if (namespace && !isIgnoreNamespaceKind(kind)) { + return Core.url(UrlHelpers.join('/kubernetes/namespace', namespace, path, id)); + } else { + return Core.url(UrlHelpers.join('/kubernetes', path, id)); + } + } + } + var baseLink = getLink(obj); + if (!HawtioCore.injector || !baseLink) { + return baseLink; + } + var $routeParams = HawtioCore.injector.get('$routeParams'); + var projectId = $routeParams['project'] || $routeParams['project']; + if (!projectId) { + return baseLink; + } + return UrlHelpers.join(Developer.projectLink(projectId), baseLink.replace(/^\/kubernetes\//, '')); + } + return null; + } + + + export function resourceKindToUriPath(kind) { + var kindPath = kind.toLowerCase() + "s"; + if (kindPath === "replicationControllers" && !isV1beta1Or2()) { + kindPath = "replicationcontrollers"; + } + return kindPath; + } + + function isIgnoreNamespaceKind(kind) { + return kind === "Host" || kind === "Minion"; + } + + /** + * Returns the root URL for the kind + */ + export function kubernetesUrlForKind(KubernetesApiURL, kind, namespace = null, path = null) { + var pathSegment = ""; + if (path) { + pathSegment = "/" + Core.trimLeading(path, "/"); + } + var kindPath = resourceKindToUriPath(kind); + var ignoreNamespace = isIgnoreNamespaceKind(kind); + if (isV1beta1Or2() || ignoreNamespace) { + var postfix = ""; + if (namespace && !ignoreNamespace) { + postfix = "?namespace=" + namespace; + } + return UrlHelpers.join(KubernetesApiURL, kindPath, pathSegment, postfix); + } else { + return UrlHelpers.join(KubernetesApiURL, "/namespaces/", namespace , kindPath, pathSegment); + } + }; + + /** + * Returns the base URL for the kind of kubernetes resource or null if it cannot be found + */ + export function kubernetesUrlForItemKind(KubernetesApiURL, json) { + var kind = json.kind; + if (kind) { + return kubernetesUrlForKind(KubernetesApiURL, kind, json.namespace); + } else { + log.warn("Ignoring missing kind " + kind + " for kubernetes json: " + angular.toJson(json)); + return null; + } + } + + export function kubernetesProxyUrlForService(KubernetesApiURL, service, path = null) { + var pathSegment = ""; + if (path) { + pathSegment = "/" + Core.trimLeading(path, "/"); + } else { + pathSegment = "/"; + } + var namespace = getNamespace(service); + if (isV1beta1Or2()) { + var postfix = "?namespace=" + namespace; + return UrlHelpers.join(KubernetesApiURL, "/proxy", kubernetesNamespacePath(), "/services/" + getName(service) + pathSegment + postfix); + } else { + return UrlHelpers.join(KubernetesApiURL, "/proxy/namespaces/", namespace, "/services/" + getName(service) + pathSegment); + } + } + + + export function kubernetesProxyUrlForServiceCurrentNamespace(service, path = null) { + var apiPrefix = UrlHelpers.join(kubernetesApiUrl()); + return kubernetesProxyUrlForService(apiPrefix, service, path); + + } + export function buildConfigRestUrl(id) { + return UrlHelpers.join(buildConfigsRestURL(), id); + } + + export function deploymentConfigRestUrl(id) { + return UrlHelpers.join(deploymentConfigsRestURL(), id); + } + + export function imageRepositoryRestUrl(id) { + return UrlHelpers.join(imageRepositoriesRestURL(), id); + } + + export function buildRestUrl(id) { + return UrlHelpers.join(buildsRestURL(), id); + } + + export function buildLogsRestUrl(id) { + return UrlHelpers.join(buildsRestURL(), id, "log"); + } + + /** + * Runs the given application JSON + */ + export function runApp($location, $scope, $http, KubernetesApiURL, json, name = "App", onSuccessFn = null, namespace = null, onCompleteFn = null) { + if (json) { + if (angular.isString(json)) { + json = angular.fromJson(json); + } + name = name || "App"; + var postfix = namespace ? " in namespace " + namespace : ""; + Core.notification('info', "Running " + name + postfix); + + var items = convertKubernetesJsonToItems(json); + angular.forEach(items, (item) => { + var url = kubernetesUrlForItemKind(KubernetesApiURL, item); + if (url) { + $http.post(url, item). + success(function (data, status, headers, config) { + log.debug("Got status: " + status + " on url: " + url + " data: " + data + " after posting: " + angular.toJson(item)); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(); + } + Core.$apply($scope); + }). + error(function (data, status, headers, config) { + var message = null; + if (angular.isObject(data)) { + message = data.message; + var reason = data.reason; + if (reason === "AlreadyExists") { + // lets ignore duplicates + log.debug("entity already exists at " + url); + return; + } + } + if (!message) { + message = "Failed to POST to " + url + " got status: " + status; + } + log.warn("Failed to save " + url + " status: " + status + " response: " + angular.toJson(data, true)); + Core.notification('error', message); + }); + } + }); + } + } + + + /** + * Returns true if the current status of the pod is running + */ + export function isRunning(podCurrentState) { + var status = (podCurrentState || {}).phase; + if (status) { + var lower = status.toLowerCase(); + return lower.startsWith("run"); + } else { + return false; + } + } + + /** + * Returns true if the labels object has all of the key/value pairs from the selector + */ + export function selectorMatches(selector, labels) { + if (angular.isObject(labels)) { + var answer = true; + var count = 0; + angular.forEach(selector, (value, key) => { + count++; + if (answer && labels[key] !== value) { + answer = false; + } + }); + return answer && count > 0; + } else { + return false; + } + } + + /** + * Returns the service registry + */ + export function getServiceRegistry() { + var injector = HawtioCore.injector; + return injector ? injector.get("ServiceRegistry") : null; + } + + + /** + * Returns a link to the kibana logs web application + */ + export function kibanaLogsLink(ServiceRegistry) { + var link = ServiceRegistry.serviceLink(kibanaServiceName); + if (link) { + if (!link.endsWith("/")) { + link += "/"; + } + return link + "#/dashboard/Fabric8"; + } else { + return null; + } + } + + export function openLogsForPods(ServiceRegistry, $window, namespace, pods) { + var link = kibanaLogsLink(ServiceRegistry); + if (link) { + var query = ""; + var count = 0; + angular.forEach(pods, (item) => { + var id = getName(item); + if (id) { + var space = query ? " OR " : ""; + count++; + query += space + '"' + id + '"'; + } + }); + if (query) { + if (count > 1) { + query = "(" + query + ")"; + } + query = 'kubernetes.namespace_name:"' + namespace + '" AND kubernetes.pod_name:' + query; + link += "?_a=(query:(query_string:(query:'" + query + "')))"; + var newWindow = $window.open(link, "viewLogs"); + } + } + } + + export function resizeController($http, KubernetesApiURL, replicationController, newReplicas, onCompleteFn = null) { + var id = getName(replicationController); + var namespace = getNamespace(replicationController) || ""; + var url = kubernetesUrlForKind(KubernetesApiURL, "ReplicationController", namespace, id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + var desiredState = data.spec; + if (!desiredState) { + desiredState = {}; + data.spec = desiredState; + } + desiredState.replicas = newReplicas; + $http.put(url, data). + success(function (data, status, headers, config) { + log.debug("updated controller " + url); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to save " + url + " " + data + " " + status); + }); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + + export function statusTextToCssClass(text, ready = false) { + if (text) { + var lower = text.toLowerCase(); + if (lower.startsWith("run") || lower.startsWith("ok")) { + if (!ready) { + return "fa fa-spinner fa-spin green"; + } + return 'fa fa-play-circle green'; + } else if (lower.startsWith("wait") || lower.startsWith("pend")) { + return 'fa fa-download'; + } else if (lower.startsWith("term") || lower.startsWith("error") || lower.startsWith("fail")) { + return 'fa fa-off orange'; + } else if (lower.startsWith("succeeded")) { + return 'fa fa-check-circle-o green'; + } + } + return 'fa fa-question red'; + } + + export function podStatus(pod) { + return getStatus(pod); + } + + export function isReady(pod) { + var status = pod.status || {}; + var answer = false; + angular.forEach(status.conditions, (condition) => { + var t = condition.type; + if (t && t === "Ready") { + var status = condition.status; + if (status === "True") { + answer = true; + } + } + }); + return answer; + } + + export function createAppViewPodCounters(appView) { + var array = []; + var map = {}; + var pods = appView.pods; + var lowestDate = null; + angular.forEach(pods, pod => { + var selector = getLabels(pod); + var selectorText = Kubernetes.labelsToString(selector, " "); + var answer = map[selector]; + if (!answer) { + answer = { + labelText: selectorText, + podsLink: UrlHelpers.join("/kubernetes/namespace/", pod.metadata.namespace, "pods?q=" + encodeURIComponent(selectorText)), + valid: 0, + waiting: 0, + error: 0 + }; + map[selector] = answer; + array.push(answer); + } + var status = (podStatus(pod) || "Error").toLowerCase(); + if (status.startsWith("run") || status.startsWith("ok")) { + answer.valid += 1; + } else if (status.startsWith("wait") || status.startsWith("pwnd")) { + answer.waiting += 1; + } else { + answer.error += 1; + } + var creationTimestamp = getCreationTimestamp(pod); + if (creationTimestamp) { + var d = new Date(creationTimestamp); + if (!lowestDate || d < lowestDate) { + lowestDate = d; + } + } + }); + appView.$creationDate = lowestDate; + return array; + } + + export function createAppViewServiceViews(appView) { + var array = []; + var pods = appView.pods; + angular.forEach(pods, pod => { + var id = getName(pod); + if (id) { + var abbrev = id; + var idx = id.indexOf("-"); + if (idx > 1) { + abbrev = id.substring(0, idx); + } + pod.idAbbrev = abbrev; + } + pod.statusClass = statusTextToCssClass(podStatus(pod), isReady(pod)); + }); + + var services = appView.services || []; + var replicationControllers = appView.replicationControllers || []; + var size = Math.max(services.length, replicationControllers.length, 1); + var appName = appView.$info.name; + for (var i = 0; i < size; i++) { + var service = services[i]; + var replicationController = replicationControllers[i]; + var controllerId = getName(replicationController); + var name = getName(service) || controllerId; + var address = Core.pathGet(service, ["spec", "portalIP"]); + if (!name && pods.length) { + name = pods[0].idAbbrev; + } + if (!appView.$info.name) { + appView.$info.name = name; + } + if (!appView.id && pods.length) { + appView.id = getName(pods[0]); + } + if (i > 0) { + appName = name; + } + var podCount = pods.length; + var podCountText = podCount + " pod" + (podCount > 1 ? "s" : ""); + var view = { + appName: appName || name, + name: name, + createdDate: appView.$creationDate, + podCount: podCount, + podCountText: podCountText, + address: address, + controllerId: controllerId, + service: service, + replicationController: replicationController, + pods: pods + }; + array.push(view); + } + return array; + } + + /** + * converts a git path into an accessible URL for the browser + */ + export function gitPathToUrl(iconPath, branch = "master") { + return (HawtioCore.injector.get('AppLibraryURL') || '') + "/git/" + branch + iconPath; + } + + function asDate(value) { + return value ? new Date(value) : null; + } + + export function enrichBuildConfig(buildConfig, sortedBuilds) { + if (buildConfig) { + var triggerUrl:string = null; + var metadata = buildConfig.metadata || {}; + var name = metadata.name; + buildConfig.$name = name; + var projectLink = Developer.projectLink(name); + var ns = metadata.namespace || currentKubernetesNamespace(); + buildConfig.$namespace = ns; + buildConfig.environments = []; + buildConfig.$creationDate = asDate(Kubernetes.getCreationTimestamp(buildConfig)); + buildConfig.$labelsText = Kubernetes.labelsToString(getLabels(buildConfig)); + + if (name) { + buildConfig.$viewLink = UrlHelpers.join("workspaces", ns, "projects", name, "environments"); + buildConfig.$editLink = UrlHelpers.join("workspaces", ns, "projects", name, "buildConfigEdit"); + + angular.forEach([false, true], (flag) => { + angular.forEach(buildConfig.triggers, (trigger) => { + if (!triggerUrl) { + var type = trigger.type; + if (type === "generic" || flag) { + var generic = trigger[type]; + if (type && generic) { + var secret = generic.secret; + if (secret) { + triggerUrl = UrlHelpers.join(buildConfigHooksRestURL(), name, secret, type); + buildConfig.$triggerUrl = triggerUrl; + } + } + } + } + }); + }); + + // lets find the latest build... + if (sortedBuilds) { + buildConfig.$lastBuild = _.find(sortedBuilds, { + metadata: { + labels: { + buildconfig: name + } + } + }); + } + } + var $fabric8Views = {}; + + function defaultPropertiesIfNotExist(name, object, autoCreate = false) { + var view = $fabric8Views[name]; + if (autoCreate && !view) { + view = {} + $fabric8Views[name] = view; + } + if (view) { + angular.forEach(object, (value, property) => { + var current = view[property]; + if (!current) { + view[property] = value; + } + }); + } + } + + function defaultPropertiesIfNotExistStartsWith(prefix, object, autoCreate = false) { + angular.forEach($fabric8Views, (view, name) => { + if (view && name.startsWith(prefix)) { + angular.forEach(object, (value, property) => { + var current = view[property]; + if (!current) { + view[property] = value; + } + }); + } + }); + } + + var labels = metadata.labels || {}; + var annotations = metadata.annotations || {}; + + // lets default the repo and user + buildConfig.$user = annotations["fabric8.jenkins/user"] || labels["user"]; + buildConfig.$repo = annotations["fabric8.jenkins/repo"] || labels["repo"]; + + angular.forEach(annotations, (value, key) => { + var parts = key.split('/', 2); + if (parts.length > 1) { + var linkId = parts[0]; + var property = parts[1]; + if (linkId && property && linkId.startsWith("fabric8.link")) { + var link = $fabric8Views[linkId]; + if (!link) { + link = { + class: linkId + }; + $fabric8Views[linkId] = link; + } + link[property] = value; + } + } + }); + + if (buildConfig.$user && buildConfig.$repo) { + // browse gogs repo view + var gogsUrl = serviceLinkUrl(gogsServiceName); + if (gogsUrl) { + defaultPropertiesIfNotExist("fabric8.link.browseGogs.view", { + label: "Browse...", + url: UrlHelpers.join(gogsUrl, buildConfig.$user, buildConfig.$repo), + description: "Browse the source code of this repository", + iconClass: "fa fa-external-link" + }, true); + } + + // run forge commands view + defaultPropertiesIfNotExist("fabric8.link.forgeCommand.view", { + label: "Command...", + url: UrlHelpers.join(projectLink, "/forge/commands/user", buildConfig.$user, buildConfig.$repo), + description: "Perform an action on this project", + iconClass: "fa fa-play-circle" + }, true); + + + // configure devops view + defaultPropertiesIfNotExist("fabric8.link.forgeCommand.devops.settings", { + label: "Settings", + url: UrlHelpers.join(projectLink, "/forge/command/devops-edit/user", buildConfig.$user, buildConfig.$repo), + description: "Configure the DevOps settings for this project", + iconClass: "fa fa-pencil-square-o" + }, true); + + } + + // add some icons and descriptions + defaultPropertiesIfNotExist("fabric8.link.repository.browse", { + label: "Browse...", + description: "Browse the source code of this repository", + iconClass: "fa fa-external-link" + }); + defaultPropertiesIfNotExist("fabric8.link.jenkins.job", { + iconClass: "fa fa-tasks", + description: "View the Jenkins Job for this build" + }); + defaultPropertiesIfNotExist("fabric8.link.jenkins.monitor", { + iconClass: "fa fa-tachometer", + description: "View the Jenkins Monitor dashboard for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.jenkins.pipeline", { + iconClass: "fa fa-arrow-circle-o-right", + description: "View the Jenkins Pipeline for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.letschat.room", { + iconClass: "fa fa-comment", + description: "Chat room for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.letschat.room", { + iconClass: "fa fa-comment", + description: "Chat room for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.taiga", { + iconClass: "fa fa-check-square-o", + description: "Issue tracker for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.issues", { + iconClass: "fa fa-check-square-o", + description: "Issues for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.releases", { + iconClass: "fa fa-tag", + description: "Issues for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.taiga.team", { + iconClass: "fa fa-users", + description: "Team members for this project" + }); + defaultPropertiesIfNotExist("fabric8.link.team", { + iconClass: "fa fa-users", + description: "Team members for this project" + }); + defaultPropertiesIfNotExistStartsWith("fabric8.link.environment.", { + iconClass: "fa fa-cloud", + description: "The kubernetes namespace for this environment" + }); + + + // lets put the views into sections... + var $fabric8CodeViews = {}; + var $fabric8BuildViews = {}; + var $fabric8TeamViews = {}; + var $fabric8EnvironmentViews = {}; + angular.forEach($fabric8Views, (value, key) => { + var view; + if (key.indexOf("taiga") > 0 || key.indexOf(".issue") > 0 || key.indexOf("letschat") > 0|| key.indexOf(".team") > 0) { + view = $fabric8TeamViews; + } else if (key.indexOf("jenkins") > 0) { + view = $fabric8BuildViews; + } else if (key.indexOf(".environment.") > 0) { + view = $fabric8EnvironmentViews; + } else { + view = $fabric8CodeViews; + } + view[key] = value; + }); + + + buildConfig.$fabric8Views = $fabric8Views; + buildConfig.$fabric8CodeViews = $fabric8CodeViews; + buildConfig.$fabric8BuildViews = $fabric8BuildViews; + buildConfig.$fabric8EnvironmentViews = $fabric8EnvironmentViews; + buildConfig.$fabric8TeamViews = $fabric8TeamViews; + + var $jenkinsJob = annotations["fabric8.io/jenkins-job"]; + if (!$jenkinsJob && $fabric8Views["fabric8.link.jenkins.job"]) { + $jenkinsJob = name; + } + buildConfig.$jenkinsJob = $jenkinsJob; + + angular.forEach($fabric8EnvironmentViews, (env) => { + var c = env.class; + var prefix = "fabric8.link.environment."; + if (c && c.startsWith(prefix)) { + var ens = c.substring(prefix.length); + env.namespace = ens; + env.url = UrlHelpers.join("/workspaces", ns, "projects", name, "namespace", ens); + } + buildConfig.environments.push(env); + }); + if (!buildConfig.environments.length) { + // lets create a single environment + var ens = ns; + var env = { + namespace: ens, + label: "Current", + description: "The environemnt that this project is built and run inside", + iconClass: "fa fa-cloud", + url: UrlHelpers.join("/workspaces", ns, "projects", name, "namespace", ens) + }; + buildConfig.environments.push(env); + + } + + buildConfig.environments = buildConfig.environments.reverse(); + + buildConfig.tools = []; + angular.forEach($fabric8CodeViews, (env) => { + buildConfig.tools.push(env); + }); + angular.forEach($fabric8TeamViews, (env) => { + buildConfig.tools.push(env); + }); + + } + } + + export function enrichBuildConfigs(buildConfigs, sortedBuilds = null) { + angular.forEach(buildConfigs, (buildConfig) => { + enrichBuildConfig(buildConfig, sortedBuilds); + }); + return buildConfigs; + } + + export function enrichBuilds(builds) { + angular.forEach(builds, (build) => { + enrichBuild(build); + }); + return _.sortBy(builds, "$creationDate").reverse(); + } + + export function enrichBuild(build) { + if (build) { + var metadata = build.metadata || {}; + var annotations = metadata.annotations || {}; + var name = getName(build); + var namespace = getNamespace(build); + build.$name = name; + build.$namespace = namespace; + + var nameArray = name.split("-"); + var nameArrayLength = nameArray.length; + build.$shortName = (nameArrayLength > 4) ? nameArray.slice(0, nameArrayLength - 4).join("-") : name.substring(0, 30); + + var labels = getLabels(build); + var configId = labels.buildconfig; + build.$configId = configId; + if (configId) { + //build.$configLink = UrlHelpers.join("kubernetes/buildConfigs", configId); + build.$configLink = UrlHelpers.join("workspaces", currentKubernetesNamespace(), "projects", configId); + } + var creationTimestamp = getCreationTimestamp(build); + if (creationTimestamp) { + var d = new Date(creationTimestamp); + build.$creationDate = d; + } + if (name) { + //build.$viewLink = UrlHelpers.join("kubernetes/builds", name); + var projectLink = UrlHelpers.join("workspaces", currentKubernetesNamespace(), "projects", configId); + build.$viewLink = UrlHelpers.join(projectLink, "builds", name); + //build.$logsLink = UrlHelpers.join("kubernetes/buildLogs", name); + build.$logsLink = UrlHelpers.join(projectLink, "buildLogs", name); + } + build.podName = build.podName || annotations["openshift.io/build.pod-name"]; + var podName = build.podName; + if (podName && namespace) { + var podNameArray = podName.split("-"); + var podNameArrayLength = podNameArray.length; + build.$podShortName = (podNameArrayLength > 5) ? podNameArray[podNameArrayLength - 5] : podName.substring(0, 30); + build.$podLink = UrlHelpers.join("kubernetes/namespace", namespace, "pods", podName); + } + } + return build; + } + + + export function enrichDeploymentConfig(deploymentConfig) { + if (deploymentConfig) { + var triggerUrl:string = null; + var name = Core.pathGet(deploymentConfig, ["metadata", "name"]); + deploymentConfig.$name = name; + var found = false; + angular.forEach(deploymentConfig.triggers, (trigger) => { + var type = trigger.type; + if (!deploymentConfig.$imageChangeParams && type === "ImageChange") { + var imageChangeParams = trigger.imageChangeParams; + if (imageChangeParams) { + var containerNames = imageChangeParams.containerNames || []; + imageChangeParams.$containerNames = containerNames.join(" "); + deploymentConfig.$imageChangeParams = imageChangeParams; + } + } + }); + } + } + + export function enrichDeploymentConfigs(deploymentConfigs) { + angular.forEach(deploymentConfigs, (deploymentConfig) => { + enrichDeploymentConfig(deploymentConfig); + }); + return deploymentConfigs; + } + + + export function enrichEvent(event) { + if (event) { + var metadata = event.metadata || {}; + + var firstTimestamp = event.firstTimestamp; + if (firstTimestamp) { + var d = new Date(firstTimestamp); + event.$firstTimestamp = d; + } + var lastTimestamp = event.lastTimestamp; + if (lastTimestamp) { + var d = new Date(lastTimestamp); + event.$lastTimestamp = d; + } + var labels = angular.copy(event.source || {}); + var involvedObject = event.involvedObject || {}; + var name = involvedObject.name; + var kind = involvedObject.kind; + if (name) { + labels['name'] = name; + } + if (kind) { + labels['kind'] = kind; + } + event.$labelsText = Kubernetes.labelsToString(labels); + + } + } + + export function enrichEvents(events, model = null) { + angular.forEach(events, (event) => { + enrichEvent(event); + }); + + // lets update links to the events for each pod and RC + if (model) { + function clearEvents(entity) { + entity.$events = []; + entity.$eventsLink = null; + entity.$eventCount = 0; + } + + function updateEvent(entity, event) { + if (entity) { + entity.$events.push(event); + if (!entity.$eventsLink) { + entity.$eventsLink = UrlHelpers.join("/kubernetes/namespace/", currentKubernetesNamespace(), "events") + "?q=kind%3D" + entity.kind + "%20name%3D" + entity.metadata.name; + } + entity.$eventCount = entity.$events.length; + } + } + + var pods = model.pods || []; + var rcs = model.replicationControllers || []; + angular.forEach(pods, clearEvents); + angular.forEach(rcs, clearEvents); + + angular.forEach(events, (event) => { + var involvedObject = event.involvedObject || {}; + var name = involvedObject.name; + var kind = involvedObject.kind; + var ns = model.currentNamespace(); + if (name && kind && ns) { + var entity = null; + if (kind === "ReplicationController") { + entity = model.getReplicationController(ns, name); + } else if (kind === "Pod") { + entity = model.getPod(ns, name); + } + if (entity) { + updateEvent(entity, event); + } + } + }); + } + return events; + } + + export function enrichImageRepository(imageRepository) { + if (imageRepository) { + var triggerUrl:string = null; + var name = Core.pathGet(imageRepository, ["metadata", "name"]); + imageRepository.$name = name; + } + } + + export function enrichImageRepositories(imageRepositories) { + angular.forEach(imageRepositories, (imageRepository) => { + enrichImageRepository(imageRepository); + }); + return imageRepositories; + } + + + var labelColors = { + 'batch': 'k8s-badge-batch', + 'region': 'k8s-badge-region', + 'type': 'k8s-badge-type', + 'system': 'k8s-badge-system' + }; + + export function containerLabelClass(labelType:string) { + if (!(labelType in labelColors)) { + return 'mouse-pointer'; + } + else return labelColors[labelType] + ' mouse-pointer'; + } + + + /** + * Returns true if the fabric8 forge plugin is enabled + */ + export function isForgeEnabled() { + // TODO should return true if the service "fabric8-forge" is valid + return true; + } + + /** + * Returns the current kubernetes selected namespace or the default one + */ + export function currentKubernetesNamespace() { + var injector = HawtioCore.injector; + if (injector) { + var KubernetesState = injector.get("KubernetesState") || {}; + return KubernetesState.selectedNamespace || defaultNamespace; + } + return defaultNamespace; + } + + export function setCurrentKubernetesNamespace(ns) { + if (ns) { + var KubernetesState = inject("KubernetesState") || {}; + KubernetesState.selectedNamespace = ns; + } + } + + /** + * Configures the json schema + */ + export function configureSchema() { + angular.forEach(schema.definitions, (definition, name) => { + var properties = definition.properties; + if (properties) { + var hideProperties = ["creationTimestamp", "kind", "apiVersion", "annotations", "additionalProperties", "namespace", "resourceVersion", "selfLink", "uid"]; + angular.forEach(hideProperties, (propertyName) => { + var property = properties[propertyName]; + if (property) { + property["hidden"] = true; + } + }); + angular.forEach(properties, (property, propertyName) => { + var ref = property["$ref"]; + var type = property["type"]; + if (ref && (!type || type === "object")) { + property["type"] = ref; + } + if (type === "array") { + var items = property["items"]; + if (items) { + var ref = items["$ref"]; + var type = items["type"]; + if (ref && (!type || type === "object")) { + items["type"] = ref; + } + } + } + }); + } + + schema.definitions.os_build_WebHookTrigger.properties.secret.type = "password"; + }) + } + + /** + * Lets remove any enriched data to leave the original json intact + */ + export function unenrich(item) { + var o = _.cloneDeep(item); + angular.forEach(o, (value, key) => { + if (key.startsWith("$") || key.startsWith("_")) { + delete o[key]; + } + }); + delete o['connectTo']; + return o; + } + + /** + * Returns the unenriched JSON representation of an object + */ + export function toRawJson(item) { + var o = unenrich(item); + return JSON.stringify(o, null, 2); // spacing level = 2 + } + + /** + * Returns the unenriched YAML representation of an object + */ + export function toRawYaml(item) { + var o = unenrich(item); + return jsyaml.dump(o, { indent: 2 }); + } + + + export function watch($scope: any, $element: any, kind, ns, fn, labelSelector = null) { + var connection = KubernetesAPI.watch({ + kind: kind, + namespace: ns, + labelSelector: labelSelector, + success: function (objects) { + fn(objects); + Core.$apply($scope); + } + }); + $element.on('$destroy', () => { + console.log("Static controller[" + kind + ", " + ns + "] element destroyed"); + $scope.$destroy(); + }); + $scope.$on('$destroy', () => { + console.log("Static controller[" + kind + ", " + ns + "] scope destroyed"); + connection.disconnect(); + }); + var oldDeleteScopeFn = $scope.deleteScope; + $scope.deleteScope = function () { + $element.remove(); + if (angular.isFunction(oldDeleteScopeFn)) { + oldDeleteScopeFn(); + } + } + } + + export function createKubernetesClient(kind, ns = null) { + var K8SClientFactory = inject("K8SClientFactory"); + if (!K8SClientFactory) { + log.warn("Could not find injected K8SClientFactory!"); + return null; + } + if (kind === "projects" || kind === "namespaces") { + ns = null; + } else if (!ns) { + ns = Kubernetes.currentKubernetesNamespace(); + } + return K8SClientFactory.create(kind, ns); + } + + + export function currentUserName() { + var userDetails = HawtioOAuth.getUserProfile(); + var answer = null; + if (userDetails) { + answer = getName(userDetails); + } + return answer || "admin"; + } + + export function createNamespace(ns, client?) { + if (!client) { + client = isOpenShift ? Kubernetes.createKubernetesClient('projects') : Kubernetes.createKubernetesClient('namespaces'); + } + if (ns && ns !== currentKubernetesNamespace()) { + var object = { + apiVersion: Kubernetes.defaultApiVersion, + kind: isOpenShift ? 'Project' : 'Namespace', + metadata: { + name: ns, + labels: { + } + } + }; + client.put(object, + (data) => { + log.info("Created namespace: " + ns) + }, + (err) => { + log.warn("Failed to create namespace: " + ns + ": " + angular.toJson(err)); + }); + } + } + + export function createRC(obj, onCompleteFn = null){ + var client = Kubernetes.createKubernetesClient('replicationcontrollers','default'); + var RCTemplate = new resourceRCTemplate(); + var rcTemplate = RCTemplate.createRC(obj); + client.put(rcTemplate, function(obj) { + console.log("Created: ", obj); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(obj); + } + }); + } + + export function updateReplicationControllerLabels($http, KubernetesApiURL, replicationController, newLabels, onCompleteFn = null){ + var id = getName(replicationController); + var namespace = getNamespace(replicationController) || ""; + var url = kubernetesUrlForKind(KubernetesApiURL, "ReplicationController", namespace, id); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + var desiredLabels = data.metadata; + if (!desiredLabels) { + desiredLabels = {}; + data.metadata = desiredLabels; + } + desiredLabels.labels = newLabels; + $http.put(url, data). + success(function (data, status, headers, config) { + log.debug("updated controller " + url); + if (angular.isFunction(onCompleteFn)) { + onCompleteFn(); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to save " + url + " " + data + " " + status); + }); + } + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + }); + } + + export function connectOracle($http, $timeout, url, connectParam, rcName, delayTime){ + $timeout(() => { + $http({ + url: url, + method:'POST', + params:{oracleName: rcName, param: connectParam} + }).success(function(data,header,config,status){ + console.log("success"); + }).error(function(data,header,config,status){ + log.warn("Failed to connect " + connectParam + " " + data + " " + status); + }); + }, delayTime); + } + + +} diff --git a/plugins/kubernetes/ts/kubernetesInterfaces.ts b/plugins/kubernetes/ts/kubernetesInterfaces.ts new file mode 100644 index 0000000..22f44c2 --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesInterfaces.ts @@ -0,0 +1,147 @@ +module Kubernetes { + + export class consts { + get NAMESPACE_STORAGE_KEY():string { return "k8sSelectedNamespace"; } + } + + export var Constants = new consts(); + + export interface ApiLocation { + proto?:string; + hostPort:string; + prefix:string; + } + + export interface ApiLocations { + openshift?: ApiLocation; + k8s?: ApiLocation; + } + + export interface KubernetesConfig { + master_uri?: string; + api?: ApiLocations; + openshift?: OpenShiftOAuthConfig; + google?: GoogleOAuthConfig; + keycloak?: KeyCloakAuthConfig; + } + + export interface OpenShiftOAuthConfig { + oauth_authorize_uri:string; + oauth_client_id:string; + } + + export interface GoogleOAuthConfig { + authenticationURI:string; + authorizationURI:string; + clientId:string; + clientSecret:string; + redirectURI:string; + scope:string; + tokenURI?:string; + } + + export interface KeyCloakAuthConfig { + oauth_authorize_uri:string; + oauth_client_id:string; + } + + export interface KubernetesState { + namespaces: Array; + selectedNamespace: string; + } + + export class WatchTypes { + public static get ENDPOINTS():string { return "endpoints"; } + public static get EVENTS():string { return "events"; } + public static get NAMESPACES():string { return "namespaces"; } + public static get NODES():string { return "nodes"; } + public static get PERSISTENT_VOLUMES():string { return "persistentvolumes"; } + public static get PERSISTENT_VOLUME_CLAIMS():string { return "persistentvolumeclaims"; } + public static get PODS():string { return "pods"; } + public static get REPLICATION_CONTROLLERS():string { return "replicationcontrollers"; } + public static get RESOURCE_QUOTAS():string { return "resourcequotas"; } + public static get OAUTH_CLIENTS():string { return "oauthclients"; } + public static get SECRETS():string { return "secrets"; } + public static get SERVICES():string { return "services"; } + public static get SERVICE_ACCOUNTS():string { return "serviceaccounts"; } + + public static get TEMPLATES():string { return "templates"; } + public static get ROUTES():string { return "routes"; } + public static get BUILD_CONFIGS():string { return "buildconfigs"; } + public static get BUILDS():string { return "builds"; } + public static get DEPLOYMENT_CONFIGS():string { return "deploymentconfigs"; } + public static get IMAGE_STREAMS():string { return "imagestreams"; } + public static get POLICIES():string { return "policies"; } + public static get POLICY_BINDINGS():string { return "policybindings"; } + public static get PROJECTS():string { return "projects"; } + public static get ROLE_BINDINGS():string { return "rolebindings"; } + public static get ROLES():string { return "roles"; } + } + + export class NamespacedTypes { + public static get k8sTypes():Array { + return [ + WatchTypes.ENDPOINTS, + WatchTypes.EVENTS, + WatchTypes.NODES, + WatchTypes.PERSISTENT_VOLUMES, + WatchTypes.PERSISTENT_VOLUME_CLAIMS, + WatchTypes.PODS, + WatchTypes.REPLICATION_CONTROLLERS, + WatchTypes.RESOURCE_QUOTAS, + WatchTypes.PERSISTENT_VOLUMES, + WatchTypes.SECRETS, + WatchTypes.SERVICES, + WatchTypes.SERVICE_ACCOUNTS + ]; + } + public static get osTypes():Array { + return [ + WatchTypes.TEMPLATES, + WatchTypes.BUILD_CONFIGS, + WatchTypes.ROUTES, + WatchTypes.BUILDS, + WatchTypes.BUILD_CONFIGS, + WatchTypes.DEPLOYMENT_CONFIGS, + WatchTypes.IMAGE_STREAMS, + WatchTypes.OAUTH_CLIENTS, + WatchTypes.POLICIES, + WatchTypes.POLICY_BINDINGS, + WatchTypes.PROJECTS, + //WatchTypes.ROLE_BINDINGS, + //WatchTypes.ROLES + ]; + } + } + + export class WatchActions { + public static get ANY():string { return "*"; } + public static get ADDED():string { return "ADDED"; } + public static get MODIFIED():string { return "MODIFIED"; } + public static get DELETED():string { return "DELETED"; } + } + + export interface ObjectMap { + [uid:string]: any; + } + + export interface WatcherService { + hasWebSocket: boolean; + addCustomizer: (type: string, customizer: (obj:any) => void) => void; + getTypes: () => Array; + getNamespace: () => string; + setNamespace: (namespace: string) => void; + getObjects: (type: string) => Array; + getObjectMap: (type: string) => ObjectMap; + addAction: (type: string, action: string, fn: (obj:any) => void) => void; + registerListener: (fn:(objects:ObjectMap) => void) => void; + registerCustomUrlFunction: (kind:string, url:(kind:string) => string) => void; + } + + export interface KubePod { + id:string; + namespace:string; + } + + +} diff --git a/plugins/kubernetes/ts/kubernetesModel.ts b/plugins/kubernetes/ts/kubernetesModel.ts new file mode 100644 index 0000000..bdbe2d2 --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesModel.ts @@ -0,0 +1,763 @@ +/// +/// + +module Kubernetes { + + export var FABRIC8_PROJECT_JSON = "fabric8ProjectJson"; + + function byId(thing) { + return thing.id; + } + + function createKey(namespace, id, kind) { + return (namespace || "") + "-" + (kind || 'undefined').toLowerCase() + '-' + (id || 'undefined').replace(/\./g, '-'); + } + + function populateKey(item) { + var result = item; + result['_key'] = createKey(getNamespace(item), getName(item), getKind(item)); + return result; + } + + function populateKeys(items:Array) { + var result = []; + angular.forEach(items, (item) => { + result.push(populateKey(item)); + }); + return result; + } + + function selectPods(pods, namespace, labels) { + return pods.filter((pod) => { + return getNamespace(pod) === namespace && selectorMatches(labels, getLabels(pod)); + }); + } + + /** + * The object which keeps track of all the pods, replication controllers, services and their associations + */ + export class KubernetesModelService { + public kubernetes = null; + public apps = []; + public services = []; + + public replicationcontrollers = []; + public get replicationControllers():Array { + return this.replicationcontrollers; + } + public set replicationControllers(replicationControllers:Array) { + this.replicationcontrollers = replicationControllers; + } + public pods = []; + public hosts = []; + public get namespaces():Array { + return this.kubernetes.namespaces; + } + //public namespaces = []; + public routes = []; + public templates = []; + public redraw = false; + public resourceVersions = {}; + + // various views on the data + public podsByHost = {}; + public servicesByKey = {}; + public replicationControllersByKey = {}; + public podsByKey = {}; + + public appInfos = []; + public appViews = []; + public appFolders = []; + + public fetched = false; + public get showRunButton():boolean { + if (isOpenShift) { + return true; + } + return _.any(this.services, (service) => { + var name = getName(service); + if (name === "templates") { + var podCounters = service.$podCounters; + return podCounters && (podCounters.valid || podCounters.ready); + } else { + return false; + } + }); + } + + public buildconfigs = []; + public events = []; + public workspaces = []; + public projects = []; + public project = null; + + public get serviceApps():Array { + return _.filter(this.services, (s) => { + return s.$host && s.$serviceUrl && s.$podCount + }); + } + + public $keepPolling() { + return keepPollingModel; + } + + public orRedraw(flag) { + this.redraw = this.redraw || flag; + } + + public getService(namespace, id) { + return this.servicesByKey[createKey(namespace, id, 'service')]; + } + + public getReplicationController(namespace, id) { + return this.replicationControllersByKey[createKey(namespace, id, 'replicationController')]; + } + + public getPod(namespace, id) { + return this.podsByKey[createKey(namespace, id, 'pod')]; + } + + public podsForNamespace(namespace = this.currentNamespace()) { + return _.filter(this.pods, { namespace: namespace }); + } + + public getBuildConfig(name) { + return _.find(this.buildconfigs, { $name: name }); + } + + public getProject(name, ns = this.currentNamespace()) { + var buildConfig = this.project; + if (!buildConfig) { + var text = localStorage[FABRIC8_PROJECT_JSON]; + if (text) { + try { + buildConfig = angular.fromJson(text); + } catch (e) { + log.warn("Could not parse json for " + FABRIC8_PROJECT_JSON + ". Was: " + text + ". " + e, e); + } + } + } + if (buildConfig && ns != getNamespace(buildConfig) && name != buildConfig.$name) { + buildConfig = this.getBuildConfig(name); + } + return buildConfig; + } + + + public setProject(buildConfig) { + this.project = buildConfig; + if (buildConfig) { + // lets store in local storage + var localStorage = inject("localStorage"); + if (localStorage) { + localStorage[FABRIC8_PROJECT_JSON] = angular.toJson(buildConfig); + } + } + } + + /** + * Returns the current selected namespace or the default namespace + */ + public currentNamespace() { + var answer = null; + if (this.kubernetes) { + answer = this.kubernetes.selectedNamespace; + } + return answer || defaultNamespace; + } + + protected updateIconUrlAndAppInfo(entity, nameField: string) { + var answer = null; + var id = getName(entity); + entity.$iconUrl = Core.pathGet(entity, ['metadata', 'annotations', 'fabric8.' + id + '/iconUrl']); + entity.$info = Core.pathGet(entity, ['metadata', 'annotations', 'fabric8.' + id + '/summary']); + if (entity.$iconUrl) { + return; + } + if (id && nameField) { + (this.templates || []).forEach((template) => { + var metadata = template.metadata; + if (metadata) { + var annotations = metadata.annotations || {}; + var iconUrl = annotations["fabric8." + id + "/iconUrl"] || annotations["fabric8/iconUrl"]; + if (iconUrl) { + (template.objects || []).forEach((item) => { + var entityName = getName(item); + if (id === entityName) { + entity.$iconUrl = iconUrl; + } + }); + } + } + }); + (this.appInfos || []).forEach((appInfo) => { + var iconPath = appInfo.iconPath; + if (iconPath && !answer && iconPath !== "null") { + var iconUrl = gitPathToUrl(iconPath); + var ids = Core.pathGet(appInfo, ["names", nameField]); + angular.forEach(ids, (appId) => { + if (appId === id) { + entity.$iconUrl = iconUrl; + entity.appPath = appInfo.appPath; + entity.$info = appInfo; + } + }); + } + }); + } + if (!entity.$iconUrl) { + entity.$iconUrl = defaultIconUrl; + } + } + + public maybeInit() { + this.fetched = true; + this.servicesByKey = {}; + this.podsByKey = {}; + this.replicationControllersByKey = {}; + + this.pods.forEach((pod) => { + if (!pod.kind) pod.kind = "Pod"; + this.podsByKey[pod._key] = pod; + var host = getHost(pod); + pod.$labelsText = Kubernetes.labelsToString(getLabels(pod)); + if (host) { + pod.$labelsText += labelFilterTextSeparator + "host=" + host; + } + pod.$iconUrl = defaultIconUrl; + this.discoverPodConnections(pod); + pod.$containerPorts = []; + + var podStatus = pod.status || {}; + var startTime = podStatus.startTime; + pod.$startTime = null; + if (startTime) { + pod.$startTime = new Date(startTime); + } + var createdTime = getCreationTimestamp(pod); + pod.$createdTime = null; + pod.$age = null; + if (createdTime) { + pod.$createdTime = new Date(createdTime); + pod.$age = humandate.relativeTime(pod.$createdTime); + } + var ready = isReady(pod); + pod.$ready = ready; + pod.$statusCss = statusTextToCssClass(podStatus.phase, ready); + + var maxRestartCount = 0; + angular.forEach(Core.pathGet(pod, ["status", "containerStatuses"]), (status) => { + var restartCount = status.restartCount; + if (restartCount) { + if (restartCount > maxRestartCount) { + maxRestartCount = restartCount; + } + } + }); + if (maxRestartCount ) { + pod.$restartCount = maxRestartCount; + } + var imageNames = ""; + angular.forEach(Core.pathGet(pod, ["spec", "containers"]), (container) => { + var image = container.image; + if (image) { + if (!imageNames) { + imageNames = image; + } else { + imageNames = imageNames + " " + image; + } + var idx = image.lastIndexOf(":"); + if (idx > 0) { + image = image.substring(0, idx); + } + var paths = image.split("/", 3); + if (paths.length) { + var answer = null; + if (paths.length == 3) { + answer = paths[1] + "/" + paths[2]; + } else if (paths.length == 2) { + answer = paths[0] + "/" + paths[1]; + } else { + answer = paths[0] + "/" + paths[1]; + } + container.$imageLink = UrlHelpers.join("https://registry.hub.docker.com/u/", answer); + } + } + angular.forEach(container.ports, (port) => { + var containerPort = port.containerPort; + if (containerPort) { + pod.$containerPorts.push(containerPort); + } + }); + }); + pod.$imageNames = imageNames; + var podStatus = podStatus; + var podSpec = (pod.spec || {}); + pod.$podIP = podStatus.podIP; + pod.$host = podSpec.host || podSpec.nodeName || podStatus.hostIP; + }); + + this.services.forEach((service) => { + if (!service.kind) service.kind = "Service"; + this.servicesByKey[service._key] = service; + var selector = getSelector(service); + service.$pods = []; + if (!service.$podCounters) { + service.$podCounters = {}; + } + var podLinkUrl = UrlHelpers.join("/kubernetes/namespace", service.metadata.namespace, "pods"); + _.assign(service.$podCounters, selector ? createPodCounters(selector, this.pods, service.$pods, Kubernetes.labelsToString(selector, ","), podLinkUrl) : {}); + service.$podCount = service.$pods.length; + + var selectedPods = service.$pods; + service.connectTo = selectedPods.map((pod) => { + return pod._key; + }).join(','); + service.$labelsText = Kubernetes.labelsToString(getLabels(service)); + this.updateIconUrlAndAppInfo(service, "serviceNames"); + var spec = service.spec || {}; + service.$portalIP = spec.portalIP; + service.$selectorText = Kubernetes.labelsToString(spec.selector); + var ports = _.map(spec.ports || [], "port"); + service.$ports = ports; + service.$portsText = ports.join(", "); + var iconUrl = service.$iconUrl; + if (iconUrl && selectedPods) { + selectedPods.forEach((pod) => { + pod.$iconUrl = iconUrl; + }); + } + service.$serviceUrl = serviceLinkUrl(service); + }); + + this.replicationControllers.forEach((replicationController) => { + if (!replicationController.kind) replicationController.kind = "ReplicationController"; + this.replicationControllersByKey[replicationController._key] = replicationController + var selector = getSelector(replicationController); + replicationController.$pods = []; + + replicationController.$podCounters = selector ? createPodCounters(selector, this.pods, replicationController.$pods) : null; + replicationController.$podCount = replicationController.$pods.length; + replicationController.$replicas = (replicationController.spec || {}).replicas; + + var selectedPods = replicationController.$pods; + replicationController.connectTo = selectedPods.map((pod) => { + return pod._key; + }).join(','); + replicationController.$labelsText = Kubernetes.labelsToString(getLabels(replicationController)); + replicationController.metadata.labels = Kubernetes.labelToChinese(getLabels(replicationController)); + this.updateIconUrlAndAppInfo(replicationController, "replicationControllerNames"); + var iconUrl = replicationController.$iconUrl; + if (iconUrl && selectedPods) { + selectedPods.forEach((pod) => { + pod.$iconUrl = iconUrl; + }); + } + }); + + // services may not map to an icon but their pods may do via the RC + // so lets default it... + this.services.forEach((service) => { + var iconUrl = service.$iconUrl; + var selectedPods = service.$pods; + if (selectedPods) { + if (!iconUrl || iconUrl === defaultIconUrl) { + iconUrl = null; + selectedPods.forEach((pod) => { + if (!iconUrl) { + iconUrl = pod.$iconUrl; + if (iconUrl) { + service.$iconUrl = iconUrl; + } + } + }); + } + } + }); + + this.updateApps(); + + var podsByHost = {}; + this.pods.forEach((pod) => { + var host = getHost(pod); + var podsForHost = podsByHost[host]; + if (!podsForHost) { + podsForHost = []; + podsByHost[host] = podsForHost; + } + podsForHost.push(pod); + }); + this.podsByHost = podsByHost; + + var tmpHosts = []; + for (var hostKey in podsByHost) { + var hostPods = []; + var podCounters = createPodCounters((pod) => getHost(pod) === hostKey, this.pods, hostPods, "host=" + hostKey); + var hostIP = null; + if (hostPods.length) { + var pod = hostPods[0]; + var currentState = pod.status; + if (currentState) { + hostIP = currentState.hostIP; + } + } + var hostDetails = { + name: hostKey, + id: hostKey, + elementId: hostKey.replace(/\./g, '_'), + hostIP: hostIP, + pods: hostPods, + kind: "Host", + $podCounters: podCounters, + $iconUrl: hostIconUrl + }; + tmpHosts.push(hostDetails); + } + + this.hosts = tmpHosts; + + enrichBuildConfigs(this.buildconfigs); + enrichEvents(this.events, this); + } + + protected updateApps() { + try { + // lets create the app views by trying to join controllers / services / pods that are related + var appViews = []; + + this.replicationControllers.forEach((replicationController) => { + var name = getName(replicationController); + var $iconUrl = replicationController.$iconUrl; + appViews.push({ + appPath: "/dummyPath/" + name, + $name: name, + $info: { + $iconUrl: $iconUrl + }, + $iconUrl: $iconUrl, + replicationControllers: [replicationController], + pods: replicationController.$pods || [], + services: [] + }); + }); + + var noMatches = []; + this.services.forEach((service) => { + // now lets see if we can find an app with an RC of the same selector + var matchesApp = null; + appViews.forEach((appView) => { + appView.replicationControllers.forEach((replicationController) => { + var repSelector = getSelector(replicationController); + if (repSelector && + selectorMatches(repSelector, getSelector(service)) && + getNamespace(service) === getNamespace(replicationController)) { + matchesApp = appView; + } + }); + }); + + if (matchesApp) { + matchesApp.services.push(service); + } else { + noMatches.push(service); + } + }); + log.debug("no matches: ", noMatches); + noMatches.forEach((service) => { + var appView = _.find(appViews, (appView) => { + return _.any(appView.replicationControllers, (rc) => { + return _.startsWith(getName(rc), getName(service)); + }); + }); + if (appView) { + appView.services.push(service); + } else { + var $iconUrl = service.$iconUrl; + appViews.push({ + appPath: "/dummyPath/" + name, + $name: name, + $info: { + $iconUrl: $iconUrl + }, + $iconUrl: $iconUrl, + replicationControllers: [], + pods: service.$pods || [], + services: [service] + }); + } + }); + + angular.forEach(this.routes, (route) => { + var metadata = route.metadata || {}; + var spec = route.spec || {}; + var serviceName = Core.pathGet(spec, ["to", "name"]); + var host = spec.host; + var namespace = getNamespace(route); + if (serviceName && host) { + var service = this.getService(namespace, serviceName); + if (service) { + service.$host = host; + + // TODO we could use some annotations / metadata to deduce what URL we should use to open this + // service in the console. For now just assume its http: + + if (host) { + var hostUrl = host; + if (hostUrl.indexOf("://") < 0) { + hostUrl = "http://" + host; + } + service.$connectUrl = UrlHelpers.join(hostUrl, "/"); + } + + // TODO definitely need that annotation, temp hack for apiman link + if (getName(service) === 'apiman' && host) { + service.$connectUrl = ( new URI().host(service.$host) + .path('apimanui/index.html')) + .query({}) + .hash(URI.encode(angular.toJson({ + backTo: new URI().toString(), + token: HawtioOAuth.getOAuthToken() + }))).toString(); + + } + } else { + log.debug("Could not find service " + serviceName + " namespace " + namespace + " for route: " + metadata.name); + } + } + }); + + appViews = _.sortBy(populateKeys(appViews), (appView) => appView._key); + + ArrayHelpers.sync(this.appViews, appViews, '$name'); + + if (this.appInfos && this.appViews) { + var folderMap = {}; + var folders = []; + var appMap = {}; + angular.forEach(this.appInfos, (appInfo) => { + if (!appInfo.$iconUrl && appInfo.iconPath && appInfo.iconPath !== "null") { + appInfo.$iconUrl = gitPathToUrl(appInfo.iconPath); + } + var appPath = appInfo.appPath; + if (appPath) { + appMap[appPath] = appInfo; + var idx = appPath.lastIndexOf("/"); + var folderPath = ""; + if (idx >= 0) { + folderPath = appPath.substring(0, idx); + } + folderPath = Core.trimLeading(folderPath, "/"); + var folder = folderMap[folderPath]; + if (!folder) { + folder = { + path: folderPath, + expanded: true, + apps: [] + }; + folders.push(folder); + folderMap[folderPath] = folder; + } + folder.apps.push(appInfo); + } + }); + this.appFolders = _.sortBy(folders, "path"); + + var apps = []; + var defaultInfo = { + $iconUrl: defaultIconUrl + }; + + angular.forEach(this.appViews, (appView:any) => { + try { + var appPath = appView.appPath; + + /* + TODO + appView.$select = () => { + Kubernetes.setJson($scope, appView.id, $scope.model.apps); + }; + */ + + var appInfo:any = angular.copy(defaultInfo); + if (appPath) { + appInfo = appMap[appPath] || appInfo; + } + if (!appView.$info) { + appView.$info = defaultInfo; + appView.$info = appInfo; + } + appView.id = appPath; + if (!appView.$name) { + appView.$name = appInfo.name || appView.$name; + } + if (!appView.$iconUrl) { + appView.$iconUrl = appInfo.$iconUrl; + } + apps.push(appView); + appView.$podCounters = createAppViewPodCounters(appView); + appView.$podCount = (appView.pods || []).length; + appView.$replicationControllersText = (appView.replicationControllers || []).map((i) => i["_key"]).join(" "); + appView.$servicesText= (appView.services || []).map((i) => i["_key"]).join(" "); + appView.$serviceViews = createAppViewServiceViews(appView); + } catch (e) { + log.warn("Failed to update appViews: " + e); + } + }); + //this.apps = apps; + this.apps = this.appViews; + } + } catch (e) { + log.warn("Caught error: " + e); + } + } + + protected discoverPodConnections(entity) { + var info = Core.pathGet(entity, ["status", "info"]); + var hostPort = null; + var currentState = entity.status || {}; + var desiredState = entity.spec || {}; + var podId = getName(entity); + var host = currentState["hostIP"]; + var podIP = currentState["podIP"]; + var hasDocker = false; + var foundContainerPort = null; + if (desiredState) { + var containers = desiredState.containers; + angular.forEach(containers, (container) => { + if (!hostPort) { + var ports = container.ports; + angular.forEach(ports, (port) => { + if (!hostPort) { + var containerPort = port.containerPort; + var portName = port.name; + var containerHostPort = port.hostPort; + if (containerPort === 8778 || "jolokia" === portName) { + if (containerPort) { + if (podIP) { + foundContainerPort = containerPort; + } + if (containerHostPort) { + hostPort = containerHostPort; + } + } + } + } + }); + } + }); + } + if (foundContainerPort && podId && isRunning(currentState)) { + if (!Kubernetes.isOpenShift) { + // TODO temp workaround for k8s on GKE https://github.com/kubernetes/kubernetes/issues/17172 + entity.$jolokiaUrl = UrlHelpers.join(Kubernetes.masterApiUrl(), + "api", + Kubernetes.defaultApiVersion, + "proxy", + "namespaces", + entity.metadata.namespace , + "pods", + //"https:" + podId + ":" + foundContainerPort, + podId + ":" + foundContainerPort, + "jolokia/"); + } else { + entity.$jolokiaUrl = UrlHelpers.join(Kubernetes.masterApiUrl(), + "api", + Kubernetes.defaultApiVersion, + "namespaces", + entity.metadata.namespace , + "pods", + "https:" + podId + ":" + foundContainerPort, + "proxy/jolokia/"); + + } + } + } + } + + function getTemplateService(model) { + var key = createKey('default', 'templates', 'service'); + var answer = model.servicesByKey[key]; + log.debug("found template service: ", answer); + return answer; + } + + /** + * Creates a model service which keeps track of all the pods, replication controllers and services along + * with their associations and status + */ + _module.factory('KubernetesModel', ['$rootScope', '$http', 'KubernetesApiURL', 'KubernetesState', 'WatcherService', '$location', '$resource', ($rootScope, $http, AppLibraryURL, KubernetesState, watcher:WatcherService, $location:ng.ILocationService, $resource:ng.resource.IResourceService) => { + + var $scope = new KubernetesModelService(); + $scope.kubernetes = KubernetesState; + + // create all of our resource classes + var typeNames = watcher.getTypes(); + _.forEach(typeNames, (type:string) => { + var urlTemplate = uriTemplateForKubernetesKind(type); + $scope[type + 'Resource'] = createResource(type, urlTemplate, $resource, $scope); + }); + + if (!isOpenShift) { + // register custom URL factories for templates/projects + watcher.registerCustomUrlFunction(KubernetesAPI.WatchTypes.BUILD_CONFIGS, (options:KubernetesAPI.K8SOptions) => { + var templateService = getTemplateService($scope); + if (templateService) { + return UrlHelpers.join(templateService.proxyUrl, '/oapi/v1/namespaces/default/buildconfigs/'); + } + return null; + }); + // register custom URL factories for templates/projects + watcher.registerCustomUrlFunction(KubernetesAPI.WatchTypes.TEMPLATES, (options:KubernetesAPI.K8SOptions) => { + var templateService = getTemplateService($scope); + if (templateService) { + return UrlHelpers.join(templateService.proxyUrl, '/oapi/v1/namespaces/default/templates/'); + } + return null; + }); + } + + // register for all updates on objects + watcher.registerListener((objects:ObjectMap) => { + var types = watcher.getTypes(); + _.forEach(types, (type:string) => { + switch (type) { + case WatchTypes.SERVICES: + var items = populateKeys(objects[type]); + angular.forEach(items, (item) => { + item.proxyUrl = kubernetesProxyUrlForService(kubernetesApiUrl(), item); + }); + $scope[type] = items; + break; + case WatchTypes.TEMPLATES: + case WatchTypes.ROUTES: + case WatchTypes.BUILDS: + case WatchTypes.BUILD_CONFIGS: + case WatchTypes.IMAGE_STREAMS: + // don't put a break here :-) + default: + $scope[type] = populateKeys(objects[type]); + } + log.debug("Type: ", type, " object: ", $scope[type]); + }); + $scope.maybeInit(); + $rootScope.$broadcast('kubernetesModelUpdated', $scope); + Core.$apply($rootScope); + }); + + // set the selected namespace if set in the location bar + // otherwise use whatever previously selected namespace is + // available + var search = $location.search(); + if ('namespace' in search) { + watcher.setNamespace(search['namespace']); + } + + function selectPods(pods, namespace, labels) { + return pods.filter((pod) => { + return getNamespace(pod) === namespace && selectorMatches(labels, getLabels(pod)); + }); + } + return $scope; + }]); + +} diff --git a/plugins/kubernetes/ts/kubernetesNavigation.ts b/plugins/kubernetes/ts/kubernetesNavigation.ts new file mode 100644 index 0000000..33f4cfa --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesNavigation.ts @@ -0,0 +1,24 @@ +/// +/// +module Kubernetes { + + export function selectSubNavBar($scope, tabName, newSubTabLabel) { + var foundTab = null; + angular.forEach($scope.subTabConfig, (tab) => { + if (tabName === tab.label || tabName === tab.id) { + foundTab = tab; + } + }); + var breadcrumbConfig = $scope.breadcrumbConfig; + if (foundTab && breadcrumbConfig) { + breadcrumbConfig.push(foundTab); + $scope.subTabConfig = [ + { + label: newSubTabLabel + } + ]; + } + + } + +} diff --git a/plugins/kubernetes/ts/kubernetesPlugin.ts b/plugins/kubernetes/ts/kubernetesPlugin.ts new file mode 100644 index 0000000..0f51dc4 --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesPlugin.ts @@ -0,0 +1,276 @@ +/// +/// + +declare var OSOAuthConfig:any; +declare var GoogleOAuthConfig:any; +declare var KeycloakConfig:any; + +module Kubernetes { + + export var _module = angular.module(pluginName, ['hawtio-core', 'hawtio-ui', 'ui.codemirror', 'ui.validate','kubernetesUI']); + export var controller = PluginHelpers.createControllerFunction(_module, pluginName); + export var route = PluginHelpers.createRoutingFunction(templatePath); + + _module.config(['$routeProvider', ($routeProvider:ng.route.IRouteProvider) => { + + $routeProvider + .when(UrlHelpers.join(context, '/pods'), route('pods.html', false)) + .when(UrlHelpers.join(context, 'replicationControllers'), route('replicationControllers.html', false)) + .when(UrlHelpers.join(context, 'services'), route('services.html', false)) + .when(UrlHelpers.join(context, 'events'), route('events.html', false)) + .when(UrlHelpers.join(context, 'apps'), route('apps.html', false)) + .when(UrlHelpers.join(context, 'apps/:namespace'), route('apps.html', false)) + .when(UrlHelpers.join(context, 'templates'), route('templates.html', false)) + .when(UrlHelpers.join(context, 'hosts'), route('hosts.html', false)) + .when(UrlHelpers.join(context, 'hosts/:id'), route('host.html', true)) + .when(UrlHelpers.join(context, 'pipelines'), route('pipelines.html', false)) + .when(UrlHelpers.join(context, 'overview'), route('overview.html', true)) + .when(context, {redirectTo: UrlHelpers.join(context, 'replicationControllers')}); + + + angular.forEach([context, "/workspaces/:workspace/projects/:project"], (context) => { + $routeProvider + .when(UrlHelpers.join(context, '/namespace/:namespace/podCreate'), route('podCreate.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/podEdit/:id'), route('podEdit.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/pods'), route('pods.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/pods/:id'), route('pod.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllers'), route('replicationControllers.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllers/:id'), route('replicationController.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllerCreate'), route('replicationControllerCreate.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/replicationControllerEdit/:id'), route('replicationControllerEdit.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/secrets'), route('secrets.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/secrets/:id'), route('secret.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/secretCreate'), route('secret.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/services'), route('services.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/services/:id'), route('service.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/serviceCreate'), route('serviceCreate.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/serviceEdit/:id'), route('serviceEdit.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/events'), route('events.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/apps'), route('apps.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace/overview'), route('overview.html', true)) + .when(UrlHelpers.join(context, '/namespace/:namespace/templates/:targetNamespace'), route('templates.html', false)) + .when(UrlHelpers.join(context, '/namespace/:namespace'), route('apps.html', false)) + .when(UrlHelpers.join(context, 'builds'), route('builds.html', false)) + .when(UrlHelpers.join(context, 'builds/:id'), route('build.html', true)) + .when(UrlHelpers.join(context, 'buildLogs/:id'), route('buildLogs.html', true)) + .when(UrlHelpers.join(context, 'buildConfigs'), route('buildConfigs.html', false)) + .when(UrlHelpers.join(context, 'buildConfigs/:id'), route('buildConfig.html', true)) + .when(UrlHelpers.join(context, 'buildConfigEdit/:id'), route('buildConfigEdit.html', true)) + .when(UrlHelpers.join(context, 'deploymentConfigs'), route('deploymentConfigs.html', false)) + .when(UrlHelpers.join(context, 'deploymentConfigs/:id'), route('deploymentConfig.html', true)) + .when(UrlHelpers.join(context, 'imageRepositories'), route('imageRepositories.html', false)) + }); + + angular.forEach([context, "/workspaces/:workspace", "/workspaces/:workspace/projects/:project"], (context) => { + $routeProvider + .when(UrlHelpers.join(context, 'buildConfigEdit'), route('buildConfigEdit.html', true)) + .when(UrlHelpers.join(context, 'buildConfigEdit/:id'), route('buildConfigEdit.html', true)) + .when(UrlHelpers.join(context, 'importProject'), route('importProject.html', true)) + }); + }]); + + + _module.factory('AppLibraryURL', ['$rootScope', ($rootScope:ng.IRootScopeService) => { + return UrlHelpers.join(kubernetesApiUrl(), "/proxy", kubernetesNamespacePath(), "/services/app-library"); + }]); + + _module.factory('WikiGitUrlPrefix', () => { + return UrlHelpers.join(kubernetesApiUrl(), "/proxy", kubernetesNamespacePath(), "services/app-library"); + }); + + _module.factory('wikiRepository', ["$location", "localStorage", ($location, localStorage) => { + return false; + }]); + + _module.factory('ConnectDialogService', ['$rootScope', ($rootScope:ng.IRootScopeService) => { + return { + dialog: new UI.Dialog(), + saveCredentials: false, + userName: null, + password: null, + jolokiaUrl: null, + containerName: null, + view: null + }; + }]); + + _module.filter('kubernetesPageLink', () => entityPageLink); + + _module.filter('relativeTime', () => { + return (date) => { + return humandate.relativeTime(date); + } + }); + + _module.run(['viewRegistry', 'ServiceRegistry', 'HawtioNav', 'KubernetesModel', '$templateCache', (viewRegistry, ServiceRegistry, HawtioNav, KubernetesModel, $templateCache) => { + + log.debug("Running"); + viewRegistry['kubernetes'] = templatePath + 'layoutKubernetes.html'; + var builder = HawtioNav.builder(); + var apps = builder.id('kube-apps') + .href(() => UrlHelpers.join(context, 'apps')) + .title(() => 'Apps') + .build(); + + var services = builder.id('kube-services') + .href(() => UrlHelpers.join(context, 'services')) + .title(() => 'Services') + .build(); + + var controllers = builder.id('kube-controllers') + .href(() => UrlHelpers.join(context, 'replicationControllers')) + .title(() => 'oracle服务') + .build(); + + var pods = builder.id('kube-pods') + .href(() => UrlHelpers.join(context, 'pods')) + .title(() => '测试页面') + .build(); + + var events = builder.id('kube-events') + .href(() => UrlHelpers.join(context, 'events')) + .title(() => '服务启动日志') + .build(); + + var hosts = builder.id('kube-hosts') + .href(() => UrlHelpers.join(context, 'hosts')) + .title(() => '集群节点') + .build(); + + var overview = builder.id('kube-overview') + .href(() => UrlHelpers.join(context, 'overview')) + .title(() => 'Diagram') + .build(); + + var builds = builder.id('kube-builds') + .href(() => UrlHelpers.join(context, 'builds')) + .title(() => 'Builds') + .build(); + + var buildConfigs = builder.id('kube-buildConfigs') + .href(() => UrlHelpers.join(context, 'buildConfigs')) + .title(() => 'Build Configs') + .build(); + + var deploys = builder.id('kube-deploys') + .href(() => UrlHelpers.join(context, 'deploymentConfigs')) + .title(() => 'Deploys') + .build(); + + var imageRepositories = builder.id('kube-imageRepositories') + .href(() => UrlHelpers.join(context, 'imageRepositories')) + .title(() => 'Registries') + .build(); + + var pipelines = builder.id('kube-pipelines') + .href(() => UrlHelpers.join(context, 'pipelines')) + .title(() => 'Pipelines') + .build(); + + var repos = builder.id('kube-repos') + .href(() => "/forge/repos") + .isValid(() => ServiceRegistry.hasService(fabric8ForgeServiceName) && ServiceRegistry.hasService(gogsServiceName)) + .title(() => 'Repositories') + .build(); + + var mainTab = builder.id('kubernetes') + .rank(100) + .defaultPage({ + rank: 20, + isValid: (yes, no) => { + yes(); + } + }) + .href(() => context) + .title(() => '服务集群') + .tabs(controllers, events) + .build(); + HawtioNav.add(mainTab); + + /* testKubernetesModel + HawtioNav.add({ + id: 'k8sAppSwitcher', + title: () => '', // not used as 'template' below overrides this + isValid: () => KubernetesModel.serviceApps.length > 0, + context: true, + template: () => $templateCache.get(UrlHelpers.join(templatePath, 'serviceApps.html')) + }); + */ + + var projectsTab = builder.id('openshift') + .rank(100) + .href(() => UrlHelpers.join(context, 'buildConfigs') + '?sub-tab=kube-buildConfigs') + .title(() => 'Projects') + // lets disable the pipelines view for now + // pipelines, + .tabs(repos, buildConfigs, builds, deploys, imageRepositories) + .build(); + + //HawtioNav.add(projectsTab); + }]); + + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'KubernetesInit', + task: (next) => { + $.getScript('osconsole/config.js') + .done((script, textStatus) => { + var config:KubernetesConfig = Kubernetes.osConfig = window['OPENSHIFT_CONFIG']; + log.debug("Fetched OAuth config: ", config); + var master:string = config.master_uri; + if (!master && config.api && config.api.k8s) { + var masterUri = new URI().host(config.api.k8s.hostPort).path("").query(""); + if (config.api.k8s.proto) { + masterUri.protocol(config.api.k8s.proto); + } + master = masterUri.toString(); + } + + OSOAuthConfig = config.openshift; + GoogleOAuthConfig = config.google; + KeycloakConfig = config.keycloak; + + if (OSOAuthConfig && !master) { + // TODO auth.master_uri no longer used right? + // master = OSOAuthConfig.master_uri; + if (!master) { + var oauth_authorize_uri = OSOAuthConfig.oauth_authorize_uri; + if (oauth_authorize_uri) { + var text = oauth_authorize_uri; + var idx = text.indexOf("://"); + if (idx > 0) { + idx += 3; + idx = text.indexOf("/", idx); + if (idx > 0) { + master = text.substring(0, ++idx); + } + } + } + } + } + if ((!Kubernetes.masterUrl || Kubernetes.masterUrl === "/") && (!master || master === "/")) { + // lets default the master to the current protocol and host/port + // in case the master url is "/" and we are + // serving up static content from inside /api/v1/namespaces/default/services/fabric8 or something like that + var href = location.href; + if (href) { + master = new URI(href).query("").path("").toString(); + } + } + if (master) { + Kubernetes.masterUrl = master; + next(); + return; + } + }) + .fail((response) => { + log.debug("Error fetching OAUTH config: ", response); + }) + .always(() => { + next(); + }); + } + }, true); + + hawtioPluginLoader.addModule('ngResource'); + hawtioPluginLoader.addModule(pluginName); +} diff --git a/plugins/kubernetes/ts/kubernetesSchema.ts b/plugins/kubernetes/ts/kubernetesSchema.ts new file mode 100644 index 0000000..5560b3a --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesSchema.ts @@ -0,0 +1,77 @@ +/// +/// +module Kubernetes { + + + var hiddenProperties = ['status', 'deletionTimestamp']; + + function withProperty(schema:any, name:string, action:(any) => void) { + if (schema.properties[name]) { + action(schema.properties[name]); + } + } + + function hideProperties(schema) { + _.forEach(hiddenProperties, (property) => { + withProperty(schema, property, (property) => { + property.hidden = true; + }) + }); + } + + _module.factory('KubernetesSchema', ['SchemaRegistry', (schemas:HawtioForms.SchemaRegistry) => { + configureSchema(); + + schemas.addListener("k8s schema customizer", (name, schema) => { + if (schema.properties) { + if (schema.properties.name) { + schema.controls = ['name', '*']; + } + withProperty(schema, 'portalIP', (property) => { + property.label = "Portal IP" + }); + withProperty(schema, 'publicIPs', (property) => { + property.label = "Public IPs" + }); + withProperty(schema, 'Spec', (property) => { + property.label = 'false'; + }); + withProperty(schema, 'Metadata', (property) => { + property.label = 'false'; + }); + hideProperties(schema); + } + + if (_.endsWith(name, "ServiceSpec")) { + schema.controls = ["portalIP", "createExternalLoadBalancer", "sessionAffinity", "publicIPs", "ports", "selector", "*"]; + withProperty(schema, 'sessionAffinity', (property) => { + log.debug("Schema: ", schema); + property.enum = ['None', 'ClientIP']; + property.default = 'None'; + }); + } + + if (_.endsWith(name, "Service")) { + schema.controls = undefined; + schema.tabs = { + 'Basic Information': ['metadata'], + 'Details': ['*'] + } + log.debug("Name: ", name, " Schema: ", schema); + } + + }); + + + schemas.addSchema('kubernetes', schema); + // now lets iterate and add all the definitions too + angular.forEach(schema.definitions, (definition, typeName) => { + //schemas.addSchema(typeName, definition); + schemas.addSchema("#/definitions/" + typeName, definition); + }); + return schema; + }]); + + + +} \ No newline at end of file diff --git a/plugins/kubernetes/ts/kubernetesServices.ts b/plugins/kubernetes/ts/kubernetesServices.ts new file mode 100644 index 0000000..4529e1b --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesServices.ts @@ -0,0 +1,49 @@ +/// + +module Kubernetes { + + // facade this to the watcher service + class KubernetesStateImpl implements KubernetesState { + constructor(private watcher:WatcherService) { + } + get namespaces():Array { + return _.map(this.watcher.getObjects(WatchTypes.NAMESPACES), (namespace) => { + return namespace.metadata.name; + }); + } + get selectedNamespace():string { + return this.watcher.getNamespace(); + } + set selectedNamespace(namespace:string) { + this.watcher.setNamespace(namespace); + } + } + + _module.factory('KubernetesState', ['WatcherService', (watcher:WatcherService) => { + return new KubernetesStateImpl(watcher); + }]); + + // TODO this doesn't need to be a service really + _module.factory('KubernetesApiURL', () => kubernetesApiUrl()); + + // TODO we'll get rid of this... + _module.factory('KubernetesVersion', [() => { + return { + query: () => null + } + }]); + + // TODO let's move these into KubernetesModel so controllers don't have to inject them separately + _module.factory('KubernetesPods', ['KubernetesModel', (KubernetesModel) => { + return KubernetesModel['podsResource']; + }]); + + _module.factory('KubernetesReplicationControllers', ['KubernetesModel', (KubernetesModel) => { + return KubernetesModel['replicationcontrollersResource']; + }]); + + _module.factory('KubernetesServices', ['KubernetesModel', (KubernetesModel) => { + return KubernetesModel['servicesResource']; + }]); + +} diff --git a/plugins/kubernetes/ts/kubernetesTopLevel.ts b/plugins/kubernetes/ts/kubernetesTopLevel.ts new file mode 100644 index 0000000..49c9cf4 --- /dev/null +++ b/plugins/kubernetes/ts/kubernetesTopLevel.ts @@ -0,0 +1,152 @@ +/// +/// +/// +/// + +module Kubernetes { + + export var FileDropController = controller("FileDropController", ["$scope", "KubernetesModel", "FileUploader", '$http', ($scope, model:KubernetesModelService, FileUploader, $http:ng.IHttpService) => { + + var log = Logger.get('kubernetes-file-uploader'); + + var uploader = $scope.uploader = new FileUploader({ + autoUpload: false, + removeAfterUpload: true, + url: kubernetesApiUrl() + }); + + $scope.uploader.onAfterAddingFile = (file) => { + var reader = new FileReader(); + reader.onload = () => { + if (reader.readyState === 2) { + log.debug("File added: ", file); + var data = reader.result; + var obj = null; + if (_.endsWith(file._file.name, '.json')) { + log.debug("Parsing JSON file"); + try { + obj = angular.fromJson(data); + } catch (err) { + log.debug("Failed to read dropped file ", file._file.name, ": ", err); + return; + } + } else if (_.endsWith(file._file.name, '.yaml')) { + log.debug("Parsing YAML file"); + try { + obj = jsyaml.load(data); + } catch (err) { + log.debug("Failed to read dropped file ", file._file.name, ": ", err); + return; + } + } else { + log.debug("Unknown file type for file: ", file._file.name); + return; + } + log.debug("Dropped object: ", obj); + if (!KubernetesAPI.getNamespace(obj)) { + obj.metadata.namespace = model.currentNamespace(); + } + KubernetesAPI.put({ + object: obj, + success: (data) => { + Core.notification("success", "Applied " + file._file.name); + }, + error: (err) => { + log.info("Got error applying", file._file.name, ": ", err); + Core.notification("warning", "Failed to apply " + file._file.name + ", error: " + err.message); + } + }); + } + } + reader.readAsText(file._file); + }; + + $scope.uploader.onBeforeUploadItem = (item) => { + log.debug("Uploading: ", item); + //Core.notification('info', 'Uploading ' + item); + }; + + $scope.uploader.onSuccessItem = (item:FileUpload.IFileItem) => { + log.debug("onSuccessItem: ", item); + }; + + $scope.uploader.onErrorItem = (item, response, status) => { + log.debug("Failed to apply, response: ", response, " status: ", status); + } + + }]); + + export var NamespaceController = controller('NamespaceController', ['$scope', 'WatcherService', ($scope, watcher:WatcherService) => { + $scope.namespaces = watcher.getObjects('namespaces'); + $scope.$watchCollection('namespaces', (newValue, oldValue) => { + if (newValue !== oldValue) { + $scope.namespace = watcher.getNamespace(); + } + }); + $scope.$watch('namespace', (newValue, oldValue) => { + if (newValue !== oldValue) { + if (newValue !== oldValue) { + watcher.setNamespace(newValue); + } + } + }); + }]); + + export var TopLevel = controller("TopLevel", ["$scope", "KubernetesVersion", "KubernetesState", ($scope, KubernetesVersion:ng.resource.IResourceClass, KubernetesState) => { + + $scope.version = undefined; + + $scope.showAppView = isAppView(); + + $scope.isActive = (href) => { + return isLinkActive(href); + }; + + $scope.mode = 'yaml'; + $scope.rawMode = true; + $scope.dirty = false; + $scope.readOnly = true; + $scope.rawModel = null; + + $scope.$on('hawtioEditor_default_dirty', ($event, dirty) => { + $scope.dirty = dirty; + }); + + $scope.save = (rawModel) => { + var obj:any = null; + var str = rawModel.replace(/\t/g, " "); + try { + obj = jsyaml.load(str); + } catch (err) { + Core.notification("warning", "Failed to save object, error: \"" + err + "\""); + } + if (!obj) { + return; + } + $scope.readOnly = true; + KubernetesAPI.put({ + object: obj, + success: (data) => { + $scope.dirty = false; + Core.notification("success", "Saved object " + getName(obj)); + Core.$apply($scope); + }, + error: (err) => { + console.log("Got error: ", err); + Core.notification("warning", "Failed to save object, error: \"" + err.message + "\""); + $scope.dirty = false; + Core.$apply($scope); + } + }); + }; + + + $scope.kubernetes = KubernetesState; + + KubernetesVersion.query((response) => { + $scope.version = response; + }); + + }]); + +} diff --git a/plugins/kubernetes/ts/namespace.ts b/plugins/kubernetes/ts/namespace.ts new file mode 100644 index 0000000..5a3fe75 --- /dev/null +++ b/plugins/kubernetes/ts/namespace.ts @@ -0,0 +1,24 @@ +/// +module Kubernetes { + + export var NamespaceController = controller("NamespaceController", ["$scope", "WatcherService", ($scope, watcher:WatcherService) => { + $scope.watcher = watcher; + $scope.namespaceObjects = watcher.getObjects('namespaces'); + $scope.namespace = watcher.getNamespace(); + $scope.namespaces = []; + $scope.$watch('namespace', (newValue, oldValue) => { + if (newValue !== oldValue) { + watcher.setNamespace(newValue); + } + }); + $scope.$watch('watcher.getNamespace()', (newValue, oldValue) => { + if (newValue !== oldValue) { + $scope.namespace = newValue; + } + }); + $scope.$watchCollection('namespaceObjects', (namespaceObjects) => { + $scope.namespaces = _.map(namespaceObjects, (namespace:any) => namespace.metadata.name); + }) + }]); + +} \ No newline at end of file diff --git a/plugins/kubernetes/ts/oracleStatusModel.ts b/plugins/kubernetes/ts/oracleStatusModel.ts new file mode 100644 index 0000000..f484b13 --- /dev/null +++ b/plugins/kubernetes/ts/oracleStatusModel.ts @@ -0,0 +1,28 @@ +/// +/// + +module Kubernetes{ + + export class oracleModelService{ + public oraclecontrollers = [] ; + + public get oracleControllers(): Array{ + return this.oraclecontrollers; + } + + public set oracleControllers(oracleControllers: Array){ + this.oraclecontrollers = oracleControllers; + } + + public findIndexOfOracleControllers(oracleControllers: Array, name: string): number{ + for(var index in oracleControllers) + if(oracleControllers[index].name === name) + return index; + return -1; + } + } + + _module.factory('OracleStatusModel', [() => { + return new oracleModelService(); + }]); +} \ No newline at end of file diff --git a/plugins/kubernetes/ts/overview.ts b/plugins/kubernetes/ts/overview.ts new file mode 100644 index 0000000..f260887 --- /dev/null +++ b/plugins/kubernetes/ts/overview.ts @@ -0,0 +1,283 @@ +/// +/// +/// + +module Kubernetes { + + var OverviewDirective = _module.directive("kubernetesOverview", ["$templateCache", "$compile", "$interpolate", "$timeout", "$window", "KubernetesState", 'KubernetesModel', ($templateCache:ng.ITemplateCacheService, $compile:ng.ICompileService, $interpolate:ng.IInterpolateService, $timeout:ng.ITimeoutService, $window:ng.IWindowService, KubernetesState, KubernetesModel) => { + + var log = Logger.get('kubernetes-overview'); + var model = KubernetesModel; + var state = KubernetesState; + + return { + restrict: 'E', + replace: true, + link: (scope, element, attr) => { + scope.model = model; + element.css({visibility: 'hidden'}); + scope.getEntity = (type:string, key:string) => { + switch (type) { + case 'host': + return model.podsByHost[key]; + case 'pod': + return model.podsByKey[key]; + case 'replicationController': + return model.replicationControllersByKey[key]; + case 'service': + return model.servicesByKey[key]; + default: + return undefined; + } + }; + + scope.kubernetes = state; + + scope.customizeDefaultOptions = (options) => { + options.Endpoint = ['Blank', {}]; + }; + scope.mouseEnter = ($event) => { + if (scope.jsPlumb) { + angular.element($event.currentTarget).addClass("hovered"); + scope.jsPlumb.getEndpoints($event.currentTarget).forEach((endpoint) => { + endpoint.connections.forEach((connection) => { + if (!connection.isHover()) { + connection.setHover(true); + connection.endpoints.forEach((e) => { + scope.mouseEnter({ + currentTarget: e.element + }); + }); + } + }); + }); + } + } + scope.mouseLeave = ($event) => { + if (scope.jsPlumb) { + angular.element($event.currentTarget).removeClass("hovered"); + scope.jsPlumb.getEndpoints($event.currentTarget).forEach((endpoint) => { + endpoint.connections.forEach((connection) => { + if (connection.isHover()) { + connection.setHover(false); + connection.endpoints.forEach((e) => { + scope.mouseLeave({ + currentTarget: e.element + }); + }); + } + }); + }); + } + } + /* + scope.customizeEndpointOptions = (jsPlumb, node, options) => { + var type = node.el.attr('data-type'); + // log.debug("endpoint type: ", type); + switch (type) { + case 'pod': + break; + case 'service': + break; + case 'replicationController': + break; + } + }; + */ + scope.customizeConnectionOptions = (jsPlumb, edge, params, options) => { + var type = edge.source.el.attr('data-type'); + options.connector = [ "Bezier", { curviness: 50, stub: 25, alwaysRespectStubs: true } ]; + params.paintStyle = { + lineWidth: 2, + strokeStyle: '#5555cc' + }; + switch (type) { + case 'pod': + break; + case 'service': + params.anchors = [ + [ "Continuous", { faces: ["right"] } ], + [ "Continuous", { faces: ["left"] } ] + /* + [1, 0.5, 0, 0, -10, -90], + [0, 0.5, 0, 0, -10, -90] + */ + ]; + break; + case 'replicationController': + params.anchors = [ + [ "Perimeter", { shape: "Circle" } ], + [ "Continuous", { faces: ["right"] } ] + /* + [0, 0.5, 0, 0, -10, -90], + [1, 0.5, 0, 0, -10, -90] + */ + ]; + break; + } + //log.debug("connection source type: ", type); + return options; + }; + function interpolate(template, config) { + return $interpolate(template)(config); + } + function createElement(template, thingName, thing) { + var config = {}; + config[thingName] = thing; + return interpolate(template, config); + } + function createElements(template, thingName, things) { + return things.map((thing) => { + return createElement(template, thingName, thing); + }); + } + function appendNewElements(parentEl, template, thingName, things) { + things.forEach((thing) => { + var key = thing['_key'] || thing['elementId'] || thing['id'] + var existing = parentEl.find("#" + key ); + if (!existing.length) { + log.debug("existing: ", existing, " key: ", key); + parentEl.append($compile(createElement(template, thingName, thing))(scope)); + } + }); + } + function namespaceFilter(item) { + return getNamespace(item) === scope.kubernetes.selectedNamespace; + } + function firstDraw() { + log.debug("First draw"); + element.empty(); + var services = model.services; + var replicationControllers = model.replicationControllers; + var pods = model.pods; + var hosts = model.hosts; + // log.debug("hosts: ", model.hosts); + var parentEl = angular.element($templateCache.get("overviewTemplate.html")); + var servicesEl = parentEl.find(".services"); + var hostsEl = parentEl.find(".hosts"); + var replicationControllersEl = parentEl.find(".replicationControllers"); + + servicesEl.append(createElements($templateCache.get("serviceTemplate.html"), 'service', services.filter(namespaceFilter))); + replicationControllersEl.append(createElements($templateCache.get("replicationControllerTemplate.html"), 'replicationController', replicationControllers.filter(namespaceFilter))); + + hosts.forEach((host) => { + var hostEl = angular.element(createElement($templateCache.get("overviewHostTemplate.html"), 'host', host)); + var podContainer = angular.element(hostEl.find('.pod-container')); + podContainer.append(createElements($templateCache.get("podTemplate.html"), "pod", host.pods)); + hostsEl.append(hostEl); + }); + //parentEl.append(createElements($templateCache.get("podTemplate.html"), 'pod', pods)); + element.append($compile(parentEl)(scope)); + $timeout(() => { element.css({visibility: 'visible'}); }, 250); + } + + function update() { + scope.$emit('jsplumbDoWhileSuspended', () => { + log.debug("Update"); + var services = model.services; + var replicationControllers = model.replicationControllers; + var pods = model.pods; + var hosts = model.hosts; + var parentEl = element.find('[hawtio-jsplumb]'); + var children = parentEl.find('.jsplumb-node'); + children.each((index, c) => { + var child = angular.element(c); + var key = child.attr('id'); + log.debug('key: ', key); + if (Core.isBlank(key)) { + return; + } + var type = child.attr('data-type'); + switch (type) { + case 'host': + if (key in model.podsByHost) { + return; + } + break; + case 'service': + if (key in model.servicesByKey && getNamespace(model.servicesByKey[key]) == scope.kubernetes.selectedNamespace) { + var service = model.servicesByKey[key]; + child.attr('connect-to', service.connectTo); + return; + } + break; + case 'pod': + /* + if (hasId(pods, id)) { + return; + } + */ + if (key in model.podsByKey) { + return; + } + break; + case 'replicationController': + if (key in model.replicationControllersByKey) { + var replicationController = model.replicationControllersByKey[key]; + child.attr('connect-to', replicationController.connectTo); + return; + } + break; + default: + log.debug("Ignoring element with unknown type"); + return; + } + log.debug("Removing: ", key); + child.remove(); + }); + var servicesEl = element.find(".services"); + var replicationControllersEl = element.find(".replicationControllers"); + var hostsEl = element.find(".hosts"); + + appendNewElements(servicesEl, $templateCache.get("serviceTemplate.html"), "service", services); + appendNewElements(replicationControllersEl, $templateCache.get("replicationControllerTemplate.html"), "replicationController", replicationControllers); + appendNewElements(hostsEl, $templateCache.get("overviewHostTemplate.html"), "host", hosts); + hosts.forEach((host) => { + var hostEl = angular.element(hostsEl.find("#" + host.elementId)); + var podContainer = angular.element(hostEl.find('.pod-container')); + appendNewElements(podContainer, $templateCache.get("podTemplate.html"), "pod", host.pods); + }); + }); + } + + function refreshDrawing() { + log.debug("Refreshing drawing"); + if (element.children().length === 0) { + firstDraw(); + } else { + update(); + } + Core.$apply(scope); + } + + scope.$on('kubernetesModelUpdated', _.debounce(refreshDrawing, 500, { trailing: true})); + setTimeout(refreshDrawing, 100); + } + }; + }]); + + var OverviewBoxController = controller("OverviewBoxController", ["$scope", "$location", ($scope, $location:ng.ILocationService) => { + $scope.viewDetails = (entity, path:string) => { + if (entity) { + var namespace = getNamespace(entity); + var id = getName(entity); + $location.path(UrlHelpers.join('/kubernetes/namespace', namespace, path, id)); + } else { + log.warn("No entity for viewDetails!"); + } + } + }]); + + var scopeName = "OverviewController"; + + var OverviewController = controller(scopeName, ["$scope", "$location", "$http", "$timeout", "$routeParams", "KubernetesModel","KubernetesState", "KubernetesApiURL", ($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL) => { + $scope.name = scopeName; + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + //$scope.subTabConfig = []; + }]); + +} diff --git a/plugins/kubernetes/ts/pipelines.ts b/plugins/kubernetes/ts/pipelines.ts new file mode 100644 index 0000000..e29ea13 --- /dev/null +++ b/plugins/kubernetes/ts/pipelines.ts @@ -0,0 +1,174 @@ +/// +/// + +module Kubernetes { + + export var PipelinesController = controller("PipelinesController", ["$scope", "KubernetesModel", "KubernetesState", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + /** + * Lets update the various data to join them together to a pipeline model + */ + function updateData() { + var pipelineSteps = {}; + if ($scope.buildConfigs && $scope.builds && $scope.deploymentConfigs) { + enrichBuildConfigs($scope.buildConfigs, $scope.builds); + $scope.fetched = true; + + angular.forEach($scope.buildConfigs, (buildConfig) => { + var pipelineKey = createPipelineKey(buildConfig); + if (pipelineKey) { + pipelineSteps[pipelineKey] = { + buildConfig: buildConfig, + builds: [], + triggeredBy: null, + triggersSteps: [], + $class: 'pipeline-build' + } + } + }); + angular.forEach($scope.builds, (build) => { + var pipelineKey = createPipelineKey(build); + if (pipelineKey) { + var pipeline = pipelineSteps[pipelineKey]; + if (!pipeline) { + //console.log("warning no pipeline generated for buildConfig for key " + pipelineKey + " for build " + angular.toJson(build, true)); + console.log("warning no pipeline generated for buildConfig for key " + pipelineKey + " for build " + build.$name); + } else { + pipeline.builds.push(build); + } + } + }); + + // TODO now we need to look at the triggers to figure out which pipelineSteps triggers each pipelineStep + + + // now lets create an array of all pipelines, starting from the first known step with a list of the steps + + var pipelines = []; + angular.forEach(pipelineSteps, (pipelineStep, key) => { + if (!pipelineStep.triggeredBy) { + // we are a root step.... + pipelines.push(pipelineStep); + // now lets add all the steps for this key... + pipelineStep.triggersSteps.push(pipelineStep); + angular.forEach(pipelineSteps, (step) => { + if (step.triggeredBy === key) { + pipelineStep.triggersSteps.push(step); + } + }); + } + }); + + angular.forEach($scope.deploymentConfigs, (deploymentConfig) => { + if (!deploymentConfig.kind) { + deploymentConfig.kind = "DeploymentConfig"; + } + angular.forEach(deploymentConfig.triggers, (trigger) => { + var type = trigger.type; + var imageChangeParams = trigger.imageChangeParams; + if (imageChangeParams && type === "ImageChange") { + var from = imageChangeParams.from; + if (from) { + var name = from.name; + if (from.kind === "ImageRepository") { + var tag = imageChangeParams.tag || "latest"; + if (name) { + // now lets find a pipeline step which fires from this + angular.forEach(pipelineSteps, (pipelineStep, key) => { + var to = Core.pathGet(pipelineStep, ["buildConfig", "parameters", "output", "to"]); + if (to && (to.kind === "ImageRepository" || to.kind === "ImageStream")) { + var toName = to.name; + if (toName === name) { + var selector = Core.pathGet(deploymentConfig, ["template", "controllerTemplate", "selector"]); + var pods = []; + var $podCounters = selector ? createPodCounters(selector, KubernetesModel.podsForNamespace(), pods) : null; + var deployPipelineStep = { + buildConfig: deploymentConfig, + $class: 'pipeline-deploy', + $podCounters: $podCounters, + $pods: pods + }; + pipelineStep.triggersSteps.push(deployPipelineStep); + } + } + }); + } + } + } + } + }); + }); + $scope.pipelines = pipelines; + } + } + + /** + * Lets create a unique key for build / config we can use to do linking of builds / configs / triggers + */ + function createPipelineKey(buildConfig) { + return Core.pathGet(buildConfig, ["parameters", "source", "git", "uri"]); + } + + $scope.$keepPolling = () => keepPollingModel; + $scope.fetch = PollHelpers.setupPolling($scope, (next:() => void) => { + var ready = 0; + var numServices = 3; + + function maybeNext() { + if (++ready >= numServices) { + next(); + } + } + + var url = buildsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.builds = enrichBuilds(data.items); + updateData(); + } + maybeNext(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + maybeNext(); + + }); + url = buildConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.buildConfigs = data.items; + updateData(); + } + maybeNext(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + maybeNext(); + }); + url = deploymentConfigsRestURL(); + $http.get(url). + success(function (data, status, headers, config) { + if (data) { + $scope.deploymentConfigs = data.items; + updateData(); + } + maybeNext(); + }). + error(function (data, status, headers, config) { + log.warn("Failed to load " + url + " " + data + " " + status); + maybeNext(); + }); + }); + + $scope.fetch(); + }]); + +} diff --git a/plugins/kubernetes/ts/pod.ts b/plugins/kubernetes/ts/pod.ts new file mode 100644 index 0000000..047d224 --- /dev/null +++ b/plugins/kubernetes/ts/pod.ts @@ -0,0 +1,71 @@ +/// +/// +/// + +module Kubernetes { + + export var PodController = controller("PodController", + ["$scope", "KubernetesModel", "KubernetesState", "ServiceRegistry", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "$window", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, ServiceRegistry, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, $window, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + + $scope.itemConfig = { + properties: { + 'containers/image$': { + template: $templateCache.get('imageTemplate.html') + }, + 'status/phase': { + template: $templateCache.get('statusTemplate.html') + }, + '\\/Env\\/': { + template: $templateCache.get('envItemTemplate.html') + }, + '^\\/labels$': { + template: $templateCache.get('labelTemplate.html') + }, + '\\/env\\/key$': { + hidden: true + } + } + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.$watch('model.pods', (newValue, oldValue) => { + updateData(); + }, true); + + $scope.flipRaw = () => { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + + $scope.openLogs = () => { + var pods = [$scope.item]; + openLogsForPods(ServiceRegistry, $window, KubernetesModel.currentNamespace(), pods); + }; + + updateData(); + + function updateData() { + $scope.id = $routeParams["id"]; + $scope.item = $scope.model.getPod(KubernetesState.selectedNamespace, $scope.id); + if ($scope.item) { + $scope.rawModel = toRawYaml($scope.item); + } + Core.$apply($scope); + } + }]); +} diff --git a/plugins/kubernetes/ts/podEdit.ts b/plugins/kubernetes/ts/podEdit.ts new file mode 100644 index 0000000..87f6bdf --- /dev/null +++ b/plugins/kubernetes/ts/podEdit.ts @@ -0,0 +1,41 @@ +/// +/// +/// + +module Kubernetes { + + export var PodEditController = controller("PodEditController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "SchemaRegistry", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, schemas:HawtioForms.SchemaRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = schemas.cloneSchema("io.fabric8.kubernetes.api.model.Pod"); + //$scope.config = KubernetesSchema.definitions.kubernetes_v1beta2_Pod; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + if ($scope.id) { + $scope.entity = $scope.model.getPod(KubernetesState.selectedNamespace, $scope.id); + Core.$apply($scope); + $scope.fetched = true; + } else { + $scope.fetched = true; + } + } + + $scope.save = ()=>{ + console.log($scope.entity); + } + }]); +} diff --git a/plugins/kubernetes/ts/podLogs.ts b/plugins/kubernetes/ts/podLogs.ts new file mode 100644 index 0000000..a6dc19f --- /dev/null +++ b/plugins/kubernetes/ts/podLogs.ts @@ -0,0 +1,164 @@ +/// +/// + +module Kubernetes { + + var log = Logger.get("kubernetes-pod-logs"); + + _module.service("PodLogReplacements", () => { + return []; + }); + + _module.run((PodLogReplacements) => { + var log = Logger.get("pod-log-replacers"); + // Add ANSI escape character replacer + // adapted from https://github.com/mmalecki/ansispan + var colors = { + '30': 'black', + '31': 'red', + '32': 'green', + '33': 'yellow', + '34': 'blue', + '35': 'purple', + '36': 'cyan', + '37': 'white' + } + PodLogReplacements.push((msg) => { + if (!msg) { + return msg; + } + var end = ""; + _.forOwn(colors, (color, code) => { + var start = ``; + msg = msg.replace(new RegExp('\033\\[' + code + 'm', 'g'), start) + msg = msg.replace(new RegExp('\033\\[0;' + code + 'm', 'g'), start); + }); + msg = msg.replace(/\033\[1m/g, '').replace(/\033\[22m/g, ''); + msg = msg.replace(/\033\[3m/g, '').replace(/\033\[23m/g, ''); + msg = msg.replace(/\033\[m/g, end); + msg = msg.replace(/\033\[0m/g, end); + msg = msg.replace(/\033\[39m/g, end); + msg = msg.replace(/\033\[2m/g, ''); + msg = msg.replace(/\033\[0;39m/g, end); + log.debug("Running replacement on message: ", msg); + return msg; + }); + }); + + _module.controller("Kubernetes.PodLogLinkController", ($scope, TerminalService, $templateCache) => { + + $scope.openLogs = (entity) => { + log.debug("Open logs: ", entity); + TerminalService.newTerminal(entity.metadata.selfLink, entity.metadata.name, $templateCache.get(UrlHelpers.join(templatePath, 'logShell.html'))); + } + + }); + + _module.directive('podLogDisplay', (userDetails, PodLogReplacements) => { + return { + restrict: 'E', + template: ` +
+

Please wait, fetching logs...

+

View previous container logs?

+

+
+ `, + link: (scope:any, element, attr) => { + var link = scope.$eval('podLink'); + var name = scope.$eval('containerName'); + + if (!link) { + return; + } + + scope.fetched = false; + scope.previous = false; + scope.messages = []; + + link = UrlHelpers.join(masterApiUrl(), link, 'log'); + link = KubernetesAPI.wsUrl(link); + link.search({ + follow: true, + tailLines: 1000, + access_token: userDetails.token + }); + + var messages = []; + + var pullMessages = _.debounce(() => { + scope.messages = scope.messages.concat(_.remove(messages, () => true).map((msg) => { + PodLogReplacements.forEach((replFunc:any) => { + if (angular.isFunction(replFunc)) { + msg = replFunc(msg); + } + }); + return msg; + })); + if (!scope.fetched) { + scope.fetched = true; + } + Core.$apply(scope); + }, 1000); + + function initSocket(link) { + scope.fetched = false; + messages.length = 0; + scope.messages.length = 0; + var ws = new WebSocket(link.toString(), 'base64.binary.k8s.io'); + ws.onmessage = (event) => { + try { + var message = window.atob(event.data); + messages.push(message); + pullMessages(); + } catch (err) { + // we'll just ignore these + //log.debug("Failed to decode message: ", event.data, " error: ", err); + } + } + return ws; + } + + var ws = initSocket(link); + + scope.$watch('previous', (value, old) => { + if (value !== old) { + if (link.hasSearch('previous')) { + link.removeSearch('previous').addSearch('previous', scope.previous); + } else { + link.addSearch('previous', scope.previous); + } + ws.close(); + ws = initSocket(link); + } + }); + + element.on('$destroy', () => { + if (ws) { + try { + ws.close(); + } catch (err) { + // nothing to do + } + delete ws; + } + }); + } + } + }); + + _module.directive('podLogWindow', ($compile, TerminalService) => { + return { + restrict: 'A', + scope: false, + link: (scope:any, element, attr) => { + addWindowActions(scope, element, TerminalService); + scope.atBottom = true; + scope.$watch('atBottom', (val) => { + console.log("atBottom: ", val); + }); + } + }; + }); + +} diff --git a/plugins/kubernetes/ts/pods.ts b/plugins/kubernetes/ts/pods.ts new file mode 100644 index 0000000..26b9bfe --- /dev/null +++ b/plugins/kubernetes/ts/pods.ts @@ -0,0 +1,162 @@ +/// +/// +/// + +module Kubernetes { + + export var EnvItem = controller("EnvItem", ["$scope", ($scope) => { + var parts = $scope.data.split('='); + $scope.key = parts.shift(); + $scope.value = parts.join('='); + }]); + + // main controller for the page + export var Pods = controller("Pods", ["$scope", "KubernetesModel", "KubernetesPods", "KubernetesState", "ServiceRegistry", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesPods:ng.resource.IResourceClass, KubernetesState, ServiceRegistry, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + + $scope.itemSchema = Forms.createFormConfiguration(); + + $scope.tableConfig = { + data: 'model.pods', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '_key', + displayName: 'Name', + defaultSort: true, + cellTemplate: $templateCache.get("idTemplate.html") + }, + { + field: '$statusCss', + displayName: 'Status', + cellTemplate: $templateCache.get("statusTemplate.html") + }, + { field: '$eventCount', + displayName: 'Events', + cellTemplate: $templateCache.get("eventSummaryTemplate.html") + }, + { + field: '$restartCount', + displayName: 'Restarts' + }, + { + field: '$createdTime', + displayName: 'Age', + cellTemplate: $templateCache.get("ageTemplate.html") + }, + { + field: '$imageNames', + displayName: 'Images', + cellTemplate: $templateCache.get("imageTemplate.html") + }, + { + field: '$host', + displayName: 'Host', + cellTemplate: $templateCache.get("hostTemplate.html") + }, + { + field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + }, + { + field: '$podIP', + displayName: 'Pod IP', + customSortField: (field) => { + return Kubernetes.sortByPodIp(field.$podIP); + } + } + ] + }; + + $scope.openLogs = () => { + var pods = $scope.tableConfig.selectedItems; + if (!pods || !pods.length) { + if ($scope.id) { + var item = $scope.item; + if (item) { + pods = [item]; + } + } + } + openLogsForPods(ServiceRegistry, $window, KubernetesModel.currentNamespace(), pods); + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.deletePrompt = (selected) => { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected:Array, next:KubePod) { + if (next) { + log.debug("deleting: ", getName(next)); + KubernetesPods.delete({ + id: getName(next) + }, undefined, () => { + log.debug("deleted: ", getName(next)); + deleteSelected(selected, selected.shift()); + }, (error) => { + log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + }); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete pods?', + action: 'The following pods will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + $scope.createPods= () => { + var xhr= new XMLHttpRequest(); + xhr.onreadystatechange = () => { + if (xhr.readyState == 4) {//4表示数据已经调用完成 + if (xhr.status == 200) {//HTTP的状态码 + var obj=JSON.parse(xhr.responseText); + var object = { + "name": "newpod", + "labels": { + "aim": "test", + "app": "oracle" + }, + "path": '/home/', + "port": 1525 + } + Kubernetes.createRC(object); + + }else{ + //alter("shibai"); + } + } + }; + xhr.open("POST", "/oracleAppPath", false);//与服务器连接并发送 + xhr.send(null); + }; + }]); +} diff --git a/plugins/kubernetes/ts/replicationController.ts b/plugins/kubernetes/ts/replicationController.ts new file mode 100644 index 0000000..c799b33 --- /dev/null +++ b/plugins/kubernetes/ts/replicationController.ts @@ -0,0 +1,57 @@ +/// +/// +/// + +module Kubernetes { + + export var ReplicationControllerController = controller("ReplicationControllerController", + ["$scope", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.itemConfig = { + properties: { + '^\\/labels$': { + template: $templateCache.get('labelTemplate.html') + } + } + }; + + $scope.$on('kubernetesModelUpdated', () => { + updateData(); + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.$watch('model.pods', (newValue, oldValue) => { + updateData(); + }, true); + + $scope.flipRaw = () => { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + + updateData(); + + function updateData() { + if ($scope.dirty) { + return; + } + $scope.id = $routeParams["id"]; + $scope.item = $scope.model.getReplicationController(KubernetesState.selectedNamespace, $scope.id); + if ($scope.item) { + $scope.rawModel = toRawYaml($scope.item); + } + Core.$apply($scope); + } + }]); +} diff --git a/plugins/kubernetes/ts/replicationControllerEdit.ts b/plugins/kubernetes/ts/replicationControllerEdit.ts new file mode 100644 index 0000000..048c349 --- /dev/null +++ b/plugins/kubernetes/ts/replicationControllerEdit.ts @@ -0,0 +1,38 @@ +/// +/// +/// + +module Kubernetes { + + export var ReplicationControllerEditController = controller("ReplicationControllerEditController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "SchemaRegistry", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, schemas:HawtioForms.SchemaRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + log.debug("Schema: ", $scope.schema); + $scope.config = schemas.cloneSchema("io.fabric8.kubernetes.api.model.ReplicationController"); + //$$scope.config = KubernetesSchema.definitions.kubernetes_v1beta3_ReplicationController; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + if ($scope.id) { + $scope.entity = $scope.model.getReplicationController(KubernetesState.selectedNamespace, $scope.id); + Core.$apply($scope); + $scope.fetched = true; + } else { + $scope.fetched = true; + } + } + }]); +} diff --git a/plugins/kubernetes/ts/replicationControllers.ts b/plugins/kubernetes/ts/replicationControllers.ts new file mode 100644 index 0000000..abe3b16 --- /dev/null +++ b/plugins/kubernetes/ts/replicationControllers.ts @@ -0,0 +1,199 @@ +/// +/// +/// + +module Kubernetes { + + export var ReplicationControllers = controller("ReplicationControllers", + ["$scope", "OracleStatusModel", "KubernetesModel", "KubernetesReplicationControllers", "KubernetesPods", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, OracleStatusModel, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesReplicationControllers:ng.resource.IResourceClass, KubernetesPods:ng.resource.IResourceClass, KubernetesState, + $templateCache, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + $scope.tableConfig = { + data: 'model.replicationControllers', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '_key', + displayName: '服务名称', + cellTemplate: $templateCache.get("idTemplate.html") + }, + //{ field: '$replicas', + // displayName: 'Scale', + // cellTemplate:$templateCache.get("desiredReplicas.html") + //}, + { field: '$pods.age', + displayName: '启动时间', + cellTemplate:$templateCache.get("ageTemplate.html") + }, + { field: '$labelsText', + displayName: '数据标签', + cellTemplate: $templateCache.get("labelTemplate.html") + }, + { field: '$pods', + displayName: '连接参数', + cellTemplate: $templateCache.get("connectParamTemplate.html") + }, + { field: '$pods[0].$eventCount', + displayName: '服务启动日志', + cellTemplate: $templateCache.get("eventSummaryTemplate.html") + }, + { field: '$podCounters', + displayName: '服务状态', + cellTemplate: $templateCache.get("podCountsAndLinkTemplate.html"), + customSortField: (field) => { + if(field.$podCounters.ready ){ + return 3; + }else if(field.$podCounters.valid || field.$podCounters.waiting){ + return 2; + }else if(field.$podCounters.error){ + return 0; + }else{ + return 1; + } + } + } + ] + } + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.deletePrompt = (selected) => { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected:Array, next:KubePod) { + if (next) { + log.debug("deleting: ", getName(next)); + Kubernetes.resizeController($http, KubernetesApiURL, next, 0, () => { + log.debug("updated number of replicas"); + KubernetesReplicationControllers.delete({ + id: getName(next) + }, undefined, () => { + log.debug("deleted: ", getName(next)); + if(next.metadata.labels.style === "oracle") + Kubernetes.connectOracle($http, $timeout, "/cancelOracleConection", "", getName(next), 0); + deleteSelected(selected, selected.shift()); + }, (error) => { + log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + }); + }); + + /*KubernetesReplicationControllers.delete({ + id: getName(next) + }, undefined, () => { + log.debug("deleted: ", getName(next)); + deleteSelected(selected, selected.shift()); + }, (error) => { + log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + });*/ + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: '是否需要删除oracle服务?', + action: '以下的oracle服务将会被删除:', + okText: '删除', + okClass: 'btn-danger', + custom: "该服务删除后将会清除oracle对应服务的端口等资源占用,但不删除数据文件,是否删除,请确认!", + customClass: "alert alert-warning", + cancelText: "取消" + }).open(); + } + + $scope.createRCs= () => { + var xhr= new XMLHttpRequest(); + xhr.onreadystatechange = () => { + if (xhr.readyState == 4) {//4表示数据已经调用完成 + if (xhr.status == 200) {//HTTP的状态码 + var obj=JSON.parse(xhr.responseText); + console.log(obj.path); + var name = Kubernetes.getRandomString(8); + //console.log(name + "=====" +port); + var object = { + "name": name, + "labels": { + "name" : name + }, + "path": obj.path, + } + Kubernetes.createRC(object, (rc) =>{ + Kubernetes.connectOracle($http, $timeout, "/connectToOracle", "", getName(rc), 0); + }); + }else if(xhr.status == 403){ + alert("两次创建oracle服务时间间隔需要超过1分钟!"); + }else{ + } + } + }; + xhr.open("POST", "/oracleAppPath", false);//与服务器连接并发送 + xhr.send(null); + } + + $scope.stopPrompt = (selected) =>{ + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: (result:boolean) => { + if (result) { + function stopSelected(selected:Array, next:KubePod) { + if (next) { + Kubernetes.resizeController($http, KubernetesApiURL, next, 0, () => { + if(next.metadata.labels.style === "oracle") + Kubernetes.connectOracle($http, $timeout, "/cancelOracleConection", "", getName(next), 0); + stopSelected(selected, selected.shift()); + }); + } + } + stopSelected(selected, selected.shift()); + } + }, + title: '是否需要停止oracle服务?', + action: '以下的oracle服务将会被停止:', + okText: '停止', + okClass: 'btn-danger', + custom: "该服务停止后将无法继续提供连接访问服务,但可通过启动按钮重新启动该服务以进行访问。是否停止,请确认", + customClass: "alert alert-warning", + cancelText: "取消" + }).open(); + } + + $scope.reStartPrompt = (selected) => { + function startSelected(selected:Array, next:KubePod){ + if(next){ + if(next.$replicas === 0) + Kubernetes.resizeController($http, KubernetesApiURL, next, 1, () => { + Kubernetes.connectOracle($http, $timeout, "/connectToOracle", "", getName(next), 0); + startSelected(selected, selected.shift()); + }); + } + } + startSelected(selected, selected.shift()); + } + + }]); +} diff --git a/plugins/kubernetes/ts/schema.ts b/plugins/kubernetes/ts/schema.ts new file mode 100644 index 0000000..8fecd73 --- /dev/null +++ b/plugins/kubernetes/ts/schema.ts @@ -0,0 +1,7020 @@ +/// + +module Kubernetes { + + export var schema = + { + "id": "http://fabric8.io/fabric8/v2/Schema#", + "$schema": "http://json-schema.org/schema#", + "definitions": { + "api_RootPaths": { + "type": "object", + "description": "", + "properties": { + "paths": { + "type": "array", + "description": "", + "items": { + "type": "string", + "description": "" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.RootPaths" + }, + "kubernetes_AWSElasticBlockStoreVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "partition": { + "type": "integer", + "description": "partition on the disk to mount (e.g." + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true" + }, + "volumeID": { + "type": "string", + "description": "unique id of the PD resource in AWS; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#awselasticblockstore" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "kubernetes_Capabilities": { + "type": "object", + "description": "", + "properties": { + "add": { + "type": "array", + "description": "added capabilities", + "items": { + "type": "string", + "description": "added capabilities" + } + }, + "drop": { + "type": "array", + "description": "droped capabilities", + "items": { + "type": "string", + "description": "droped capabilities" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Capabilities" + }, + "kubernetes_CephFSVolumeSource": { + "type": "object", + "description": "", + "properties": { + "monitors": { + "type": "array", + "description": "a collection of Ceph monitors", + "items": { + "type": "string", + "description": "a collection of Ceph monitors" + } + }, + "readOnly": { + "type": "boolean", + "description": "Ceph fs to be mounted with read-only permissions" + }, + "secretFile": { + "type": "string", + "description": "path to secret for rados user; default is /etc/ceph/user.secret; optional" + }, + "secretRef": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "user": { + "type": "string", + "description": "rados user name; default is admin; optional" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "kubernetes_Container": { + "type": "object", + "description": "", + "properties": { + "args": { + "type": "array", + "description": "command array; the docker image's cmd is used if this is not provided; arguments to the entrypoint; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved", + "items": { + "type": "string", + "description": "command array; the docker image's cmd is used if this is not provided; arguments to the entrypoint; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved" + } + }, + "command": { + "type": "array", + "description": "entrypoint array; not executed within a shell; the docker image's entrypoint is used if this is not provided; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved", + "items": { + "type": "string", + "description": "entrypoint array; not executed within a shell; the docker image's entrypoint is used if this is not provided; cannot be updated; variable references $(VAR_NAME) are expanded using the container's environment variables; if a variable cannot be resolved" + } + }, + "env": { + "type": "array", + "description": "list of environment variables to set in the container; cannot be updated", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "image": { + "type": "string", + "description": "Docker image name; see http://releases.k8s.io/HEAD/docs/user-guide/images.md" + }, + "imagePullPolicy": { + "type": "string", + "description": "image pull policy; one of Always" + }, + "lifecycle": { + "$ref": "#/definitions/kubernetes_Lifecycle", + "javaType": "io.fabric8.kubernetes.api.model.Lifecycle" + }, + "livenessProbe": { + "$ref": "#/definitions/kubernetes_Probe", + "javaType": "io.fabric8.kubernetes.api.model.Probe" + }, + "name": { + "type": "string", + "description": "name of the container; must be a DNS_LABEL and unique within the pod; cannot be updated", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "ports": { + "type": "array", + "description": "list of ports to expose from the container; cannot be updated", + "items": { + "$ref": "#/definitions/kubernetes_ContainerPort", + "javaType": "io.fabric8.kubernetes.api.model.ContainerPort" + } + }, + "readinessProbe": { + "$ref": "#/definitions/kubernetes_Probe", + "javaType": "io.fabric8.kubernetes.api.model.Probe" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "securityContext": { + "$ref": "#/definitions/kubernetes_SecurityContext", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContext" + }, + "stdin": { + "type": "boolean", + "description": "Whether this container should allocate a buffer for stdin in the container runtime; default is false" + }, + "terminationMessagePath": { + "type": "string", + "description": "path at which the file to which the container's termination message will be written is mounted into the container's filesystem; message written is intended to be brief final status" + }, + "tty": { + "type": "boolean", + "description": "Whether this container should allocate a TTY for itself" + }, + "volumeMounts": { + "type": "array", + "description": "pod volumes to mount into the container's filesyste; cannot be updated", + "items": { + "$ref": "#/definitions/kubernetes_VolumeMount", + "javaType": "io.fabric8.kubernetes.api.model.VolumeMount" + } + }, + "workingDir": { + "type": "string", + "description": "container's working directory; defaults to image's default; cannot be updated" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Container" + }, + "kubernetes_ContainerPort": { + "type": "object", + "description": "", + "properties": { + "containerPort": { + "type": "integer", + "description": "number of port to expose on the pod's IP address" + }, + "hostIP": { + "type": "string", + "description": "host IP to bind the port to" + }, + "hostPort": { + "type": "integer", + "description": "number of port to expose on the host; most containers do not need this" + }, + "name": { + "type": "string", + "description": "name for the port that can be referred to by services; must be an IANA_SVC_NAME and unique within the pod" + }, + "protocol": { + "type": "string", + "description": "protocol for port; must be UDP or TCP; TCP if unspecified" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerPort" + }, + "kubernetes_ContainerState": { + "type": "object", + "description": "", + "properties": { + "running": { + "$ref": "#/definitions/kubernetes_ContainerStateRunning", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateRunning" + }, + "terminated": { + "$ref": "#/definitions/kubernetes_ContainerStateTerminated", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateTerminated" + }, + "waiting": { + "$ref": "#/definitions/kubernetes_ContainerStateWaiting", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateWaiting" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerState" + }, + "kubernetes_ContainerStateRunning": { + "type": "object", + "description": "", + "properties": { + "startedAt": { + "type": "string", + "description": "time at which the container was last (re-)started" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateRunning" + }, + "kubernetes_ContainerStateTerminated": { + "type": "object", + "description": "", + "properties": { + "containerID": { + "type": "string", + "description": "container's ID in the format 'docker://\u003ccontainer_id\u003e'" + }, + "exitCode": { + "type": "integer", + "description": "exit status from the last termination of the container" + }, + "finishedAt": { + "type": "string", + "description": "time at which the container last terminated" + }, + "message": { + "type": "string", + "description": "message regarding the last termination of the container" + }, + "reason": { + "type": "string", + "description": "(brief) reason from the last termination of the container" + }, + "signal": { + "type": "integer", + "description": "signal from the last termination of the container" + }, + "startedAt": { + "type": "string", + "description": "time at which previous execution of the container started" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateTerminated" + }, + "kubernetes_ContainerStateWaiting": { + "type": "object", + "description": "", + "properties": { + "reason": { + "type": "string", + "description": "(brief) reason the container is not yet running" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStateWaiting" + }, + "kubernetes_ContainerStatus": { + "type": "object", + "description": "", + "properties": { + "containerID": { + "type": "string", + "description": "container's ID in the format 'docker://\u003ccontainer_id\u003e'; see http://releases.k8s.io/HEAD/docs/user-guide/container-environment.md#container-information" + }, + "image": { + "type": "string", + "description": "image of the container; see http://releases.k8s.io/HEAD/docs/user-guide/images.md" + }, + "imageID": { + "type": "string", + "description": "ID of the container's image" + }, + "lastState": { + "$ref": "#/definitions/kubernetes_ContainerState", + "javaType": "io.fabric8.kubernetes.api.model.ContainerState" + }, + "name": { + "type": "string", + "description": "name of the container; must be a DNS_LABEL and unique within the pod; cannot be updated", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "ready": { + "type": "boolean", + "description": "specifies whether the container has passed its readiness probe" + }, + "restartCount": { + "type": "integer", + "description": "the number of times the container has been restarted" + }, + "state": { + "$ref": "#/definitions/kubernetes_ContainerState", + "javaType": "io.fabric8.kubernetes.api.model.ContainerState" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ContainerStatus" + }, + "kubernetes_EmptyDirVolumeSource": { + "type": "object", + "description": "", + "properties": { + "medium": { + "type": "string", + "description": "type of storage used to back the volume; must be an empty string (default) or Memory; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#emptydir" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EmptyDirVolumeSource" + }, + "kubernetes_EndpointAddress": { + "type": "object", + "description": "", + "properties": { + "ip": { + "type": "string", + "description": "IP address of the endpoint" + }, + "targetRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointAddress" + }, + "kubernetes_EndpointPort": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of this port", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "port": { + "type": "integer", + "description": "port number of the endpoint" + }, + "protocol": { + "type": "string", + "description": "protocol for this port; must be UDP or TCP; TCP if unspecified" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointPort" + }, + "kubernetes_EndpointSubset": { + "type": "object", + "description": "", + "properties": { + "addresses": { + "type": "array", + "description": "IP addresses which offer the related ports", + "items": { + "$ref": "#/definitions/kubernetes_EndpointAddress", + "javaType": "io.fabric8.kubernetes.api.model.EndpointAddress" + } + }, + "ports": { + "type": "array", + "description": "port numbers available on the related IP addresses", + "items": { + "$ref": "#/definitions/kubernetes_EndpointPort", + "javaType": "io.fabric8.kubernetes.api.model.EndpointPort" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointSubset" + }, + "kubernetes_Endpoints": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Endpoints", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "subsets": { + "type": "array", + "description": "sets of addresses and ports that comprise a service", + "items": { + "$ref": "#/definitions/kubernetes_EndpointSubset", + "javaType": "io.fabric8.kubernetes.api.model.EndpointSubset" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Endpoints", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_EndpointsList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of endpoints", + "items": { + "$ref": "#/definitions/kubernetes_Endpoints", + "javaType": "io.fabric8.kubernetes.api.model.Endpoints" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "EndpointsList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EndpointsList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_EnvVar": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the environment variable; must be a C_IDENTIFIER", + "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" + }, + "value": { + "type": "string", + "description": "value of the environment variable; defaults to empty string; variable references $(VAR_NAME) are expanded using the previously defined environment varibles in the container and any service environment variables; if a variable cannot be resolved" + }, + "valueFrom": { + "$ref": "#/definitions/kubernetes_EnvVarSource", + "javaType": "io.fabric8.kubernetes.api.model.EnvVarSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + }, + "kubernetes_EnvVarSource": { + "type": "object", + "description": "", + "properties": { + "fieldRef": { + "$ref": "#/definitions/kubernetes_ObjectFieldSelector", + "javaType": "io.fabric8.kubernetes.api.model.ObjectFieldSelector" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EnvVarSource" + }, + "kubernetes_Event": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "count": { + "type": "integer", + "description": "the number of times this event has occurred" + }, + "firstTimestamp": { + "type": "string", + "description": "the time at which the event was first recorded" + }, + "involvedObject": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "kind": { + "type": "string", + "description": "", + "default": "Event", + "required": true + }, + "lastTimestamp": { + "type": "string", + "description": "the time at which the most recent occurrence of this event was recorded" + }, + "message": { + "type": "string", + "description": "human-readable description of the status of this operation" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "reason": { + "type": "string", + "description": "short" + }, + "source": { + "$ref": "#/definitions/kubernetes_EventSource", + "javaType": "io.fabric8.kubernetes.api.model.EventSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Event", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_EventList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of events", + "items": { + "$ref": "#/definitions/kubernetes_Event", + "javaType": "io.fabric8.kubernetes.api.model.Event" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "EventList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EventList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_EventSource": { + "type": "object", + "description": "", + "properties": { + "component": { + "type": "string", + "description": "component that generated the event" + }, + "host": { + "type": "string", + "description": "name of the host where the event is generated" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.EventSource" + }, + "kubernetes_ExecAction": { + "type": "object", + "description": "", + "properties": { + "command": { + "type": "array", + "description": "command line to execute inside the container; working directory for the command is root ('/') in the container's file system; the command is exec'd", + "items": { + "type": "string", + "description": "command line to execute inside the container; working directory for the command is root ('/') in the container's file system; the command is exec'd" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ExecAction" + }, + "kubernetes_GCEPersistentDiskVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "partition": { + "type": "integer", + "description": "partition on the disk to mount (e.g." + }, + "pdName": { + "type": "string", + "description": "unique name of the PD resource in GCE; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#gcepersistentdisk" + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "kubernetes_GitRepoVolumeSource": { + "type": "object", + "description": "", + "properties": { + "repository": { + "type": "string", + "description": "repository URL" + }, + "revision": { + "type": "string", + "description": "commit hash for the specified revision" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.GitRepoVolumeSource" + }, + "kubernetes_GlusterfsVolumeSource": { + "type": "object", + "description": "", + "properties": { + "endpoints": { + "type": "string", + "description": "gluster hosts endpoints name; see http://releases.k8s.io/HEAD/examples/glusterfs/README.md#create-a-pod" + }, + "path": { + "type": "string", + "description": "path to gluster volume; see http://releases.k8s.io/HEAD/examples/glusterfs/README.md#create-a-pod" + }, + "readOnly": { + "type": "boolean", + "description": "glusterfs volume to be mounted with read-only permissions; see http://releases.k8s.io/HEAD/examples/glusterfs/README.md#create-a-pod" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "kubernetes_HTTPGetAction": { + "type": "object", + "description": "", + "properties": { + "host": { + "type": "string", + "description": "hostname to connect to; defaults to pod IP" + }, + "path": { + "type": "string", + "description": "path to access on the HTTP server" + }, + "port": { + "$ref": "#/definitions/kubernetes_util_IntOrString", + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + }, + "scheme": { + "type": "string", + "description": "scheme to connect with" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.HTTPGetAction" + }, + "kubernetes_Handler": { + "type": "object", + "description": "", + "properties": { + "exec": { + "$ref": "#/definitions/kubernetes_ExecAction", + "javaType": "io.fabric8.kubernetes.api.model.ExecAction" + }, + "httpGet": { + "$ref": "#/definitions/kubernetes_HTTPGetAction", + "javaType": "io.fabric8.kubernetes.api.model.HTTPGetAction" + }, + "tcpSocket": { + "$ref": "#/definitions/kubernetes_TCPSocketAction", + "javaType": "io.fabric8.kubernetes.api.model.TCPSocketAction" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Handler" + }, + "kubernetes_HostPathVolumeSource": { + "type": "object", + "description": "", + "properties": { + "path": { + "type": "string", + "description": "path of the directory on the host; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#hostpath" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "kubernetes_ISCSIVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "iqn": { + "type": "string", + "description": "iSCSI Qualified Name" + }, + "lun": { + "type": "integer", + "description": "iscsi target lun number" + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true" + }, + "targetPortal": { + "type": "string", + "description": "iSCSI target portal" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "kubernetes_Lifecycle": { + "type": "object", + "description": "", + "properties": { + "postStart": { + "$ref": "#/definitions/kubernetes_Handler", + "javaType": "io.fabric8.kubernetes.api.model.Handler" + }, + "preStop": { + "$ref": "#/definitions/kubernetes_Handler", + "javaType": "io.fabric8.kubernetes.api.model.Handler" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Lifecycle" + }, + "kubernetes_List": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of objects", + "items": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "List", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.BaseKubernetesList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ListMeta": { + "type": "object", + "description": "", + "properties": { + "resourceVersion": { + "type": "string", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system" + }, + "selfLink": { + "type": "string", + "description": "URL for the object; populated by the system" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + }, + "kubernetes_LoadBalancerIngress": { + "type": "object", + "description": "", + "properties": { + "hostname": { + "type": "string", + "description": "hostname of ingress point" + }, + "ip": { + "type": "string", + "description": "IP address of ingress point" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerIngress" + }, + "kubernetes_LoadBalancerStatus": { + "type": "object", + "description": "", + "properties": { + "ingress": { + "type": "array", + "description": "load-balancer ingress points", + "items": { + "$ref": "#/definitions/kubernetes_LoadBalancerIngress", + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerIngress" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerStatus" + }, + "kubernetes_LocalObjectReference": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "kubernetes_MetadataFile": { + "type": "object", + "description": "", + "properties": { + "fieldRef": { + "$ref": "#/definitions/kubernetes_ObjectFieldSelector", + "javaType": "io.fabric8.kubernetes.api.model.ObjectFieldSelector" + }, + "name": { + "type": "string", + "description": "the name of the file to be created" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.MetadataFile" + }, + "kubernetes_MetadataVolumeSource": { + "type": "object", + "description": "", + "properties": { + "items": { + "type": "array", + "description": "list of metadata files", + "items": { + "$ref": "#/definitions/kubernetes_MetadataFile", + "javaType": "io.fabric8.kubernetes.api.model.MetadataFile" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.MetadataVolumeSource" + }, + "kubernetes_NFSVolumeSource": { + "type": "object", + "description": "", + "properties": { + "path": { + "type": "string", + "description": "the path that is exported by the NFS server; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs" + }, + "readOnly": { + "type": "boolean", + "description": "forces the NFS export to be mounted with read-only permissions; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs" + }, + "server": { + "type": "string", + "description": "the hostname or IP address of the NFS server; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "kubernetes_Namespace": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Namespace", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_NamespaceSpec", + "javaType": "io.fabric8.kubernetes.api.model.NamespaceSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_NamespaceStatus", + "javaType": "io.fabric8.kubernetes.api.model.NamespaceStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Namespace", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_NamespaceList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "items is the list of Namespace objects in the list; see http://releases.k8s.io/HEAD/docs/user-guide/namespaces.md", + "items": { + "$ref": "#/definitions/kubernetes_Namespace", + "javaType": "io.fabric8.kubernetes.api.model.Namespace" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "NamespaceList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamespaceList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_NamespaceSpec": { + "type": "object", + "description": "", + "properties": { + "finalizers": { + "type": "array", + "description": "an opaque list of values that must be empty to permanently remove object from storage; see http://releases.k8s.io/HEAD/docs/design/namespaces.md#finalizers", + "items": { + "type": "string", + "description": "an opaque list of values that must be empty to permanently remove object from storage; see http://releases.k8s.io/HEAD/docs/design/namespaces.md#finalizers" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamespaceSpec" + }, + "kubernetes_NamespaceStatus": { + "type": "object", + "description": "", + "properties": { + "phase": { + "type": "string", + "description": "phase is the current lifecycle phase of the namespace; see http://releases.k8s.io/HEAD/docs/design/namespaces.md#phases" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamespaceStatus" + }, + "kubernetes_Node": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Node", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_NodeSpec", + "javaType": "io.fabric8.kubernetes.api.model.NodeSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_NodeStatus", + "javaType": "io.fabric8.kubernetes.api.model.NodeStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Node", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_NodeAddress": { + "type": "object", + "description": "", + "properties": { + "address": { + "type": "string", + "description": "the node address" + }, + "type": { + "type": "string", + "description": "node address type" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeAddress" + }, + "kubernetes_NodeCondition": { + "type": "object", + "description": "", + "properties": { + "lastHeartbeatTime": { + "type": "string", + "description": "last time we got an update on a given condition" + }, + "lastTransitionTime": { + "type": "string", + "description": "last time the condition transit from one status to another" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about last transition" + }, + "reason": { + "type": "string", + "description": "(brief) reason for the condition's last transition" + }, + "status": { + "type": "string", + "description": "status of the condition" + }, + "type": { + "type": "string", + "description": "type of node condition" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeCondition" + }, + "kubernetes_NodeList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of nodes", + "items": { + "$ref": "#/definitions/kubernetes_Node", + "javaType": "io.fabric8.kubernetes.api.model.Node" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "NodeList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_NodeSpec": { + "type": "object", + "description": "", + "properties": { + "externalID": { + "type": "string", + "description": "deprecated. External ID assigned to the node by some machine database (e.g. a cloud provider). Defaults to node name when empty." + }, + "podCIDR": { + "type": "string", + "description": "pod IP range assigned to the node" + }, + "providerID": { + "type": "string", + "description": "ID of the node assigned by the cloud provider in the format: \u003cProviderName\u003e://\u003cProviderSpecificNodeID\u003e" + }, + "unschedulable": { + "type": "boolean", + "description": "disable pod scheduling on the node; see http://releases.k8s.io/HEAD/docs/admin/node.md#manual-node-administration" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeSpec" + }, + "kubernetes_NodeStatus": { + "type": "object", + "description": "", + "properties": { + "addresses": { + "type": "array", + "description": "list of addresses reachable to the node; see http://releases.k8s.io/HEAD/docs/admin/node.md#node-addresses", + "items": { + "$ref": "#/definitions/kubernetes_NodeAddress", + "javaType": "io.fabric8.kubernetes.api.model.NodeAddress" + } + }, + "capacity": { + "type": "object", + "description": "compute resource capacity of the node; see http://releases.k8s.io/HEAD/docs/user-guide/compute-resources.md", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "conditions": { + "type": "array", + "description": "list of node conditions observed; see http://releases.k8s.io/HEAD/docs/admin/node.md#node-condition", + "items": { + "$ref": "#/definitions/kubernetes_NodeCondition", + "javaType": "io.fabric8.kubernetes.api.model.NodeCondition" + } + }, + "nodeInfo": { + "$ref": "#/definitions/kubernetes_NodeSystemInfo", + "javaType": "io.fabric8.kubernetes.api.model.NodeSystemInfo" + }, + "phase": { + "type": "string", + "description": "most recently observed lifecycle phase of the node; see http://releases.k8s.io/HEAD/docs/admin/node.md#node-phase" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeStatus" + }, + "kubernetes_NodeSystemInfo": { + "type": "object", + "description": "", + "properties": { + "bootID": { + "type": "string", + "description": "boot id is the boot-id reported by the node" + }, + "containerRuntimeVersion": { + "type": "string", + "description": "Container runtime version reported by the node through runtime remote API (e.g. docker://1.5.0)" + }, + "kernelVersion": { + "type": "string", + "description": "Kernel version reported by the node from 'uname -r' (e.g. 3.16.0-0.bpo.4-amd64)" + }, + "kubeProxyVersion": { + "type": "string", + "description": "Kube-proxy version reported by the node" + }, + "kubeletVersion": { + "type": "string", + "description": "Kubelet version reported by the node" + }, + "machineID": { + "type": "string", + "description": "machine-id reported by the node" + }, + "osImage": { + "type": "string", + "description": "OS image used reported by the node from /etc/os-release (e.g. Debian GNU/Linux 7 (wheezy))" + }, + "systemUUID": { + "type": "string", + "description": "system-uuid reported by the node" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NodeSystemInfo" + }, + "kubernetes_ObjectFieldSelector": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "version of the schema that fieldPath is written in terms of; defaults to v1" + }, + "fieldPath": { + "type": "string", + "description": "path of the field to select in the specified API version" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ObjectFieldSelector" + }, + "kubernetes_ObjectMeta": { + "type": "object", + "description": "", + "properties": { + "annotations": { + "type": "object", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about objects; see http://releases.k8s.io/HEAD/docs/user-guide/annotations.md", + "additionalProperties": { + "type": "string", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about objects; see http://releases.k8s.io/HEAD/docs/user-guide/annotations.md" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; populated by the system" + }, + "deletionTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object will be deleted; populated by the system when a graceful deletion is requested" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional" + }, + "generation": { + "type": "integer", + "description": "a sequence number representing a specific generation of the desired state; populated by the system; read-only", + "javaType": "Long" + }, + "labels": { + "type": "object", + "description": "map of string keys and values that can be used to organize and categorize objects; may match selectors of replication controllers and services; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md", + "additionalProperties": { + "type": "string", + "description": "map of string keys and values that can be used to organize and categorize objects; may match selectors of replication controllers and services; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "name": { + "type": "string", + "description": "string that identifies an object. Must be unique within a namespace; cannot be updated; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "namespace": { + "type": "string", + "description": "namespace of the object; must be a DNS_LABEL; cannot be updated; see http://releases.k8s.io/HEAD/docs/user-guide/namespaces.md", + "maxLength": 253, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" + }, + "resourceVersion": { + "type": "string", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system" + }, + "selfLink": { + "type": "string", + "description": "URL for the object; populated by the system" + }, + "uid": { + "type": "string", + "description": "unique UUID across space and time; populated by the system; read-only; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#uids" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "kubernetes_ObjectReference": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "API version of the referent" + }, + "fieldPath": { + "type": "string", + "description": "if referring to a piece of an object instead of an entire object" + }, + "kind": { + "type": "string", + "description": "kind of the referent; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds" + }, + "name": { + "type": "string", + "description": "name of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names" + }, + "namespace": { + "type": "string", + "description": "namespace of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/namespaces.md" + }, + "resourceVersion": { + "type": "string", + "description": "specific resourceVersion to which this reference is made" + }, + "uid": { + "type": "string", + "description": "uid of the referent; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#uids" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "kubernetes_PersistentVolume": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolume", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PersistentVolumeSpec", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_PersistentVolumeStatus", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolume", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_PersistentVolumeClaim": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolumeClaim", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimSpec", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimStatus", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaim", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_PersistentVolumeClaimList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "a list of persistent volume claims; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#persistentvolumeclaims", + "items": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaim", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaim" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolumeClaimList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_PersistentVolumeClaimSpec": { + "type": "object", + "description": "", + "properties": { + "accessModes": { + "type": "array", + "description": "the desired access modes the volume should have; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1", + "items": { + "type": "string", + "description": "the desired access modes the volume should have; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1" + } + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "volumeName": { + "type": "string", + "description": "the binding reference to the persistent volume backing this claim" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimSpec" + }, + "kubernetes_PersistentVolumeClaimStatus": { + "type": "object", + "description": "", + "properties": { + "accessModes": { + "type": "array", + "description": "the actual access modes the volume has; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1", + "items": { + "type": "string", + "description": "the actual access modes the volume has; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes-1" + } + }, + "capacity": { + "type": "object", + "description": "the actual resources the volume has", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "phase": { + "type": "string", + "description": "the current phase of the claim" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimStatus" + }, + "kubernetes_PersistentVolumeClaimVolumeSource": { + "type": "object", + "description": "", + "properties": { + "claimName": { + "type": "string", + "description": "the name of the claim in the same namespace to be mounted as a volume; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#persistentvolumeclaims" + }, + "readOnly": { + "type": "boolean", + "description": "mount volume as read-only when true; default false" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource" + }, + "kubernetes_PersistentVolumeList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of persistent volumes; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md", + "items": { + "$ref": "#/definitions/kubernetes_PersistentVolume", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolume" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PersistentVolumeList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_PersistentVolumeSource": { + "type": "object", + "description": "", + "properties": { + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeSource" + }, + "kubernetes_PersistentVolumeSpec": { + "type": "object", + "description": "", + "properties": { + "accessModes": { + "type": "array", + "description": "all ways the volume can be mounted; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes", + "items": { + "type": "string", + "description": "all ways the volume can be mounted; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes" + } + }, + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "capacity": { + "type": "object", + "description": "a description of the persistent volume's resources and capacityr; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#capacity", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "claimRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "persistentVolumeReclaimPolicy": { + "type": "string", + "description": "what happens to a volume when released from its claim; Valid options are Retain (default) and Recycle. Recyling must be supported by the volume plugin underlying this persistent volume. See http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#recycling-policy" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeSpec" + }, + "kubernetes_PersistentVolumeStatus": { + "type": "object", + "description": "", + "properties": { + "message": { + "type": "string", + "description": "human-readable message indicating details about why the volume is in this state" + }, + "phase": { + "type": "string", + "description": "the current phase of a persistent volume; see http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#phase" + }, + "reason": { + "type": "string", + "description": "(brief) reason the volume is not is not available" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeStatus" + }, + "kubernetes_Pod": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Pod", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PodSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_PodStatus", + "javaType": "io.fabric8.kubernetes.api.model.PodStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Pod", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_PodCondition": { + "type": "object", + "description": "", + "properties": { + "status": { + "type": "string", + "description": "status of the condition" + }, + "type": { + "type": "string", + "description": "kind of the condition" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodCondition" + }, + "kubernetes_PodList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of pods; see http://releases.k8s.io/HEAD/docs/user-guide/pods.md", + "items": { + "$ref": "#/definitions/kubernetes_Pod", + "javaType": "io.fabric8.kubernetes.api.model.Pod" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PodList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_PodSpec": { + "type": "object", + "description": "", + "properties": { + "activeDeadlineSeconds": { + "type": "integer", + "description": "", + "javaType": "Long" + }, + "containers": { + "type": "array", + "description": "list of containers belonging to the pod; cannot be updated; containers cannot currently be added or removed; there must be at least one container in a Pod; see http://releases.k8s.io/HEAD/docs/user-guide/containers.md", + "items": { + "$ref": "#/definitions/kubernetes_Container", + "javaType": "io.fabric8.kubernetes.api.model.Container" + } + }, + "dnsPolicy": { + "type": "string", + "description": "DNS policy for containers within the pod; one of 'ClusterFirst' or 'Default'" + }, + "host": { + "type": "string", + "description": "deprecated" + }, + "hostNetwork": { + "type": "boolean", + "description": "host networking requested for this pod" + }, + "imagePullSecrets": { + "type": "array", + "description": "list of references to secrets in the same namespace available for pulling the container images; see http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod", + "items": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "nodeName": { + "type": "string", + "description": "node requested for this pod" + }, + "nodeSelector": { + "type": "object", + "description": "selector which must match a node's labels for the pod to be scheduled on that node; see http://releases.k8s.io/HEAD/docs/user-guide/node-selection/README.md", + "additionalProperties": { + "type": "string", + "description": "selector which must match a node's labels for the pod to be scheduled on that node; see http://releases.k8s.io/HEAD/docs/user-guide/node-selection/README.md" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "restartPolicy": { + "type": "string", + "description": "restart policy for all containers within the pod; one of Always" + }, + "serviceAccount": { + "type": "string", + "description": "deprecated; use serviceAccountName instead" + }, + "serviceAccountName": { + "type": "string", + "description": "name of the ServiceAccount to use to run this pod; see http://releases.k8s.io/HEAD/docs/design/service_accounts.md" + }, + "terminationGracePeriodSeconds": { + "type": "integer", + "description": "optional duration in seconds the pod needs to terminate gracefully; may be decreased in delete request; value must be non-negative integer; the value zero indicates delete immediately; if this value is not set", + "javaType": "Long" + }, + "volumes": { + "type": "array", + "description": "list of volumes that can be mounted by containers belonging to the pod; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md", + "items": { + "$ref": "#/definitions/kubernetes_Volume", + "javaType": "io.fabric8.kubernetes.api.model.Volume" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodSpec" + }, + "kubernetes_PodStatus": { + "type": "object", + "description": "", + "properties": { + "conditions": { + "type": "array", + "description": "current service state of pod; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#pod-conditions", + "items": { + "$ref": "#/definitions/kubernetes_PodCondition", + "javaType": "io.fabric8.kubernetes.api.model.PodCondition" + } + }, + "containerStatuses": { + "type": "array", + "description": "list of container statuses; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-statuses", + "items": { + "$ref": "#/definitions/kubernetes_ContainerStatus", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStatus" + } + }, + "hostIP": { + "type": "string", + "description": "IP address of the host to which the pod is assigned; empty if not yet scheduled" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about why the pod is in this condition" + }, + "phase": { + "type": "string", + "description": "current condition of the pod; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#pod-phase" + }, + "podIP": { + "type": "string", + "description": "IP address allocated to the pod; routable at least within the cluster; empty if not yet allocated" + }, + "reason": { + "type": "string", + "description": "(brief-CamelCase) reason indicating details about why the pod is in this condition" + }, + "startTime": { + "type": "string", + "description": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod." + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodStatus" + }, + "kubernetes_PodTemplateSpec": { + "type": "object", + "description": "", + "properties": { + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_PodSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodSpec" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.PodTemplateSpec" + }, + "kubernetes_Probe": { + "type": "object", + "description": "", + "properties": { + "exec": { + "$ref": "#/definitions/kubernetes_ExecAction", + "javaType": "io.fabric8.kubernetes.api.model.ExecAction" + }, + "httpGet": { + "$ref": "#/definitions/kubernetes_HTTPGetAction", + "javaType": "io.fabric8.kubernetes.api.model.HTTPGetAction" + }, + "initialDelaySeconds": { + "type": "integer", + "description": "number of seconds after the container has started before liveness probes are initiated; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes", + "javaType": "Long" + }, + "tcpSocket": { + "$ref": "#/definitions/kubernetes_TCPSocketAction", + "javaType": "io.fabric8.kubernetes.api.model.TCPSocketAction" + }, + "timeoutSeconds": { + "type": "integer", + "description": "number of seconds after which liveness probes timeout; defaults to 1 second; see http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes", + "javaType": "Long" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Probe" + }, + "kubernetes_RBDVolumeSource": { + "type": "object", + "description": "", + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount" + }, + "image": { + "type": "string", + "description": "rados image name; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "keyring": { + "type": "string", + "description": "keyring is the path to key ring for rados user; default is /etc/ceph/keyring; optional; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "monitors": { + "type": "array", + "description": "a collection of Ceph monitors; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it", + "items": { + "type": "string", + "description": "a collection of Ceph monitors; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + } + }, + "pool": { + "type": "string", + "description": "rados pool name; default is rbd; optional; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "readOnly": { + "type": "boolean", + "description": "rbd volume to be mounted with read-only permissions; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + }, + "secretRef": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "user": { + "type": "string", + "description": "rados user name; default is admin; optional; see http://releases.k8s.io/HEAD/examples/rbd/README.md#how-to-use-it" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + }, + "kubernetes_ReplicationController": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ReplicationController", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_ReplicationControllerSpec", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_ReplicationControllerStatus", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationController", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ReplicationControllerList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of replication controllers; see http://releases.k8s.io/HEAD/docs/user-guide/replication-controller.md", + "items": { + "$ref": "#/definitions/kubernetes_ReplicationController", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationController" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ReplicationControllerList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ReplicationControllerSpec": { + "type": "object", + "description": "", + "properties": { + "replicas": { + "type": "integer", + "description": "number of replicas desired; defaults to 1; see http://releases.k8s.io/HEAD/docs/user-guide/replication-controller.md#what-is-a-replication-controller" + }, + "selector": { + "type": "object", + "description": "label keys and values that must match in order to be controlled by this replication controller", + "additionalProperties": { + "type": "string", + "description": "label keys and values that must match in order to be controlled by this replication controller" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "template": { + "$ref": "#/definitions/kubernetes_PodTemplateSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodTemplateSpec" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerSpec" + }, + "kubernetes_ReplicationControllerStatus": { + "type": "object", + "description": "", + "properties": { + "observedGeneration": { + "type": "integer", + "description": "reflects the generation of the most recently observed replication controller", + "javaType": "Long" + }, + "replicas": { + "type": "integer", + "description": "most recently oberved number of replicas; see http://releases.k8s.io/HEAD/docs/user-guide/replication-controller.md#what-is-a-replication-controller" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerStatus" + }, + "kubernetes_ResourceQuota": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ResourceQuota", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_ResourceQuotaSpec", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_ResourceQuotaStatus", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuota", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ResourceQuotaList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "items is a list of ResourceQuota objects; see http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", + "items": { + "$ref": "#/definitions/kubernetes_ResourceQuota", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuota" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ResourceQuotaList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ResourceQuotaSpec": { + "type": "object", + "description": "", + "properties": { + "hard": { + "type": "object", + "description": "hard is the set of desired hard limits for each named resource; see http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaSpec" + }, + "kubernetes_ResourceQuotaStatus": { + "type": "object", + "description": "", + "properties": { + "hard": { + "type": "object", + "description": "hard is the set of enforced hard limits for each named resource; see http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "used": { + "type": "object", + "description": "used is the current observed total usage of the resource in the namespace", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaStatus" + }, + "kubernetes_ResourceRequirements": { + "type": "object", + "description": "", + "properties": { + "limits": { + "type": "object", + "description": "Maximum amount of compute resources allowed; see http://releases.k8s.io/HEAD/docs/design/resources.md#resource-specifications", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + }, + "requests": { + "type": "object", + "description": "Minimum amount of resources requested; if Requests is omitted for a container", + "additionalProperties": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "javaType": "java.util.Map\u003cString,io.fabric8.kubernetes.api.model.Quantity\u003e" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "kubernetes_RunAsUserStrategyOptions": { + "type": "object", + "description": "", + "properties": { + "type": { + "type": "string", + "description": "strategy used to generate RunAsUser" + }, + "uid": { + "type": "integer", + "description": "the uid to always run as; required for MustRunAs", + "javaType": "Long" + }, + "uidRangeMax": { + "type": "integer", + "description": "max value for range based allocators", + "javaType": "Long" + }, + "uidRangeMin": { + "type": "integer", + "description": "min value for range based allocators", + "javaType": "Long" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.RunAsUserStrategyOptions" + }, + "kubernetes_SELinuxContextStrategyOptions": { + "type": "object", + "description": "", + "properties": { + "seLinuxOptions": { + "$ref": "#/definitions/kubernetes_SELinuxOptions", + "javaType": "io.fabric8.kubernetes.api.model.SELinuxOptions" + }, + "type": { + "type": "string", + "description": "strategy used to generate the SELinux context" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SELinuxContextStrategyOptions" + }, + "kubernetes_SELinuxOptions": { + "type": "object", + "description": "", + "properties": { + "level": { + "type": "string", + "description": "the level label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "role": { + "type": "string", + "description": "the role label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "type": { + "type": "string", + "description": "the type label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + }, + "user": { + "type": "string", + "description": "the user label to apply to the container; see http://releases.k8s.io/HEAD/docs/user-guide/labels.md" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SELinuxOptions" + }, + "kubernetes_Secret": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "data": { + "type": "object", + "description": "data contains the secret data. Each key must be a valid DNS_SUBDOMAIN or leading dot followed by valid DNS_SUBDOMAIN. Each value must be a base64 encoded string as described in https://tools.ietf.org/html/rfc4648#section-4", + "additionalProperties": { + "type": "string", + "description": "data contains the secret data. Each key must be a valid DNS_SUBDOMAIN or leading dot followed by valid DNS_SUBDOMAIN. Each value must be a base64 encoded string as described in https://tools.ietf.org/html/rfc4648#section-4" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "kind": { + "type": "string", + "description": "", + "default": "Secret", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "type": { + "type": "string", + "description": "type facilitates programmatic handling of secret data" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Secret", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_SecretList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "items is a list of secret objects; see http://releases.k8s.io/HEAD/docs/user-guide/secrets.md", + "items": { + "$ref": "#/definitions/kubernetes_Secret", + "javaType": "io.fabric8.kubernetes.api.model.Secret" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SecretList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecretList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_SecretVolumeSource": { + "type": "object", + "description": "", + "properties": { + "secretName": { + "type": "string", + "description": "secretName is the name of a secret in the pod's namespace; see http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#secrets" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource" + }, + "kubernetes_SecurityContext": { + "type": "object", + "description": "", + "properties": { + "capabilities": { + "$ref": "#/definitions/kubernetes_Capabilities", + "javaType": "io.fabric8.kubernetes.api.model.Capabilities" + }, + "privileged": { + "type": "boolean", + "description": "run the container in privileged mode; see http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context" + }, + "runAsNonRoot": { + "type": "boolean", + "description": "indicates the container must be run as a non-root user either by specifying the runAsUser or in the image specification" + }, + "runAsUser": { + "type": "integer", + "description": "the user id that runs the first process in the container; see http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context", + "javaType": "Long" + }, + "seLinuxOptions": { + "$ref": "#/definitions/kubernetes_SELinuxOptions", + "javaType": "io.fabric8.kubernetes.api.model.SELinuxOptions" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecurityContext" + }, + "kubernetes_SecurityContextConstraints": { + "type": "object", + "description": "", + "properties": { + "allowHostDirVolumePlugin": { + "type": "boolean", + "description": "allow the use of the host dir volume plugin" + }, + "allowHostNetwork": { + "type": "boolean", + "description": "allow the use of the hostNetwork in the pod spec" + }, + "allowHostPorts": { + "type": "boolean", + "description": "allow the use of the host ports in the containers" + }, + "allowPrivilegedContainer": { + "type": "boolean", + "description": "allow containers to run as privileged" + }, + "allowedCapabilities": { + "type": "array", + "description": "capabilities that are allowed to be added", + "items": { + "type": "string", + "description": "capabilities that are allowed to be added" + } + }, + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "groups": { + "type": "array", + "description": "groups allowed to use this SecurityContextConstraints", + "items": { + "type": "string", + "description": "groups allowed to use this SecurityContextConstraints" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SecurityContextConstraints", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "runAsUser": { + "$ref": "#/definitions/kubernetes_RunAsUserStrategyOptions", + "javaType": "io.fabric8.kubernetes.api.model.RunAsUserStrategyOptions" + }, + "seLinuxContext": { + "$ref": "#/definitions/kubernetes_SELinuxContextStrategyOptions", + "javaType": "io.fabric8.kubernetes.api.model.SELinuxContextStrategyOptions" + }, + "users": { + "type": "array", + "description": "users allowed to use this SecurityContextConstraints", + "items": { + "type": "string", + "description": "users allowed to use this SecurityContextConstraints" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraints", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_SecurityContextConstraintsList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_SecurityContextConstraints", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraints" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SecurityContextConstraintsList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraintsList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_Service": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Service", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/kubernetes_ServiceSpec", + "javaType": "io.fabric8.kubernetes.api.model.ServiceSpec" + }, + "status": { + "$ref": "#/definitions/kubernetes_ServiceStatus", + "javaType": "io.fabric8.kubernetes.api.model.ServiceStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Service", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ServiceAccount": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "imagePullSecrets": { + "type": "array", + "description": "list of references to secrets in the same namespace available for pulling container images; see http://releases.k8s.io/HEAD/docs/user-guide/secrets.md#manually-specifying-an-imagepullsecret", + "items": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ServiceAccount", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "secrets": { + "type": "array", + "description": "list of secrets that can be used by pods running as this service account; see http://releases.k8s.io/HEAD/docs/user-guide/secrets.md", + "items": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccount", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "kubernetes_ServiceAccountList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of ServiceAccounts; see http://releases.k8s.io/HEAD/docs/design/service_accounts.md#service-accounts", + "items": { + "$ref": "#/definitions/kubernetes_ServiceAccount", + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccount" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ServiceAccountList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccountList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ServiceList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of services", + "items": { + "$ref": "#/definitions/kubernetes_Service", + "javaType": "io.fabric8.kubernetes.api.model.Service" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ServiceList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "kubernetes_ServicePort": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "the name of this port; optional if only one port is defined", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "nodePort": { + "type": "integer", + "description": "the port on each node on which this service is exposed when type=NodePort or LoadBalancer; usually assigned by the system; if specified" + }, + "port": { + "type": "integer", + "description": "the port number that is exposed" + }, + "protocol": { + "type": "string", + "description": "the protocol used by this port; must be UDP or TCP; TCP if unspecified" + }, + "targetPort": { + "$ref": "#/definitions/kubernetes_util_IntOrString", + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServicePort" + }, + "kubernetes_ServiceSpec": { + "type": "object", + "description": "", + "properties": { + "clusterIP": { + "type": "string", + "description": "IP address of the service; usually assigned by the system; if specified" + }, + "deprecatedPublicIPs": { + "type": "array", + "description": "deprecated. externally visible IPs (e.g. load balancers) that should be proxied to this service", + "items": { + "type": "string", + "description": "deprecated. externally visible IPs (e.g. load balancers) that should be proxied to this service" + } + }, + "portalIP": { + "type": "string", + "description": "deprecated" + }, + "ports": { + "type": "array", + "description": "ports exposed by the service; see http://releases.k8s.io/HEAD/docs/user-guide/services.md#virtual-ips-and-service-proxies", + "items": { + "$ref": "#/definitions/kubernetes_ServicePort", + "javaType": "io.fabric8.kubernetes.api.model.ServicePort" + } + }, + "selector": { + "type": "object", + "description": "label keys and values that must match in order to receive traffic for this service; if empty", + "additionalProperties": { + "type": "string", + "description": "label keys and values that must match in order to receive traffic for this service; if empty" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "sessionAffinity": { + "type": "string", + "description": "enable client IP based session affinity; must be ClientIP or None; defaults to None; see http://releases.k8s.io/HEAD/docs/user-guide/services.md#virtual-ips-and-service-proxies" + }, + "type": { + "type": "string", + "description": "type of this service; must be ClusterIP" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceSpec" + }, + "kubernetes_ServiceStatus": { + "type": "object", + "description": "", + "properties": { + "loadBalancer": { + "$ref": "#/definitions/kubernetes_LoadBalancerStatus", + "javaType": "io.fabric8.kubernetes.api.model.LoadBalancerStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.ServiceStatus" + }, + "kubernetes_Status": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "code": { + "type": "integer", + "description": "suggested HTTP return code for this status; 0 if not set" + }, + "details": { + "$ref": "#/definitions/kubernetes_StatusDetails", + "javaType": "io.fabric8.kubernetes.api.model.StatusDetails" + }, + "kind": { + "type": "string", + "description": "", + "default": "Status", + "required": true + }, + "message": { + "type": "string", + "description": "human-readable description of the status of this operation" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + }, + "reason": { + "type": "string", + "description": "machine-readable description of why this operation is in the 'Failure' status; if this value is empty there is no information available; a reason clarifies an HTTP status code but does not override it" + }, + "status": { + "type": "string", + "description": "status of the operation; either Success" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Status" + }, + "kubernetes_StatusCause": { + "type": "object", + "description": "", + "properties": { + "field": { + "type": "string", + "description": "field of the resource that has caused this error" + }, + "message": { + "type": "string", + "description": "human-readable description of the cause of the error; this field may be presented as-is to a reader" + }, + "reason": { + "type": "string", + "description": "machine-readable description of the cause of the error; if this value is empty there is no information available" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.StatusCause" + }, + "kubernetes_StatusDetails": { + "type": "object", + "description": "", + "properties": { + "causes": { + "type": "array", + "description": "the Causes array includes more details associated with the StatusReason failure; not all StatusReasons may provide detailed causes", + "items": { + "$ref": "#/definitions/kubernetes_StatusCause", + "javaType": "io.fabric8.kubernetes.api.model.StatusCause" + } + }, + "kind": { + "type": "string", + "description": "the kind attribute of the resource associated with the status StatusReason; on some operations may differ from the requested resource Kind; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds" + }, + "name": { + "type": "string", + "description": "the name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)" + }, + "retryAfterSeconds": { + "type": "integer", + "description": "the number of seconds before the client should attempt to retry this operation" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.StatusDetails" + }, + "kubernetes_TCPSocketAction": { + "type": "object", + "description": "", + "properties": { + "port": { + "$ref": "#/definitions/kubernetes_util_IntOrString", + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.TCPSocketAction" + }, + "kubernetes_TypeMeta": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources" + }, + "kind": { + "type": "string", + "description": "kind of object" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.TypeMeta" + }, + "kubernetes_Volume": { + "type": "object", + "description": "", + "properties": { + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "emptyDir": { + "$ref": "#/definitions/kubernetes_EmptyDirVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.EmptyDirVolumeSource" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "gitRepo": { + "$ref": "#/definitions/kubernetes_GitRepoVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GitRepoVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_MetadataVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.MetadataVolumeSource" + }, + "name": { + "type": "string", + "description": "volume name; must be a DNS_LABEL and unique within the pod; see http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names", + "maxLength": 63, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "persistentVolumeClaim": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + }, + "secret": { + "$ref": "#/definitions/kubernetes_SecretVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Volume" + }, + "kubernetes_VolumeMount": { + "type": "object", + "description": "", + "properties": { + "mountPath": { + "type": "string", + "description": "path within the container at which the volume should be mounted" + }, + "name": { + "type": "string", + "description": "name of the volume to mount" + }, + "readOnly": { + "type": "boolean", + "description": "mounted read-only if true" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.VolumeMount" + }, + "kubernetes_VolumeSource": { + "type": "object", + "description": "", + "properties": { + "awsElasticBlockStore": { + "$ref": "#/definitions/kubernetes_AWSElasticBlockStoreVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.AWSElasticBlockStoreVolumeSource" + }, + "cephfs": { + "$ref": "#/definitions/kubernetes_CephFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.CephFSVolumeSource" + }, + "emptyDir": { + "$ref": "#/definitions/kubernetes_EmptyDirVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.EmptyDirVolumeSource" + }, + "gcePersistentDisk": { + "$ref": "#/definitions/kubernetes_GCEPersistentDiskVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GCEPersistentDiskVolumeSource" + }, + "gitRepo": { + "$ref": "#/definitions/kubernetes_GitRepoVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GitRepoVolumeSource" + }, + "glusterfs": { + "$ref": "#/definitions/kubernetes_GlusterfsVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.GlusterfsVolumeSource" + }, + "hostPath": { + "$ref": "#/definitions/kubernetes_HostPathVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.HostPathVolumeSource" + }, + "iscsi": { + "$ref": "#/definitions/kubernetes_ISCSIVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.ISCSIVolumeSource" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_MetadataVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.MetadataVolumeSource" + }, + "nfs": { + "$ref": "#/definitions/kubernetes_NFSVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.NFSVolumeSource" + }, + "persistentVolumeClaim": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource" + }, + "rbd": { + "$ref": "#/definitions/kubernetes_RBDVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.RBDVolumeSource" + }, + "secret": { + "$ref": "#/definitions/kubernetes_SecretVolumeSource", + "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.VolumeSource" + }, + "kubernetes_config_AuthInfo": { + "type": "object", + "description": "", + "properties": { + "client-certificate": { + "type": "string", + "description": "" + }, + "client-certificate-data": { + "type": "string", + "description": "" + }, + "client-key": { + "type": "string", + "description": "" + }, + "client-key-data": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "password": { + "type": "string", + "description": "" + }, + "token": { + "type": "string", + "description": "" + }, + "username": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.AuthInfo" + }, + "kubernetes_config_Cluster": { + "type": "object", + "description": "", + "properties": { + "api-version": { + "type": "string", + "description": "" + }, + "certificate-authority": { + "type": "string", + "description": "" + }, + "certificate-authority-data": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "insecure-skip-tls-verify": { + "type": "boolean", + "description": "" + }, + "server": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Cluster" + }, + "kubernetes_config_Config": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "" + }, + "clusters": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedCluster", + "javaType": "io.fabric8.kubernetes.api.model.NamedCluster" + } + }, + "contexts": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedContext", + "javaType": "io.fabric8.kubernetes.api.model.NamedContext" + } + }, + "current-context": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "kind": { + "type": "string", + "description": "" + }, + "preferences": { + "$ref": "#/definitions/kubernetes_config_Preferences", + "javaType": "io.fabric8.kubernetes.api.model.Preferences" + }, + "users": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedAuthInfo", + "javaType": "io.fabric8.kubernetes.api.model.NamedAuthInfo" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Config" + }, + "kubernetes_config_Context": { + "type": "object", + "description": "", + "properties": { + "cluster": { + "type": "string", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + }, + "namespace": { + "type": "string", + "description": "" + }, + "user": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Context" + }, + "kubernetes_config_NamedAuthInfo": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "" + }, + "user": { + "$ref": "#/definitions/kubernetes_config_AuthInfo", + "javaType": "io.fabric8.kubernetes.api.model.AuthInfo" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedAuthInfo" + }, + "kubernetes_config_NamedCluster": { + "type": "object", + "description": "", + "properties": { + "cluster": { + "$ref": "#/definitions/kubernetes_config_Cluster", + "javaType": "io.fabric8.kubernetes.api.model.Cluster" + }, + "name": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedCluster" + }, + "kubernetes_config_NamedContext": { + "type": "object", + "description": "", + "properties": { + "context": { + "$ref": "#/definitions/kubernetes_config_Context", + "javaType": "io.fabric8.kubernetes.api.model.Context" + }, + "name": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedContext" + }, + "kubernetes_config_NamedExtension": { + "type": "object", + "description": "", + "properties": { + "extension": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "name": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + }, + "kubernetes_config_Preferences": { + "type": "object", + "description": "", + "properties": { + "colors": { + "type": "boolean", + "description": "" + }, + "extensions": { + "type": "array", + "description": "", + "items": { + "$ref": "#/definitions/kubernetes_config_NamedExtension", + "javaType": "io.fabric8.kubernetes.api.model.NamedExtension" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Preferences" + }, + "kubernetes_resource_Quantity": { + "type": "object", + "description": "", + "properties": { + "Amount": { + "$ref": "#/definitions/speter_inf_Dec", + "javaType": "io.fabric8.openshift.api.model.Dec" + }, + "Format": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "kubernetes_runtime_RawExtension": { + "type": "object", + "description": "", + "properties": { + "RawJSON": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "kubernetes_util_IntOrString": { + "type": "object", + "description": "", + "properties": { + "IntVal": { + "type": "integer", + "description": "" + }, + "Kind": { + "type": "integer", + "description": "" + }, + "StrVal": { + "type": "string", + "description": "" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.IntOrString" + }, + "kubernetes_watch_WatchEvent": { + "type": "object", + "description": "", + "properties": { + "object": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "type": { + "type": "string", + "description": "the type of watch event; may be ADDED" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.kubernetes.api.model.WatchEvent" + }, + "os_authorization_AuthorizationAttributes": { + "type": "object", + "description": "", + "properties": { + "content": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "namespace": { + "type": "string", + "description": "namespace of the action being requested" + }, + "resource": { + "type": "string", + "description": "one of the existing resource types" + }, + "resourceName": { + "type": "string", + "description": "name of the resource being requested for a get or delete" + }, + "verb": { + "type": "string", + "description": "one of get" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.AuthorizationAttributes" + }, + "os_authorization_ClusterPolicy": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicy", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time any part of the object was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roles": { + "type": "array", + "description": "all the roles held by this policy", + "items": { + "$ref": "#/definitions/os_authorization_NamedClusterRole", + "javaType": "io.fabric8.openshift.api.model.NamedClusterRole" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicy", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterPolicyBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicyBinding", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time any part of the object was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "policyRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "roleBindings": { + "type": "array", + "description": "all the role bindings held by this policy", + "items": { + "$ref": "#/definitions/os_authorization_NamedClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.NamedClusterRoleBinding" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterPolicyBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of cluster policy bindings", + "items": { + "$ref": "#/definitions/os_authorization_ClusterPolicyBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicyBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_ClusterPolicyList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of cluster policies", + "items": { + "$ref": "#/definitions/os_authorization_ClusterPolicy", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicy" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterPolicyList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_ClusterRole": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterRole", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "rules": { + "type": "array", + "description": "list of policy rules", + "items": { + "$ref": "#/definitions/os_authorization_PolicyRule", + "javaType": "io.fabric8.openshift.api.model.PolicyRule" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterRole", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterRoleBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "groupNames": { + "type": "array", + "description": "all the groups directly bound to the role", + "items": { + "type": "string", + "description": "all the groups directly bound to the role" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterRoleBinding", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roleRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "subjects": { + "type": "array", + "description": "references to subjects bound to the role. Only User", + "items": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "userNames": { + "type": "array", + "description": "all user names directly bound to the role", + "items": { + "type": "string", + "description": "all user names directly bound to the role" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_ClusterRoleBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of cluster role bindings", + "items": { + "$ref": "#/definitions/os_authorization_ClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ClusterRoleBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_LocalSubjectAccessReview": { + "type": "object", + "description": "", + "properties": { + "TypeMeta": { + "$ref": "#/definitions/kubernetes_TypeMeta", + "javaType": "io.fabric8.kubernetes.api.model.TypeMeta" + }, + "content": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "groups": { + "type": "array", + "description": "optional", + "items": { + "type": "string", + "description": "optional" + } + }, + "namespace": { + "type": "string", + "description": "namespace of the action being requested" + }, + "resource": { + "type": "string", + "description": "one of the existing resource types" + }, + "resourceName": { + "type": "string", + "description": "name of the resource being requested for a get or delete" + }, + "user": { + "type": "string", + "description": "optional" + }, + "verb": { + "type": "string", + "description": "one of get" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.LocalSubjectAccessReview" + }, + "os_authorization_NamedClusterRole": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the cluster role" + }, + "role": { + "$ref": "#/definitions/os_authorization_ClusterRole", + "javaType": "io.fabric8.openshift.api.model.ClusterRole" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedClusterRole" + }, + "os_authorization_NamedClusterRoleBinding": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the cluster role binding" + }, + "roleBinding": { + "$ref": "#/definitions/os_authorization_ClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedClusterRoleBinding" + }, + "os_authorization_NamedRole": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the role" + }, + "role": { + "$ref": "#/definitions/os_authorization_Role", + "javaType": "io.fabric8.openshift.api.model.Role" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedRole" + }, + "os_authorization_NamedRoleBinding": { + "type": "object", + "description": "", + "properties": { + "name": { + "type": "string", + "description": "name of the roleBinding" + }, + "roleBinding": { + "$ref": "#/definitions/os_authorization_RoleBinding", + "javaType": "io.fabric8.openshift.api.model.RoleBinding" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedRoleBinding" + }, + "os_authorization_Policy": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Policy", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time that any part of the policy was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roles": { + "type": "array", + "description": "roles held by this policy", + "items": { + "$ref": "#/definitions/os_authorization_NamedRole", + "javaType": "io.fabric8.openshift.api.model.NamedRole" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Policy", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_PolicyBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "PolicyBinding", + "required": true + }, + "lastModified": { + "type": "string", + "description": "last time that any part of the object was created" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "policyRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "roleBindings": { + "type": "array", + "description": "all roleBindings held by this policyBinding", + "items": { + "$ref": "#/definitions/os_authorization_NamedRoleBinding", + "javaType": "io.fabric8.openshift.api.model.NamedRoleBinding" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_PolicyBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of policy bindings", + "items": { + "$ref": "#/definitions/os_authorization_PolicyBinding", + "javaType": "io.fabric8.openshift.api.model.PolicyBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PolicyBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_PolicyList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of policies", + "items": { + "$ref": "#/definitions/os_authorization_Policy", + "javaType": "io.fabric8.openshift.api.model.Policy" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "PolicyList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_PolicyRule": { + "type": "object", + "description": "", + "properties": { + "attributeRestrictions": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "nonResourceURLs": { + "type": "array", + "description": "set of partial urls that a user should have access to. *s are allowed", + "items": { + "type": "string", + "description": "set of partial urls that a user should have access to. *s are allowed" + } + }, + "resourceNames": { + "type": "array", + "description": "optional white list of names that the rule applies to. An empty set means that everything is allowed.", + "items": { + "type": "string", + "description": "optional white list of names that the rule applies to. An empty set means that everything is allowed." + } + }, + "resources": { + "type": "array", + "description": "list of resources this rule applies to. * represents all resources.", + "items": { + "type": "string", + "description": "list of resources this rule applies to. * represents all resources." + } + }, + "verbs": { + "type": "array", + "description": "list of verbs that apply to ALL the resourceKinds and attributeRestrictions contained in this rule. The verb * represents all kinds.", + "items": { + "type": "string", + "description": "list of verbs that apply to ALL the resourceKinds and attributeRestrictions contained in this rule. The verb * represents all kinds." + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.PolicyRule" + }, + "os_authorization_Role": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Role", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "rules": { + "type": "array", + "description": "all the rules for this role", + "items": { + "$ref": "#/definitions/os_authorization_PolicyRule", + "javaType": "io.fabric8.openshift.api.model.PolicyRule" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Role", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_RoleBinding": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "groupNames": { + "type": "array", + "description": "all the groups directly bound to the role", + "items": { + "type": "string", + "description": "all the groups directly bound to the role" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RoleBinding", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "roleRef": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "subjects": { + "type": "array", + "description": "references to subjects bound to the role. Only User", + "items": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "userNames": { + "type": "array", + "description": "all the usernames directly bound to the role", + "items": { + "type": "string", + "description": "all the usernames directly bound to the role" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RoleBinding", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_authorization_RoleBindingList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of role bindings", + "items": { + "$ref": "#/definitions/os_authorization_RoleBinding", + "javaType": "io.fabric8.openshift.api.model.RoleBinding" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RoleBindingList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RoleBindingList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_RoleList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of roles", + "items": { + "$ref": "#/definitions/os_authorization_Role", + "javaType": "io.fabric8.openshift.api.model.Role" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RoleList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RoleList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_authorization_SubjectAccessReview": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "content": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "groups": { + "type": "array", + "description": "optional", + "items": { + "type": "string", + "description": "optional" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "SubjectAccessReview", + "required": true + }, + "namespace": { + "type": "string", + "description": "namespace of the action being requested" + }, + "resource": { + "type": "string", + "description": "one of the existing resource types" + }, + "resourceName": { + "type": "string", + "description": "name of the resource being requested for a get or delete" + }, + "user": { + "type": "string", + "description": "optional" + }, + "verb": { + "type": "string", + "description": "one of get" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReview" + }, + "os_authorization_SubjectAccessReviewResponse": { + "type": "object", + "description": "", + "properties": { + "allowed": { + "type": "boolean", + "description": "true if the action would be allowed" + }, + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "SubjectAccessReviewResponse", + "required": true + }, + "namespace": { + "type": "string", + "description": "the namespace used for the access review" + }, + "reason": { + "type": "string", + "description": "reason is optional" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReviewResponse" + }, + "os_build_Build": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Build", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_build_BuildSpec", + "javaType": "io.fabric8.openshift.api.model.BuildSpec" + }, + "status": { + "$ref": "#/definitions/os_build_BuildStatus", + "javaType": "io.fabric8.openshift.api.model.BuildStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Build", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_build_BuildConfig": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildConfig", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_build_BuildConfigSpec", + "javaType": "io.fabric8.openshift.api.model.BuildConfigSpec" + }, + "status": { + "$ref": "#/definitions/os_build_BuildConfigStatus", + "javaType": "io.fabric8.openshift.api.model.BuildConfigStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfig", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_build_BuildConfigList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of build configs", + "items": { + "$ref": "#/definitions/os_build_BuildConfig", + "javaType": "io.fabric8.openshift.api.model.BuildConfig" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildConfigList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfigList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_build_BuildConfigSpec": { + "type": "object", + "description": "", + "properties": { + "output": { + "$ref": "#/definitions/os_build_BuildOutput", + "javaType": "io.fabric8.openshift.api.model.BuildOutput" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "revision": { + "$ref": "#/definitions/os_build_SourceRevision", + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "serviceAccount": { + "type": "string", + "description": "the name of the service account to use to run pods created by the build" + }, + "source": { + "$ref": "#/definitions/os_build_BuildSource", + "javaType": "io.fabric8.openshift.api.model.BuildSource" + }, + "strategy": { + "$ref": "#/definitions/os_build_BuildStrategy", + "javaType": "io.fabric8.openshift.api.model.BuildStrategy" + }, + "triggers": { + "type": "array", + "description": "determines how new builds can be launched from a build config. if no triggers are defined", + "items": { + "$ref": "#/definitions/os_build_BuildTriggerPolicy", + "javaType": "io.fabric8.openshift.api.model.BuildTriggerPolicy" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfigSpec" + }, + "os_build_BuildConfigStatus": { + "type": "object", + "description": "", + "properties": { + "lastVersion": { + "type": "integer", + "description": "used to inform about number of last triggered build" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildConfigStatus" + }, + "os_build_BuildList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of builds", + "items": { + "$ref": "#/definitions/os_build_Build", + "javaType": "io.fabric8.openshift.api.model.Build" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_build_BuildOutput": { + "type": "object", + "description": "", + "properties": { + "pushSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "to": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildOutput" + }, + "os_build_BuildRequest": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "kind": { + "type": "string", + "description": "", + "default": "BuildRequest", + "required": true + }, + "lastVersion": { + "type": "integer", + "description": "LastVersion of the BuildConfig that triggered this build" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "revision": { + "$ref": "#/definitions/os_build_SourceRevision", + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "triggeredByImage": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildRequest", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_build_BuildSource": { + "type": "object", + "description": "", + "properties": { + "contextDir": { + "type": "string", + "description": "specifies sub-directory where the source code for the application exists" + }, + "git": { + "$ref": "#/definitions/os_build_GitBuildSource", + "javaType": "io.fabric8.openshift.api.model.GitBuildSource" + }, + "sourceSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "type": { + "type": "string", + "description": "type of source control management system" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildSource" + }, + "os_build_BuildSpec": { + "type": "object", + "description": "", + "properties": { + "output": { + "$ref": "#/definitions/os_build_BuildOutput", + "javaType": "io.fabric8.openshift.api.model.BuildOutput" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "revision": { + "$ref": "#/definitions/os_build_SourceRevision", + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "serviceAccount": { + "type": "string", + "description": "the name of the service account to use to run pods created by the build" + }, + "source": { + "$ref": "#/definitions/os_build_BuildSource", + "javaType": "io.fabric8.openshift.api.model.BuildSource" + }, + "strategy": { + "$ref": "#/definitions/os_build_BuildStrategy", + "javaType": "io.fabric8.openshift.api.model.BuildStrategy" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildSpec" + }, + "os_build_BuildStatus": { + "type": "object", + "description": "", + "properties": { + "cancelled": { + "type": "boolean", + "description": "describes if a canceling event was triggered for the build" + }, + "completionTimestamp": { + "type": "string", + "description": "server time when the pod running this build stopped running" + }, + "config": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "duration": { + "type": "integer", + "description": "amount of time the build has been running", + "javaType": "Long" + }, + "message": { + "type": "string", + "description": "human-readable message indicating details about why the build has this status" + }, + "phase": { + "type": "string", + "description": "observed point in the build lifecycle" + }, + "startTimestamp": { + "type": "string", + "description": "server time when this build started running in a pod" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildStatus" + }, + "os_build_BuildStrategy": { + "type": "object", + "description": "", + "properties": { + "customStrategy": { + "$ref": "#/definitions/os_build_CustomBuildStrategy", + "javaType": "io.fabric8.openshift.api.model.CustomBuildStrategy" + }, + "dockerStrategy": { + "$ref": "#/definitions/os_build_DockerBuildStrategy", + "javaType": "io.fabric8.openshift.api.model.DockerBuildStrategy" + }, + "sourceStrategy": { + "$ref": "#/definitions/os_build_SourceBuildStrategy", + "javaType": "io.fabric8.openshift.api.model.SourceBuildStrategy" + }, + "type": { + "type": "string", + "description": "identifies the type of build strategy" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildStrategy" + }, + "os_build_BuildTriggerPolicy": { + "type": "object", + "description": "", + "properties": { + "generic": { + "$ref": "#/definitions/os_build_WebHookTrigger", + "javaType": "io.fabric8.openshift.api.model.WebHookTrigger" + }, + "github": { + "$ref": "#/definitions/os_build_WebHookTrigger", + "javaType": "io.fabric8.openshift.api.model.WebHookTrigger" + }, + "imageChange": { + "$ref": "#/definitions/os_build_ImageChangeTrigger", + "javaType": "io.fabric8.openshift.api.model.ImageChangeTrigger" + }, + "type": { + "type": "string", + "description": "type of build trigger" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.BuildTriggerPolicy" + }, + "os_build_CustomBuildStrategy": { + "type": "object", + "description": "", + "properties": { + "env": { + "type": "array", + "description": "additional environment variables you want to pass into a builder container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "exposeDockerSocket": { + "type": "boolean", + "description": "allow running Docker commands (and build Docker images) from inside the container" + }, + "forcePull": { + "type": "boolean", + "description": "forces pulling of builder image from remote registry if true" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "pullSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.CustomBuildStrategy" + }, + "os_build_DockerBuildStrategy": { + "type": "object", + "description": "", + "properties": { + "env": { + "type": "array", + "description": "additional environment variables you want to pass into a builder container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "forcePull": { + "type": "boolean", + "description": "forces the source build to pull the image if true" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "noCache": { + "type": "boolean", + "description": "if true" + }, + "pullSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DockerBuildStrategy" + }, + "os_build_GitBuildSource": { + "type": "object", + "description": "", + "properties": { + "httpProxy": { + "type": "string", + "description": "specifies a http proxy to be used during git clone operations" + }, + "httpsProxy": { + "type": "string", + "description": "specifies a https proxy to be used during git clone operations" + }, + "ref": { + "type": "string", + "description": "identifies the branch/tag/ref to build" + }, + "uri": { + "type": "string", + "description": "points to the source that will be built" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.GitBuildSource" + }, + "os_build_GitSourceRevision": { + "type": "object", + "description": "", + "properties": { + "author": { + "$ref": "#/definitions/os_build_SourceControlUser", + "javaType": "io.fabric8.openshift.api.model.SourceControlUser" + }, + "commit": { + "type": "string", + "description": "hash identifying a specific commit" + }, + "committer": { + "$ref": "#/definitions/os_build_SourceControlUser", + "javaType": "io.fabric8.openshift.api.model.SourceControlUser" + }, + "message": { + "type": "string", + "description": "description of a specific commit" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.GitSourceRevision" + }, + "os_build_ImageChangeTrigger": { + "type": "object", + "description": "", + "properties": { + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "lastTriggeredImageID": { + "type": "string", + "description": "used internally to save last used image ID for build" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageChangeTrigger" + }, + "os_build_SourceBuildStrategy": { + "type": "object", + "description": "", + "properties": { + "env": { + "type": "array", + "description": "additional environment variables you want to pass into a builder container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "forcePull": { + "type": "boolean", + "description": "forces the source build to pull the image if true" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "incremental": { + "type": "boolean", + "description": "forces the source build to do incremental builds if true" + }, + "pullSecret": { + "$ref": "#/definitions/kubernetes_LocalObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.LocalObjectReference" + }, + "scripts": { + "type": "string", + "description": "location of the source scripts" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SourceBuildStrategy" + }, + "os_build_SourceControlUser": { + "type": "object", + "description": "", + "properties": { + "email": { + "type": "string", + "description": "e-mail of the source control user" + }, + "name": { + "type": "string", + "description": "name of the source control user" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SourceControlUser" + }, + "os_build_SourceRevision": { + "type": "object", + "description": "", + "properties": { + "git": { + "$ref": "#/definitions/os_build_GitSourceRevision", + "javaType": "io.fabric8.openshift.api.model.GitSourceRevision" + }, + "type": { + "type": "string", + "description": "type of the build source" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.SourceRevision" + }, + "os_build_WebHookTrigger": { + "type": "object", + "description": "", + "properties": { + "secret": { + "type": "string", + "description": "secret used to validate requests" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.WebHookTrigger" + }, + "os_deploy_CustomDeploymentStrategyParams": { + "type": "object", + "description": "", + "properties": { + "command": { + "type": "array", + "description": "optionally overrides the container command (default is specified by the image)", + "items": { + "type": "string", + "description": "optionally overrides the container command (default is specified by the image)" + } + }, + "environment": { + "type": "array", + "description": "environment variables provided to the deployment process container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + }, + "image": { + "type": "string", + "description": "a Docker image which can carry out a deployment" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.CustomDeploymentStrategyParams" + }, + "os_deploy_DeploymentCause": { + "type": "object", + "description": "", + "properties": { + "imageTrigger": { + "$ref": "#/definitions/os_deploy_DeploymentCauseImageTrigger", + "javaType": "io.fabric8.openshift.api.model.DeploymentCauseImageTrigger" + }, + "type": { + "type": "string", + "description": "the type of trigger that resulted in a new deployment" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentCause" + }, + "os_deploy_DeploymentCauseImageTrigger": { + "type": "object", + "description": "", + "properties": { + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentCauseImageTrigger" + }, + "os_deploy_DeploymentConfig": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "DeploymentConfig", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_deploy_DeploymentConfigSpec", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigSpec" + }, + "status": { + "$ref": "#/definitions/os_deploy_DeploymentConfigStatus", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfig", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_deploy_DeploymentConfigList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "a list of deployment configs", + "items": { + "$ref": "#/definitions/os_deploy_DeploymentConfig", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfig" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "DeploymentConfigList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_deploy_DeploymentConfigSpec": { + "type": "object", + "description": "", + "properties": { + "replicas": { + "type": "integer", + "description": "the desired number of replicas" + }, + "selector": { + "type": "object", + "description": "a label query over pods that should match the replicas count", + "additionalProperties": { + "type": "string", + "description": "a label query over pods that should match the replicas count" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "strategy": { + "$ref": "#/definitions/os_deploy_DeploymentStrategy", + "javaType": "io.fabric8.openshift.api.model.DeploymentStrategy" + }, + "template": { + "$ref": "#/definitions/kubernetes_PodTemplateSpec", + "javaType": "io.fabric8.kubernetes.api.model.PodTemplateSpec" + }, + "triggers": { + "type": "array", + "description": "how new deployments are triggered", + "items": { + "$ref": "#/definitions/os_deploy_DeploymentTriggerPolicy", + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerPolicy" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigSpec" + }, + "os_deploy_DeploymentConfigStatus": { + "type": "object", + "description": "", + "properties": { + "details": { + "$ref": "#/definitions/os_deploy_DeploymentDetails", + "javaType": "io.fabric8.openshift.api.model.DeploymentDetails" + }, + "latestVersion": { + "type": "integer", + "description": "used to determine whether the current deployment is out of sync" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigStatus" + }, + "os_deploy_DeploymentDetails": { + "type": "object", + "description": "", + "properties": { + "causes": { + "type": "array", + "description": "extended data associated with all the causes for creating a new deployment", + "items": { + "$ref": "#/definitions/os_deploy_DeploymentCause", + "javaType": "io.fabric8.openshift.api.model.DeploymentCause" + } + }, + "message": { + "type": "string", + "description": "a user specified change message" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentDetails" + }, + "os_deploy_DeploymentStrategy": { + "type": "object", + "description": "", + "properties": { + "customParams": { + "$ref": "#/definitions/os_deploy_CustomDeploymentStrategyParams", + "javaType": "io.fabric8.openshift.api.model.CustomDeploymentStrategyParams" + }, + "recreateParams": { + "$ref": "#/definitions/os_deploy_RecreateDeploymentStrategyParams", + "javaType": "io.fabric8.openshift.api.model.RecreateDeploymentStrategyParams" + }, + "resources": { + "$ref": "#/definitions/kubernetes_ResourceRequirements", + "javaType": "io.fabric8.kubernetes.api.model.ResourceRequirements" + }, + "rollingParams": { + "$ref": "#/definitions/os_deploy_RollingDeploymentStrategyParams", + "javaType": "io.fabric8.openshift.api.model.RollingDeploymentStrategyParams" + }, + "type": { + "type": "string", + "description": "the name of a deployment strategy" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentStrategy" + }, + "os_deploy_DeploymentTriggerImageChangeParams": { + "type": "object", + "description": "", + "properties": { + "automatic": { + "type": "boolean", + "description": "whether detection of a new tag value should trigger a deployment" + }, + "containerNames": { + "type": "array", + "description": "restricts tag updates to a set of container names in the pod", + "items": { + "type": "string", + "description": "restricts tag updates to a set of container names in the pod" + } + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "lastTriggeredImage": { + "type": "string", + "description": "the last image to be triggered" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerImageChangeParams" + }, + "os_deploy_DeploymentTriggerPolicy": { + "type": "object", + "description": "", + "properties": { + "imageChangeParams": { + "$ref": "#/definitions/os_deploy_DeploymentTriggerImageChangeParams", + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerImageChangeParams" + }, + "type": { + "type": "string", + "description": "the type of the trigger" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.DeploymentTriggerPolicy" + }, + "os_deploy_ExecNewPodHook": { + "type": "object", + "description": "", + "properties": { + "command": { + "type": "array", + "description": "the hook command and its arguments", + "items": { + "type": "string", + "description": "the hook command and its arguments" + } + }, + "containerName": { + "type": "string", + "description": "the name of a container from the pod template whose image will be used for the hook container" + }, + "env": { + "type": "array", + "description": "environment variables provided to the hook container", + "items": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ExecNewPodHook" + }, + "os_deploy_LifecycleHook": { + "type": "object", + "description": "", + "properties": { + "execNewPod": { + "$ref": "#/definitions/os_deploy_ExecNewPodHook", + "javaType": "io.fabric8.openshift.api.model.ExecNewPodHook" + }, + "failurePolicy": { + "type": "string", + "description": "what action to take if the hook fails" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "os_deploy_RecreateDeploymentStrategyParams": { + "type": "object", + "description": "", + "properties": { + "post": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "pre": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RecreateDeploymentStrategyParams" + }, + "os_deploy_RollingDeploymentStrategyParams": { + "type": "object", + "description": "", + "properties": { + "intervalSeconds": { + "type": "integer", + "description": "the time to wait between polling deployment status after update", + "javaType": "Long" + }, + "post": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "pre": { + "$ref": "#/definitions/os_deploy_LifecycleHook", + "javaType": "io.fabric8.openshift.api.model.LifecycleHook" + }, + "timeoutSeconds": { + "type": "integer", + "description": "the time to wait for updates before giving up", + "javaType": "Long" + }, + "updatePercent": { + "type": "integer", + "description": "the percentage of replicas to scale up or down each interval (negative value switches scale order to down/up instead of up/down)" + }, + "updatePeriodSeconds": { + "type": "integer", + "description": "the time to wait between individual pod updates", + "javaType": "Long" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RollingDeploymentStrategyParams" + }, + "os_image_Image": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "dockerImageManifest": { + "type": "string", + "description": "raw JSON of the manifest" + }, + "dockerImageMetadata": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + }, + "dockerImageMetadataVersion": { + "type": "string", + "description": "conveys version of the object" + }, + "dockerImageReference": { + "type": "string", + "description": "string that can be used to pull this image" + }, + "kind": { + "type": "string", + "description": "", + "default": "Image", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Image", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_image_ImageList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of image objects", + "items": { + "$ref": "#/definitions/os_image_Image", + "javaType": "io.fabric8.openshift.api.model.Image" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ImageList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_image_ImageStream": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "ImageStream", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_image_ImageStreamSpec", + "javaType": "io.fabric8.openshift.api.model.ImageStreamSpec" + }, + "status": { + "$ref": "#/definitions/os_image_ImageStreamStatus", + "javaType": "io.fabric8.openshift.api.model.ImageStreamStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStream", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_image_ImageStreamList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of image stream objects", + "items": { + "$ref": "#/definitions/os_image_ImageStream", + "javaType": "io.fabric8.openshift.api.model.ImageStream" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ImageStreamList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStreamList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_image_ImageStreamSpec": { + "type": "object", + "description": "", + "properties": { + "dockerImageRepository": { + "type": "string", + "description": "optional field if specified this stream is backed by a Docker repository on this server" + }, + "tags": { + "type": "array", + "description": "map arbitrary string values to specific image locators", + "items": { + "$ref": "#/definitions/os_image_NamedTagReference", + "javaType": "io.fabric8.openshift.api.model.NamedTagReference" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStreamSpec" + }, + "os_image_ImageStreamStatus": { + "type": "object", + "description": "", + "properties": { + "dockerImageRepository": { + "type": "string", + "description": "represents the effective location this stream may be accessed at" + }, + "tags": { + "type": "array", + "description": "historical record of images associated with each tag", + "items": { + "$ref": "#/definitions/os_image_NamedTagEventList", + "javaType": "io.fabric8.openshift.api.model.NamedTagEventList" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ImageStreamStatus" + }, + "os_image_NamedTagEventList": { + "type": "object", + "description": "", + "properties": { + "items": { + "type": "array", + "description": "list of tag events related to the tag", + "items": { + "$ref": "#/definitions/os_image_TagEvent", + "javaType": "io.fabric8.openshift.api.model.TagEvent" + } + }, + "tag": { + "type": "string", + "description": "the tag" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedTagEventList" + }, + "os_image_NamedTagReference": { + "type": "object", + "description": "", + "properties": { + "annotations": { + "type": "object", + "description": "annotations associated with images using this tag", + "additionalProperties": { + "type": "string", + "description": "annotations associated with images using this tag" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "from": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + }, + "name": { + "type": "string", + "description": "name of tag" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.NamedTagReference" + }, + "os_image_TagEvent": { + "type": "object", + "description": "", + "properties": { + "created": { + "type": "string", + "description": "when the event was created" + }, + "dockerImageReference": { + "type": "string", + "description": "the string that can be used to pull this image" + }, + "image": { + "type": "string", + "description": "the image" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.TagEvent" + }, + "os_oauth_OAuthAccessToken": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "authorizeToken": { + "type": "string", + "description": "contains the token that authorized this token" + }, + "clientName": { + "type": "string", + "description": "references the client that created this token" + }, + "expiresIn": { + "type": "integer", + "description": "is the seconds from creation time before this token expires", + "javaType": "Long" + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAccessToken", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "redirectURI": { + "type": "string", + "description": "redirection URI associated with the token" + }, + "refreshToken": { + "type": "string", + "description": "optional value by which this token can be renewed" + }, + "scopes": { + "type": "array", + "description": "list of requested scopes", + "items": { + "type": "string", + "description": "list of requested scopes" + } + }, + "userName": { + "type": "string", + "description": "user name associated with this token" + }, + "userUID": { + "type": "string", + "description": "unique UID associated with this token" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAccessToken", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthAccessTokenList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth access tokens", + "items": { + "$ref": "#/definitions/os_oauth_OAuthAccessToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAccessToken" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAccessTokenList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAccessTokenList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_oauth_OAuthAuthorizeToken": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "clientName": { + "type": "string", + "description": "references the client that created this token" + }, + "expiresIn": { + "type": "integer", + "description": "seconds from creation time before this token expires", + "javaType": "Long" + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAuthorizeToken", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "redirectURI": { + "type": "string", + "description": "redirection URI associated with the token" + }, + "scopes": { + "type": "array", + "description": "list of requested scopes", + "items": { + "type": "string", + "description": "list of requested scopes" + } + }, + "state": { + "type": "string", + "description": "state data from request" + }, + "userName": { + "type": "string", + "description": "user name associated with this token" + }, + "userUID": { + "type": "string", + "description": "unique UID associated with this token. userUID and userName must both match for this token to be valid" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeToken", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthAuthorizeTokenList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth authorization tokens", + "items": { + "$ref": "#/definitions/os_oauth_OAuthAuthorizeToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeToken" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthAuthorizeTokenList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeTokenList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_oauth_OAuthClient": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClient", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "redirectURIs": { + "type": "array", + "description": "valid redirection URIs associated with a client", + "items": { + "type": "string", + "description": "valid redirection URIs associated with a client" + } + }, + "respondWithChallenges": { + "type": "boolean", + "description": "indicates whether the client wants authentication needed responses made in the form of challenges instead of redirects" + }, + "secret": { + "type": "string", + "description": "unique secret associated with a client" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClient", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthClientAuthorization": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "clientName": { + "type": "string", + "description": "references the client that created this authorization" + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClientAuthorization", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "scopes": { + "type": "array", + "description": "list of granted scopes", + "items": { + "type": "string", + "description": "list of granted scopes" + } + }, + "userName": { + "type": "string", + "description": "user name that authorized this client" + }, + "userUID": { + "type": "string", + "description": "unique UID associated with this authorization. userUID and userName must both match for this authorization to be valid" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorization", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_oauth_OAuthClientAuthorizationList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth client authorizations", + "items": { + "$ref": "#/definitions/os_oauth_OAuthClientAuthorization", + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorization" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClientAuthorizationList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorizationList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_oauth_OAuthClientList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of oauth clients", + "items": { + "$ref": "#/definitions/os_oauth_OAuthClient", + "javaType": "io.fabric8.openshift.api.model.OAuthClient" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "OAuthClientList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.OAuthClientList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_project_Project": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Project", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_project_ProjectSpec", + "javaType": "io.fabric8.openshift.api.model.ProjectSpec" + }, + "status": { + "$ref": "#/definitions/os_project_ProjectStatus", + "javaType": "io.fabric8.openshift.api.model.ProjectStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Project", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_project_ProjectList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of projects", + "items": { + "$ref": "#/definitions/os_project_Project", + "javaType": "io.fabric8.openshift.api.model.Project" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "ProjectList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_project_ProjectRequest": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "description": { + "type": "string", + "description": "description to apply to a project" + }, + "displayName": { + "type": "string", + "description": "display name to apply to a project" + }, + "kind": { + "type": "string", + "description": "", + "default": "ProjectRequest", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectRequest", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_project_ProjectSpec": { + "type": "object", + "description": "", + "properties": { + "finalizers": { + "type": "array", + "description": "an opaque list of values that must be empty to permanently remove object from storage", + "items": { + "type": "string", + "description": "an opaque list of values that must be empty to permanently remove object from storage" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectSpec" + }, + "os_project_ProjectStatus": { + "type": "object", + "description": "", + "properties": { + "phase": { + "type": "string", + "description": "phase is the current lifecycle phase of the project" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.ProjectStatus" + }, + "os_route_Route": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Route", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "spec": { + "$ref": "#/definitions/os_route_RouteSpec", + "javaType": "io.fabric8.openshift.api.model.RouteSpec" + }, + "status": { + "$ref": "#/definitions/os_route_RouteStatus", + "javaType": "io.fabric8.openshift.api.model.RouteStatus" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Route", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_route_RouteList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of routes", + "items": { + "$ref": "#/definitions/os_route_Route", + "javaType": "io.fabric8.openshift.api.model.Route" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "RouteList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RouteList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_route_RouteSpec": { + "type": "object", + "description": "", + "properties": { + "host": { + "type": "string", + "description": "optional: alias/dns that points to the service" + }, + "path": { + "type": "string", + "description": "optional: path that the router watches to route traffic to the service" + }, + "tls": { + "$ref": "#/definitions/os_route_TLSConfig", + "javaType": "io.fabric8.openshift.api.model.TLSConfig" + }, + "to": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RouteSpec" + }, + "os_route_RouteStatus": { + "type": "object", + "description": "", + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.RouteStatus" + }, + "os_route_TLSConfig": { + "type": "object", + "description": "", + "properties": { + "caCertificate": { + "type": "string", + "description": "provides the cert authority certificate contents" + }, + "certificate": { + "type": "string", + "description": "provides certificate contents" + }, + "destinationCACertificate": { + "type": "string", + "description": "provides the contents of the ca certificate of the final destination. When using re-encrypt termination this file should be provided in order to have routers use it for health checks on the secure connection" + }, + "key": { + "type": "string", + "description": "provides key file contents" + }, + "termination": { + "type": "string", + "description": "indicates termination type. if not set" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.TLSConfig" + }, + "os_template_Parameter": { + "type": "object", + "description": "", + "properties": { + "description": { + "type": "string", + "description": "optional: describes the parameter" + }, + "from": { + "type": "string", + "description": "input value for the generator" + }, + "generate": { + "type": "string", + "description": "optional: generate specifies the generator to be used to generate random string from an input value specified by the from field. the result string is stored in the value field. if not specified" + }, + "name": { + "type": "string", + "description": "name of the parameter" + }, + "required": { + "type": "boolean", + "description": "indicates the parameter must have a non-empty value or be generated" + }, + "value": { + "type": "string", + "description": "optional: holds the parameter data. if specified" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Parameter" + }, + "os_template_Template": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Template", + "required": true + }, + "labels": { + "type": "object", + "description": "optional: list of lables that are applied to every object during the template to config transformation", + "additionalProperties": { + "type": "string", + "description": "optional: list of lables that are applied to every object during the template to config transformation" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "objects": { + "type": "array", + "description": "list of objects to include in the template", + "items": { + "$ref": "#/definitions/kubernetes_runtime_RawExtension", + "javaType": "io.fabric8.kubernetes.api.model.HasMetadata" + } + }, + "parameters": { + "type": "array", + "description": "optional: list of parameters used during template to config transformation", + "items": { + "$ref": "#/definitions/os_template_Parameter", + "javaType": "io.fabric8.openshift.api.model.Parameter" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Template", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_template_TemplateList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of templates", + "items": { + "$ref": "#/definitions/os_template_Template", + "javaType": "io.fabric8.openshift.api.model.Template" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "TemplateList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.TemplateList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_user_Group": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "kind": { + "type": "string", + "description": "", + "default": "Group", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "users": { + "type": "array", + "description": "list of users in this group", + "items": { + "type": "string", + "description": "list of users in this group" + } + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Group", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_user_GroupList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of groups", + "items": { + "$ref": "#/definitions/os_user_Group", + "javaType": "io.fabric8.openshift.api.model.Group" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "GroupList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.GroupList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_user_Identity": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "extra": { + "type": "object", + "description": "extra information for this identity", + "additionalProperties": { + "type": "string", + "description": "extra information for this identity" + }, + "javaType": "java.util.Map\u003cString,String\u003e" + }, + "kind": { + "type": "string", + "description": "", + "default": "Identity", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "providerName": { + "type": "string", + "description": "source of identity information" + }, + "providerUserName": { + "type": "string", + "description": "uniquely represents this identity in the scope of the provider" + }, + "user": { + "$ref": "#/definitions/kubernetes_ObjectReference", + "javaType": "io.fabric8.kubernetes.api.model.ObjectReference" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Identity", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_user_IdentityList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of identities", + "items": { + "$ref": "#/definitions/os_user_Identity", + "javaType": "io.fabric8.openshift.api.model.Identity" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "IdentityList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.IdentityList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "os_user_User": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "fullName": { + "type": "string", + "description": "full name of user" + }, + "groups": { + "type": "array", + "description": "list of groups", + "items": { + "type": "string", + "description": "list of groups" + } + }, + "identities": { + "type": "array", + "description": "list of identities", + "items": { + "type": "string", + "description": "list of identities" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "User", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.User", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.HasMetadata" + ] + }, + "os_user_UserList": { + "type": "object", + "description": "", + "properties": { + "apiVersion": { + "type": "string", + "description": "", + "default": "v1", + "required": true, + "enum": [ + "v1" + ] + }, + "items": { + "type": "array", + "description": "list of users", + "items": { + "$ref": "#/definitions/os_user_User", + "javaType": "io.fabric8.openshift.api.model.User" + } + }, + "kind": { + "type": "string", + "description": "", + "default": "UserList", + "required": true + }, + "metadata": { + "$ref": "#/definitions/kubernetes_ListMeta", + "javaType": "io.fabric8.kubernetes.api.model.ListMeta" + } + }, + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.UserList", + "javaInterfaces": [ + "io.fabric8.kubernetes.api.model.KubernetesResource", + "io.fabric8.kubernetes.api.model.KubernetesResourceList" + ] + }, + "speter_inf_Dec": { + "type": "object", + "description": "", + "additionalProperties": true, + "javaType": "io.fabric8.openshift.api.model.Dec" + } + }, + "type": "object", + "properties": { + "BaseKubernetesList": { + "$ref": "#/definitions/kubernetes_List", + "javaType": "io.fabric8.kubernetes.api.model.BaseKubernetesList" + }, + "BuildConfigList": { + "$ref": "#/definitions/os_build_BuildConfigList", + "javaType": "io.fabric8.openshift.api.model.BuildConfigList" + }, + "BuildList": { + "$ref": "#/definitions/os_build_BuildList", + "javaType": "io.fabric8.openshift.api.model.BuildList" + }, + "BuildRequest": { + "$ref": "#/definitions/os_build_BuildRequest", + "javaType": "io.fabric8.openshift.api.model.BuildRequest" + }, + "ClusterPolicy": { + "$ref": "#/definitions/os_authorization_ClusterPolicy", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicy" + }, + "ClusterPolicyBinding": { + "$ref": "#/definitions/os_authorization_ClusterPolicyBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBinding" + }, + "ClusterPolicyBindingList": { + "$ref": "#/definitions/os_authorization_ClusterPolicyBindingList", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyBindingList" + }, + "ClusterPolicyList": { + "$ref": "#/definitions/os_authorization_ClusterPolicyList", + "javaType": "io.fabric8.openshift.api.model.ClusterPolicyList" + }, + "ClusterRoleBinding": { + "$ref": "#/definitions/os_authorization_ClusterRoleBinding", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBinding" + }, + "ClusterRoleBindingList": { + "$ref": "#/definitions/os_authorization_ClusterRoleBindingList", + "javaType": "io.fabric8.openshift.api.model.ClusterRoleBindingList" + }, + "Config": { + "$ref": "#/definitions/kubernetes_config_Config", + "javaType": "io.fabric8.kubernetes.api.model.Config" + }, + "ContainerStatus": { + "$ref": "#/definitions/kubernetes_ContainerStatus", + "javaType": "io.fabric8.kubernetes.api.model.ContainerStatus" + }, + "DeploymentConfigList": { + "$ref": "#/definitions/os_deploy_DeploymentConfigList", + "javaType": "io.fabric8.openshift.api.model.DeploymentConfigList" + }, + "Endpoints": { + "$ref": "#/definitions/kubernetes_Endpoints", + "javaType": "io.fabric8.kubernetes.api.model.Endpoints" + }, + "EndpointsList": { + "$ref": "#/definitions/kubernetes_EndpointsList", + "javaType": "io.fabric8.kubernetes.api.model.EndpointsList" + }, + "EnvVar": { + "$ref": "#/definitions/kubernetes_EnvVar", + "javaType": "io.fabric8.kubernetes.api.model.EnvVar" + }, + "EventList": { + "$ref": "#/definitions/kubernetes_EventList", + "javaType": "io.fabric8.kubernetes.api.model.EventList" + }, + "Group": { + "$ref": "#/definitions/os_user_Group", + "javaType": "io.fabric8.openshift.api.model.Group" + }, + "GroupList": { + "$ref": "#/definitions/os_user_GroupList", + "javaType": "io.fabric8.openshift.api.model.GroupList" + }, + "Identity": { + "$ref": "#/definitions/os_user_Identity", + "javaType": "io.fabric8.openshift.api.model.Identity" + }, + "IdentityList": { + "$ref": "#/definitions/os_user_IdentityList", + "javaType": "io.fabric8.openshift.api.model.IdentityList" + }, + "ImageList": { + "$ref": "#/definitions/os_image_ImageList", + "javaType": "io.fabric8.openshift.api.model.ImageList" + }, + "ImageStreamList": { + "$ref": "#/definitions/os_image_ImageStreamList", + "javaType": "io.fabric8.openshift.api.model.ImageStreamList" + }, + "LocalSubjectAccessReview": { + "$ref": "#/definitions/os_authorization_LocalSubjectAccessReview", + "javaType": "io.fabric8.openshift.api.model.LocalSubjectAccessReview" + }, + "Namespace": { + "$ref": "#/definitions/kubernetes_Namespace", + "javaType": "io.fabric8.kubernetes.api.model.Namespace" + }, + "NamespaceList": { + "$ref": "#/definitions/kubernetes_NamespaceList", + "javaType": "io.fabric8.kubernetes.api.model.NamespaceList" + }, + "Node": { + "$ref": "#/definitions/kubernetes_Node", + "javaType": "io.fabric8.kubernetes.api.model.Node" + }, + "NodeList": { + "$ref": "#/definitions/kubernetes_NodeList", + "javaType": "io.fabric8.kubernetes.api.model.NodeList" + }, + "OAuthAccessToken": { + "$ref": "#/definitions/os_oauth_OAuthAccessToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAccessToken" + }, + "OAuthAccessTokenList": { + "$ref": "#/definitions/os_oauth_OAuthAccessTokenList", + "javaType": "io.fabric8.openshift.api.model.OAuthAccessTokenList" + }, + "OAuthAuthorizeToken": { + "$ref": "#/definitions/os_oauth_OAuthAuthorizeToken", + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeToken" + }, + "OAuthAuthorizeTokenList": { + "$ref": "#/definitions/os_oauth_OAuthAuthorizeTokenList", + "javaType": "io.fabric8.openshift.api.model.OAuthAuthorizeTokenList" + }, + "OAuthClient": { + "$ref": "#/definitions/os_oauth_OAuthClient", + "javaType": "io.fabric8.openshift.api.model.OAuthClient" + }, + "OAuthClientAuthorization": { + "$ref": "#/definitions/os_oauth_OAuthClientAuthorization", + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorization" + }, + "OAuthClientAuthorizationList": { + "$ref": "#/definitions/os_oauth_OAuthClientAuthorizationList", + "javaType": "io.fabric8.openshift.api.model.OAuthClientAuthorizationList" + }, + "OAuthClientList": { + "$ref": "#/definitions/os_oauth_OAuthClientList", + "javaType": "io.fabric8.openshift.api.model.OAuthClientList" + }, + "ObjectMeta": { + "$ref": "#/definitions/kubernetes_ObjectMeta", + "javaType": "io.fabric8.kubernetes.api.model.ObjectMeta" + }, + "PersistentVolume": { + "$ref": "#/definitions/kubernetes_PersistentVolume", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolume" + }, + "PersistentVolumeClaim": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaim", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaim" + }, + "PersistentVolumeClaimList": { + "$ref": "#/definitions/kubernetes_PersistentVolumeClaimList", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeClaimList" + }, + "PersistentVolumeList": { + "$ref": "#/definitions/kubernetes_PersistentVolumeList", + "javaType": "io.fabric8.kubernetes.api.model.PersistentVolumeList" + }, + "PodList": { + "$ref": "#/definitions/kubernetes_PodList", + "javaType": "io.fabric8.kubernetes.api.model.PodList" + }, + "Policy": { + "$ref": "#/definitions/os_authorization_Policy", + "javaType": "io.fabric8.openshift.api.model.Policy" + }, + "PolicyBinding": { + "$ref": "#/definitions/os_authorization_PolicyBinding", + "javaType": "io.fabric8.openshift.api.model.PolicyBinding" + }, + "PolicyBindingList": { + "$ref": "#/definitions/os_authorization_PolicyBindingList", + "javaType": "io.fabric8.openshift.api.model.PolicyBindingList" + }, + "PolicyList": { + "$ref": "#/definitions/os_authorization_PolicyList", + "javaType": "io.fabric8.openshift.api.model.PolicyList" + }, + "Project": { + "$ref": "#/definitions/os_project_Project", + "javaType": "io.fabric8.openshift.api.model.Project" + }, + "ProjectList": { + "$ref": "#/definitions/os_project_ProjectList", + "javaType": "io.fabric8.openshift.api.model.ProjectList" + }, + "ProjectRequest": { + "$ref": "#/definitions/os_project_ProjectRequest", + "javaType": "io.fabric8.openshift.api.model.ProjectRequest" + }, + "Quantity": { + "$ref": "#/definitions/kubernetes_resource_Quantity", + "javaType": "io.fabric8.kubernetes.api.model.Quantity" + }, + "ReplicationControllerList": { + "$ref": "#/definitions/kubernetes_ReplicationControllerList", + "javaType": "io.fabric8.kubernetes.api.model.ReplicationControllerList" + }, + "ResourceQuota": { + "$ref": "#/definitions/kubernetes_ResourceQuota", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuota" + }, + "ResourceQuotaList": { + "$ref": "#/definitions/kubernetes_ResourceQuotaList", + "javaType": "io.fabric8.kubernetes.api.model.ResourceQuotaList" + }, + "Role": { + "$ref": "#/definitions/os_authorization_Role", + "javaType": "io.fabric8.openshift.api.model.Role" + }, + "RoleBinding": { + "$ref": "#/definitions/os_authorization_RoleBinding", + "javaType": "io.fabric8.openshift.api.model.RoleBinding" + }, + "RoleBindingList": { + "$ref": "#/definitions/os_authorization_RoleBindingList", + "javaType": "io.fabric8.openshift.api.model.RoleBindingList" + }, + "RoleList": { + "$ref": "#/definitions/os_authorization_RoleList", + "javaType": "io.fabric8.openshift.api.model.RoleList" + }, + "RootPaths": { + "$ref": "#/definitions/api_RootPaths", + "javaType": "io.fabric8.kubernetes.api.model.RootPaths" + }, + "RouteList": { + "$ref": "#/definitions/os_route_RouteList", + "javaType": "io.fabric8.openshift.api.model.RouteList" + }, + "Secret": { + "$ref": "#/definitions/kubernetes_Secret", + "javaType": "io.fabric8.kubernetes.api.model.Secret" + }, + "SecretList": { + "$ref": "#/definitions/kubernetes_SecretList", + "javaType": "io.fabric8.kubernetes.api.model.SecretList" + }, + "SecurityContextConstraints": { + "$ref": "#/definitions/kubernetes_SecurityContextConstraints", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraints" + }, + "SecurityContextConstraintsList": { + "$ref": "#/definitions/kubernetes_SecurityContextConstraintsList", + "javaType": "io.fabric8.kubernetes.api.model.SecurityContextConstraintsList" + }, + "ServiceAccount": { + "$ref": "#/definitions/kubernetes_ServiceAccount", + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccount" + }, + "ServiceAccountList": { + "$ref": "#/definitions/kubernetes_ServiceAccountList", + "javaType": "io.fabric8.kubernetes.api.model.ServiceAccountList" + }, + "ServiceList": { + "$ref": "#/definitions/kubernetes_ServiceList", + "javaType": "io.fabric8.kubernetes.api.model.ServiceList" + }, + "Status": { + "$ref": "#/definitions/kubernetes_Status", + "javaType": "io.fabric8.kubernetes.api.model.Status" + }, + "SubjectAccessReview": { + "$ref": "#/definitions/os_authorization_SubjectAccessReview", + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReview" + }, + "SubjectAccessReviewResponse": { + "$ref": "#/definitions/os_authorization_SubjectAccessReviewResponse", + "javaType": "io.fabric8.openshift.api.model.SubjectAccessReviewResponse" + }, + "TagEvent": { + "$ref": "#/definitions/os_image_TagEvent", + "javaType": "io.fabric8.openshift.api.model.TagEvent" + }, + "Template": { + "$ref": "#/definitions/os_template_Template", + "javaType": "io.fabric8.openshift.api.model.Template" + }, + "TemplateList": { + "$ref": "#/definitions/os_template_TemplateList", + "javaType": "io.fabric8.openshift.api.model.TemplateList" + }, + "User": { + "$ref": "#/definitions/os_user_User", + "javaType": "io.fabric8.openshift.api.model.User" + }, + "UserList": { + "$ref": "#/definitions/os_user_UserList", + "javaType": "io.fabric8.openshift.api.model.UserList" + }, + "WatchEvent": { + "$ref": "#/definitions/kubernetes_watch_WatchEvent", + "javaType": "io.fabric8.kubernetes.api.model.WatchEvent" + } + }, + "additionalProperties": true + } + + +} \ No newline at end of file diff --git a/plugins/kubernetes/ts/schemaHelpers.ts b/plugins/kubernetes/ts/schemaHelpers.ts new file mode 100644 index 0000000..2a91fc2 --- /dev/null +++ b/plugins/kubernetes/ts/schemaHelpers.ts @@ -0,0 +1,26 @@ +/// +/// +module Kubernetes { + + export function schemaSetRequired(schema, propertyName, isRequired = true) { + if (schema && propertyName) { + var required = schema.required; + if (isRequired) { + if (!required) { + required = []; + schema.required = required; + } + if (!_.contains(required, propertyName)) { + required.push(propertyName); + } + } else { + if (required) { + var idx = required.indexOf(propertyName); + if (idx >= 0) { + required.splice(idx, 1); + } + } + } + } + } +} diff --git a/plugins/kubernetes/ts/secret.ts b/plugins/kubernetes/ts/secret.ts new file mode 100644 index 0000000..3d11972 --- /dev/null +++ b/plugins/kubernetes/ts/secret.ts @@ -0,0 +1,250 @@ +/// +/// +/// + +module Kubernetes { + + export var SecretController = controller("SecretController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "K8SClientFactory", + ($scope, KubernetesModel:Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, K8SClientFactory) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + selectSubNavBar($scope, "Secrets", $scope.id ? "Edit Secret: " + $scope.id : "Create Secret"); + + var kubeClient = createKubernetesClient("secrets"); + + var onSaveUrl = $location.search()["savedUrl"]; + var createKind = $location.search()["kind"]; + + $scope.sshKeys = sshSecretDataKeys; + $scope.httpsKeys = httpsSecretDataKeys; + + var secretLabels = { + "ssh-key": "SSH private key", + "ssh-key.pub": "SSH public key", + "ca.crt": "CA Certificate", + ".dockercfg": "Docker config", + "username": "User name" + }; + var secretTooltips = { + "ssh-key": "SSH private key text contents", + "ca.crt": "Certificate Authority (CA) Certificate", + ".dockercfg": "Docker configuration token" + }; + + + $scope.$on('kubernetesModelUpdated', function () { + if ($scope.id && !$scope.secret) { + updateData(); + } + }); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.propertyKeys = () => { + return _.keys(secretLabels); + }; + + $scope.checkNameUnique = (value) => { + var answer = true; + angular.forEach($scope.model.secrets, (secret) => { + var name = getName(secret); + if (value === name) { + answer = false; + } + }); + return answer; + }; + + $scope.checkFieldUnique = (key) => { + return $scope.entity.properties[key] ? false : true; + }; + + $scope.hasAllKeys = (keys) => { + var answer = keys && keys.length; + angular.forEach(keys, (key) => { + if (!$scope.entity.properties[key]) { + answer = false; + } + }); + return answer; + }; + + $scope.addFieldDialog = { + controller: null, + newReplicas: 0, + dialog: new UI.Dialog(), + onOk: () => { + $scope.addFieldDialog.dialog.close(); + $scope.addDataField(); + }, + open: (controller) => { + var addFieldDialog = $scope.addFieldDialog; + addFieldDialog.dialog.open(); + + $timeout(() => { + $('#newDataName').focus(); + }, 50); + }, + close: () => { + $scope.addFieldDialog.dialog.close(); + } + }; + + + + $scope.entityChanged = () => { + $scope.changed = true; + }; + + $scope.addFields = (keys) => { + angular.forEach(keys, (key) => addField(key)); + Core.$apply($scope); + }; + + function addField(key) { + var property = createProperty(key, ""); + $scope.entity.properties[key] = property; + $scope.entity.newDataKey = ""; + $scope.showAddDataFieldForm = false; + $scope.entityChanged(); + } + + $scope.addDataField = () => { + var key = $scope.entity.newDataKey; + if (key) { + addField(key); + Core.$apply($scope); + } + }; + + $scope.deleteProperty = (key) => { + if (key) { + delete $scope.entity.properties[key]; + $scope.entityChanged(); + Core.$apply($scope); + } + }; + + $scope.cancel = () => { + updateData(); + }; + + $scope.save = () => { + var entity = $scope.entity || {}; + var name = entity.name; + if (name) { + if (!$scope.secret) { + $scope.secret = { + apiVersion: Kubernetes.defaultApiVersion, + kind: "Secret", + metadata: { + name: "" + }, + data: {} + } + } + var data = {}; + angular.forEach(entity.properties, (property) => { + var key = property.key; + var value = property.value || ""; + if (key) { + data[key] = window.btoa(value); + } + }); + $scope.secret.metadata.name = name; + $scope.secret.data = data; + + Core.notification('info', "Saving secret " + name); + + kubeClient.put($scope.secret, + (data) => { + var secretsLink = onSaveUrl || Developer.namespaceLink($scope, $routeParams, "secrets"); + var params = {}; + if (onSaveUrl) { + params['secret'] = name; + } + $location.path(secretsLink); + $location.search(params); + log.info("navigating to URL: " + secretsLink + " with params " + angular.toJson($location.search())); + }, + (err) => { + Core.notification('error', "Failed to secret " + name + "\n" + err); + }); + } + }; + + updateData(); + + function createProperty(key, text) { + var label = secretLabels[key] || Core.humanizeValue(key); + var tooltip = secretTooltips[key] || "Value of the " + label; + + var rows = 5; + var lines = text.split("\n").length + 1; + if (lines > rows) { + rows = lines; + } + var type = "textarea"; + if (key === "username") { + type = "text"; + if (!text) { + text = currentUserName(); + } + } else if (key === "password") { + type = "password"; + } + var property = { + key: key, + label: label, + tooltip: tooltip, + rows: rows, + value: text, + type: type + }; + return property; + } + + function updateData() { + $scope.item = null; + $scope.changed = false; + $scope.entity = { + name: $scope.id, + properties: {} + }; + if ($scope.id) { + angular.forEach($scope.model.secrets, (secret) => { + var name = getName(secret); + if (name === $scope.id) { + $scope.secret = secret; + angular.forEach(secret.data, (value, key) => { + var text = ""; + if (angular.isString(value) && value) { + text = window.atob(value); + } + var property = createProperty(key, text); + $scope.entity.properties[key] = property; + }); + $scope.fetched = true; + Core.$apply($scope); + } + }); + } else { + if (createKind === "ssh") { + $scope.addFields($scope.sshKeys); + } else if (createKind === "https") { + $scope.addFields($scope.httpsKeys); + } + $scope.fetched = true; + Core.$apply($scope); + } + } + }]); +} diff --git a/plugins/kubernetes/ts/secrets.ts b/plugins/kubernetes/ts/secrets.ts new file mode 100644 index 0000000..3ed5a22 --- /dev/null +++ b/plugins/kubernetes/ts/secrets.ts @@ -0,0 +1,76 @@ +/// +/// +/// +/// + +module Kubernetes { + + export var SecretsController = controller("SecretsController", ["$scope", "KubernetesModel", "KubernetesState", "ServiceRegistry", "$dialog", "$window", "$templateCache", "$routeParams", "$location", "localStorage", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, ServiceRegistry, $dialog, $window, $templateCache, $routeParams, $location:ng.ILocationService, localStorage, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.$on('kubernetesModelUpdated', function () { + Core.$apply($scope); + }); + + $scope.$createSecretLink = Developer.namespaceLink($scope, $routeParams, "secretCreate"); + + var kubeClient = createKubernetesClient("secrets"); + + $scope.tableConfig = { + data: 'model.secrets', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { + field: '_key', + displayName: 'Name', + defaultSort: true, + cellTemplate: $templateCache.get("idTemplate.html") + }, + { + field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + }, + ] + }; + + $scope.deletePrompt = (selected) => { + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected, next) { + if (next) { + kubeClient.delete(next, () => { + deleteSelected(selected, selected.shift()); + }); + } else { + // TODO + // updateData(); + } + } + + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete Secrets', + action: 'The following Secrets will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + }]); +} diff --git a/plugins/kubernetes/ts/service.ts b/plugins/kubernetes/ts/service.ts new file mode 100644 index 0000000..9acc1af --- /dev/null +++ b/plugins/kubernetes/ts/service.ts @@ -0,0 +1,55 @@ +/// +/// +/// + +module Kubernetes { + + export var ServiceController = controller("ServiceController", + ["$scope", "KubernetesModel", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.rawModel = null; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.itemConfig = { + properties: { + '^\\/labels$': { + template: $templateCache.get('labelTemplate.html') + } + } + }; + + $scope.$on('kubernetesModelUpdated', function () { + updateData(); + }); + + $scope.$watch('model.services', (newValue, oldValue) => { + updateData(); + }, true); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + $scope.flipRaw = () => { + $scope.rawMode = !$scope.rawMode; + Core.$apply($scope); + }; + + updateData(); + + function updateData() { + $scope.id = $routeParams["id"]; + $scope.namespace = $routeParams["namespace"] || KubernetesState.selectedNamespace; + $scope.item = $scope.model.getService($scope.namespace, $scope.id); + if ($scope.item) { + $scope.rawModel = toRawYaml($scope.item); + } + Core.$apply($scope); + } + }]); +} diff --git a/plugins/kubernetes/ts/serviceEdit.ts b/plugins/kubernetes/ts/serviceEdit.ts new file mode 100644 index 0000000..8837509 --- /dev/null +++ b/plugins/kubernetes/ts/serviceEdit.ts @@ -0,0 +1,37 @@ +/// +/// +/// + +module Kubernetes { + + export var ServiceEditController = controller("ServiceEditController", + ["$scope", "KubernetesModel", "KubernetesState", "KubernetesSchema", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", "SchemaRegistry", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesState, KubernetesSchema, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL, schemas:HawtioForms.SchemaRegistry) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + $scope.id = $routeParams["id"]; + $scope.schema = KubernetesSchema; + $scope.config = schemas.cloneSchema("io.fabric8.kubernetes.api.model.Service"); + //$scope.config = KubernetesSchema.definitions.kubernetes_v1beta2_Service; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$on('$routeUpdate', ($event) => { + updateData(); + }); + + updateData(); + + function updateData() { + if ($scope.id) { + $scope.entity = $scope.model.getService(KubernetesState.selectedNamespace, $scope.id); + Core.$apply($scope); + $scope.fetched = true; + } else { + $scope.fetched = true; + } + } + }]); +} diff --git a/plugins/kubernetes/ts/serviceRegistry.ts b/plugins/kubernetes/ts/serviceRegistry.ts new file mode 100644 index 0000000..546a306 --- /dev/null +++ b/plugins/kubernetes/ts/serviceRegistry.ts @@ -0,0 +1,91 @@ +/// +/// +/// +/// + +module Kubernetes { + + _module.factory('ServiceRegistry', [() => { + return new ServiceRegistryService(); + }]); + + /** + * Represents a simple interface to service discovery that can be used early on in the application lifecycle before the + * underlying model has been created via dependency injection + */ + export class ServiceRegistryService { + private model:KubernetesModelService = null; + + /** + * Returns true if there is a service available for the given ID or false + */ + public hasService(serviceName: string) { + return this.findService(serviceName) ? true : false; + } + + /** + * Returns the service for the given service name (ID) or null if it cannot be found + * + * @param serviceName the name of the service to look for + * @return {null} + */ + public findService(serviceName: string) { + var answer = null; + if (serviceName) { + var model = this.getModel(); + if (model) { + var namespace = model.currentNamespace(); + return model.getService(namespace ,serviceName); +/* + TODO lets only look in the current namespace + angular.forEach(model.services, (service) => { + if (serviceName === getName(service)) { + answer = service; + } + }); +*/ + } + } + return answer; + } + + /** + * Returns the service link for the given service name + * + * @param serviceName the name of the service + * @return {null} + */ + public serviceLink(serviceName: string): string { + var service = this.findService(serviceName); + return serviceLinkUrl(service); + } + + /** + * Returns the service link for the given service name if its ready (has at least one ready pod) + * + * @param serviceName the name of the service + * @return {null} + */ + public serviceReadyLink(serviceName: string): string { + var service = this.findService(serviceName); + if (readyPodCount(service)) { + return serviceLinkUrl(service); + } else { + return null; + } + } + + private getModel():KubernetesModelService { + var answer = this.model; + // lets allow lazy load so we can be invoked before the injector has been created + if (!answer) { + var injector = HawtioCore.injector; + if (injector) { + this.model = injector.get('KubernetesModel'); + } + } + answer = this.model; + return answer; + } + } +} diff --git a/plugins/kubernetes/ts/services.ts b/plugins/kubernetes/ts/services.ts new file mode 100644 index 0000000..6d88bd9 --- /dev/null +++ b/plugins/kubernetes/ts/services.ts @@ -0,0 +1,102 @@ +/// +/// +/// + +module Kubernetes { + + export var ServiceApps = _module.controller('Kubernetes.ServiceApps', ($scope, KubernetesModel) => { + $scope.model = KubernetesModel; + }); + + export var Services = controller("Services", + ["$scope", "KubernetesModel", "KubernetesServices", "KubernetesPods", "KubernetesState", "$templateCache", "$location", "$routeParams", "$http", "$timeout", "KubernetesApiURL", + ($scope, KubernetesModel: Kubernetes.KubernetesModelService, KubernetesServices:ng.resource.IResourceClass, KubernetesPods:ng.resource.IResourceClass, KubernetesState, + $templateCache:ng.ITemplateCacheService, $location:ng.ILocationService, $routeParams, $http, $timeout, KubernetesApiURL) => { + + $scope.kubernetes = KubernetesState; + $scope.model = KubernetesModel; + + ControllerHelpers.bindModelToSearchParam($scope, $location, 'mode', 'mode', 'list'); + + $scope.tableConfig = { + data: 'model.services', + showSelectionCheckbox: true, + enableRowClickSelection: false, + multiSelect: true, + selectedItems: [], + filterOptions: { + filterText: $location.search()["q"] || '' + }, + columnDefs: [ + { field: '_key', + displayName: 'Name', + cellTemplate: $templateCache.get("idTemplate.html") + }, + { field: '$serviceUrl', + displayName: 'Address', + cellTemplate: $templateCache.get("portalAddress.html") + }, + { field: '$podCount', + displayName: 'Pods', + cellTemplate: $templateCache.get("podCountsAndLinkTemplate.html"), + customSortField: (field) => { + // need to concat all the pod counters + var ready = field.$podCounters.ready || 0; + var valid = field.$podCounters.valid || 0; + var waiting = field.$podCounters.waiting || 0; + var error = field.$podCounters.error || 0; + return ready + valid + waiting + error; + } + }, + { field: '$selectorText', + displayName: 'Selector', + cellTemplate: $templateCache.get("selectorTemplate.html") + }, + { field: '$labelsText', + displayName: 'Labels', + cellTemplate: $templateCache.get("labelTemplate.html") + } + ] + }; + + Kubernetes.initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.deletePrompt = (selected) => { + if (angular.isString(selected)) { + selected = [{ + id: selected + }]; + } + UI.multiItemConfirmActionDialog({ + collection: selected, + index: 'metadata.name', + onClose: (result:boolean) => { + if (result) { + function deleteSelected(selected:Array, next:KubePod) { + if (next) { + log.debug("deleting: ", getName(next)); + KubernetesServices.delete({ + id: getName(next) + }, undefined, () => { + log.debug("deleted: ", getName(next)); + deleteSelected(selected, selected.shift()); + }, (error) => { + log.debug("Error deleting: ", error); + deleteSelected(selected, selected.shift()); + }); + } + } + deleteSelected(selected, selected.shift()); + } + }, + title: 'Delete services?', + action: 'The following services will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + + }]); +} diff --git a/plugins/kubernetes/ts/sharedControllers.ts b/plugins/kubernetes/ts/sharedControllers.ts new file mode 100644 index 0000000..1608077 --- /dev/null +++ b/plugins/kubernetes/ts/sharedControllers.ts @@ -0,0 +1,127 @@ +/// +/// +/// + +module Kubernetes { + + // controller for the status icon cell + export var PodStatus = controller("PodStatus", ["$scope", ($scope) => { + $scope.statusMapping = (text) => { + return statusTextToCssClass(text); + } + }]); + + _module.controller("Kubernetes.TermController", ($scope, TerminalService) => { + $scope.canConnectTo = (container) => { + if (container.securityContext && container.securityContext.privileged) { + return false; + } + return true; + } + $scope.openTerminal = (selfLink, containerName) => { + var id = TerminalService.newTerminal(selfLink, containerName); + log.debug("Created terminal, id: ", id); + } + }); + + // controller that deals with the labels per pod + export var Labels = controller("Labels", ["$scope", "$location", ($scope, $location) => { + $scope.labels = []; + var labelKeyWeights = { + "name": 1, + "replicationController": 2, + "group": 3 + }; + $scope.$watch('entity', (newValue, oldValue) => { + if (newValue) { + // log.debug("labels: ", newValue); + // massage the labels a bit + $scope.labels = []; + angular.forEach(Core.pathGet($scope.entity, ["metadata", "labels"]), (value, key) => { + if (key === 'fabric8' || key === 'style' || key === 'status') { + // TODO not sure what this is for, the container type? + return; + } + + $scope.labels.push({ + key: key, + title: value + }); + }); + + // lets sort by key but lets make sure that we weight certain labels so they are first + $scope.labels = $scope.labels.sort((a, b) => { + function getWeight(key) { + return labelKeyWeights[key] || 1000; + } + var n1 = a["key"]; + var n2 = b["key"]; + var w1 = getWeight(n1); + var w2 = getWeight(n2); + var diff = w1 - w2; + if (diff < 0) { + return -1; + } else if (diff > 0) { + return 1; + } + if (n1 && n2) { + if (n1 > n2) { + return 1; + } else if (n1 < n2) { + return -1; + } else { + return 0; + } + } else { + if (n1 === n2) { + return 0; + } else if (n1) { + return 1; + } else { + return -1; + } + } + }); + } + }); + + $scope.handleClick = (entity, labelType:string, value) => { + // log.debug("handleClick, entity: ", entity, " key: ", labelType, " value: ", value); + $scope.$emit('labelFilterUpdate', value.title) + } + + $scope.labelClass = containerLabelClass; + }]); + + //服务状态过滤 + export var Status = controller('Status', ["$scope", "$http", "$interval", "$location", "KubernetesApiURL", ($scope, $http, $interval, $location, KubernetesApiURL) => { + $scope.$watch('entity', (newValue, oldValue) => { + if(newValue){ + //console.log($scope.entity.metadata.labels); + if($scope.entity.metadata.labels.status === "0" && $scope.entity.metadata.labels.lock === "0"){ + var labels = + Kubernetes.updateReplicationControllerLabels($http, KubernetesApiURL, $scope.entity, {"style": "oracle", "status": "0", "lock": "1"}); + var ip = $scope.entity.$pods[0].$host + ":" + $scope.entity.$pods[0].spec.containers[0].ports[0].hostPort; + var timer = $interval(() => { + $http({ + url:'/connectToOracle', + method:'POST', + params:{param: ip} + }).success(function(data,header,config,status){ + if(header === 200){ + console.log(data); + $interval.cancel(timer); + } + }).error(function(data,header,config,status){ + + }); + }, 60000, 10); + + timer.then(() => { + console.log("All Connect Done!"); + }); + } + } + },true); + }]); +} diff --git a/plugins/kubernetes/ts/tabs.ts b/plugins/kubernetes/ts/tabs.ts new file mode 100644 index 0000000..10680f9 --- /dev/null +++ b/plugins/kubernetes/ts/tabs.ts @@ -0,0 +1,14 @@ +/// +/// +/// + +module Kubernetes { + + _module.directive("hawtioTabs", ['HawtioSubTabs', (HawtioSubTabs) => { + return { + link: (scope, element, attrs) => { + HawtioSubTabs.apply(scope.$eval('subTabConfig')); + } + }; + }]); +} diff --git a/plugins/kubernetes/ts/templates.ts b/plugins/kubernetes/ts/templates.ts new file mode 100644 index 0000000..801b457 --- /dev/null +++ b/plugins/kubernetes/ts/templates.ts @@ -0,0 +1,330 @@ +/// + +module Kubernetes { + export var TemplateController = controller("TemplateController", [ + "$scope", "$location", "$http", "$timeout", "$routeParams", "marked", "$templateCache", "$modal", "KubernetesModel", "KubernetesState", "KubernetesApiURL", + ($scope, $location, $http, $timeout, $routeParams, marked, $templateCache, $modal, KubernetesModel, KubernetesState, KubernetesApiURL) => { + var model = $scope.model = KubernetesModel; + $scope.filterText = $location.search()["q"]; + + $scope.targetNamespace = $routeParams.targetNamespace; + initShared($scope, $location, $http, $timeout, $routeParams, KubernetesModel, KubernetesState, KubernetesApiURL); + + $scope.$watchCollection('model.namespaces', () => { + if (!$scope.targetNamespace) { + $scope.targetNamespace = model.currentNamespace(); + } + }); + + var returnTo = new URI($location.search()['returnTo'] || '/kubernetes/apps'); + + function goBack() { + $location.path(returnTo.path()).search(returnTo.query(true)); + } + + function getAnnotations(obj) { + return Core.pathGet(obj, ['metadata', 'annotations']); + } + + function getValueFor(obj, key) { + var annotations = getAnnotations(obj); + if (!annotations) { + return ""; + } + var name = getName(obj); + if (name) { + var fullKey = "fabric8." + name + "/" + key; + var answer = annotations[fullKey]; + if (answer) { + return answer; + } + } + var key: any = _.find(_.keys(annotations), (k: string) => _.endsWith(k, key)); + if (key) { + return annotations[key]; + } else { + return ""; + } + } + + $scope.cancel = () => { + if ($scope.formConfig) { + delete $scope.formConfig; + delete $scope.entity; + $scope.objects = undefined; + return; + } + goBack(); + } + + /* + $scope.$watch('model.templates.length', (newValue) => { + if (newValue === 0) { + goBack(); + } + }); + */ + + $scope.filterTemplates = (template) => { + if (Core.isBlank($scope.filterText)) { + return true; + } + return _.contains(angular.toJson(template), $scope.filterText.toLowerCase()); + }; + + $scope.openFullDescription = (template) => { + var text = marked(getValueFor(template, 'description') || 'No description'); + var modal = $modal.open({ + templateUrl: UrlHelpers.join(templatePath, 'templateDescription.html'), + controller: ['$scope', '$modalInstance', ($scope, $modalInstance) => { + $scope.text = text, + $scope.ok = () => { + modal.close(); + } + }] + }); + }; + + $scope.getDescription = (template) => { + var answer:any = $(marked(getValueFor(template, 'description') || 'No description')); + var textDefault = answer.html(); + var maxLength = 200; + if (textDefault.length > maxLength) { + var truncated = $.trim(textDefault).substring(0, maxLength).split(' ').slice(0, -1).join(' '); + answer.html(truncated + '...'); + answer.append($templateCache.get('truncatedDescriptionTag.html')); + } + return answer.html(); + }; + + $scope.getIconUrl = (template) => { + return getValueFor(template, 'iconUrl') || defaultIconUrl; + }; + + $scope.deployTemplate = (template) => { + log.debug("Template parameters: ", template.parameters); + log.debug("Template objects: ", template.objects); + log.debug("Template annotations: ", template.metadata.annotations); + var templateAnnotations = template.metadata.annotations; + if (templateAnnotations) { + _.forEach(template.objects, (object:any) => { + var annotations = object.metadata.annotations || {}; + var name = getName(object); + var matches = _.filter(_.keys(templateAnnotations), (key) => key.match('.' + name + '/')); + matches.forEach((match) => { + if (!(match in annotations)) { + annotations[match] = templateAnnotations[match]; + } + }); + object.metadata.annotations = annotations; + }); + } + var routeServiceName = undefined; + var service = _.find(template.objects, (obj) => { + if (getKind(obj) === "Service") { + var ports = getPorts(obj); + if (ports && ports.length === 1) { + return true; + } + } else { + return false; + } + }); + if (service) { + routeServiceName = getName(service); + } + log.debug("Service: ", service); + if ((!routeServiceName || !isOpenShift) && (!template.parameters || template.parameters.length === 0)) { + log.debug("No parameters required, deploying objects"); + applyObjects(template.objects); + return; + } + var formConfig = { + style: HawtioForms.FormStyle.STANDARD, + hideLegend: true, + properties: {} + }; + var params = template.parameters; + _.forEach(params, (param:any) => { + var property = {}; + property.label = _.startCase(param.name); + property.description = param.description; + property.default = param.value; + // TODO, do parameters support types? + property.type = 'string'; + formConfig.properties[param.name] = property; + }); + if (routeServiceName && isOpenShift) { + formConfig.properties.createRoute = { + type: 'boolean', + default: true, + label: "Create Route" + }; +/* + formConfig.properties.routeName = { + type: 'string', + label: 'Route Name', + default: routeServiceName, + 'control-group-attributes': { + 'ng-show': 'entity.createRoute' + } + }; +*/ + formConfig.properties.routeServiceName = { + type: 'hidden', + default: routeServiceName + } + + var namespace = currentKubernetesNamespace(); + // TODO store this in localStorage! + var domain = "vagrant.f8"; + var defaultRouteHostSuffix = '.' + (namespace === "default" ? "" : namespace + ".") + domain; + formConfig.properties.routeHostname = { + type: 'string', + default: defaultRouteHostSuffix, + label: "Route host name suffix", + 'control-group-attributes': { + 'ng-show': 'entity.createRoute' + } + }; + } + $scope.entity = {}; + $scope.formConfig = formConfig; + $scope.objects = template.objects; + log.debug("Form config: ", formConfig); + }; + + function substitute(str, data) { + return str.replace(/\${\w*}/g, (match) => { + var key = match.replace(/\${/, '').replace(/}/, '').trim(); + return data[key] || match; + }); + }; + + $scope.substituteAndDeployTemplate = () => { + var objects = $scope.objects; + var objectsText = angular.toJson(objects, true); + // pull these out of the entity object so they're not used in substitutions + var createRoute = $scope.entity.createRoute; + var routeHostnameSuffix = $scope.entity.routeHostname || ""; + var routeName = $scope.entity.routeName; + var routeServiceName = $scope.entity.routeServiceName; + delete $scope.entity.createRoute; + delete $scope.entity.routeHostname; + delete $scope.entity.routeName; + delete $scope.entity.routeServiceName; + objectsText = substitute(objectsText, $scope.entity); + objects = angular.fromJson(objectsText); + if (createRoute) { + var routes = []; + angular.forEach(objects, (object) => { + var kind = object.kind; + var name = getName(object); + if (name && "Service" === kind) { + var routeHostname = name + routeHostnameSuffix; + var route = { + kind: "Route", + apiVersion: defaultOSApiVersion, + metadata: { + name: name, + }, + spec: { + host: routeHostname, + to: { + kind: "Service", + name: name + } + } + }; + routes.push(route); + } + }); + objects = objects.concat(routes); + } + if ($scope.targetNamespace !== model.currentNamespace()) { + $scope.$on('WatcherNamespaceChanged', () => { + log.debug("Namespace changed"); + setTimeout(() => { + applyObjects(objects); + Core.$apply($scope); + }, 500); + }); + Core.notification('info', "Switching to namespace " + $scope.targetNamespace + " and deploying template"); + model.kubernetes.selectedNamespace = $scope.targetNamespace; + } else { + applyObjects(objects); + } + }; + + function applyObjects(objects) { + var projectClient = Kubernetes.createKubernetesClient("projects"); + + _.forEach(objects, (object:any) => { + log.debug("Object: ", object); + + var kind = getKind(object); + var name = getName(object); + var ns = getNamespace(object); + + if (kind && name) { + if (ns && ns !== currentKubernetesNamespace()) { + var project = { + apiVersion: Kubernetes.defaultApiVersion, + kind: "Project", + metadata: { + name: ns, + labels: { + } + } + }; + projectClient.put(project, + (data) => { + log.info("Created namespace: " + ns) + }, + (err) => { + log.warn("Failed to create namespace: " + ns + ": " + angular.toJson(err)); + }); + } + + var pluralKind = kind.toLowerCase() + "s"; + var kubeClient = Kubernetes.createKubernetesClient(pluralKind, ns); + kubeClient.put(object, + (data) => { + log.info("updated " + kind + " name: " + name + (ns ? " ns: " + ns: "")); + }, + (err) => { + log.warn("Failed to update " + kind + " name: " + name + (ns ? " ns: " + ns: "") + " error: " + angular.toJson(err)); + }); + } + }); + goBack(); + } + + $scope.deleteTemplate = (template) => { + UI.multiItemConfirmActionDialog({ + collection: [template], + index: 'metadata.name', + onClose: (result:boolean) => { + if (result) { + KubernetesModel['templatesResource'].delete({ + id: template.metadata.name + }, undefined, () => { + KubernetesModel['templatesResource'].query((data) => { + KubernetesModel.templates = data.items; + }); + }, (error) => { + log.debug("Error deleting template: ", error); + }); + } + }, + title: 'Delete Template?', + action: 'The following template will be deleted:', + okText: 'Delete', + okClass: 'btn-danger', + custom: "This operation is permanent once completed!", + customClass: "alert alert-warning" + }).open(); + }; + }]); +} + diff --git a/plugins/kubernetes/ts/term.ts b/plugins/kubernetes/ts/term.ts new file mode 100644 index 0000000..d22d98b --- /dev/null +++ b/plugins/kubernetes/ts/term.ts @@ -0,0 +1,288 @@ +/// +/// + +module Kubernetes { + + var log = Logger.get("kubernetes-term-windows"); + + _module.config((kubernetesContainerSocketProvider) => { + kubernetesContainerSocketProvider.WebSocketFactory = "CustomWebSockets"; + }); + + _module.factory('CustomWebSockets', (userDetails:any) => { + return function CustomWebSocket(url, protocols) { + var paths = url.split('?'); + if (!_.startsWith(paths[0], masterApiUrl())) { + paths[0] = UrlHelpers.join(masterApiUrl(), paths[0]); + } + url = KubernetesAPI.wsUrl(paths[0]); + url.search(paths[1] + '&access_token=' + userDetails.token); + log.debug("Using ws url: ", url.toString()); + return new WebSocket(url.toString(), protocols); + }; + }); + + _module.service('TerminalService', ($rootScope, $document, $compile, $templateCache) => { + var body = $document.find('body'); + function positionTerminals(terminals) { + var total = _.keys(terminals).length; + var dist = (body.width() - 225) / total; + var position = 5; + angular.forEach(terminals, (value, key) => { + if (!value.scope.docked) { + return; + } + value.el.css('left', position + 'px'); + position = position + dist; + }); + } + var defaultTemplate = $templateCache.get(UrlHelpers.join(templatePath, 'termShell.html')); + var self = { + positionTerminals: () => { + positionTerminals(self.terminals); + }, + terminals: {}, + newTerminal: (podLink, containerName, template = defaultTemplate) => { + var terminalId = UrlHelpers.join(podLink, containerName); + if (terminalId in self.terminals) { + log.debug("Already a terminal with id: ", terminalId); + self.raiseTerminal(terminalId); + return terminalId; + } + var scope = $rootScope.$new(); + scope.podLink = podLink; + scope.containerName = containerName; + scope.id = terminalId; + scope.docked = true; + var el = $($compile(template)(scope)); + var term = { + scope: scope, + el: el + }; + body.append(el); + self.terminals[terminalId] = term; + positionTerminals(self.terminals); + return terminalId; + }, + closeTerminal: (id) => { + var term = self.terminals[id]; + if (term) { + term.el.remove(); + delete self.terminals[id]; + positionTerminals(self.terminals); + } + }, + raiseTerminal: (id) => { + angular.forEach(self.terminals, (value, key) => { + if (key === id) { + value.el.css('z-index', '4000'); + value.el.find('.terminal').focus(); + } else { + value.el.css('z-index', '3000'); + } + }); + } + }; + return self; + }); + + export function addWindowActions(scope, element, TerminalService) { + var moved = false; + var lastX = 0; + var lastY = 0; + var header = element.find('.terminal-title'); + var body = element.find('.terminal-body'); + element.on('$destroy', () => { + $('#main').css({ display: 'inherit' }); + }); + + var HEIGHT = 348; + var WIDTH = 600; + var TITLE_HEIGHT = 35; + var NAV_OFFSET = 46; + + element.css({ + height: HEIGHT, + width: WIDTH + }); + header.css({ + height: TITLE_HEIGHT + }); + body.css({ + position: 'absolute', + top: 35, + left: 0, + right: 0, + bottom: 0 + }); + scope.close = () => { + TerminalService.closeTerminal(scope.id); + }; + scope.raise = () => { + TerminalService.raiseTerminal(scope.id); + }; + scope.$watch('docked', (docked) => { + if (docked) { + element.width(WIDTH); + if (!element.hasClass('minimized')) { + element.height(HEIGHT); + } + } + }); + scope.startResize = (e) => { + e.preventDefault(); + log.debug("Start resize"); + scope.resizing = true; + element.on('mouseup', scope.stopResize); + $(document).on('mousemove', scope.doResize); + $(document).on('mouseleave', scope.stopResize); + }; + scope.doResize = (e) => { + if (scope.resizing) { + log.debug("Resizing, e: ", e); + if (!moved) { + lastX = e.clientX; + lastY = e.clientY; + moved = true; + return; + } + var height = element.height(); + var width = element.width(); + var deltaX = e.clientX - lastX; + var deltaY = e.clientY - lastY; + var newHeight = height + deltaY; + var newWidth = width + deltaX; + if (newHeight > 35 && newWidth > 80) { + element.height(height + deltaY); + element.width(width + deltaX); + } + lastX = e.clientX; + lastY = e.clientY; + } + }; + scope.stopResize = (e) => { + scope.resizing = false; + moved = false; + element.off('mouseup', scope.stopResize); + $(document).off('mousemove', scope.doResize); + $(document).off('mouseleave', scope.stopResize); + } + scope.mouseDown = (e) => { + e.preventDefault(); + if (element.hasClass('minimized') || element.hasClass('maximized')) { + return; + } + scope.dragging = true; + element.on('mouseup', scope.mouseUp); + $(document).on('mousemove', scope.mouseMove); + $(document).on('mouseleave', scope.mouseUp); + }; + scope.mouseUp = (e) => { + e.preventDefault(); + scope.dragging = false; + moved = false; + var height = element.height(); + var offset = element.offset(); + var winHeight = $(window).height(); + if (offset.top > (winHeight - height - 20)) { + element.css({ top: "inherit", left: "inherit" }); + scope.docked = true; + TerminalService.positionTerminals(); + } else { + scope.docked = false; + } + element.off('mouseup', scope.mouseUp); + $(document).off('mousemove', scope.mouseMove); + $(document).off('mouseleave', scope.mouseUp); + }; + scope.mouseMove = (e) => { + if (scope.dragging) { + if (!moved) { + lastX = e.clientX; + lastY = e.clientY; + moved = true; + return; + } + var deltaX = e.clientX - lastX; + var deltaY = e.clientY - lastY; + var elOffset = element.offset(); + element.offset({ top: elOffset.top + deltaY, left: elOffset.left + deltaX }); + lastX = e.clientX; + lastY = e.clientY; + } + } + + function restoreWindow(scope, element) { + if (scope.offset) { + element.offset(scope.offset); + scope.docked = false; + } + if (scope.height) { + element.height(scope.height); + } + if (scope.width) { + element.width(scope.width); + } + } + + function saveWindow(scope, element) { + scope.offset = element.offset(); + scope.height = element.height(); + scope.width = element.width(); + } + + scope.maximized = () => { + return element.hasClass('maximized'); + } + + scope.maximize = ($e) => { + $e.preventDefault(); + if (element.hasClass('minimized')) { + scope.minimize(); + } + if (element.hasClass('maximized')) { + restoreWindow(scope, element); + $('#main').css({ display: 'inherit' }); + } else { + saveWindow(scope, element); + $('#main').css({ display: 'none' }); + element.css({ + height: 'inherit', + bottom: 0, + width: '100%', + top: NAV_OFFSET, + left: 0 + }); + } + element.toggleClass('maximized'); + } + scope.minimize = ($e) => { + $e.preventDefault(); + if (element.hasClass('maximized')) { + scope.maximize(); + } + if (element.hasClass('minimized')) { + restoreWindow(scope, element); + } else { + saveWindow(scope, element); + scope.docked = true; + element.css({ height: TITLE_HEIGHT, top: "inherit", left: "inherit" }); + TerminalService.positionTerminals(); + } + element.toggleClass('minimized'); + }; + } + + _module.directive('terminalWindow', ($compile, TerminalService) => { + return { + restrict: 'A', + scope: false, + link: (scope:any, element, attr) => { + addWindowActions(scope, element, TerminalService); + var body = element.find('.terminal-body'); + body.append($compile('')(scope)); + } + }; + }); +} + diff --git a/plugins/kubernetes/ts/utilHelpers.ts b/plugins/kubernetes/ts/utilHelpers.ts new file mode 100644 index 0000000..2e022cc --- /dev/null +++ b/plugins/kubernetes/ts/utilHelpers.ts @@ -0,0 +1,181 @@ +/// +module Kubernetes { + export var hostPorts =[]; + + /** + * Sorts the the ip field + * + * @param ip the ip such as '10.1.2.13' + * @returns {any} + */ + export function sortByPodIp(ip) : any { + // i guess there is maybe nicer ways of sort this without parsing and slicing + var regex = /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; + var groups = regex.exec(ip); + if (angular.isDefined(groups)) { + var g1 = ("00" + groups[1]).slice(-3); + var g2 = ("00" + groups[2]).slice(-3); + var g3 = ("00" + groups[3]).slice(-3); + var g4 = ("00" + groups[4]).slice(-3); + var answer = g1 + g2 + g3 + g4; + return answer; + } else { + return 0; + } + } + + export function ramdomPort(): number{ + var hostPort=Math.floor(30000+Math.random()*(65535-30000)); + while(hostPorts.indexOf(hostPort) === 0){ + hostPort = Math.floor(30000+Math.random()*(65535-30000)); + } + hostPorts.push(hostPort); + return hostPort + } + + export function getRandomString(len : number) : string{ + len = len || 32; + var $chars = 'abcdefhijkmnprstwxyz'; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1 + var maxPos = $chars.length; + var pwd = ''; + for (var i = 0; i < len; i++) { + pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); + } + return pwd; + } + + export class resourceRCTemplate{ + + public image="s1:latest"; + public names = ["admin","cfgtoollogs","checkpoints","diag","flash-recovery-area","oradata"]; + + public createRC(Obj){ + var labels = { + "style": "oracle", + "status": "created" + }; + for(var item in Obj.labels) + labels[item] = Obj.labels[item]; + + return { + "apiVersion" : Kubernetes.defaultApiVersion, + "kind" : "ReplicationController", + "metadata" : { + "name" : Obj.name, + "labels" : labels + }, + "spec" : { + replicas : Obj.replicas || 1, + "template" : this.createTemplate(Obj) + } + } + } + + public createVolumeMounts(){ + var volumeMounts = []; + for(var item in this.names){ + if(this.names[item] === 'flash-recovery-area') + volumeMounts.push({ + "name" : this.names[item], + "mountPath" : "/opt/oracle/app/flash_recovery_area" + }); + else + volumeMounts.push({ + "name" : this.names[item], + "mountPath" : "/opt/oracle/app/" + this.names[item] + }); + } + return volumeMounts; + } + + public createVolumes(rootPath :string){ + var volumes = []; + for(var item in this.names){ + if(this.names[item] === 'flash-recovery-area') + volumes.push({ + "name" : this.names[item], + "hostPath" :{ + "path" : rootPath + "flash_recovery_area" + } + }); + else + volumes.push({ + "name" : this.names[item], + "hostPath" :{ + "path" : rootPath + this.names[item] + } + }); + } + return volumes; + } + + public createContainers(Obj){ + var containers = []; + containers.push( + { + "name" : "oracle", + "image": this.image, + "imagePullPolicy": "IfNotPresent", + "command":["/assets/entrypoint.sh"], + "ports": [ + { + "containerPort": 1521, + "hostPort": Obj.port || ramdomPort() + }], + "volumeMounts" : this.createVolumeMounts() + }); + return containers + } + + public createTemplate(Obj){ + return { + "metadata": + { + //"name": Obj.name, + "labels": Obj.labels + }, + "spec" : { + "terminationGracePeriodSeconds" : 0, + "containers" : this.createContainers(Obj), + "volumes" : this.createVolumes(Obj.path) + } + } + } + } + + export function findLabelValue(value:string, key: string):string { + var trueValue = ''; + switch(value){ + case '01': + trueValue = '财政'; + break; + case '02': + trueValue = '社保'; + break; + case 'A': + trueValue = '批次A'; + break; + case 'B': + trueValue = '批次B'; + break; + default: + if(key === "version"){ + var reg= new RegExp('^[0-9]$').exec(value); + if(reg) + trueValue = '版本' + reg[0]; + else trueValue = value; + } + else + trueValue = value; + } + return trueValue + } + + export function labelToChinese(labels){ + var answer = {}; + angular.forEach(labels,(value, key) => { + answer[key] = findLabelValue(value, key); + }); + return answer + } +} \ No newline at end of file diff --git a/plugins/kubernetes/ts/watcher.ts b/plugins/kubernetes/ts/watcher.ts new file mode 100644 index 0000000..bdd5618 --- /dev/null +++ b/plugins/kubernetes/ts/watcher.ts @@ -0,0 +1,276 @@ +/// + +module Kubernetes { + var log = Logger.get('kubernetes-watcher'); + + var k8sTypes = KubernetesAPI.NamespacedTypes.k8sTypes; + var osTypes = KubernetesAPI.NamespacedTypes.osTypes; + + var self = {}; + + var updateFunction = () => { + + log.debug("Objects changed, firing listeners"); + var objects = {}; + _.forEach(self.getTypes(), (type:string) => { + objects[type] = self.getObjects(type); + }); + _.forEach(self.listeners, (listener:(ObjectMap) => void) => { + listener(objects); + }); + }; + var debouncedUpdate = _.debounce(updateFunction, 75, { trailing: true }); + + var namespaceWatch = { + selected: undefined, + watch: undefined, + objects: [], + objectMap: {}, + watches: {} + }; + + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'KubernetesWatcherInit', + depends: ['KubernetesApiDiscovery'], + task: (next) => { + var booted = false; + if (isOpenShift) { + log.info("Backend is an Openshift instance"); + } else { + log.info("Backend is a vanilla Kubernetes instance"); + } + namespaceWatch.watch = KubernetesAPI.watch({ + kind: KubernetesAPI.WatchTypes.NAMESPACES, + success: (objects) => { + namespaceWatch.objects = objects; + if (!booted) { + booted = true; + self.setNamespace(localStorage[Constants.NAMESPACE_STORAGE_KEY] || defaultNamespace); + next(); + } + log.debug("Got namespaces: ", namespaceWatch.objects); + }, error: (error:any) => { + log.warn("Error fetching namespaces: ", error); + // TODO is this necessary? + //HawtioOAuth.doLogout(); + if (!booted) { + booted = true; + next(); + } + } + }); + } + }); + + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'KubernetesApiDiscovery', + depends: ['hawtio-oauth'], + task: (next) => { + isOpenShift = false; + + var userProfile = HawtioOAuth.getUserProfile(); + log.debug("User profile: ", userProfile); + if (userProfile && userProfile.provider === "hawtio-google-oauth") { + log.debug("Possibly running on GCE"); + // api master is on GCE + $.ajax({ + url: UrlHelpers.join(masterApiUrl(), 'api', 'v1', 'namespaces'), + complete: (jqXHR, textStatus) => { + if (textStatus === "success") { + log.debug("jqXHR: ", jqXHR); + userProfile.oldToken = userProfile.token; + userProfile.token = undefined; + $.ajaxSetup({ + beforeSend: (request) => { + + } + }); + } + next(); + }, + beforeSend: (request) => { + + } + }); + } else { + log.debug("Not running on GCE"); + // double-check if we're on vanilla k8s or openshift + var rootUri = new URI(masterApiUrl()).path("/oapi").query("").toString(); + log.debug("Checking for an openshift backend"); + HawtioOAuth.authenticatedHttpRequest({ + url: rootUri, + success: (data) => { + if (data) { + isOpenShift = true; + } + next(); + }, + error: (jqXHR, textStatus, errorThrown) => { + var error = KubernetesAPI.getErrorObject(jqXHR); + if (!error) { + log.debug("Failed to find root paths: ", textStatus, ": ", errorThrown); + } else { + log.debug("Failed to find root paths: ", error); + } + isOpenShift = false; + next(); + } + }); + } + } + }); + + var customUrlHandlers = {}; + + self.setNamespace = (namespace: string) => { + if (namespace === namespaceWatch.selected) { + return; + } + if (namespaceWatch.selected) { + log.debug("Stopping current watches"); + _.forOwn(namespaceWatch.watches, (watch, key) => { + if (!KubernetesAPI.namespaced(key)) { + return; + } + log.debug("Disconnecting watch: ", key); + watch.disconnect(); + }); + _.forEach(_.keys(namespaceWatch.watches), (key) => { + if (!KubernetesAPI.namespaced(key)) { + return; + } + log.debug("Deleting kind: ", key); + delete namespaceWatch.watches[key]; + }); + } + namespaceWatch.selected = namespace; + if (namespace) { + _.forEach(self.getTypes(), (kind:string) => { + if (kind === KubernetesAPI.WatchTypes.NAMESPACES) { + return; + } + if (!namespaceWatch.watches[kind]) { + log.debug("Creating watch for kind: ", kind); + var config = { + kind: kind, + namespace: KubernetesAPI.namespaced(kind) ? namespace : undefined, + success: (objects) => { + watch.objects = objects; + debouncedUpdate(); + } + }; + if (kind in customUrlHandlers) { + config.urlFunction = customUrlHandlers[kind]; + } + var watch = KubernetesAPI.watch(config); + watch.config = config; + namespaceWatch.watches[kind] = watch; + } + }); + } + }; + + self.hasWebSocket = true; + + self.getNamespace = () => namespaceWatch.selected; + + self.registerCustomUrlFunction = (kind:string, url:(options:KubernetesAPI.K8SOptions) => string) => { + customUrlHandlers[kind] = url; + if (kind in namespaceWatch.watches) { + var watch = namespaceWatch.watches[kind]; + var config = watch.config; + config.urlFunction = url; + watch.disconnect(); + delete namespaceWatch.watches[kind]; + config.success = (objects) => { + watch.objects = objects; + debouncedUpdate(); + } + watch = KubernetesAPI.watch(config); + watch.config = config; + namespaceWatch.watches[kind] = watch; + } + } + + self.getTypes = () => { + var filter = (kind:string) => { + // filter out stuff we don't care about yet + switch(kind) { + case KubernetesAPI.WatchTypes.OAUTH_CLIENTS: + case KubernetesAPI.WatchTypes.IMAGE_STREAMS: + case KubernetesAPI.WatchTypes.POLICIES: + case KubernetesAPI.WatchTypes.ROLES: + case KubernetesAPI.WatchTypes.ROLE_BINDINGS: + case KubernetesAPI.WatchTypes.POLICY_BINDINGS: + case KubernetesAPI.WatchTypes.PERSISTENT_VOLUME_CLAIMS: + case KubernetesAPI.WatchTypes.PERSISTENT_VOLUMES: + case KubernetesAPI.WatchTypes.ENDPOINTS: + case KubernetesAPI.WatchTypes.RESOURCE_QUOTAS: + case KubernetesAPI.WatchTypes.SERVICE_ACCOUNTS: + return false; + + default: + return true; + } + } + var answer = k8sTypes.concat([WatchTypes.NAMESPACES]); + if (isOpenShift) { + answer = answer.concat(osTypes); + } else { + answer = answer.concat(KubernetesAPI.WatchTypes.TEMPLATES); + answer = answer.concat(KubernetesAPI.WatchTypes.BUILD_CONFIGS); + } + return _.filter(answer, filter); + } + + self.getObjects = (kind: string) => { + if (kind === WatchTypes.NAMESPACES) { + return namespaceWatch.objects; + } + if (kind in namespaceWatch.watches) { + return namespaceWatch.watches[kind].objects; + } else { + return undefined; + } + } + + self.listeners = void>> []; + + // listener gets notified after a bunch of changes have occurred + self.registerListener = (fn:(objects:ObjectMap) => void) => { + self.listeners.push(fn); + } + + var projectsHandle = undefined; + + // kick off the project watcher a bit sooner also + hawtioPluginLoader.registerPreBootstrapTask({ + name: 'ProjectsWatcher', + depends: ['KubernetesApiDiscovery'], + task: (next) => { + if (isOpenShift) { + + projectsHandle = KubernetesAPI.watch({ + kind: KubernetesAPI.WatchTypes.PROJECTS, + namespace: undefined, + success: (objects) => { + if (self.listeners && self.listeners.length) { + log.debug("got projects: ", objects); + _.forEach(self.listeners, (listener:(objects:ObjectMap) => void) => { + listener({ + projects: objects + }); + }); + } + } + }); + } + next(); + } + }); + + +_module.service('WatcherService', ['userDetails', '$rootScope', '$timeout', (userDetails, $rootScope, $timeout) => { + return self; +}]); +} diff --git a/plugins/main.less b/plugins/main.less new file mode 100644 index 0000000..8b2a2da --- /dev/null +++ b/plugins/main.less @@ -0,0 +1,252 @@ +.nowrap { + white-space: nowrap; +} + +.ngCellText .app-icon-small { + width: 24px; + vertical-align: middle; +} + +.filter-header { + padding-bottom: 10px; +} + +.app-name { + padding-left: 10px; +} + +.profile-selector-name .app-name { + padding-left: 4px; +} + + +img.icon-small-app { + width: 24px; + height: 24px; + vertical-align: text-bottom; +} + +.profile-selector-name { + line-height: 24px; +} + +img.icon-selected-app { + width: 64px; + height: 64px; + vertical-align: middle; +} + +.selected-app-name { + line-height: 36px; + padding-left: 5px; +} + +.controller-pod-counts { + padding-right: 16px; + padding-top: 8px; +} + +.pipeline-build-block { + background-color: rgb(238, 238, 238); + display: inline-block; + width: 100%; +} + +.pipeline-build { + background: white; + -moz-border-radius: 10px; + border-radius: 10px; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + margin-top: 10px; + margin-bottom: 10px; + margin-left: 20px; + margin-right: 20px; +} + +.pipeline-deploy { + background: white; + border:5px solid; + -moz-border-radius: 10px; + border-radius: 10px; + padding-top: 10px; + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + margin-top: 10px; + margin-bottom: 10px; + margin-left: 20px; + margin-right: 20px; + color: black; +} + +.widget-body > .pipeline-panel, +.widget-body > .pipeline-panel > *, +.widget-body > .pipeline-panel > * > *, +.widget-body > .pipeline-panel > * > * > *, +.widget-body > .pipeline-panel > * > * > * > * { + height: 100%; + vertical-align: middle; +} + +.pipeline-block { + width: 100%; +} + +.build-fail { + border-color: lightcoral; +} + +.build-success { + border-color: lightgreen; +} + +.build-pending { + border-color: khaki; +} + +.build-aborted { + border-color: silver; +} + +.build-not-started { + border-color: lightblue; +} + + +.pipeline-build a { + color: black; +} +.pipeline-deploy a { + color: black; +} + +.pipeline-pod-counts { + padding-right: 16px; + padding-top: 8px; +} + +.pipeline-row { + background: lightgrey; + border-radius: 4px; + height: 80px; + display: inline; + border-radius: 4px; + text-align: center; + vertical-align: middle; + border: 20px; + margin: 5px; +} + +.pipeline-arrow { + font-size: 1.2em; +} + +.icon-heading { + font-size: 24px; +} + + +.row-header { + padding-bottom: 20px; +} + +.project-overview-title { + padding-left: 80px; + padding-top: 18px; +} + +.project-overview-title a { + color: black; +} + +/* + +.raw-json-view { + width: 90%; height: 700px; +} +*/ + +.raw-json-view .CodeMirror { + height: 90%; +} + +.k8sServiceApp-menu { + width: 260px; +} + +.k8sServiceApp > a { + padding-top: 5px !important; + padding-bottom: 5px !important; + line-height: 32px !important; +} + +.k8sServiceApp > a > img { + vertical-align: bottom; +} + +.k8sServiceApp > a > span { + font-size: 14px; + line-height: 32px; +} + +.breadcrumb-tabs { + padding-top: 5px; +} + +tbody .ngCellText i { + margin-right: 5px; +} + +.log-success { + color: green; +} + +.log-warn { + color: orange +} + +.log-error { + color: red; +} + + +.form-warning.bg-danger { + padding: 8px; +} + +legend { + border-bottom: none; +} + +/* TODO lets work around some ui-bootstrap / patternfly css gremlins */ +.modal .modal-dialog { + margin-top: 0px; + margin-bottom: 0px; +} + +/* lets set this to the same size as modal-dialog */ +.modal { + width: 600px; +} + +.btn.btn-padding { + margin-left: 5px; + margin-right: 5px; +} + +.k8s-badge-batch { + background-color: darkblue; +} +.k8s-badge-type { + background-color: darkgreen; +} +.k8s-badge-region { + background-color: darkred; +} + +.k8s-badge-system { + background-color: darkmagenta; +} diff --git a/plugins/navigation/ts/navigationPlugin.ts b/plugins/navigation/ts/navigationPlugin.ts new file mode 100644 index 0000000..46a6973 --- /dev/null +++ b/plugins/navigation/ts/navigationPlugin.ts @@ -0,0 +1,168 @@ +/// +module Navigation { + + export var pluginName = 'hawtio-navigation'; + export var log = Logger.get(pluginName); + export var _module = angular.module(pluginName, []); + + _module.run(() => { + }); + + _module.service('HawtioBreadcrumbs', () => { + var _config = []; + var self = { + apply: (config) => { + _config.length = 0; + _.forEach(config, (crumb) => { + _config.push(crumb); + }); + }, + get: () => { + return _config; + } + }; + return self; + }); + + _module.service('HawtioSubTabs', () => { + var _config = []; + var self = { + apply: (config) => { + _config.length = 0; + _.forEach(config, (crumb) => { + _config.push(crumb); + }); + }, + get: () => { + return _config; + } + } + return self; + }); + + _module.directive('viewportHeight', ['$window', '$document', ($window, $document) => { + return { + restrict: 'A', + link: (scope, element, attr) => { + // log.debug("Window: ", $window); + // log.debug("element: ", element); + var win = $($window); + var resizeFunc = () => { + var viewportHeight = win.innerHeight(); + // log.debug("Viewport height: ", viewportHeight); + var elTop = element.offset().top; + // log.debug("Element top: ", elTop); + var height = viewportHeight - elTop; + element.css('height', height); + }; + win.on('resize', resizeFunc); + element.on('$destroy', () => { + win.off('resize', resizeFunc); + }); + setTimeout(resizeFunc, 50); + } + } + }]); + + _module.directive('hawtioMainOutlet', ['HawtioSubTabs', (HawtioSubTabs) => { + return { + restrict: 'A', + link: (scope, element, attrs) => { + scope.HawtioSubTabs = HawtioSubTabs; + scope.$watchCollection('HawtioSubTabs.get()', (subTabConfig) => { + // log.debug("subTabConfig: ", subTabConfig); + if (subTabConfig && subTabConfig.length > 0) { + element.removeClass('hidden-nav'); + //element.css({ 'margin-left': '' }); + } else { + element.addClass('hidden-nav'); + //element.css({ 'margin-left': 'auto' }); + } + }); + } + }; + + }]); + + _module.directive('hawtioTabsOutlet', ['HawtioSubTabs', (HawtioSubTabs) => { + var initialized = false; + return { + restrict: 'AE', + replace: true, + template: ` + + `, + link: (scope, element, attrs) => { + if (!initialized) { + try { + ($)().setupVerticalNavigation(false); + } catch (err) { + // ignore if we haven't loaded patternfly + } + initialized = true; + } + scope.HawtioSubTabs = HawtioSubTabs; + var collapsed = false; + scope.getClass = () => { + //log.debug("My class: ", element.attr('class')); + if (!scope.subTabConfig || !scope.subTabConfig.length) { + return 'hidden'; + } + if (collapsed) { + return 'collapsed'; + } + return ''; + } + scope.$on('hawtioCollapseNav', () => { + collapsed = !collapsed; + }); + scope.$watch('HawtioSubTabs.get()', (subTabConfig) => { + scope.subTabConfig = subTabConfig; + }); + } + }; + }]); + + _module.directive('hawtioBreadcrumbsOutlet', ['HawtioBreadcrumbs', (HawtioBreadcrumbs) => { + return { + restrict: 'E', + scope: {}, + template: ` +
+ +
+ `, + link: (scope, element, attrs) => { + scope.breadcrumbs = HawtioBreadcrumbs; + scope.$watchCollection('breadcrumbs.get()', (breadcrumbConfig) => { + scope.breadcrumbConfig = breadcrumbConfig; + }); + } + }; + }]); + + //hawtioPluginLoader.addModule('patternfly'); + hawtioPluginLoader.addModule(pluginName); + +} + diff --git a/resumable-node.js b/resumable-node.js new file mode 100644 index 0000000..6389c7a --- /dev/null +++ b/resumable-node.js @@ -0,0 +1,213 @@ +var fs = require('fs'), path = require('path'), util = require('util'), Stream = require('stream').Stream; + + + +module.exports = resumable = function(temporaryFolder){ + var $ = this; + $.temporaryFolder = temporaryFolder; + $.maxFileSize = null; + $.fileParameterName = 'file'; + + try { + fs.mkdirSync($.temporaryFolder); + }catch(e){} + + + var cleanIdentifier = function(identifier){ + return identifier.replace(/^0-9A-Za-z_-/img, ''); + } + + var getChunkFilename = function(chunkNumber, identifier){ + // Clean up the identifier + identifier = cleanIdentifier(identifier); + // What would the file name be? + return path.join($.temporaryFolder, './resumable-'+identifier+'.'+chunkNumber); + } + + var validateRequest = function(chunkNumber, chunkSize, totalSize, identifier, filename, fileSize){ + // Clean up the identifier + identifier = cleanIdentifier(identifier); + + // Check if the request is sane + if (chunkNumber==0 || chunkSize==0 || totalSize==0 || identifier.length==0 || filename.length==0) { + return 'non_resumable_request'; + } + var numberOfChunks = Math.max(Math.floor(totalSize/(chunkSize*1.0)), 1); + if (chunkNumber>numberOfChunks) { + return 'invalid_resumable_request1'; + } + + // Is the file too big? + if($.maxFileSize && totalSize>$.maxFileSize) { + return 'invalid_resumable_request2'; + } + + if(typeof(fileSize)!='undefined') { + if(chunkNumber1 && chunkNumber==numberOfChunks && fileSize!=((totalSize%chunkSize)+chunkSize)) { + // The chunks in the POST is the last one, and the fil is not the correct size + return 'invalid_resumable_request4'; + } + if(numberOfChunks==1 && fileSize!=totalSize) { + // The file is only a single chunk, and the data size does not fit + return 'invalid_resumable_request5'; + } + } + + return 'valid'; + } + + //'found', filename, original_filename, identifier + //'not_found', null, null, null + $.get = function(req, callback){ + var chunkNumber = req.param('resumableChunkNumber', 0); + var chunkSize = req.param('resumableChunkSize', 0); + var totalSize = req.param('resumableTotalSize', 0); + var identifier = req.param('resumableIdentifier', ""); + var filename = req.param('resumableFilename', ""); + + if(validateRequest(chunkNumber, chunkSize, totalSize, identifier, filename)=='valid') { + var chunkFilename = getChunkFilename(chunkNumber, identifier); + fs.exists(chunkFilename, function(exists){ + if(exists){ + callback('found', chunkFilename, filename, identifier); + } else { + callback('not_found', chunkFilename, filename, identifier); + } + }); + } else { + callback('not_found2', chunkFilename, filename, identifier); + } + } + + //'partly_done', filename, original_filename, identifier + //'done', filename, original_filename, identifier + //'invalid_resumable_request', null, null, null + //'non_resumable_request', null, null, null + $.post = function(req, callback){ + + var fields = req.body; + var files = req.files; + + var chunkNumber = fields['resumableChunkNumber']; + var chunkSize = fields['resumableChunkSize']; + var totalSize = fields['resumableTotalSize']; + var identifier = cleanIdentifier(fields['resumableIdentifier']); + var filename = fields['resumableFilename']; + + var original_filename = fields['resumableIdentifier']; + + if(!files[$.fileParameterName] || !files[$.fileParameterName].size) { + callback('invalid_resumable_request', null, null, null); + return; + } + var validation = validateRequest(chunkNumber, chunkSize, totalSize, identifier, files[$.fileParameterName].size); + if(validation=='valid') { + var chunkFilename = getChunkFilename(chunkNumber, identifier); + + // Save the chunk (TODO: OVERWRITE) + fs.rename(files[$.fileParameterName].path, chunkFilename, function(){ + + // Do we have all the chunks? + var currentTestChunk = 1; + var numberOfChunks = Math.max(Math.floor(totalSize/(chunkSize*1.0)), 1); + var testChunkExists = function(){ + fs.exists(getChunkFilename(currentTestChunk, identifier), function(exists){ + if(exists){ + currentTestChunk++; + if(currentTestChunk>numberOfChunks) { + callback('done', filename, original_filename, identifier); + } else { + // Recursion + testChunkExists(); + } + } else { + callback('partly_done', filename, original_filename, identifier); + } + }); + } + testChunkExists(); + }); + } else { + callback(validation, filename, original_filename, identifier); + } + } + + + // Pipe chunks directly in to an existsing WritableStream + // r.write(identifier, response); + // r.write(identifier, response, {end:false}); + // + // var stream = fs.createWriteStream(filename); + // r.write(identifier, stream); + // stream.on('data', function(data){...}); + // stream.on('end', function(){...}); + $.write = function(identifier, writableStream, options) { + options = options || {}; + options.end = (typeof options['end'] == 'undefined' ? true : options['end']); + + // Iterate over each chunk + var pipeChunk = function(number) { + + var chunkFilename = getChunkFilename(number, identifier); + + fs.exists(chunkFilename, function(exists) { + + if (exists) { + // If the chunk with the current number exists, + // then create a ReadStream from the file + // and pipe it to the specified writableStream. + var sourceStream = fs.createReadStream(chunkFilename); + sourceStream.pipe(writableStream, { + end: false + }); + sourceStream.on('end', function() { + // When the chunk is fully streamed, + // jump to the next one + pipeChunk(number + 1); + }); + } else { + // When all the chunks have been piped, end the stream + if (options.end) writableStream.end(); + if (options.onDone) options.onDone(); + } + }); + } + pipeChunk(1); + } + + + $.clean = function(identifier, options) { + options = options || {}; + + // Iterate over each chunk + var pipeChunkRm = function(number) { + + var chunkFilename = getChunkFilename(number, identifier); + + //console.log('removing pipeChunkRm ', number, 'chunkFilename', chunkFilename); + fs.exists(chunkFilename, function(exists) { + if (exists) { + + console.log('exist removing ', chunkFilename); + fs.unlink(chunkFilename, function(err) { + if (err && options.onError) options.onError(err); + }); + + pipeChunkRm(number + 1); + + } else { + + if (options.onDone) options.onDone(); + + } + }); + } + pipeChunkRm(1); + } + + return $; +}
+
+ +
+ + + {{view.service.$host}} + + {{view.service.$host}} + +
+
+ +
+
+ +
+
+
+
+ deployed: + {{view.createdDate | relativeTime}} +
+
+ not deployed +
+
+
+
+ pod template: + {{view.controllerId}} +
+
+ no pod template +
+
+
+ + pods: + + {{view.podCount}} + + + {{view.podCount}} + + +
+
+ +
+
+
+
+ + + + + + + + +
+ + + + + + + +
+ IP: + {{pod.status.podIP}} +
+
+
+ ports: {{pod.$containerPorts.join(", ")}} +
+
+ minion: + + {{pod.$host}} + +
+
+ +
+ +
+ +
+ + + + + + + +
+ + + + + + + +
+ IP: + {{pod.status.podIP}} +
+
+ +
+
+
+
+
+
+