From 8f54b51ecdff07021f60ce32f0f27ac40315937c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 26 Sep 2023 16:21:55 +0200 Subject: [PATCH] update templates --- app/Http/Controllers/ProjectController.php | 9 ++- .../Shared/EnvironmentVariable/All.php | 1 - app/Models/Service.php | 42 ++++++++---- examples/docker-compose-ghost.yaml | 28 -------- examples/service-templates.json | 66 ++++++++++++------- 5 files changed, 79 insertions(+), 67 deletions(-) diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php index 97b61eb87..f02b240ba 100644 --- a/app/Http/Controllers/ProjectController.php +++ b/app/Http/Controllers/ProjectController.php @@ -70,8 +70,8 @@ public function new() $oneClickServiceName = $type->after('one-click-service-')->value(); $oneClickService = data_get($services, "$oneClickServiceName.compose"); $oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null); - $oneClickRequiredFqdn = data_get($services, "$oneClickServiceName.generateFqdn", []); - $oneClickRequiredFqdn = collect($oneClickRequiredFqdn); + $oneClickConfiguration = data_get($services, "$oneClickServiceName.configuration.proxy", []); + $oneClickConfiguration = collect($oneClickConfiguration); if ($oneClickDotEnvs) { $oneClickDotEnvs = Str::of(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/'); } @@ -94,6 +94,9 @@ public function new() if ($value->contains('SERVICE_PASSWORD')) { $value = Str::of(Str::password(symbols: false)); } + if ($value->contains('SERVICE_PASSWORD64')) { + $value = Str::of(Str::password(length: 64, symbols: false)); + } if ($value->contains('SERVICE_BASE64')) { $length = Str::of($value)->after('SERVICE_BASE64_')->beforeLast('_')->value(); if (is_numeric($length)) { @@ -112,7 +115,7 @@ public function new() ]); }); } - $service->parse(isNew: true, requiredFqdns: $oneClickRequiredFqdn); + $service->parse(isNew: true, configuration: $oneClickConfiguration); return redirect()->route('project.service', [ 'service_uuid' => $service->uuid, diff --git a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php index 59d556644..a95c94977 100644 --- a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -57,7 +57,6 @@ public function saveVariables($isPreview) $this->resource->environment_variables()->delete(); } foreach ($variables as $key => $variable) { - ray($key, $variable); $found = $existingVariables->where('key', $key)->first(); if ($found) { $found->value = $variable; diff --git a/app/Models/Service.php b/app/Models/Service.php index e6f1acf8a..b820b4f2d 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -115,7 +115,7 @@ private function sslip(Server $server) } return "{$server->ip}.sslip.io"; } - private function generateFqdn($serviceVariables, $serviceName, Collection $requiredFqdns) + private function generateFqdn($serviceVariables, $serviceName, Collection $configuration) { // Add sslip.io to the service $defaultUsableFqdn = null; @@ -123,8 +123,8 @@ private function generateFqdn($serviceVariables, $serviceName, Collection $requi if (Str::of($serviceVariables)->contains('SERVICE_FQDN') || Str::of($serviceVariables)->contains('SERVICE_URL')) { $defaultUsableFqdn = "http://$serviceName-{$this->uuid}.{$sslip}"; } - if ($requiredFqdns->count() > 0) { - foreach ($requiredFqdns as $requiredFqdn) { + if ($configuration->count() > 0) { + foreach ($configuration as $requiredFqdn) { $requiredFqdn = (array)$requiredFqdn; $name = data_get($requiredFqdn, 'name'); $path = data_get($requiredFqdn, 'path'); @@ -139,10 +139,10 @@ private function generateFqdn($serviceVariables, $serviceName, Collection $requi } return $defaultUsableFqdn ?? null; } - public function parse(bool $isNew = false, ?Collection $requiredFqdns = null): Collection + public function parse(bool $isNew = false, ?Collection $configuration = null): Collection { - if (!$requiredFqdns) { - $requiredFqdns = collect([]); + if (!$configuration) { + $configuration = collect([]); } if ($this->docker_compose_raw) { try { @@ -161,7 +161,7 @@ public function parse(bool $isNew = false, ?Collection $requiredFqdns = null): C $envs = collect([]); $ports = collect([]); - $services = collect($services)->map(function ($service, $serviceName) use ($composeVolumes, $composeNetworks, $definedNetwork, $envs, $volumes, $ports, $isNew, $requiredFqdns) { + $services = collect($services)->map(function ($service, $serviceName) use ($composeVolumes, $composeNetworks, $definedNetwork, $envs, $volumes, $ports, $isNew, $configuration) { $container_name = "$serviceName-{$this->uuid}"; $isDatabase = false; $serviceVariables = collect(data_get($service, 'environment', [])); @@ -207,14 +207,13 @@ public function parse(bool $isNew = false, ?Collection $requiredFqdns = null): C } else { $savedService = ServiceApplication::create([ 'name' => $serviceName, - 'fqdn' => $this->generateFqdn($serviceVariables, $serviceName, $requiredFqdns), + 'fqdn' => $this->generateFqdn($serviceVariables, $serviceName, $configuration), 'image' => $image, 'service_id' => $this->id ]); } - if ($requiredFqdns->count() > 0) { - $found = false; - foreach ($requiredFqdns as $requiredFqdn) { + if ($configuration->count() > 0) { + foreach ($configuration as $requiredFqdn) { $requiredFqdn = (array)$requiredFqdn; $name = data_get($requiredFqdn, 'name'); if ($serviceName === $name) { @@ -232,7 +231,7 @@ public function parse(bool $isNew = false, ?Collection $requiredFqdns = null): C if (data_get($savedService, 'fqdn')) { $defaultUsableFqdn = data_get($savedService, 'fqdn', null); } else { - $defaultUsableFqdn = $this->generateFqdn($serviceVariables, $serviceName, $requiredFqdns); + $defaultUsableFqdn = $this->generateFqdn($serviceVariables, $serviceName, $configuration); } $savedService->fqdn = $defaultUsableFqdn; $savedService->save(); @@ -389,9 +388,22 @@ public function parse(bool $isNew = false, ?Collection $requiredFqdns = null): C data_set($service, 'networks', $networks); + // Get variables from the service foreach ($serviceVariables as $variable) { $value = Str::after($variable, '='); + // if (!Str::of($val)->contains($value)) { + // EnvironmentVariable::updateOrCreate([ + // 'key' => $variable, + // 'service_id' => $this->id, + // ], [ + // 'value' => $val, + // 'is_build_time' => false, + // 'service_id' => $this->id, + // 'is_preview' => false, + // ]); + // continue; + // } if (!Str::startsWith($value, '$SERVICE_') && !Str::startsWith($value, '${SERVICE_') && Str::startsWith($value, '$')) { $value = Str::of(replaceVariables(Str::of($value))); $nakedName = $nakedValue = null; @@ -468,7 +480,11 @@ public function parse(bool $isNew = false, ?Collection $requiredFqdns = null): C } else if ($variableName->startsWith('SERVICE_PASSWORD')) { $variableDefined = EnvironmentVariable::whereServiceId($this->id)->where('key', $variableName->value())->first(); if (!$variableDefined) { - $generatedValue = Str::password(symbols: false); + if ($variableName->startsWith('SERVICE_PASSWORD64')) { + $generatedValue = Str::password(length: 64, symbols: false); + } else { + $generatedValue = Str::password(symbols: false); + } } else { $generatedValue = $variableDefined->value; } diff --git a/examples/docker-compose-ghost.yaml b/examples/docker-compose-ghost.yaml index a5db1e2bd..eb55f86f6 100644 --- a/examples/docker-compose-ghost.yaml +++ b/examples/docker-compose-ghost.yaml @@ -1,14 +1,8 @@ services: ghost: - documentation: https://ghost.org/docs/config image: ghost:5 volumes: - ghost-content-data:/var/lib/ghost/content - - type: volume - source: /data/g - target: /data - volume: - nocopy: true environment: - url=$SERVICE_FQDN_GHOST - database__client=mysql @@ -16,24 +10,9 @@ services: - database__connection__user=$SERVICE_USER_MYSQL - database__connection__password=$SERVICE_PASSWORD_MYSQL - database__connection__database=${MYSQL_DATABASE-ghost} - networks: - default: - aliases: - - alias1 - - alias3 - ipv4_address: 172.16.238.10 - ipv6_address: 2001:3984:3989::10 - ports: - - "2368" - - 1234:2368 - - target: 2368 - published: 1234 - protocol: tcp - mode: host depends_on: - mysql mysql: - documentation: https://hub.docker.com/_/mysql image: mysql:8.0 volumes: - ghost-mysql-data:/var/lib/mysql @@ -42,10 +21,3 @@ services: - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQL_ROOT} -networks: - default: - ipam: - driver: default - config: - - subnet: "172.16.238.0/24" - - subnet: "2001:3984:3989::/64" diff --git a/examples/service-templates.json b/examples/service-templates.json index f5f4ab5c2..6cfc505fb 100644 --- a/examples/service-templates.json +++ b/examples/service-templates.json @@ -5,37 +5,59 @@ }, "uptime-kuma": { "documentation": "https://github.com/louislam/uptime-kuma", - "generateFqdn": [ - { - "name": "uptime-kuma", - "path": "/" - } - ], + "configuration": { + "proxy": [ + { + "name": "uptime-kuma", + "path": "/" + } + ] + }, "compose": "c2VydmljZXM6CiAgdXB0aW1lLWt1bWE6CiAgICBpbWFnZTogbG91aXNsYW0vdXB0aW1lLWt1bWE6MQogICAgdm9sdW1lczoKICAgICAgLSB1cHRpbWUta3VtYTovYXBwL2RhdGEK" }, "appsmith": { "documentation": "https://docs.appsmith.com/", - "generateFqdn": [ - { - "name": "appsmith" - } - ], + "configuration": { + "proxy": [ + { + "name": "appsmith" + } + ] + }, "envs": "QVBQU01JVEhfTUFJTF9FTkFCTEVEPWZhbHNlCkFQUFNNSVRIX0RJU0FCTEVfVEVMRU1FVFJZPXRydWUKQVBQU01JVEhfRElTQUJMRV9JTlRFUkNPTT10cnVlCkFQUFNNSVRIX1NFTlRSWV9EU049CkFQUFNNSVRIX1NNQVJUX0xPT0tfSUQ9", "compose": "c2VydmljZXM6CiAgYXBwc21pdGg6CiAgICBpbWFnZTogaW5kZXguZG9ja2VyLmlvL2FwcHNtaXRoL2FwcHNtaXRoLWNlCiAgICB2b2x1bWVzOgogICAgICAtIHN0YWNrcy1kYXRhOi9hcHBzbWl0aC1zdGFja3M=" }, + "fider": { + "documentation": "https://fider.io/docs", + "compose":"c2VydmljZXM6CiAgZmlkZXI6CiAgICBpbWFnZTogZ2V0ZmlkZXIvZmlkZXI6c3RhYmxlCiAgICBlbnZpcm9ubWVudDoKICAgICAgQkFTRV9VUkw6ICRTRVJWSUNFX0ZRRE5fRklERVIKICAgICAgREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovLyRTRVJWSUNFX1VTRVJfTVlTUUw6JFNFUlZJQ0VfUEFTU1dPUkRfTVlTUUxAZGF0YWJhc2U6NTQzMi9maWRlcj9zc2xtb2RlPWRpc2FibGUKICAgICAgSldUX1NFQ1JFVDogJFNFUlZJQ0VfUEFTU1dPUkQ2NF9GSURFUgogICAgICBFTUFJTF9OT1JFUExZOiAkRU1BSUxfTk9SRVBMWQogICAgICBFTUFJTF9NQUlMR1VOX0FQSTogJEVNQUlMX01BSUxHVU5fQVBJCiAgICAgIEVNQUlMX01BSUxHVU5fRE9NQUlOOiAkRU1BSUxfTUFJTEdVTl9ET01BSU4KICAgICAgRU1BSUxfTUFJTEdVTl9SRUdJT046ICRFTUFJTF9NQUlMR1VOX1JFR0lPTgogICAgICBFTUFJTF9TTVRQX0hPU1Q6ICRFTUFJTF9TTVRQX0hPU1QKICAgICAgRU1BSUxfU01UUF9QT1JUOiAkRU1BSUxfU01UUF9QT1JUCiAgICAgIEVNQUlMX1NNVFBfVVNFUk5BTUU6ICRFTUFJTF9TTVRQX1VTRVJOQU1FCiAgICAgIEVNQUlMX1NNVFBfUEFTU1dPUkQ6ICRFTUFJTF9TTVRQX1BBU1NXT1JECiAgICAgIEVNQUlMX1NNVFBfRU5BQkxFX1NUQVJUVExTOiAkRU1BSUxfU01UUF9FTkFCTEVfU1RBUlRUTFMKICAgICAgRU1BSUxfQVdTU0VTX1JFR0lPTjogJEVNQUlMX0FXU1NFU19SRUdJT04KICAgICAgRU1BSUxfQVdTU0VTX0FDQ0VTU19LRVlfSUQ6ICRFTUFJTF9BV1NTRVNfQUNDRVNTX0tFWV9JRAogICAgICBFTUFJTF9BV1NTRVNfU0VDUkVUX0FDQ0VTU19LRVk6ICRFTUFJTF9BV1NTRVNfU0VDUkVUX0FDQ0VTU19LRVkKICBkYXRhYmFzZToKICAgIGltYWdlOiBwb3N0Z3JlczoxMgogICAgdm9sdW1lczoKICAgICAgLSBwZ19kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YQogICAgZW52aXJvbm1lbnQ6CiAgICAgIFBPU1RHUkVTX1VTRVI6ICRTRVJWSUNFX1VTRVJfTVlTUUwKICAgICAgUE9TVEdSRVNfUEFTU1dPUkQ6ICRTRVJWSUNFX1BBU1NXT1JEX01ZU1FMCiAgICAgIFBPU1RHUkVTX0RCOiAke1BPU1RHUkVTX0RCOi1maWRlcn0=" + }, + "ghost": { + "documentation": "https://ghost.org/docs", + "configuration": { + "proxy": [ + { + "name": "ghost", + "path": "/" + } + ] + }, + "compose": "c2VydmljZXM6CiAgZ2hvc3Q6CiAgICBpbWFnZTogZ2hvc3Q6NQogICAgdm9sdW1lczoKICAgICAgLSBnaG9zdC1jb250ZW50LWRhdGE6L3Zhci9saWIvZ2hvc3QvY29udGVudAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gdXJsPSRTRVJWSUNFX0ZRRE5fR0hPU1QKICAgICAgLSBkYXRhYmFzZV9fY2xpZW50PW15c3FsCiAgICAgIC0gZGF0YWJhc2VfX2Nvbm5lY3Rpb25fX2hvc3Q9bXlzcWwKICAgICAgLSBkYXRhYmFzZV9fY29ubmVjdGlvbl9fdXNlcj0kU0VSVklDRV9VU0VSX01ZU1FMCiAgICAgIC0gZGF0YWJhc2VfX2Nvbm5lY3Rpb25fX3Bhc3N3b3JkPSRTRVJWSUNFX1BBU1NXT1JEX01ZU1FMCiAgICAgIC0gZGF0YWJhc2VfX2Nvbm5lY3Rpb25fX2RhdGFiYXNlPSR7TVlTUUxfREFUQUJBU0UtZ2hvc3R9CiAgICBkZXBlbmRzX29uOgogICAgICAtIG15c3FsCiAgbXlzcWw6CiAgICBpbWFnZTogbXlzcWw6OC4wCiAgICB2b2x1bWVzOgogICAgICAtIGdob3N0LW15c3FsLWRhdGE6L3Zhci9saWIvbXlzcWwKICAgIGVudmlyb25tZW50OgogICAgICAtIE1ZU1FMX1VTRVI9JHtTRVJWSUNFX1VTRVJfTVlTUUx9CiAgICAgIC0gTVlTUUxfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01ZU1FMfQogICAgICAtIE1ZU1FMX0RBVEFCQVNFPSR7TVlTUUxfREFUQUJBU0V9CiAgICAgIC0gTVlTUUxfUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTVlTUUxfUk9PVH0= " + }, "appwrite": { "documentation": "https://appwrite.io/docs", - "generateFqdn": [ - { - "name": "appwrite", - "path": "/" - }, - { - "name": "appwrite-realtime", - "customFqdn": "appwrite", - "path": "/v1/realtime" - } - ], + "configuration": { + "proxy": [ + { + "name": "appwrite", + "path": "/" + }, + { + "name": "appwrite-realtime", + "customFqdn": "appwrite", + "path": "/v1/realtime" + } + ] + }, "envs": "X0FQUF9FTlY9cHJvZHVjdGlvbgpfQVBQX0xPQ0FMRT1lbgpfQVBQX09QVElPTlNfQUJVU0U9ZW5hYmxlZApfQVBQX09QVElPTlNfRk9SQ0VfSFRUUFM9ZGlzYWJsZWQKX0FQUF9PUEVOU1NMX0tFWV9WMT0KX0FQUF9ET01BSU5fRlVOQ1RJT05TPQpfQVBQX0NPTlNPTEVfV0hJVEVMSVNUX1JPT1Q9ZW5hYmxlZApfQVBQX0NPTlNPTEVfV0hJVEVMSVNUX0VNQUlMUz0KX0FQUF9DT05TT0xFX1dISVRFTElTVF9JUFM9Cl9BUFBfU1lTVEVNX0VNQUlMX05BTUU9QXBwd3JpdGUKX0FQUF9TWVNURU1fRU1BSUxfQUREUkVTUz10ZWFtQGFwcHdyaXRlLmlvCl9BUFBfU1lTVEVNX1JFU1BPTlNFX0ZPUk1BVD0KX0FQUF9TWVNURU1fU0VDVVJJVFlfRU1BSUxfQUREUkVTUz1jZXJ0c0BhcHB3cml0ZS5pbwpfQVBQX1VTQUdFX1NUQVRTPWVuYWJsZWQKX0FQUF9MT0dHSU5HX1BST1ZJREVSPQpfQVBQX0xPR0dJTkdfQ09ORklHPQpfQVBQX1VTQUdFX0FHR1JFR0FUSU9OX0lOVEVSVkFMPTMwCl9BUFBfVVNBR0VfVElNRVNFUklFU19JTlRFUlZBTD0zMApfQVBQX1VTQUdFX0RBVEFCQVNFX0lOVEVSVkFMPTkwMApfQVBQX1dPUktFUl9QRVJfQ09SRT02Cl9BUFBfUkVESVNfSE9TVD1yZWRpcwpfQVBQX1JFRElTX1BPUlQ9NjM3OQpfQVBQX1JFRElTX1VTRVI9Cl9BUFBfUkVESVNfUEFTUz0KX0FQUF9EQl9IT1NUPW1hcmlhZGIKX0FQUF9EQl9QT1JUPTMzMDYKX0FQUF9EQl9TQ0hFTUE9YXBwd3JpdGUKX0FQUF9EQl9VU0VSPSRTRVJWSUNFX1VTRVJfTVlTUUwKX0FQUF9EQl9QQVNTPSRTRVJWSUNFX1BBU1NXT1JEX01ZU1FMCl9BUFBfREJfUk9PVF9QQVNTPSRTRVJWSUNFX1BBU1NXT1JEX1JPT1RNWVNRTApfQVBQX0lORkxVWERCX0hPU1Q9aW5mbHV4ZGIKX0FQUF9JTkZMVVhEQl9QT1JUPTgwODYKX0FQUF9TVEFUU0RfSE9TVD10ZWxlZ3JhZgpfQVBQX1NUQVRTRF9QT1JUPTgxMjUKX0FQUF9TTVRQX0hPU1Q9Cl9BUFBfU01UUF9QT1JUPQpfQVBQX1NNVFBfU0VDVVJFPQpfQVBQX1NNVFBfVVNFUk5BTUU9Cl9BUFBfU01UUF9QQVNTV09SRD0KX0FQUF9TTVNfUFJPVklERVI9Cl9BUFBfU01TX0ZST009Cl9BUFBfU1RPUkFHRV9MSU1JVD0zMDAwMDAwMApfQVBQX1NUT1JBR0VfUFJFVklFV19MSU1JVD0yMDAwMDAwMApfQVBQX1NUT1JBR0VfQU5USVZJUlVTPWRpc2FibGVkCl9BUFBfU1RPUkFHRV9BTlRJVklSVVNfSE9TVD1jbGFtYXYKX0FQUF9TVE9SQUdFX0FOVElWSVJVU19QT1JUPTMzMTAKX0FQUF9TVE9SQUdFX0RFVklDRT1sb2NhbApfQVBQX1NUT1JBR0VfUzNfQUNDRVNTX0tFWT0KX0FQUF9TVE9SQUdFX1MzX1NFQ1JFVD0KX0FQUF9TVE9SQUdFX1MzX1JFR0lPTj11cy1lYXN0LTEKX0FQUF9TVE9SQUdFX1MzX0JVQ0tFVD0KX0FQUF9TVE9SQUdFX0RPX1NQQUNFU19BQ0NFU1NfS0VZPQpfQVBQX1NUT1JBR0VfRE9fU1BBQ0VTX1NFQ1JFVD0KX0FQUF9TVE9SQUdFX0RPX1NQQUNFU19SRUdJT049dXMtZWFzdC0xCl9BUFBfU1RPUkFHRV9ET19TUEFDRVNfQlVDS0VUPQpfQVBQX1NUT1JBR0VfQkFDS0JMQVpFX0FDQ0VTU19LRVk9Cl9BUFBfU1RPUkFHRV9CQUNLQkxBWkVfU0VDUkVUPQpfQVBQX1NUT1JBR0VfQkFDS0JMQVpFX1JFR0lPTj11cy13ZXN0LTAwNApfQVBQX1NUT1JBR0VfQkFDS0JMQVpFX0JVQ0tFVD0KX0FQUF9TVE9SQUdFX0xJTk9ERV9BQ0NFU1NfS0VZPQpfQVBQX1NUT1JBR0VfTElOT0RFX1NFQ1JFVD0KX0FQUF9TVE9SQUdFX0xJTk9ERV9SRUdJT049ZXUtY2VudHJhbC0xCl9BUFBfU1RPUkFHRV9MSU5PREVfQlVDS0VUPQpfQVBQX1NUT1JBR0VfV0FTQUJJX0FDQ0VTU19LRVk9Cl9BUFBfU1RPUkFHRV9XQVNBQklfU0VDUkVUPQpfQVBQX1NUT1JBR0VfV0FTQUJJX1JFR0lPTj1ldS1jZW50cmFsLTEKX0FQUF9TVE9SQUdFX1dBU0FCSV9CVUNLRVQ9Cl9BUFBfRlVOQ1RJT05TX1NJWkVfTElNSVQ9MzAwMDAwMDAKX0FQUF9GVU5DVElPTlNfVElNRU9VVD05MDAKX0FQUF9GVU5DVElPTlNfQlVJTERfVElNRU9VVD05MDAKX0FQUF9GVU5DVElPTlNfQ09OVEFJTkVSUz0xMApfQVBQX0ZVTkNUSU9OU19DUFVTPTAKX0FQUF9GVU5DVElPTlNfTUVNT1JZPTAKX0FQUF9GVU5DVElPTlNfTUVNT1JZX1NXQVA9MApfQVBQX0ZVTkNUSU9OU19SVU5USU1FUz1ub2RlLTE2LjAscGhwLTguMCxweXRob24tMy45LHJ1YnktMy4wCl9BUFBfRVhFQ1VUT1JfU0VDUkVUPXlvdXItc2VjcmV0LWtleQpfQVBQX0VYRUNVVE9SX0hPU1Q9aHR0cDovL2FwcHdyaXRlLWV4ZWN1dG9yL3YxCl9BUFBfRVhFQ1VUT1JfUlVOVElNRV9ORVRXT1JLPWFwcHdyaXRlX3J1bnRpbWVzCl9BUFBfRlVOQ1RJT05TX0VOVlM9bm9kZS0xNi4wLHBocC03LjQscHl0aG9uLTMuOSxydWJ5LTMuMApfQVBQX0ZVTkNUSU9OU19JTkFDVElWRV9USFJFU0hPTEQ9NjAKRE9DS0VSSFVCX1BVTExfVVNFUk5BTUU9CkRPQ0tFUkhVQl9QVUxMX1BBU1NXT1JEPQpET0NLRVJIVUJfUFVMTF9FTUFJTD0KT1BFTl9SVU5USU1FU19ORVRXT1JLPWFwcHdyaXRlX3J1bnRpbWVzCl9BUFBfRlVOQ1RJT05TX1JVTlRJTUVTX05FVFdPUks9cnVudGltZXMKX0FQUF9ET0NLRVJfSFVCX1VTRVJOQU1FPQpfQVBQX0RPQ0tFUl9IVUJfUEFTU1dPUkQ9Cl9BUFBfRlVOQ1RJT05TX01BSU5URU5BTkNFX0lOVEVSVkFMPTM2MDAKX0FQUF9WQ1NfR0lUSFVCX0FQUF9OQU1FPQpfQVBQX1ZDU19HSVRIVUJfUFJJVkFURV9LRVk9Cl9BUFBfVkNTX0dJVEhVQl9BUFBfSUQ9Cl9BUFBfVkNTX0dJVEhVQl9DTElFTlRfSUQ9Cl9BUFBfVkNTX0dJVEhVQl9DTElFTlRfU0VDUkVUPQpfQVBQX1ZDU19HSVRIVUJfV0VCSE9PS19TRUNSRVQ9Cl9BUFBfTUFJTlRFTkFOQ0VfSU5URVJWQUw9ODY0MDAKX0FQUF9NQUlOVEVOQU5DRV9SRVRFTlRJT05fQ0FDSEU9MjU5MjAwMApfQVBQX01BSU5URU5BTkNFX1JFVEVOVElPTl9FWEVDVVRJT049MTIwOTYwMApfQVBQX01BSU5URU5BTkNFX1JFVEVOVElPTl9BVURJVD0xMjA5NjAwCl9BUFBfTUFJTlRFTkFOQ0VfUkVURU5USU9OX0FCVVNFPTg2NDAwCl9BUFBfTUFJTlRFTkFOQ0VfUkVURU5USU9OX1VTQUdFX0hPVVJMWT04NjQwMDAwCl9BUFBfTUFJTlRFTkFOQ0VfUkVURU5USU9OX1NDSEVEVUxFUz04NjQwMApfQVBQX0dSQVBIUUxfTUFYX0JBVENIX1NJWkU9MTAKX0FQUF9HUkFQSFFMX01BWF9DT01QTEVYSVRZPTI1MApfQVBQX0dSQVBIUUxfTUFYX0RFUFRIPTMKX0FQUF9NSUdSQVRJT05TX0ZJUkVCQVNFX0NMSUVOVF9JRD0KX0FQUF9NSUdSQVRJT05TX0ZJUkVCQVNFX0NMSUVOVF9TRUNSRVQ9Cl9BUFBfQVNTSVNUQU5UX09QRU5BSV9BUElfS0VZPQ==", "compose": "eC1sb2dnaW5nOiAmeC1sb2dnaW5nCiAgbG9nZ2luZzoKICAgIGRyaXZlcjogJ2pzb24tZmlsZScKICAgIG9wdGlvbnM6CiAgICAgIG1heC1maWxlOiAnNScKICAgICAgbWF4LXNpemU6ICcxMG0nCnZlcnNpb246ICczJwoKc2VydmljZXM6CiAgYXBwd3JpdGU6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIDw8OiAqeC1sb2dnaW5nCiAgICBsYWJlbHM6CiAgICAgIC0gdHJhZWZpay5lbmFibGU9dHJ1ZQogICAgICAtIHRyYWVmaWsuY29uc3RyYWludC1sYWJlbC1zdGFjaz1hcHB3cml0ZQogICAgICAtIHRyYWVmaWsuaHR0cC5zZXJ2aWNlcy5hcHB3cml0ZV9hcGkubG9hZGJhbGFuY2VyLnNlcnZlci5wb3J0PTgwCiAgICAgICNodHRwCiAgICAgIC0gdHJhZWZpay5odHRwLnJvdXRlcnMuYXBwd3JpdGVfYXBpX2h0dHAuZW50cnlwb2ludHM9d2ViCiAgICAgIC0gdHJhZWZpay5odHRwLnJvdXRlcnMuYXBwd3JpdGVfYXBpX2h0dHAucnVsZT1QYXRoUHJlZml4KGAvYCkKICAgICAgLSB0cmFlZmlrLmh0dHAucm91dGVycy5hcHB3cml0ZV9hcGlfaHR0cC5zZXJ2aWNlPWFwcHdyaXRlX2FwaQogICAgICAjIGh0dHBzCiAgICAgIC0gdHJhZWZpay5odHRwLnJvdXRlcnMuYXBwd3JpdGVfYXBpX2h0dHBzLmVudHJ5cG9pbnRzPXdlYnNlY3VyZQogICAgICAtIHRyYWVmaWsuaHR0cC5yb3V0ZXJzLmFwcHdyaXRlX2FwaV9odHRwcy5ydWxlPVBhdGhQcmVmaXgoYC9gKQogICAgICAtIHRyYWVmaWsuaHR0cC5yb3V0ZXJzLmFwcHdyaXRlX2FwaV9odHRwcy5zZXJ2aWNlPWFwcHdyaXRlX2FwaQogICAgICAtIHRyYWVmaWsuaHR0cC5yb3V0ZXJzLmFwcHdyaXRlX2FwaV9odHRwcy50bHM9dHJ1ZQogICAgdm9sdW1lczoKICAgICAgLSBhcHB3cml0ZS11cGxvYWRzOi9zdG9yYWdlL3VwbG9hZHM6cncKICAgICAgLSBhcHB3cml0ZS1jYWNoZTovc3RvcmFnZS9jYWNoZTpydwogICAgICAtIGFwcHdyaXRlLWNvbmZpZzovc3RvcmFnZS9jb25maWc6cncKICAgICAgLSBhcHB3cml0ZS1jZXJ0aWZpY2F0ZXM6L3N0b3JhZ2UvY2VydGlmaWNhdGVzOnJ3CiAgICAgIC0gYXBwd3JpdGUtZnVuY3Rpb25zOi9zdG9yYWdlL2Z1bmN0aW9uczpydwogICAgZGVwZW5kc19vbjoKICAgICAgLSBtYXJpYWRiCiAgICAgIC0gcmVkaXMKIyAgICAgIC0gY2xhbWF2CiAgICAgIC0gaW5mbHV4ZGIKCiAgYXBwd3JpdGUtcmVhbHRpbWU6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHJlYWx0aW1lCiAgICA8PDogKngtbG9nZ2luZwogICAgbGFiZWxzOgogICAgICAtIHRyYWVmaWsuZW5hYmxlPXRydWUKICAgICAgLSAidHJhZWZpay5jb25zdHJhaW50LWxhYmVsLXN0YWNrPWFwcHdyaXRlIgogICAgICAtICJ0cmFlZmlrLmh0dHAuc2VydmljZXMuYXBwd3JpdGVfcmVhbHRpbWUubG9hZGJhbGFuY2VyLnNlcnZlci5wb3J0PTgwIgogICAgICAjd3MKICAgICAgLSB0cmFlZmlrLmh0dHAucm91dGVycy5hcHB3cml0ZV9yZWFsdGltZV93cy5lbnRyeXBvaW50cz13ZWIKICAgICAgLSB0cmFlZmlrLmh0dHAucm91dGVycy5hcHB3cml0ZV9yZWFsdGltZV93cy5ydWxlPVBhdGhQcmVmaXgoYC92MS9yZWFsdGltZWApCiAgICAgIC0gdHJhZWZpay5odHRwLnJvdXRlcnMuYXBwd3JpdGVfcmVhbHRpbWVfd3Muc2VydmljZT1hcHB3cml0ZV9yZWFsdGltZQogICAgICAjIHdzcwogICAgICAtIHRyYWVmaWsuaHR0cC5yb3V0ZXJzLmFwcHdyaXRlX3JlYWx0aW1lX3dzcy5lbnRyeXBvaW50cz13ZWJzZWN1cmUKICAgICAgLSB0cmFlZmlrLmh0dHAucm91dGVycy5hcHB3cml0ZV9yZWFsdGltZV93c3MucnVsZT1QYXRoUHJlZml4KGAvdjEvcmVhbHRpbWVgKQogICAgICAtIHRyYWVmaWsuaHR0cC5yb3V0ZXJzLmFwcHdyaXRlX3JlYWx0aW1lX3dzcy5zZXJ2aWNlPWFwcHdyaXRlX3JlYWx0aW1lCiAgICAgIC0gdHJhZWZpay5odHRwLnJvdXRlcnMuYXBwd3JpdGVfcmVhbHRpbWVfd3NzLnRscz10cnVlCiAgICAgIC0gdHJhZWZpay5odHRwLnJvdXRlcnMuYXBwd3JpdGVfcmVhbHRpbWVfd3NzLnRscy5jZXJ0cmVzb2x2ZXI9ZG5zCiAgICBkZXBlbmRzX29uOgogICAgICAtIG1hcmlhZGIKICAgICAgLSByZWRpcwoKICBhcHB3cml0ZS13b3JrZXItYXVkaXRzOgogICAgaW1hZ2U6IGFwcHdyaXRlL2FwcHdyaXRlOjEuNC4zCiAgICBlbnRyeXBvaW50OiB3b3JrZXItYXVkaXRzCiAgICA8PDogKngtbG9nZ2luZwogICAgZGVwZW5kc19vbjoKICAgICAgLSByZWRpcwogICAgICAtIG1hcmlhZGIKCiAgYXBwd3JpdGUtd29ya2VyLXdlYmhvb2tzOgogICAgaW1hZ2U6IGFwcHdyaXRlL2FwcHdyaXRlOjEuNC4zCiAgICBlbnRyeXBvaW50OiB3b3JrZXItd2ViaG9va3MKICAgIDw8OiAqeC1sb2dnaW5nCiAgICBkZXBlbmRzX29uOgogICAgICAtIHJlZGlzCiAgICAgIC0gbWFyaWFkYgoKICBhcHB3cml0ZS13b3JrZXItZGVsZXRlczoKICAgIGltYWdlOiBhcHB3cml0ZS9hcHB3cml0ZToxLjQuMwogICAgZW50cnlwb2ludDogd29ya2VyLWRlbGV0ZXMKICAgIDw8OiAqeC1sb2dnaW5nCiAgICBkZXBlbmRzX29uOgogICAgICAtIHJlZGlzCiAgICAgIC0gbWFyaWFkYgogICAgdm9sdW1lczogCiAgICAgIC0gYXBwd3JpdGUtdXBsb2Fkczovc3RvcmFnZS91cGxvYWRzOnJ3CiAgICAgIC0gYXBwd3JpdGUtY2FjaGU6L3N0b3JhZ2UvY2FjaGU6cncKICAgICAgLSBhcHB3cml0ZS1mdW5jdGlvbnM6L3N0b3JhZ2UvZnVuY3Rpb25zOnJ3CiAgICAgIC0gYXBwd3JpdGUtYnVpbGRzOi9zdG9yYWdlL2J1aWxkczpydwogICAgICAtIGFwcHdyaXRlLWNlcnRpZmljYXRlczovc3RvcmFnZS9jZXJ0aWZpY2F0ZXM6cncKCiAgYXBwd3JpdGUtd29ya2VyLWRhdGFiYXNlczoKICAgIGltYWdlOiBhcHB3cml0ZS9hcHB3cml0ZToxLjQuMwogICAgZW50cnlwb2ludDogd29ya2VyLWRhdGFiYXNlcwogICAgPDw6ICp4LWxvZ2dpbmcKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcmVkaXMKICAgICAgLSBtYXJpYWRiCgogIGFwcHdyaXRlLXdvcmtlci1idWlsZHM6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHdvcmtlci1idWlsZHMKICAgIDw8OiAqeC1sb2dnaW5nCiAgICBkZXBlbmRzX29uOgogICAgICAtIHJlZGlzCiAgICAgIC0gbWFyaWFkYgogICAgdm9sdW1lczoKICAgICAgLSBhcHB3cml0ZS1mdW5jdGlvbnM6L3N0b3JhZ2UvZnVuY3Rpb25zOnJ3CiAgICAgIC0gYXBwd3JpdGUtYnVpbGRzOi9zdG9yYWdlL2J1aWxkczpydwoKICBhcHB3cml0ZS13b3JrZXItY2VydGlmaWNhdGVzOgogICAgaW1hZ2U6IGFwcHdyaXRlL2FwcHdyaXRlOjEuNC4zCiAgICBlbnRyeXBvaW50OiB3b3JrZXItY2VydGlmaWNhdGVzCiAgICA8PDogKngtbG9nZ2luZwogICAgZGVwZW5kc19vbjoKICAgICAgLSByZWRpcwogICAgICAtIG1hcmlhZGIKICAgIHZvbHVtZXM6IAogICAgICAtIGFwcHdyaXRlLWNvbmZpZzovc3RvcmFnZS9jb25maWc6cncKICAgICAgLSBhcHB3cml0ZS1jZXJ0aWZpY2F0ZXM6L3N0b3JhZ2UvY2VydGlmaWNhdGVzOnJ3CgogIGFwcHdyaXRlLXdvcmtlci1mdW5jdGlvbnM6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHdvcmtlci1mdW5jdGlvbnMKICAgIDw8OiAqeC1sb2dnaW5nCiAgICBkZXBlbmRzX29uOgogICAgICAtIHJlZGlzCiAgICAgIC0gbWFyaWFkYgogICAgICAtIG9wZW5ydW50aW1lcy1leGVjdXRvcgoKICBhcHB3cml0ZS13b3JrZXItbWFpbHM6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHdvcmtlci1tYWlscwogICAgPDw6ICp4LWxvZ2dpbmcKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcmVkaXMKCiAgYXBwd3JpdGUtd29ya2VyLW1lc3NhZ2luZzoKICAgIGltYWdlOiBhcHB3cml0ZS9hcHB3cml0ZToxLjQuMwogICAgZW50cnlwb2ludDogd29ya2VyLW1lc3NhZ2luZwogICAgPDw6ICp4LWxvZ2dpbmcKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcmVkaXMKCiAgYXBwd3JpdGUtd29ya2VyLW1pZ3JhdGlvbnM6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHdvcmtlci1taWdyYXRpb25zCiAgICA8PDogKngtbG9nZ2luZwogICAgZGVwZW5kc19vbjoKICAgICAgLSBtYXJpYWRiCgogIGFwcHdyaXRlLW1haW50ZW5hbmNlOgogICAgaW1hZ2U6IGFwcHdyaXRlL2FwcHdyaXRlOjEuNC4zCiAgICBlbnRyeXBvaW50OiBtYWludGVuYW5jZQogICAgPDw6ICp4LWxvZ2dpbmcKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcmVkaXMKCiAgYXBwd3JpdGUtdXNhZ2U6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHVzYWdlCiAgICA8PDogKngtbG9nZ2luZwogICAgZGVwZW5kc19vbjoKICAgICAgLSBpbmZsdXhkYgogICAgICAtIG1hcmlhZGIKCiAgYXBwd3JpdGUtc2NoZWR1bGU6CiAgICBpbWFnZTogYXBwd3JpdGUvYXBwd3JpdGU6MS40LjMKICAgIGVudHJ5cG9pbnQ6IHNjaGVkdWxlCiAgICA8PDogKngtbG9nZ2luZwogICAgZGVwZW5kc19vbjoKICAgICAgLSBtYXJpYWRiCiAgICAgIC0gcmVkaXMKCiAgYXBwd3JpdGUtYXNzaXN0YW50OgogICAgaW1hZ2U6IGFwcHdyaXRlL2Fzc2lzdGFudDowLjIuMQogICAgPDw6ICp4LWxvZ2dpbmcKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCgogIG9wZW5ydW50aW1lcy1leGVjdXRvcjoKICAgIGhvc3RuYW1lOiBhcHB3cml0ZS1leGVjdXRvcgogICAgPDw6ICp4LWxvZ2dpbmcKICAgIHN0b3Bfc2lnbmFsOiBTSUdJTlQKICAgIGltYWdlOiBvcGVucnVudGltZXMvZXhlY3V0b3I6MC40LjEKICAgIHZvbHVtZXM6CiAgICAgIC0gL3Zhci9ydW4vZG9ja2VyLnNvY2s6L3Zhci9ydW4vZG9ja2VyLnNvY2sKICAgICAgLSBhcHB3cml0ZS1idWlsZHM6L3N0b3JhZ2UvYnVpbGRzOnJ3CiAgICAgIC0gYXBwd3JpdGUtZnVuY3Rpb25zOi9zdG9yYWdlL2Z1bmN0aW9uczpydwogICAgICAjIEhvc3QgbW91bnQgbmVzc2Vzc2FyeSB0byBzaGFyZSBmaWxlcyBiZXR3ZWVuIGV4ZWN1dG9yIGFuZCBydW50aW1lcy4KICAgICAgIyBJdCdzIG5vdCBwb3NzaWJsZSB0byBzaGFyZSBtb3VudCBmaWxlIGJldHdlZW4gMiBjb250YWluZXJzIHdpdGhvdXQgaG9zdCBtb3VudCAoY29weWluZyBpcyB0b28gc2xvdykKICAgICAgLSAvdG1wOi90bXA6cncKICAgIGVudmlyb25tZW50OgogICAgICAtIE9QUl9FWEVDVVRPUl9JTkFDVElWRV9UUkVTSE9MRD0kX0FQUF9GVU5DVElPTlNfSU5BQ1RJVkVfVEhSRVNIT0xECiAgICAgIC0gT1BSX0VYRUNVVE9SX01BSU5URU5BTkNFX0lOVEVSVkFMPSRfQVBQX0ZVTkNUSU9OU19NQUlOVEVOQU5DRV9JTlRFUlZBTAogICAgICAtIE9QUl9FWEVDVVRPUl9ORVRXT1JLPSRfQVBQX0ZVTkNUSU9OU19SVU5USU1FU19ORVRXT1JLCiAgICAgIC0gT1BSX0VYRUNVVE9SX0RPQ0tFUl9IVUJfVVNFUk5BTUU9JF9BUFBfRE9DS0VSX0hVQl9VU0VSTkFNRQogICAgICAtIE9QUl9FWEVDVVRPUl9ET0NLRVJfSFVCX1BBU1NXT1JEPSRfQVBQX0RPQ0tFUl9IVUJfUEFTU1dPUkQKICAgICAgLSBPUFJfRVhFQ1VUT1JfRU5WPSRfQVBQX0VOVgogICAgICAtIE9QUl9FWEVDVVRPUl9SVU5USU1FUz0kX0FQUF9GVU5DVElPTlNfUlVOVElNRVMKICAgICAgLSBPUFJfRVhFQ1VUT1JfU0VDUkVUPSRfQVBQX0VYRUNVVE9SX1NFQ1JFVAogICAgICAtIE9QUl9FWEVDVVRPUl9MT0dHSU5HX1BST1ZJREVSPSRfQVBQX0xPR0dJTkdfUFJPVklERVIKICAgICAgLSBPUFJfRVhFQ1VUT1JfTE9HR0lOR19DT05GSUc9JF9BUFBfTE9HR0lOR19DT05GSUcKICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9ERVZJQ0U9JF9BUFBfU1RPUkFHRV9ERVZJQ0UKICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9TM19BQ0NFU1NfS0VZPSRfQVBQX1NUT1JBR0VfUzNfQUNDRVNTX0tFWQogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX1MzX1NFQ1JFVD0kX0FQUF9TVE9SQUdFX1MzX1NFQ1JFVAogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX1MzX1JFR0lPTj0kX0FQUF9TVE9SQUdFX1MzX1JFR0lPTgogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX1MzX0JVQ0tFVD0kX0FQUF9TVE9SQUdFX1MzX0JVQ0tFVAogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX0RPX1NQQUNFU19BQ0NFU1NfS0VZPSRfQVBQX1NUT1JBR0VfRE9fU1BBQ0VTX0FDQ0VTU19LRVkKICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9ET19TUEFDRVNfU0VDUkVUPSRfQVBQX1NUT1JBR0VfRE9fU1BBQ0VTX1NFQ1JFVAogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX0RPX1NQQUNFU19SRUdJT049JF9BUFBfU1RPUkFHRV9ET19TUEFDRVNfUkVHSU9OCiAgICAgIC0gT1BSX0VYRUNVVE9SX1NUT1JBR0VfRE9fU1BBQ0VTX0JVQ0tFVD0kX0FQUF9TVE9SQUdFX0RPX1NQQUNFU19CVUNLRVQKICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9CQUNLQkxBWkVfQUNDRVNTX0tFWT0kX0FQUF9TVE9SQUdFX0JBQ0tCTEFaRV9BQ0NFU1NfS0VZCiAgICAgIC0gT1BSX0VYRUNVVE9SX1NUT1JBR0VfQkFDS0JMQVpFX1NFQ1JFVD0kX0FQUF9TVE9SQUdFX0JBQ0tCTEFaRV9TRUNSRVQKICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9CQUNLQkxBWkVfUkVHSU9OPSRfQVBQX1NUT1JBR0VfQkFDS0JMQVpFX1JFR0lPTgogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX0JBQ0tCTEFaRV9CVUNLRVQ9JF9BUFBfU1RPUkFHRV9CQUNLQkxBWkVfQlVDS0VUCiAgICAgIC0gT1BSX0VYRUNVVE9SX1NUT1JBR0VfTElOT0RFX0FDQ0VTU19LRVk9JF9BUFBfU1RPUkFHRV9MSU5PREVfQUNDRVNTX0tFWQogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX0xJTk9ERV9TRUNSRVQ9JF9BUFBfU1RPUkFHRV9MSU5PREVfU0VDUkVUCiAgICAgIC0gT1BSX0VYRUNVVE9SX1NUT1JBR0VfTElOT0RFX1JFR0lPTj0kX0FQUF9TVE9SQUdFX0xJTk9ERV9SRUdJT04KICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9MSU5PREVfQlVDS0VUPSRfQVBQX1NUT1JBR0VfTElOT0RFX0JVQ0tFVAogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX1dBU0FCSV9BQ0NFU1NfS0VZPSRfQVBQX1NUT1JBR0VfV0FTQUJJX0FDQ0VTU19LRVkKICAgICAgLSBPUFJfRVhFQ1VUT1JfU1RPUkFHRV9XQVNBQklfU0VDUkVUPSRfQVBQX1NUT1JBR0VfV0FTQUJJX1NFQ1JFVAogICAgICAtIE9QUl9FWEVDVVRPUl9TVE9SQUdFX1dBU0FCSV9SRUdJT049JF9BUFBfU1RPUkFHRV9XQVNBQklfUkVHSU9OCiAgICAgIC0gT1BSX0VYRUNVVE9SX1NUT1JBR0VfV0FTQUJJX0JVQ0tFVD0kX0FQUF9TVE9SQUdFX1dBU0FCSV9CVUNLRVQKCiAgbWFyaWFkYjoKICAgIGltYWdlOiBtYXJpYWRiOjEwLjcgIyBmaXggaXNzdWVzIHdoZW4gdXBncmFkaW5nIHVzaW5nOiBteXNxbF91cGdyYWRlIC11IHJvb3QgLXAKICAgIDw8OiAqeC1sb2dnaW5nCiAgICB2b2x1bWVzOgogICAgICAtIGFwcHdyaXRlLW1hcmlhZGI6L3Zhci9saWIvbXlzcWw6cncKICAgIGVudmlyb25tZW50OgogICAgICAtIE1ZU1FMX1JPT1RfUEFTU1dPUkQ9JHtfQVBQX0RCX1JPT1RfUEFTU30KICAgICAgLSBNWVNRTF9EQVRBQkFTRT0ke19BUFBfREJfU0NIRU1BfQogICAgICAtIE1ZU1FMX1VTRVI9JHtfQVBQX0RCX1VTRVJ9CiAgICAgIC0gTVlTUUxfUEFTU1dPUkQ9JHtfQVBQX0RCX1BBU1N9CiAgICBjb21tYW5kOiAnbXlzcWxkIC0taW5ub2RiLWZsdXNoLW1ldGhvZD1mc3luYycKCiAgcmVkaXM6CiAgICBpbWFnZTogcmVkaXM6Ny4wLjQtYWxwaW5lCiAgICA8PDogKngtbG9nZ2luZwogICAgY29tbWFuZDogPgogICAgICByZWRpcy1zZXJ2ZXIKICAgICAgLS1tYXhtZW1vcnkgICAgICAgICAgICA1MTJtYgogICAgICAtLW1heG1lbW9yeS1wb2xpY3kgICAgIGFsbGtleXMtbHJ1CiAgICAgIC0tbWF4bWVtb3J5LXNhbXBsZXMgICAgNQogICAgdm9sdW1lczoKICAgICAgLSBhcHB3cml0ZS1yZWRpczovZGF0YTpydwoKICBjbGFtYXY6CiAgICBpbWFnZTogYXBwd3JpdGUvY2xhbWF2OjEuMi4wCiAgICB2b2x1bWVzOgogICAgICAtIGFwcHdyaXRlLXVwbG9hZHM6L3N0b3JhZ2UvdXBsb2FkcwoKICBpbmZsdXhkYjoKICAgIGltYWdlOiBhcHB3cml0ZS9pbmZsdXhkYjoxLjUuMAogICAgPDw6ICp4LWxvZ2dpbmcKICAgIHZvbHVtZXM6CiAgICAgIC0gYXBwd3JpdGUtaW5mbHV4ZGI6L3Zhci9saWIvaW5mbHV4ZGI6cncKCiAgdGVsZWdyYWY6CiAgICBpbWFnZTogYXBwd3JpdGUvdGVsZWdyYWY6MS40LjAKICAgIDw8OiAqeC1sb2dnaW5nCg== " }