From 29e1cc677d9dc1b3cda9a79fdd0dfef131584caf Mon Sep 17 00:00:00 2001 From: daniwe4 Date: Tue, 11 Nov 2025 08:23:08 +0100 Subject: [PATCH] master setup: mv setup from shell to php scripts --- .github/workflows/checks.yml | 14 +- CHANGELOG.md | 6 + README.md | 63 ++- Update/shell_update_steps_template.sh | 6 + Update/update.conf | 2 + app/composer.json | 12 +- app/src/App.php | 4 +- app/src/Commands/Instances/ApplyCommand.php | 34 +- app/src/Commands/Instances/CSPCommand.php | 29 +- app/src/Commands/Instances/CreateCommand.php | 77 +-- app/src/Commands/Instances/DeleteCommand.php | 33 +- app/src/Commands/Instances/DownCommand.php | 31 +- app/src/Commands/Instances/ExecCommand.php | 27 +- app/src/Commands/Instances/ListCommand.php | 29 +- app/src/Commands/Instances/LoginCommand.php | 32 +- app/src/Commands/Instances/PathCommand.php | 27 +- app/src/Commands/Instances/RestartCommand.php | 31 +- .../Instances/SetUpdateTokenCommand.php | 29 +- app/src/Commands/Instances/StatusCommand.php | 21 +- app/src/Commands/Instances/UpCommand.php | 31 +- app/src/Commands/Keycloak/DownCommand.php | 25 +- app/src/Commands/Keycloak/LoginCommand.php | 22 +- app/src/Commands/Keycloak/RestartCommand.php | 25 +- app/src/Commands/Keycloak/UpCommand.php | 25 +- .../Commands/Mail/ChangePasswordCommand.php | 23 +- app/src/Commands/Mail/DownCommand.php | 21 +- app/src/Commands/Mail/LoginCommand.php | 14 +- app/src/Commands/Mail/RestartCommand.php | 21 +- app/src/Commands/Mail/UpCommand.php | 20 +- app/src/Commands/Pack/ExportCommand.php | 45 +- app/src/Commands/Pack/ImportCommand.php | 43 +- app/src/Commands/Pack/PackCreateCommand.php | 77 +-- app/src/Commands/Proxy/DownCommand.php | 20 +- app/src/Commands/Proxy/LoginCommand.php | 17 +- app/src/Commands/Proxy/PruneCommand.php | 21 +- app/src/Commands/Proxy/ReloadCommand.php | 20 +- app/src/Commands/Proxy/RestartCommand.php | 20 +- app/src/Commands/Proxy/UpCommand.php | 20 +- app/src/Commands/Repo/AddCommand.php | 23 +- app/src/Commands/Repo/DeleteCommand.php | 20 +- app/src/Commands/Repo/ListCommand.php | 14 +- app/src/Commands/Repo/UpdateCommand.php | 21 +- app/src/Commands/Salt/DownCommand.php | 20 +- app/src/Commands/Salt/LoginCommand.php | 16 +- app/src/Commands/Salt/PruneCommand.php | 22 +- app/src/Commands/Salt/RestartCommand.php | 22 +- app/src/Commands/Salt/StatesCommand.php | 14 +- app/src/Commands/Salt/UpCommand.php | 22 +- app/src/Commands/System/UpdateCommand.php | 85 ++++ app/src/Commands/User/AddCommand.php | 34 +- app/src/Commands/User/DeleteCommand.php | 26 +- app/src/Commands/User/ListCommand.php | 14 +- app/src/Lib/Config/Config.php | 205 ++++++++ app/src/Lib/Config/ConfigChecker.php | 80 ++++ app/src/Lib/Config/ConfigReader.php | 61 +++ app/src/Lib/ConsoleOutput/SetupWriter.php | 35 ++ app/src/Lib/Docker/Docker.php | 6 +- app/src/Lib/Docker/DockerShell.php | 260 +++++++++-- app/src/Lib/FileSystem/Filesystem.php | 13 +- app/src/Lib/FileSystem/FilesystemShell.php | 52 ++- app/src/Lib/Git/Git.php | 3 + app/src/Lib/Git/GitShell.php | 69 +++ app/src/Lib/Logger/LoggerFactory.php | 15 + app/src/Lib/System/Update.php | 204 ++++++++ app/src/Setup/CopyFiles/Copy.php | 79 ++++ .../Setup/FileStructure/BaseDirectories.php | 89 ++++ app/src/Setup/FileStructure/BaseFiles.php | 78 ++++ app/src/Setup/IP/IP.php | 33 ++ app/src/Setup/Install.php | 262 +++++++++++ app/src/Setup/Server/Keycloak.php | 132 ++++++ app/src/Setup/Server/Mail.php | 106 +++++ app/src/Setup/Server/Proxy.php | 77 +++ app/src/Setup/Server/Salt.php | 50 ++ app/src/Setup/Server/StartServers.php | 41 ++ {setup => app/src/Setup}/doil.sh | 19 +- .../src/Setup}/stack/config/master.cnf | 0 .../src/Setup}/stack/config/minion.cnf | 0 .../stack/states/access/access/init.sls | 0 .../stack/states/access/description.txt | 0 .../src/Setup}/stack/states/access/top.sls | 0 .../stack/states/apache/apache/apache.conf | 0 .../Setup}/stack/states/apache/apache/default | 0 .../states/apache/apache/default_ilias10 | 0 .../stack/states/apache/apache/init.sls | 0 .../stack/states/apache/description.txt | 0 .../src/Setup}/stack/states/apache/top.sls | 0 .../autoinstall/autoinstall/ilias-config.json | 0 .../states/autoinstall/autoinstall/init.sls | 0 .../Setup}/stack/states/autoinstall/top.sls | 0 .../Setup}/stack/states/base/msmtp/init.sls | 0 .../stack/states/base/msmtp/msmtp.conf.j2 | 0 .../Setup}/stack/states/base/mysql/init.sls | 0 .../src/Setup}/stack/states/base/mysql/my.cnf | 0 .../Setup}/stack/states/base/mysql/mysql.conf | 0 .../stack/states/base/mysql/mysql_starter.sh | 0 .../Setup}/stack/states/base/postfix/aliases | 0 .../Setup}/stack/states/base/postfix/init.sls | 0 .../Setup}/stack/states/base/postfix/mailname | 0 .../Setup}/stack/states/base/postfix/main.cf | 0 .../stack/states/base/postfix/transport | 0 .../Setup}/stack/states/base/startup/init.sls | 0 .../stack/states/base/startup/salt-startup.sh | 0 .../stack/states/base/startup/startup.conf | 0 .../Setup}/stack/states/base/tools/init.sls | 0 .../src/Setup}/stack/states/base/top.sls | 0 .../change-roundcube-password/init.sls | 0 .../states/change-roundcube-password/top.sls | 0 .../compile-skins/compileskins/init.sls | 0 .../states/compile-skins/description.txt | 0 .../Setup}/stack/states/compile-skins/top.sls | 0 .../composer-install/init.sls | 0 .../states/composer-install/description.txt | 0 .../stack/states/composer-install/top.sls | 0 .../stack/states/composer/composer/init.sls | 0 .../src/Setup}/stack/states/composer/top.sls | 0 .../stack/states/composer2/composer/init.sls | 0 .../src/Setup}/stack/states/composer2/top.sls | 0 .../stack/states/composer54/composer/init.sls | 0 .../Setup}/stack/states/composer54/top.sls | 0 .../dev/devtools/adminer-4.8.0-mysql-en.php | 0 .../states/dev/devtools/githook-post-merge | 0 .../Setup}/stack/states/dev/devtools/init.sls | 0 .../states/dev/devtools/install-lessc.sh | 0 .../stack/states/dev/devtools/install-sass.sh | 0 .../src/Setup}/stack/states/dev/top.sls | 0 .../disable-captainhook/captainhook/init.sls | 0 .../disable-captainhook/description.txt | 0 .../stack/states/disable-captainhook/top.sls | 0 .../states/disable-https/description.txt | 0 .../stack/states/disable-https/https/init.sls | 0 .../Setup}/stack/states/disable-https/top.sls | 0 .../stack/states/disable-saml/description.txt | 0 .../states/disable-saml/saml/DeleteIdp.php.j2 | 0 .../disable-saml/saml/DeleteIdpV10.php.j2 | 0 .../saml/deleteInstanceFromKeycloak.php.j2 | 0 .../stack/states/disable-saml/saml/init.sls | 0 .../Setup}/stack/states/disable-saml/top.sls | 0 .../disable-whoops-devmode/description.txt | 0 .../states/disable-whoops-devmode/top.sls | 0 .../whoops-devmode/init.sls | 0 .../states/disable-xdebug/description.txt | 0 .../stack/states/disable-xdebug/top.sls | 0 .../states/disable-xdebug/xdebug/init.sls | 0 .../enable-captainhook/captainhook/init.sls | 0 .../states/enable-captainhook/description.txt | 0 .../stack/states/enable-captainhook/top.sls | 0 .../stack/states/enable-https/description.txt | 0 .../stack/states/enable-https/https/init.sls | 0 .../Setup}/stack/states/enable-https/top.sls | 0 .../stack/states/enable-saml/description.txt | 0 .../states/enable-saml/saml/SetIdp.php.j2 | 0 .../states/enable-saml/saml/SetIdpV10.php.j2 | 0 .../saml/addInstanceToKeycloak.php.j2 | 0 .../enable-saml/saml/authsources.php.j2 | 0 .../states/enable-saml/saml/config.php.j2 | 0 .../stack/states/enable-saml/saml/init.sls | 0 .../Setup}/stack/states/enable-saml/top.sls | 0 .../enable-whoops-devmode/description.txt | 0 .../states/enable-whoops-devmode/top.sls | 0 .../whoops-devmode/init.sls | 0 .../states/enable-xdebug/description.txt | 0 .../Setup}/stack/states/enable-xdebug/top.sls | 0 .../states/enable-xdebug/xdebug/init.sls | 0 .../states/ilias-update-hook/description.txt | 0 .../ilias-update-hook/init.sls | 0 .../ilias-update-hook/update_hook.php.j2 | 0 .../stack/states/ilias-update-hook/top.sls | 0 .../stack/states/ilias/ilCron/ilias_cron.sh | 0 .../stack/states/ilias/ilCron/ilias_cron_9.sh | 0 .../stack/states/ilias/ilCron/ilias_logrotate | 0 .../Setup}/stack/states/ilias/ilCron/init.sls | 0 .../stack/states/ilias/ilCron/logrotate.sh | 0 .../stack/states/ilias/ilServer/ilServer.conf | 0 .../stack/states/ilias/ilServer/ilServer.ini | 0 .../stack/states/ilias/ilServer/init.sls | 5 +- .../Setup}/stack/states/ilias/ilias/init.sls | 0 .../stack/states/ilias/imagemagick/init.sls | 4 +- .../stack/states/ilias/imagemagick/policy.xml | 0 .../states/ilias/openssl-legacy/init.sls | 0 .../states/ilias/openssl-legacy/openssl.cnf | 0 .../src/Setup}/stack/states/ilias/top.sls | 0 .../keycloak/delete_keycloak_client.sh.j2 | 0 .../stack/states/keycloak/keycloak/init.sls | 0 .../src/Setup}/stack/states/keycloak/top.sls | 0 .../check-postbox-configuration.sh | 0 .../delete-postbox-configuration.sh | 0 .../mailservices/dovecot-10-mail.conf | 0 .../mailservices/dovecot-15-lda.conf | 0 .../mailservices/dovecot-90-sieve.conf | 0 .../states/mailservices/mailservices/init.sls | 47 +- .../states/mailservices/mailservices/mailname | 0 .../mailservices/mailservices/mysql-my.cnf | 0 .../mailservices/postfix-canonical-redirect | 0 .../mailservices/mailservices/postfix-main.cf | 0 .../mailservices/postfix_fg_starter.sh | 0 .../mailservices/roundcube-config.inc.php | 0 .../mailservices/roundcube-debian-db.php | 0 .../mailservices/mailservices/roundcube.conf | 0 .../mailservices/service-config-sieve.tpl | 0 .../mailservices/service-config.tpl | 0 .../mailservices/mailservices/sv-apache.conf | 0 .../mailservices/mailservices/sv-dovecot.conf | 0 .../mailservices/mailservices/sv-mysql.conf | 0 .../mailservices/mailservices/sv-postfix.conf | 0 .../Setup}/stack/states/mailservices/top.sls | 0 .../stack/states/nodejs/nodejs/init.sls | 0 .../src/Setup}/stack/states/nodejs/top.sls | 0 .../stack/states/php7.2/description.txt | 0 .../Setup}/stack/states/php7.2/php/init.sls | 4 - .../src/Setup}/stack/states/php7.2/top.sls | 0 .../stack/states/php7.3/description.txt | 0 .../Setup}/stack/states/php7.3/php/init.sls | 4 - .../src/Setup}/stack/states/php7.3/top.sls | 0 .../stack/states/php7.4/description.txt | 0 .../Setup}/stack/states/php7.4/php/init.sls | 4 - .../src/Setup}/stack/states/php7.4/top.sls | 0 .../stack/states/php8.0/description.txt | 0 .../Setup}/stack/states/php8.0/php/init.sls | 4 - .../src/Setup}/stack/states/php8.0/top.sls | 0 .../stack/states/php8.1/description.txt | 0 .../Setup}/stack/states/php8.1/php/init.sls | 4 - .../src/Setup}/stack/states/php8.1/top.sls | 0 .../stack/states/php8.2/description.txt | 0 .../Setup}/stack/states/php8.2/php/init.sls | 4 - .../src/Setup}/stack/states/php8.2/top.sls | 0 .../stack/states/php8.3/description.txt | 0 .../Setup}/stack/states/php8.3/php/init.sls | 4 - .../src/Setup}/stack/states/php8.3/top.sls | 0 .../stack/states/php8.4/description.txt | 0 .../Setup}/stack/states/php8.4/php/init.sls | 4 - .../src/Setup}/stack/states/php8.4/top.sls | 0 .../description.txt | 0 .../prevent-super-global-replacement/init.sls | 0 .../prevent-super-global-replacement/top.sls | 0 .../states/proxy-enable-https/https/init.sls | 0 .../stack/states/proxy-enable-https/top.sls | 0 .../proxyservices/add-configuration.sh | 0 .../proxyservices/check-for-lost-minions.sh | 0 .../proxyservices/proxyservices/init.sls | 0 .../proxyservices/service-config.tpl | 0 .../proxyservices/proxyservices/sv-nginx.conf | 0 .../Setup}/stack/states/proxyservices/top.sls | 0 .../reactor/postfix_on_minion_start.sls | 0 .../states/reactor/proxy_on_minion_start.sls | 0 .../states/reactor/proxy_on_minion_stop.sls | 0 .../reset-ilias-root-password/description.txt | 0 .../reset-ilias-root-password/init.sls | 0 .../states/reset-ilias-root-password/top.sls | 0 .../states/set-update-token/description.txt | 0 .../set-update-token/init.sls | 0 .../stack/states/set-update-token/top.sls | 0 app/src/Setup/templates/base/Dockerfile | 62 +++ .../src/Setup}/templates/keycloak/Dockerfile | 3 +- .../Setup}/templates/keycloak/conf/init.sql | 0 .../keycloak/conf/keycloak-startup.conf | 0 .../Setup}/templates/keycloak/conf/minion.cnf | 0 .../Setup}/templates/keycloak/conf/mysql.conf | 0 .../templates/keycloak/conf/mysql_starter.sh | 0 .../templates/keycloak/conf/run-supervisor.sh | 0 .../templates/keycloak/conf/salt-minion.conf | 0 .../templates/keycloak/conf/salt-startup.sh | 0 .../templates/keycloak/conf/startup.conf | 0 .../templates/keycloak/docker-compose.yml | 4 +- .../src/Setup}/templates/mail/Dockerfile | 10 +- .../Setup/templates/mail/conf/dovecot-23.pref | 3 + .../src/Setup}/templates/mail/conf/minion.cnf | 0 .../templates/mail/conf/run-supervisor.sh | 0 .../templates/mail/conf/salt-minion.conf | 0 .../templates/mail/conf/salt-startup.sh | 0 .../Setup}/templates/mail/conf/startup.conf | 0 .../Setup}/templates/mail/docker-compose.yml | 14 +- .../src/Setup}/templates/minion/README.md | 0 .../templates/minion/docker-compose-mac.yml | 4 +- .../templates/minion/docker-compose.yml | 4 +- .../Setup}/templates/minion/run-supervisor.sh | 0 .../Setup}/templates/minion/salt-minion.conf | 0 .../src/Setup}/templates/proxy/Dockerfile | 3 +- .../proxy/conf/generate_index_html.sh | 0 .../proxy/conf/localcerts/apache.key | 0 .../proxy/conf/localcerts/apache.pem | 0 .../Setup}/templates/proxy/conf/minion.cnf | 0 .../templates/proxy/conf/nginx/local.conf | 0 .../templates/proxy/conf/nginx/sites/.gitkeep | 0 .../Setup}/templates/proxy/conf/robots.txt | 0 .../templates/proxy/conf/run-supervisor.sh | 0 .../templates/proxy/conf/salt-minion.conf | 0 .../templates/proxy/conf/salt-startup.sh | 0 .../Setup}/templates/proxy/conf/startup.conf | 0 .../Setup}/templates/proxy/docker-compose.yml | 4 +- .../src/Setup}/templates/salt/Dockerfile | 3 +- .../Setup}/templates/salt/docker-compose.yml | 13 +- app/src/cli.php | 181 +++++++- .../Commands/Instances/ApplyCommandTest.php | 36 +- .../Commands/Instances/CSPCommandTest.php | 4 + .../Commands/Instances/CreateCommandTest.php | 3 + .../Commands/Instances/DeleteCommandTest.php | 48 +- .../Commands/Instances/DownCommandTest.php | 3 + .../Commands/Instances/ListCommandTest.php | 35 +- .../Commands/Instances/LoginCommandTest.php | 3 + .../Commands/Instances/PathCommandTest.php | 2 + .../Commands/Instances/RestartCommandTest.php | 3 + .../Commands/Instances/StatusCommandTest.php | 2 + .../Commands/Instances/UpCommandTest.php | 3 + .../Mail/ChangePasswordCommandTest.php | 2 + app/tests/Commands/Mail/DownCommandTest.php | 2 + app/tests/Commands/Mail/LoginCommandTest.php | 2 + .../Commands/Mail/RestartCommandTest.php | 2 + app/tests/Commands/Mail/UpCommandTest.php | 2 + app/tests/Commands/Pack/ExportCommandTest.php | 2 + app/tests/Commands/Pack/ImportCommandTest.php | 2 + app/tests/Commands/Proxy/DownCommandTest.php | 2 + app/tests/Commands/Proxy/LoginCommandTest.php | 2 + app/tests/Commands/Proxy/PruneCommandTest.php | 35 +- .../Commands/Proxy/ReloadCommandTest.php | 2 + .../Commands/Proxy/RestartCommandTest.php | 2 + app/tests/Commands/Proxy/UpCommandTest.php | 2 + app/tests/Commands/Repo/AddCommandTest.php | 2 + app/tests/Commands/Repo/DeleteCommandTest.php | 2 + app/tests/Commands/Repo/ListCommandTest.php | 2 + app/tests/Commands/Repo/RepoManagerTest.php | 3 + app/tests/Commands/Repo/RepoTest.php | 2 + app/tests/Commands/Repo/UpdateCommandTest.php | 2 + app/tests/Commands/Salt/DownCommandTest.php | 2 + app/tests/Commands/Salt/LoginCommandTest.php | 2 + app/tests/Commands/Salt/PruneCommandTest.php | 4 +- .../Commands/Salt/RestartCommandTest.php | 21 +- app/tests/Commands/Salt/StatesCommandTest.php | 2 + app/tests/Commands/Salt/UpCommandTest.php | 21 +- .../Commands/System/UpdateCommandTest.php | 168 +++++++ app/tests/Commands/User/AddCommandTest.php | 2 + app/tests/Commands/User/DeleteCommandTest.php | 3 + app/tests/Commands/User/ListCommandTest.php | 2 + app/tests/Commands/User/UserManagerTest.php | 17 +- app/tests/Commands/User/UserTest.php | 2 + app/tests/Setup/CopyFiles/CopyTest.php | 74 +++ .../FileStructure/BaseDirectoriesTest.php | 121 +++++ .../Setup/FileStructure/BaseFilesTest.php | 122 +++++ app/tests/Setup/IP/IPTest.php | 61 +++ setup/{templates/php => }/Dockerfile | 8 +- setup/colors.sh | 18 - setup/conf/doil.conf | 14 - setup/env.sh | 30 -- setup/install | 86 ++++ setup/install.sh | 180 ------- setup/{ => scripts}/check_requirements.sh | 12 +- setup/{ => scripts}/checks.sh | 60 ++- setup/{ => scripts}/helper.sh | 0 setup/{ => scripts}/log.sh | 6 +- setup/scripts/uninstall.sh | 138 ++++++ setup/system.sh | 438 ------------------ setup/templates/base/Dockerfile | 18 - setup/tests/tests/test-helper.sh | 27 -- setup/tests/tests/test-system.sh | 64 --- setup/tests/tstfy.sh | 244 ---------- setup/{uninstall.sh => uninstall} | 32 +- setup/update.sh | 42 -- setup/updates/update-20240730.sh | 18 - setup/updates/update-20240801.sh | 9 - setup/updates/update-20240806.sh | 9 - setup/updates/update-20240807.sh | 30 -- setup/updates/update-20240902.sh | 7 - setup/updates/update-20240926.sh | 7 - setup/updates/update-20240930.sh | 9 - setup/updates/update-20241010.sh | 8 - setup/updates/update-20241113.sh | 51 -- setup/updates/update-20241206.sh | 59 --- setup/updates/update-20250130.sh | 6 - setup/updates/update-20250217.sh | 6 - setup/updates/update-20250226.sh | 95 ---- setup/updates/update-20250404.sh | 7 - setup/updates/update-20250430.sh | 6 - setup/updates/update-20250523.sh | 7 - setup/updates/update-20250624.sh | 7 - setup/updates/update-20250701.sh | 8 - setup/updates/update-20250707.sh | 7 - setup/updates/update-20250725.sh | 7 - setup/updates/update-20250806.sh | 97 ---- setup/updates/update-20250901.sh | 7 - setup/updates/update-20250903.sh | 8 - setup/updates/update-20250908.sh | 42 -- setup/updates/update-20250918.sh | 36 -- setup/updates/update-20250924.sh | 7 - setup/updates/update-20251103.sh | 30 -- setup/updates/update-20251125.sh | 32 -- setup/updates/update.sh | 110 ----- 385 files changed, 3903 insertions(+), 2819 deletions(-) create mode 100644 Update/shell_update_steps_template.sh create mode 100644 Update/update.conf create mode 100644 app/src/Commands/System/UpdateCommand.php create mode 100644 app/src/Lib/Config/Config.php create mode 100644 app/src/Lib/Config/ConfigChecker.php create mode 100644 app/src/Lib/Config/ConfigReader.php create mode 100644 app/src/Lib/ConsoleOutput/SetupWriter.php create mode 100644 app/src/Lib/System/Update.php create mode 100644 app/src/Setup/CopyFiles/Copy.php create mode 100644 app/src/Setup/FileStructure/BaseDirectories.php create mode 100644 app/src/Setup/FileStructure/BaseFiles.php create mode 100644 app/src/Setup/IP/IP.php create mode 100644 app/src/Setup/Install.php create mode 100644 app/src/Setup/Server/Keycloak.php create mode 100644 app/src/Setup/Server/Mail.php create mode 100644 app/src/Setup/Server/Proxy.php create mode 100644 app/src/Setup/Server/Salt.php create mode 100644 app/src/Setup/Server/StartServers.php rename {setup => app/src/Setup}/doil.sh (83%) rename {setup => app/src/Setup}/stack/config/master.cnf (100%) rename {setup => app/src/Setup}/stack/config/minion.cnf (100%) rename {setup => app/src/Setup}/stack/states/access/access/init.sls (100%) rename {setup => app/src/Setup}/stack/states/access/description.txt (100%) rename {setup => app/src/Setup}/stack/states/access/top.sls (100%) rename {setup => app/src/Setup}/stack/states/apache/apache/apache.conf (100%) rename {setup => app/src/Setup}/stack/states/apache/apache/default (100%) rename {setup => app/src/Setup}/stack/states/apache/apache/default_ilias10 (100%) rename {setup => app/src/Setup}/stack/states/apache/apache/init.sls (100%) rename {setup => app/src/Setup}/stack/states/apache/description.txt (100%) rename {setup => app/src/Setup}/stack/states/apache/top.sls (100%) rename {setup => app/src/Setup}/stack/states/autoinstall/autoinstall/ilias-config.json (100%) rename {setup => app/src/Setup}/stack/states/autoinstall/autoinstall/init.sls (100%) rename {setup => app/src/Setup}/stack/states/autoinstall/top.sls (100%) rename {setup => app/src/Setup}/stack/states/base/msmtp/init.sls (100%) rename {setup => app/src/Setup}/stack/states/base/msmtp/msmtp.conf.j2 (100%) rename {setup => app/src/Setup}/stack/states/base/mysql/init.sls (100%) rename {setup => app/src/Setup}/stack/states/base/mysql/my.cnf (100%) rename {setup => app/src/Setup}/stack/states/base/mysql/mysql.conf (100%) rename {setup => app/src/Setup}/stack/states/base/mysql/mysql_starter.sh (100%) rename {setup => app/src/Setup}/stack/states/base/postfix/aliases (100%) rename {setup => app/src/Setup}/stack/states/base/postfix/init.sls (100%) rename {setup => app/src/Setup}/stack/states/base/postfix/mailname (100%) rename {setup => app/src/Setup}/stack/states/base/postfix/main.cf (100%) rename {setup => app/src/Setup}/stack/states/base/postfix/transport (100%) rename {setup => app/src/Setup}/stack/states/base/startup/init.sls (100%) rename {setup => app/src/Setup}/stack/states/base/startup/salt-startup.sh (100%) rename {setup => app/src/Setup}/stack/states/base/startup/startup.conf (100%) rename {setup => app/src/Setup}/stack/states/base/tools/init.sls (100%) rename {setup => app/src/Setup}/stack/states/base/top.sls (100%) rename {setup => app/src/Setup}/stack/states/change-roundcube-password/change-roundcube-password/init.sls (100%) rename {setup => app/src/Setup}/stack/states/change-roundcube-password/top.sls (100%) rename {setup => app/src/Setup}/stack/states/compile-skins/compileskins/init.sls (100%) rename {setup => app/src/Setup}/stack/states/compile-skins/description.txt (100%) rename {setup => app/src/Setup}/stack/states/compile-skins/top.sls (100%) rename {setup => app/src/Setup}/stack/states/composer-install/composer-install/init.sls (100%) rename {setup => app/src/Setup}/stack/states/composer-install/description.txt (100%) rename {setup => app/src/Setup}/stack/states/composer-install/top.sls (100%) rename {setup => app/src/Setup}/stack/states/composer/composer/init.sls (100%) rename {setup => app/src/Setup}/stack/states/composer/top.sls (100%) rename {setup => app/src/Setup}/stack/states/composer2/composer/init.sls (100%) rename {setup => app/src/Setup}/stack/states/composer2/top.sls (100%) rename {setup => app/src/Setup}/stack/states/composer54/composer/init.sls (100%) rename {setup => app/src/Setup}/stack/states/composer54/top.sls (100%) rename {setup => app/src/Setup}/stack/states/dev/devtools/adminer-4.8.0-mysql-en.php (100%) rename {setup => app/src/Setup}/stack/states/dev/devtools/githook-post-merge (100%) rename {setup => app/src/Setup}/stack/states/dev/devtools/init.sls (100%) rename {setup => app/src/Setup}/stack/states/dev/devtools/install-lessc.sh (100%) rename {setup => app/src/Setup}/stack/states/dev/devtools/install-sass.sh (100%) rename {setup => app/src/Setup}/stack/states/dev/top.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-captainhook/captainhook/init.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-captainhook/description.txt (100%) rename {setup => app/src/Setup}/stack/states/disable-captainhook/top.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-https/description.txt (100%) rename {setup => app/src/Setup}/stack/states/disable-https/https/init.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-https/top.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-saml/description.txt (100%) rename {setup => app/src/Setup}/stack/states/disable-saml/saml/DeleteIdp.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/disable-saml/saml/DeleteIdpV10.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/disable-saml/saml/deleteInstanceFromKeycloak.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/disable-saml/saml/init.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-saml/top.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-whoops-devmode/description.txt (100%) rename {setup => app/src/Setup}/stack/states/disable-whoops-devmode/top.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-whoops-devmode/whoops-devmode/init.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-xdebug/description.txt (100%) rename {setup => app/src/Setup}/stack/states/disable-xdebug/top.sls (100%) rename {setup => app/src/Setup}/stack/states/disable-xdebug/xdebug/init.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-captainhook/captainhook/init.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-captainhook/description.txt (100%) rename {setup => app/src/Setup}/stack/states/enable-captainhook/top.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-https/description.txt (100%) rename {setup => app/src/Setup}/stack/states/enable-https/https/init.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-https/top.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/description.txt (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/saml/SetIdp.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/saml/SetIdpV10.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/saml/addInstanceToKeycloak.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/saml/authsources.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/saml/config.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/saml/init.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-saml/top.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-whoops-devmode/description.txt (100%) rename {setup => app/src/Setup}/stack/states/enable-whoops-devmode/top.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-whoops-devmode/whoops-devmode/init.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-xdebug/description.txt (100%) rename {setup => app/src/Setup}/stack/states/enable-xdebug/top.sls (100%) rename {setup => app/src/Setup}/stack/states/enable-xdebug/xdebug/init.sls (100%) rename {setup => app/src/Setup}/stack/states/ilias-update-hook/description.txt (100%) rename {setup => app/src/Setup}/stack/states/ilias-update-hook/ilias-update-hook/init.sls (100%) rename {setup => app/src/Setup}/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 (100%) rename {setup => app/src/Setup}/stack/states/ilias-update-hook/top.sls (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilCron/ilias_cron.sh (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilCron/ilias_cron_9.sh (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilCron/ilias_logrotate (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilCron/init.sls (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilCron/logrotate.sh (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilServer/ilServer.conf (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilServer/ilServer.ini (100%) rename {setup => app/src/Setup}/stack/states/ilias/ilServer/init.sls (96%) rename {setup => app/src/Setup}/stack/states/ilias/ilias/init.sls (100%) rename {setup => app/src/Setup}/stack/states/ilias/imagemagick/init.sls (71%) rename {setup => app/src/Setup}/stack/states/ilias/imagemagick/policy.xml (100%) rename {setup => app/src/Setup}/stack/states/ilias/openssl-legacy/init.sls (100%) rename {setup => app/src/Setup}/stack/states/ilias/openssl-legacy/openssl.cnf (100%) rename {setup => app/src/Setup}/stack/states/ilias/top.sls (100%) rename {setup => app/src/Setup}/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 (100%) rename {setup => app/src/Setup}/stack/states/keycloak/keycloak/init.sls (100%) rename {setup => app/src/Setup}/stack/states/keycloak/top.sls (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/check-postbox-configuration.sh (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/delete-postbox-configuration.sh (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/dovecot-10-mail.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/dovecot-15-lda.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/dovecot-90-sieve.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/init.sls (87%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/mailname (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/mysql-my.cnf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/postfix-canonical-redirect (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/postfix-main.cf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/postfix_fg_starter.sh (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/roundcube-config.inc.php (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/roundcube-debian-db.php (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/roundcube.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/service-config-sieve.tpl (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/service-config.tpl (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/sv-apache.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/sv-dovecot.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/sv-mysql.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/mailservices/sv-postfix.conf (100%) rename {setup => app/src/Setup}/stack/states/mailservices/top.sls (100%) rename {setup => app/src/Setup}/stack/states/nodejs/nodejs/init.sls (100%) rename {setup => app/src/Setup}/stack/states/nodejs/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php7.2/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php7.2/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php7.2/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php7.3/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php7.3/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php7.3/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php7.4/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php7.4/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php7.4/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php8.0/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php8.0/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php8.0/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php8.1/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php8.1/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php8.1/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php8.2/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php8.2/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php8.2/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php8.3/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php8.3/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php8.3/top.sls (100%) rename {setup => app/src/Setup}/stack/states/php8.4/description.txt (100%) rename {setup => app/src/Setup}/stack/states/php8.4/php/init.sls (97%) rename {setup => app/src/Setup}/stack/states/php8.4/top.sls (100%) rename {setup => app/src/Setup}/stack/states/prevent-super-global-replacement/description.txt (100%) rename {setup => app/src/Setup}/stack/states/prevent-super-global-replacement/prevent-super-global-replacement/init.sls (100%) rename {setup => app/src/Setup}/stack/states/prevent-super-global-replacement/top.sls (100%) rename {setup => app/src/Setup}/stack/states/proxy-enable-https/https/init.sls (100%) rename {setup => app/src/Setup}/stack/states/proxy-enable-https/top.sls (100%) rename {setup => app/src/Setup}/stack/states/proxyservices/proxyservices/add-configuration.sh (100%) rename {setup => app/src/Setup}/stack/states/proxyservices/proxyservices/check-for-lost-minions.sh (100%) rename {setup => app/src/Setup}/stack/states/proxyservices/proxyservices/init.sls (100%) rename {setup => app/src/Setup}/stack/states/proxyservices/proxyservices/service-config.tpl (100%) rename {setup => app/src/Setup}/stack/states/proxyservices/proxyservices/sv-nginx.conf (100%) rename {setup => app/src/Setup}/stack/states/proxyservices/top.sls (100%) rename {setup => app/src/Setup}/stack/states/reactor/postfix_on_minion_start.sls (100%) rename {setup => app/src/Setup}/stack/states/reactor/proxy_on_minion_start.sls (100%) rename {setup => app/src/Setup}/stack/states/reactor/proxy_on_minion_stop.sls (100%) rename {setup => app/src/Setup}/stack/states/reset-ilias-root-password/description.txt (100%) rename {setup => app/src/Setup}/stack/states/reset-ilias-root-password/reset-ilias-root-password/init.sls (100%) rename {setup => app/src/Setup}/stack/states/reset-ilias-root-password/top.sls (100%) rename {setup => app/src/Setup}/stack/states/set-update-token/description.txt (100%) rename {setup => app/src/Setup}/stack/states/set-update-token/set-update-token/init.sls (100%) rename {setup => app/src/Setup}/stack/states/set-update-token/top.sls (100%) create mode 100755 app/src/Setup/templates/base/Dockerfile rename {setup => app/src/Setup}/templates/keycloak/Dockerfile (98%) rename {setup => app/src/Setup}/templates/keycloak/conf/init.sql (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/keycloak-startup.conf (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/minion.cnf (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/mysql.conf (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/mysql_starter.sh (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/run-supervisor.sh (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/salt-minion.conf (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/salt-startup.sh (100%) rename {setup => app/src/Setup}/templates/keycloak/conf/startup.conf (100%) rename {setup => app/src/Setup}/templates/keycloak/docker-compose.yml (92%) rename {setup => app/src/Setup}/templates/mail/Dockerfile (66%) create mode 100644 app/src/Setup/templates/mail/conf/dovecot-23.pref rename {setup => app/src/Setup}/templates/mail/conf/minion.cnf (100%) rename {setup => app/src/Setup}/templates/mail/conf/run-supervisor.sh (100%) rename {setup => app/src/Setup}/templates/mail/conf/salt-minion.conf (100%) rename {setup => app/src/Setup}/templates/mail/conf/salt-startup.sh (100%) rename {setup => app/src/Setup}/templates/mail/conf/startup.conf (100%) rename {setup => app/src/Setup}/templates/mail/docker-compose.yml (80%) rename {setup => app/src/Setup}/templates/minion/README.md (100%) rename {setup => app/src/Setup}/templates/minion/docker-compose-mac.yml (97%) rename {setup => app/src/Setup}/templates/minion/docker-compose.yml (97%) rename {setup => app/src/Setup}/templates/minion/run-supervisor.sh (100%) rename {setup => app/src/Setup}/templates/minion/salt-minion.conf (100%) rename {setup => app/src/Setup}/templates/proxy/Dockerfile (93%) rename {setup => app/src/Setup}/templates/proxy/conf/generate_index_html.sh (100%) rename {setup => app/src/Setup}/templates/proxy/conf/localcerts/apache.key (100%) rename {setup => app/src/Setup}/templates/proxy/conf/localcerts/apache.pem (100%) rename {setup => app/src/Setup}/templates/proxy/conf/minion.cnf (100%) rename {setup => app/src/Setup}/templates/proxy/conf/nginx/local.conf (100%) rename {setup => app/src/Setup}/templates/proxy/conf/nginx/sites/.gitkeep (100%) rename {setup => app/src/Setup}/templates/proxy/conf/robots.txt (100%) rename {setup => app/src/Setup}/templates/proxy/conf/run-supervisor.sh (100%) rename {setup => app/src/Setup}/templates/proxy/conf/salt-minion.conf (100%) rename {setup => app/src/Setup}/templates/proxy/conf/salt-startup.sh (100%) rename {setup => app/src/Setup}/templates/proxy/conf/startup.conf (100%) rename {setup => app/src/Setup}/templates/proxy/docker-compose.yml (97%) rename {setup => app/src/Setup}/templates/salt/Dockerfile (91%) rename {setup => app/src/Setup}/templates/salt/docker-compose.yml (72%) create mode 100644 app/tests/Commands/System/UpdateCommandTest.php create mode 100644 app/tests/Setup/CopyFiles/CopyTest.php create mode 100644 app/tests/Setup/FileStructure/BaseDirectoriesTest.php create mode 100644 app/tests/Setup/FileStructure/BaseFilesTest.php create mode 100644 app/tests/Setup/IP/IPTest.php rename setup/{templates/php => }/Dockerfile (85%) delete mode 100644 setup/colors.sh delete mode 100755 setup/conf/doil.conf delete mode 100644 setup/env.sh create mode 100755 setup/install delete mode 100755 setup/install.sh rename setup/{ => scripts}/check_requirements.sh (88%) rename setup/{ => scripts}/checks.sh (80%) rename setup/{ => scripts}/helper.sh (100%) rename setup/{ => scripts}/log.sh (94%) create mode 100644 setup/scripts/uninstall.sh delete mode 100644 setup/system.sh delete mode 100755 setup/templates/base/Dockerfile delete mode 100755 setup/tests/tests/test-helper.sh delete mode 100755 setup/tests/tests/test-system.sh delete mode 100755 setup/tests/tstfy.sh rename setup/{uninstall.sh => uninstall} (52%) delete mode 100755 setup/update.sh delete mode 100644 setup/updates/update-20240730.sh delete mode 100644 setup/updates/update-20240801.sh delete mode 100644 setup/updates/update-20240806.sh delete mode 100644 setup/updates/update-20240807.sh delete mode 100644 setup/updates/update-20240902.sh delete mode 100644 setup/updates/update-20240926.sh delete mode 100644 setup/updates/update-20240930.sh delete mode 100644 setup/updates/update-20241010.sh delete mode 100644 setup/updates/update-20241113.sh delete mode 100644 setup/updates/update-20241206.sh delete mode 100644 setup/updates/update-20250130.sh delete mode 100644 setup/updates/update-20250217.sh delete mode 100644 setup/updates/update-20250226.sh delete mode 100644 setup/updates/update-20250404.sh delete mode 100644 setup/updates/update-20250430.sh delete mode 100644 setup/updates/update-20250523.sh delete mode 100644 setup/updates/update-20250624.sh delete mode 100644 setup/updates/update-20250701.sh delete mode 100644 setup/updates/update-20250707.sh delete mode 100644 setup/updates/update-20250725.sh delete mode 100644 setup/updates/update-20250806.sh delete mode 100644 setup/updates/update-20250901.sh delete mode 100644 setup/updates/update-20250903.sh delete mode 100644 setup/updates/update-20250908.sh delete mode 100644 setup/updates/update-20250918.sh delete mode 100644 setup/updates/update-20250924.sh delete mode 100644 setup/updates/update-20251103.sh delete mode 100644 setup/updates/update-20251125.sh delete mode 100755 setup/updates/update.sh diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 7fda9c42..4cbc4fc3 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -8,8 +8,9 @@ jobs: strategy: fail-fast: false matrix: - php: [ 7.4, 8.0 ] + php: [ 8.4 ] steps: + - name: Checkout code uses: actions/checkout@v2 @@ -34,17 +35,10 @@ jobs: run: pip install yamllint - name: Install doil - run: sudo ./setup/install.sh - env: - GHRUN: yes + run: sudo ./setup/install yes - name: PHP Unit Test run: CI/PHPUnit/run_tests.sh - env: - GHRUN: "yes" - - - name: Setup Unit Tests - run: ./setup/tests/tstfy.sh setup/tests/tests - name: SLS Tests - run: ./CI/validate-sls-files.sh setup/stack/states \ No newline at end of file + run: ./CI/validate-sls-files.sh app/src/Setup/stack/states \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d0579a..4dc35418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 20260122 +## What's Changed +* a great part of the setup is handled by php now +* updates are now triggered via 'sudo doil system:update' +* base debian image is now 'Debian 13 - Trixie' + ## 20251103 ## What's Changed * update Captainhook Hooks while running update_hook script diff --git a/README.md b/README.md index 2504103b..1c81ec3f 100644 --- a/README.md +++ b/README.md @@ -8,43 +8,43 @@ all mails from your instances, so you can test the ILIAS emailing. ## Installation -1. download and unpack the [latest release](https://github.com/conceptsandtraining/doil/releases) -1. cd into the unpacked directory -1. if you run doil on a remote host ensure to change the host name in `setup/conf/doil.conf` to your host name -1. adjust your mail password in `setup/conf/doil.conf` -1. if you run global instances make sure to adjust 'global_instances_path' in `setup/conf/doil.conf` to specify - where to place them, default is '/srv/instances'. Attention, paths with 'home' are not allowed here. -1. execute `sudo ./setup/install.sh` in order to install **doil** -1. you can remove the downloaded folder afterwards -1. check `doil help` for available commands and further instructions +1. download and unpack the [latest release](https://github.com/conceptsandtraining/doil/releases) + Alternatively, you can simply clone the repo via Git. + ```bash + git clone https://github.com/conceptsandtraining/doil.git + ``` +1. cd into the directory +1. run the setup install script + ```bash + sudo setup/install + ``` +1. doil will automatically pause and ask you to configure the doil config file at /etc/doil/doil.conf + Please adjust it to your needs. At least update the paths for the ssh files. +1. continue with 'y' +1. check `doil` for available commands and further instructions +1. you can safely delete the downloaded/cloned folder doil ## Update -If you use a **doil** version older than 20221110, we recommend completely removing an already installed -**doil** from the system. This includes already installed instances. After that, you can proceed to the -Installation section. +If you use a **doil** version from before the year 2026, we recommend completely removing an already installed +**doil** from the system. After that, you can proceed to the Installation section. Removal Tips: -* `docker ps -a` shows all containers -* `docker rm ` removes container by id (ensure to delete all doil instances) -* `docker images` shows all images -* `docker rmi ` remove image by id (ensure to delete all doil images) -* `docker volume ls` shows all volumes -* `docker volume rm ` remove volume by name (ensure to delete mail, proxy and salt) -* `docker network prune` removes all networks without dependencies -* `sudo rm -rf /etc/doil /usr/local/lib/doil /usr/local/share/doil /usr/local/bin/doil ~/.doil /var/log/doil` -* remove the instances folders or if you placed all instances in one folder remove the whole folder +1. download and unpack the [latest release](https://github.com/conceptsandtraining/doil/releases) + Alternatively, you can simply clone the repo via Git. + ```bash + git clone https://github.com/conceptsandtraining/doil.git + ``` +1. cd into the directory +1. run the uninstall script + ```bash + sudo setup/uninstall + ``` -Otherwise, use the update script. +Otherwise, use the update command with sudo. -1. checkout the newest master branch or copy and extract the zip -2. cd into the unpacked directory -3. if you run global instances make sure to adjust 'global_instances_path' in `setup/conf/doil.conf` to specify -where to place them, default is '/srv/instances'. Attention, paths with 'home' are not allowed here. The update -will move all global instances to the set path. -4. execute sudo ./setup/update.sh in order to update **doil** -5. you can remove the downloaded folder afterward +* sudo doil system:update ## Dependencies @@ -54,9 +54,8 @@ however **doil** needs [Docker](https://www.docker.com/) in order to work: * docker (follow [this](https://docs.docker.com/engine/install/) instructions depending on your os to install docker), if you have installed docker by your package manager ensure that **docker-buildx-plugin** and **docker-compose-plugin** are available and installed and also executable by your user. * git -* .ssh folder in your home directory. **doil** will mount it into the container. **doil** needs this to have access to any private git repositories that may be used. -Additional dependencies, but these are installed automatically during setup. +Additional dependencies, but these are installed automatically inside the containers during setup. * php version => 7.4 * php*.*-zip @@ -296,7 +295,7 @@ the folder easily clone it again from [doil](https://github.com/conceptsandtrain Cd into the cloned folder and execute the script. -`sudo ./setup/uninstall.sh` +`sudo ./setup/uninstall` The script will ask you if you want to remove **doil** completely from your system or if you want to keep your instances, images ... diff --git a/Update/shell_update_steps_template.sh b/Update/shell_update_steps_template.sh new file mode 100644 index 00000000..c460bc75 --- /dev/null +++ b/Update/shell_update_steps_template.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Don't change this file manually. +# Make a copy and name the file shell_steps.sh for additional steps during update. + +echo "no additional shell steps for this update" \ No newline at end of file diff --git a/Update/update.conf b/Update/update.conf new file mode 100644 index 00000000..06c9ae7f --- /dev/null +++ b/Update/update.conf @@ -0,0 +1,2 @@ +full_update=true +php_container_update=false \ No newline at end of file diff --git a/app/composer.json b/app/composer.json index 61519a56..f4776210 100644 --- a/app/composer.json +++ b/app/composer.json @@ -14,18 +14,18 @@ } }, "require": { - "symfony/console": "^5.4", + "symfony/console": "^8", "pimple/pimple": "^3.5", - "symfony/process": "^5.4", + "symfony/process": "^8", "ext-posix": "*", "ext-zip": "*", - "symfony/filesystem": "^5.4", + "symfony/filesystem": "^8", "ext-openssl": "*", - "psr/log": "1.1.4", - "monolog/monolog": "2.8.0", + "psr/log": "^3", + "monolog/monolog": "^3", "ext-pcntl": "*" }, "require-dev": { - "phpunit/phpunit": "^9" + "phpunit/phpunit": "^12" } } diff --git a/app/src/App.php b/app/src/App.php index bf0292b6..8aee9143 100644 --- a/app/src/App.php +++ b/app/src/App.php @@ -9,14 +9,14 @@ class App extends Application { - const NAME = "Doil Version 20251125 - build 2025-11-25"; + const NAME = "Doil Version 20260122 - build 2026-01-22"; public function __construct(Command ...$commands) { parent::__construct(self::NAME); foreach ($commands as $command) { - $this->add($command); + $this->addCommand($command); } } } diff --git a/app/src/Commands/Instances/ApplyCommand.php b/app/src/Commands/Instances/ApplyCommand.php index 78a740c0..3a18f9d1 100644 --- a/app/src/Commands/Instances/ApplyCommand.php +++ b/app/src/Commands/Instances/ApplyCommand.php @@ -11,13 +11,17 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Command\SignalableCommandInterface; -class ApplyCommand extends Command implements SignalableCommandInterface +#[AsCommand( + name: 'instances:apply|apply', + description: 'Apply state for the given instance. This is useful for re-applying singular state to your instance.' +)] +class ApplyCommand extends Command { protected const PATH_STATES = "/usr/local/share/doil/stack/states"; @@ -40,29 +44,18 @@ class ApplyCommand extends Command implements SignalableCommandInterface "set-update-token" ]; - protected static $defaultName = "instances:apply"; - protected static $defaultDescription = - "Apply state for the given instance. This is useful for re-applying singular state to your instance."; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["apply"]) ->addArgument("instance", InputArgument::OPTIONAL, "name of the instance to apply state to") ->addArgument("state", InputArgument::OPTIONAL, "name of the state to apply") ->addOption("all", "a", InputOption::VALUE_NONE, "if is set apply state to all instances") @@ -198,12 +191,13 @@ public function getSubscribedSignals(): array return [SIGINT, SIGTERM]; } - public function handleSignal(int $signal) : void + public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false { if (SIGINT === $signal || SIGTERM === $signal) { echo "Aborted by User!\n"; exit(0); } + return false; } protected function applyState( diff --git a/app/src/Commands/Instances/CSPCommand.php b/app/src/Commands/Instances/CSPCommand.php index d64fa7e8..43f62b05 100644 --- a/app/src/Commands/Instances/CSPCommand.php +++ b/app/src/Commands/Instances/CSPCommand.php @@ -11,36 +11,29 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Exception\InvalidArgumentException; +#[AsCommand( + name: 'instances:csp|csp', + description: 'This command sets CSP rules for the given instance or all instances.' +)] class CSPCommand extends Command { - protected static $defaultName = "instances:csp"; - protected static $defaultDescription = - "This command sets CSP rules for the given instance or 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) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["csp"]) ->addArgument("instance", InputArgument::OPTIONAL, "Name of the instance to set csp for") ->addOption("rules", "r", InputOption::VALUE_REQUIRED, "CSP rules as string") ->addOption("global", "g", InputOption::VALUE_NONE, "Determines if an instance is global or not") diff --git a/app/src/Commands/Instances/CreateCommand.php b/app/src/Commands/Instances/CreateCommand.php index aa4a8597..35cae508 100644 --- a/app/src/Commands/Instances/CreateCommand.php +++ b/app/src/Commands/Instances/CreateCommand.php @@ -19,12 +19,17 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Command\SignalableCommandInterface; +#[AsCommand( + name: 'instances:create|create', + description: 'This command creates an instance depending on the given parameters. If you do not specify any parameter you will be prompted with a wizard.' +)] class CreateCommand extends Command implements SignalableCommandInterface { protected const DEBIAN_TAG = "11"; @@ -33,6 +38,7 @@ class CreateCommand extends Command implements SignalableCommandInterface protected const GLOBAL_REPO_PATH = "/usr/local/share/doil/repositories"; protected const LOCAL_INSTANCES_PATH = "/.doil/instances"; protected const GLOBAL_INSTANCES_PATH = "/usr/local/share/doil/instances"; + protected const USER_GLOBAL_INSTANCES_PATH = "/srv/instances"; protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; protected const BASIC_FOLDERS = [ "/conf", @@ -49,48 +55,23 @@ class CreateCommand extends Command implements SignalableCommandInterface "/volumes/etc/mysql" ]; - protected static $defaultName = "instances:create"; - protected static $defaultDescription = - "This command creates an instance depending on the given parameters. If you do not specify any parameter you will be prompted with a wizard."; - - protected Docker $docker; - protected RepoManager $repo_manager; - protected Git $git; - protected Posix $posix; - protected Filesystem $filesystem; - protected Linux $linux; - protected ProjectConfig $project_config; - protected Writer $writer; - protected IliasInfo $ilias_info; - public function __construct( - Docker $docker, - RepoManager $repo_manager, - Git $git, - Posix $posix, - Filesystem $filesystem, - Linux $linux, - ProjectConfig $project_config, - Writer $writer, - IliasInfo $ilias_info + protected Docker $docker, + protected RepoManager $repo_manager, + protected Git $git, + protected Posix $posix, + protected Filesystem $filesystem, + protected Linux $linux, + protected ProjectConfig $project_config, + protected Writer $writer, + protected IliasInfo $ilias_info ) { parent::__construct(); - - $this->docker = $docker; - $this->repo_manager = $repo_manager; - $this->git = $git; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->linux = $linux; - $this->project_config = $project_config; - $this->writer = $writer; - $this->ilias_info = $ilias_info; } public function configure() : void { $this - ->setAliases(["create"]) ->addOption("name", "e", InputOption::VALUE_OPTIONAL, "Sets the name of the instance") ->addOption("repo", "r", InputOption::VALUE_OPTIONAL, "Sets the repository to use") ->addOption("use-global-repo", "u", InputOption::VALUE_NONE, "Determines if the repo is global one or not") @@ -317,10 +298,6 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(5); $this->docker->executeDockerCommand($instance_name, "/etc/init.d/mariadb stop"); - $this->docker->executeDockerCommand($instance_name, "rm -rf /etc/apt/sources.list.de/salt.list"); - $this->docker->executeDockerCommand($instance_name, "curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp"); - $this->docker->executeDockerCommand($instance_name, "curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources"); - $this->docker->copy($instance_name, "/var/log/apache2/", $instance_path . "/volumes/logs/"); $this->docker->copy($instance_name, "/etc/mysql/", $instance_path . "/volumes/etc/"); $this->docker->copy($instance_name, "/var/lib/mysql/", $instance_path . "/volumes/"); @@ -360,7 +337,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->docker->setGrain($instance_salt_name, "cpass", "$cron_password"); sleep(1); if ($update_token) { - $this->docker->setGrain($instance_salt_name, "update_token", "${$update_token}"); + $this->docker->setGrain($instance_salt_name, "update_token", "{$update_token}"); sleep(1); } $this->docker->setGrain($instance_salt_name, "doil_domain", $http_scheme . $host . "/" . $options["name"]); @@ -375,7 +352,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(1); $this->docker->setGrain($instance_salt_name, "ilias_version", $ilias_version); sleep(1); - $this->docker->executeDockerCommand("doil_saltmain", "salt \"" . $instance_salt_name . "\" saltutil.refresh_grains"); + $this->docker->executeDockerCommand("doil_salt", "salt \"" . $instance_salt_name . "\" saltutil.refresh_grains"); $this->writer->endBlock(); $this->docker->executeDockerCommand($instance_name, "git config --global --add safe.directory \"*\""); @@ -707,11 +684,7 @@ protected function gatherOptionData(InputInterface $input, OutputInterface $outp $options["global"] = $global; if ($global) { - $target = explode("=", $this->filesystem->getLineInFile("/etc/doil/doil.conf", "global_instances_path=") ?? "")[1]; - if (! $target) { - $target = ""; - } - call_user_func($this->checkGlobalTarget(), $target); + $target = self::USER_GLOBAL_INSTANCES_PATH; } // Skip readme @@ -796,17 +769,6 @@ protected function checkTarget() : Closure return $t; }; } - protected function checkGlobalTarget() : Closure - { - return function(string $t) { - if (is_null($t) || $t == "") { - throw new RuntimeException("Missing config entry 'global_instances_path'. Please add this entry to /etc/doil/doil.conf to create global instances."); - } - if (stristr($t, "/home/") !== false) { - throw new RuntimeException("Global instances must not be created below /home directory. Please change the entry in /etc/doil/doil.conf."); - } - }; - } protected function getBranches(OutputInterface $output, string $path, string $url) : array { @@ -846,11 +808,12 @@ public function getSubscribedSignals(): array return [SIGINT, SIGTERM]; } - public function handleSignal(int $signal) : void + public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false { if (SIGINT === $signal || SIGTERM === $signal) { echo "Aborted by User!\n"; exit(0); } + return false; } } diff --git a/app/src/Commands/Instances/DeleteCommand.php b/app/src/Commands/Instances/DeleteCommand.php index 35ef8247..61e851d2 100644 --- a/app/src/Commands/Instances/DeleteCommand.php +++ b/app/src/Commands/Instances/DeleteCommand.php @@ -11,42 +11,35 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Exception\InvalidArgumentException; +#[AsCommand( + name: 'instances:delete|delete', + description: "!NEEDS SUDO PRIVILEGES! This command deletes one or all instances. It will remove everything belonging " . + "to the given instance including all its files, configuration and misc data." +)] class DeleteCommand extends Command { protected const SALT_MAIN = "/usr/local/lib/doil/server/salt/"; protected const POSTFIX = "/usr/local/lib/doil/server/mail/"; protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; - protected static $defaultName = "instances:delete"; - protected static $defaultDescription = - "!NEEDS SUDO PRIVILEGES! This command deletes one or all instances. It will remove everything belonging " . - "to the given instance including all its files, configuration and misc data." - ; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["delete"]) ->addArgument("instance", InputArgument::OPTIONAL, "name of the instance to delete") ->addOption("all", "a", InputOption::VALUE_NONE, "if is set all instances will be deleted") ->addOption("global", "g", InputOption::VALUE_NONE, "determines if an instance is global or not") @@ -139,7 +132,7 @@ protected function deleteInstance( $this->docker->removeContainer($instance . "_" . $suffix); - $this->docker->executeCommand(self::SALT_MAIN, "doil_saltmain", "salt-key", "-d", "$instance.$suffix", "-y", "-q"); + $this->docker->executeCommand(self::SALT_MAIN, "doil_salt", "salt-key", "-d", "$instance.$suffix", "-y", "-q"); if ($is_up) { $this->docker->executeDockerCommand( "doil_proxy", diff --git a/app/src/Commands/Instances/DownCommand.php b/app/src/Commands/Instances/DownCommand.php index d1196703..56433a67 100644 --- a/app/src/Commands/Instances/DownCommand.php +++ b/app/src/Commands/Instances/DownCommand.php @@ -11,36 +11,29 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:down|down', + description: "This command stops an instance. If [instance] not given doil will try to stop the instance" . + " from the current active directory if doil can find a suitable configuration." +)] class DownCommand extends Command { - protected static $defaultName = "instances:down"; - protected static $defaultDescription = - "This command stops an instance. If [instance] not given doil will try to stop the instance" . - " from the current active directory if doil can find a suitable configuration." - ; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["down"]) ->addArgument("instance", InputArgument::OPTIONAL, "name of the instance to stop") ->addOption("global", "g", InputOption::VALUE_NONE, "determines if an instance is global or not") ->addOption("all", "a", InputOption::VALUE_NONE, "If is set stop all instances") diff --git a/app/src/Commands/Instances/ExecCommand.php b/app/src/Commands/Instances/ExecCommand.php index f303c342..951699f1 100644 --- a/app/src/Commands/Instances/ExecCommand.php +++ b/app/src/Commands/Instances/ExecCommand.php @@ -11,33 +11,28 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:exec|exec', + description: 'This command lets you execute a command inside a running docker instance.' +)] class ExecCommand extends Command { - protected static $defaultName = "instances:exec"; - protected static $defaultDescription = "This command lets you execute a command inside a running docker instance."; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["exec"]) ->addArgument("instance", InputArgument::REQUIRED, "name of the instance") ->addArgument("cmd", InputArgument::REQUIRED, "command to execute inside instance") ->addOption("working-dir", "w", InputOption::VALUE_OPTIONAL, "determines the working directory inside the instance") diff --git a/app/src/Commands/Instances/ListCommand.php b/app/src/Commands/Instances/ListCommand.php index c4a84df6..d0a5442b 100644 --- a/app/src/Commands/Instances/ListCommand.php +++ b/app/src/Commands/Instances/ListCommand.php @@ -8,31 +8,22 @@ use CaT\Doil\Lib\ConsoleOutput\Writer; use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:list|ls', + description: 'Lists all created instances.' +)] class ListCommand extends Command { - protected static $defaultName = "instances:list"; - protected static $defaultDescription = "Lists all created instances."; - - - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; - } - - public function configure() : void - { - $this->setAliases(["ls"]); } public function execute(InputInterface $input, OutputInterface $output) : int diff --git a/app/src/Commands/Instances/LoginCommand.php b/app/src/Commands/Instances/LoginCommand.php index 1bdc3bd7..382954cc 100644 --- a/app/src/Commands/Instances/LoginCommand.php +++ b/app/src/Commands/Instances/LoginCommand.php @@ -10,36 +10,30 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:login|login', + description: "This command lets you log into the running docker container " . + "of your ILIAS instance. If [instance] not given " . + "doil will try to login the instance from the current active " . + "directory if doil can find a suitable configuration." +)] class LoginCommand extends Command { - protected static $defaultName = "instances:login"; - protected static $defaultDescription = - "This command lets you log into the running docker container " . - "of your ILIAS instance. If [instance] not given " . - "doil will try to login the instance from the current active " . - "directory if doil can find a suitable configuration." - ; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; } public function configure() : void { $this - ->setAliases(["login"]) ->addArgument("instance", InputArgument::OPTIONAL, "name of the instance to start") ->addOption("global", "g", InputOption::VALUE_NONE, "determines if an instance is global or not") ; diff --git a/app/src/Commands/Instances/PathCommand.php b/app/src/Commands/Instances/PathCommand.php index 928cdccc..b0da874b 100644 --- a/app/src/Commands/Instances/PathCommand.php +++ b/app/src/Commands/Instances/PathCommand.php @@ -11,33 +11,28 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:path|path', + description: 'Shows the root folder of the desired instance.' +)] class PathCommand extends Command { - protected static $defaultName = "instances:path"; - protected static $defaultDescription = "Shows the root folder of the desired instance."; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["path"]) ->addArgument("instance", InputArgument::OPTIONAL, "name of the instance to start") ->addOption("global", "g", InputOption::VALUE_NONE, "determines if an instance is global or not") ->addOption("pure", "p", InputOption::VALUE_NONE, "output is not formatted") diff --git a/app/src/Commands/Instances/RestartCommand.php b/app/src/Commands/Instances/RestartCommand.php index 45d00f36..25eb9401 100644 --- a/app/src/Commands/Instances/RestartCommand.php +++ b/app/src/Commands/Instances/RestartCommand.php @@ -11,36 +11,29 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:restart|restart', + description: "This command restarts an instance. If [instance] not given doil will try to restart the instance" . + " from the current active directory if doil can find a suitable configuration." +)] class RestartCommand extends Command { - protected static $defaultName = "instances:restart"; - protected static $defaultDescription = - "This command restarts an instance. If [instance] not given doil will try to restart the instance" . - " from the current active directory if doil can find a suitable configuration." - ; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["restart"]) ->addArgument("instance", InputArgument::OPTIONAL, "Name of the instance to start") ->addOption("global", "g", InputOption::VALUE_NONE, "Determines if an instance is global or not") ->addOption("all", "a", InputOption::VALUE_NONE, "If is set start all instances") diff --git a/app/src/Commands/Instances/SetUpdateTokenCommand.php b/app/src/Commands/Instances/SetUpdateTokenCommand.php index b460e7de..101979d8 100644 --- a/app/src/Commands/Instances/SetUpdateTokenCommand.php +++ b/app/src/Commands/Instances/SetUpdateTokenCommand.php @@ -10,37 +10,30 @@ use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Exception\InvalidArgumentException; +#[AsCommand( + name: 'instances:set-update-token|sut', + description: '!NEEDS SUDO PRIVILEGES! This command sets an update token for all instances' +)] class SetUpdateTokenCommand extends Command { - protected static $defaultName = "instances:set-update-token"; - protected static $defaultDescription = - "!NEEDS SUDO PRIVILEGES! This command sets an 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) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected 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") ->addOption("autoyes", "a", InputOption::VALUE_NONE, "Auto answer questions with yes") diff --git a/app/src/Commands/Instances/StatusCommand.php b/app/src/Commands/Instances/StatusCommand.php index 62bffb48..3d639003 100644 --- a/app/src/Commands/Instances/StatusCommand.php +++ b/app/src/Commands/Instances/StatusCommand.php @@ -6,26 +6,19 @@ use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:status|status', + description: 'This command lists all running instances.' +)] class StatusCommand extends Command { - protected static $defaultName = "instances:status"; - protected static $defaultDescription = "This command lists all running instances."; - - protected Docker $docker; - - public function __construct(Docker $docker) + public function __construct(protected Docker $docker) { parent::__construct(); - - $this->docker = $docker; - } - - public function configure() : void - { - $this->setAliases(["status"]); } public function execute(InputInterface $input, OutputInterface $output) : int @@ -36,7 +29,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int strstr($a, "CONTAINER ID") || strstr($a, "doil_mail") || strstr($a, "doil_proxy") || - strstr($a, "doil_saltmain") || + strstr($a, "doil_salt") || strstr($a, "doil_keycloak") || strstr($a, "_local") || strstr($a, "_global") diff --git a/app/src/Commands/Instances/UpCommand.php b/app/src/Commands/Instances/UpCommand.php index ce3dc05b..76a2c54f 100644 --- a/app/src/Commands/Instances/UpCommand.php +++ b/app/src/Commands/Instances/UpCommand.php @@ -11,36 +11,29 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'instances:up|up', + description: "This command starts an instance. If [instance] not given doil will try to start the instance" . + " from the current active directory if doil can find a suitable configuration." +)] class UpCommand extends Command { - protected static $defaultName = "instances:up"; - protected static $defaultDescription = - "This command starts an instance. If [instance] not given doil will try to start the instance" . - " from the current active directory if doil can find a suitable configuration." - ; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - - public function __construct(Docker $docker, Posix $posix, Filesystem $filesystem, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; } public function configure() : void { $this - ->setAliases(["up"]) ->addArgument("instance", InputArgument::OPTIONAL, "Name of the instance to start") ->addOption("global", "g", InputOption::VALUE_NONE, "Determines if an instance is global or not") ->addOption("all", "a", InputOption::VALUE_NONE, "If is set start all instances") diff --git a/app/src/Commands/Keycloak/DownCommand.php b/app/src/Commands/Keycloak/DownCommand.php index 81695e7b..76578c7b 100644 --- a/app/src/Commands/Keycloak/DownCommand.php +++ b/app/src/Commands/Keycloak/DownCommand.php @@ -8,33 +8,30 @@ use CaT\Doil\Lib\ConsoleOutput\Writer; use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'keycloak:down', + description: "Stops the keycloak server." +)] class DownCommand extends Command { protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; - protected static $defaultName = "keycloak:down"; - protected static $defaultDescription = "Stops the keycloak server"; - - protected Docker $docker; - protected Writer $writer; - protected Filesystem $filesystem; - - public function __construct(Docker $docker, Writer $writer, Filesystem $filesystem) - { - $this->docker = $docker; - $this->writer = $writer; - $this->filesystem = $filesystem; - + public function __construct( + protected Docker $docker, + protected Writer $writer, + protected Filesystem $filesystem + ) { parent::__construct(); } protected function configure() : void { if (!$this->filesystem->exists(self::KEYCLOAK_PATH)) { - $this->setHidden(true); + $this->setHidden(); } } diff --git a/app/src/Commands/Keycloak/LoginCommand.php b/app/src/Commands/Keycloak/LoginCommand.php index 6a9d5862..ad046c69 100644 --- a/app/src/Commands/Keycloak/LoginCommand.php +++ b/app/src/Commands/Keycloak/LoginCommand.php @@ -7,31 +7,29 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'keycloak:login', + description: "Login into the keycloak server." +)] class LoginCommand extends Command { protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; - protected static $defaultName = "keycloak:login"; - protected static $defaultDescription = "Login into the keycloak server"; - - protected Docker $docker; - protected Filesystem $filesystem; - - public function __construct(Docker $docker, Filesystem $filesystem) - { - $this->docker = $docker; - $this->filesystem = $filesystem; - + public function __construct( + protected Docker $docker, + protected Filesystem $filesystem + ) { parent::__construct(); } protected function configure() : void { if (!$this->filesystem->exists(self::KEYCLOAK_PATH)) { - $this->setHidden(true); + $this->setHidden(); } } diff --git a/app/src/Commands/Keycloak/RestartCommand.php b/app/src/Commands/Keycloak/RestartCommand.php index 1d4362dc..aee72f30 100644 --- a/app/src/Commands/Keycloak/RestartCommand.php +++ b/app/src/Commands/Keycloak/RestartCommand.php @@ -8,33 +8,30 @@ use CaT\Doil\Lib\ConsoleOutput\Writer; use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'keycloak:restart', + description: "Restarts the keycloak server." +)] class RestartCommand extends Command { protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; - protected static $defaultName = "keycloak:restart"; - protected static $defaultDescription = "Restarts the keycloak server"; - - protected Docker $docker; - protected Writer $writer; - protected Filesystem $filesystem; - - public function __construct(Docker $docker, Writer $writer, Filesystem $filesystem) - { - $this->docker = $docker; - $this->writer = $writer; - $this->filesystem = $filesystem; - + public function __construct( + protected Docker $docker, + protected Writer $writer, + protected Filesystem $filesystem + ) { parent::__construct(); } protected function configure() : void { if (!$this->filesystem->exists(self::KEYCLOAK_PATH)) { - $this->setHidden(true); + $this->setHidden(); } } diff --git a/app/src/Commands/Keycloak/UpCommand.php b/app/src/Commands/Keycloak/UpCommand.php index 2744ee66..2ebbbe62 100644 --- a/app/src/Commands/Keycloak/UpCommand.php +++ b/app/src/Commands/Keycloak/UpCommand.php @@ -8,33 +8,30 @@ use CaT\Doil\Lib\ConsoleOutput\Writer; use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'keycloak:up', + description: "Starts the keycloak server." +)] class UpCommand extends Command { protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; - protected static $defaultName = "keycloak:up"; - protected static $defaultDescription = "Starts the keycloak server"; - - protected Docker $docker; - protected Writer $writer; - protected Filesystem $filesystem; - - public function __construct(Docker $docker, Writer $writer, Filesystem $filesystem) - { - $this->docker = $docker; - $this->writer = $writer; - $this->filesystem = $filesystem; - + public function __construct( + protected Docker $docker, + protected Writer $writer, + protected Filesystem $filesystem + ) { parent::__construct(); } protected function configure() : void { if (!$this->filesystem->exists(self::KEYCLOAK_PATH)) { - $this->setHidden(true); + $this->setHidden(); } } diff --git a/app/src/Commands/Mail/ChangePasswordCommand.php b/app/src/Commands/Mail/ChangePasswordCommand.php index 841d9aab..4122c722 100644 --- a/app/src/Commands/Mail/ChangePasswordCommand.php +++ b/app/src/Commands/Mail/ChangePasswordCommand.php @@ -9,27 +9,24 @@ use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'mail:change-password', + description: "!NEEDS SUDO PRIVILEGES! Change the roundcube password." +)] class ChangePasswordCommand extends Command { protected const MAIL_PATH = "/usr/local/lib/doil/server/mail"; - protected static $defaultName = "mail:change-password"; - protected static $defaultDescription = "!NEEDS SUDO PRIVILEGES! Change the roundcube password."; - - protected Docker $docker; - protected Writer $writer; - protected Posix $posix; - - public function __construct(Docker $docker, Writer $writer, Posix $posix) - { + public function __construct( + protected Docker $docker, + protected Writer $writer, + protected Posix $posix + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; - $this->posix = $posix; } public function configure() : void diff --git a/app/src/Commands/Mail/DownCommand.php b/app/src/Commands/Mail/DownCommand.php index 49ae67bd..112bcd25 100644 --- a/app/src/Commands/Mail/DownCommand.php +++ b/app/src/Commands/Mail/DownCommand.php @@ -7,25 +7,22 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'mail:down', + description: "Stops the mail server." +)] class DownCommand extends Command { protected const MAIL_PATH = "/usr/local/lib/doil/server/mail"; - - protected static $defaultName = "mail:down"; - protected static $defaultDescription = "Stops the mail server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } diff --git a/app/src/Commands/Mail/LoginCommand.php b/app/src/Commands/Mail/LoginCommand.php index d052e0d9..0baddfdb 100644 --- a/app/src/Commands/Mail/LoginCommand.php +++ b/app/src/Commands/Mail/LoginCommand.php @@ -6,23 +6,21 @@ use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'mail:login', + description: "Login into the mail server." +)] class LoginCommand extends Command { protected const MAIL_PATH = "/usr/local/lib/doil/server/mail"; - protected static $defaultName = "mail:login"; - protected static $defaultDescription = "Login into the mail server"; - - protected Docker $docker; - - public function __construct(Docker $docker) + public function __construct(protected Docker $docker) { parent::__construct(); - - $this->docker = $docker; } diff --git a/app/src/Commands/Mail/RestartCommand.php b/app/src/Commands/Mail/RestartCommand.php index 2f6e34c9..3db24d89 100644 --- a/app/src/Commands/Mail/RestartCommand.php +++ b/app/src/Commands/Mail/RestartCommand.php @@ -7,28 +7,25 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'mail:restart', + description: "Restarts the mail server." +)] class RestartCommand extends Command { protected const MAIL_PATH = "/usr/local/lib/doil/server/mail"; - protected static $defaultName = "mail:restart"; - protected static $defaultDescription = "Restarts the mail server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } - public function execute(InputInterface $input, OutputInterface $output) : int { if (! $this->docker->isInstanceUp(self::MAIL_PATH)) { diff --git a/app/src/Commands/Mail/UpCommand.php b/app/src/Commands/Mail/UpCommand.php index adbfbf10..d1a29d63 100644 --- a/app/src/Commands/Mail/UpCommand.php +++ b/app/src/Commands/Mail/UpCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'mail:up', + description: "Starts the mail server." +)] class UpCommand extends Command { protected const MAIL_PATH = "/usr/local/lib/doil/server/mail"; - protected static $defaultName = "mail:up"; - protected static $defaultDescription = "Starts the mail server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } diff --git a/app/src/Commands/Pack/ExportCommand.php b/app/src/Commands/Pack/ExportCommand.php index 3d327a99..797b7ce0 100644 --- a/app/src/Commands/Pack/ExportCommand.php +++ b/app/src/Commands/Pack/ExportCommand.php @@ -18,46 +18,29 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; +#[AsCommand( + name: 'pack:export', + description: "Exports an instance to an archive with all the data needed for an import." . + " The final archive name will be -doilpack.zip." +)] class ExportCommand extends Command { - protected static $defaultName = "pack:export"; - protected static $defaultDescription = - "Exports an instance to an archive with all the data needed for an import." - . " The final archive name will be -doilpack.zip."; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected Writer $writer; - protected ProjectConfig $project_config; - protected Git $git; - protected RepoManager $repo_manager; - protected IliasInfo $ilias_info; - public function __construct( - Docker $docker, - Posix $posix, - Filesystem $filesystem, - Writer $writer, - ProjectConfig $project_config, - Git $git, - RepoManager $repo_manager, - IliasInfo $ilias_info + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected Writer $writer, + protected ProjectConfig $project_config, + protected Git $git, + protected RepoManager $repo_manager, + protected IliasInfo $ilias_info ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->writer = $writer; - $this->project_config = $project_config; - $this->git = $git; - $this->repo_manager = $repo_manager; - $this->ilias_info = $ilias_info; } public function configure() : void diff --git a/app/src/Commands/Pack/ImportCommand.php b/app/src/Commands/Pack/ImportCommand.php index f38ffc65..7c324130 100644 --- a/app/src/Commands/Pack/ImportCommand.php +++ b/app/src/Commands/Pack/ImportCommand.php @@ -18,45 +18,32 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Filesystem\Exception\FileNotFoundException; +#[AsCommand( + name: 'pack:import', + description: "With this command doil is able to import an archive of doilpack into an ILIAS installation. " . + "If the installation is not present, it will be created with the properties of the configuration " . + "inside of the pack. If the instance is present all existing data will be overwritten by the new data." +)] class ImportCommand extends Command { protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; protected const DOIL_INI_PATH = "/etc/doil/doil.conf"; - protected static $defaultName = "pack:import"; - protected static $defaultDescription = - "With this command doil is able to import an archive of doilpack into an ILIAS installation. " . - "If the installation is not present, it will be created with the properties of the configuration " . - "inside of the pack. If the instance is present all existing data will be overwritten by the new data." - ; - - protected Docker $docker; - protected Posix $posix; - protected Filesystem $filesystem; - protected RepoManager $repo_manager; - protected Writer $writer; - protected IliasInfo $ilias_info; public function __construct( - Docker $docker, - Posix $posix, - Filesystem $filesystem, - RepoManager $repo_manager, - Writer $writer, - IliasInfo $ilias_info + protected Docker $docker, + protected Posix $posix, + protected Filesystem $filesystem, + protected RepoManager $repo_manager, + protected Writer $writer, + protected IliasInfo $ilias_info ) { parent::__construct(); - - $this->docker = $docker; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->repo_manager = $repo_manager; - $this->writer = $writer; - $this->ilias_info = $ilias_info; } public function configure() : void @@ -323,7 +310,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int $instance, "bash", "-c", - "php /var/www/html/setup/setup.php update /var/ilias/data/ilias-config.json -y" + "cd /var/www/html && php setup/setup.php update /var/ilias/data/ilias-config.json -y" ); } else if ($path . "/volumes/ilias/cli/setup.php") { $this->docker->executeCommand( @@ -331,7 +318,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int $instance, "bash", "-c", - "php /var/www/html/cli/setup.php update /var/ilias/data/ilias-config.json -y" + "cd /var/www/html/cli && php setup.php update /var/ilias/data/ilias-config.json -y" ); } else { throw new RuntimeException("Can not found setup.php."); diff --git a/app/src/Commands/Pack/PackCreateCommand.php b/app/src/Commands/Pack/PackCreateCommand.php index cb4fddbc..1fda288d 100644 --- a/app/src/Commands/Pack/PackCreateCommand.php +++ b/app/src/Commands/Pack/PackCreateCommand.php @@ -19,12 +19,17 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Command\SignalableCommandInterface; +#[AsCommand( + name: 'pack:create|pack-create', + description: "This command creates an instance depending on the given parameters. If you do not specify any parameter you will be prompted with a wizard." +)] class PackCreateCommand extends Command implements SignalableCommandInterface { protected const DEBIAN_TAG = "11"; @@ -33,6 +38,7 @@ class PackCreateCommand extends Command implements SignalableCommandInterface protected const GLOBAL_REPO_PATH = "/usr/local/share/doil/repositories"; protected const LOCAL_INSTANCES_PATH = "/.doil/instances"; protected const GLOBAL_INSTANCES_PATH = "/usr/local/share/doil/instances"; + protected const USER_GLOBAL_INSTANCES_PATH = "/srv/instances"; protected const KEYCLOAK_PATH = "/usr/local/lib/doil/server/keycloak"; protected const BASIC_FOLDERS = [ "/conf", @@ -49,48 +55,23 @@ class PackCreateCommand extends Command implements SignalableCommandInterface "/volumes/etc/mysql", ]; - protected static $defaultName = "pack:create"; - protected static $defaultDescription = - "This command creates an instance depending on the given parameters. If you do not specify any parameter you will be prompted with a wizard."; - - protected Docker $docker; - protected RepoManager $repo_manager; - protected Git $git; - protected Posix $posix; - protected Filesystem $filesystem; - protected Linux $linux; - protected ProjectConfig $project_config; - protected Writer $writer; - protected IliasInfo $ilias_info; - public function __construct( - Docker $docker, - RepoManager $repo_manager, - Git $git, - Posix $posix, - Filesystem $filesystem, - Linux $linux, - ProjectConfig $project_config, - Writer $writer, - IliasInfo $ilias_info + protected Docker $docker, + protected RepoManager $repo_manager, + protected Git $git, + protected Posix $posix, + protected Filesystem $filesystem, + protected Linux $linux, + protected ProjectConfig $project_config, + protected Writer $writer, + protected IliasInfo $ilias_info ) { parent::__construct(); - - $this->docker = $docker; - $this->repo_manager = $repo_manager; - $this->git = $git; - $this->posix = $posix; - $this->filesystem = $filesystem; - $this->linux = $linux; - $this->project_config = $project_config; - $this->writer = $writer; - $this->ilias_info = $ilias_info; } public function configure() : void { $this - ->setAliases(["pack-create"]) ->addOption("name", "e", InputOption::VALUE_OPTIONAL, "Sets the name of the instance") ->addOption("repo", "r", InputOption::VALUE_OPTIONAL, "Sets the repository to use") ->addOption("use-global-repo", "u", InputOption::VALUE_NONE, "Determines if the repo is global one or not") @@ -100,7 +81,7 @@ public function configure() : void ->addOption("xdebug", "x", InputOption::VALUE_NONE, "Determines if xdebug should be installed or not") ->addOption("global", "g", InputOption::VALUE_NONE, "Determines if an instance is global or not") ->addOption("skip-readme", "s", InputOption::VALUE_NONE, "Doesn't create the README.md file") - ->setHidden(true) + ->setHidden() ; } @@ -324,10 +305,6 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(5); $this->docker->executeDockerCommand($instance_name, "/etc/init.d/mariadb stop"); - $this->docker->executeDockerCommand($instance_name, "rm -rf /etc/apt/sources.list.de/salt.list"); - $this->docker->executeDockerCommand($instance_name, "curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp"); - $this->docker->executeDockerCommand($instance_name, "curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources"); - $this->docker->copy($instance_name, "/var/log/apache2/", $instance_path . "/volumes/logs/"); $this->docker->copy($instance_name, "/etc/mysql/", $instance_path . "/volumes/etc/"); $this->docker->copy($instance_name, "/var/lib/mysql/", $instance_path . "/volumes/"); @@ -382,7 +359,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(1); $this->docker->setGrain($instance_salt_name, "ilias_version", "${ilias_version}"); $this->docker->commit($instance_name); - $this->docker->executeDockerCommand("doil_saltmain", "salt \"" . $instance_salt_name . "\" saltutil.refresh_grains"); + $this->docker->executeDockerCommand("doil_salt", "salt \"" . $instance_salt_name . "\" saltutil.refresh_grains"); $this->writer->endBlock(); $this->docker->executeDockerCommand($instance_name, "git config --global --add safe.directory \"*\""); @@ -649,11 +626,7 @@ protected function gatherOptionData(InputInterface $input, OutputInterface $outp $options["global"] = $global; if ($global) { - $target = explode("=", $this->filesystem->getLineInFile("/etc/doil/doil.conf", "global_instances_path=") ?? "")[1]; - if (! $target) { - $target = ""; - } - call_user_func($this->checkGlobalTarget(), $target); + $target = self::USER_GLOBAL_INSTANCES_PATH; } $options["skip_readme"] = false; @@ -730,17 +703,6 @@ protected function checkTarget() : Closure return $t; }; } - protected function checkGlobalTarget() : Closure - { - return function(string $t) { - if (is_null($t) || $t == "") { - throw new RuntimeException("Missing config entry 'global_instances_path'. Please add this entry to /etc/doil/doil.conf to create global instances."); - } - if (stristr($t, "/home/") !== false) { - throw new RuntimeException("Global instances must not be created below /home directory. Please change the entry in /etc/doil/doil.conf."); - } - }; - } protected function getBranches(OutputInterface $output, string $path, string $url) : array { @@ -780,11 +742,12 @@ public function getSubscribedSignals(): array return [SIGINT, SIGTERM]; } - public function handleSignal(int $signal) : void + public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false { if (SIGINT === $signal || SIGTERM === $signal) { echo "Aborted by User!\n"; exit(0); } + return false; } } diff --git a/app/src/Commands/Proxy/DownCommand.php b/app/src/Commands/Proxy/DownCommand.php index b5a853c3..e72659a2 100644 --- a/app/src/Commands/Proxy/DownCommand.php +++ b/app/src/Commands/Proxy/DownCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'proxy:down', + description: "Stops the proxy server." +)] class DownCommand extends Command { protected const PROXY_PATH = "/usr/local/lib/doil/server/proxy"; - protected static $defaultName = "proxy:down"; - protected static $defaultDescription = "Stops the proxy server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } diff --git a/app/src/Commands/Proxy/LoginCommand.php b/app/src/Commands/Proxy/LoginCommand.php index 450a69bb..e7c40373 100644 --- a/app/src/Commands/Proxy/LoginCommand.php +++ b/app/src/Commands/Proxy/LoginCommand.php @@ -6,23 +6,22 @@ use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'proxy:login', + description: "Login into the proxy server." +)] class LoginCommand extends Command { protected const PROXY_PATH = "/usr/local/lib/doil/server/proxy"; - protected static $defaultName = "proxy:login"; - protected static $defaultDescription = "Login into the proxy server"; - - protected Docker $docker; - - public function __construct(Docker $docker) - { + public function __construct( + protected Docker $docker + ) { parent::__construct(); - - $this->docker = $docker; } diff --git a/app/src/Commands/Proxy/PruneCommand.php b/app/src/Commands/Proxy/PruneCommand.php index 72560fb0..ea518b05 100644 --- a/app/src/Commands/Proxy/PruneCommand.php +++ b/app/src/Commands/Proxy/PruneCommand.php @@ -7,25 +7,24 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'proxy:prune', + description: "Removes the config for each doil instance from proxy. This could be helpful for debugging purposes." . + " Restarting doil instances will write the config back.." +)] class PruneCommand extends Command { protected const PROXY_PATH = "/usr/local/lib/doil/server/proxy"; - protected static $defaultName = "proxy:prune"; - protected static $defaultDescription = "Removes the config for each doil instance from proxy. This could be helpful for debugging purposes. Restarting doil instances will write the config back."; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } public function execute(InputInterface $input, OutputInterface $output) : int diff --git a/app/src/Commands/Proxy/ReloadCommand.php b/app/src/Commands/Proxy/ReloadCommand.php index 95ec0b31..d2c41b2d 100644 --- a/app/src/Commands/Proxy/ReloadCommand.php +++ b/app/src/Commands/Proxy/ReloadCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'proxy:reload', + description: "Reloads the proxy server configuration." +)] class ReloadCommand extends Command { protected const PROXY_PATH = "/usr/local/lib/doil/server/proxy"; - protected static $defaultName = "proxy:reload"; - protected static $defaultDescription = "Reloads the proxy server configuration"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } public function execute(InputInterface $input, OutputInterface $output) : int diff --git a/app/src/Commands/Proxy/RestartCommand.php b/app/src/Commands/Proxy/RestartCommand.php index e0203698..34cf3203 100644 --- a/app/src/Commands/Proxy/RestartCommand.php +++ b/app/src/Commands/Proxy/RestartCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'proxy:restart', + description: "Restarts the proxy server." +)] class RestartCommand extends Command { protected const PROXY_PATH = "/usr/local/lib/doil/server/proxy"; - protected static $defaultName = "proxy:restart"; - protected static $defaultDescription = "Restarts the proxy server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } diff --git a/app/src/Commands/Proxy/UpCommand.php b/app/src/Commands/Proxy/UpCommand.php index 4dfc0a6d..c2404988 100644 --- a/app/src/Commands/Proxy/UpCommand.php +++ b/app/src/Commands/Proxy/UpCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'proxy:up', + description: "Starts the proxy server." +)] class UpCommand extends Command { protected const PROXY_PATH = "/usr/local/lib/doil/server/proxy"; - protected static $defaultName = "proxy:up"; - protected static $defaultDescription = "Starts the proxy server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } diff --git a/app/src/Commands/Repo/AddCommand.php b/app/src/Commands/Repo/AddCommand.php index 4e2ceae9..430e198c 100644 --- a/app/src/Commands/Repo/AddCommand.php +++ b/app/src/Commands/Repo/AddCommand.php @@ -10,26 +10,23 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; +#[AsCommand( + name: 'repo:add', + description: "Adds a repository to the doil configuration file to prepare the possibility " . + "to use another repository within the create process of a new instance." +)] class AddCommand extends Command { - protected static $defaultName = "repo:add"; - protected static $defaultDescription = - "Adds a repository to the doil configuration file to prepare the possibility " - . "to use another repository within the create process of a new instance." - ; - - protected RepoManager $repo_manager; - protected Writer $writer; - - public function __construct(RepoManager $repo_manager, Writer $writer) - { + public function __construct( + protected RepoManager $repo_manager, + protected Writer $writer + ) { parent::__construct(); - $this->repo_manager = $repo_manager; - $this->writer = $writer; } public function configure() : void diff --git a/app/src/Commands/Repo/DeleteCommand.php b/app/src/Commands/Repo/DeleteCommand.php index f8df5416..ebe6c4eb 100644 --- a/app/src/Commands/Repo/DeleteCommand.php +++ b/app/src/Commands/Repo/DeleteCommand.php @@ -10,25 +10,23 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Exception\InvalidArgumentException; +#[AsCommand( + name: 'repo:delete', + description: "Deletes a repository." +)] class DeleteCommand extends Command { - protected static $defaultName = "repo:delete"; - protected static $defaultDescription = "Deletes a repository."; - - protected RepoManager $repo_manager; - protected Writer $writer; - - public function __construct(RepoManager $repo_manager, Writer $writer) - { + public function __construct( + protected RepoManager $repo_manager, + protected Writer $writer + ) { parent::__construct(); - - $this->repo_manager = $repo_manager; - $this->writer = $writer; } public function configure() : void diff --git a/app/src/Commands/Repo/ListCommand.php b/app/src/Commands/Repo/ListCommand.php index f188542a..3791e555 100644 --- a/app/src/Commands/Repo/ListCommand.php +++ b/app/src/Commands/Repo/ListCommand.php @@ -5,21 +5,19 @@ namespace CaT\Doil\Commands\Repo; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'repo:list', + description: "Lists all registered repositories." +)] class ListCommand extends Command { - protected static $defaultName = "repo:list"; - protected static $defaultDescription = "Lists all registered repositories."; - - protected RepoManager $repo_manager; - - public function __construct(RepoManager $repo_manager) + public function __construct(protected RepoManager $repo_manager) { parent::__construct(); - - $this->repo_manager = $repo_manager; } public function execute(InputInterface $input, OutputInterface $output) : int diff --git a/app/src/Commands/Repo/UpdateCommand.php b/app/src/Commands/Repo/UpdateCommand.php index 63de174b..dd7649d3 100644 --- a/app/src/Commands/Repo/UpdateCommand.php +++ b/app/src/Commands/Repo/UpdateCommand.php @@ -10,26 +10,23 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Exception\InvalidArgumentException; +#[AsCommand( + name: 'repo:update', + description: "Updates one or all repositories so that it won't be fetched when an instances is created." +)] class UpdateCommand extends Command { - protected static $defaultName = "repo:update"; - protected static $defaultDescription = - "Updates one or all repositories so that it won't be fetched when an instances is created."; - - protected RepoManager $repo_manager; - protected Writer $writer; - - public function __construct(RepoManager $repo_manager, Writer $writer) - { + public function __construct( + protected RepoManager $repo_manager, + protected Writer $writer + ) { parent::__construct(); - - $this->repo_manager = $repo_manager; - $this->writer = $writer; } public function configure() : void diff --git a/app/src/Commands/Salt/DownCommand.php b/app/src/Commands/Salt/DownCommand.php index 97aca901..3dc9c7c6 100644 --- a/app/src/Commands/Salt/DownCommand.php +++ b/app/src/Commands/Salt/DownCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'salt:down', + description: "Deletes a repository." +)] class DownCommand extends Command { protected const SALT_PATH = "/usr/local/lib/doil/server/salt"; - protected static $defaultName = "salt:down"; - protected static $defaultDescription = "Stops the salt main server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } diff --git a/app/src/Commands/Salt/LoginCommand.php b/app/src/Commands/Salt/LoginCommand.php index 3a368dee..1d081033 100644 --- a/app/src/Commands/Salt/LoginCommand.php +++ b/app/src/Commands/Salt/LoginCommand.php @@ -6,23 +6,21 @@ use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'salt:login', + description: "Login into the salt main server." +)] class LoginCommand extends Command { protected const SALT_PATH = "/usr/local/lib/doil/server/salt"; - protected static $defaultName = "salt:login"; - protected static $defaultDescription = "Login into the salt main server"; - - protected Docker $docker; - - public function __construct(Docker $docker) + public function __construct(protected Docker $docker) { parent::__construct(); - - $this->docker = $docker; } @@ -32,7 +30,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->docker->startContainerByDockerCompose(self::SALT_PATH); } - $this->docker->loginIntoContainer(self::SALT_PATH, "doil_saltmain"); + $this->docker->loginIntoContainer(self::SALT_PATH, "doil_salt"); return Command::SUCCESS; } } \ No newline at end of file diff --git a/app/src/Commands/Salt/PruneCommand.php b/app/src/Commands/Salt/PruneCommand.php index 2544a1aa..b9b720b2 100644 --- a/app/src/Commands/Salt/PruneCommand.php +++ b/app/src/Commands/Salt/PruneCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'salt:prune', + description: "Delete all registered minion keys. This could be helpful for debugging purposes. A restart of salt forces the keys to be regenerated." +)] class PruneCommand extends Command { protected const SALT_PATH = "/usr/local/lib/doil/server/salt"; - protected static $defaultName = "salt:prune"; - protected static $defaultDescription = "Delete all registered minion keys. This could be helpful for debugging purposes. A restart of salt forces the keys to be regenerated."; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } @@ -36,7 +34,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int } $this->writer->beginBlock($output, "Prune salt main"); - $this->docker->executeCommand(self::SALT_PATH, "doil_saltmain", "salt-key", "-y", "-D"); + $this->docker->executeCommand(self::SALT_PATH, "doil_salt", "salt-key", "-y", "-D"); $this->writer->endBlock(); return Command::SUCCESS; diff --git a/app/src/Commands/Salt/RestartCommand.php b/app/src/Commands/Salt/RestartCommand.php index 9d795518..68300209 100644 --- a/app/src/Commands/Salt/RestartCommand.php +++ b/app/src/Commands/Salt/RestartCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'salt:restart', + description: "Restarts the salt main server." +)] class RestartCommand extends Command { protected const SALT_PATH = "/usr/local/lib/doil/server/salt"; - protected static $defaultName = "salt:restart"; - protected static $defaultDescription = "Restarts the salt main server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } @@ -42,7 +40,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(3); $instances = array_filter($this->docker->getRunningInstanceNames()); foreach ($instances as $instance) { - if ($instance == "doil_saltmain") { + if ($instance == "doil_salt") { continue; } if ( diff --git a/app/src/Commands/Salt/StatesCommand.php b/app/src/Commands/Salt/StatesCommand.php index f682645e..a377e099 100644 --- a/app/src/Commands/Salt/StatesCommand.php +++ b/app/src/Commands/Salt/StatesCommand.php @@ -6,23 +6,21 @@ use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'salt:states', + description: "List all currently available states to apply." +)] class StatesCommand extends Command { protected const PATH_STATES = "/usr/local/share/doil/stack/states"; - protected static $defaultName = "salt:states"; - protected static $defaultDescription = "List all currently available states to apply"; - - protected Filesystem $filesystem; - - public function __construct(Filesystem $filesystem) + public function __construct(protected Filesystem $filesystem) { parent::__construct(); - - $this->filesystem = $filesystem; } diff --git a/app/src/Commands/Salt/UpCommand.php b/app/src/Commands/Salt/UpCommand.php index 3fc1325b..0d7c92b5 100644 --- a/app/src/Commands/Salt/UpCommand.php +++ b/app/src/Commands/Salt/UpCommand.php @@ -7,25 +7,23 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'salt:up', + description: "Starts the salt main server." +)] class UpCommand extends Command { protected const SALT_PATH = "/usr/local/lib/doil/server/salt"; - protected static $defaultName = "salt:up"; - protected static $defaultDescription = "Starts the salt main server"; - - protected Docker $docker; - protected Writer $writer; - - public function __construct(Docker $docker, Writer $writer) - { + public function __construct( + protected Docker $docker, + protected Writer $writer + ) { parent::__construct(); - - $this->docker = $docker; - $this->writer = $writer; } @@ -42,7 +40,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int sleep(3); $instances = array_filter($this->docker->getRunningInstanceNames()); foreach ($instances as $instance) { - if ($instance == "doil_saltmain") { + if ($instance == "doil_salt") { continue; } if ( diff --git a/app/src/Commands/System/UpdateCommand.php b/app/src/Commands/System/UpdateCommand.php new file mode 100644 index 00000000..1c2e1a3a --- /dev/null +++ b/app/src/Commands/System/UpdateCommand.php @@ -0,0 +1,85 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\System; + +use CaT\Doil\Lib\Git\Git; +use CaT\Doil\Lib\Posix\Posix; +use CaT\Doil\Lib\System\Update; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +#[AsCommand( + name: 'system:update', + description: "!NEEDS SUDO PRIVILEGES! This command updates doil on your system." +)] +class UpdateCommand extends Command +{ + protected const DOIL_GIT_REPO = "https://github.com/conceptsandtraining/doil.git"; + + public function __construct( + protected Posix $posix, + protected Filesystem $filesystem, + protected Git $git, + protected Update $update, + protected Writer $writer + ) { + parent::__construct(); + } + + 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; + } + + $version = $this->filesystem->getLineInFile("/usr/local/lib/doil/app/src/App.php", "Doil Version"); + $version = explode(" ", $version)[5]; + + $output->writeln("Current version: {$version}"); + + $tags = $this->git->getTagsFromGithubUrl(self::DOIL_GIT_REPO); + + $tags = array_filter($tags, fn ($tag) => $tag > $version); + + if (count($tags) == 0) { + $output->writeln("Nothing to do. Everything is up to date!"); + return Command::SUCCESS; + } + + $output->writeln("Possible updates"); + foreach ($tags as $tag) { + $output->writeln("\t$tag"); + } + + $question = new ConfirmationQuestion( + "This update will update to the latest available version.\nDo you want to continue the update? [y/N] ", + false + ); + $helper = $this->getHelper('question'); + if (! $helper->ask($input, $output, $question)) { + $this->writer->error( + $output, + "Aborted by user!", + "Please run 'sudo doil system:update' again to continue update." + ); + return Command::FAILURE; + } + + $this->update->run(self::DOIL_GIT_REPO, $tags); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/app/src/Commands/User/AddCommand.php b/app/src/Commands/User/AddCommand.php index 27d05a18..dec692bb 100644 --- a/app/src/Commands/User/AddCommand.php +++ b/app/src/Commands/User/AddCommand.php @@ -11,37 +11,25 @@ use CaT\Doil\Commands\Repo\RepoManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'user:add', + description: "!NEEDS SUDO PRIVILEGES! Adds a user to the doil system." +)] class AddCommand extends Command { - protected static $defaultName = "user:add"; - protected static $defaultDescription = "!NEEDS SUDO PRIVILEGES! Adds a user to the doil system"; - - protected UserManager $user_manager; - protected Posix $posix; - protected Linux $linux; - protected Filesystem $filesystem; - protected Writer $writer; - protected RepoManager $repo_manager; - public function __construct( - UserManager $user_manager, - Posix $posix, - Linux $linux, - Filesystem $filesystem, - Writer $writer, - RepoManager $repo_manager + protected UserManager $user_manager, + protected Posix $posix, + protected Linux $linux, + protected Filesystem $filesystem, + protected Writer $writer, + protected RepoManager $repo_manager ) { parent::__construct(); - - $this->user_manager = $user_manager; - $this->posix = $posix; - $this->linux = $linux; - $this->filesystem = $filesystem; - $this->writer = $writer; - $this->repo_manager = $repo_manager; } public function configure() : void diff --git a/app/src/Commands/User/DeleteCommand.php b/app/src/Commands/User/DeleteCommand.php index 337ebf81..b4f8881b 100644 --- a/app/src/Commands/User/DeleteCommand.php +++ b/app/src/Commands/User/DeleteCommand.php @@ -10,29 +10,25 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Exception\InvalidArgumentException; +#[AsCommand( + name: 'user:delete', + description: "!NEEDS SUDO PRIVILEGES! Deletes a user from the doil system." +)] class DeleteCommand extends Command { - protected static $defaultName = "user:delete"; - protected static $defaultDescription = "!NEEDS SUDO PRIVILEGES! Deletes a user from the doil system"; - - protected UserManager $user_manager; - protected Posix $posix; - protected Linux $linux; - protected Writer $writer; - - public function __construct(UserManager $user_manager, Posix $posix, Linux $linux, Writer $writer) - { + public function __construct( + protected UserManager $user_manager, + protected Posix $posix, + protected Linux $linux, + protected Writer $writer + ) { parent::__construct(); - - $this->user_manager = $user_manager; - $this->posix = $posix; - $this->linux = $linux; - $this->writer = $writer; } public function configure() : void diff --git a/app/src/Commands/User/ListCommand.php b/app/src/Commands/User/ListCommand.php index 8f46f782..11146ce0 100644 --- a/app/src/Commands/User/ListCommand.php +++ b/app/src/Commands/User/ListCommand.php @@ -5,21 +5,19 @@ namespace CaT\Doil\Commands\User; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +#[AsCommand( + name: 'user:list', + description: "Lists all users of the doil system." +)] class ListCommand extends Command { - protected static $defaultName = "user:list"; - protected static $defaultDescription = "Lists all users of the doil system"; - - protected UserManager $user_manager; - - public function __construct(UserManager $user_manager) + public function __construct(protected UserManager $user_manager) { parent::__construct(); - - $this->user_manager = $user_manager; } public function execute(InputInterface $input, OutputInterface $output) : int diff --git a/app/src/Lib/Config/Config.php b/app/src/Lib/Config/Config.php new file mode 100644 index 00000000..d7cc3c6c --- /dev/null +++ b/app/src/Lib/Config/Config.php @@ -0,0 +1,205 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Lib\Config; + +class Config +{ + public function __construct( + protected string $host = "doil", + protected array $allowed_hosts = [], + protected bool $https_proxy = false, + protected string $mail_password = "ilias", + protected bool $keycloak_enabled = false, + protected string $keycloak_hostname = "http://doil/keycloak", + protected string $keycloak_new_admin_password = "admin", + protected string $keycloak_old_admin_password = "admin", + protected string $keycloak_db_username = "admin", + protected string $keycloak_db_password = "admin", + protected string $update_token = "", + protected string $git_private_ssh_key_path = "", + protected string $git_public_ssh_key_path = "", + ) {} + + public function getHost() : string + { + return $this->host; + } + + public function withHost(string $host) : Config + { + $clone = clone $this; + $clone->host = $host; + return $clone; + } + + public function getAllowedHosts() : array + { + return $this->allowed_hosts; + } + + public function withAllowedHosts(array $allowed_hosts) : Config + { + $clone = clone $this; + $clone->allowed_hosts = $allowed_hosts; + return $clone; + } + + public function getHttpsProxy() : bool + { + return $this->https_proxy; + } + + public function withHttpsProxy(bool $https_proxy) : Config + { + $clone = clone $this; + $clone->https_proxy = $https_proxy; + return $clone; + } + + public function getMailPassword() : string + { + return $this->mail_password; + } + + public function withMailPassword(string $mail_password) : Config + { + $clone = clone $this; + $clone->mail_password = $mail_password; + return $clone; + } + + public function isKeycloakEnabled() : bool + { + return $this->keycloak_enabled; + } + + public function withEnableKeycloak(bool $keycloak_enabled) : Config + { + $clone = clone $this; + $clone->keycloak_enabled = $keycloak_enabled; + return $clone; + } + + public function getKeycloakHostname() : string + { + return $this->keycloak_hostname; + } + + public function withKeycloakHostname(string $keycloak_hostname) : Config + { + $clone = clone $this; + $clone->keycloak_hostname = $keycloak_hostname; + return $clone; + } + + public function getKeycloakNewAdminPassword() : string + { + return $this->keycloak_new_admin_password; + } + + public function withKeycloakNewAdminPassword(string $keycloak_new_admin_password) : Config + { + $clone = clone $this; + $clone->keycloak_new_admin_password = $keycloak_new_admin_password; + return $clone; + } + + public function getKeycloakOldAdminPassword() : string + { + return $this->keycloak_old_admin_password; + } + + public function withKeycloakOldAdminPassword(string $keycloak_old_admin_password) : Config + { + $clone = clone $this; + $clone->keycloak_old_admin_password = $keycloak_old_admin_password; + return $clone; + } + + public function getKeycloakDbUsername() : string + { + return $this->keycloak_db_username; + } + + public function withKeycloakDbUsername(string $keycloak_db_username) : Config + { + $clone = clone $this; + $clone->keycloak_db_username = $keycloak_db_username; + return $clone; + } + + public function getKeycloakDbPassword() : string + { + return $this->keycloak_db_password; + } + + public function withKeycloakDbPassword(string $keycloak_db_password) : Config + { + $clone = clone $this; + $clone->keycloak_db_password = $keycloak_db_password; + return $clone; + } + + public function getUpdateToken() : string + { + return $this->update_token; + } + + public function withUpdateToken(string $update_token) : Config + { + $clone = clone $this; + $clone->update_token = $update_token; + return $clone; + } + + public function getGitPrivateSSHKeyPath() : string + { + return $this->git_private_ssh_key_path; + } + + public function withGitPrivateSSHKeyPath(string $git_private_ssh_key_path) : Config + { + $clone = clone $this; + $clone->git_private_ssh_key_path = $git_private_ssh_key_path; + return $clone; + } + + public function getGitPublicSSHKeyPath() : string + { + return $this->git_public_ssh_key_path; + } + + public function withGitPublicSSHKeyPath(string $git_public_ssh_key_path) : Config + { + $clone = clone $this; + $clone->git_public_ssh_key_path = $git_public_ssh_key_path; + return $clone; + } + + public function __toString() : string + { + $allowed_hosts = implode(",", $this->allowed_hosts); + $https_proxy = var_export($this->https_proxy, true); + $keycloak_enabled = var_export($this->keycloak_enabled, true); + + return <<host +allowed_hosts=$allowed_hosts +https_proxy=$https_proxy +mail_password=$this->mail_password +keycloak_enabled=$keycloak_enabled +keycloak_hostname=$this->keycloak_hostname +keycloak_new_admin_password=$this->keycloak_new_admin_password +keycloak_old_admin_password=$this->keycloak_old_admin_password +keycloak_db_username=$this->keycloak_db_username +keycloak_db_password=$this->keycloak_db_password +update_token=$this->update_token +git_private_ssh_key_path=$this->git_private_ssh_key_path +git_public_ssh_key_path=$this->git_public_ssh_key_path +DOC; + } +} \ No newline at end of file diff --git a/app/src/Lib/Config/ConfigChecker.php b/app/src/Lib/Config/ConfigChecker.php new file mode 100644 index 00000000..bb25000e --- /dev/null +++ b/app/src/Lib/Config/ConfigChecker.php @@ -0,0 +1,80 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Lib\Config; + +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Filesystem\Exception\FileNotFoundException; + +class ConfigChecker +{ + public function __construct( + protected Filesystem $filesystem + ) {} + + public function check(Config $config) : void + { + if ($config->getHost() == '') { + throw new \InvalidArgumentException('Host cannot be empty.'); + } + + if (!is_array($config->getAllowedHosts())) { + throw new \InvalidArgumentException('AllowedHosts must be an array.'); + } + + if (!is_bool($config->getHttpsProxy())) { + throw new \InvalidArgumentException('HttpsProxy must be a boolean.'); + } + + if ($config->getMailPassword() == '') { + throw new \InvalidArgumentException('Mail password cannot be empty.'); + } + + if (!is_bool($config->isKeycloakEnabled())) { + throw new \InvalidArgumentException('KeycloakEnabled must be a boolean.'); + } + + if ($config->getKeycloakHostname() == '') { + throw new \InvalidArgumentException('KeycloakHostname cannot be empty.'); + } + + if ($config->getKeycloakNewAdminPassword() == '') { + throw new \InvalidArgumentException('KeycloakNewAdminPassword cannot be empty.'); + } + + if ($config->getKeycloakOldAdminPassword() == '') { + throw new \InvalidArgumentException('KeycloakOldAdminPassword cannot be empty.'); + } + + if ($config->getKeycloakDbUsername() == '') { + throw new \InvalidArgumentException('KeycloakDbUsername cannot be empty.'); + } + + if ($config->getKeycloakDbPassword() == '') { + throw new \InvalidArgumentException('KeycloakDbPassword cannot be empty.'); + } + + if (!is_string($config->getUpdateToken())) { + throw new \InvalidArgumentException('UpdateToken must be a string.'); + } + + if ($config->getGitPrivateSSHKeyPath() == '') { + throw new \InvalidArgumentException('GitPrivateSSHKeyPath cannot be empty.'); + } + + if ($config->getGitPublicSSHKeyPath() == '') { + throw new \InvalidArgumentException('GitPublicSSHKeyPath cannot be empty.'); + } + + if (! $this->filesystem->exists($config->getGitPrivateSSHKeyPath())) { + throw new FileNotFoundException("Cannot locate GitPrivateSSHKey."); + } + + if (! $this->filesystem->exists($config->getGitPublicSSHKeyPath())) { + throw new FileNotFoundException("Cannot locate GitPublicSSHKey."); + } + } +} \ No newline at end of file diff --git a/app/src/Lib/Config/ConfigReader.php b/app/src/Lib/Config/ConfigReader.php new file mode 100644 index 00000000..ab8e2dfe --- /dev/null +++ b/app/src/Lib/Config/ConfigReader.php @@ -0,0 +1,61 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Lib\Config; + +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Filesystem\Exception\FileNotFoundException; + +class ConfigReader +{ + protected const CONFIG_PATH = "/etc/doil"; + + public function __construct( + protected Config $config, + protected Filesystem $filesystem, + ) {} + + /** + * @throws FileNotFoundException + */ + public function getConfig(): Config + { + if (!$this->filesystem->exists(self::CONFIG_PATH . "/doil.conf")) { + throw new FileNotFoundException("Config file not found at: " . self::CONFIG_PATH . "/doil.conf"); + } + + $ini = $this->filesystem->parseIniFile(self::CONFIG_PATH . "/doil.conf"); + + $this->config = $this->config + ->withHost($ini["host"]) + ->withAllowedHosts(explode(",", $ini["allowed_hosts"])) + ->withHttpsProxy($ini["https_proxy"]) + ->withMailPassword($ini["mail_password"]) + ->withEnableKeycloak($ini["keycloak_enabled"]) + ->withKeycloakHostname($ini["keycloak_hostname"]) + ->withKeycloakNewAdminPassword($ini["keycloak_new_admin_password"]) + ->withKeycloakOldAdminPassword($ini["keycloak_old_admin_password"]) + ->withKeycloakDbUsername($ini["keycloak_db_username"]) + ->withKeycloakDbPassword($ini["keycloak_db_password"]) + ->withUpdateToken($ini["update_token"]) + ->withGitPrivateSSHKeyPath($ini["git_private_ssh_key_path"]) + ->withGitPublicSSHKeyPath($ini["git_public_ssh_key_path"]) + ; + + return $this->config; + } + + public function writeToFile() : bool + { + $this->filesystem->makeDirectoryRecursive(self::CONFIG_PATH); + if (file_put_contents(self::CONFIG_PATH."/doil.conf~", $this->config, 0, null) !== false) { + return rename(self::CONFIG_PATH . "/doil.conf~", self::CONFIG_PATH . "/doil.conf", null); + } + + @unlink(self::CONFIG_PATH."/doil.conf~"); + return false; + } +} \ No newline at end of file diff --git a/app/src/Lib/ConsoleOutput/SetupWriter.php b/app/src/Lib/ConsoleOutput/SetupWriter.php new file mode 100644 index 00000000..4bfd9c6d --- /dev/null +++ b/app/src/Lib/ConsoleOutput/SetupWriter.php @@ -0,0 +1,35 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Lib\ConsoleOutput; + +use Symfony\Component\Console\Output\OutputInterface; + +class SetupWriter implements Writer +{ + protected array $blocks = []; + protected array $section = []; + + public function beginBlock(OutputInterface $output, string $txt) : void + { + $section = $output->section(); + $section->writeln($txt . " ..."); + $this->blocks[] = $txt; + $this->section[] = $section; + } + + public function endBlock() : void + { + $txt = array_pop($this->blocks); + $section = array_pop($this->section); + $section->overwrite($txt . " ... done"); + } + + public function error(OutputInterface $output, string $msg, string $hint = "") : void + { + $output->writeln("Error:"); + $output->writeln("\t" . $msg); + $output->writeln("\t" . $hint); + } +} \ No newline at end of file diff --git a/app/src/Lib/Docker/Docker.php b/app/src/Lib/Docker/Docker.php index b50cf499..0d0280f7 100644 --- a/app/src/Lib/Docker/Docker.php +++ b/app/src/Lib/Docker/Docker.php @@ -10,6 +10,7 @@ public function startContainerByDockerCompose(string $path) : void; public function stopContainerByDockerCompose(string $path) : void; public function ps() : array; public function getRunningInstanceNames() : array; + public function getAllInstanceNames() : array; public function loginIntoContainer(string $path, string $name) : void; public function isInstanceUp(string $path) : bool; public function executeCommand(string $path, string $name, ...$command) : void; @@ -17,6 +18,7 @@ public function executeBashCommandInsideContainer(string $name, ?string $working public function hasVolume(string $name) : bool; public function removeVolume(string $name) : void; public function getImageIdsByName(string $name) : array; + public function getDoilRelatedImageIdsByPattern(string $pattern) : array; public function removeImage(string $id) : void; /** @@ -32,11 +34,13 @@ public function pull(string $name, string $tag) : void; public function build(string $path, string $name) : void; public function runContainer(string $name) : void; public function stop(string $name) : void; + public function kill(string $name) : void; public function removeContainer(string $name) : void; public function executeDockerCommand(string $name, string $cmd) : void; public function executeDockerCommandWithReturn(string $name, string $cmd) : string; public function setGrain(string $name, string $key, string $value) : void; public function refreshGrains(string $name) : void; public function deleteInstances(array $instances) : void; - public function pruneNetworks() : void; + public function getNetworksByPattern(string $pattern) : array; + public function removeNetwork(string $id) : void; } \ No newline at end of file diff --git a/app/src/Lib/Docker/DockerShell.php b/app/src/Lib/Docker/DockerShell.php index f97738e3..6c2c7a76 100644 --- a/app/src/Lib/Docker/DockerShell.php +++ b/app/src/Lib/Docker/DockerShell.php @@ -8,6 +8,7 @@ use CaT\Doil\Lib\SymfonyShell; use CaT\Doil\Lib\Logger\LoggerFactory; use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Process\Exception\ProcessFailedException; class DockerShell implements Docker { @@ -18,12 +19,11 @@ class DockerShell implements Docker protected const PROXY = "/usr/local/lib/doil/server/proxy"; protected const MAIL = "/usr/local/lib/doil/server/mail"; - public function __construct(LoggerFactory $logger, Posix $posix, Filesystem $filesystem) - { - $this->logger = $logger; - $this->posix = $posix; - $this->filesystem = $filesystem; - } + public function __construct( + protected LoggerFactory $logger, + protected Posix $posix, + protected Filesystem $filesystem + ) {} protected array $systems = [ self::SALT, @@ -72,6 +72,9 @@ public function startContainerByDockerCompose(string $path) : void $this->populateProxy(); } + /** + * @throws ProcessFailedException + */ public function stopContainerByDockerCompose(string $path) : void { $cmd = [ @@ -91,6 +94,9 @@ public function stopContainerByDockerCompose(string $path) : void } } + /** + * @throws ProcessFailedException + */ public function ps() : array { $cmd = [ @@ -104,6 +110,25 @@ public function ps() : array return explode("\n", $this->run($cmd, $logger)); } + /** + * @throws ProcessFailedException + */ + public function getAllInstanceNames() : array + { + $cmd = [ + "docker", + "ps", + "-a", + "--format", + "{{.Names}}" + ]; + $logger = $this->logger->getDoilLogger("DOCKER"); + return explode("\n", $this->run($cmd, $logger)); + } + + /** + * @throws ProcessFailedException + */ public function getRunningInstanceNames() : array { $cmd = [ @@ -118,6 +143,9 @@ public function getRunningInstanceNames() : array return explode("\n", $this->run($cmd, $logger)); } + /** + * @throws ProcessFailedException + */ public function loginIntoContainer(string $path, string $name) : void { $cmd = [ @@ -137,6 +165,9 @@ public function loginIntoContainer(string $path, string $name) : void $this->runTTY($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function isInstanceUp(string $path) : bool { $cmd = [ @@ -151,6 +182,9 @@ public function isInstanceUp(string $path) : bool return $this->run($cmd, $logger) != ""; } + /** + * @throws ProcessFailedException + */ public function executeCommand(string $path, string $name, ...$command) : void { $cmd = [ @@ -170,6 +204,9 @@ public function executeCommand(string $path, string $name, ...$command) : void $this->runTTY($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function executeNoTTYCommand(string $path, string $name, ...$command) : void { $cmd = [ @@ -190,6 +227,9 @@ public function executeNoTTYCommand(string $path, string $name, ...$command) : v $this->runNoTTYNoReturn($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function executeBashCommandInsideContainer(string $name, ?string $working_dir, string ...$command) : void { $wd = "/"; @@ -216,6 +256,9 @@ public function executeBashCommandInsideContainer(string $name, ?string $working $this->runTTY($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function hasVolume(string $name) : bool { $cmd = [ @@ -235,6 +278,27 @@ public function hasVolume(string $name) : bool return $result != ""; } + /** + * @throws ProcessFailedException + */ + public function getVolumesByPattern(string $pattern) : array + { + $cmd = [ + "docker", + "volume", + "ls", + "-q", + "--filter", + "name={$pattern}" + ]; + + $logger = $this->logger->getDoilLogger("DOCKER"); + return explode("\n", $this->run($cmd, $logger)); + } + + /** + * @throws ProcessFailedException + */ public function removeVolume(string $name) : void { $cmd = [ @@ -250,6 +314,9 @@ public function removeVolume(string $name) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function getImageIdsByName(string $name) : array { $cmd = [ @@ -264,6 +331,26 @@ public function getImageIdsByName(string $name) : array return explode("\n", $this->run($cmd, $logger)); } + /** + * @throws ProcessFailedException + */ + public function getDoilRelatedImageIdsByPattern(string $pattern) : array + { + $cmd = [ + "docker", + "images", + "-q", + "--filter", + "reference={$pattern}", + ]; + + $logger = $this->logger->getDoilLogger("DOCKER"); + return explode("\n", $this->run($cmd, $logger)); + } + + /** + * @throws ProcessFailedException + */ public function removeImage(string $id) : void { $cmd = [ @@ -280,13 +367,16 @@ public function removeImage(string $id) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function getSaltAcceptedKeys() : array { $cmd = [ "docker", "exec", "-t", - "doil_saltmain", + "doil_salt", "bash", "-c", "salt-key -L --out json" @@ -298,13 +388,16 @@ public function getSaltAcceptedKeys() : array return $keys; } + /** + * @throws ProcessFailedException + */ public function getShadowHashForInstance(string $name, string $password) : string { $cmd = [ "docker", "exec", "-i", - "doil_saltmain", + "doil_salt", "bash", "-c", "salt \"$name\" shadow.gen_password \"$password\" --out txt" @@ -316,13 +409,16 @@ public function getShadowHashForInstance(string $name, string $password) : strin return trim($result[1]); } + /** + * @throws ProcessFailedException + */ public function applyState(string $name, string $state) : void { $cmd = [ "docker", "exec", "-i", - "doil_saltmain", + "doil_salt", "bash", "-c", "salt \"$name\" state.highstate saltenv=$state" @@ -334,6 +430,9 @@ public function applyState(string $name, string $state) : void $logger->info($result); } + /** + * @throws ProcessFailedException + */ public function commit(string $instance_name, ?string $image_name = null) : void { if (is_null($image_name)) { @@ -352,6 +451,9 @@ public function commit(string $instance_name, ?string $image_name = null) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function copy(string $instance_name, string $from, string $to) : void { $cmd = [ @@ -366,6 +468,9 @@ public function copy(string $instance_name, string $from, string $to) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function listContainerDirectory(string $container_name, string $path) : array { $cmd = [ @@ -382,6 +487,9 @@ public function listContainerDirectory(string $container_name, string $path) : a return explode("\n", trim($this->run($cmd, $logger))); } + /** + * @throws ProcessFailedException + */ public function pull(string $name, string $tag) : void { $cmd = [ @@ -395,6 +503,9 @@ public function pull(string $name, string $tag) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function build(string $path, string $name) : void { $cmd = [ @@ -411,6 +522,9 @@ public function build(string $path, string $name) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function runContainer(string $name) : void { $cmd = [ @@ -427,6 +541,9 @@ public function runContainer(string $name) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function stop(string $name) : void { $cmd = [ @@ -440,6 +557,25 @@ public function stop(string $name) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ + public function kill(string $name) : void + { + $cmd = [ + "docker", + "kill", + $name + ]; + + $logger = $this->logger->getDoilLogger($name); + $logger->info("Kill instance"); + $this->run($cmd, $logger); + } + + /** + * @throws ProcessFailedException + */ public function removeContainer(string $name) : void { $cmd = [ @@ -454,6 +590,9 @@ public function removeContainer(string $name) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function executeDockerCommand(string $name, string $cmd) : void { $cmd = [ @@ -471,6 +610,9 @@ public function executeDockerCommand(string $name, string $cmd) : void $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function executeDockerCommandWithReturn(string $name, string $cmd) : string { $cmd = [ @@ -488,13 +630,16 @@ public function executeDockerCommandWithReturn(string $name, string $cmd) : stri return $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function setGrain(string $name, string $key, string $value) : void { $cmd = [ "docker", "exec", "-d", - "doil_saltmain", + "doil_salt", "bash", "-c", "salt \"$name\" grains.setval \"$key\" \"$value\"" @@ -505,13 +650,16 @@ public function setGrain(string $name, string $key, string $value) : void $this->runTTY($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function refreshGrains(string $name) : void { $cmd = [ "docker", "exec", "-d", - "doil_saltmain", + "doil_salt", "bash", "-c", "salt \"$name\" saltutil.refresh_grains" @@ -522,6 +670,9 @@ public function refreshGrains(string $name) : void $this->runTTY($cmd, $logger); } + /** + * @throws ProcessFailedException + */ public function deleteInstances(array $instances) : void { foreach ($instances as $instance) { @@ -535,45 +686,59 @@ public function deleteInstances(array $instances) : void } } - public function pruneNetworks() : void + /** + * @throws ProcessFailedException + */ + public function getNetworksByPattern(string $pattern) : array { $cmd = [ "docker", "network", - "prune", - "-f" + "ls", + "-q", + "--filter", + "name={$pattern}" ]; $logger = $this->logger->getDoilLogger("DOCKER"); - $logger->info("Prune network"); - $this->run($cmd, $logger); + return explode("\n", $this->run($cmd, $logger)); } - protected function getImageNameByInstance(string $instance) : string + /** + * @throws ProcessFailedException + */ + public function removeNetwork(string $id) : void { $cmd = [ "docker", - "inspect", - $instance, - "--format={{.Config.Image}}" + "network", + "rm", + $id ]; $logger = $this->logger->getDoilLogger("DOCKER"); - return $this->run($cmd, $logger); + $this->run($cmd, $logger); } - protected function kill(string $name) : void + /** + * @throws ProcessFailedException + */ + public function getImageNameByInstance(string $instance) : string { $cmd = [ "docker", - "kill", - $name + "inspect", + $instance, + "--format={{.Config.Image}}" ]; - $logger = $this->logger->getDoilLogger($name); - $this->run($cmd, $logger); + $logger = $this->logger->getDoilLogger("DOCKER"); + return $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ protected function startDoilSystemsIfNeeded() : void { if (! $this->isInstanceUp(self::SALT)) { @@ -595,6 +760,9 @@ protected function startDoilSystemsIfNeeded() : void } } + /** + * @throws ProcessFailedException + */ protected function startContainerByDockerComposeWithForceRecreate(string $path) : void { $cmd = [ @@ -612,6 +780,9 @@ protected function startContainerByDockerComposeWithForceRecreate(string $path) $this->run($cmd, $logger); } + /** + * @throws ProcessFailedException + */ protected function populateProxy() : void { $this->executeDockerCommand( @@ -655,6 +826,9 @@ protected function getSaltIpByName(string $name) : string )); } + /** + * @throws ProcessFailedException + */ protected function cleanupProxy(string $path) : void { $name = basename($path); @@ -663,4 +837,38 @@ protected function cleanupProxy(string $path) : void "rm -f /etc/nginx/conf.d/sites/$name.conf && /root/generate_index_html.sh" ); } + + /** + * @throws ProcessFailedException + */ + public function getDoilRelatedContainersNames() : array + { + $cmd = [ + "docker", + "ps", + "--filter", + "name=_local", + "--filter", + "name=_global", + "--filter", + "name=doil_", + "--format={{.Names}}", + ]; + $logger = $this->logger->getDoilLogger("DOCKER"); + $instances = explode("\n", $this->run($cmd, $logger)); + return array_filter($instances); + } + + public function pruneImages() : void + { + $cmd = [ + "docker", + "image", + "prune", + "-a", + "-f" + ]; + $logger = $this->logger->getDoilLogger("DOCKER"); + $this->run($cmd, $logger); + } } \ No newline at end of file diff --git a/app/src/Lib/FileSystem/Filesystem.php b/app/src/Lib/FileSystem/Filesystem.php index f8b639e2..5838b95c 100644 --- a/app/src/Lib/FileSystem/Filesystem.php +++ b/app/src/Lib/FileSystem/Filesystem.php @@ -15,17 +15,18 @@ public function exists(string $path) : bool; public function getFilesInPath(string $path) : array; public function remove(string $path) : void; public function hasWriteAccess(string $path) : bool; - public function makeDirectoryRecursive(string $path) : void; + public function makeDirectoryRecursive(string $path) : bool; public function copy(string $from, string $to) : void; public function copyDirectory(string $from, string $to) : void; - public function chownRecursive(string $path, string $owner, string $group) : void; - public function chmod(string $path, int $mode, bool $recursive) : void; + public function chownRecursive(string $path, int|string $owner, int|string $group) : void; + public function chmod(string $path, int $mode, bool $recursive = false) : void; public function chmodDirsOnly(string $path, int $mode) : void; public function symlink(string $from, string $to) : void; - public function readLink(string $path) : string; + public function readLink(string $path) : bool|string; public function zip(string $name) : void; public function unzip(string $from, string $to) : void; public function searchForFileRecursive(string $path, string $pattern) : ?string; + public function searchForFilesRecursive(string $path, string $pattern) : array; public function replaceStringInFile(string $path, string $needle, string $substitute) : void; public function replaceStringInJsonFile(string $path, array $keys, string $substitute) : void; public function replaceLineInFile(string $path, string $needle, string $substitute) : void; @@ -34,7 +35,9 @@ public function saveToJsonFile(string $path, array $objects) : void; public function readFromJsonFile(string $path) : array; public function grepMysqlPasswordFromFile(string $path) : string; public function addToGitConfig(string $path, string $section, string $line) : void; - public function parseIniFile(string $path) : array; + public function parseIniFile(string $path,int $scanner_type = INI_SCANNER_TYPED) : array; public function getContent(string $path) : string; public function find_dirs(string $path, string $name, int $depth = 0) : array; + public function setContent(string $path, string $content, bool $append = false) : int|bool; + public function touch(string $path) : void; } \ No newline at end of file diff --git a/app/src/Lib/FileSystem/FilesystemShell.php b/app/src/Lib/FileSystem/FilesystemShell.php index 776e4d0b..196a54a7 100644 --- a/app/src/Lib/FileSystem/FilesystemShell.php +++ b/app/src/Lib/FileSystem/FilesystemShell.php @@ -7,8 +7,10 @@ use ZipArchive; use SplFileInfo; use RegexIterator; +use FilesystemIterator; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; +use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem as SymfonyFileSystem; class FilesystemShell implements Filesystem @@ -45,6 +47,9 @@ public function getFilesInPath(string $path) : array return array_values(array_diff(scandir($path), ['.', '..'])); } + /** + * @throws IOException + */ public function remove(string $path) : void { if(file_exists($path)){ @@ -57,12 +62,12 @@ public function hasWriteAccess(string $path) : bool return is_writable($path); } - public function makeDirectoryRecursive(string $path) : void + public function makeDirectoryRecursive(string $path) : bool { if ($this->exists($path)) { - return; + return true; } - mkdir($path, 0777, true); + return mkdir($path, 0775, true); } public function copy(string $from, string $to) : void @@ -75,7 +80,10 @@ public function copyDirectory(string $from, string $to) : void $this->symfony_file_system->mirror($from, $to); } - public function chownRecursive(string $path, string $owner, string $group) : void + /** + * @throws IOException + */ + public function chownRecursive(string $path, int|string $owner, int|string $group) : void { $this->symfony_file_system->chown($path, $owner, true); $this->symfony_file_system->chgrp($path, $group, true); @@ -105,7 +113,7 @@ public function symlink(string $from, string $to) : void $this->symfony_file_system->symlink($from, $to); } - public function readLink(string $path) : string + public function readLink(string $path) : bool|string { return readlink($path); } @@ -169,6 +177,20 @@ public function searchForFileRecursive(string $path, string $pattern) : ?string return null; } + public function searchForFilesRecursive(string $path, string $pattern) : array + { + $dir = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS); + $ite = new RecursiveIteratorIterator($dir); + $files = new RegexIterator($ite, $pattern, RegexIterator::MATCH); + + $result = []; + foreach ($files as $file) { + $result[] = $file->getPathname(); + } + + return $result; + } + public function replaceStringInFile(string $path, string $needle, string $substitute) : void { $data = file($path); @@ -248,9 +270,9 @@ public function addToGitConfig(string $path, string $section, string $line) : vo $this->symfony_file_system->appendToFile($path, "\t" . $line . "\n"); } - public function parseIniFile(string $path) : array + public function parseIniFile(string $path, int $scanner_type = INI_SCANNER_TYPED) : array { - return parse_ini_file($path, false, INI_SCANNER_TYPED); + return parse_ini_file($path, false, $scanner_type); } public function getContent(string $path) : string @@ -265,4 +287,20 @@ public function find_dirs(string $path, string $name, int $depth = 0) : array return $output; } + + /** + * @throws IOException + */ + public function touch(string $path) : void + { + $this->symfony_file_system->touch($path); + } + + public function setContent(string $path, string $content, bool $append = false) : int|bool + { + if ($append) { + return file_put_contents($path, $content, FILE_APPEND); + } + return file_put_contents($path, $content); + } } \ No newline at end of file diff --git a/app/src/Lib/Git/Git.php b/app/src/Lib/Git/Git.php index 8237cdb4..31da747b 100644 --- a/app/src/Lib/Git/Git.php +++ b/app/src/Lib/Git/Git.php @@ -9,8 +9,11 @@ interface Git public function getBranches(string $path) : array; public function getCurrentBranch(string $path) : string; public function fetchBare(string $path) : void; + public function clone(string $url, string $path) : void; public function cloneBare(string $url, string $path) : void; public function setLocalConfig(string $path, ...$commands) : void; public function checkoutRemote(string $path, string $branch) : void; public function getRemotes(string $path) : array; + public function getTagsFromGithubUrl(string $url) : array; + public function setGlobalSafeDirectory(string $path) : void; } \ No newline at end of file diff --git a/app/src/Lib/Git/GitShell.php b/app/src/Lib/Git/GitShell.php index bd3cc7bb..7854a0b9 100644 --- a/app/src/Lib/Git/GitShell.php +++ b/app/src/Lib/Git/GitShell.php @@ -60,6 +60,32 @@ public function fetchBare(string $path) : void $this->run($cmd, $this->logger); } + public function clone(string $url, string $path) : void + { + $cmd = [ + "git", + "clone", + $url, + $path + ]; + + $this->logger->info("Clone from url '$url' to path '$path'"); + $this->run($cmd, $this->logger); + } + + public function status(string $path) : string + { + $cmd = [ + "git", + "-C", + $path, + "status" + ]; + + $this->logger->info("Git status from path '$path'"); + return $this->run($cmd, $this->logger); + } + public function cloneBare(string $url, string $path) : void { $cmd = [ @@ -126,4 +152,47 @@ public function getRemotes(string $path) : array return $arr; } + + public function getTagsFromGithubUrl(string $url) : array + { + $cmd = [ + "git", + "ls-remote", + "--tags", + $url + ]; + + $this->logger->info("Get tags by url '$url'"); + $temp = $this->run($cmd, $this->logger); + $temp = explode("\n", $temp); + array_pop($temp); + + $result = []; + foreach ($temp as $t) { + $t = explode("/", $t); + $t = array_pop($t); + if (str_contains($t, ".")) { + continue; + } + $result[] = $t; + } + + natsort($result); + return $result; + } + + public function setGlobalSafeDirectory(string $path) : void + { + $cmd = [ + "git", + "config", + "--global", + "--add", + "safe.directory", + $path + ]; + + $this->logger->info("Add global safe directory for path '$path'"); + $this->run($cmd, $this->logger); + } } \ No newline at end of file diff --git a/app/src/Lib/Logger/LoggerFactory.php b/app/src/Lib/Logger/LoggerFactory.php index 6170de1d..c46c0770 100644 --- a/app/src/Lib/Logger/LoggerFactory.php +++ b/app/src/Lib/Logger/LoggerFactory.php @@ -11,9 +11,24 @@ class LoggerFactory { + protected const SETUP_LOG_PATH = "/var/log/doil/setup.log"; protected const DOIL_LOG_PATH = "/var/log/doil/doil.log"; protected const SALT_LOG_PATH = "/var/log/doil/salt.log"; + /** + * @throws \InvalidArgumentException + */ + public function getSetupLogger(string $channel) : LoggerInterface + { + $logger = new Logger($channel); + $stream = new StreamHandler(self::SETUP_LOG_PATH, Logger::DEBUG, true, 0777); + $form = new LineFormatter(null,null,true,false,true); + $form->setJsonPrettyPrint(true); + $stream->setFormatter($form); + $logger->pushHandler($stream); + return $logger; + } + public function getDoilLogger(string $channel) : LoggerInterface { $logger = new Logger($channel); diff --git a/app/src/Lib/System/Update.php b/app/src/Lib/System/Update.php new file mode 100644 index 00000000..2e6a4dc8 --- /dev/null +++ b/app/src/Lib/System/Update.php @@ -0,0 +1,204 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Lib\System; + +use CaT\Doil\Lib\Git\Git; +use Psr\Log\LoggerInterface; +use CaT\Doil\Lib\Posix\Posix; +use CaT\Doil\Lib\Docker\Docker; +use CaT\Doil\Setup\Server\Salt; +use CaT\Doil\Setup\Server\Mail; +use CaT\Doil\Lib\Config\Config; +use CaT\Doil\Setup\Server\Proxy; +use CaT\Doil\Setup\CopyFiles\Copy; +use CaT\Doil\Setup\Server\Keycloak; +use CaT\Doil\Lib\Config\ConfigReader; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use CaT\Doil\Lib\Config\ConfigChecker; +use CaT\Doil\Lib\Logger\LoggerFactory; +use CaT\Doil\Lib\FileSystem\Filesystem; +use CaT\Doil\Setup\Server\StartServers; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Console\Output\ConsoleOutputInterface; + +class Update +{ + protected const DOIL_TARGET_DIR = "/tmp/doil"; + protected const GLOBAL_SAFE_DIRECTORY = "/usr/local/share/doil/repositories/*"; + protected const COMPOSER_LOCK = "/usr/local/lib/doil/app/composer.lock"; + protected const BUILD_FILE_NAME = "build_php_image.sh"; + protected const UPDATE_SCRIPT = "shell_update_steps.sh"; + + protected int $user_id; + protected string $home_dir; + + public function __construct( + protected LoggerFactory $loggerFactory, + protected ConsoleOutputInterface $output, + protected InputInterface $input, + protected Writer $writer, + protected Git $git, + protected Filesystem $filesystem, + protected ConfigReader $configReader, + protected ConfigChecker $config_checker, + protected Copy $copy, + protected Docker $docker, + protected Posix $posix, + protected Salt $salt, + protected Proxy $proxy, + protected Mail $mail, + protected Keycloak $keycloak, + protected StartServers $start_servers + ) { + $this->user_id = $this->posix->getUserId(); + $this->home_dir = $this->posix->getHomeDirectory($this->user_id); + } + + public function run(string $repo, array $tags): void + { + $logger = $this->loggerFactory->getDoilLogger("UPDATE"); + + $this->git->clone($repo, self::DOIL_TARGET_DIR); + + $update_conf = $this->filesystem->parseIniFile(self::DOIL_TARGET_DIR . "/Update/update.conf"); + $full_update = $update_conf["full_update"]; + $php_container_update = $update_conf["php_container_update"]; + + try { + $config = $this->configReader->getConfig(); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'sudo doil system:update' again." + ); + $logger->error($e->getTraceAsString()); + return; + } + + $this->writer->beginBlock($this->output, "Checking doil config file"); + try { + $this->config_checker->check($config); + } catch (\InvalidArgumentException $e) { + $this->writer->error( + $this->output, + "Cannot read config file!\n\t" . $e->getMessage(), + "If the problem is fixed, run 'sudo doil system:update' again." + ); + return; + } + $this->writer->endBlock(); + + if (!$this->filesystem->exists($this->home_dir . "/" . self::BUILD_FILE_NAME)) { + foreach ($tags as $tag) { + $this->git->checkoutRemote(self::DOIL_TARGET_DIR, $tag); + $this->copyDoil($logger, $config); + } + + if (!$full_update) { + $this->writer->beginBlock($this->output, "Executing additional shell script"); + $this->executeUpdateScript(); + $this->writer->endBlock(); + $this->output->writeln("Your doil installation is up to date."); + return; + } + + $this->removeDoilContainers(); + $this->git->setGlobalSafeDirectory(self::GLOBAL_SAFE_DIRECTORY); + if ($this->filesystem->exists(self::COMPOSER_LOCK)) { + $this->filesystem->remove(self::COMPOSER_LOCK); + } + + if ($php_container_update) { + $this->generatePHPImageScript(); + $this->output->writeln("\n\tDOIL needs your help!"); + $this->output->writeln("\n\tDoil tries to use as few dependencies as possible.\n\tTherefore, a PHP container is started with every Doil request.\n\tUpdates also run through this container. Since the running container\n\tcannot update itself, that's where you come in."); + $this->output->writeln("\n\tDoil has created the script 'build_php_image.sh' in your home\n\tfolder. Please run this script as sudo and restart the update.\n\tIMPORTANT: Do not delete the script!\n\n\tThanks, you rock!"); + return; + } + + } + + $this->filesystem->remove($this->home_dir . "/" . self::BUILD_FILE_NAME); + + $this->writer->beginBlock($this->output, "Starting doil system containers"); + $this->start_servers->run($config, $logger); + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Executing additional shell script"); + $this->executeUpdateScript(); + $this->writer->endBlock(); + + $this->output->writeln("\nThanks for using doil, you rock!"); + } + + protected function copyDoil(LoggerInterface $logger, Config $config): void + { + $this->writer->beginBlock($this->output, "Copying doil files"); + try { + $this->copy->copyDoil(self::DOIL_TARGET_DIR, $config); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'sudo doil system:update' again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + } + + protected function removeDoilContainers(): void + { + $doil_related_containers = $this->docker->getDoilRelatedContainersNames(); + $doil_system_containers = array_filter( + $doil_related_containers, + fn ($container) => str_contains($container, "doil_") + ); + + foreach ($doil_related_containers as $doil_related_container) { + $this->docker->kill($doil_related_container); + } + + foreach ($doil_system_containers as $doil_system_container) { + $this->docker->removeContainer($doil_system_container); + } + + $this->docker->pruneImages(); + } + + protected function generatePHPImageScript(): void + { + $script = <<filesystem->hasWriteAccess($this->home_dir)) { + throw new IOException("Unable to generate PHP image script!"); + } + + $this->filesystem->setContent($this->home_dir . "/" . self::BUILD_FILE_NAME, $script); + + $this->filesystem->chownRecursive($this->home_dir . "/" . self::BUILD_FILE_NAME, $this->user_id, $this->user_id); + $this->filesystem->chmod($this->home_dir . "/" . self::BUILD_FILE_NAME, 0744); + } + + protected function executeUpdateScript(): void + { + if (!$this->filesystem->exists(self::DOIL_TARGET_DIR . "/Update/" . self::UPDATE_SCRIPT)) { + return; + } + + $this->filesystem->chmod(self::DOIL_TARGET_DIR . "/Update/" . self::UPDATE_SCRIPT, 0744); + + shell_exec(self::DOIL_TARGET_DIR . "/Update/" . self::UPDATE_SCRIPT); + } +} \ No newline at end of file diff --git a/app/src/Setup/CopyFiles/Copy.php b/app/src/Setup/CopyFiles/Copy.php new file mode 100644 index 00000000..d7901366 --- /dev/null +++ b/app/src/Setup/CopyFiles/Copy.php @@ -0,0 +1,79 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\CopyFiles; + +use CaT\Doil\Lib\Config\Config; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Filesystem\Exception\IOException; + +class Copy +{ + protected const SERVER = [ + "mail", + "proxy", + "salt" + ]; + + protected const TEMPLATES = [ + "minion", + "base" + ]; + + public function __construct( + protected FileSystem $fileSystemShell + ) {} + + /** + * @throws IOException + */ + public function copyDoil(string $base_path, Config $config) : void + { + if ($config->isKeycloakEnabled()) { + $this->fileSystemShell->copyDirectory( + $base_path . "/app/src/Setup/templates/keycloak", + "/usr/local/lib/doil/server/keycloak" + ); + } + foreach (self::SERVER as $server) { + $this->fileSystemShell->copyDirectory( + $base_path . "/app/src/Setup/templates/$server", + "/usr/local/lib/doil/server/$server" + ); + } + + foreach (self::TEMPLATES as $template) { + $this->fileSystemShell->copyDirectory( + $base_path . "/app/src/Setup/templates/$template", + "/usr/local/share/doil/templates/$template" + ); + } + + $this->fileSystemShell->copy( + $base_path . "/setup/Dockerfile", + "/usr/local/lib/doil/server/php/Dockerfile" + ); + + $this->fileSystemShell->copy( + $base_path . "/app/src/Setup/doil.sh", + "/usr/local/bin/doil" + ); + + $this->fileSystemShell->copyDirectory( + $base_path . "/app", + "/usr/local/lib/doil/app" + ); + + $this->fileSystemShell->copyDirectory( + $base_path . "/app/src/Setup/stack", + "/usr/local/share/doil/stack" + ); + + if ($this->fileSystemShell->exists("/usr/local/lib/doil/app/composer.lock")) { + $this->fileSystemShell->remove("/usr/local/lib/doil/app/composer.lock"); + } + } +} \ No newline at end of file diff --git a/app/src/Setup/FileStructure/BaseDirectories.php b/app/src/Setup/FileStructure/BaseDirectories.php new file mode 100644 index 00000000..588cd406 --- /dev/null +++ b/app/src/Setup/FileStructure/BaseDirectories.php @@ -0,0 +1,89 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\FileStructure; + +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Filesystem\Exception\IOException; + +class BaseDirectories +{ + protected const USER_PATHS = [ + ".doil/config", + ".doil/repositories", + ".doil/instances" + ]; + + protected const PATHS = [ + "/usr/local/lib/doil", + "/usr/local/lib/doil/server", + "/usr/local/lib/doil/server/php", + "/usr/local/share/doil", + "/usr/local/share/doil/templates", + ]; + + protected const SUPER_BIT_PATHS = [ + "/etc/doil", + "/srv/instances", + "/usr/local/lib/doil/app", + "/usr/local/share/doil/instances", + "/usr/local/share/doil/repositories", + "/var/log/doil", + ]; + + public function __construct( + protected FileSystem $file_system, + protected string $home_dir, + protected string $user_name, + ) {} + + public function createBaseDirs() : void + { + foreach (self::USER_PATHS as $path) { + if (! $this->file_system->makeDirectoryRecursive($this->home_dir . "/" . $path)) { + throw new IOException("Unable to create directory " . $this->home_dir . "/" . $path); + } + } + + foreach (self::PATHS as $path) { + if (! $this->file_system->makeDirectoryRecursive($path)) { + throw new IOException("Unable to create directory " . $path); + } + } + + foreach (self::SUPER_BIT_PATHS as $path) { + if (! $this->file_system->makeDirectoryRecursive($path)) { + throw new IOException("Unable to create directory " . $path); + } + } + } + + public function setOwnerGroupForBaseDirs() : void + { + $this->file_system->chownRecursive($this->home_dir . "/.doil", $this->user_name, $this->user_name); + + foreach (self::PATHS as $path) { + $this->file_system->chownRecursive($path, "root", "doil"); + } + + foreach (self::SUPER_BIT_PATHS as $path) { + $this->file_system->chownRecursive($path, "root", "doil"); + } + } + + public function setFilePermissionsForBaseDirs() : void + { + $this->file_system->chmod($this->home_dir . "/.doil", 0775); + + foreach (self::PATHS as $path) { + $this->file_system->chmod($path, 0775); + } + + foreach (self::SUPER_BIT_PATHS as $path) { + $this->file_system->chmod($path, 02775); + } + } +} \ No newline at end of file diff --git a/app/src/Setup/FileStructure/BaseFiles.php b/app/src/Setup/FileStructure/BaseFiles.php new file mode 100644 index 00000000..77c6162f --- /dev/null +++ b/app/src/Setup/FileStructure/BaseFiles.php @@ -0,0 +1,78 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\FileStructure; + +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Filesystem\Exception\IOException; + +class BaseFiles +{ + protected const GLOBAL_FILES = [ + "/etc/doil/repositories.json", + "/etc/doil/user.json" + ]; + + protected const USER_FILES = [ + ".doil/config/repositories.json" + ]; + + protected string $home_dir; + protected string $user_name; + + public function __construct( + protected FileSystem $fileSystemShell, + string $home_dir, + string $user_name, + ) { + $this->home_dir = $home_dir; + $this->user_name = $user_name; + } + + /** + * @throws IOException + */ + public function touchFiles() : void + { + foreach (self::GLOBAL_FILES as $file) { + $this->fileSystemShell->touch($file); + } + + foreach (self::USER_FILES as $file) { + $this->fileSystemShell->touch($this->home_dir . "/" . $file); + } + } + + public function setDefaultUser() : int|bool + { + return $this->fileSystemShell->setContent( + "/etc/doil/user.json", + '"a:1:{i:0;O:27:\"CaT\\\\Doil\\\\Commands\\\\User\\\\User\":1:{s:7:\"\u0000*\u0000name\";s:' . strlen($this->user_name) . ':\"' . $this->user_name . '\";}}"' + ); + } + + public function setDefaultRepository() : int|bool + { + return $this->fileSystemShell->setContent( + "/etc/doil/repositories.json", + '"a:1:{i:1;O:27:\"CaT\\\\Doil\\\\Commands\\\\Repo\\\\Repo\":3:{s:7:\"\u0000*\u0000name\";s:5:\"ilias\";s:6:\"\u0000*\u0000url\";s:44:\"https:\\/\\/github.com\\/ILIAS-eLearning\\/ILIAS.git\";s:9:\"\u0000*\u0000global\";b:1;}}"' + ); + } + + public function setFilePermissionsForBaseFiles() : void + { + foreach (self::GLOBAL_FILES as $file) { + $this->fileSystemShell->chmod($file, 0664); + } + } + + public function setFileOwner() : void + { + foreach (self::USER_FILES as $file) { + $this->fileSystemShell->chownRecursive($this->home_dir . "/" . $file, $this->user_name, $this->user_name); + } + } +} \ No newline at end of file diff --git a/app/src/Setup/IP/IP.php b/app/src/Setup/IP/IP.php new file mode 100644 index 00000000..69c1bb90 --- /dev/null +++ b/app/src/Setup/IP/IP.php @@ -0,0 +1,33 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\IP; + +use CaT\Doil\Lib\Config\Config; +use CaT\Doil\Lib\FileSystem\Filesystem; + +class IP +{ + public const IP = "172.24.0.254"; + + public function __construct( + protected Filesystem $filesystem + ) {} + + /** + * @throws \RuntimeException + */ + public function setIPToHosts(Config $config) : int|bool + { + if (!is_null($this->filesystem->getLineInFile("/etc/hosts", self::IP))) { + throw new \RuntimeException("IP " . self::IP . " already set!"); + } + + $line = self::IP . " " . $config->getHost() . "\n"; + + return $this->filesystem->setContent("/etc/hosts", $line, true); + } +} \ No newline at end of file diff --git a/app/src/Setup/Install.php b/app/src/Setup/Install.php new file mode 100644 index 00000000..01ca3385 --- /dev/null +++ b/app/src/Setup/Install.php @@ -0,0 +1,262 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup; + +use CaT\Doil\Setup\IP\IP; + +use CaT\Doil\Setup\CopyFiles\Copy; +use CaT\Doil\Lib\Config\ConfigReader; +use CaT\Doil\Lib\Logger\LoggerFactory; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use CaT\Doil\Lib\Config\ConfigChecker; +use CaT\Doil\Lib\FileSystem\Filesystem; +use CaT\Doil\Setup\Server\StartServers; +use CaT\Doil\Setup\FileStructure\BaseFiles; +use CaT\Doil\Setup\Filestructure\BaseDirectories; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Process\Exception\ProcessFailedException; + +class Install +{ + public function __construct( + protected LoggerFactory $logger_factory, + protected QuestionHelper $question_helper, + protected ConsoleOutputInterface $output, + protected InputInterface $input, + protected Writer $writer, + protected BaseDirectories $base_directories, + protected BaseFiles $base_files, + protected Copy $copy, + protected IP $ip, + protected ConfigReader $config_reader, + protected ConfigChecker $config_checker, + protected Filesystem $filesystem, + protected StartServers $start_servers, + protected string $script_dir + ) {} + + public function run() : void + { + $this->writer->beginBlock($this->output, "Preparing the doil config file"); + try { + $config = $this->config_reader->getConfig(); + } catch (IOException $e) { + if (!$this->config_reader->writeToFile()) { + $this->writer->error( + $this->output, + "Can't write config file!", + "Please run 'setup/uninstall' before running setup again." + ); + } + + $question = new ConfirmationQuestion( + "\n\tdoil adds a config at /etc/doil/doil.conf.\n\tPlease adjust this file to your needs.\n\tAt least you have to add the paths for your ssh keys.\n\tOtherwise the setup won't continue.\n\tContinue? [Yn]: ", + true + ); + + if (!$this->question_helper->ask($this->input, $this->output, $question)) { + $this->writer->error( + $this->output, + "Aborted by user!", + "Please run 'setup/uninstall' before running setup again." + ); + return; + } + + $config = $this->config_reader->getConfig(); + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Checking doil config file"); + try { + $this->config_checker->check($config); + } catch (\InvalidArgumentException $e) { + $this->writer->error( + $this->output, + "Cannot read config file!\n\t" . $e->getMessage(), + "Please run 'setup/uninstall' before running setup again." + ); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Creating doil base directories"); + try { + $this->base_directories->createBaseDirs(); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Setting up setup logger"); + try { + $logger = $this->logger_factory->getSetupLogger("SETUP"); + } catch (\InvalidArgumentException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + return; + } + $this->writer->endBlock(); + + + $this->writer->beginBlock($this->output, "Setting ownership for doil base directories"); + try { + $this->base_directories->setOwnerGroupForBaseDirs(); + $logger->info("Setting ownership for doil base directories"); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Setting file permissions for doil base directories"); + try { + $this->base_directories->setFilePermissionsForBaseDirs(); + $logger->info("Setting file permissions for doil base directories"); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Creating doil base files"); + try { + $this->base_files->touchFiles(); + $logger->info("Creating doil base files"); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Creating doil default user"); + if ($this->base_files->setDefaultUser() === false) { + $this->writer->error( + $this->output, + "Cannot create doil default user!", + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error("Cannot create doil default user!"); + return; + } + $logger->info("Creating doil default user"); + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Creating doil default repository"); + if ($this->base_files->setDefaultRepository() === false) { + $this->writer->error( + $this->output, + "Cannot create doil default repository!", + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error("Cannot create doil default repository!"); + return; + } + $logger->info("Creating doil default repository"); + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Setting file permissions for doil base files"); + try { + $this->base_files->setFilePermissionsForBaseFiles(); + $logger->info("Setting file permissions for doil base files"); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Setting file owner for doil base files"); + try { + $this->base_files->setFileOwner(); + $logger->info("Setting file owner for doil base files"); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Copying doil files"); + try { + $this->copy->copyDoil($this->script_dir . "/..", $config); + $logger->info("Copying doil files"); + } catch (IOException $e) { + $this->writer->error( + $this->output, + $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + return; + } + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Setting doil ip to hosts"); + if ($this->ip->setIPToHosts($config) === false) { + $this->writer->error( + $this->output, + "Cannot set doil ip to hosts!", + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error("Cannot set doil ip to hosts!"); + return; + } + $logger->info("Setting doil ip to hosts"); + $this->writer->endBlock(); + + $this->writer->beginBlock($this->output, "Starting doil system containers"); + try { + $this->start_servers->run($config, $logger); + $logger->info("Starting doil system containers"); + } catch (ProcessFailedException $e) { + $this->writer->error( + $this->output, + "Starting doil system containers failed!\n" . $e->getMessage(), + "If the problem is fixed, run 'setup/uninstall' before running setup again." + ); + $logger->error($e->getTraceAsString()); + } + $this->writer->endBlock(); + } +} + diff --git a/app/src/Setup/Server/Keycloak.php b/app/src/Setup/Server/Keycloak.php new file mode 100644 index 00000000..b24cad03 --- /dev/null +++ b/app/src/Setup/Server/Keycloak.php @@ -0,0 +1,132 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\Server; + +use Psr\Log\LoggerInterface; +use CaT\Doil\Lib\SymfonyShell; +use CaT\Doil\Lib\Config\Config; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Process\Exception\ProcessFailedException; + +class Keycloak +{ + use SymfonyShell; + + public function __construct( + protected Filesystem $filesystem, + ) {} + + /** + * @throws ProcessFailedException + */ + public function start(LoggerInterface $logger, Config $config) : void + { + $replace_data = [ + "/usr/local/lib/doil/server/keycloak/conf/keycloak-startup.conf" => [ + "%TPL_SERVER_HOSTNAME%" => $config->getKeycloakHostname(), + "%TPL_DB_USERNAME%" => $config->getKeycloakDbUsername(), + "%TPL_DB_PASSWORD%" => $config->getKeycloakDbPassword() + ], + "/usr/local/lib/doil/server/keycloak/conf/init.sql" => [ + "%TPL_DB_USERNAME%" => $config->getKeycloakDbUsername(), + "%TPL_DB_PASSWORD%" => $config->getKeycloakDbPassword() + ], + "/usr/local/share/doil/stack/states/keycloak/keycloak/init.sls" => [ + "%TPL_NEW_ADMIN_PASSWORD%" => $config->getKeycloakNewAdminPassword(), + "%TPL_OLD_ADMIN_PASSWORD%" => $config->getKeycloakOldAdminPassword() + ] + ]; + + $this->replace($replace_data); + + $cmd = [ + "docker", + "compose", + "-f", + "/usr/local/lib/doil/server/keycloak/docker-compose.yml", + "up", + "-d" + ]; + + $logger->info("Start instance doil_keycloak"); + $this->run($cmd, $logger); + + // Time for proxy registration on doil master + sleep(120); + + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt doil.keycloak state.highstate saltenv=keycloak" + ]; + + $logger->info("Apply salt highstate on keycloak server"); + $this->run($cmd, $logger); + } + + /** + * @throws ProcessFailedException + */ + public function commit(LoggerInterface $logger) : void + { + $cmd = [ + "docker", + "commit", + "doil_keycloak", + "doil_keycloak:stable" + ]; + + $logger->info("Commit instance doil_keycloak"); + $this->run($cmd, $logger); + } + + /** + * @throws ProcessFailedException + */ + public function distributeData(LoggerInterface $logger, Config $config) : void + { + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt 'doil.keycloak' http.query http://localhost:8080/realms/master/protocol/saml/descriptor --out=raw | cut -d \"'\" -f6" + ]; + + $logger->info("Get idp meta data"); + $idp_metadata = $this->run($cmd, $logger); + + $replace_data = [ + "/usr/local/share/doil/stack/states/enable-saml/saml/init.sls" => [ + "%TPL_IDP_META%" => $idp_metadata, + "%TPL_KEYCLOAK_HOSTNAME%" => $config->getKeycloakHostname(), + "%TPL_ADMIN_PASSWORD%" => $config->getKeycloakNewAdminPassword() + ], + "/usr/local/share/doil/stack/states/disable-saml/saml/init.sls" => [ + "%TPL_KEYCLOAK_HOSTNAME%" => $config->getKeycloakHostname(), + "%TPL_ADMIN_PASSWORD%" => $config->getKeycloakNewAdminPassword() + ] + ]; + + $this->replace($replace_data); + } + + protected function replace(array $replace_data) : void + { + foreach ($replace_data as $file => $replacements) { + foreach ($replacements as $needle => $replacement) { + $this->filesystem->replaceStringInFile($file, $needle, $replacement); + } + } + } +} \ No newline at end of file diff --git a/app/src/Setup/Server/Mail.php b/app/src/Setup/Server/Mail.php new file mode 100644 index 00000000..306dbaa9 --- /dev/null +++ b/app/src/Setup/Server/Mail.php @@ -0,0 +1,106 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\Server; + +use Psr\Log\LoggerInterface; +use CaT\Doil\Lib\SymfonyShell; +use Symfony\Component\Process\Exception\ProcessFailedException; + +class Mail +{ + use SymfonyShell; + + /** + * @throws ProcessFailedException + */ + public function start(LoggerInterface $logger, string $mail_password) : void + { + $cmd = [ + "docker", + "compose", + "-f", + "/usr/local/lib/doil/server/mail/docker-compose.yml", + "up", + "-d" + ]; + + $logger->info("Start instance doil_mail"); + $this->run($cmd, $logger); + + // Time for proxy registration on doil master + sleep(20); + + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt doil.mail state.highstate saltenv=mailservices" + ]; + + $logger->info("Apply salt highstate on mail server"); + $this->run($cmd, $logger); + + if ($mail_password == "ilias") { + return; + } + + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt doil.mail shadow.gen_password \"{$mail_password}\" --out txt" + ]; + $logger->info("Generate roundcube_password"); + $password = $this->run($cmd, $logger); + $password = explode(" ", trim($password))[1]; + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt doil.mail grains.setval 'roundcube_password' '{$password}'" + ]; + $logger->info("Set roundcube_password grain"); + $this->run($cmd, $logger); + + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt doil.mail state.highstate saltenv=change-roundcube-password" + ]; + $logger->info("Run change-roundcube-password state"); + $this->run($cmd, $logger); + } + + /** + * @throws ProcessFailedException + */ + public function commit(LoggerInterface $logger) : void + { + $cmd = [ + "docker", + "commit", + "doil_mail", + "doil_mail:stable" + ]; + + $logger->info("Commit instance doil_mail"); + $this->run($cmd, $logger); + } +} \ No newline at end of file diff --git a/app/src/Setup/Server/Proxy.php b/app/src/Setup/Server/Proxy.php new file mode 100644 index 00000000..d8ada8d7 --- /dev/null +++ b/app/src/Setup/Server/Proxy.php @@ -0,0 +1,77 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\Server; + +use Psr\Log\LoggerInterface; +use CaT\Doil\Lib\SymfonyShell; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Process\Exception\ProcessFailedException; + +class Proxy +{ + use SymfonyShell; + + public function __construct( + protected Filesystem $filesystem + ) {} + + /** + * @throws ProcessFailedException + */ + public function start(LoggerInterface $logger, string $host) : void + { + $this->filesystem->replaceStringInFile( + "/usr/local/lib/doil/server/proxy/conf/nginx/local.conf", + "%TPL_SERVER_NAME%", + $host + ); + + $cmd = [ + "docker", + "compose", + "-f", + "/usr/local/lib/doil/server/proxy/docker-compose.yml", + "up", + "-d" + ]; + + $logger->info("Start instance doil_proxy"); + $this->run($cmd, $logger); + + // Time for proxy registration on doil master + sleep(20); + + $cmd = [ + "docker", + "exec", + "-i", + "doil_salt", + "bash", + "-c", + "salt doil.proxy state.highstate saltenv=proxyservices" + ]; + + $logger->info("Apply salt highstate on proxy server"); + $this->run($cmd, $logger); + } + + /** + * @throws ProcessFailedException + */ + public function commit(LoggerInterface $logger) : void + { + $cmd = [ + "docker", + "commit", + "doil_proxy", + "doil_proxy:stable" + ]; + + $logger->info("Commit instance doil_proxy"); + $this->run($cmd, $logger); + } +} \ No newline at end of file diff --git a/app/src/Setup/Server/Salt.php b/app/src/Setup/Server/Salt.php new file mode 100644 index 00000000..28199c05 --- /dev/null +++ b/app/src/Setup/Server/Salt.php @@ -0,0 +1,50 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\Server; + +use Psr\Log\LoggerInterface; +use CaT\Doil\Lib\SymfonyShell; +use Symfony\Component\Process\Exception\ProcessFailedException; + +class Salt +{ + use SymfonyShell; + + /** + * @throws ProcessFailedException + */ + public function start(LoggerInterface $logger) : void + { + $cmd = [ + "docker", + "compose", + "-f", + "/usr/local/lib/doil/server/salt/docker-compose.yml", + "up", + "-d" + ]; + + $logger->info("Start instance"); + $this->run($cmd, $logger); + } + + /** + * @throws ProcessFailedException + */ + public function commit(LoggerInterface $logger) : void + { + $cmd = [ + "docker", + "commit", + "doil_salt", + "doil_salt:stable" + ]; + + $logger->info("Start instance"); + $this->run($cmd, $logger); + } +} \ No newline at end of file diff --git a/app/src/Setup/Server/StartServers.php b/app/src/Setup/Server/StartServers.php new file mode 100644 index 00000000..f784b679 --- /dev/null +++ b/app/src/Setup/Server/StartServers.php @@ -0,0 +1,41 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\Server; + +use Psr\Log\LoggerInterface; +use CaT\Doil\Lib\Config\Config; +use Symfony\Component\Process\Exception\ProcessFailedException; + +class StartServers +{ + public function __construct( + protected Salt $salt, + protected Proxy $proxy, + protected Mail $mail, + protected Keycloak $keycloak, + ) {} + + /** + * @throws ProcessFailedException + */ + public function run(Config $config, LoggerInterface $logger): void { + $this->salt->start($logger); + $this->salt->commit($logger); + + $this->proxy->start($logger, $config->getHost()); + $this->proxy->commit($logger); + + $this->mail->start($logger, $config->getMailPassword()); + $this->mail->commit($logger); + + if ($config->isKeycloakEnabled()) { + $this->keycloak->start($logger, $config); + $this->keycloak->commit($logger); + $this->keycloak->distributeData($logger, $config); + } + } +} \ No newline at end of file diff --git a/setup/doil.sh b/app/src/Setup/doil.sh similarity index 83% rename from setup/doil.sh rename to app/src/Setup/doil.sh index a680dd4d..66212d90 100755 --- a/setup/doil.sh +++ b/app/src/Setup/doil.sh @@ -49,20 +49,14 @@ then echo "Please ensure that ${USER} is member of the doil group and try again!" exit fi - MAP_USER="--user $(id -u):$(id -g)" -fi - -GLOBAL_INSTANCES_PATH=$(doil_get_conf global_instances_path) -if [ -z $GLOBAL_INSTANCES_PATH ] -then - GLOBAL_INSTANCES_PATH="" -else - GLOBAL_INSTANCES_PATH="-v $GLOBAL_INSTANCES_PATH:$GLOBAL_INSTANCES_PATH" + MAP_USER="--user $(id -u $(logname)):$(id -g)" fi DOCKER_GRP_ID=$(cat /etc/group | grep "^docker:" | cut -d : -f3) DOIL_GRP_ID=$(cat /etc/group | grep "^doil:" | cut -d : -f3) +USER_NAME=$(echo $SUDO_USER) + docker run --rm "${TERMINAL}" \ -v /home:/home \ -v $(pwd):$(pwd) \ @@ -72,13 +66,14 @@ docker run --rm "${TERMINAL}" \ -v /usr/local/bin:/usr/local/bin \ -v /etc/doil:/etc/doil \ -v /etc:/etc \ + -v /etc/hosts:/hosts \ -v /var/log:/var/log \ -e PHP_INI_SCAN_DIR=/srv/php/mods-available \ - -e SUDO_UID="$SUDO_UID" \ - $GLOBAL_INSTANCES_PATH \ + -e SUDO_UID=$(id -u $(logname)) \ + -v /srv/instances:/srv/instances \ -w $(pwd) \ $MAP_USER \ --group-add ${DOCKER_GRP_ID} \ --group-add ${DOIL_GRP_ID} \ doil_php:stable \ - /usr/bin/php8.2 -c /srv/php/php.ini /usr/local/lib/doil/app/src/cli.php "$@" \ No newline at end of file + /usr/bin/php8.4 -c /srv/php/php.ini /usr/local/lib/doil/app/src/cli.php "" "" "" "$USER_NAME" "false" "$@" \ No newline at end of file diff --git a/setup/stack/config/master.cnf b/app/src/Setup/stack/config/master.cnf similarity index 100% rename from setup/stack/config/master.cnf rename to app/src/Setup/stack/config/master.cnf diff --git a/setup/stack/config/minion.cnf b/app/src/Setup/stack/config/minion.cnf similarity index 100% rename from setup/stack/config/minion.cnf rename to app/src/Setup/stack/config/minion.cnf diff --git a/setup/stack/states/access/access/init.sls b/app/src/Setup/stack/states/access/access/init.sls similarity index 100% rename from setup/stack/states/access/access/init.sls rename to app/src/Setup/stack/states/access/access/init.sls diff --git a/setup/stack/states/access/description.txt b/app/src/Setup/stack/states/access/description.txt similarity index 100% rename from setup/stack/states/access/description.txt rename to app/src/Setup/stack/states/access/description.txt diff --git a/setup/stack/states/access/top.sls b/app/src/Setup/stack/states/access/top.sls similarity index 100% rename from setup/stack/states/access/top.sls rename to app/src/Setup/stack/states/access/top.sls diff --git a/setup/stack/states/apache/apache/apache.conf b/app/src/Setup/stack/states/apache/apache/apache.conf similarity index 100% rename from setup/stack/states/apache/apache/apache.conf rename to app/src/Setup/stack/states/apache/apache/apache.conf diff --git a/setup/stack/states/apache/apache/default b/app/src/Setup/stack/states/apache/apache/default similarity index 100% rename from setup/stack/states/apache/apache/default rename to app/src/Setup/stack/states/apache/apache/default diff --git a/setup/stack/states/apache/apache/default_ilias10 b/app/src/Setup/stack/states/apache/apache/default_ilias10 similarity index 100% rename from setup/stack/states/apache/apache/default_ilias10 rename to app/src/Setup/stack/states/apache/apache/default_ilias10 diff --git a/setup/stack/states/apache/apache/init.sls b/app/src/Setup/stack/states/apache/apache/init.sls similarity index 100% rename from setup/stack/states/apache/apache/init.sls rename to app/src/Setup/stack/states/apache/apache/init.sls diff --git a/setup/stack/states/apache/description.txt b/app/src/Setup/stack/states/apache/description.txt similarity index 100% rename from setup/stack/states/apache/description.txt rename to app/src/Setup/stack/states/apache/description.txt diff --git a/setup/stack/states/apache/top.sls b/app/src/Setup/stack/states/apache/top.sls similarity index 100% rename from setup/stack/states/apache/top.sls rename to app/src/Setup/stack/states/apache/top.sls diff --git a/setup/stack/states/autoinstall/autoinstall/ilias-config.json b/app/src/Setup/stack/states/autoinstall/autoinstall/ilias-config.json similarity index 100% rename from setup/stack/states/autoinstall/autoinstall/ilias-config.json rename to app/src/Setup/stack/states/autoinstall/autoinstall/ilias-config.json diff --git a/setup/stack/states/autoinstall/autoinstall/init.sls b/app/src/Setup/stack/states/autoinstall/autoinstall/init.sls similarity index 100% rename from setup/stack/states/autoinstall/autoinstall/init.sls rename to app/src/Setup/stack/states/autoinstall/autoinstall/init.sls diff --git a/setup/stack/states/autoinstall/top.sls b/app/src/Setup/stack/states/autoinstall/top.sls similarity index 100% rename from setup/stack/states/autoinstall/top.sls rename to app/src/Setup/stack/states/autoinstall/top.sls diff --git a/setup/stack/states/base/msmtp/init.sls b/app/src/Setup/stack/states/base/msmtp/init.sls similarity index 100% rename from setup/stack/states/base/msmtp/init.sls rename to app/src/Setup/stack/states/base/msmtp/init.sls diff --git a/setup/stack/states/base/msmtp/msmtp.conf.j2 b/app/src/Setup/stack/states/base/msmtp/msmtp.conf.j2 similarity index 100% rename from setup/stack/states/base/msmtp/msmtp.conf.j2 rename to app/src/Setup/stack/states/base/msmtp/msmtp.conf.j2 diff --git a/setup/stack/states/base/mysql/init.sls b/app/src/Setup/stack/states/base/mysql/init.sls similarity index 100% rename from setup/stack/states/base/mysql/init.sls rename to app/src/Setup/stack/states/base/mysql/init.sls diff --git a/setup/stack/states/base/mysql/my.cnf b/app/src/Setup/stack/states/base/mysql/my.cnf similarity index 100% rename from setup/stack/states/base/mysql/my.cnf rename to app/src/Setup/stack/states/base/mysql/my.cnf diff --git a/setup/stack/states/base/mysql/mysql.conf b/app/src/Setup/stack/states/base/mysql/mysql.conf similarity index 100% rename from setup/stack/states/base/mysql/mysql.conf rename to app/src/Setup/stack/states/base/mysql/mysql.conf diff --git a/setup/stack/states/base/mysql/mysql_starter.sh b/app/src/Setup/stack/states/base/mysql/mysql_starter.sh similarity index 100% rename from setup/stack/states/base/mysql/mysql_starter.sh rename to app/src/Setup/stack/states/base/mysql/mysql_starter.sh diff --git a/setup/stack/states/base/postfix/aliases b/app/src/Setup/stack/states/base/postfix/aliases similarity index 100% rename from setup/stack/states/base/postfix/aliases rename to app/src/Setup/stack/states/base/postfix/aliases diff --git a/setup/stack/states/base/postfix/init.sls b/app/src/Setup/stack/states/base/postfix/init.sls similarity index 100% rename from setup/stack/states/base/postfix/init.sls rename to app/src/Setup/stack/states/base/postfix/init.sls diff --git a/setup/stack/states/base/postfix/mailname b/app/src/Setup/stack/states/base/postfix/mailname similarity index 100% rename from setup/stack/states/base/postfix/mailname rename to app/src/Setup/stack/states/base/postfix/mailname diff --git a/setup/stack/states/base/postfix/main.cf b/app/src/Setup/stack/states/base/postfix/main.cf similarity index 100% rename from setup/stack/states/base/postfix/main.cf rename to app/src/Setup/stack/states/base/postfix/main.cf diff --git a/setup/stack/states/base/postfix/transport b/app/src/Setup/stack/states/base/postfix/transport similarity index 100% rename from setup/stack/states/base/postfix/transport rename to app/src/Setup/stack/states/base/postfix/transport diff --git a/setup/stack/states/base/startup/init.sls b/app/src/Setup/stack/states/base/startup/init.sls similarity index 100% rename from setup/stack/states/base/startup/init.sls rename to app/src/Setup/stack/states/base/startup/init.sls diff --git a/setup/stack/states/base/startup/salt-startup.sh b/app/src/Setup/stack/states/base/startup/salt-startup.sh similarity index 100% rename from setup/stack/states/base/startup/salt-startup.sh rename to app/src/Setup/stack/states/base/startup/salt-startup.sh diff --git a/setup/stack/states/base/startup/startup.conf b/app/src/Setup/stack/states/base/startup/startup.conf similarity index 100% rename from setup/stack/states/base/startup/startup.conf rename to app/src/Setup/stack/states/base/startup/startup.conf diff --git a/setup/stack/states/base/tools/init.sls b/app/src/Setup/stack/states/base/tools/init.sls similarity index 100% rename from setup/stack/states/base/tools/init.sls rename to app/src/Setup/stack/states/base/tools/init.sls diff --git a/setup/stack/states/base/top.sls b/app/src/Setup/stack/states/base/top.sls similarity index 100% rename from setup/stack/states/base/top.sls rename to app/src/Setup/stack/states/base/top.sls diff --git a/setup/stack/states/change-roundcube-password/change-roundcube-password/init.sls b/app/src/Setup/stack/states/change-roundcube-password/change-roundcube-password/init.sls similarity index 100% rename from setup/stack/states/change-roundcube-password/change-roundcube-password/init.sls rename to app/src/Setup/stack/states/change-roundcube-password/change-roundcube-password/init.sls diff --git a/setup/stack/states/change-roundcube-password/top.sls b/app/src/Setup/stack/states/change-roundcube-password/top.sls similarity index 100% rename from setup/stack/states/change-roundcube-password/top.sls rename to app/src/Setup/stack/states/change-roundcube-password/top.sls diff --git a/setup/stack/states/compile-skins/compileskins/init.sls b/app/src/Setup/stack/states/compile-skins/compileskins/init.sls similarity index 100% rename from setup/stack/states/compile-skins/compileskins/init.sls rename to app/src/Setup/stack/states/compile-skins/compileskins/init.sls diff --git a/setup/stack/states/compile-skins/description.txt b/app/src/Setup/stack/states/compile-skins/description.txt similarity index 100% rename from setup/stack/states/compile-skins/description.txt rename to app/src/Setup/stack/states/compile-skins/description.txt diff --git a/setup/stack/states/compile-skins/top.sls b/app/src/Setup/stack/states/compile-skins/top.sls similarity index 100% rename from setup/stack/states/compile-skins/top.sls rename to app/src/Setup/stack/states/compile-skins/top.sls diff --git a/setup/stack/states/composer-install/composer-install/init.sls b/app/src/Setup/stack/states/composer-install/composer-install/init.sls similarity index 100% rename from setup/stack/states/composer-install/composer-install/init.sls rename to app/src/Setup/stack/states/composer-install/composer-install/init.sls diff --git a/setup/stack/states/composer-install/description.txt b/app/src/Setup/stack/states/composer-install/description.txt similarity index 100% rename from setup/stack/states/composer-install/description.txt rename to app/src/Setup/stack/states/composer-install/description.txt diff --git a/setup/stack/states/composer-install/top.sls b/app/src/Setup/stack/states/composer-install/top.sls similarity index 100% rename from setup/stack/states/composer-install/top.sls rename to app/src/Setup/stack/states/composer-install/top.sls diff --git a/setup/stack/states/composer/composer/init.sls b/app/src/Setup/stack/states/composer/composer/init.sls similarity index 100% rename from setup/stack/states/composer/composer/init.sls rename to app/src/Setup/stack/states/composer/composer/init.sls diff --git a/setup/stack/states/composer/top.sls b/app/src/Setup/stack/states/composer/top.sls similarity index 100% rename from setup/stack/states/composer/top.sls rename to app/src/Setup/stack/states/composer/top.sls diff --git a/setup/stack/states/composer2/composer/init.sls b/app/src/Setup/stack/states/composer2/composer/init.sls similarity index 100% rename from setup/stack/states/composer2/composer/init.sls rename to app/src/Setup/stack/states/composer2/composer/init.sls diff --git a/setup/stack/states/composer2/top.sls b/app/src/Setup/stack/states/composer2/top.sls similarity index 100% rename from setup/stack/states/composer2/top.sls rename to app/src/Setup/stack/states/composer2/top.sls diff --git a/setup/stack/states/composer54/composer/init.sls b/app/src/Setup/stack/states/composer54/composer/init.sls similarity index 100% rename from setup/stack/states/composer54/composer/init.sls rename to app/src/Setup/stack/states/composer54/composer/init.sls diff --git a/setup/stack/states/composer54/top.sls b/app/src/Setup/stack/states/composer54/top.sls similarity index 100% rename from setup/stack/states/composer54/top.sls rename to app/src/Setup/stack/states/composer54/top.sls diff --git a/setup/stack/states/dev/devtools/adminer-4.8.0-mysql-en.php b/app/src/Setup/stack/states/dev/devtools/adminer-4.8.0-mysql-en.php similarity index 100% rename from setup/stack/states/dev/devtools/adminer-4.8.0-mysql-en.php rename to app/src/Setup/stack/states/dev/devtools/adminer-4.8.0-mysql-en.php diff --git a/setup/stack/states/dev/devtools/githook-post-merge b/app/src/Setup/stack/states/dev/devtools/githook-post-merge similarity index 100% rename from setup/stack/states/dev/devtools/githook-post-merge rename to app/src/Setup/stack/states/dev/devtools/githook-post-merge diff --git a/setup/stack/states/dev/devtools/init.sls b/app/src/Setup/stack/states/dev/devtools/init.sls similarity index 100% rename from setup/stack/states/dev/devtools/init.sls rename to app/src/Setup/stack/states/dev/devtools/init.sls diff --git a/setup/stack/states/dev/devtools/install-lessc.sh b/app/src/Setup/stack/states/dev/devtools/install-lessc.sh similarity index 100% rename from setup/stack/states/dev/devtools/install-lessc.sh rename to app/src/Setup/stack/states/dev/devtools/install-lessc.sh diff --git a/setup/stack/states/dev/devtools/install-sass.sh b/app/src/Setup/stack/states/dev/devtools/install-sass.sh similarity index 100% rename from setup/stack/states/dev/devtools/install-sass.sh rename to app/src/Setup/stack/states/dev/devtools/install-sass.sh diff --git a/setup/stack/states/dev/top.sls b/app/src/Setup/stack/states/dev/top.sls similarity index 100% rename from setup/stack/states/dev/top.sls rename to app/src/Setup/stack/states/dev/top.sls diff --git a/setup/stack/states/disable-captainhook/captainhook/init.sls b/app/src/Setup/stack/states/disable-captainhook/captainhook/init.sls similarity index 100% rename from setup/stack/states/disable-captainhook/captainhook/init.sls rename to app/src/Setup/stack/states/disable-captainhook/captainhook/init.sls diff --git a/setup/stack/states/disable-captainhook/description.txt b/app/src/Setup/stack/states/disable-captainhook/description.txt similarity index 100% rename from setup/stack/states/disable-captainhook/description.txt rename to app/src/Setup/stack/states/disable-captainhook/description.txt diff --git a/setup/stack/states/disable-captainhook/top.sls b/app/src/Setup/stack/states/disable-captainhook/top.sls similarity index 100% rename from setup/stack/states/disable-captainhook/top.sls rename to app/src/Setup/stack/states/disable-captainhook/top.sls diff --git a/setup/stack/states/disable-https/description.txt b/app/src/Setup/stack/states/disable-https/description.txt similarity index 100% rename from setup/stack/states/disable-https/description.txt rename to app/src/Setup/stack/states/disable-https/description.txt diff --git a/setup/stack/states/disable-https/https/init.sls b/app/src/Setup/stack/states/disable-https/https/init.sls similarity index 100% rename from setup/stack/states/disable-https/https/init.sls rename to app/src/Setup/stack/states/disable-https/https/init.sls diff --git a/setup/stack/states/disable-https/top.sls b/app/src/Setup/stack/states/disable-https/top.sls similarity index 100% rename from setup/stack/states/disable-https/top.sls rename to app/src/Setup/stack/states/disable-https/top.sls diff --git a/setup/stack/states/disable-saml/description.txt b/app/src/Setup/stack/states/disable-saml/description.txt similarity index 100% rename from setup/stack/states/disable-saml/description.txt rename to app/src/Setup/stack/states/disable-saml/description.txt diff --git a/setup/stack/states/disable-saml/saml/DeleteIdp.php.j2 b/app/src/Setup/stack/states/disable-saml/saml/DeleteIdp.php.j2 similarity index 100% rename from setup/stack/states/disable-saml/saml/DeleteIdp.php.j2 rename to app/src/Setup/stack/states/disable-saml/saml/DeleteIdp.php.j2 diff --git a/setup/stack/states/disable-saml/saml/DeleteIdpV10.php.j2 b/app/src/Setup/stack/states/disable-saml/saml/DeleteIdpV10.php.j2 similarity index 100% rename from setup/stack/states/disable-saml/saml/DeleteIdpV10.php.j2 rename to app/src/Setup/stack/states/disable-saml/saml/DeleteIdpV10.php.j2 diff --git a/setup/stack/states/disable-saml/saml/deleteInstanceFromKeycloak.php.j2 b/app/src/Setup/stack/states/disable-saml/saml/deleteInstanceFromKeycloak.php.j2 similarity index 100% rename from setup/stack/states/disable-saml/saml/deleteInstanceFromKeycloak.php.j2 rename to app/src/Setup/stack/states/disable-saml/saml/deleteInstanceFromKeycloak.php.j2 diff --git a/setup/stack/states/disable-saml/saml/init.sls b/app/src/Setup/stack/states/disable-saml/saml/init.sls similarity index 100% rename from setup/stack/states/disable-saml/saml/init.sls rename to app/src/Setup/stack/states/disable-saml/saml/init.sls diff --git a/setup/stack/states/disable-saml/top.sls b/app/src/Setup/stack/states/disable-saml/top.sls similarity index 100% rename from setup/stack/states/disable-saml/top.sls rename to app/src/Setup/stack/states/disable-saml/top.sls diff --git a/setup/stack/states/disable-whoops-devmode/description.txt b/app/src/Setup/stack/states/disable-whoops-devmode/description.txt similarity index 100% rename from setup/stack/states/disable-whoops-devmode/description.txt rename to app/src/Setup/stack/states/disable-whoops-devmode/description.txt diff --git a/setup/stack/states/disable-whoops-devmode/top.sls b/app/src/Setup/stack/states/disable-whoops-devmode/top.sls similarity index 100% rename from setup/stack/states/disable-whoops-devmode/top.sls rename to app/src/Setup/stack/states/disable-whoops-devmode/top.sls diff --git a/setup/stack/states/disable-whoops-devmode/whoops-devmode/init.sls b/app/src/Setup/stack/states/disable-whoops-devmode/whoops-devmode/init.sls similarity index 100% rename from setup/stack/states/disable-whoops-devmode/whoops-devmode/init.sls rename to app/src/Setup/stack/states/disable-whoops-devmode/whoops-devmode/init.sls diff --git a/setup/stack/states/disable-xdebug/description.txt b/app/src/Setup/stack/states/disable-xdebug/description.txt similarity index 100% rename from setup/stack/states/disable-xdebug/description.txt rename to app/src/Setup/stack/states/disable-xdebug/description.txt diff --git a/setup/stack/states/disable-xdebug/top.sls b/app/src/Setup/stack/states/disable-xdebug/top.sls similarity index 100% rename from setup/stack/states/disable-xdebug/top.sls rename to app/src/Setup/stack/states/disable-xdebug/top.sls diff --git a/setup/stack/states/disable-xdebug/xdebug/init.sls b/app/src/Setup/stack/states/disable-xdebug/xdebug/init.sls similarity index 100% rename from setup/stack/states/disable-xdebug/xdebug/init.sls rename to app/src/Setup/stack/states/disable-xdebug/xdebug/init.sls diff --git a/setup/stack/states/enable-captainhook/captainhook/init.sls b/app/src/Setup/stack/states/enable-captainhook/captainhook/init.sls similarity index 100% rename from setup/stack/states/enable-captainhook/captainhook/init.sls rename to app/src/Setup/stack/states/enable-captainhook/captainhook/init.sls diff --git a/setup/stack/states/enable-captainhook/description.txt b/app/src/Setup/stack/states/enable-captainhook/description.txt similarity index 100% rename from setup/stack/states/enable-captainhook/description.txt rename to app/src/Setup/stack/states/enable-captainhook/description.txt diff --git a/setup/stack/states/enable-captainhook/top.sls b/app/src/Setup/stack/states/enable-captainhook/top.sls similarity index 100% rename from setup/stack/states/enable-captainhook/top.sls rename to app/src/Setup/stack/states/enable-captainhook/top.sls diff --git a/setup/stack/states/enable-https/description.txt b/app/src/Setup/stack/states/enable-https/description.txt similarity index 100% rename from setup/stack/states/enable-https/description.txt rename to app/src/Setup/stack/states/enable-https/description.txt diff --git a/setup/stack/states/enable-https/https/init.sls b/app/src/Setup/stack/states/enable-https/https/init.sls similarity index 100% rename from setup/stack/states/enable-https/https/init.sls rename to app/src/Setup/stack/states/enable-https/https/init.sls diff --git a/setup/stack/states/enable-https/top.sls b/app/src/Setup/stack/states/enable-https/top.sls similarity index 100% rename from setup/stack/states/enable-https/top.sls rename to app/src/Setup/stack/states/enable-https/top.sls diff --git a/setup/stack/states/enable-saml/description.txt b/app/src/Setup/stack/states/enable-saml/description.txt similarity index 100% rename from setup/stack/states/enable-saml/description.txt rename to app/src/Setup/stack/states/enable-saml/description.txt diff --git a/setup/stack/states/enable-saml/saml/SetIdp.php.j2 b/app/src/Setup/stack/states/enable-saml/saml/SetIdp.php.j2 similarity index 100% rename from setup/stack/states/enable-saml/saml/SetIdp.php.j2 rename to app/src/Setup/stack/states/enable-saml/saml/SetIdp.php.j2 diff --git a/setup/stack/states/enable-saml/saml/SetIdpV10.php.j2 b/app/src/Setup/stack/states/enable-saml/saml/SetIdpV10.php.j2 similarity index 100% rename from setup/stack/states/enable-saml/saml/SetIdpV10.php.j2 rename to app/src/Setup/stack/states/enable-saml/saml/SetIdpV10.php.j2 diff --git a/setup/stack/states/enable-saml/saml/addInstanceToKeycloak.php.j2 b/app/src/Setup/stack/states/enable-saml/saml/addInstanceToKeycloak.php.j2 similarity index 100% rename from setup/stack/states/enable-saml/saml/addInstanceToKeycloak.php.j2 rename to app/src/Setup/stack/states/enable-saml/saml/addInstanceToKeycloak.php.j2 diff --git a/setup/stack/states/enable-saml/saml/authsources.php.j2 b/app/src/Setup/stack/states/enable-saml/saml/authsources.php.j2 similarity index 100% rename from setup/stack/states/enable-saml/saml/authsources.php.j2 rename to app/src/Setup/stack/states/enable-saml/saml/authsources.php.j2 diff --git a/setup/stack/states/enable-saml/saml/config.php.j2 b/app/src/Setup/stack/states/enable-saml/saml/config.php.j2 similarity index 100% rename from setup/stack/states/enable-saml/saml/config.php.j2 rename to app/src/Setup/stack/states/enable-saml/saml/config.php.j2 diff --git a/setup/stack/states/enable-saml/saml/init.sls b/app/src/Setup/stack/states/enable-saml/saml/init.sls similarity index 100% rename from setup/stack/states/enable-saml/saml/init.sls rename to app/src/Setup/stack/states/enable-saml/saml/init.sls diff --git a/setup/stack/states/enable-saml/top.sls b/app/src/Setup/stack/states/enable-saml/top.sls similarity index 100% rename from setup/stack/states/enable-saml/top.sls rename to app/src/Setup/stack/states/enable-saml/top.sls diff --git a/setup/stack/states/enable-whoops-devmode/description.txt b/app/src/Setup/stack/states/enable-whoops-devmode/description.txt similarity index 100% rename from setup/stack/states/enable-whoops-devmode/description.txt rename to app/src/Setup/stack/states/enable-whoops-devmode/description.txt diff --git a/setup/stack/states/enable-whoops-devmode/top.sls b/app/src/Setup/stack/states/enable-whoops-devmode/top.sls similarity index 100% rename from setup/stack/states/enable-whoops-devmode/top.sls rename to app/src/Setup/stack/states/enable-whoops-devmode/top.sls diff --git a/setup/stack/states/enable-whoops-devmode/whoops-devmode/init.sls b/app/src/Setup/stack/states/enable-whoops-devmode/whoops-devmode/init.sls similarity index 100% rename from setup/stack/states/enable-whoops-devmode/whoops-devmode/init.sls rename to app/src/Setup/stack/states/enable-whoops-devmode/whoops-devmode/init.sls diff --git a/setup/stack/states/enable-xdebug/description.txt b/app/src/Setup/stack/states/enable-xdebug/description.txt similarity index 100% rename from setup/stack/states/enable-xdebug/description.txt rename to app/src/Setup/stack/states/enable-xdebug/description.txt diff --git a/setup/stack/states/enable-xdebug/top.sls b/app/src/Setup/stack/states/enable-xdebug/top.sls similarity index 100% rename from setup/stack/states/enable-xdebug/top.sls rename to app/src/Setup/stack/states/enable-xdebug/top.sls diff --git a/setup/stack/states/enable-xdebug/xdebug/init.sls b/app/src/Setup/stack/states/enable-xdebug/xdebug/init.sls similarity index 100% rename from setup/stack/states/enable-xdebug/xdebug/init.sls rename to app/src/Setup/stack/states/enable-xdebug/xdebug/init.sls diff --git a/setup/stack/states/ilias-update-hook/description.txt b/app/src/Setup/stack/states/ilias-update-hook/description.txt similarity index 100% rename from setup/stack/states/ilias-update-hook/description.txt rename to app/src/Setup/stack/states/ilias-update-hook/description.txt diff --git a/setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls b/app/src/Setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls similarity index 100% rename from setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls rename to app/src/Setup/stack/states/ilias-update-hook/ilias-update-hook/init.sls diff --git a/setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 b/app/src/Setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 similarity index 100% rename from setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 rename to app/src/Setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 diff --git a/setup/stack/states/ilias-update-hook/top.sls b/app/src/Setup/stack/states/ilias-update-hook/top.sls similarity index 100% rename from setup/stack/states/ilias-update-hook/top.sls rename to app/src/Setup/stack/states/ilias-update-hook/top.sls diff --git a/setup/stack/states/ilias/ilCron/ilias_cron.sh b/app/src/Setup/stack/states/ilias/ilCron/ilias_cron.sh similarity index 100% rename from setup/stack/states/ilias/ilCron/ilias_cron.sh rename to app/src/Setup/stack/states/ilias/ilCron/ilias_cron.sh diff --git a/setup/stack/states/ilias/ilCron/ilias_cron_9.sh b/app/src/Setup/stack/states/ilias/ilCron/ilias_cron_9.sh similarity index 100% rename from setup/stack/states/ilias/ilCron/ilias_cron_9.sh rename to app/src/Setup/stack/states/ilias/ilCron/ilias_cron_9.sh diff --git a/setup/stack/states/ilias/ilCron/ilias_logrotate b/app/src/Setup/stack/states/ilias/ilCron/ilias_logrotate similarity index 100% rename from setup/stack/states/ilias/ilCron/ilias_logrotate rename to app/src/Setup/stack/states/ilias/ilCron/ilias_logrotate diff --git a/setup/stack/states/ilias/ilCron/init.sls b/app/src/Setup/stack/states/ilias/ilCron/init.sls similarity index 100% rename from setup/stack/states/ilias/ilCron/init.sls rename to app/src/Setup/stack/states/ilias/ilCron/init.sls diff --git a/setup/stack/states/ilias/ilCron/logrotate.sh b/app/src/Setup/stack/states/ilias/ilCron/logrotate.sh similarity index 100% rename from setup/stack/states/ilias/ilCron/logrotate.sh rename to app/src/Setup/stack/states/ilias/ilCron/logrotate.sh diff --git a/setup/stack/states/ilias/ilServer/ilServer.conf b/app/src/Setup/stack/states/ilias/ilServer/ilServer.conf similarity index 100% rename from setup/stack/states/ilias/ilServer/ilServer.conf rename to app/src/Setup/stack/states/ilias/ilServer/ilServer.conf diff --git a/setup/stack/states/ilias/ilServer/ilServer.ini b/app/src/Setup/stack/states/ilias/ilServer/ilServer.ini similarity index 100% rename from setup/stack/states/ilias/ilServer/ilServer.ini rename to app/src/Setup/stack/states/ilias/ilServer/ilServer.ini diff --git a/setup/stack/states/ilias/ilServer/init.sls b/app/src/Setup/stack/states/ilias/ilServer/init.sls similarity index 96% rename from setup/stack/states/ilias/ilServer/init.sls rename to app/src/Setup/stack/states/ilias/ilServer/init.sls index e9caa248..7fa9c5c9 100755 --- a/setup/stack/states/ilias/ilServer/init.sls +++ b/app/src/Setup/stack/states/ilias/ilServer/init.sls @@ -1,12 +1,11 @@ {% set ilias_version = salt['grains.get']('ilias_version', '9') %} +{% if ilias_version | int >= 10 %} ilServer_packages: pkg.installed: - pkgs: - - default-jre - {% if ilias_version | int >= 10 %} - maven - {% endif %} +{% endif %} javaport_grain: grains.present: diff --git a/setup/stack/states/ilias/ilias/init.sls b/app/src/Setup/stack/states/ilias/ilias/init.sls similarity index 100% rename from setup/stack/states/ilias/ilias/init.sls rename to app/src/Setup/stack/states/ilias/ilias/init.sls diff --git a/setup/stack/states/ilias/imagemagick/init.sls b/app/src/Setup/stack/states/ilias/imagemagick/init.sls similarity index 71% rename from setup/stack/states/ilias/imagemagick/init.sls rename to app/src/Setup/stack/states/ilias/imagemagick/init.sls index f07f55f5..b339dedc 100644 --- a/setup/stack/states/ilias/imagemagick/init.sls +++ b/app/src/Setup/stack/states/ilias/imagemagick/init.sls @@ -1,4 +1,4 @@ -/etc/ImageMagick-6/policy.xml: +/etc/ImageMagick-7/policy.xml: file.managed: - user: root - group: root @@ -9,4 +9,4 @@ restart_apache: cmd.wait: - name: supervisorctl restart apache2 - watch: - - file: /etc/ImageMagick-6/policy.xml \ No newline at end of file + - file: /etc/ImageMagick-7/policy.xml \ No newline at end of file diff --git a/setup/stack/states/ilias/imagemagick/policy.xml b/app/src/Setup/stack/states/ilias/imagemagick/policy.xml similarity index 100% rename from setup/stack/states/ilias/imagemagick/policy.xml rename to app/src/Setup/stack/states/ilias/imagemagick/policy.xml diff --git a/setup/stack/states/ilias/openssl-legacy/init.sls b/app/src/Setup/stack/states/ilias/openssl-legacy/init.sls similarity index 100% rename from setup/stack/states/ilias/openssl-legacy/init.sls rename to app/src/Setup/stack/states/ilias/openssl-legacy/init.sls diff --git a/setup/stack/states/ilias/openssl-legacy/openssl.cnf b/app/src/Setup/stack/states/ilias/openssl-legacy/openssl.cnf similarity index 100% rename from setup/stack/states/ilias/openssl-legacy/openssl.cnf rename to app/src/Setup/stack/states/ilias/openssl-legacy/openssl.cnf diff --git a/setup/stack/states/ilias/top.sls b/app/src/Setup/stack/states/ilias/top.sls similarity index 100% rename from setup/stack/states/ilias/top.sls rename to app/src/Setup/stack/states/ilias/top.sls diff --git a/setup/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 b/app/src/Setup/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 similarity index 100% rename from setup/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 rename to app/src/Setup/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 diff --git a/setup/stack/states/keycloak/keycloak/init.sls b/app/src/Setup/stack/states/keycloak/keycloak/init.sls similarity index 100% rename from setup/stack/states/keycloak/keycloak/init.sls rename to app/src/Setup/stack/states/keycloak/keycloak/init.sls diff --git a/setup/stack/states/keycloak/top.sls b/app/src/Setup/stack/states/keycloak/top.sls similarity index 100% rename from setup/stack/states/keycloak/top.sls rename to app/src/Setup/stack/states/keycloak/top.sls diff --git a/setup/stack/states/mailservices/mailservices/check-postbox-configuration.sh b/app/src/Setup/stack/states/mailservices/mailservices/check-postbox-configuration.sh similarity index 100% rename from setup/stack/states/mailservices/mailservices/check-postbox-configuration.sh rename to app/src/Setup/stack/states/mailservices/mailservices/check-postbox-configuration.sh diff --git a/setup/stack/states/mailservices/mailservices/delete-postbox-configuration.sh b/app/src/Setup/stack/states/mailservices/mailservices/delete-postbox-configuration.sh similarity index 100% rename from setup/stack/states/mailservices/mailservices/delete-postbox-configuration.sh rename to app/src/Setup/stack/states/mailservices/mailservices/delete-postbox-configuration.sh diff --git a/setup/stack/states/mailservices/mailservices/dovecot-10-mail.conf b/app/src/Setup/stack/states/mailservices/mailservices/dovecot-10-mail.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/dovecot-10-mail.conf rename to app/src/Setup/stack/states/mailservices/mailservices/dovecot-10-mail.conf diff --git a/setup/stack/states/mailservices/mailservices/dovecot-15-lda.conf b/app/src/Setup/stack/states/mailservices/mailservices/dovecot-15-lda.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/dovecot-15-lda.conf rename to app/src/Setup/stack/states/mailservices/mailservices/dovecot-15-lda.conf diff --git a/setup/stack/states/mailservices/mailservices/dovecot-90-sieve.conf b/app/src/Setup/stack/states/mailservices/mailservices/dovecot-90-sieve.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/dovecot-90-sieve.conf rename to app/src/Setup/stack/states/mailservices/mailservices/dovecot-90-sieve.conf diff --git a/setup/stack/states/mailservices/mailservices/init.sls b/app/src/Setup/stack/states/mailservices/mailservices/init.sls similarity index 87% rename from setup/stack/states/mailservices/mailservices/init.sls rename to app/src/Setup/stack/states/mailservices/mailservices/init.sls index f8697b5a..71a10ead 100755 --- a/setup/stack/states/mailservices/mailservices/init.sls +++ b/app/src/Setup/stack/states/mailservices/mailservices/init.sls @@ -3,32 +3,45 @@ {% set ram = salt['grains.get']('mem_total', '4096') %} {% set doil_host_system = salt['grains.get']('doil_host_system', 'linux') %} +get_wget: + pkg.installed: + - pkgs: + - wget + +php_repo_list: + cmd.run: + - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list + - unless: test -f /etc/apt/sources.list.d/php.list + +php_repo_key: + cmd.run: + - name: wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg + - unless: test -f /etc/apt/trusted.gpg.d/php.gpg + mailservice_packages: pkg.installed: + - refresh: True - pkgs: - apache2 - mariadb-server - python3-mysqldb - postfix - - dovecot-core - - dovecot-imapd - - dovecot-managesieved - roundcube - roundcube-plugins - - libapache2-mod-php8.2 - - php8.2-curl - - php8.2-gd + - libapache2-mod-php8.4 + - php8.4-curl + - php8.4-gd - php-json - - php8.2-mysql - - php8.2-readline - - php8.2-xsl - - php8.2-cli - - php8.2-zip - - php8.2-mbstring - - php8.2-soap - - php8.2-bcmath - - php8.2-imap - - php8.2-xmlrpc + - php8.4-mysql + - php8.4-readline + - php8.4-xsl + - php8.4-cli + - php8.4-zip + - php8.4-mbstring + - php8.4-soap + - php8.4-bcmath + - php8.4-imap + - php8.4-xmlrpc stop_dovecot: cmd.run: @@ -86,7 +99,7 @@ stop_dovecot: a2_enable_php: module.run: - name: apache.a2enmod - - mod: php8.2 + - mod: php8.4 /etc/mailname: file.managed: diff --git a/setup/stack/states/mailservices/mailservices/mailname b/app/src/Setup/stack/states/mailservices/mailservices/mailname similarity index 100% rename from setup/stack/states/mailservices/mailservices/mailname rename to app/src/Setup/stack/states/mailservices/mailservices/mailname diff --git a/setup/stack/states/mailservices/mailservices/mysql-my.cnf b/app/src/Setup/stack/states/mailservices/mailservices/mysql-my.cnf similarity index 100% rename from setup/stack/states/mailservices/mailservices/mysql-my.cnf rename to app/src/Setup/stack/states/mailservices/mailservices/mysql-my.cnf diff --git a/setup/stack/states/mailservices/mailservices/postfix-canonical-redirect b/app/src/Setup/stack/states/mailservices/mailservices/postfix-canonical-redirect similarity index 100% rename from setup/stack/states/mailservices/mailservices/postfix-canonical-redirect rename to app/src/Setup/stack/states/mailservices/mailservices/postfix-canonical-redirect diff --git a/setup/stack/states/mailservices/mailservices/postfix-main.cf b/app/src/Setup/stack/states/mailservices/mailservices/postfix-main.cf similarity index 100% rename from setup/stack/states/mailservices/mailservices/postfix-main.cf rename to app/src/Setup/stack/states/mailservices/mailservices/postfix-main.cf diff --git a/setup/stack/states/mailservices/mailservices/postfix_fg_starter.sh b/app/src/Setup/stack/states/mailservices/mailservices/postfix_fg_starter.sh similarity index 100% rename from setup/stack/states/mailservices/mailservices/postfix_fg_starter.sh rename to app/src/Setup/stack/states/mailservices/mailservices/postfix_fg_starter.sh diff --git a/setup/stack/states/mailservices/mailservices/roundcube-config.inc.php b/app/src/Setup/stack/states/mailservices/mailservices/roundcube-config.inc.php similarity index 100% rename from setup/stack/states/mailservices/mailservices/roundcube-config.inc.php rename to app/src/Setup/stack/states/mailservices/mailservices/roundcube-config.inc.php diff --git a/setup/stack/states/mailservices/mailservices/roundcube-debian-db.php b/app/src/Setup/stack/states/mailservices/mailservices/roundcube-debian-db.php similarity index 100% rename from setup/stack/states/mailservices/mailservices/roundcube-debian-db.php rename to app/src/Setup/stack/states/mailservices/mailservices/roundcube-debian-db.php diff --git a/setup/stack/states/mailservices/mailservices/roundcube.conf b/app/src/Setup/stack/states/mailservices/mailservices/roundcube.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/roundcube.conf rename to app/src/Setup/stack/states/mailservices/mailservices/roundcube.conf diff --git a/setup/stack/states/mailservices/mailservices/service-config-sieve.tpl b/app/src/Setup/stack/states/mailservices/mailservices/service-config-sieve.tpl similarity index 100% rename from setup/stack/states/mailservices/mailservices/service-config-sieve.tpl rename to app/src/Setup/stack/states/mailservices/mailservices/service-config-sieve.tpl diff --git a/setup/stack/states/mailservices/mailservices/service-config.tpl b/app/src/Setup/stack/states/mailservices/mailservices/service-config.tpl similarity index 100% rename from setup/stack/states/mailservices/mailservices/service-config.tpl rename to app/src/Setup/stack/states/mailservices/mailservices/service-config.tpl diff --git a/setup/stack/states/mailservices/mailservices/sv-apache.conf b/app/src/Setup/stack/states/mailservices/mailservices/sv-apache.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/sv-apache.conf rename to app/src/Setup/stack/states/mailservices/mailservices/sv-apache.conf diff --git a/setup/stack/states/mailservices/mailservices/sv-dovecot.conf b/app/src/Setup/stack/states/mailservices/mailservices/sv-dovecot.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/sv-dovecot.conf rename to app/src/Setup/stack/states/mailservices/mailservices/sv-dovecot.conf diff --git a/setup/stack/states/mailservices/mailservices/sv-mysql.conf b/app/src/Setup/stack/states/mailservices/mailservices/sv-mysql.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/sv-mysql.conf rename to app/src/Setup/stack/states/mailservices/mailservices/sv-mysql.conf diff --git a/setup/stack/states/mailservices/mailservices/sv-postfix.conf b/app/src/Setup/stack/states/mailservices/mailservices/sv-postfix.conf similarity index 100% rename from setup/stack/states/mailservices/mailservices/sv-postfix.conf rename to app/src/Setup/stack/states/mailservices/mailservices/sv-postfix.conf diff --git a/setup/stack/states/mailservices/top.sls b/app/src/Setup/stack/states/mailservices/top.sls similarity index 100% rename from setup/stack/states/mailservices/top.sls rename to app/src/Setup/stack/states/mailservices/top.sls diff --git a/setup/stack/states/nodejs/nodejs/init.sls b/app/src/Setup/stack/states/nodejs/nodejs/init.sls similarity index 100% rename from setup/stack/states/nodejs/nodejs/init.sls rename to app/src/Setup/stack/states/nodejs/nodejs/init.sls diff --git a/setup/stack/states/nodejs/top.sls b/app/src/Setup/stack/states/nodejs/top.sls similarity index 100% rename from setup/stack/states/nodejs/top.sls rename to app/src/Setup/stack/states/nodejs/top.sls diff --git a/setup/stack/states/php7.2/description.txt b/app/src/Setup/stack/states/php7.2/description.txt similarity index 100% rename from setup/stack/states/php7.2/description.txt rename to app/src/Setup/stack/states/php7.2/description.txt diff --git a/setup/stack/states/php7.2/php/init.sls b/app/src/Setup/stack/states/php7.2/php/init.sls similarity index 97% rename from setup/stack/states/php7.2/php/init.sls rename to app/src/Setup/stack/states/php7.2/php/init.sls index 945c7264..69533a4d 100755 --- a/setup/stack/states/php7.2/php/init.sls +++ b/app/src/Setup/stack/states/php7.2/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php7.2/top.sls b/app/src/Setup/stack/states/php7.2/top.sls similarity index 100% rename from setup/stack/states/php7.2/top.sls rename to app/src/Setup/stack/states/php7.2/top.sls diff --git a/setup/stack/states/php7.3/description.txt b/app/src/Setup/stack/states/php7.3/description.txt similarity index 100% rename from setup/stack/states/php7.3/description.txt rename to app/src/Setup/stack/states/php7.3/description.txt diff --git a/setup/stack/states/php7.3/php/init.sls b/app/src/Setup/stack/states/php7.3/php/init.sls similarity index 97% rename from setup/stack/states/php7.3/php/init.sls rename to app/src/Setup/stack/states/php7.3/php/init.sls index 9f23bf0b..4f7becf7 100755 --- a/setup/stack/states/php7.3/php/init.sls +++ b/app/src/Setup/stack/states/php7.3/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php7.3/top.sls b/app/src/Setup/stack/states/php7.3/top.sls similarity index 100% rename from setup/stack/states/php7.3/top.sls rename to app/src/Setup/stack/states/php7.3/top.sls diff --git a/setup/stack/states/php7.4/description.txt b/app/src/Setup/stack/states/php7.4/description.txt similarity index 100% rename from setup/stack/states/php7.4/description.txt rename to app/src/Setup/stack/states/php7.4/description.txt diff --git a/setup/stack/states/php7.4/php/init.sls b/app/src/Setup/stack/states/php7.4/php/init.sls similarity index 97% rename from setup/stack/states/php7.4/php/init.sls rename to app/src/Setup/stack/states/php7.4/php/init.sls index 827c0a9f..3c069d81 100755 --- a/setup/stack/states/php7.4/php/init.sls +++ b/app/src/Setup/stack/states/php7.4/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php7.4/top.sls b/app/src/Setup/stack/states/php7.4/top.sls similarity index 100% rename from setup/stack/states/php7.4/top.sls rename to app/src/Setup/stack/states/php7.4/top.sls diff --git a/setup/stack/states/php8.0/description.txt b/app/src/Setup/stack/states/php8.0/description.txt similarity index 100% rename from setup/stack/states/php8.0/description.txt rename to app/src/Setup/stack/states/php8.0/description.txt diff --git a/setup/stack/states/php8.0/php/init.sls b/app/src/Setup/stack/states/php8.0/php/init.sls similarity index 97% rename from setup/stack/states/php8.0/php/init.sls rename to app/src/Setup/stack/states/php8.0/php/init.sls index 58906c17..67d0d8d9 100755 --- a/setup/stack/states/php8.0/php/init.sls +++ b/app/src/Setup/stack/states/php8.0/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php8.0/top.sls b/app/src/Setup/stack/states/php8.0/top.sls similarity index 100% rename from setup/stack/states/php8.0/top.sls rename to app/src/Setup/stack/states/php8.0/top.sls diff --git a/setup/stack/states/php8.1/description.txt b/app/src/Setup/stack/states/php8.1/description.txt similarity index 100% rename from setup/stack/states/php8.1/description.txt rename to app/src/Setup/stack/states/php8.1/description.txt diff --git a/setup/stack/states/php8.1/php/init.sls b/app/src/Setup/stack/states/php8.1/php/init.sls similarity index 97% rename from setup/stack/states/php8.1/php/init.sls rename to app/src/Setup/stack/states/php8.1/php/init.sls index fe8a0bda..f2da8f4a 100755 --- a/setup/stack/states/php8.1/php/init.sls +++ b/app/src/Setup/stack/states/php8.1/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php8.1/top.sls b/app/src/Setup/stack/states/php8.1/top.sls similarity index 100% rename from setup/stack/states/php8.1/top.sls rename to app/src/Setup/stack/states/php8.1/top.sls diff --git a/setup/stack/states/php8.2/description.txt b/app/src/Setup/stack/states/php8.2/description.txt similarity index 100% rename from setup/stack/states/php8.2/description.txt rename to app/src/Setup/stack/states/php8.2/description.txt diff --git a/setup/stack/states/php8.2/php/init.sls b/app/src/Setup/stack/states/php8.2/php/init.sls similarity index 97% rename from setup/stack/states/php8.2/php/init.sls rename to app/src/Setup/stack/states/php8.2/php/init.sls index e76f0742..3cb1f3e6 100755 --- a/setup/stack/states/php8.2/php/init.sls +++ b/app/src/Setup/stack/states/php8.2/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php8.2/top.sls b/app/src/Setup/stack/states/php8.2/top.sls similarity index 100% rename from setup/stack/states/php8.2/top.sls rename to app/src/Setup/stack/states/php8.2/top.sls diff --git a/setup/stack/states/php8.3/description.txt b/app/src/Setup/stack/states/php8.3/description.txt similarity index 100% rename from setup/stack/states/php8.3/description.txt rename to app/src/Setup/stack/states/php8.3/description.txt diff --git a/setup/stack/states/php8.3/php/init.sls b/app/src/Setup/stack/states/php8.3/php/init.sls similarity index 97% rename from setup/stack/states/php8.3/php/init.sls rename to app/src/Setup/stack/states/php8.3/php/init.sls index 965b27a4..55a6c256 100755 --- a/setup/stack/states/php8.3/php/init.sls +++ b/app/src/Setup/stack/states/php8.3/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php8.3/top.sls b/app/src/Setup/stack/states/php8.3/top.sls similarity index 100% rename from setup/stack/states/php8.3/top.sls rename to app/src/Setup/stack/states/php8.3/top.sls diff --git a/setup/stack/states/php8.4/description.txt b/app/src/Setup/stack/states/php8.4/description.txt similarity index 100% rename from setup/stack/states/php8.4/description.txt rename to app/src/Setup/stack/states/php8.4/description.txt diff --git a/setup/stack/states/php8.4/php/init.sls b/app/src/Setup/stack/states/php8.4/php/init.sls similarity index 97% rename from setup/stack/states/php8.4/php/init.sls rename to app/src/Setup/stack/states/php8.4/php/init.sls index 03e54db8..261814a5 100755 --- a/setup/stack/states/php8.4/php/init.sls +++ b/app/src/Setup/stack/states/php8.4/php/init.sls @@ -1,7 +1,3 @@ -apt_https: - pkg.installed: - - name: software-properties-common - php_repo_list: cmd.run: - name: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list diff --git a/setup/stack/states/php8.4/top.sls b/app/src/Setup/stack/states/php8.4/top.sls similarity index 100% rename from setup/stack/states/php8.4/top.sls rename to app/src/Setup/stack/states/php8.4/top.sls diff --git a/setup/stack/states/prevent-super-global-replacement/description.txt b/app/src/Setup/stack/states/prevent-super-global-replacement/description.txt similarity index 100% rename from setup/stack/states/prevent-super-global-replacement/description.txt rename to app/src/Setup/stack/states/prevent-super-global-replacement/description.txt diff --git a/setup/stack/states/prevent-super-global-replacement/prevent-super-global-replacement/init.sls b/app/src/Setup/stack/states/prevent-super-global-replacement/prevent-super-global-replacement/init.sls similarity index 100% rename from setup/stack/states/prevent-super-global-replacement/prevent-super-global-replacement/init.sls rename to app/src/Setup/stack/states/prevent-super-global-replacement/prevent-super-global-replacement/init.sls diff --git a/setup/stack/states/prevent-super-global-replacement/top.sls b/app/src/Setup/stack/states/prevent-super-global-replacement/top.sls similarity index 100% rename from setup/stack/states/prevent-super-global-replacement/top.sls rename to app/src/Setup/stack/states/prevent-super-global-replacement/top.sls diff --git a/setup/stack/states/proxy-enable-https/https/init.sls b/app/src/Setup/stack/states/proxy-enable-https/https/init.sls similarity index 100% rename from setup/stack/states/proxy-enable-https/https/init.sls rename to app/src/Setup/stack/states/proxy-enable-https/https/init.sls diff --git a/setup/stack/states/proxy-enable-https/top.sls b/app/src/Setup/stack/states/proxy-enable-https/top.sls similarity index 100% rename from setup/stack/states/proxy-enable-https/top.sls rename to app/src/Setup/stack/states/proxy-enable-https/top.sls diff --git a/setup/stack/states/proxyservices/proxyservices/add-configuration.sh b/app/src/Setup/stack/states/proxyservices/proxyservices/add-configuration.sh similarity index 100% rename from setup/stack/states/proxyservices/proxyservices/add-configuration.sh rename to app/src/Setup/stack/states/proxyservices/proxyservices/add-configuration.sh diff --git a/setup/stack/states/proxyservices/proxyservices/check-for-lost-minions.sh b/app/src/Setup/stack/states/proxyservices/proxyservices/check-for-lost-minions.sh similarity index 100% rename from setup/stack/states/proxyservices/proxyservices/check-for-lost-minions.sh rename to app/src/Setup/stack/states/proxyservices/proxyservices/check-for-lost-minions.sh diff --git a/setup/stack/states/proxyservices/proxyservices/init.sls b/app/src/Setup/stack/states/proxyservices/proxyservices/init.sls similarity index 100% rename from setup/stack/states/proxyservices/proxyservices/init.sls rename to app/src/Setup/stack/states/proxyservices/proxyservices/init.sls diff --git a/setup/stack/states/proxyservices/proxyservices/service-config.tpl b/app/src/Setup/stack/states/proxyservices/proxyservices/service-config.tpl similarity index 100% rename from setup/stack/states/proxyservices/proxyservices/service-config.tpl rename to app/src/Setup/stack/states/proxyservices/proxyservices/service-config.tpl diff --git a/setup/stack/states/proxyservices/proxyservices/sv-nginx.conf b/app/src/Setup/stack/states/proxyservices/proxyservices/sv-nginx.conf similarity index 100% rename from setup/stack/states/proxyservices/proxyservices/sv-nginx.conf rename to app/src/Setup/stack/states/proxyservices/proxyservices/sv-nginx.conf diff --git a/setup/stack/states/proxyservices/top.sls b/app/src/Setup/stack/states/proxyservices/top.sls similarity index 100% rename from setup/stack/states/proxyservices/top.sls rename to app/src/Setup/stack/states/proxyservices/top.sls diff --git a/setup/stack/states/reactor/postfix_on_minion_start.sls b/app/src/Setup/stack/states/reactor/postfix_on_minion_start.sls similarity index 100% rename from setup/stack/states/reactor/postfix_on_minion_start.sls rename to app/src/Setup/stack/states/reactor/postfix_on_minion_start.sls diff --git a/setup/stack/states/reactor/proxy_on_minion_start.sls b/app/src/Setup/stack/states/reactor/proxy_on_minion_start.sls similarity index 100% rename from setup/stack/states/reactor/proxy_on_minion_start.sls rename to app/src/Setup/stack/states/reactor/proxy_on_minion_start.sls diff --git a/setup/stack/states/reactor/proxy_on_minion_stop.sls b/app/src/Setup/stack/states/reactor/proxy_on_minion_stop.sls similarity index 100% rename from setup/stack/states/reactor/proxy_on_minion_stop.sls rename to app/src/Setup/stack/states/reactor/proxy_on_minion_stop.sls diff --git a/setup/stack/states/reset-ilias-root-password/description.txt b/app/src/Setup/stack/states/reset-ilias-root-password/description.txt similarity index 100% rename from setup/stack/states/reset-ilias-root-password/description.txt rename to app/src/Setup/stack/states/reset-ilias-root-password/description.txt diff --git a/setup/stack/states/reset-ilias-root-password/reset-ilias-root-password/init.sls b/app/src/Setup/stack/states/reset-ilias-root-password/reset-ilias-root-password/init.sls similarity index 100% rename from setup/stack/states/reset-ilias-root-password/reset-ilias-root-password/init.sls rename to app/src/Setup/stack/states/reset-ilias-root-password/reset-ilias-root-password/init.sls diff --git a/setup/stack/states/reset-ilias-root-password/top.sls b/app/src/Setup/stack/states/reset-ilias-root-password/top.sls similarity index 100% rename from setup/stack/states/reset-ilias-root-password/top.sls rename to app/src/Setup/stack/states/reset-ilias-root-password/top.sls diff --git a/setup/stack/states/set-update-token/description.txt b/app/src/Setup/stack/states/set-update-token/description.txt similarity index 100% rename from setup/stack/states/set-update-token/description.txt rename to app/src/Setup/stack/states/set-update-token/description.txt diff --git a/setup/stack/states/set-update-token/set-update-token/init.sls b/app/src/Setup/stack/states/set-update-token/set-update-token/init.sls similarity index 100% rename from setup/stack/states/set-update-token/set-update-token/init.sls rename to app/src/Setup/stack/states/set-update-token/set-update-token/init.sls diff --git a/setup/stack/states/set-update-token/top.sls b/app/src/Setup/stack/states/set-update-token/top.sls similarity index 100% rename from setup/stack/states/set-update-token/top.sls rename to app/src/Setup/stack/states/set-update-token/top.sls diff --git a/app/src/Setup/templates/base/Dockerfile b/app/src/Setup/templates/base/Dockerfile new file mode 100755 index 00000000..9147e53f --- /dev/null +++ b/app/src/Setup/templates/base/Dockerfile @@ -0,0 +1,62 @@ +FROM debian:13 + +RUN apt-get update && apt-get install -y supervisor wget + +RUN mkdir -p /etc/apt/keyrings +RUN echo "deb https://packages.sury.org/php/ trixie main" > /etc/apt/sources.list.d/php.list +RUN wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg + +RUN apt-get update && apt-get install -y \ + default-jdk-headless \ + cron \ + apache2 \ + mc \ + vim \ + nano \ + less \ + zip \ + unzip \ + git \ + tree \ + ftp \ + curl \ + imagemagick \ + ghostscript \ + npm \ + libapache2-mod-php8.4 \ + php8.4-curl \ + php8.4-gd \ + php-json \ + php8.4-mysql \ + php8.4-readline \ + php8.4-xsl \ + php8.4-cli \ + php8.4-zip \ + php8.4-mbstring \ + php8.4-soap \ + php8.4-bcmath \ + php8.4-imap \ + apt-utils \ + mariadb-server \ + python3-mysqldb \ + python3-dev \ + default-libmysqlclient-dev \ + build-essential \ + pkg-config + +RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb +RUN apt install -y ./wkhtmltox_0.12.6.1-3.bookworm_amd64.deb + +RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp +RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources +RUN apt-get update && apt-get install -y salt-minion + +RUN /opt/saltstack/salt/bin/python3 -m pip install --upgrade pip +RUN /opt/saltstack/salt/bin/python3 -m pip install mysql + +RUN apt-get update && apt-get remove -y python3-dev default-libmysqlclient-dev build-essential pkg-config + +RUN echo "#!/bin/bash" > /usr/local/bin/run-supervisor.sh && echo "/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf" >> /usr/local/bin/run-supervisor.sh +RUN chmod +x /usr/local/bin/run-supervisor.sh + +ENTRYPOINT ["/usr/local/bin/run-supervisor.sh"] diff --git a/setup/templates/keycloak/Dockerfile b/app/src/Setup/templates/keycloak/Dockerfile similarity index 98% rename from setup/templates/keycloak/Dockerfile rename to app/src/Setup/templates/keycloak/Dockerfile index 1ea186cc..c5d59c4b 100644 --- a/setup/templates/keycloak/Dockerfile +++ b/app/src/Setup/templates/keycloak/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:12 +FROM debian:13 RUN apt-get update && apt-get install -y supervisor RUN apt-get update && apt-get install -y vim jq nano less virt-what net-tools procps curl unzip mariadb-server python3-dev default-libmysqlclient-dev build-essential pkg-config @@ -16,6 +16,7 @@ RUN unzip keycloak-25.0.5.zip RUN mv keycloak-25.0.5 /opt/keycloak RUN rm keycloak-25.0.5.zip +RUN mkdir -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources RUN apt-get update && apt-get install -y salt-minion diff --git a/setup/templates/keycloak/conf/init.sql b/app/src/Setup/templates/keycloak/conf/init.sql similarity index 100% rename from setup/templates/keycloak/conf/init.sql rename to app/src/Setup/templates/keycloak/conf/init.sql diff --git a/setup/templates/keycloak/conf/keycloak-startup.conf b/app/src/Setup/templates/keycloak/conf/keycloak-startup.conf similarity index 100% rename from setup/templates/keycloak/conf/keycloak-startup.conf rename to app/src/Setup/templates/keycloak/conf/keycloak-startup.conf diff --git a/setup/templates/keycloak/conf/minion.cnf b/app/src/Setup/templates/keycloak/conf/minion.cnf similarity index 100% rename from setup/templates/keycloak/conf/minion.cnf rename to app/src/Setup/templates/keycloak/conf/minion.cnf diff --git a/setup/templates/keycloak/conf/mysql.conf b/app/src/Setup/templates/keycloak/conf/mysql.conf similarity index 100% rename from setup/templates/keycloak/conf/mysql.conf rename to app/src/Setup/templates/keycloak/conf/mysql.conf diff --git a/setup/templates/keycloak/conf/mysql_starter.sh b/app/src/Setup/templates/keycloak/conf/mysql_starter.sh similarity index 100% rename from setup/templates/keycloak/conf/mysql_starter.sh rename to app/src/Setup/templates/keycloak/conf/mysql_starter.sh diff --git a/setup/templates/keycloak/conf/run-supervisor.sh b/app/src/Setup/templates/keycloak/conf/run-supervisor.sh similarity index 100% rename from setup/templates/keycloak/conf/run-supervisor.sh rename to app/src/Setup/templates/keycloak/conf/run-supervisor.sh diff --git a/setup/templates/keycloak/conf/salt-minion.conf b/app/src/Setup/templates/keycloak/conf/salt-minion.conf similarity index 100% rename from setup/templates/keycloak/conf/salt-minion.conf rename to app/src/Setup/templates/keycloak/conf/salt-minion.conf diff --git a/setup/templates/keycloak/conf/salt-startup.sh b/app/src/Setup/templates/keycloak/conf/salt-startup.sh similarity index 100% rename from setup/templates/keycloak/conf/salt-startup.sh rename to app/src/Setup/templates/keycloak/conf/salt-startup.sh diff --git a/setup/templates/keycloak/conf/startup.conf b/app/src/Setup/templates/keycloak/conf/startup.conf similarity index 100% rename from setup/templates/keycloak/conf/startup.conf rename to app/src/Setup/templates/keycloak/conf/startup.conf diff --git a/setup/templates/keycloak/docker-compose.yml b/app/src/Setup/templates/keycloak/docker-compose.yml similarity index 92% rename from setup/templates/keycloak/docker-compose.yml rename to app/src/Setup/templates/keycloak/docker-compose.yml index 218987b0..19a2387c 100644 --- a/setup/templates/keycloak/docker-compose.yml +++ b/app/src/Setup/templates/keycloak/docker-compose.yml @@ -10,14 +10,14 @@ services: networks: doil_proxy: ipv4_address: 172.24.0.250 - salt_saltnet: + doil_saltnet: volumes: - keycloak_1:/var/lib/mysql - admin:/root/.keycloak networks: doil_proxy: external: true - salt_saltnet: + doil_saltnet: external: true volumes: keycloak_1: diff --git a/setup/templates/mail/Dockerfile b/app/src/Setup/templates/mail/Dockerfile similarity index 66% rename from setup/templates/mail/Dockerfile rename to app/src/Setup/templates/mail/Dockerfile index 4db0666d..34e05e7d 100755 --- a/setup/templates/mail/Dockerfile +++ b/app/src/Setup/templates/mail/Dockerfile @@ -1,9 +1,10 @@ -FROM debian:12 +FROM debian:13 # base RUN apt-get update && apt-get install -y supervisor RUN apt-get update && apt-get install -y vim nano curl less virt-what net-tools procps git debconf-utils python3-dev default-libmysqlclient-dev build-essential pkg-config +RUN mkdir -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources RUN apt-get update && apt-get install -y salt-minion @@ -13,6 +14,13 @@ RUN /opt/saltstack/salt/bin/python3 -m pip install mysql RUN apt-get update && apt-get remove -y python3-dev default-libmysqlclient-dev build-essential pkg-config +RUN echo "deb http://deb.debian.org/debian bookworm main\ndeb http://security.debian.org/debian-security bookworm-security main" | tee /etc/apt/sources.list.d/bookworm.list + +COPY conf/dovecot-23.pref /etc/apt/preferences.d/dovecot-23.pref + +RUN apt-get update && apt-get install -y -t=bookworm dovecot-core dovecot-imapd dovecot-sieve dovecot-managesieved +RUN apt-mark hold dovecot-core dovecot-imapd dovecot-sieve dovecot-managesieved + COPY conf/run-supervisor.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/run-supervisor.sh CMD ["/usr/local/bin/run-supervisor.sh"] diff --git a/app/src/Setup/templates/mail/conf/dovecot-23.pref b/app/src/Setup/templates/mail/conf/dovecot-23.pref new file mode 100644 index 00000000..a0c8002f --- /dev/null +++ b/app/src/Setup/templates/mail/conf/dovecot-23.pref @@ -0,0 +1,3 @@ +Package: dovecot* +Pin: release n=bookworm +Pin-Priority: 1001 \ No newline at end of file diff --git a/setup/templates/mail/conf/minion.cnf b/app/src/Setup/templates/mail/conf/minion.cnf similarity index 100% rename from setup/templates/mail/conf/minion.cnf rename to app/src/Setup/templates/mail/conf/minion.cnf diff --git a/setup/templates/mail/conf/run-supervisor.sh b/app/src/Setup/templates/mail/conf/run-supervisor.sh similarity index 100% rename from setup/templates/mail/conf/run-supervisor.sh rename to app/src/Setup/templates/mail/conf/run-supervisor.sh diff --git a/setup/templates/mail/conf/salt-minion.conf b/app/src/Setup/templates/mail/conf/salt-minion.conf similarity index 100% rename from setup/templates/mail/conf/salt-minion.conf rename to app/src/Setup/templates/mail/conf/salt-minion.conf diff --git a/setup/templates/mail/conf/salt-startup.sh b/app/src/Setup/templates/mail/conf/salt-startup.sh similarity index 100% rename from setup/templates/mail/conf/salt-startup.sh rename to app/src/Setup/templates/mail/conf/salt-startup.sh diff --git a/setup/templates/mail/conf/startup.conf b/app/src/Setup/templates/mail/conf/startup.conf similarity index 100% rename from setup/templates/mail/conf/startup.conf rename to app/src/Setup/templates/mail/conf/startup.conf diff --git a/setup/templates/mail/docker-compose.yml b/app/src/Setup/templates/mail/docker-compose.yml similarity index 80% rename from setup/templates/mail/docker-compose.yml rename to app/src/Setup/templates/mail/docker-compose.yml index ad04db5a..86a337e6 100755 --- a/setup/templates/mail/docker-compose.yml +++ b/app/src/Setup/templates/mail/docker-compose.yml @@ -10,7 +10,7 @@ services: networks: doil_proxy: ipv4_address: 172.24.0.253 - salt_saltnet: + doil_saltnet: volumes: - type: bind source: ./conf/salt-startup.sh @@ -24,13 +24,15 @@ services: - type: bind source: ./conf/minion.cnf target: /etc/salt/minion - - sieve:/var/www/sieve - - mail:/var/mail + - doil_sieve:/var/www/sieve + - doil_mail:/var/mail networks: doil_proxy: external: true - salt_saltnet: + doil_saltnet: external: true volumes: - sieve: - mail: + doil_sieve: + name: doil_sieve + doil_mail: + name: doil_mail diff --git a/setup/templates/minion/README.md b/app/src/Setup/templates/minion/README.md similarity index 100% rename from setup/templates/minion/README.md rename to app/src/Setup/templates/minion/README.md diff --git a/setup/templates/minion/docker-compose-mac.yml b/app/src/Setup/templates/minion/docker-compose-mac.yml similarity index 97% rename from setup/templates/minion/docker-compose-mac.yml rename to app/src/Setup/templates/minion/docker-compose-mac.yml index 366f6047..45309c27 100755 --- a/setup/templates/minion/docker-compose-mac.yml +++ b/app/src/Setup/templates/minion/docker-compose-mac.yml @@ -30,12 +30,12 @@ services: - JAVA_SERVER_PATH=/var/www/html/Services/WebServices/RPC/lib - JAVA_SERVER_START networks: - - main_saltnet + - doil_saltnet - doil_proxy networks: doil_proxy: external: true - main_saltnet: + doil_saltnet: external: true volumes: persistent: diff --git a/setup/templates/minion/docker-compose.yml b/app/src/Setup/templates/minion/docker-compose.yml similarity index 97% rename from setup/templates/minion/docker-compose.yml rename to app/src/Setup/templates/minion/docker-compose.yml index 10ed9813..f39b4c77 100755 --- a/setup/templates/minion/docker-compose.yml +++ b/app/src/Setup/templates/minion/docker-compose.yml @@ -56,9 +56,9 @@ services: - JAVA_SERVER_START networks: - doil_proxy - - salt_saltnet + - doil_saltnet networks: doil_proxy: external: true - salt_saltnet: + doil_saltnet: external: true diff --git a/setup/templates/minion/run-supervisor.sh b/app/src/Setup/templates/minion/run-supervisor.sh similarity index 100% rename from setup/templates/minion/run-supervisor.sh rename to app/src/Setup/templates/minion/run-supervisor.sh diff --git a/setup/templates/minion/salt-minion.conf b/app/src/Setup/templates/minion/salt-minion.conf similarity index 100% rename from setup/templates/minion/salt-minion.conf rename to app/src/Setup/templates/minion/salt-minion.conf diff --git a/setup/templates/proxy/Dockerfile b/app/src/Setup/templates/proxy/Dockerfile similarity index 93% rename from setup/templates/proxy/Dockerfile rename to app/src/Setup/templates/proxy/Dockerfile index 141f2d41..ba6c2320 100755 --- a/setup/templates/proxy/Dockerfile +++ b/app/src/Setup/templates/proxy/Dockerfile @@ -1,8 +1,9 @@ -FROM debian:12 +FROM debian:13 RUN apt-get update && apt-get install -y supervisor RUN apt-get update && apt-get install -y vim nano less virt-what net-tools procps curl +RUN mkdir -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources RUN apt-get update && apt-get install -y salt-minion diff --git a/setup/templates/proxy/conf/generate_index_html.sh b/app/src/Setup/templates/proxy/conf/generate_index_html.sh similarity index 100% rename from setup/templates/proxy/conf/generate_index_html.sh rename to app/src/Setup/templates/proxy/conf/generate_index_html.sh diff --git a/setup/templates/proxy/conf/localcerts/apache.key b/app/src/Setup/templates/proxy/conf/localcerts/apache.key similarity index 100% rename from setup/templates/proxy/conf/localcerts/apache.key rename to app/src/Setup/templates/proxy/conf/localcerts/apache.key diff --git a/setup/templates/proxy/conf/localcerts/apache.pem b/app/src/Setup/templates/proxy/conf/localcerts/apache.pem similarity index 100% rename from setup/templates/proxy/conf/localcerts/apache.pem rename to app/src/Setup/templates/proxy/conf/localcerts/apache.pem diff --git a/setup/templates/proxy/conf/minion.cnf b/app/src/Setup/templates/proxy/conf/minion.cnf similarity index 100% rename from setup/templates/proxy/conf/minion.cnf rename to app/src/Setup/templates/proxy/conf/minion.cnf diff --git a/setup/templates/proxy/conf/nginx/local.conf b/app/src/Setup/templates/proxy/conf/nginx/local.conf similarity index 100% rename from setup/templates/proxy/conf/nginx/local.conf rename to app/src/Setup/templates/proxy/conf/nginx/local.conf diff --git a/setup/templates/proxy/conf/nginx/sites/.gitkeep b/app/src/Setup/templates/proxy/conf/nginx/sites/.gitkeep similarity index 100% rename from setup/templates/proxy/conf/nginx/sites/.gitkeep rename to app/src/Setup/templates/proxy/conf/nginx/sites/.gitkeep diff --git a/setup/templates/proxy/conf/robots.txt b/app/src/Setup/templates/proxy/conf/robots.txt similarity index 100% rename from setup/templates/proxy/conf/robots.txt rename to app/src/Setup/templates/proxy/conf/robots.txt diff --git a/setup/templates/proxy/conf/run-supervisor.sh b/app/src/Setup/templates/proxy/conf/run-supervisor.sh similarity index 100% rename from setup/templates/proxy/conf/run-supervisor.sh rename to app/src/Setup/templates/proxy/conf/run-supervisor.sh diff --git a/setup/templates/proxy/conf/salt-minion.conf b/app/src/Setup/templates/proxy/conf/salt-minion.conf similarity index 100% rename from setup/templates/proxy/conf/salt-minion.conf rename to app/src/Setup/templates/proxy/conf/salt-minion.conf diff --git a/setup/templates/proxy/conf/salt-startup.sh b/app/src/Setup/templates/proxy/conf/salt-startup.sh similarity index 100% rename from setup/templates/proxy/conf/salt-startup.sh rename to app/src/Setup/templates/proxy/conf/salt-startup.sh diff --git a/setup/templates/proxy/conf/startup.conf b/app/src/Setup/templates/proxy/conf/startup.conf similarity index 100% rename from setup/templates/proxy/conf/startup.conf rename to app/src/Setup/templates/proxy/conf/startup.conf diff --git a/setup/templates/proxy/docker-compose.yml b/app/src/Setup/templates/proxy/docker-compose.yml similarity index 97% rename from setup/templates/proxy/docker-compose.yml rename to app/src/Setup/templates/proxy/docker-compose.yml index 9a47b8de..fbfda463 100755 --- a/setup/templates/proxy/docker-compose.yml +++ b/app/src/Setup/templates/proxy/docker-compose.yml @@ -10,7 +10,7 @@ services: networks: doil_proxy: ipv4_address: 172.24.0.254 - salt_saltnet: + doil_saltnet: ports: - "80:80" - "443:443" @@ -40,7 +40,7 @@ services: source: ./conf/robots.txt target: /var/www/html/robots.txt networks: - salt_saltnet: + doil_saltnet: external: true doil_proxy: name: doil_proxy diff --git a/setup/templates/salt/Dockerfile b/app/src/Setup/templates/salt/Dockerfile similarity index 91% rename from setup/templates/salt/Dockerfile rename to app/src/Setup/templates/salt/Dockerfile index c1d40994..47290b89 100755 --- a/setup/templates/salt/Dockerfile +++ b/app/src/Setup/templates/salt/Dockerfile @@ -1,7 +1,8 @@ -FROM debian:12 +FROM debian:13 RUN apt-get update && apt-get install -y vim nano less virt-what net-tools procps curl +RUN mkdir -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources RUN apt-get update && apt-get install -y salt-master diff --git a/setup/templates/salt/docker-compose.yml b/app/src/Setup/templates/salt/docker-compose.yml similarity index 72% rename from setup/templates/salt/docker-compose.yml rename to app/src/Setup/templates/salt/docker-compose.yml index 5cd1e826..ca88fae5 100755 --- a/setup/templates/salt/docker-compose.yml +++ b/app/src/Setup/templates/salt/docker-compose.yml @@ -1,20 +1,21 @@ services: - doil_saltmain: + doil_salt: build: context: . dockerfile: Dockerfile - image: doil_saltmain:stable - container_name: doil_saltmain + image: doil_salt:stable + container_name: doil_salt hostname: doil - domainname: saltmain + domainname: salt volumes: - /usr/local/share/doil/stack/states:/srv/salt/states - /usr/local/share/doil/stack/config/master.cnf:/etc/salt/master networks: - saltnet: + doil_saltnet: ipv4_address: 172.20.0.254 networks: - saltnet: + doil_saltnet: + name: doil_saltnet ipam: driver: default config: diff --git a/app/src/cli.php b/app/src/cli.php index ec46bd05..0c11b71c 100644 --- a/app/src/cli.php +++ b/app/src/cli.php @@ -8,31 +8,172 @@ use CaT\Doil\Commands\Repo; use CaT\Doil\Commands\Pack; use CaT\Doil\Commands\Salt; +use CaT\Doil\Commands\System; use CaT\Doil\Commands\User; +use CaT\Doil\Setup\Install; use CaT\Doil\Commands\Proxy; use CaT\Doil\Lib\Git\GitShell; use CaT\Doil\Lib\ProjectConfig; use CaT\Doil\Commands\Keycloak; +use CaT\Doil\Lib\System\Update; use CaT\Doil\Commands\Instances; use CaT\Doil\Lib\ILIAS\IliasInfo; use CaT\Doil\Lib\Posix\PosixShell; use CaT\Doil\Lib\Linux\LinuxShell; use CaT\Doil\Lib\Docker\DockerShell; +use CaT\Doil\Lib\Config\ConfigReader; use CaT\Doil\Lib\Logger\LoggerFactory; +use CaT\Doil\Lib\Config\ConfigChecker; use CaT\Doil\Commands\Repo\RepoManager; +use CaT\Doil\Setup\Server\StartServers; +use CaT\Doil\Lib\ConsoleOutput\SetupWriter; use CaT\Doil\Lib\FileSystem\FilesystemShell; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Helper\QuestionHelper; require_once __DIR__ . "/../vendor/autoload.php"; -$c = buildContainerForApp(); -$app = $c["app"]; -$app->run(); +$command = $argv[1] ?? ""; +$script_dir = $argv[2] ?? ""; +$home_dir = $argv[3] ?? ""; +$user_name = $argv[4] ?? ""; -function buildContainerForApp() : Container +unset($_SERVER['argv'][1]); +unset($_SERVER['argv'][2]); +unset($_SERVER['argv'][3]); +unset($_SERVER['argv'][4]); +unset($_SERVER['argv'][5]); + +$_SERVER['argv'] = array_values($_SERVER['argv']); + +$c = buildContainerForApp($script_dir, $home_dir, $user_name); + +switch ($command) { + case "install": + $install = $c["install"]; + $install->run(); + break; + default: + $app = $c["app"]; + $app->run(); +} + +function buildContainerForApp(string $script_dir = "", string $home_dir = "", string $user_name = "") : Container { $c = new Container(); + $c["install"] = function($c) use ($script_dir) { + return new Install( + $c["logger"], + $c["setup.question_helper"], + $c["setup.output"], + $c["setup.input"], + $c["setup.writer"], + $c["setup.base_directories"], + $c["setup.base_files"], + $c["setup.copy"], + $c["setup.ip"], + $c["setup.config_reader"], + $c["setup.config_checker"], + $c["filesystem.shell"], + $c["setup.server.start"], + $script_dir + ); + }; + + $c["setup.server.start"] = function($c) { + return new StartServers( + $c["setup.salt"], + $c["setup.proxy"], + $c["setup.mail"], + $c["setup.keycloak"], + ); + }; + + $c["setup.question_helper"] = function($c) { + return new QuestionHelper(); + }; + + $c["setup.output"] = function($c) { + return new ConsoleOutput(); + }; + + $c["setup.input"] = function($c) { + return new ArgvInput(); + }; + + $c["setup.writer"] = function($c) { + return new SetupWriter(); + }; + + $c["setup.base_directories"] = function($c) use ($home_dir, $user_name) { + return new CaT\Doil\Setup\FileStructure\BaseDirectories( + $c["filesystem.shell"], + $home_dir, + $user_name + ); + }; + + $c["setup.base_files"] = function($c) use ($home_dir, $user_name) { + return new CaT\Doil\Setup\FileStructure\BaseFiles( + $c["filesystem.shell"], + $home_dir, + $user_name + ); + }; + + $c["setup.copy"] = function($c) { + return new CaT\Doil\Setup\CopyFiles\Copy( + $c["filesystem.shell"] + ); + }; + + $c["setup.ip"] = function($c) { + return new CaT\Doil\Setup\IP\IP( + $c["filesystem.shell"], + ); + }; + + $c["setup.config_reader"] = function($c) { + return new ConfigReader( + $c["setup.config"], + $c["filesystem.shell"], + ); + }; + + $c["setup.config_checker"] = function($c) { + return new ConfigChecker( + $c["filesystem.shell"] + ); + }; + + $c["setup.config"] = function($c) { + return new CaT\Doil\Lib\Config\Config(); + }; + + $c["setup.salt"] = function($c) { + return new CaT\Doil\Setup\Server\Salt(); + }; + + $c["setup.proxy"] = function($c) { + return new CaT\Doil\Setup\Server\Proxy( + $c["filesystem.shell"] + ); + }; + + $c["setup.mail"] = function($c) { + return new CaT\Doil\Setup\Server\Mail(); + }; + + $c["setup.keycloak"] = function($c) { + return new CaT\Doil\Setup\Server\Keycloak( + $c["filesystem.shell"] + ); + }; + + $c["app"] = function($c) { return new App( $c["command.instances.apply"], @@ -76,6 +217,7 @@ function buildContainerForApp() : Container $c["command.salt.up"], $c["command.salt.states"], $c["command.salt.down"], + $c["command.system.update"], $c["command.user.add"], $c["command.user.delete"], $c["command.user.list"] @@ -140,6 +282,27 @@ function buildContainerForApp() : Container ); }; + $c["system.update"] = function($c) { + return new Update( + $c["logger"], + $c["setup.output"], + $c["setup.input"], + $c["command.writer"], + $c["git.shell"], + $c["filesystem.shell"], + $c["setup.config_reader"], + $c["setup.config_checker"], + $c["setup.copy"], + $c["docker.shell"], + $c["posix.shell"], + $c["setup.salt"], + $c["setup.proxy"], + $c["setup.mail"], + $c["setup.keycloak"], + $c["setup.server.start"], + ); + }; + $c["command.writer"] = function() { return new CommandWriter(); }; @@ -477,6 +640,16 @@ function buildContainerForApp() : Container ); }; + $c["command.system.update"] = function($c) { + return new System\UpdateCommand( + $c["posix.shell"], + $c["filesystem.shell"], + $c["git.shell"], + $c["system.update"], + $c["command.writer"] + ); + }; + $c["command.user.add"] = function($c) { return new User\AddCommand( $c["user.manager"], diff --git a/app/tests/Commands/Instances/ApplyCommandTest.php b/app/tests/Commands/Instances/ApplyCommandTest.php index 75f4c8f3..44461666 100644 --- a/app/tests/Commands/Instances/ApplyCommandTest.php +++ b/app/tests/Commands/Instances/ApplyCommandTest.php @@ -9,7 +9,9 @@ use CaT\Doil\Lib\FileSystem\Filesystem; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ApplyCommandTest extends TestCase { public function test_execute_with_non_existing_global_dir() : void @@ -82,16 +84,20 @@ public function test_execute_with_state_not_in_path() : void $posix = $this->createMock(Posix::class); $filesystem = $this->createMock(Filesystem::class); $writer = new CommandWriter(); - $instance = "master"; $command = new ApplyCommand($docker, $posix, $filesystem, $writer); $tester = new CommandTester($command); + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("exists") - ->withConsecutive(["/home/doil/.doil/instances/$instance"], ["/usr/local/share/doil/stack/states/access"]) - ->willReturnOnConsecutiveCalls(true, false) + ->willReturnCallback(function () use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1 => true, + 2 => false, + }; + }) ; $posix @@ -121,16 +127,19 @@ public function test_execute_with_state() : void $posix = $this->createMock(Posix::class); $filesystem = $this->createMock(Filesystem::class); $writer = $this->createMock(Writer::class); - $instance = "master"; $command = new ApplyCommand($docker, $posix, $filesystem, $writer); $tester = new CommandTester($command); + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("exists") - ->withConsecutive(["/home/doil/.doil/instances/$instance"], ["/usr/local/share/doil/stack/states/access"]) - ->willReturnOnConsecutiveCalls(true, true) + ->willReturnCallback(function () use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1, 2 => true, + }; + }) ; $posix @@ -173,16 +182,19 @@ public function test_execute_with_state_and_no_commit() : void $posix = $this->createMock(Posix::class); $filesystem = $this->createMock(Filesystem::class); $writer = $this->createMock(Writer::class); - $instance = "master"; $command = new ApplyCommand($docker, $posix, $filesystem, $writer); $tester = new CommandTester($command); + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("exists") - ->withConsecutive(["/home/doil/.doil/instances/$instance"], ["/usr/local/share/doil/stack/states/access"]) - ->willReturnOnConsecutiveCalls(true, true) + ->willReturnCallback(function () use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1, 2 => true, + }; + }) ; $posix diff --git a/app/tests/Commands/Instances/CSPCommandTest.php b/app/tests/Commands/Instances/CSPCommandTest.php index feb85c5b..9b33d554 100644 --- a/app/tests/Commands/Instances/CSPCommandTest.php +++ b/app/tests/Commands/Instances/CSPCommandTest.php @@ -11,7 +11,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Output\OutputInterface; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class CommandWriterWrapper extends CommandWriter { public function beginBlock(OutputInterface $output, string $txt) : void @@ -27,6 +29,7 @@ public function error(OutputInterface $output, string $msg, string $hint = "") : } } +#[AllowMockObjectsWithoutExpectations] class CSPCommandWrapper extends CSPCommand { public function hasDockerComposeFile(string $path, OutputInterface $output) : bool @@ -35,6 +38,7 @@ public function hasDockerComposeFile(string $path, OutputInterface $output) : bo } } +#[AllowMockObjectsWithoutExpectations] class CSPCommandTest extends TestCase { public function test_execute_with_no_instance_no_all() : void diff --git a/app/tests/Commands/Instances/CreateCommandTest.php b/app/tests/Commands/Instances/CreateCommandTest.php index 8df058b5..43ae7a88 100644 --- a/app/tests/Commands/Instances/CreateCommandTest.php +++ b/app/tests/Commands/Instances/CreateCommandTest.php @@ -18,7 +18,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Output\OutputInterface; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class CreateCommandWrapper extends CreateCommand { protected function normalizeTarget() : Closure @@ -49,6 +51,7 @@ protected function getIliasVersion(string $path) : string } } +#[AllowMockObjectsWithoutExpectations] class CreateCommandTest extends TestCase { public function test_execute_with_wrong_chars_in_instance_param() : void diff --git a/app/tests/Commands/Instances/DeleteCommandTest.php b/app/tests/Commands/Instances/DeleteCommandTest.php index 7cc456e6..97748e39 100644 --- a/app/tests/Commands/Instances/DeleteCommandTest.php +++ b/app/tests/Commands/Instances/DeleteCommandTest.php @@ -10,7 +10,9 @@ use Symfony\Component\Console\Application; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DeleteCommandTest extends TestCase { public function test_execute_with_non_root_user() : void @@ -171,13 +173,30 @@ public function test_execute() : void ->willReturn(true) ; + $matcher = $this->exactly(2); $docker - ->expects($this->exactly(2)) + ->expects($matcher) ->method("executeCommand") - ->withConsecutive( - ["/usr/local/lib/doil/server/salt/", "doil_saltmain", "salt-key", "-d", "master.global", "-y", "-q"], - ["/usr/local/lib/doil/server/mail/", "doil_mail", "/bin/bash", "-c", "/root/delete-postbox-configuration.sh $instance &>/dev/null"] - ) + ->willReturnCallback(function (... $values) use ($matcher, $instance) { + match ($matcher->numberOfInvocations()) { + 1 => $values == [ + "/usr/local/lib/doil/server/salt/", + "doil_salt", + "salt-key", + "-d", + "master.global", + "-y", + "-q" + ], + 2 => $values == [ + "/usr/local/lib/doil/server/mail/", + "doil_mail", + "/bin/bash", + "-c", + "/root/delete-postbox-configuration.sh $instance &>/dev/null" + ], + }; + }) ; $docker ->expects($this->once()) @@ -227,13 +246,22 @@ public function test_execute() : void ->with("/usr/local/share/doil/instances/master") ->willReturn("/home/user/instances/master") ; + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("remove") - ->withConsecutive( - ["/usr/local/share/doil/instances/master"], - ["/home/user/instances/master"] - ) + ->willReturnCallback(function (string $value) use ($matcher, $instance) { + match ($matcher->numberOfInvocations()) { + 1 => $this->assertEquals( + "/usr/local/share/doil/instances/master", + $value + ), + 2 => $this->assertEquals( + "/home/user/instances/master", + $value + ), + }; + }) ; $tester->setInputs(["yes"]); diff --git a/app/tests/Commands/Instances/DownCommandTest.php b/app/tests/Commands/Instances/DownCommandTest.php index 02a51092..693a1938 100644 --- a/app/tests/Commands/Instances/DownCommandTest.php +++ b/app/tests/Commands/Instances/DownCommandTest.php @@ -10,7 +10,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Output\OutputInterface; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DownCommandWrapper extends DownCommand { public function hasDockerComposeFile(string $path, OutputInterface $output) : bool @@ -19,6 +21,7 @@ public function hasDockerComposeFile(string $path, OutputInterface $output) : bo } } +#[AllowMockObjectsWithoutExpectations] class DownCommandTest extends TestCase { public function test_execute_with_no_instance_no_docker_compose_file() : void diff --git a/app/tests/Commands/Instances/ListCommandTest.php b/app/tests/Commands/Instances/ListCommandTest.php index 8abfd579..daef5c4a 100644 --- a/app/tests/Commands/Instances/ListCommandTest.php +++ b/app/tests/Commands/Instances/ListCommandTest.php @@ -8,7 +8,9 @@ use CaT\Doil\Lib\FileSystem\Filesystem; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ListCommandTest extends TestCase { public function test_execute_with_non_existing_local_dir() : void @@ -69,11 +71,16 @@ public function test_execute_with_non_existing_global_dir() : void ->willReturn("/home/doil") ; + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("exists") - ->withConsecutive(["/home/doil/.doil/instances"], ["/usr/local/share/doil/instances"]) - ->willReturnOnConsecutiveCalls(true, false) + ->willReturnCallback(function (string $value) use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1 => $value == "/home/doil/.doil/instances", + 2 => $value != "/usr/local/share/doil/instances", + }; + }) ; $filesystem ->expects($this->once()) @@ -115,17 +122,27 @@ public function test_execute() : void ->willReturn("/home/doil") ; + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("exists") - ->withConsecutive(["/home/doil/.doil/instances"], ["/usr/local/share/doil/instances"]) - ->willReturnOnConsecutiveCalls(true, true) + ->willReturnCallback(function (string $value) use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1 => $value == "/home/doil/.doil/instances", + 2 => $value == "/usr/local/share/doil/instances", + }; + }) ; + $matcher = $this->exactly(2); $filesystem - ->expects($this->exactly(2)) + ->expects($matcher) ->method("getFilesInPath") - ->withConsecutive(["/home/doil/.doil/instances"], ["/usr/local/share/doil/instances"]) - ->willReturnOnConsecutiveCalls(["local1", "local2", "local3"], ["global1", "global2"]) + ->willReturnCallback(function () use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1 => ["local1", "local2", "local3"], + 2 => ["global1", "global2"], + }; + }) ; $tester->execute([]); diff --git a/app/tests/Commands/Instances/LoginCommandTest.php b/app/tests/Commands/Instances/LoginCommandTest.php index 91c68a9e..6af7d504 100644 --- a/app/tests/Commands/Instances/LoginCommandTest.php +++ b/app/tests/Commands/Instances/LoginCommandTest.php @@ -8,7 +8,9 @@ use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Output\OutputInterface; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class LoginCommandWrapper extends LoginCommand { public function hasDockerComposeFile(string $path, OutputInterface $output) : bool @@ -17,6 +19,7 @@ public function hasDockerComposeFile(string $path, OutputInterface $output) : bo } } +#[AllowMockObjectsWithoutExpectations] class LoginCommandTest extends TestCase { public function test_execute_with_no_instance_name() : void diff --git a/app/tests/Commands/Instances/PathCommandTest.php b/app/tests/Commands/Instances/PathCommandTest.php index 5af3f84d..83923369 100644 --- a/app/tests/Commands/Instances/PathCommandTest.php +++ b/app/tests/Commands/Instances/PathCommandTest.php @@ -9,7 +9,9 @@ use CaT\Doil\Lib\FileSystem\Filesystem; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class PathCommandTest extends TestCase { public function test_execute_with_missing_instance() : void diff --git a/app/tests/Commands/Instances/RestartCommandTest.php b/app/tests/Commands/Instances/RestartCommandTest.php index eca7f696..46284f85 100644 --- a/app/tests/Commands/Instances/RestartCommandTest.php +++ b/app/tests/Commands/Instances/RestartCommandTest.php @@ -10,7 +10,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Output\OutputInterface; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class RestartCommandWrapper extends RestartCommand { public function hasDockerComposeFile(string $path, OutputInterface $output) : bool @@ -19,6 +21,7 @@ public function hasDockerComposeFile(string $path, OutputInterface $output) : bo } } +#[AllowMockObjectsWithoutExpectations] class RestartCommandTest extends TestCase { public function test_execute_with_no_instance_no_docker_compose_file() : void diff --git a/app/tests/Commands/Instances/StatusCommandTest.php b/app/tests/Commands/Instances/StatusCommandTest.php index c5a833ec..5ab2dbe0 100644 --- a/app/tests/Commands/Instances/StatusCommandTest.php +++ b/app/tests/Commands/Instances/StatusCommandTest.php @@ -5,7 +5,9 @@ use CaT\Doil\Lib\Docker\Docker; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class StatusCommandTest extends TestCase { public function testExecute() : void diff --git a/app/tests/Commands/Instances/UpCommandTest.php b/app/tests/Commands/Instances/UpCommandTest.php index e96ba3cd..227ce7bc 100644 --- a/app/tests/Commands/Instances/UpCommandTest.php +++ b/app/tests/Commands/Instances/UpCommandTest.php @@ -10,7 +10,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Output\OutputInterface; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UpCommandWrapper extends UpCommand { public function hasDockerComposeFile(string $path, OutputInterface $output) : bool @@ -19,6 +21,7 @@ public function hasDockerComposeFile(string $path, OutputInterface $output) : bo } } +#[AllowMockObjectsWithoutExpectations] class UpCommandTest extends TestCase { public function test_execute_with_no_instance_no_docker_compose_file() : void diff --git a/app/tests/Commands/Mail/ChangePasswordCommandTest.php b/app/tests/Commands/Mail/ChangePasswordCommandTest.php index a20b4f2e..2ff0312d 100644 --- a/app/tests/Commands/Mail/ChangePasswordCommandTest.php +++ b/app/tests/Commands/Mail/ChangePasswordCommandTest.php @@ -8,7 +8,9 @@ use CaT\Doil\Lib\ConsoleOutput\Writer; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ChangePasswordCommandTest extends TestCase { public function test_execute_as_non_root() : void diff --git a/app/tests/Commands/Mail/DownCommandTest.php b/app/tests/Commands/Mail/DownCommandTest.php index d20ae648..9e9bab7c 100644 --- a/app/tests/Commands/Mail/DownCommandTest.php +++ b/app/tests/Commands/Mail/DownCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DownCommandTest extends TestCase { public function test_execute_mail_already_down() : void diff --git a/app/tests/Commands/Mail/LoginCommandTest.php b/app/tests/Commands/Mail/LoginCommandTest.php index 1b0abe0b..91e95fb7 100644 --- a/app/tests/Commands/Mail/LoginCommandTest.php +++ b/app/tests/Commands/Mail/LoginCommandTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class LoginCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/Mail/RestartCommandTest.php b/app/tests/Commands/Mail/RestartCommandTest.php index 130e0792..c919ce5d 100644 --- a/app/tests/Commands/Mail/RestartCommandTest.php +++ b/app/tests/Commands/Mail/RestartCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class RestartCommandTest extends TestCase { public function test_execute_mail_already_down() : void diff --git a/app/tests/Commands/Mail/UpCommandTest.php b/app/tests/Commands/Mail/UpCommandTest.php index 390e4a6b..81d41c39 100644 --- a/app/tests/Commands/Mail/UpCommandTest.php +++ b/app/tests/Commands/Mail/UpCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UpCommandTest extends TestCase { public function test_execute_mail_already_up() : void diff --git a/app/tests/Commands/Pack/ExportCommandTest.php b/app/tests/Commands/Pack/ExportCommandTest.php index 6d8c11ff..b0a0c765 100644 --- a/app/tests/Commands/Pack/ExportCommandTest.php +++ b/app/tests/Commands/Pack/ExportCommandTest.php @@ -13,7 +13,9 @@ use CaT\Doil\Commands\Repo\RepoManager; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ExportCommandTest extends TestCase { public function test_execute_without_instance_param() : void diff --git a/app/tests/Commands/Pack/ImportCommandTest.php b/app/tests/Commands/Pack/ImportCommandTest.php index 3432fdfa..868658e7 100644 --- a/app/tests/Commands/Pack/ImportCommandTest.php +++ b/app/tests/Commands/Pack/ImportCommandTest.php @@ -11,7 +11,9 @@ use CaT\Doil\Commands\Repo\RepoManager; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ImportCommandTest extends TestCase { public function test_execute_without_instance_param() : void diff --git a/app/tests/Commands/Proxy/DownCommandTest.php b/app/tests/Commands/Proxy/DownCommandTest.php index 1a394741..9c2de772 100644 --- a/app/tests/Commands/Proxy/DownCommandTest.php +++ b/app/tests/Commands/Proxy/DownCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DownCommandTest extends TestCase { public function test_execute_proxy_already_down() : void diff --git a/app/tests/Commands/Proxy/LoginCommandTest.php b/app/tests/Commands/Proxy/LoginCommandTest.php index b1f33c61..c0acce01 100644 --- a/app/tests/Commands/Proxy/LoginCommandTest.php +++ b/app/tests/Commands/Proxy/LoginCommandTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class LoginCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/Proxy/PruneCommandTest.php b/app/tests/Commands/Proxy/PruneCommandTest.php index 40921a93..d711b195 100644 --- a/app/tests/Commands/Proxy/PruneCommandTest.php +++ b/app/tests/Commands/Proxy/PruneCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class PruneCommandTest extends TestCase { public function test_execute() : void @@ -33,23 +35,26 @@ public function test_execute() : void ->with("doil_proxy", "/etc/nginx/conf.d/sites/") ->willReturn(["foo1", "foo2"]) ; + $matcher = $this->exactly(2); $docker - ->expects($this->exactly(2)) + ->expects($matcher) ->method("executeCommand") - ->withConsecutive( - [ - "/usr/local/lib/doil/server/proxy", - "doil_proxy", - "rm", - "/etc/nginx/conf.d/sites/foo1" - ], - [ - "/usr/local/lib/doil/server/proxy", - "doil_proxy", - "rm", - "/etc/nginx/conf.d/sites/foo2" - ], - ) + ->willReturnCallback(function (... $values) use ($matcher) { + match ($matcher->numberOfInvocations()) { + 1 => $values == [ + "/usr/local/lib/doil/server/proxy", + "doil_proxy", + "rm", + "/etc/nginx/conf.d/sites/foo1" + ], + 2 => $values == [ + "/usr/local/lib/doil/server/proxy", + "doil_proxy", + "rm", + "/etc/nginx/conf.d/sites/foo2" + ], + }; + }) ; $execute_result = $tester->execute([]); diff --git a/app/tests/Commands/Proxy/ReloadCommandTest.php b/app/tests/Commands/Proxy/ReloadCommandTest.php index a606f14b..6c4a31a4 100644 --- a/app/tests/Commands/Proxy/ReloadCommandTest.php +++ b/app/tests/Commands/Proxy/ReloadCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ReloadCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/Proxy/RestartCommandTest.php b/app/tests/Commands/Proxy/RestartCommandTest.php index 39788b4b..09c4172b 100644 --- a/app/tests/Commands/Proxy/RestartCommandTest.php +++ b/app/tests/Commands/Proxy/RestartCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class RestartCommandTest extends TestCase { public function test_execute_proxy_already_down() : void diff --git a/app/tests/Commands/Proxy/UpCommandTest.php b/app/tests/Commands/Proxy/UpCommandTest.php index bb1631b3..df48a0ab 100644 --- a/app/tests/Commands/Proxy/UpCommandTest.php +++ b/app/tests/Commands/Proxy/UpCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UpCommandTest extends TestCase { public function test_execute_proxy_already_up() : void diff --git a/app/tests/Commands/Repo/AddCommandTest.php b/app/tests/Commands/Repo/AddCommandTest.php index 19318e60..49cea998 100644 --- a/app/tests/Commands/Repo/AddCommandTest.php +++ b/app/tests/Commands/Repo/AddCommandTest.php @@ -10,7 +10,9 @@ use Symfony\Component\Console\Application; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class AddCommandTest extends TestCase { public function test_execute_without_name() : void diff --git a/app/tests/Commands/Repo/DeleteCommandTest.php b/app/tests/Commands/Repo/DeleteCommandTest.php index ecfbe6ea..9038b861 100644 --- a/app/tests/Commands/Repo/DeleteCommandTest.php +++ b/app/tests/Commands/Repo/DeleteCommandTest.php @@ -10,7 +10,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Exception\InvalidArgumentException; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DeleteCommandTest extends TestCase { public function test_execute_without_name_and_all() : void diff --git a/app/tests/Commands/Repo/ListCommandTest.php b/app/tests/Commands/Repo/ListCommandTest.php index 965268b9..31e9f63b 100644 --- a/app/tests/Commands/Repo/ListCommandTest.php +++ b/app/tests/Commands/Repo/ListCommandTest.php @@ -6,7 +6,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ListCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/Repo/RepoManagerTest.php b/app/tests/Commands/Repo/RepoManagerTest.php index 3d82f93c..36bcb934 100644 --- a/app/tests/Commands/Repo/RepoManagerTest.php +++ b/app/tests/Commands/Repo/RepoManagerTest.php @@ -9,7 +9,9 @@ use CaT\Doil\Lib\Posix\Posix; use PHPUnit\Framework\TestCase; use CaT\Doil\Lib\FileSystem\Filesystem; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class RepoManagerWrapper extends RepoManager { public function getLocalRepos() : array @@ -29,6 +31,7 @@ public function getGlobalRepos() : array } } +#[AllowMockObjectsWithoutExpectations] class RepoManagerTest extends TestCase { public function test_create() : void diff --git a/app/tests/Commands/Repo/RepoTest.php b/app/tests/Commands/Repo/RepoTest.php index 1fb991b1..765d83f8 100644 --- a/app/tests/Commands/Repo/RepoTest.php +++ b/app/tests/Commands/Repo/RepoTest.php @@ -3,7 +3,9 @@ namespace CaT\Doil\Commands\Repo; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class RepoTest extends TestCase { public function test_create() : void diff --git a/app/tests/Commands/Repo/UpdateCommandTest.php b/app/tests/Commands/Repo/UpdateCommandTest.php index 03382fc1..1039758e 100644 --- a/app/tests/Commands/Repo/UpdateCommandTest.php +++ b/app/tests/Commands/Repo/UpdateCommandTest.php @@ -10,7 +10,9 @@ use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Exception\InvalidArgumentException; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UpdateCommandTest extends TestCase { public function test_execute_without_name_and_all() : void diff --git a/app/tests/Commands/Salt/DownCommandTest.php b/app/tests/Commands/Salt/DownCommandTest.php index 5e27bb54..3485f764 100644 --- a/app/tests/Commands/Salt/DownCommandTest.php +++ b/app/tests/Commands/Salt/DownCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DownCommandTest extends TestCase { public function test_execute_salt_already_down() : void diff --git a/app/tests/Commands/Salt/LoginCommandTest.php b/app/tests/Commands/Salt/LoginCommandTest.php index c50d1430..c9a17db6 100644 --- a/app/tests/Commands/Salt/LoginCommandTest.php +++ b/app/tests/Commands/Salt/LoginCommandTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use CaT\Doil\Lib\Docker\Docker; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class LoginCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/Salt/PruneCommandTest.php b/app/tests/Commands/Salt/PruneCommandTest.php index 3ca5d444..1f5ca698 100644 --- a/app/tests/Commands/Salt/PruneCommandTest.php +++ b/app/tests/Commands/Salt/PruneCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class PruneCommandTest extends TestCase { public function test_execute() : void @@ -30,7 +32,7 @@ public function test_execute() : void $docker ->expects($this->once()) ->method("executeCommand") - ->with("/usr/local/lib/doil/server/salt", "doil_saltmain", "salt-key", "-y", "-D") + ->with("/usr/local/lib/doil/server/salt", "doil_salt", "salt-key", "-y", "-D") ; $execute_result = $tester->execute([]); diff --git a/app/tests/Commands/Salt/RestartCommandTest.php b/app/tests/Commands/Salt/RestartCommandTest.php index 0fb5ccb5..c609d943 100644 --- a/app/tests/Commands/Salt/RestartCommandTest.php +++ b/app/tests/Commands/Salt/RestartCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class RestartCommandTest extends TestCase { public function test_execute_salt_already_down() : void @@ -61,13 +63,22 @@ public function test_execute() : void ->method("getRunningInstanceNames") ->willReturn(["foo1_local", "foo2_global"]) ; + $matcher = $this->exactly(2); $docker - ->expects($this->exactly(2)) + ->expects($matcher) ->method("executeDockerCommand") - ->withConsecutive( - ["foo1_local", "supervisorctl start startup 2>&1 >/dev/null"], - ["foo2_global", "supervisorctl start startup 2>&1 >/dev/null"] - ) + ->willReturnCallback(function (... $values) use ($matcher) { + match ($matcher->numberOfInvocations()) { + 1 => $values == [ + "foo1_local", + "supervisorctl start startup 2>&1 >/dev/null" + ], + 2 => $values == [ + "foo2_global", + "supervisorctl start startup 2>&1 >/dev/null" + ], + }; + }) ; $execute_result = $tester->execute([]); diff --git a/app/tests/Commands/Salt/StatesCommandTest.php b/app/tests/Commands/Salt/StatesCommandTest.php index 3f9bcd32..36abce31 100644 --- a/app/tests/Commands/Salt/StatesCommandTest.php +++ b/app/tests/Commands/Salt/StatesCommandTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use CaT\Doil\Lib\FileSystem\Filesystem; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class StatesCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/Salt/UpCommandTest.php b/app/tests/Commands/Salt/UpCommandTest.php index f1749349..2097c973 100644 --- a/app/tests/Commands/Salt/UpCommandTest.php +++ b/app/tests/Commands/Salt/UpCommandTest.php @@ -6,7 +6,9 @@ use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\ConsoleOutput\Writer; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UpCommandTest extends TestCase { public function test_execute_salt_already_up() : void @@ -55,13 +57,22 @@ public function test_execute() : void ->method("getRunningInstanceNames") ->willReturn(["foo1_local", "foo2_local"]) ; + $matcher = $this->exactly(2); $docker - ->expects($this->exactly(2)) + ->expects($matcher) ->method("executeDockerCommand") - ->withConsecutive( - ["foo1_local", "supervisorctl start startup"], - ["foo2_local", "supervisorctl start startup"] - ) + ->willReturnCallback(function (... $values) use ($matcher) { + match ($matcher->numberOfInvocations()) { + 1 => $values == [ + "foo1_local", + "supervisorctl start startup" + ], + 2 => $values == [ + "foo2_global", + "supervisorctl start startup" + ], + }; + }) ; $execute_result = $tester->execute([]); diff --git a/app/tests/Commands/System/UpdateCommandTest.php b/app/tests/Commands/System/UpdateCommandTest.php new file mode 100644 index 00000000..d5123d1f --- /dev/null +++ b/app/tests/Commands/System/UpdateCommandTest.php @@ -0,0 +1,168 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\System; + +use CaT\Doil\Lib\Git\Git; +use CaT\Doil\Lib\Posix\Posix; +use PHPUnit\Framework\TestCase; +use CaT\Doil\Lib\System\Update; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Console\Application; +use CaT\Doil\Lib\ConsoleOutput\CommandWriter; +use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; + +#[AllowMockObjectsWithoutExpectations] +class UpdateCommandTest extends TestCase +{ + public function test_execute_as_non_root() : void + { + $posix = $this->createMock(Posix::class); + $filesystem = $this->createMock(Filesystem::class); + $git = $this->createMock(Git::class); + $update = $this->createMock(Update::class); + $writer = new CommandWriter(); + + $command = new UpdateCommand($posix, $filesystem, $git, $update, $writer); + $tester = new CommandTester($command); + + $posix + ->expects($this->once()) + ->method('isSudo') + ->willReturn(false) + ; + + $execute_result = $tester->execute([]); + $output = $tester->getDisplay(true); + + $result = "Error:\n\tPlease execute this script as sudo user!\n\t\n"; + $this->assertEquals($result, $output); + $this->assertEquals(1, $execute_result); + } + + public function test_execute_nothing_to_do() : void + { + $posix = $this->createMock(Posix::class); + $filesystem = $this->createMock(Filesystem::class); + $git = $this->createMock(Git::class); + $update = $this->createMock(Update::class); + $writer = new CommandWriter(); + + $command = new UpdateCommand($posix, $filesystem, $git, $update, $writer); + $tester = new CommandTester($command); + + $posix + ->expects($this->once()) + ->method('isSudo') + ->willReturn(true) + ; + + $filesystem + ->expects($this->once()) + ->method('getLineInFile') + ->with("/usr/local/lib/doil/app/src/App.php", "Doil Version") + ->willReturn("const NAME = \"Doil Version 20251101 - build 2025-11-01\";") + ; + + $git + ->expects($this->once()) + ->method('getTagsFromGithubUrl') + ->with("https://github.com/conceptsandtraining/doil.git") + ->willReturn(["20251005", "20251010", "20250920"]) + ; + + $execute_result = $tester->execute([]); + $output = $tester->getDisplay(true); + + $result = "Current version: 20251101\nNothing to do. Everything is up to date!\n"; + $this->assertEquals($result, $output); + $this->assertEquals(0, $execute_result); + } + + public function test_execute_no_confirm() : void + { + $posix = $this->createMock(Posix::class); + $filesystem = $this->createMock(Filesystem::class); + $git = $this->createMock(Git::class); + $update = $this->createMock(Update::class); + $writer = new CommandWriter(); + + $command = new UpdateCommand($posix, $filesystem, $git, $update, $writer); + $tester = new CommandTester($command); + $app = new Application("doil"); + $command->setApplication($app); + + $posix + ->expects($this->once()) + ->method('isSudo') + ->willReturn(true) + ; + + $filesystem + ->expects($this->once()) + ->method('getLineInFile') + ->with("/usr/local/lib/doil/app/src/App.php", "Doil Version") + ->willReturn("Doil Version 20251101 - build 2025-11-01") + ; + + $git + ->expects($this->once()) + ->method('getTagsFromGithubUrl') + ->with("https://github.com/conceptsandtraining/doil.git") + ->willReturn(["20261005", "20261010", "20260920"]) + ; + + $tester->setInputs(['no']); + $execute_result = $tester->execute([]); + + $this->assertEquals(1, $execute_result); + } + + public function test_execute_yes_confirm() : void + { + $posix = $this->createMock(Posix::class); + $filesystem = $this->createMock(Filesystem::class); + $git = $this->createMock(Git::class); + $update = $this->createMock(Update::class); + $writer = new CommandWriter(); + + $command = new UpdateCommand($posix, $filesystem, $git, $update, $writer); + $tester = new CommandTester($command); + $app = new Application("doil"); + $command->setApplication($app); + + $posix + ->expects($this->once()) + ->method('isSudo') + ->willReturn(true) + ; + + $filesystem + ->expects($this->once()) + ->method('getLineInFile') + ->with("/usr/local/lib/doil/app/src/App.php", "Doil Version") + ->willReturn("Doil Version 20251101 - build 2025-11-01") + ; + + $git + ->expects($this->once()) + ->method('getTagsFromGithubUrl') + ->with("https://github.com/conceptsandtraining/doil.git") + ->willReturn(["20261005", "20261010", "20260920"]) + ; + + $update + ->expects($this->once()) + ->method('run') + ->with("https://github.com/conceptsandtraining/doil.git", ["20261005", "20261010", "20260920"]) + ; + + $tester->setInputs(['yes']); + $execute_result = $tester->execute([]); + + + $this->assertEquals(0, $execute_result); + } +} diff --git a/app/tests/Commands/User/AddCommandTest.php b/app/tests/Commands/User/AddCommandTest.php index 25a692d3..59b76e3e 100644 --- a/app/tests/Commands/User/AddCommandTest.php +++ b/app/tests/Commands/User/AddCommandTest.php @@ -13,7 +13,9 @@ use CaT\Doil\Commands\Repo\RepoManager; use CaT\Doil\Lib\ConsoleOutput\CommandWriter; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class AddCommandTest extends TestCase { public function test_execute_without_name() : void diff --git a/app/tests/Commands/User/DeleteCommandTest.php b/app/tests/Commands/User/DeleteCommandTest.php index 7112b550..ad930e33 100644 --- a/app/tests/Commands/User/DeleteCommandTest.php +++ b/app/tests/Commands/User/DeleteCommandTest.php @@ -13,7 +13,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Exception\InvalidArgumentException; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class DeleteCommandDummy extends DeleteCommand { protected function confirmAcknowledgement(InputInterface $input, OutputInterface $output) : bool @@ -22,6 +24,7 @@ protected function confirmAcknowledgement(InputInterface $input, OutputInterface } } +#[AllowMockObjectsWithoutExpectations] class DeleteCommandTest extends TestCase { public function test_execute_without_name_and_all() : void diff --git a/app/tests/Commands/User/ListCommandTest.php b/app/tests/Commands/User/ListCommandTest.php index 8b7a5814..79ec98ff 100644 --- a/app/tests/Commands/User/ListCommandTest.php +++ b/app/tests/Commands/User/ListCommandTest.php @@ -6,7 +6,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class ListCommandTest extends TestCase { public function test_execute() : void diff --git a/app/tests/Commands/User/UserManagerTest.php b/app/tests/Commands/User/UserManagerTest.php index 5f7805bb..e93f541a 100644 --- a/app/tests/Commands/User/UserManagerTest.php +++ b/app/tests/Commands/User/UserManagerTest.php @@ -6,7 +6,9 @@ use PHPUnit\Framework\TestCase; use CaT\Doil\Lib\FileSystem\Filesystem; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UserManagerTest extends TestCase { public function test_create() : void @@ -102,14 +104,17 @@ public function test_createFileInfrastructure() : void $filesystem = $this->createMock(Filesystem::class); $user_manager = new UserManager($filesystem); + $matcher = $this->exactly(3); $filesystem - ->expects($this->exactly(3)) + ->expects($matcher) ->method("makeDirectoryRecursive") - ->withConsecutive( - ["/tmp/doil_test/.doil/config"], - ["/tmp/doil_test/.doil/repositories"], - ["/tmp/doil_test/.doil/instances"] - ) + ->willReturnCallback(function (string $value) use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1 => $value == "/tmp/doil_test/.doil/config", + 2 => $value == "/tmp/doil_test/.doil/repositories", + 3 => $value == "/tmp/doil_test/.doil/instances", + }; + }) ; $filesystem ->expects($this->once()) diff --git a/app/tests/Commands/User/UserTest.php b/app/tests/Commands/User/UserTest.php index 60bca084..06d96df8 100644 --- a/app/tests/Commands/User/UserTest.php +++ b/app/tests/Commands/User/UserTest.php @@ -5,7 +5,9 @@ namespace CaT\Doil\Commands\User; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +#[AllowMockObjectsWithoutExpectations] class UserTest extends TestCase { public function test_create() : void diff --git a/app/tests/Setup/CopyFiles/CopyTest.php b/app/tests/Setup/CopyFiles/CopyTest.php new file mode 100644 index 00000000..553117ff --- /dev/null +++ b/app/tests/Setup/CopyFiles/CopyTest.php @@ -0,0 +1,74 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\CopyFiles; + +use PHPUnit\Framework\TestCase; +use CaT\Doil\Lib\Config\Config; +use CaT\Doil\Lib\FileSystem\Filesystem; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; + +#[AllowMockObjectsWithoutExpectations] +class CopyTest extends TestCase +{ + public function test_copyDoil() : void + { + $base_path = "/tmp/foo"; + $filesystem = $this->createMock(Filesystem::class); + $config = $this->createMock(Config::class); + + $copy = new Copy($filesystem); + + $config + ->expects($this->once()) + ->method('isKeycloakEnabled') + ->willReturn(true) + ; + + $matcher = $this->exactly(8); + $filesystem + ->expects($matcher) + ->method('copyDirectory') + ->willReturnCallback(function () use ($matcher, $base_path) { + match ($matcher->numberOfInvocations()) { + 1 => [$base_path . "/app/src/Setup/templates/keycloak", "/usr/local/lib/doil/server/keycloak"], + 2 => [$base_path . "/app/src/Setup/templates/mail", "/usr/local/lib/doil/server/mail"], + 3 => [$base_path . "/app/src/Setup/templates/proxy", "/usr/local/lib/doil/server/proxy"], + 4 => [$base_path . "/app/src/Setup/templates/salt", "/usr/local/lib/doil/server/salt"], + 5 => [$base_path . "/app/src/Setup/templates/minion", "/usr/local/share/doil/templates/minion"], + 6 => [$base_path . "/app/src/Setup/templates/base", "/usr/local/share/doil/templates/base"], + 7 => [$base_path . "/app", "/usr/local/lib/doil/app"], + 8 => [$base_path . "/app/src/Setup/stack", "/usr/local/share/doil/stack"] + }; + }) + ; + + $matcher = $this->exactly(2); + $filesystem + ->expects($matcher) + ->method('copy') + ->willReturnCallback(function () use ($matcher, $base_path) { + match ($matcher->numberOfInvocations()) { + 1 => [$base_path . "/setup/Dockerfile", "/usr/local/lib/doil/server/php/Dockerfile"], + 2 => [$base_path . "/app/src/Setup/doil.sh", "/usr/local/bin/doil"] + }; + }) + ; + + $filesystem + ->expects($this->once()) + ->method('exists') + ->with("/usr/local/lib/doil/app/composer.lock") + ->willReturn(true) + ; + $filesystem + ->expects($this->once()) + ->method('remove') + ->with("/usr/local/lib/doil/app/composer.lock") + ; + + $copy->copyDoil($base_path, $config); + + } +} \ No newline at end of file diff --git a/app/tests/Setup/FileStructure/BaseDirectoriesTest.php b/app/tests/Setup/FileStructure/BaseDirectoriesTest.php new file mode 100644 index 00000000..7d6e0b85 --- /dev/null +++ b/app/tests/Setup/FileStructure/BaseDirectoriesTest.php @@ -0,0 +1,121 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\FileStructure; + +use PHPUnit\Framework\TestCase; +use CaT\Doil\Lib\FileSystem\Filesystem; +use Symfony\Component\Filesystem\Exception\IOException; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; + +#[AllowMockObjectsWithoutExpectations] +class BaseDirectoriesTest extends TestCase +{ + public function test_createBaseDirs_positive() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_directories = new BaseDirectories($filesystem, $home_dir, $user_name); + + $filesystem + ->expects($this->exactly(14)) + ->method("makeDirectoryRecursive") + ->willReturn(true) + ; + + $base_directories->createBaseDirs(); + } + + public function test_createBaseDirs_negative() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_directories = new BaseDirectories($filesystem, $home_dir, $user_name); + + $matcher = $this->exactly(3); + $filesystem + ->expects($matcher) + ->method("makeDirectoryRecursive") + ->willReturnCallback(function () use ($matcher) { + return match ($matcher->numberOfInvocations()) { + 1, 2 => true, + 3 => false + }; + }) + ; + + $this->expectException(IOException::class); + $base_directories->createBaseDirs(); + } + + public function test_setOwnerGroupForBaseDirs() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_directories = new BaseDirectories($filesystem, $home_dir, $user_name); + + $matcher = $this->exactly(12); + $filesystem + ->expects($matcher) + ->method("chownRecursive") + ->willReturnCallback(function () use ($matcher, $home_dir, $user_name) { + match ($matcher->numberOfInvocations()) { + 1 => [$home_dir . "/.doil/" . $user_name, $user_name], + 2 => ["/usr/local/lib/doil", "root", "doil"], + 3 => ["/usr/local/lib/doil/server", "root", "doil"], + 4 => ["/usr/local/lib/doil/server/php", "root", "doil"], + 5 => ["/usr/local/share/doil", "root", "doil"], + 6 => ["/usr/local/share/doil/templates", "root", "doil"], + 7 => ["/etc/doil", "root", "doil"], + 8 => ["/srv/instances", "root", "doil"], + 9 => ["/usr/local/lib/doil/app", "root", "doil"], + 10 => ["/usr/local/share/doil/instances", "root", "doil"], + 11 => ["/usr/local/share/doil/repositories", "root", "doil"], + 12 => ["/var/log/doil", "root", "doil"] + }; + }) + ; + + $base_directories->setOwnerGroupForBaseDirs(); + } + + public function test_setFilePermissionsForBaseDirs() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_directories = new BaseDirectories($filesystem, $home_dir, $user_name); + + $matcher = $this->exactly(12); + $filesystem + ->expects($matcher) + ->method("chmod") + ->willReturnCallback(function () use ($matcher, $home_dir) { + match ($matcher->numberOfInvocations()) { + 1 => [$home_dir . "/.doil/", 0775], + 2 => ["/usr/local/lib/doil", 0775], + 3 => ["/usr/local/lib/doil/server", 0775], + 4 => ["/usr/local/lib/doil/server/php", 0775], + 5 => ["/usr/local/share/doil", 0775], + 6 => ["/usr/local/share/doil/templates", 0775], + 7 => ["/etc/doil", 02775], + 8 => ["/srv/instances", 02775], + 9 => ["/usr/local/lib/doil/app", 02775], + 10 => ["/usr/local/share/doil/instances", 02775], + 11 => ["/usr/local/share/doil/repositories", 02775], + 12 => ["/var/log/doil", 02775] + }; + }) + ; + + $base_directories->setFilePermissionsForBaseDirs(); + } +} \ No newline at end of file diff --git a/app/tests/Setup/FileStructure/BaseFilesTest.php b/app/tests/Setup/FileStructure/BaseFilesTest.php new file mode 100644 index 00000000..5c76765c --- /dev/null +++ b/app/tests/Setup/FileStructure/BaseFilesTest.php @@ -0,0 +1,122 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\FileStructure; + +use PHPUnit\Framework\TestCase; +use CaT\Doil\Lib\FileSystem\Filesystem; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; + +#[AllowMockObjectsWithoutExpectations] +class BaseFilesTest extends TestCase +{ + public function test_createBaseDirs_positive() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_files = new BaseFiles($filesystem, $home_dir, $user_name); + + $matcher = $this->exactly(3); + $filesystem + ->expects($matcher) + ->method("touch") + ->willReturnCallback(function () use ($matcher, $home_dir) { + match ($matcher->numberOfInvocations()) { + 1 => ["/etc/doil/repositories.json"], + 2 => ["/etc/doil/user.json"], + 3 => [$home_dir . "/.doil/config/repositories.json"] + }; + }) + ; + + $base_files->touchFiles(); + } + + public function test_setDefaultUser() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_files = new BaseFiles($filesystem, $home_dir, $user_name); + + $filesystem + ->expects($this->once()) + ->method("setContent") + ->with( + "/etc/doil/user.json", + '"a:1:{i:0;O:27:\"CaT\\\\Doil\\\\Commands\\\\User\\\\User\":1:{s:7:\"\u0000*\u0000name\";s:' . strlen($user_name) . ':\"' . $user_name . '\";}}"' + ) + ; + + $base_files->setDefaultUser(); + } + + public function test_setDefaultRepository() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_files = new BaseFiles($filesystem, $home_dir, $user_name); + + $filesystem + ->expects($this->once()) + ->method("setContent") + ->with( + "/etc/doil/repositories.json", + '"a:1:{i:1;O:27:\"CaT\\\\Doil\\\\Commands\\\\Repo\\\\Repo\":3:{s:7:\"\u0000*\u0000name\";s:5:\"ilias\";s:6:\"\u0000*\u0000url\";s:44:\"https:\\/\\/github.com\\/ILIAS-eLearning\\/ILIAS.git\";s:9:\"\u0000*\u0000global\";b:1;}}"' + ) + ; + + $base_files->setDefaultRepository(); + } + + public function test_setFilePermissionsForBaseFiles() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_files = new BaseFiles($filesystem, $home_dir, $user_name); + + $matcher = $this->exactly(2); + $filesystem + ->expects($matcher) + ->method("chmod") + ->willReturnCallback(function () use ($matcher, $home_dir) { + match ($matcher->numberOfInvocations()) { + 1 => ["/etc/doil/repositories.json", 0664], + 2 => ["/etc/doil/user.json", 0664] + }; + }) + ; + + $base_files->setFilePermissionsForBaseFiles(); + } + + public function test_setFileOwner() : void + { + $filesystem = $this->createMock(Filesystem::class); + $home_dir = "/home/test"; + $user_name = "doil"; + + $base_files = new BaseFiles($filesystem, $home_dir, $user_name); + + $matcher = $this->exactly(1); + $filesystem + ->expects($matcher) + ->method("chownRecursive") + ->willReturnCallback(function () use ($matcher, $home_dir, $user_name) { + match ($matcher->numberOfInvocations()) { + 1 => [$home_dir . "/.doil/config/repositories.json", $user_name, $user_name] + }; + }) + ; + + $base_files->setFileOwner(); + } +} \ No newline at end of file diff --git a/app/tests/Setup/IP/IPTest.php b/app/tests/Setup/IP/IPTest.php new file mode 100644 index 00000000..006c740f --- /dev/null +++ b/app/tests/Setup/IP/IPTest.php @@ -0,0 +1,61 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Setup\IP; + +use PHPUnit\Framework\TestCase; +use CaT\Doil\Lib\Config\Config; +use CaT\Doil\Lib\FileSystem\Filesystem; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; + +#[AllowMockObjectsWithoutExpectations] +class IPTest extends TestCase +{ + public function test_setIPToHosts_Exception() : void + { + $filesystem = $this->createMock(Filesystem::class); + $config = $this->createMock(Config::class); + + $ip = new IP($filesystem); + + $filesystem + ->expects($this->once()) + ->method('getLineInFile') + ->with("/etc/hosts", IP::IP) + ->willReturn("foobar") + ; + + $this->expectException(\RuntimeException::class); + $ip->setIPToHosts($config); + } + + public function test_setIPToHosts() : void + { + $filesystem = $this->createMock(Filesystem::class); + $config = $this->createMock(Config::class); + + $ip = new IP($filesystem); + + $filesystem + ->expects($this->once()) + ->method('getLineInFile') + ->with("/etc/hosts", IP::IP) + ->willReturn(null) + ; + + $config + ->expects($this->once()) + ->method('getHost') + ->willReturn("foobar") + ; + + $filesystem + ->expects($this->once()) + ->method('setContent') + ->with("/etc/hosts", IP::IP . " foobar\n", true) + ; + + $ip->setIPToHosts($config); + } +} \ No newline at end of file diff --git a/setup/templates/php/Dockerfile b/setup/Dockerfile similarity index 85% rename from setup/templates/php/Dockerfile rename to setup/Dockerfile index c978dfa5..02db7f53 100644 --- a/setup/templates/php/Dockerfile +++ b/setup/Dockerfile @@ -1,6 +1,6 @@ -FROM debian:12 +FROM debian:13 -RUN apt-get update && apt-get install -y vim ca-certificates curl zip unzip git php8.2-cli php8.2-zip php8.2-dom php8.2-mbstring php-json +RUN apt-get update && apt-get install -y vim ca-certificates curl zip unzip git php8.4-cli php8.4-curl php8.4-zip php8.4-dom php8.4-mbstring php-json RUN install -m 0755 -d /etc/apt/keyrings RUN curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc RUN chmod a+r /etc/apt/keyrings/docker.asc @@ -17,5 +17,5 @@ RUN php -r "unlink('composer-setup.php');" RUN mv composer.phar /usr/local/bin/composer RUN mkdir /srv/php -RUN mv /etc/php/8.2/cli/php.ini /srv/php -RUN mv /etc/php/8.2/mods-available /srv/php +RUN mv /etc/php/8.4/cli/php.ini /srv/php +RUN mv /etc/php/8.4/mods-available /srv/php diff --git a/setup/colors.sh b/setup/colors.sh deleted file mode 100644 index 2aac4642..00000000 --- a/setup/colors.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# doil is a tool that creates and manages multiple docker container -# with ILIAS and comes with several tools to help manage everything. -# It is able to download ILIAS and other ILIAS related software -# like cate. -# -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/doil -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil - -GREEN='\033[0;32m' -RED='\033[0;31m' -NC='\033[0m' \ No newline at end of file diff --git a/setup/conf/doil.conf b/setup/conf/doil.conf deleted file mode 100755 index 807266f5..00000000 --- a/setup/conf/doil.conf +++ /dev/null @@ -1,14 +0,0 @@ -host=doil -allowed_hosts=false -https_proxy=false -mail_password=ilias -global_instances_path=/srv/instances -enable_keycloak=false -keycloak_hostname=http://doil/keycloak -keycloak_new_admin_password=admin -keycloak_old_admin_password=admin -keycloak_db_username=admin -keycloak_db_password=admin -update_token=false -git_private_ssh_key_path=false -git_public_ssh_key_path=false \ No newline at end of file diff --git a/setup/env.sh b/setup/env.sh deleted file mode 100644 index 923a10fd..00000000 --- a/setup/env.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# doil is a tool that creates and manages multiple docker container -# with ILIAS and comes with several tools to help manage everything. -# It is able to download ILIAS and other ILIAS related software -# like cate. -# -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/doil -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil - -# set doil pathes -DOILLIBPATH="/usr/local/lib/doil" - -# set the host -case "$(uname -s)" in - Darwin) - HOST="mac" - ;; - Linux) - HOST="linux" - ;; - *) - exit - ;; -esac \ No newline at end of file diff --git a/setup/install b/setup/install new file mode 100755 index 00000000..c2111a6f --- /dev/null +++ b/setup/install @@ -0,0 +1,86 @@ +#!/bin/bash + +if [[ ! -z $1 && $1 == "yes" ]] +then + GHRUN="yes" +fi + +SCRIPT_DIR=$(realpath "$0" | sed 's|\(.*\)/.*|\1|') + +source ${SCRIPT_DIR}/scripts/checks.sh +source ${SCRIPT_DIR}/scripts/log.sh +source ${SCRIPT_DIR}/scripts/check_requirements.sh + +check_requirements + +doil_status_send_message "Adding group 'doil'" +CHECK_GROUP=$(grep doil /etc/group) +if [[ -z ${CHECK_GROUP} ]] +then + groupadd doil +fi +doil_status_okay + +doil_status_send_message "Adding user to group 'doil'" +id -nG $SUDO_USER | grep -qw 'doil' +if [[ $? -ne 0 ]] +then + usermod -a -G doil ${SUDO_USER} +fi +doil_status_okay + +doil_status_send_message "Checking if user is in 'doil' group" +doil_check_user_in_doil_group +if [[ $? -ne 0 ]] +then + doil_status_failed + doil_status_send_error "INFO" "Please log out and log in to the host system again to ensure\n\tthat your user belongs to the doil group and start install again." + exit +fi +doil_status_okay + +# build base doil php image +doil_status_send_message "Building doil base image" +docker buildx build -q -t doil_php:stable "${SCRIPT_DIR}" &> /dev/null +docker run --rm -ti \ + -v /home:/home \ + -v $(pwd):$(pwd) \ + -e PHP_INI_SCAN_DIR=/srv/php/mods-available \ + -w "${SCRIPT_DIR}"/../app \ + --user $(id -u $(logname)):$(id -g $(logname)) \ + doil_php:stable /usr/local/bin/composer -q install --no-dev +doil_status_okay + +if [[ ! -v GHRUN ]] +then + USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6) + USER_NAME=$(echo $SUDO_USER) + + DOCKER_GRP_ID=$(cat /etc/group | grep "^docker:" | cut -d : -f3) + DOIL_GRP_ID=$(cat /etc/group | grep "^doil:" | cut -d : -f3) + + # start the setup process + docker run --rm -ti \ + -v "${USER_HOME}":"${USER_HOME}" \ + -v $(pwd):$(pwd) \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /usr/local:/usr/local \ + -v /etc:/etc \ + -v /etc/hosts:/etc/hosts \ + -v /var/log:/var/log \ + -v /srv:/srv \ + -e PHP_INI_SCAN_DIR=/srv/php/mods-available \ + -w "${SCRIPT_DIR}"/../app \ + -e SUDO_UID=$(id -u $(logname)) \ + --group-add ${DOCKER_GRP_ID} \ + --group-add ${DOIL_GRP_ID} \ + doil_php:stable \ + /usr/bin/php8.4 -c /srv/php/php.ini src/cli.php install "${SCRIPT_DIR}" "${USER_HOME}" "${USER_NAME}" + + doil_status_send_message "Cleanup" + rm -rf "${SCRIPT_DIR}"/../app/vendor + rm -rf "${SCRIPT_DIR}"/../app/composer.lock + doil_status_okay +fi + +echo "Thanks for using doil, you rock!" \ No newline at end of file diff --git a/setup/install.sh b/setup/install.sh deleted file mode 100755 index 9cc131ab..00000000 --- a/setup/install.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/bin/bash - -# doil is a tool that creates and manages multiple docker container -# with ILIAS and comes with several tools to help manage everything. -# It is able to download ILIAS and other ILIAS related software -# like cate. -# -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/doil -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil - -# get the helper -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) - -source ${SCRIPT_DIR}/checks.sh -source ${SCRIPT_DIR}/log.sh -source ${SCRIPT_DIR}/system.sh -source ${SCRIPT_DIR}/check_requirements.sh -source ${SCRIPT_DIR}/updates/update.sh -source ${SCRIPT_DIR}/helper.sh -source ${SCRIPT_DIR}/env.sh -source ${SCRIPT_DIR}/colors.sh - -check_requirements - -doil_status_send_message "Adding group 'doil'" -doil_system_add_group -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Adding user to group 'doil'" -doil_system_add_user_to_doil_group -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Checking if user is in 'doil' group" -doil_check_user_in_doil_group -if [[ $? -ne 0 ]] -then - doil_status_failed - doil_status_send_error "INFO" "Please log out and log in to the host system again to ensure\n\tthat your user belongs to the doil group and start install again." - exit -fi -doil_status_okay - -doil_status_send_message "Creating log file" -doil_system_setup_log -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Creating mandatory folder" -doil_system_create_folder -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Setting up basic configuration" -doil_system_setup_config -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -ENABLE_KEYCLOAK=$(doil_get_conf enable_keycloak) - -doil_status_send_message "Copy doil system" -doil_system_copy_doil "$ENABLE_KEYCLOAK" -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Setting up IP" -doil_system_setup_ip -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Setting up access rights" -doil_system_setup_access -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Configuring user specific data" -doil_system_setup_userconfig -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Add safe git dir for user" -doil_system_add_safe_git_dir -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - -doil_status_send_message "Delete potential composer lock file" -doil_system_delete_potential_composer_lock -doil_status_okay - -if [[ -z ${GHRUN} ]] -then - # start salt server - doil_status_send_message "Building doil php image" - doil_system_build_php_image - doil_status_okay - - # start salt server - doil_status_send_message "Installing salt server" - doil_system_install_saltserver - doil_status_okay - - # start proxy server - doil_status_send_message "Installing proxy server" - doil_system_install_proxyserver - doil_status_okay - - # start keycloak server - if [[ "$ENABLE_KEYCLOAK" == true ]] - then - doil_status_send_message "Installing keycloak server" - doil_system_install_keycloakserver - doil_status_okay - fi - - # start mail server - doil_status_send_message "Installing mail server" - doil_system_install_mailserver - doil_status_okay -fi - -doil_status_send_message "Ensure ~/.docker is owned by sudo user" -doil_system_chown_dot_docker -if [[ $? -ne 0 ]] -then - doil_status_failed - exit -fi -doil_status_okay - - -################# -# Everything done -NOW=$(date +'%d.%m.%Y %I:%M:%S') -echo "[${NOW}] Everything done" \ No newline at end of file diff --git a/setup/check_requirements.sh b/setup/scripts/check_requirements.sh similarity index 88% rename from setup/check_requirements.sh rename to setup/scripts/check_requirements.sh index f6a96144..eb634055 100644 --- a/setup/check_requirements.sh +++ b/setup/scripts/check_requirements.sh @@ -5,7 +5,7 @@ # It is able to download ILIAS and other ILIAS related software # like cate. # -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) +# Copyright (C) 2020 - 2025 Daniel Weise (daniel.weise@concepts-and-training.de) # Permission to copy and modify is granted under the AGPL license # # Contribute: https://github.com/conceptsandtraining/doil @@ -23,11 +23,11 @@ function check_requirements() { then doil_check_doil_artifacts if [[ $? -ne 0 ]] - then - doil_status_failed - doil_status_send_error "REQUIREMENT ERROR" "Detect doil artifact. Please ensure to remove doil completely from your system before running install. Otherwise use 'doil update'!" - exit - fi + then + doil_status_failed + doil_status_send_error "REQUIREMENT ERROR" "Detect doil artifact. Please ensure to remove doil completely from your system before running install. Otherwise use 'doil update'!" + exit + fi fi # sudo user check diff --git a/setup/checks.sh b/setup/scripts/checks.sh similarity index 80% rename from setup/checks.sh rename to setup/scripts/checks.sh index 53caa3c2..b99fc0ec 100644 --- a/setup/checks.sh +++ b/setup/scripts/checks.sh @@ -5,7 +5,7 @@ # It is able to download ILIAS and other ILIAS related software # like cate. # -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) +# Copyright (C) 2020 - 2025 Daniel Weise (daniel.weise@concepts-and-training.de) # Permission to copy and modify is granted under the AGPL license # # Contribute: https://github.com/conceptsandtraining/doil @@ -122,6 +122,51 @@ function doil_check_host() { return 0 } +doil_version_compare() { + if [[ $1 == $2 ]] + then + return 0 + fi + local IFS=. + local i ver1=($1) ver2=($2) + # fill empty fields in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) + do + ver1[i]=0 + done + for ((i=0; i<${#ver1[@]}; i++)) + do + if [[ -z ${ver2[i]} ]] + then + # fill empty fields in ver2 with zeros + ver2[i]=0 + fi + if ((10#${ver1[i]} > 10#${ver2[i]})) + then + return 1 + fi + if ((10#${ver1[i]} < 10#${ver2[i]})) + then + return 2 + fi + done + return 0 +} + +doil_test_version_compare() { + doil_version_compare $1 $2 + case $? in + 0) op='=';; + 1) op='>';; + 2) op='<';; + esac + if [[ $op != $3 ]] + then + return 255 + fi + return 0 +} + # checks if the installed docker version is # supported # @@ -132,16 +177,3 @@ function doil_check_docker_version() { doil_test_version_compare ${DOCKER_VERSION} "19.02" ">" return $? } - -# checks if .ssh folder exists -# -# return 255 if .shh is not exists -# return 0 if .ssh is exists -function doil_check_ssh() { - if [[ -d /home/$SUDO_USER/.ssh ]] - then - return 0 - fi - - return 255 -} \ No newline at end of file diff --git a/setup/helper.sh b/setup/scripts/helper.sh similarity index 100% rename from setup/helper.sh rename to setup/scripts/helper.sh diff --git a/setup/log.sh b/setup/scripts/log.sh similarity index 94% rename from setup/log.sh rename to setup/scripts/log.sh index 6f0c0cb2..3220a1cd 100644 --- a/setup/log.sh +++ b/setup/scripts/log.sh @@ -5,7 +5,7 @@ # It is able to download ILIAS and other ILIAS related software # like cate. # -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) +# Copyright (C) 2020 - 2025 Daniel Weise (daniel.weise@concepts-and-training.de) # Permission to copy and modify is granted under the AGPL license # # Contribute: https://github.com/conceptsandtraining/doil @@ -13,6 +13,10 @@ # /ᐠ。‸。ᐟ\ # Thanks to Concepts and Training for supporting doil +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' + doil_status_send_message() { exec >>/dev/tty 2>&1 echo -n "${1} ..." diff --git a/setup/scripts/uninstall.sh b/setup/scripts/uninstall.sh new file mode 100644 index 00000000..e32bffc3 --- /dev/null +++ b/setup/scripts/uninstall.sh @@ -0,0 +1,138 @@ +#!/bin/bash + +# doil is a tool that creates and manages multiple docker container +# with ILIAS and comes with several tools to help manage everything. +# It is able to download ILIAS and other ILIAS related software +# like cate. +# +# Copyright (C) 2020 - 2025 Daniel Weise (daniel.weise@concepts-and-training.de) +# Permission to copy and modify is granted under the AGPL license +# +# Contribute: https://github.com/conceptsandtraining/doil +# +# /ᐠ。‸。ᐟ\ +# Thanks to Concepts and Training for supporting doil + +function doil_system_remove() { + ALL=$1 + + if [ -d /usr/local/lib/doil ] + then + rm -rf /usr/local/lib/doil + fi + + if [ -d /usr/local/share/doil ] + then + rm -rf /usr/local/share/doil + fi + + if [ -d /var/log/doil ] + then + rm -rf /var/log/doil + fi + + if [ -f /usr/local/bin/doil ] + then + rm /usr/local/bin/doil + fi + + doil_system_stop_instances + doil_system_rm_system_instances + doil_system_remove_doil_system_images + doil_system_remove_networks + doil_system_remove_volumes + doil_system_remove_hosts_entry + + delgroup doil >/dev/null 2>&1 + + if [ ! -z ${ALL} ] + then + GLOBAL_INSTANCES_PATH=$(doil_get_conf global_instances_path) + if [ -d "${GLOBAL_INSTANCES_PATH}" ] + then + rm -rf "${GLOBAL_INSTANCES_PATH}" + fi + + doil_system_remove_instances + doil_system_remove_all_images + doil_system_remove_instances_on_disk + + fi + + doil_system_remove_user_doil_folders + + if [ -d /etc/doil ] + then + rm -rf /etc/doil + fi + +} + +function doil_system_stop_instances() { + if [ $(docker ps -q --filter "name=_local" --filter "name=_global" --filter "name=doil_" | wc -l) -gt 0 ] + then + (docker kill $(docker ps -q --filter "name=_local" --filter "name=_global" --filter "name=doil_")) >/dev/null 2>&1 + fi +} + +function doil_system_remove_instances() { + if [ $(docker ps -a -q --filter "name=_local" --filter "name=_global" --filter "name=doil_" | wc -l) -gt 0 ] + then + (docker rm $(docker ps -a -q --filter "name=_local" --filter "name=_global" --filter "name=doil_")) >/dev/null 2>&1 + fi +} + +function doil_system_rm_system_instances() { + if [ $(docker ps -a -q --filter "name=doil_" | wc -l) -gt 0 ] + then + (docker rm $(docker ps -a -q --filter "name=doil_")) >/dev/null 2>&1 + fi +} + +function doil_system_remove_all_images() { + docker rmi -f $(docker images -q --filter reference=doil[/,_]*) >/dev/null 2>&1 +} + +function doil_system_remove_doil_system_images() { + docker rmi -f $(docker images -q --filter reference=doil_*) >/dev/null 2>&1 + docker image prune -f >/dev/null 2>&1 +} + +function doil_system_remove_instances_on_disk() { + if [ ! -z "$(find /home -type l | grep .doil)" ] + then + (find /home -type l | grep .doil | xargs realpath | xargs rm -rf) >/dev/null 2>&1 + fi +} + +function doil_system_remove_networks() { + if [ $(docker network ls -q --filter "name=doil_" | wc -l) -gt 0 ] + then + (docker network rm $(docker network ls -q --filter "name=doil_")) >/dev/null 2>&1 + fi +} + +function doil_system_remove_volumes() { + volumes=( + doil_mail + doil_sieve + keycloak_admin + keycloak_keycloak_1 + ) + + for volume in "${strings[@]}" + do + docker volume rm "$volume" >/dev/null 2>&1 + done +} + +function doil_system_remove_user_doil_folders() { + find /home -name .doil -type d -exec rm -rf {} + +} + +function doil_system_remove_hosts_entry() { + HOST=$(doil_get_conf "host=") + sed -i "/172.24.0.254 ${HOST}/d" /etc/hosts +} + + diff --git a/setup/system.sh b/setup/system.sh deleted file mode 100644 index 6dc6ca98..00000000 --- a/setup/system.sh +++ /dev/null @@ -1,438 +0,0 @@ -#!/bin/bash - -# doil is a tool that creates and manages multiple docker container -# with ILIAS and comes with several tools to help manage everything. -# It is able to download ILIAS and other ILIAS related software -# like cate. -# -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/doil -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil - -function doil_system_remove_old_version() { - # removing old version - if [ -d /usr/local/lib/doil ] - then - rm -rf /usr/local/lib/doil - fi - - if [ -d /usr/local/share/doil/stack ] - then - rm -rf /usr/local/share/doil/stack - fi - - if [ -d /usr/local/share/doil/templates ] - then - rm -rf /usr/local/share/doil/templastes - fi - - return 0 -} - -function doil_system_remove() { - ALL=$1 - - if [ -d /usr/local/lib/doil ] - then - rm -rf /usr/local/lib/doil - fi - - if [ -d /usr/local/share/doil ] - then - rm -rf /usr/local/share/doil - fi - - if [ -d /var/log/doil ] - then - rm -rf /var/log/doil - fi - - if [ -f /usr/local/bin/doil ] - then - rm /usr/local/bin/doil - fi - - doil_system_stop_instances - doil_system_rm_system_instances - doil_system_remove_doil_system_images - doil_system_remove_networks - doil_system_remove_volumes - doil_system_remove_user_doil_folders - doil_system_remove_hosts_entry - - delgroup doil - - if [ ! -z ${ALL} ] - then - GLOBAL_INSTANCES_PATH=$(doil_get_conf global_instances_path) - if [ -d "${GLOBAL_INSTANCES_PATH}" ] - then - rm -rf "${GLOBAL_INSTANCES_PATH}" - fi - - doil_system_remove_instances - doil_system_remove_all_images - doil_system_remove_instances_on_disk - - fi - - if [ -d /etc/doil ] - then - rm -rf /etc/doil - fi - -} - -function doil_system_stop_instances() { - if [ $(docker ps -q --filter "name=_local" --filter "name=_global" --filter "name=doil_" | wc -l) -gt 0 ] - then - (docker kill $(docker ps -q --filter "name=_local" --filter "name=_global" --filter "name=doil_")) >/dev/null 2>&1 - fi -} - -function doil_system_remove_instances() { - if [ $(docker ps -a -q --filter "name=_local" --filter "name=_global" --filter "name=doil_" | wc -l) -gt 0 ] - then - (docker rm $(docker ps -a -q --filter "name=_local" --filter "name=_global" --filter "name=doil_")) >/dev/null 2>&1 - fi -} - -function doil_system_rm_system_instances() { - if [ $(docker ps -a -q --filter "name=doil_" | wc -l) -gt 0 ] - then - (docker rm $(docker ps -a -q --filter "name=doil_")) >/dev/null 2>&1 - fi -} - -function doil_system_remove_all_images() { - docker rmi -f $(docker images -q --filter reference=doil[/,_]*) >/dev/null 2>&1 -} - -function doil_system_remove_doil_system_images() { - docker rmi -f $(docker images -q --filter reference=doil_*) >/dev/null 2>&1 - docker image prune -f >/dev/null 2>&1 -} - -function doil_system_remove_instances_on_disk() { - if [ ! -z "$(find /home -type l | grep .doil)" ] - then - (find /home -type l | grep .doil | xargs realpath | xargs rm -rf) >/dev/null 2>&1 - fi -} - -function doil_system_remove_networks() { - docker network prune -f >/dev/null 2>&1 -} - -function doil_system_remove_volumes() { - docker volume prune -af >/dev/null 2>&1 -} - -function doil_system_remove_user_doil_folders() { - find /home -name .doil -type d -exec rm -rf {} + -} - -function doil_system_remove_hosts_entry() { - HOST=$(doil_get_conf "host=") - sed -i "/172.24.0.254 ${HOST}/d" /etc/hosts -} - -function doil_system_add_safe_git_dir() { - git config --global --add safe.directory '/usr/local/share/doil/repositories/*' - return 0 -} - -function doil_system_add_group() { - CHECK_GROUP=$(grep doil /etc/group) - if [[ -z ${CHECK_GROUP} ]] - then - groupadd doil - fi - - return 0 -} - -function doil_system_add_user_to_doil_group() { - id -nG $SUDO_USER | grep -qw 'doil' - if [[ $? -ne 0 ]] - then - usermod -a -G doil ${SUDO_USER} - fi - return 0 -} - -function doil_system_create_folder() { - GLOBAL_INSTANCES_PATH=$(cat ${SCRIPT_DIR}/conf/doil.conf | grep "global_instances_path" | cut -d '=' -f 2-) - if [ ! -d "${GLOBAL_INSTANCES_PATH}" ] - then - mkdir -p "${GLOBAL_INSTANCES_PATH}" - fi - - if [ ! -d /etc/doil ] - then - mkdir /etc/doil/ - fi - - if [ ! -d /usr/local/lib/doil ] - then - mkdir /usr/local/lib/doil - fi - - if [ ! -d /usr/local/lib/doil/server ] - then - mkdir /usr/local/lib/doil/server - fi - - if [ ! -d /usr/local/share/doil/instances ] - then - mkdir -p /usr/local/share/doil/instances - fi - - if [ ! -d /usr/local/share/doil/repositories ] - then - mkdir -p /usr/local/share/doil/repositories - fi - - if [ ! -d /usr/local/share/doil/templates ] - then - mkdir /usr/local/share/doil/templates - fi - - return 0 -} - -function doil_system_copy_doil() { - enable_keycloak="$1" - if [[ "$enable_keycloak" == true ]] - then - cp -r ${SCRIPT_DIR}/templates/keycloak /usr/local/lib/doil/server/ - else - if [ -d /usr/local/lib/doil/server/keycloak ] - then - rm -rf /usr/local/lib/doil/server/keycloak - fi - fi - - cp ${SCRIPT_DIR}/doil.sh /usr/local/bin/doil - cp -r ${SCRIPT_DIR}/templates/mail /usr/local/lib/doil/server/ - cp -r ${SCRIPT_DIR}/templates/proxy /usr/local/lib/doil/server/ - cp -r ${SCRIPT_DIR}/templates/salt /usr/local/lib/doil/server/ - cp -r ${SCRIPT_DIR}/templates/php /usr/local/lib/doil/server/ - cp -r ${SCRIPT_DIR}/templates/minion /usr/local/share/doil/templates - cp -r ${SCRIPT_DIR}/templates/base /usr/local/share/doil/templates - cp -r ${SCRIPT_DIR}/../app /usr/local/lib/doil - cp -r ${SCRIPT_DIR}/stack /usr/local/share/doil - - return 0 -} - -function doil_system_setup_config() { - - cp ${SCRIPT_DIR}/conf/doil.conf /etc/doil/doil.conf - - if [ ! -f /etc/doil/repositories.json ] - then - touch /etc/doil/repositories.json - fi - - if [ ! -f /etc/doil/user.json ] - then - touch /etc/doil/user.json - fi - - # ilias repo - echo '"a:1:{i:1;O:27:\"CaT\\Doil\\Commands\\Repo\\Repo\":3:{s:7:\"\u0000*\u0000name\";s:5:\"ilias\";s:6:\"\u0000*\u0000url\";s:44:\"https://github.com/ILIAS-eLearning/ILIAS.git\";s:9:\"\u0000*\u0000global\";b:1;}}"' > "/etc/doil/repositories.json" - - chown -R root:doil /etc/doil - - return 0 -} - -function doil_system_setup_ip() { - - IPEXIST=$(grep "172.24.0.254" /etc/hosts) - if [[ -z ${IPEXIST} ]] - then - HOST=$(doil_get_conf "host=") - printf "172.24.0.254 ${HOST}" >> "/etc/hosts" - fi - return 0 -} - -function doil_system_setup_access() { - GLOBAL_INSTANCES_PATH=$(cat ${SCRIPT_DIR}/conf/doil.conf | grep "global_instances_path" | cut -d '=' -f 2-) - - chown -R root:doil "${GLOBAL_INSTANCES_PATH}" - chown -R root:doil /usr/local/lib/doil - chown -R root:doil /etc/doil - chown -R root:doil /usr/local/share/doil - chown root:doil /usr/local/bin/doil - chown -R root:doil /var/log/doil/ - - chmod g+w "${GLOBAL_INSTANCES_PATH}" - chmod -R g+s "${GLOBAL_INSTANCES_PATH}" - chmod g+w /etc/doil/repositories.json - chmod g+w /etc/doil/user.json - chmod -R g+w /etc/doil - chmod -R g+s /etc/doil - chmod -R g+w /usr/local/share/doil/templates - chmod -R g+w /usr/local/share/doil/instances - chmod -R g+s /usr/local/share/doil/instances - chmod -R g+w /usr/local/share/doil/repositories - chmod -R g+s /usr/local/share/doil/repositories - chmod +x /usr/local/bin/doil - chmod -R 777 /var/log/doil/ - - return 0 -} - -function doil_system_setup_userconfig() { - - HOME=$(eval echo "~${SUDO_USER}") - - if [ ! -d ${HOME}/.doil/ ] - then - mkdir ${HOME}/.doil/ - fi - - if [ ! -d ${HOME}/.doil/config/ ] - then - mkdir ${HOME}/.doil/config/ - fi - - if [ ! -f ${HOME}/.doil/config/repositories.json ] - then - touch ${HOME}/.doil/config/repositories.json - fi - - if [ ! -d ${HOME}/.doil/repositories ] - then - mkdir ${HOME}/.doil/repositories - fi - - if [ ! -d ${HOME}/.doil/instances ] - then - mkdir ${HOME}/.doil/instances - fi - - chown -R ${SUDO_USER}:${SODU_USER} "${HOME}/.doil" - - USEREXISTS=$(grep "${SUDO_USER}" /etc/doil/user.json) - if [[ -z ${USEREXISTS} ]] - then - echo '"a:1:{i:0;O:27:\"CaT\\Doil\\Commands\\User\\User\":1:{s:7:\"\u0000*\u0000name\";s:'${#SUDO_USER}':\"'${SUDO_USER}'\";}}"' >> "/etc/doil/user.json" - fi - - return 0 -} - -function doil_system_setup_log() { - if [[ ! -d /var/log/doil/ ]] - then - mkdir /var/log/doil/ - fi - - if [[ ! -d /var/log/doil/xdebug ]] - then - mkdir /var/log/doil/xdebug - fi - - if [[ ! -f /var/log/doil/stream.log ]] - then - touch /var/log/doil/stream.log - fi -} -function doil_system_delete_potential_composer_lock() { - if [ -f /usr/local/lib/doil/app/composer.lock ] - then - rm -rf /usr/local/lib/doil/app/composer.lock - fi - return 0 -} - -function doil_system_build_php_image() { - (docker buildx build -q -t doil_php:stable /usr/local/lib/doil/server/php) 2>&1 > /var/log/doil/stream.log - docker run --rm -ti -v /home:/home -v /usr/local/lib/doil:/usr/local/lib/doil -e PHP_INI_SCAN_DIR=/srv/php/mods-available -w /usr/local/lib/doil/app --user $(id -u):$(id -g) doil_php:stable /usr/local/bin/composer -q -n install -} - -function doil_system_install_saltserver() { - cd /usr/local/lib/doil/server/salt - BUILD=$(docker compose up -d 2>&1 > /var/log/doil/stream.log) 2>&1 > /var/log/doil/stream.log - docker commit doil_saltmain doil_saltmain:stable 2>&1 > /var/log/doil/stream.log -} - -function doil_system_install_keycloakserver() { - cd /usr/local/lib/doil/server/keycloak - - KEYCLOAK_HOSTNAME=$(printf '%s\n' "$(doil_get_conf keycloak_hostname)" | sed -e 's/[\/&]/\\&/g') - KEYCLOAK_NEW_ADMIN_PASSWORD=$(doil_get_conf keycloak_new_admin_password) - KEYCLOAK_OLD_ADMIN_PASSWORD=$(doil_get_conf keycloak_old_admin_password) - # Please leave this in as an example for default user creation - # KEYCLOAK_USR_PASSWORD=$(doil_get_conf keycloak_usr_password) - KEYCLOAK_DB_USERNAME=$(doil_get_conf keycloak_db_username) - KEYCLOAK_DB_PASSWORD=$(doil_get_conf keycloak_db_password) - - sed -i "s/%TPL_SERVER_HOSTNAME%/${KEYCLOAK_HOSTNAME}/g" "/usr/local/lib/doil/server/keycloak/conf/keycloak-startup.conf" - sed -i "s/%TPL_DB_USERNAME%/${KEYCLOAK_DB_USERNAME}/g" "/usr/local/lib/doil/server/keycloak/conf/keycloak-startup.conf" - sed -i "s/%TPL_DB_PASSWORD%/${KEYCLOAK_DB_PASSWORD}/g" "/usr/local/lib/doil/server/keycloak/conf/keycloak-startup.conf" - - sed -i "s/%TPL_DB_USERNAME%/${KEYCLOAK_DB_USERNAME}/g" "/usr/local/lib/doil/server/keycloak/conf/init.sql" - sed -i "s/%TPL_DB_PASSWORD%/${KEYCLOAK_DB_PASSWORD}/g" "/usr/local/lib/doil/server/keycloak/conf/init.sql" - - sed -i "s/%TPL_NEW_ADMIN_PASSWORD%/${KEYCLOAK_NEW_ADMIN_PASSWORD}/g" "/usr/local/share/doil/stack/states/keycloak/keycloak/init.sls" - sed -i "s/%TPL_OLD_ADMIN_PASSWORD%/${KEYCLOAK_OLD_ADMIN_PASSWORD}/g" "/usr/local/share/doil/stack/states/keycloak/keycloak/init.sls" - # Please leave this in as an example for default user creation - # sed -i "s/%TPL_USR_PASSWORD%/${KEYCLOAK_USR_PASSWORD}/g" "/usr/local/share/doil/stack/states/keycloak/keycloak/init.sls" - - BUILD=$(docker compose up -d 2>&1 > /var/log/doil/stream.log) 2>&1 > /var/log/doil/stream.log - sleep 120 - docker exec -i doil_saltmain bash -c "salt 'doil.keycloak' state.highstate saltenv=keycloak" 2>&1 > /var/log/doil/stream.log - docker commit doil_keycloak doil_keycloak:stable 2>&1 > /var/log/doil/stream.log - IDP_META=$(docker exec -i doil_saltmain bash -c "salt 'doil.keycloak' http.query http://localhost:8080/realms/master/protocol/saml/descriptor --out=raw | cut -d \"'\" -f6") - sed -i "s|%TPL_IDP_META%|${IDP_META}|g" "/usr/local/share/doil/stack/states/enable-saml/saml/init.sls" - sed -i "s|%TPL_KEYCLOAK_HOSTNAME%|${KEYCLOAK_HOSTNAME}|g" "/usr/local/share/doil/stack/states/enable-saml/saml/init.sls" - sed -i "s/%TPL_ADMIN_PASSWORD%/${KEYCLOAK_NEW_ADMIN_PASSWORD}/g" "/usr/local/share/doil/stack/states/enable-saml/saml/init.sls" - sed -i "s|%TPL_KEYCLOAK_HOSTNAME%|${KEYCLOAK_HOSTNAME}|g" "/usr/local/share/doil/stack/states/disable-saml/saml/init.sls" - sed -i "s/%TPL_ADMIN_PASSWORD%/${KEYCLOAK_NEW_ADMIN_PASSWORD}/g" "/usr/local/share/doil/stack/states/disable-saml/saml/init.sls" -} - -function doil_system_install_proxyserver() { - cd /usr/local/lib/doil/server/proxy - NAME=$(printf '%s\n' $(doil_get_conf host=) | sed -e 's/[\/&]/\\&/g') - sed -i "s/%TPL_SERVER_NAME%/${NAME}/g" "/usr/local/lib/doil/server/proxy/conf/nginx/local.conf" - BUILD=$(docker compose up -d 2>&1 > /var/log/doil/stream.log) 2>&1 > /var/log/doil/stream.log - sleep 20 - docker exec -i doil_saltmain bash -c "salt 'doil.proxy' state.highstate saltenv=proxyservices" 2>&1 > /var/log/doil/stream.log - docker commit doil_proxy doil_proxy:stable 2>&1 > /var/log/doil/stream.log -} - -function doil_system_install_mailserver() { - cd /usr/local/lib/doil/server/mail - BUILD=$(docker compose up -d 2>&1 > /var/log/doil/stream.log) 2>&1 > /var/log/doil/stream.log - sleep 20 - docker exec -i doil_saltmain bash -c "salt 'doil.mail' state.highstate saltenv=mailservices" 2>&1 > /var/log/doil/stream.log - PASSWORD=$(doil_get_conf mail_password) - if [[ "${PASSWORD}" != "ilias" ]] - then - PASSWORD_HASH=$(docker exec -i doil_saltmain bash -c "salt \"doil.mail\" shadow.gen_password \"${PASSWORD}\" --out txt" | cut -d ' ' -f 2-) - docker exec -i doil_saltmain bash -c "salt \"doil.mail\" grains.setval 'roundcube_password' '${PASSWORD_HASH}'" 2>&1 > /var/log/doil/stream.log - docker exec -i doil_saltmain bash -c "salt \"doil.mail\" state.highstate saltenv=change-roundcube-password" 2>&1 > /var/log/doil/stream.log - fi - docker commit doil_mail doil_mail:stable 2>&1 > /var/log/doil/stream.log -} - -function doil_system_chown_dot_docker() { - HOME=$(eval echo "~${SUDO_USER}") - - if [[ -d "${HOME}/.docker" ]] - then - chown -R ${SUDO_USER}:${SODU_USER} "${HOME}/.docker" - return 0 - fi - - return 255 -} diff --git a/setup/templates/base/Dockerfile b/setup/templates/base/Dockerfile deleted file mode 100755 index bc270852..00000000 --- a/setup/templates/base/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM debian:12 - -RUN apt-get update && apt-get install -y supervisor -RUN apt-get update && apt-get install -y cron default-jre apache2 mc vim nano less zip unzip git tree wget ftp curl wkhtmltopdf imagemagick ghostscript npm libapache2-mod-php8.2 php8.2-curl php8.2-gd php-json php8.2-mysql php8.2-readline php8.2-xsl php8.2-cli php8.2-zip php8.2-mbstring php8.2-soap php8.2-bcmath php8.2-imap apt-utils mariadb-server python3-mysqldb python3-dev default-libmysqlclient-dev build-essential pkg-config - -RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp -RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources -RUN apt-get update && apt-get install -y salt-minion - -RUN /opt/saltstack/salt/bin/python3 -m pip install --upgrade pip -RUN /opt/saltstack/salt/bin/python3 -m pip install mysql - -RUN apt-get update && apt-get remove -y python3-dev default-libmysqlclient-dev build-essential pkg-config - -RUN echo "#!/bin/bash" > /usr/local/bin/run-supervisor.sh && echo "/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf" >> /usr/local/bin/run-supervisor.sh -RUN chmod +x /usr/local/bin/run-supervisor.sh - -ENTRYPOINT ["/usr/local/bin/run-supervisor.sh"] diff --git a/setup/tests/tests/test-helper.sh b/setup/tests/tests/test-helper.sh deleted file mode 100755 index a9e9c491..00000000 --- a/setup/tests/tests/test-helper.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -test_doil_check_sudo() { - source ./setup/checks.sh - doil_check_sudo - local CHECK=$? - assert_string_contains "255" "${CHECK}" -} - -test_doil_check_host() { - source ./setup/checks.sh - - doil_check_host - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_check_docker_version() { - source ./setup/checks.sh - source ./setup/helper.sh - - doil_check_docker_version - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} \ No newline at end of file diff --git a/setup/tests/tests/test-system.sh b/setup/tests/tests/test-system.sh deleted file mode 100755 index 5a3aa14a..00000000 --- a/setup/tests/tests/test-system.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash - -test_doil_system_remove_old_version() { - source ./setup/system.sh - - doil_system_remove_old_version - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_system_add_group() { - source ./setup/system.sh - - doil_system_add_group - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_system_create_folder() { - source ./setup/system.sh - - doil_system_create_folder - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_system_copy_doil() { - source ./setup/system.sh - - doil_system_copy_doil - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_system_setup_config() { - source ./setup/system.sh - - doil_system_setup_config - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_system_setup_access() { - source ./setup/system.sh - - doil_system_setup_access - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} - -test_doil_system_setup_userconfig() { - source ./setup/system.sh - - doil_system_setup_userconfig - local CHECK=$? - - assert_string_contains "0" "${CHECK}" -} \ No newline at end of file diff --git a/setup/tests/tstfy.sh b/setup/tests/tstfy.sh deleted file mode 100755 index 091526d6..00000000 --- a/setup/tests/tstfy.sh +++ /dev/null @@ -1,244 +0,0 @@ -#!/usr/bin/env bash - -# tstfy is a bash unit test suite -# -# Copyright (C) 2020 - 2021 Laura Herzog (laura.herzog@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/tstfy -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil - -# Setup local variables -TEST_STATUS=TRUE -CAT="$(which cat)" -SED="$(which sed)" -GREP="$(which grep)" -RM="$(which rm)" - -# fakes -function rm() { - return 0 -} -function touch() { - return 0 -} -function mkdir() { - return 0 -} -function cp() { - return 0 -} -function mv() { - return 0 -} -function sed() { - return 0 -} -function grep() { - return 0 -} -function cat() { - return 0 -} -function groupadd() { - return 0 -} -function usermod() { - return 0 -} -function chmod() { - return 0 -} -function chown() { - return 0 -} -function printf() { - return 0 -} - -# asserts -_assert_expression() { - local ASSERTION=$1 - local CONDITION=$2 - local MESSAGE=$3 - ( - local STDOUT=$(mktemp) - local STDERR=$(mktemp) - trap "$RM -f \"${STDOUT}\" \"${STDERR}\"" EXIT - - local STATUS - eval "(${ASSERTION})" >"${STDOUT}" 2>"${STDERR}" && STATUS=$? || STATUS=$? - - if ! eval "${CONDITION}" - then - echo -n "FAILURE" - echo -e "\n\t\t${MESSAGE}" - return 1 - fi - ) || return $? -} - -assert() { - local ASSERTION=$1 - local MESSAGE=${2:-} - - _assert_expression \ - "${ASSERTION}" \ - "[ \${STATUS} == 0 ]" \ - "\"${MESSAGE}\"" -} - -assert_equals() { - local EXPECTED=$1 - local ACTUAL=$2 - - if [ "${EXPECTED}" != "${ACTUAL}" ] - then - echo -n "FAILURE" - echo -e "\n\t\texpected [${EXPECTED}] but was [${ACTUAL}]" - return 1 - fi -} - -assert_not_equals() { - local EXPECTED=$1 - local ACTUAL=$2 - - if [ "${EXPECTED}" == "${ACTUAL}" ] - then - echo -n "FAILURE" - echo -e "\n\t\texpected [${EXPECTED}] to be different but is equal to [${ACTUAL}]" - return 1 - fi -} - -assert_fails() { - local ASSERTION=$1 - local MESSAGE=${2:-} - - _assert_expression \ - "${ASSERTION}" \ - "[ \${STATUS} != 0 ]" \ - "\"${MESSAGE}\"" -} - -assert_status_code() { - local EXPECTED_STATUS=$1 - local ASSERTION="$2" - local MESSAGE="${3:-}" - - _assert_expression \ - "${ASSERTION}" \ - "[ \${STATUS} == ${EXPECTED_STATUS} ]" \ - "expected status code [${EXPECTED_STATUS}] but was ${STATUS}" -} - -assert_contains() { - local EXPECTED=$1 - local ACTUAL=$2 - - if [[ ! " ${ACTUAL[*]} " =~ " ${EXPECTED} " ]] - then - echo -n "FAILURE" - echo -e "\n\t\texpected [${EXPECTED}] in stack but stack contains [${ACTUAL}]" - return 1 - fi -} - -assert_string_contains() { - local EXPECTED=$1 - local ACTUAL=$2 - - if [[ ! ${ACTUAL} == *"${EXPECTED}"* ]] - then - echo -n "FAILURE" - echo -e "\n\t\texpected [${EXPECTED}] in string but string contains [${ACTUAL}]" - return 1 - fi -} - -tstfy_run_test() { - set -e - "${1}" -} - -tstfy() { - declare -a TESTS - - if [[ -d $@ ]] - then - TEST_FILES=$(find . -type f -name "test-*") - else - TEST_FILES=$@ - fi - - TEST_COUNTER=0 - TEST_COUNTER_FILES=0 - TEST_COUNTER_SUCCESS=0 - TEST_COUNTER_FAILED=0 - - for TEST_FILE in ${TEST_FILES[@]} - do - FILE_EXISTS=TRUE - FILE_READABLE=TRUE - - test -e "${TEST_FILE}" || FILE_EXISTS=FALSE - test -r "${TEST_FILE}" || FILE_READABLE=FALSE - - if [[ ${FILE_EXISTS} == FALSE ]] - then - echo -e "File ${TEST_FILE} does not exist. Skipping." - fi - - if [[ ${FILE_READABLE} == FALSE ]] - then - echo -e "File ${TEST_FILE} is not readable. Skipping." - fi - - if [[ ${FILE_EXISTS} == TRUE ]] && - [[ ${FILE_READABLE} == TRUE ]] - then - TEST_COUNTER_FILES=$[$TEST_COUNTER_FILES +1] - echo "" - echo "Running tests in ${TEST_FILE}" - source ${TEST_FILE} - - for TEST in $(set | "${GREP}" -E '^test.* \(\)' | "${SED}" -e 's: .*::') - do - if [[ ! " ${TESTS[@]} " =~ " ${TEST} " ]]; then - TESTS=("${TESTS[@]}" ${TEST}) - TEST_COUNTER=$[$TEST_COUNTER +1] - - # run test - echo -en "\tRunning ${TEST} ... " - - local STATUS=0 - declare -F | "${GREP}" ' setup$' >/dev/null && setup - tstfy_run_test ${TEST} || STATUS=$? - declare -F | "${GREP}" ' teardown$' >/dev/null && teardown - - # check status - if [[ ${STATUS} == 0 ]] - then - echo -n "ok" - TEST_COUNTER_SUCCESS=$[$TEST_COUNTER_SUCCESS +1] - else - TEST_COUNTER_FAILED=$[$TEST_COUNTER_FAILED +1] - TEST_STATUS=FALSE - fi - - echo -e " " - fi - done - fi - done - echo -e "${TEST_COUNTER} test(s) in ${TEST_COUNTER_FILES} file(s), ${TEST_COUNTER_SUCCESS} succeed, ${TEST_COUNTER_FAILED} failed\n" -} -tstfy $@ - -if [[ ${TEST_STATUS} == FALSE ]] -then - exit 1 -fi \ No newline at end of file diff --git a/setup/uninstall.sh b/setup/uninstall similarity index 52% rename from setup/uninstall.sh rename to setup/uninstall index d8082b14..8ef12242 100755 --- a/setup/uninstall.sh +++ b/setup/uninstall @@ -1,29 +1,11 @@ #!/bin/bash -# doil is a tool that creates and manages multiple docker container -# with ILIAS and comes with several tools to help manage everything. -# It is able to download ILIAS and other ILIAS related software -# like cate. -# -# Copyright (C) 2020 - 2023 Daniel Weise (daniel.weise@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/doil -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil +SCRIPT_DIR=$(realpath "$0" | sed 's|\(.*\)/.*|\1|') -# get the helper -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) - -source ${SCRIPT_DIR}/checks.sh -source ${SCRIPT_DIR}/log.sh -source ${SCRIPT_DIR}/system.sh -source ${SCRIPT_DIR}/check_requirements.sh -source ${SCRIPT_DIR}/updates/update.sh -source ${SCRIPT_DIR}/helper.sh -source ${SCRIPT_DIR}/env.sh -source ${SCRIPT_DIR}/colors.sh +source ${SCRIPT_DIR}/scripts/checks.sh +source ${SCRIPT_DIR}/scripts/log.sh +source ${SCRIPT_DIR}/scripts/helper.sh +source ${SCRIPT_DIR}/scripts/uninstall.sh function delete() { ALL=$1 @@ -34,8 +16,12 @@ function delete() { fi doil_system_remove + + echo "Doil is now removed from your system." + echo "Thank you for using doil!" } + # sudo user check doil_check_sudo if [[ $? -ne 0 ]] diff --git a/setup/update.sh b/setup/update.sh deleted file mode 100755 index 563c5a55..00000000 --- a/setup/update.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# doil is a tool that creates and manages multiple docker container -# with ILIAS and comes with several tools to help manage everything. -# It is able to download ILIAS and other ILIAS related software -# like cate. -# -# Copyright (C) 2020 - 2021 Laura Herzog (laura.herzog@concepts-and-training.de) -# Permission to copy and modify is granted under the AGPL license -# -# Contribute: https://github.com/conceptsandtraining/doil -# -# /ᐠ。‸。ᐟ\ -# Thanks to Concepts and Training for supporting doil - -# get the helper -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) - -source ${SCRIPT_DIR}/checks.sh -source ${SCRIPT_DIR}/log.sh -source ${SCRIPT_DIR}/system.sh -source ${SCRIPT_DIR}/check_requirements.sh -source ${SCRIPT_DIR}/updates/update.sh -source ${SCRIPT_DIR}/helper.sh -source ${SCRIPT_DIR}/env.sh -source ${SCRIPT_DIR}/colors.sh - -echo "This update will stop all running doil instances. Please ensure to save relevant files." -read -r -p "Do you want to continue update? [y/N] " RESPONSE -case "$RESPONSE" in - [yY][eE][sS]|[yY]) - check_requirements update - echo "Performing updates. This will take a while." - # perform the update - doil_perform_update - echo "Update finished" - ;; - *) - echo "Abort by user!" - exit - ;; -esac diff --git a/setup/updates/update-20240730.sh b/setup/updates/update-20240730.sh deleted file mode 100644 index 1d5c765c..00000000 --- a/setup/updates/update-20240730.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20240730() { -cat < /dev/null - sleep 5 - docker exec -it ${INSTANCE} /bin/bash -c "sed -i 's%/var/lib/salt/pki/minion/minion_master.pub%/etc/salt/pki/minion/minion_master.pub%g' /root/salt-startup.sh" &> /dev/null - docker commit ${INSTANCE} doil/${INSTANCE}:stable &> /dev/null - docker stop ${INSTANCE} &> /dev/null - done - doil_status_okay - fi - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20240902.sh b/setup/updates/update-20240902.sh deleted file mode 100644 index 30e1ac33..00000000 --- a/setup/updates/update-20240902.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20240902() { - 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/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20240926.sh b/setup/updates/update-20240926.sh deleted file mode 100644 index ac109159..00000000 --- a/setup/updates/update-20240926.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20240926() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/* /usr/local/share/doil/stack/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20240930.sh b/setup/updates/update-20240930.sh deleted file mode 100644 index 437d68c7..00000000 --- a/setup/updates/update-20240930.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20240930() { - cp ${SCRIPT_DIR}/../app/src/Commands/Pack/ImportCommand.php /usr/local/lib/doil/app/src/Commands/Pack/ - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/* /usr/local/share/doil/stack/ - doil salt:restart - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20241010.sh b/setup/updates/update-20241010.sh deleted file mode 100644 index ae6231c8..00000000 --- a/setup/updates/update-20241010.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20241010() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/* /usr/local/share/doil/stack/ - docker exec -i doil_saltmain bash -c "salt -C '*.local or *.global' state.highstate saltenv=apache" - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20241113.sh b/setup/updates/update-20241113.sh deleted file mode 100644 index 21396e32..00000000 --- a/setup/updates/update-20241113.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -source ${SCRIPT_DIR}/updates/update.sh - -doil_update_20241113() { - -cat < /dev/null - sleep 5 - docker exec -it ${INSTANCE} /bin/bash -c "sed -i 's%${NEEDLE}%${REPLACE}%g' /var/ilias/data/ilias-config.json" &> /dev/null - docker exec -it ${INSTANCE} /bin/bash -c "cd /var/www/html && php setup/setup.php update -y /var/ilias/data/ilias-config.json" &> /dev/null - NAME=$(echo "${INSTANCE%_*}") - SUFFIX=$(echo "${INSTANCE}" | rev | cut -d "_" -f 1 | rev) - GLOBAL_PARAM="-g" - if [ "${SUFFIX}" == "local" ] - then - GLOBAL_PARAM="" - fi - doil apply "${NAME}" "${GLOBAL_PARAM}" enable-https - docker exec -it ${INSTANCE} /bin/bash -c "salt-call grains.set doil_domain ${REPLACE}/${NAME}" - doil apply "${NAME}" "${GLOBAL_PARAM}" access - docker commit ${INSTANCE} doil/${INSTANCE}:stable &> /dev/null - docker stop ${INSTANCE} &> /dev/null - done - doil_status_okay - fi - fi - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250130.sh b/setup/updates/update-20250130.sh deleted file mode 100644 index 7dc3f53a..00000000 --- a/setup/updates/update-20250130.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250130() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250217.sh b/setup/updates/update-20250217.sh deleted file mode 100644 index 494fb43d..00000000 --- a/setup/updates/update-20250217.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250217() { - cp -r ${SCRIPT_DIR}/../setup/stack/* /usr/local/share/doil/stack/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250226.sh b/setup/updates/update-20250226.sh deleted file mode 100644 index c29f5405..00000000 --- a/setup/updates/update-20250226.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250226() { - -cat < /dev/null - docker commit doil_proxy doil_proxy:stable &> /dev/null - - 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 - if [ "${UPDATE_TOKEN}" != "false" ] - then - docker exec -it doil_saltmain /bin/bash -c "salt \"${NAME}.${SUFFIX}\" state.highstate saltenv=ilias-update-hook" &> /dev/null - fi - if [ ${STARTED} == 1 ] - then - doil down ${NAME} ${GLOBAL} - else - doil restart ${NAME} ${GLOBAL} - fi - fi - done - - if [ "${UPDATE_TOKEN}" != "false" ] - then - doil sut -q -a -t "${UPDATE_TOKEN}" &> /dev/null - doil sut -q -a -t "${UPDATE_TOKEN}" -g &> /dev/null - fi - - doil_status_okay - fi - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250404.sh b/setup/updates/update-20250404.sh deleted file mode 100644 index db0e521e..00000000 --- a/setup/updates/update-20250404.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250404() { - cp -r ${SCRIPT_DIR}/../setup/templates/proxy/conf/nginx/local.conf /usr/local/lib/doil/server/proxy/conf/nginx/local.conf - doil proxy:restart - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250430.sh b/setup/updates/update-20250430.sh deleted file mode 100644 index 6445e8df..00000000 --- a/setup/updates/update-20250430.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250430() { - update - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250523.sh b/setup/updates/update-20250523.sh deleted file mode 100644 index 60345eef..00000000 --- a/setup/updates/update-20250523.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250523() { - 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/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250624.sh b/setup/updates/update-20250624.sh deleted file mode 100644 index 6d74143f..00000000 --- a/setup/updates/update-20250624.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250624() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 /usr/local/share/doil/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250701.sh b/setup/updates/update-20250701.sh deleted file mode 100644 index d3899d3d..00000000 --- a/setup/updates/update-20250701.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250701() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/autoinstall/* /usr/local/share/doil/stack/states/autoinstall/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/enable-saml/saml/authsources.php.j2 /usr/local/share/doil/stack/states/enable-saml/saml/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250707.sh b/setup/updates/update-20250707.sh deleted file mode 100644 index b6e815a8..00000000 --- a/setup/updates/update-20250707.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250707() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/enable-saml/saml/authsources.php.j2 /usr/local/share/doil/stack/states/enable-saml/saml/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250725.sh b/setup/updates/update-20250725.sh deleted file mode 100644 index 520ff0a7..00000000 --- a/setup/updates/update-20250725.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250725() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/autoinstall/autoinstall/init.sls /usr/local/share/doil/stack/states/autoinstall/autoinstall/ - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250806.sh b/setup/updates/update-20250806.sh deleted file mode 100644 index 1ff4bfd8..00000000 --- a/setup/updates/update-20250806.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250806() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias/* /usr/local/share/doil/stack/states/ilias - cp -r ${SCRIPT_DIR}/../setup/stack/states/autoinstall/* /usr/local/share/doil/stack/states/autoinstall - - for DIR in /home/$SUDO_USER/.doil/instances/* - do - WWW_LINE_NUMBER=$(/usr/bin/cat "${DIR}"/docker-compose.yml 2> /dev/null | grep -n /var/www/.ssh | cut -d ':' -f 1) - ROOT_LINE_NUMBER=$(/usr/bin/cat "${DIR}"/docker-compose.yml 2> /dev/null | grep -n /root/.ssh | cut -d ':' -f 1) - - if [ "${WWW_LINE_NUMBER}" != "" ] - then - sed -i "$((WWW_LINE_NUMBER-2)),$((WWW_LINE_NUMBER))d" "${DIR}"/docker-compose.yml - fi - - if [ "${ROOT_LINE_NUMBER}" != "" ] - then - sed -i "$((ROOT_LINE_NUMBER-2)),$((ROOT_LINE_NUMBER))d" "${DIR}"/docker-compose.yml - fi - done - - for DIR in $(doil_get_conf global_instances_path=)/* - do - WWW_LINE_NUMBER=$(/usr/bin/cat "${DIR}"/docker-compose.yml 2> /dev/null | grep -n /var/www/.ssh | cut -d ':' -f 1) - ROOT_LINE_NUMBER=$(/usr/bin/cat "${DIR}"/docker-compose.yml 2> /dev/null | grep -n /root/.ssh | cut -d ':' -f 1) - if [ "${WWW_LINE_NUMBER}" != "" ] - then - sed -i "$((WWW_LINE_NUMBER-2)),$((WWW_LINE_NUMBER))d" "${DIR}"/docker-compose.yml - fi - - if [ "${ROOT_LINE_NUMBER}" != "" ] - then - sed -i "$((ROOT_LINE_NUMBER-2)),$((ROOT_LINE_NUMBER))d" "${DIR}"/docker-compose.yml - fi - done - - GIT_PRIVATE_SSH_KEY_PATH=$(doil_get_conf git_private_ssh_key_path=) - if [ "${GIT_PRIVATE_SSH_KEY_PATH}" == "" ] - then - echo "Please ensure to set 'git_private_ssh_key_path' in '/etc/doil/doil.conf' properly!" - exit 1 - fi - GIT_PRIVATE_SSH_KEY="$(cat ${GIT_PRIVATE_SSH_KEY_PATH})" - - GIT_PUBLIC_SSH_KEY_PATH=$(doil_get_conf git_public_ssh_key_path=) - if [ "${GIT_PUBLIC_SSH_KEY_PATH}" == "" ] - then - echo "Please ensure to set 'git_public_ssh_key_path' in '/etc/doil/doil.conf' properly!" - exit 1 - fi - GIT_PUBLIC_SSH_KEY="$(cat ${GIT_PUBLIC_SSH_KEY_PATH})" - - if [ $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}" | wc -l) -gt 0 ] - then - for INSTANCE in $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}") - do - NAME=${INSTANCE%_*} - SUFFIX=${INSTANCE##*_} - GLOBAL="" - if [ "${SUFFIX}" == "global" ] - then - GLOBAL="-g" - fi - doil down ${NAME} ${GLOBAL} &> /dev/null - sleep 15 - doil up ${NAME} ${GLOBAL} &> /dev/null - sleep 5 - - doil_status_send_message "Apply state ilias to ${NAME}" - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' state.highstate saltenv=ilias" &> /dev/null - doil_status_okay - - doil_status_send_message "Deploy ssh keys to ${NAME}" - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'echo \"${GIT_PRIVATE_SSH_KEY}\" > /root/.ssh/doil_git'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'echo \"${GIT_PRIVATE_SSH_KEY}\" > /var/www/.ssh/doil_git'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'echo \"${GIT_PUBLIC_SSH_KEY}\" > /root/.ssh/doil_git.pub'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'echo \"${GIT_PUBLIC_SSH_KEY}\" > /var/www/.ssh/doil_git.pub'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'echo \"Host *github*\n\tIdentityFile ~/.ssh/doil_git\n\tIdentitiesOnly yes\" > /root/.ssh/config'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'echo \"Host *github*\n\tIdentityFile ~/.ssh/doil_git\n\tIdentitiesOnly yes\" > /var/www/.ssh/config'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'ssh-keyscan github.com > /root/.ssh/known_hosts'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'ssh-keyscan github.com > /var/www/.ssh/known_hosts'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'chmod 0400 /root/.ssh/doil_git /var/www/.ssh/doil_git'" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'chown -R 1000:1000 /var/www/.ssh'" &> /dev/null - doil_status_okay - - doil_status_send_message "Commit image for ${NAME}" - docker commit ${INSTANCE} doil/${INSTANCE}:stable &> /dev/null - doil_status_okay - - docker stop ${INSTANCE} &> /dev/null - done - fi - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250901.sh b/setup/updates/update-20250901.sh deleted file mode 100644 index 8308e602..00000000 --- a/setup/updates/update-20250901.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250901() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250903.sh b/setup/updates/update-20250903.sh deleted file mode 100644 index 81b64f1a..00000000 --- a/setup/updates/update-20250903.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250903() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias/imagemagick/init.sls /usr/local/share/doil/stack/states/ilias/imagemagick/ - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20250908.sh b/setup/updates/update-20250908.sh deleted file mode 100644 index 49e0a11e..00000000 --- a/setup/updates/update-20250908.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250908() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/mailservices/mailservices/* /usr/local/share/doil/stack/states/mailservices/mailservices/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 /usr/local/share/doil/stack/states/keycloak/keycloak/delete_keycloak_client.sh.j2 - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 /usr/local/share/doil/stack/states/ilias-update-hook/ilias-update-hook/update_hook.php.j2 - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias/* /usr/local/share/doil/stack/states/ilias/ - - if [ $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}" | wc -l) -gt 0 ] - then - for INSTANCE in $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}") - do - NAME=${INSTANCE%_*} - SUFFIX=${INSTANCE##*_} - GLOBAL="" - if [ "${SUFFIX}" == "global" ] - then - GLOBAL="-g" - fi - - doil up ${NAME} ${GLOBAL} &> /dev/null - sleep 5 - - doil_status_send_message "Apply state ilias-update-hook to ${NAME}" - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' state.highstate saltenv=ilias-update-hook" &> /dev/null - doil_status_okay - - doil_status_send_message "Apply state ilias to ${NAME}" - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' state.highstate saltenv=ilias" &> /dev/null - doil_status_okay - - doil_status_send_message "Commit image for ${NAME}" - docker commit ${INSTANCE} doil/${INSTANCE}:stable &> /dev/null - doil_status_okay - - docker stop ${INSTANCE} &> /dev/null - done - fi - - return $? -} diff --git a/setup/updates/update-20250918.sh b/setup/updates/update-20250918.sh deleted file mode 100644 index f0d93c52..00000000 --- a/setup/updates/update-20250918.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250918() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias/* /usr/local/share/doil/stack/states/ilias/ - - if [ $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}" | wc -l) -gt 0 ] - then - for INSTANCE in $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}") - do - NAME=${INSTANCE%_*} - SUFFIX=${INSTANCE##*_} - GLOBAL="" - if [ "${SUFFIX}" == "global" ] - then - GLOBAL="-g" - fi - - doil up ${NAME} ${GLOBAL} &> /dev/null - sleep 5 - - doil_status_send_message "Apply state ilias to ${NAME}" - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' state.highstate saltenv=ilias" &> /dev/null - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' cmd.run 'supervisorctl update" &> /dev/null - doil_status_okay - - doil_status_send_message "Commit image for ${NAME}" - docker commit ${INSTANCE} doil/${INSTANCE}:stable &> /dev/null - doil_status_okay - - docker stop ${INSTANCE} &> /dev/null - done - fi - - return $? -} diff --git a/setup/updates/update-20250924.sh b/setup/updates/update-20250924.sh deleted file mode 100644 index 25943811..00000000 --- a/setup/updates/update-20250924.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20250924() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20251103.sh b/setup/updates/update-20251103.sh deleted file mode 100644 index 5a8050ae..00000000 --- a/setup/updates/update-20251103.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20251103() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/ilias-update-hook/* /usr/local/share/doil/stack/states/ilias-update-hook/ - - if [ $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}" | wc -l) -gt 0 ] - then - for INSTANCE in $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}") - do - NAME=${INSTANCE%_*} - SUFFIX=${INSTANCE##*_} - GLOBAL="" - if [ "${SUFFIX}" == "global" ] - then - GLOBAL="-g" - fi - - doil up ${NAME} ${GLOBAL} &> /dev/null - sleep 5 - - doil_status_send_message "Apply state ilias to ${NAME}" - docker exec -it doil_saltmain /bin/bash -c "salt '${NAME}.${SUFFIX}' state.highstate saltenv=ilias-update-hook" &> /dev/null - doil_status_okay - - docker stop ${INSTANCE} &> /dev/null - done - fi - return $? -} \ No newline at end of file diff --git a/setup/updates/update-20251125.sh b/setup/updates/update-20251125.sh deleted file mode 100644 index 0cf1adcd..00000000 --- a/setup/updates/update-20251125.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -doil_update_20251125() { - cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ - cp -r ${SCRIPT_DIR}/../setup/stack/states/nodejs/* /usr/local/share/doil/stack/states/nodejs/ - - if [ $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}" | wc -l) -gt 0 ] - then - for INSTANCE in $(docker ps -a --filter "name=_local" --filter "name=_global" --format "{{.Names}}") - do - NAME=${INSTANCE%_*} - SUFFIX=${INSTANCE##*_} - GLOBAL="" - if [ "${SUFFIX}" == "global" ] - then - GLOBAL="-g" - fi - - doil up ${NAME} ${GLOBAL} &> /dev/null - sleep 5 - - doil_status_send_message "Apply state ilias to ${NAME}" - docker exec -it "${INSTANCE}" /bin/bash -c "rm -rf /etc/apt/sources.list.d/salt.list" &> /dev/null - docker exec -it "${INSTANCE}" /bin/bash -c "salt 'curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp" &> /dev/null - docker exec -it "${INSTANCE}" /bin/bash -c "salt 'curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources" &> /dev/null - doil_status_okay - - docker stop ${INSTANCE} &> /dev/null - done - fi - return $? -} \ No newline at end of file diff --git a/setup/updates/update.sh b/setup/updates/update.sh deleted file mode 100755 index dc2f6f04..00000000 --- a/setup/updates/update.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env bash - -update() { - ENABLE_KEYCLOAK=$(doil_get_conf enable_keycloak) - - doil_status_send_message_nl "Stopping all services" - doil_system_stop_instances - - doil_status_send_message "Removing old doil system" - doil_system_remove_old_version - if [[ $? -ne 0 ]] - then - doil_status_failed - exit - fi - doil_status_okay - - doil_status_send_message "Copying new doil system" - doil_system_create_folder - doil_system_copy_doil "$ENABLE_KEYCLOAK" - doil_status_okay - - doil_status_send_message "Creating log file" - doil_system_setup_log - if [[ $? -ne 0 ]] - then - doil_status_failed - exit - fi - doil_status_okay - - doil_status_send_message "Setting up access rights" - doil_system_setup_access - if [[ $? -ne 0 ]] - then - doil_status_failed - exit - fi - doil_status_okay - - doil_status_send_message "Stopping all doil instances" - doil_system_stop_instances - doil_status_okay - - doil_status_send_message "Removing doil system instances" - doil_system_rm_system_instances - doil_status_okay - - doil_status_send_message "Removing old doil images" - doil_system_remove_doil_system_images - doil_status_okay - - doil_status_send_message "Copying new doil system" - doil_system_create_folder - doil_system_copy_doil "$ENABLE_KEYCLOAK" - doil_status_okay - - doil_status_send_message "Adding safe git dir for user" - doil_system_add_safe_git_dir - if [[ $? -ne 0 ]] - then - doil_status_failed - exit - fi - doil_status_okay - - doil_status_send_message "Deleting potential composer lock file" - doil_system_delete_potential_composer_lock - doil_status_okay - - doil_status_send_message "Building doil php image" - doil_system_build_php_image - if [[ $? -ne 0 ]] - then - doil_status_failed - exit - fi - doil_status_okay - - doil_status_send_message "Setting up access rights" - doil_system_setup_access - if [[ $? -ne 0 ]] - then - doil_status_failed - exit - fi - doil_status_okay - - doil_status_send_message "Reinstalling salt service" - doil_system_install_saltserver - doil_status_okay - - # start keycloak server - if [[ "$ENABLE_KEYCLOAK" == true ]] - then - doil_status_send_message "Reinstalling keycloak server" - doil_system_install_keycloakserver - doil_status_okay - fi - - doil_status_send_message "Reinstalling proxy service" - doil_system_install_proxyserver - doil_status_okay - - doil_status_send_message "Reinstalling mail service" - doil_system_install_mailserver - doil_status_okay - - return 0 -} \ No newline at end of file