diff --git a/group_vars/all/07_applications.yml b/group_vars/all/07_applications.yml index a1298a2f..3dafaeae 100644 --- a/group_vars/all/07_applications.yml +++ b/group_vars/all/07_applications.yml @@ -40,6 +40,12 @@ defaults_applications: #plc_rotation_key_k256_private_key_hex: # Needs to be defined in inventory file - Use: openssl rand -hex 32 #admin_password: # Needs to be defined in inventory file - Use: openssl rand -base64 16 + ## Discourse: + discourse: + container: "discourse_application" # Name of the container application + repository: "discourse_repository" # Name of the repository folder + # database_password: # Needs to be defined in inventory file + ## Friendica friendica: version: "latest" diff --git a/inventory.example.yml b/inventory.example.yml deleted file mode 100644 index 72bea98f..00000000 --- a/inventory.example.yml +++ /dev/null @@ -1,51 +0,0 @@ -# THIS INVENTORY IS AN EXAMPLE INVENTORY. -# You should change all of the variables in here. -# Addidiotnally feel free to overwrite configuration variables of group_vars/all in the enventory - -# PASSWORDS AND SECRETS: -akaunting_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -akaunting_setup_admin_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -baserow_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_etherpad_api_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_fsesl_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_rails_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_shared_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_postgresql_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -bigbluebutton_turn_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -central_mariadb_root_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -central_postgres_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -discourse_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -gitlab_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -gitlab_initial_root_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -gitea_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -listmonk_admin_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -listmonk_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mailu_api_token: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mailu_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mailu_initial_root_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mailu_secret_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mastodon_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mastodon_otp_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mastodon_secret_key_base: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mastodon_vapid_private_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -mastodon_vapid_public_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matomo_auth_token: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matomo_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matrix_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matrix_generic_secret_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matrix_form_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matrix_macaroon_secret_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -matrix_registration_shared_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -nextcloud_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -openproject_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -peertube_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -peertube_secret: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -pixelfed_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -pixelfed_app_key: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -wordpress_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -yourls_database_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" -yourls_administrator_password: "I_NEED_TO_CHANGE_THIS_UNSECURE_PASSWORD" - -path_mass_storage: "/mnt/hdd/" -path_rapid_storage: "/mnt/ssd/" \ No newline at end of file diff --git a/roles/docker-discourse/handlers/main.yml b/roles/docker-discourse/handlers/main.yml index 431b2cca..a825baae 100644 --- a/roles/docker-discourse/handlers/main.yml +++ b/roles/docker-discourse/handlers/main.yml @@ -1,7 +1,7 @@ --- - name: "stop and remove discourse container if it exist" docker_container: - name: "{{discourse_application_container}}" + name: "{{applications.discourse.container}}" state: absent register: container_action failed_when: container_action.failed and 'No such container' not in container_action.msg @@ -16,6 +16,6 @@ - name: rebuild discourse command: - cmd: "./launcher rebuild {{discourse_application_container}}" + cmd: "./launcher rebuild {{applications.discourse.container}}" chdir: "{{discourse_repository_directory}}" listen: recreate discourse \ No newline at end of file diff --git a/roles/docker-discourse/tasks/main.yml b/roles/docker-discourse/tasks/main.yml index 6317e6eb..faf3cbf9 100644 --- a/roles/docker-discourse/tasks/main.yml +++ b/roles/docker-discourse/tasks/main.yml @@ -60,9 +60,9 @@ - name: flush, to recreate discourse app meta: flush_handlers -- name: "add {{discourse_application_container}} to network central_postgres" +- name: "add {{applications.discourse.container}} to network central_postgres" command: - cmd: "docker network connect central_postgres {{discourse_application_container}}" + cmd: "docker network connect central_postgres {{applications.discourse.container}}" ignore_errors: true when: enable_central_database | bool diff --git a/roles/docker-discourse/templates/discourse_application.yml.j2 b/roles/docker-discourse/templates/discourse_application.yml.j2 index 207d01d4..8a7db606 100644 --- a/roles/docker-discourse/templates/discourse_application.yml.j2 +++ b/roles/docker-discourse/templates/discourse_application.yml.j2 @@ -130,4 +130,4 @@ run: docker_args: - --network={{application_id}}_default - - --name={{discourse_application_container}} + - --name={{applications.discourse.container}} diff --git a/roles/docker-discourse/vars/main.yml b/roles/docker-discourse/vars/main.yml index ffeed9e4..f28b0b1f 100644 --- a/roles/docker-discourse/vars/main.yml +++ b/roles/docker-discourse/vars/main.yml @@ -1,6 +1,5 @@ application_id: "discourse" -discourse_application_container: "discourse_application" -database_password: "{{ discourse_database_password }}" +database_password: "{{ applications.discourse.database_password }}" database_type: "postgres" -discourse_repository_directory: "{{docker_compose.directories.services}}repository/" -discourse_application_yml_destination: "{{discourse_repository_directory}}containers/discourse_application.yml" \ No newline at end of file +discourse_repository_directory: "{{docker_compose.directories.services}}{{applications.discourse.repository}}/" +discourse_application_yml_destination: "{{discourse_repository_directory}}containers/{{applications.discourse.container}}.yml" \ No newline at end of file diff --git a/roles/update-docker/tasks/main.yml b/roles/update-docker/tasks/main.yml index 8fb91cda..51c50e44 100644 --- a/roles/update-docker/tasks/main.yml +++ b/roles/update-docker/tasks/main.yml @@ -5,8 +5,8 @@ when: mode_backup | bool - name: create {{update_docker_script}} - copy: - src: update-docker.py + template: + src: update-docker.py.j2 dest: "{{update_docker_script}}" - name: configure update-docker.cymais.service diff --git a/roles/update-docker/files/update-docker.py b/roles/update-docker/templates/update-docker.py.j2 similarity index 73% rename from roles/update-docker/files/update-docker.py rename to roles/update-docker/templates/update-docker.py.j2 index d29086a8..84264228 100644 --- a/roles/update-docker/files/update-docker.py +++ b/roles/update-docker/templates/update-docker.py.j2 @@ -4,6 +4,11 @@ import sys import time def run_command(command): + """ + Executes the specified shell command, streaming and collecting its output in real-time. + If the command exits with a non-zero status, a subprocess.CalledProcessError is raised, + including the exit code, the executed command, and the full output (as bytes) for debugging purposes. + """ process = None try: process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -25,19 +30,35 @@ def run_command(command): def git_pull(): """ Checks whether the Git repository in the specified directory is up to date and performs a git pull if necessary. - """ - print(f"Checking if the git repository is up to date.") - local = subprocess.check_output("git rev-parse @", shell=True).decode().strip() - remote = subprocess.check_output("git rev-parse @{u}", shell=True).decode().strip() + Raises: + Exception: If retrieving the local or remote git revision fails because the command returns a non-zero exit code. + """ + print("Checking if the git repository is up to date.") + + # Run 'git rev-parse @' and check its exit code explicitly. + local_proc = subprocess.run("git rev-parse @", shell=True, capture_output=True) + if local_proc.returncode != 0: + error_msg = local_proc.stderr.decode().strip() or "Unknown error while retrieving local revision." + raise Exception(f"Failed to retrieve local git revision: {error_msg}") + local = local_proc.stdout.decode().strip() + + # Run 'git rev-parse @{u}' and check its exit code explicitly. + remote_proc = subprocess.run("git rev-parse @{u}", shell=True, capture_output=True) + if remote_proc.returncode != 0: + error_msg = remote_proc.stderr.decode().strip() or "Unknown error while retrieving remote revision." + raise Exception(f"Failed to retrieve remote git revision: {error_msg}") + remote = remote_proc.stdout.decode().strip() + if local != remote: print("Repository is not up to date. Performing git pull.") run_command("git pull") return True - + print("Repository is already up to date.") return False - + +{% raw %} def get_image_digests(directory): """ Retrieves the image digests for all images in the specified Docker Compose project. @@ -54,6 +75,7 @@ def get_image_digests(directory): return {} else: raise # Other errors are still raised +{% endraw %} def is_any_service_up(): """ @@ -98,6 +120,20 @@ def update_docker(directory): else: print("Docker images are up to date. No rebuild necessary.") +def update_discourse(directory): + """ + Updates Discourse by running the rebuild command on the launcher script. + """ + repository_directory = os.path.join(directory, "services", "{{applications.discourse.repository}}") + print(f"Using path {repository_directory} to pull discourse repository.") + os.chdir(repository_directory) + if git_pull(): + print("Start Discourse update procedure.") + update_procedure("docker stop {{applications.discourse.container}}") + update_procedure("./launcher rebuild {{applications.discourse.container}}") + else: + print("Discourse update skipped. No changes in git repository.") + def update_mastodon(): """ Runs the database migration for Mastodon to ensure all required tables are up to date. @@ -130,14 +166,6 @@ def update_nextcloud(): update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ db:add-missing-primary-keys") print("Deacitvate Maintanance Mode") update_procedure("docker-compose exec -T -u www-data application /var/www/html/occ maintenance:mode --off") - -def update_discourse(directory): - """ - Updates Discourse by running the rebuild command on the launcher script. - """ - os.chdir(directory) - print("Start Discourse update procedure.") - update_procedure("./launcher rebuild app") def update_procedure(command): """ @@ -178,16 +206,13 @@ if __name__ == "__main__": print(f"Checking for updates in: {dir_path}") os.chdir(dir_path) + # Pull git repository if it exist + # @deprecated: This function should be removed in the future, as soon as all docker applications use the correct folder path if os.path.isdir(os.path.join(dir_path, ".git")): - git_repository_was_pulled = git_pull() + print("DEPRECATED: Docker .git repositories should be saved under /opt/docker/{instance}/services/{repository_name} ") + git_pull() - # Discourse is an exception and uses own update command instead of docker compose - if os.path.basename(dir_path) == "discourse": - if git_repository_was_pulled: - update_discourse(dir_path) - else: - print("Discourse update skipped. No changes in git repository.") - elif os.path.basename(dir_path) == "matrix": + if os.path.basename(dir_path) == "matrix": # No autoupdate for matrix is possible atm, # due to the reason that the role has to be executed every time. # The update has to be executed in the role @@ -198,9 +223,15 @@ if __name__ == "__main__": update_docker(dir_path) # The following instances need additional update and upgrade procedures - if os.path.basename(dir_path) == "nextcloud": - update_nextcloud() + if os.path.basename(dir_path) == "discourse": + update_discourse(dir_path) elif os.path.basename(dir_path) == "listmonk": upgrade_listmonk() elif os.path.basename(dir_path) == "mastodon": update_mastodon() + elif os.path.basename(dir_path) == "nextcloud": + update_nextcloud() + + # @todo implement dedicated procedure for bluesky + # @todo implement dedicated procedure for openproject + # @todo implement dedicated procedure for taiga