From 214cc35c5703ea2c15d78fbc1ff4761e6be82901 Mon Sep 17 00:00:00 2001 From: daniwe4 Date: Mon, 10 Jun 2024 15:02:36 +0200 Subject: [PATCH] master states:442 distribute update token, and enable doil to trigger instance updates via url --- CHANGELOG.md | 8 + README.md | 3 + app/src/Commands/Instances/ApplyCommand.php | 4 +- app/src/Commands/Instances/CreateCommand.php | 17 ++ .../Instances/SetUpdateTokenCommand.php | 155 ++++++++++++++++++ app/src/Commands/Pack/PackCreateCommand.php | 22 ++- app/src/cli.php | 10 ++ .../Commands/Instances/CreateCommandTest.php | 6 +- setup/conf/doil.conf | 2 +- setup/stack/config/master.cnf | 4 + .../states/ilias-update-hook/description.txt | 1 + .../ilias-update-hook/init.sls | 8 + .../ilias-update-hook/update_hook.php.j2 | 69 ++++++++ setup/stack/states/ilias-update-hook/top.sls | 3 + .../proxyservices/service-config.tpl | 11 ++ .../states/set-update-token/description.txt | 1 + .../set-update-token/init.sls | 7 + setup/stack/states/set-update-token/top.sls | 3 + setup/templates/minion/docker-compose.yml | 3 + setup/updates/update-20241206.sh | 69 ++++++++ 20 files changed, 399 insertions(+), 7 deletions(-) create mode 100644 app/src/Commands/Instances/SetUpdateTokenCommand.php create mode 100644 setup/stack/states/ilias-update-hook/description.txt create mode 100644 setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls create mode 100644 setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 create mode 100644 setup/stack/states/ilias-update-hook/top.sls create mode 100644 setup/stack/states/set-update-token/description.txt create mode 100644 setup/stack/states/set-update-token/set-update-token/init.sls create mode 100644 setup/stack/states/set-update-token/top.sls create mode 100644 setup/updates/update-20241206.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 7034ac1d..43cbb49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,14 @@ * better salt key handling * !! Attention: doil needs to be reinstalled !! +## 20240617 +## What's Changes +* update of an instance can now be triggered by url + +## 20240604 +## What's Changed +* CSP Rules per instance + ## 20240422 ## What's Changed * fix typo in apache 000-default diff --git a/README.md b/README.md index 95964f91..c69ae8cf 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ The following commands are available: * `doil delete ` deletes an instance you do not need anymore * `doil status` lists the current running doil instances * `doil exec ` executes a bash command inside the instance +* `doil sut` (alias for `doil instances:set-update-token`) Sets an update token as an environment variable. This is cross-checked during instance updates via the browser See `doil instances: --help` for more information @@ -180,6 +181,8 @@ Following commands come with the `--global` flag: * `doil instances:path` * `doil instances:login` * `doil instances:exec` +* `doil instances:csp` +* `doil instance:set-update-token` **`doil repo`** * `doil repo:add` diff --git a/app/src/Commands/Instances/ApplyCommand.php b/app/src/Commands/Instances/ApplyCommand.php index f37e890c..ec582138 100644 --- a/app/src/Commands/Instances/ApplyCommand.php +++ b/app/src/Commands/Instances/ApplyCommand.php @@ -34,7 +34,9 @@ class ApplyCommand extends Command "change-roundcube-password", "nodejs", "proxy-enable-https", - "keycloak" + "keycloak", + "ilias-update-hook", + "set-update-token" ]; protected static $defaultName = "instances:apply"; diff --git a/app/src/Commands/Instances/CreateCommand.php b/app/src/Commands/Instances/CreateCommand.php index c65ded68..8974c4f6 100644 --- a/app/src/Commands/Instances/CreateCommand.php +++ b/app/src/Commands/Instances/CreateCommand.php @@ -135,6 +135,8 @@ public function execute(InputInterface $input, OutputInterface $output) : int $keycloak = true; } + $update_token = $this->filesystem->getLineInFile("/etc/doil/doil.conf", "update_token"); + $this->writer->beginBlock($output, "Creating instance " . $options['name']); if (isset($options["repo_path"]) && ! $this->filesystem->exists($options["repo_path"])) { @@ -319,6 +321,11 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(1); $this->docker->setGrain($instance_salt_name, "cpass", "$cron_password"); sleep(1); + if (!is_null($update_token)) { + $token = explode("=", $update_token); + $this->docker->setGrain($instance_salt_name, "update_token", "${token[1]}"); + sleep(1); + } $this->docker->setGrain($instance_salt_name, "doil_domain", "http://" . $host . "/" . $options["name"]); sleep(1); $this->docker->setGrain($instance_salt_name, "doil_project_name", $options["name"]); @@ -383,6 +390,16 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->writer->endBlock(); } + // apply set-update-token state + $this->writer->beginBlock($output, "Apply set-update-token state"); + $this->docker->applyState($instance_salt_name, "set-update-token"); + $this->writer->endBlock(); + + // apply ilias-update-hook state + $this->writer->beginBlock($output, "Apply ilias-update-hook state"); + $this->docker->applyState($instance_salt_name, "ilias-update-hook"); + $this->writer->endBlock(); + // apply access state $this->writer->beginBlock($output, "Apply access state"); $this->docker->applyState($instance_salt_name, "access"); diff --git a/app/src/Commands/Instances/SetUpdateTokenCommand.php b/app/src/Commands/Instances/SetUpdateTokenCommand.php new file mode 100644 index 00000000..fc4927e7 --- /dev/null +++ b/app/src/Commands/Instances/SetUpdateTokenCommand.php @@ -0,0 +1,155 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\Instances; + +use CaT\Doil\Lib\Posix\Posix; +use CaT\Doil\Lib\Docker\Docker; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Exception\InvalidArgumentException; + +class SetUpdateTokenCommand extends Command +{ + protected static $defaultName = "instances:set-update-token"; + protected static $defaultDescription = + "!NEEDS SUDO PRIVILEGES! This command sets a update token for all instances" + ; + + protected Docker $docker; + protected Posix $posix; + protected Filesystem $filesystem; + protected Writer $writer; + + public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) + { + parent::__construct(); + + $this->docker = $docker; + $this->posix = $posix; + $this->filesystem = $filesystem; + $this->writer = $writer; + } + + public function configure() : void + { + $this + ->setAliases(["sut"]) + ->addOption("token", "t", InputOption::VALUE_REQUIRED, "Update token as string") + ->addOption("global", "g", InputOption::VALUE_NONE, "Determines if an instance is global or not") + ; + } + + public function execute(InputInterface $input, OutputInterface $output) : int + { + if (! $this->posix->isSudo()) { + $this->writer->error( + $output, + "Please execute this script as sudo user!" + ); + return Command::FAILURE; + } + + $token = $input->getOption("token"); + + $home_dir = $this->posix->getHomeDirectory($this->posix->getUserId()); + + $path = "/usr/local/share/doil/instances"; + $suffix = "global"; + if (! $input->getOption("global")) { + $path = "$home_dir/.doil/instances"; + $suffix = "local"; + } + + $instances = $this->filesystem->getFilesInPath($path); + if (count($instances) == 0) { + $this->writer->error( + $output, + "No instances found!", + "Use doil instances:ls --help for more information." + ); + return Command::FAILURE; + } + + $question = new ConfirmationQuestion( + "This will also update 'update_token' in your doil config. Want to continue? [yN]: ", + false + ); + + $helper = $this->getHelper("question"); + if (!$helper->ask($input, $output, $question)) { + $output->writeln("Abort by user!"); + return Command::FAILURE; + } + + $this->filesystem->replaceLineInFile("/etc/doil/doil.conf", "/update_token=.*/", "update_token=" . $token); + + foreach ($instances as $i) { + $started = $this->startInstance($output, $path, $i); + sleep(3); + $this->applyUpdateToken($output, $i . "." . $suffix, $token); + $this->docker->commit($i . "_" . $suffix); + if ($started) { + $this->stopInstance($output, $path, $i); + } + } + return Command::SUCCESS; + } + + protected function startInstance(OutputInterface $output, string $path, string $instance) : bool + { + if (! $this->hasDockerComposeFile($path . "/" . $instance, $output)) { + throw new InvalidArgumentException("Can't find a suitable docker-compose.yml file in $path/$instance"); + } + + if (! $this->docker->isInstanceUp($path . "/" . $instance)) { + $this->writer->beginBlock($output, "Start instance $instance"); + $this->docker->startContainerByDockerCompose($path . "/" . $instance); + $this->writer->endBlock(); + return true; + } + + return false; + } + + protected function stopInstance(OutputInterface $output, string $path, string $instance) : string + { + if ($this->docker->isInstanceUp($path . "/" . $instance)) { + $this->writer->beginBlock($output, "Stop instance $instance"); + $this->docker->stopContainerByDockerCompose($path . "/" . $instance); + $this->writer->endBlock(); + } + + return $instance; + } + + protected function hasDockerComposeFile(string $path, OutputInterface $output) : bool + { + if ($this->filesystem->exists($path . "/docker-compose.yml")) { + return true; + } + + $output->writeln("Error:"); + $output->writeln("\tCan't find a suitable docker-compose file in this directory '$path'."); + $output->writeln("\tIs this the right directory?"); + $output->writeln("\tSupported filenames: docker-compose.yml"); + + return false; + } + + protected function applyUpdateToken(OutputInterface $output, string $salt_key, string $token) + { + $this->writer->beginBlock($output, "Apply update token to $salt_key"); + $this->docker->setGrain($salt_key, "update_token", $token); + $this->docker->refreshGrains($salt_key); + $this->docker->applyState($salt_key, "set-update-token"); + $this->writer->endBlock(); + } +} \ No newline at end of file diff --git a/app/src/Commands/Pack/PackCreateCommand.php b/app/src/Commands/Pack/PackCreateCommand.php index e5990a90..65b2552b 100644 --- a/app/src/Commands/Pack/PackCreateCommand.php +++ b/app/src/Commands/Pack/PackCreateCommand.php @@ -135,6 +135,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int if ($this->filesystem->exists(self::KEYCLOAK_PATH)) { $keycloak = true; } + $update_token = $this->filesystem->getLineInFile("/etc/doil/doil.conf", "update_token"); $this->writer->beginBlock($output, "Creating instance " . $options['name']); @@ -314,10 +315,17 @@ public function execute(InputInterface $input, OutputInterface $output) : int } $this->docker->setGrain($instance_salt_name, "mpass", "${mysql_password}"); + $host = explode("=", $this->filesystem->getLineInFile("/etc/doil/doil.conf", "host")); + sleep(1); - $this->docker->setGrain($instance_salt_name, "cpass", "${cron_password}"); + $this->docker->setGrain($instance_salt_name, "cpass", "$cron_password"); sleep(1); - $doil_domain = "http://" . $host . "/" . $options["name"]; + if (!is_null($update_token)) { + $token = explode("=", $update_token); + $this->docker->setGrain($instance_salt_name, "update_token", "${token[1]}"); + sleep(1); + } + $doil_domain = "http://" . $host[1] . "/" . $options["name"]; $this->docker->setGrain($instance_salt_name, "doil_domain", "${doil_domain}"); sleep(1); $this->docker->setGrain($instance_salt_name, "doil_project_name", "${options['name']}"); @@ -362,9 +370,19 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->writer->endBlock(); } + // apply composer state $this->writer->beginBlock($output, "Apply composer state"); $this->docker->applyState($instance_salt_name, $this->getComposerVersion($ilias_version)); + + // apply set-update-token state + $this->writer->beginBlock($output, "Apply set-update-token state"); + $this->docker->applyState($instance_salt_name, "set-update-token"); + $this->writer->endBlock(); + + // apply ilias-update-hook state + $this->writer->beginBlock($output, "Apply ilias-update-hook state"); + $this->docker->applyState($instance_salt_name, "ilias-update-hook"); $this->writer->endBlock(); // apply enable-captainhook state diff --git a/app/src/cli.php b/app/src/cli.php index b5bb858b..ec46bd05 100644 --- a/app/src/cli.php +++ b/app/src/cli.php @@ -45,6 +45,7 @@ function buildContainerForApp() : Container $c["command.instances.login"], $c["command.instances.path"], $c["command.instances.restart"], + $c["command.instances.set.update.token"], $c["command.instances.status"], $c["command.instances.up"], $c["command.keycloak.down"], @@ -240,6 +241,15 @@ function buildContainerForApp() : Container ); }; + $c["command.instances.set.update.token"] = function($c) { + return new Instances\SetUpdateTokenCommand( + $c["docker.shell"], + $c["posix.shell"], + $c["filesystem.shell"], + $c["command.writer"] + ); + }; + $c["command.instances.status"] = function($c) { return new Instances\StatusCommand( $c["docker.shell"] diff --git a/app/tests/Commands/Instances/CreateCommandTest.php b/app/tests/Commands/Instances/CreateCommandTest.php index 36f99e1d..3771611e 100644 --- a/app/tests/Commands/Instances/CreateCommandTest.php +++ b/app/tests/Commands/Instances/CreateCommandTest.php @@ -335,10 +335,10 @@ public function test_execute() : void ->willReturn(false, true, false, true) ; $filesystem - ->expects($this->once()) + ->expects($this->exactly(2)) ->method("getLineInFile") - ->with("/etc/doil/doil.conf", "host") - ->willReturnOnConsecutiveCalls("foo=doil", "7.8") + ->withConsecutive(["/etc/doil/doil.conf", "host"], ["/etc/doil/doil.conf", "update_token"]) + ->willReturnOnConsecutiveCalls("foo=doil", "update_token=foobar") ; $filesystem ->expects($this->once()) diff --git a/setup/conf/doil.conf b/setup/conf/doil.conf index 116486d4..e2fa0184 100755 --- a/setup/conf/doil.conf +++ b/setup/conf/doil.conf @@ -7,4 +7,4 @@ keycloak_hostname=http://doil/keycloak keycloak_new_admin_password=admin keycloak_old_admin_password=admin keycloak_db_username=admin -keycloak_db_password=admin \ No newline at end of file +keycloak_db_password=admin diff --git a/setup/stack/config/master.cnf b/setup/stack/config/master.cnf index 77f5b635..13e89988 100755 --- a/setup/stack/config/master.cnf +++ b/setup/stack/config/master.cnf @@ -680,6 +680,8 @@ file_roots: - /srv/salt/states/ilias keycloak: - /srv/salt/states/keycloak + ilias-update-hook: + - /srv/salt/states/ilias-update-hook compile-skins: - /srv/salt/states/compile-skins composer: @@ -720,6 +722,8 @@ file_roots: - /srv/salt/states/disable-saml prevent-super-global-replacement: - /srv/salt/states/prevent-super-global-replacement + set-update-token: + - /srv/salt/states/set-update-token # The master_roots setting configures a master-only copy of the file_roots dictionary, diff --git a/setup/stack/states/ilias-update-hook/description.txt b/setup/stack/states/ilias-update-hook/description.txt new file mode 100644 index 00000000..783219a3 --- /dev/null +++ b/setup/stack/states/ilias-update-hook/description.txt @@ -0,0 +1 @@ +description = Inject an update hook file into docroot \ No newline at end of file diff --git a/setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls b/setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls new file mode 100644 index 00000000..dafe2ba2 --- /dev/null +++ b/setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls @@ -0,0 +1,8 @@ +{% set ilias_version = salt['grains.get']('ilias_version', '8.0') %} + +/var/www/html/.update_hook.php: + file.managed: + - source: salt://ilias-update-hook/update_hook.php.j2 + - template: jinja + - context: + ilias_version: {{ ilias_version }} \ No newline at end of file diff --git a/setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 b/setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 new file mode 100644 index 00000000..1557a284 --- /dev/null +++ b/setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 @@ -0,0 +1,69 @@ + - Extended GPL, see LICENSE */ + +$request_headers = apache_request_headers(); +if (is_null($request_headers) || !array_key_exists("Authorization", $request_headers)) { + http_response_code(401); + throw new Exception("Authorization required"); +} +$request_token = $request_headers["Authorization"]; + +$environment_token = getenv("UPDATE_TOKEN"); +if (is_null($environment_token)) { + http_response_code(401); + throw new Exception("Authorization required"); +} + +if ($environment_token !== $request_token) { + http_response_code(401); + throw new Exception("Authorization required"); +} + +// Pull current checked out branch from origin +$pull_output = []; +$result_code = 0; +$branch = exec("git branch --show-current"); +exec("git pull origin " . $branch . " 2>&1", $pull_output, $result_code); +if ($result_code !== 0) { + http_response_code(500); + throw new Exception("Failed to run update hook"); +} + +// Run composer install +$composer_output = []; +$result_code = 0; +exec("COMPOSER_HOME=/usr/local/bin/composer composer install 2>&1", $composer_output, $result_code); +if ($result_code !== 0) { + http_response_code(500); + throw new Exception("Failed to run update hook"); +} + +// Run ilias update +$update_output = []; +$result_code = 0; +{% if ilias_version | int < 10 %} +exec("php " . __DIR__ . "/setup/setup.php update -y 2>&1", $update_output, $result_code); +{% else %} +exec("php " . __DIR__ . "/cli/setup.php update -y 2>&1", $update_output, $result_code); +{% endif %} +if ($result_code !== 0) { + http_response_code(500); + throw new Exception("Failed to run update hook"); +} + +$output = ""; +foreach ($pull_output as $line) { + $output .= $line . "
"; +} + +foreach ($composer_output as $line) { + $output .= $line . "
"; +} + +foreach ($update_output as $line) { + $output .= $line . "
"; +} + +echo $output; + diff --git a/setup/stack/states/ilias-update-hook/top.sls b/setup/stack/states/ilias-update-hook/top.sls new file mode 100644 index 00000000..8a10ad74 --- /dev/null +++ b/setup/stack/states/ilias-update-hook/top.sls @@ -0,0 +1,3 @@ +ilias-update-hook: + '*': + - ilias-update-hook \ No newline at end of file diff --git a/setup/stack/states/proxyservices/proxyservices/service-config.tpl b/setup/stack/states/proxyservices/proxyservices/service-config.tpl index f8a0e04b..ab69b39e 100755 --- a/setup/stack/states/proxyservices/proxyservices/service-config.tpl +++ b/setup/stack/states/proxyservices/proxyservices/service-config.tpl @@ -7,4 +7,15 @@ location /%DOMAIN%/ { proxy_set_header X-Forwarded-Proto https; rewrite ^/%DOMAIN%/(.*) /%DOMAIN%/$1 break; +} + +location /%DOMAIN%/update/ { +proxy_pass http://%IP%/; +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $remote_addr; +proxy_pass_request_headers on; +proxy_set_header X-Forwarded-Proto https; + +rewrite ^/%DOMAIN%/(.*) /%DOMAIN%/.update_hook.php break; } \ No newline at end of file diff --git a/setup/stack/states/set-update-token/description.txt b/setup/stack/states/set-update-token/description.txt new file mode 100644 index 00000000..f17a1f48 --- /dev/null +++ b/setup/stack/states/set-update-token/description.txt @@ -0,0 +1 @@ +description = Set an update token for all instances \ No newline at end of file diff --git a/setup/stack/states/set-update-token/set-update-token/init.sls b/setup/stack/states/set-update-token/set-update-token/init.sls new file mode 100644 index 00000000..baca43de --- /dev/null +++ b/setup/stack/states/set-update-token/set-update-token/init.sls @@ -0,0 +1,7 @@ +{% set update_token = salt['grains.get']('update_token', '') %} + +/etc/apache2/envvars: + file.replace: + - pattern: '^export UPDATE_TOKEN=.*$' + - repl: 'export UPDATE_TOKEN={{ update_token }}' + - append_if_not_found: True \ No newline at end of file diff --git a/setup/stack/states/set-update-token/top.sls b/setup/stack/states/set-update-token/top.sls new file mode 100644 index 00000000..ecd86735 --- /dev/null +++ b/setup/stack/states/set-update-token/top.sls @@ -0,0 +1,3 @@ +set-update-token: + '*': + - set-update-token \ No newline at end of file diff --git a/setup/templates/minion/docker-compose.yml b/setup/templates/minion/docker-compose.yml index dcd0db81..ffec14e3 100755 --- a/setup/templates/minion/docker-compose.yml +++ b/setup/templates/minion/docker-compose.yml @@ -49,6 +49,9 @@ services: - type: bind source: ~/.ssh/ target: /root/.ssh + - type: bind + source: ~/.ssh/ + target: /var/www/.ssh - type: bind source: ./conf/salt-minion.conf target: /etc/supervisor/conf.d/salt-minion.conf diff --git a/setup/updates/update-20241206.sh b/setup/updates/update-20241206.sh new file mode 100644 index 00000000..9b35e133 --- /dev/null +++ b/setup/updates/update-20241206.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +doil_update_20241206() { + + cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ + cp -r ${SCRIPT_DIR}/../setup/stack/states/* /usr/local/share/doil/stack/states/ + cp -r ${SCRIPT_DIR}/../setup/stack/config/* /usr/local/share/doil/stack/config/ + cp -r ${SCRIPT_DIR}/../setup/templates/minion/* /usr/local/share/doil/templates/minion/ + cp -r ${SCRIPT_DIR}/../setup/templates/proxy/conf/* /usr/local/lib/doil/server/proxy/conf/ + + doil salt:restart + doil proxy:restart + sleep 10 + + NAME=$(cat /etc/doil/doil.conf | grep "host=" | cut -d '=' -f 2-) + sed -i "s/%TPL_SERVER_NAME%/${NAME}/g" "/usr/local/lib/doil/server/proxy/conf/nginx/local.conf" + docker exec -it doil_saltmain /bin/bash -c "salt \"doil.proxy\" state.highstate saltenv=proxyservices" &> /dev/null + docker commit doil_proxy doil_proxy:stable + + doil proxy:reload + + if [ $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}" | wc -l) -gt 0 ] + doil_status_send_message "Applying patch on existing instances" + then + for INSTANCE in $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}") + do + STARTED=0 + NAME=${INSTANCE%_*} + SUFFIX=${INSTANCE##*_} + + if [ -L /usr/local/share/doil/instances/"${NAME}" ] || [ -L /home/"${SUDO_USER}"/.doil/instances/"${NAME}" ] + then + if [ "${SUFFIX}" == "global" ] + then + INSTANCE_PATH=$(/usr/local/bin/doil path "${NAME}" -g -p) + GLOBAL="-g" + else + INSTANCE_PATH=$(su -c "/usr/local/bin/doil path ${NAME} -p" "${SUDO_USER}") + GLOBAL="" + fi + + if [[ ! $(docker ps --filter "name=_local" --filter "name=_global" --format "{{.Names}}") =~ ${INSTANCE} ]] + then + doil up ${NAME} ${GLOBAL} + STARTED=1 + fi + + DOCKER_COMPOSE_PATH="${INSTANCE_PATH}/docker-compose.yml" + + if ! grep -q "target: /var/www/.ssh" "${DOCKER_COMPOSE_PATH}" + then + sed -i 's/volumes:/&\n - type: bind\n source: ~\/.ssh\/\n target: \/var\/www\/.ssh/' "${DOCKER_COMPOSE_PATH}" + fi + sleep 5 + docker exec -it doil_saltmain /bin/bash -c "salt \"${NAME}.${SUFFIX}\" state.highstate saltenv=ilias-update-hook" &> /dev/null + if [ ${STARTED} == 1 ] + then + doil down ${NAME} ${GLOBAL} + else + doil restart ${NAME} ${GLOBAL} + fi + fi + done + + doil_status_okay + fi + + return $? +} \ No newline at end of file