diff --git a/ansible/roles/server/tasks/prefect.yml b/ansible/roles/server/tasks/prefect.yml index 47294de..a165a2d 100644 --- a/ansible/roles/server/tasks/prefect.yml +++ b/ansible/roles/server/tasks/prefect.yml @@ -133,6 +133,42 @@ retries: 12 delay: 5 +- name: Check if worker image exists locally + community.docker.docker_image_info: + name: "{{ prefect_worker_image }}" + register: _prefect_worker_image_info + +- name: Bootstrap worker image on first run (sync source + build) + when: _prefect_worker_image_info.images | length == 0 + block: + - name: Sync Prefect source to host for initial image build + ansible.posix.synchronize: + src: "{{ playbook_dir }}/../../prefect/" + dest: "{{ prefect_flow_code_host_path }}/" + delete: true + rsync_opts: + - "--exclude=__pycache__" + - "--exclude=.git" + - "--checksum" + - "--omit-dir-times" + + - name: Fix ownership of synced Prefect tree + ansible.builtin.file: + path: /opt/iac/prefect + state: directory + recurse: true + owner: root + group: root + + - name: Build worker image + community.docker.docker_image: + name: "{{ prefect_worker_image }}" + source: build + force_source: true + build: + path: "{{ prefect_flow_code_host_path }}" + dockerfile: Dockerfile.worker + - name: Ensure Prefect worker container is running community.docker.docker_container: name: prefect-worker diff --git a/ansible/roles/server/tasks/traefik.yml b/ansible/roles/server/tasks/traefik.yml index 1818e69..933fa34 100644 --- a/ansible/roles/server/tasks/traefik.yml +++ b/ansible/roles/server/tasks/traefik.yml @@ -13,11 +13,10 @@ app_environment: "{{ 'dev' if '-dev' in inventory_hostname else 'prod' }}" base_domain: "{{ infrastructure_secrets.base_domain }}" -- name: Set Traefik redirect target and app domains for TLS pre-warm +- name: Set Traefik redirect target and app domains ansible.builtin.set_fact: traefik_redirect_target: "{{ app_environment }}.{{ base_domain }}" - # From iac.yml app_domains when set, else single redirect target - traefik_app_domains: "{{ infrastructure_secrets.app_domains | default([traefik_redirect_target]) }}" + traefik_app_domains: "{{ [app_environment + '.' + base_domain] }}" - name: Create Traefik directories ansible.builtin.file: @@ -38,11 +37,18 @@ mode: '0644' notify: Restart Traefik -- name: Deploy Traefik dynamic redirects +- name: Deploy Traefik dynamic redirects (www/apex → prod only) ansible.builtin.template: src: traefik-dynamic-redirects.yml.j2 dest: /etc/traefik/dynamic/redirects.yml mode: '0644' + when: app_environment == 'prod' + +- name: Remove redirect config on dev (www/apex handled by prod) + ansible.builtin.file: + path: /etc/traefik/dynamic/redirects.yml + state: absent + when: app_environment != 'prod' - name: Deploy Traefik HTTP→HTTPS redirect (low priority so ACME works on :80) ansible.builtin.template: diff --git a/prefect/backup/restore_from_backup.py b/prefect/backup/restore_from_backup.py index d33bd2a..4640d7b 100644 --- a/prefect/backup/restore_from_backup.py +++ b/prefect/backup/restore_from_backup.py @@ -91,11 +91,21 @@ def main() -> None: print(f"Dump not found: {dump}") continue print(f"Restoring DB: {service}") - with open(dump, "rb") as f: + container_dump = "/tmp/restore.dump" + subprocess.run( + compose + ["cp", str(dump), f"{service}:{container_dump}"], + cwd=deploy_dir, check=True, + ) + try: subprocess.run( compose + ["exec", "-T", service, "pg_restore", "-U", user, "-d", db, - "--clean", "--if-exists", "--no-owner", "--no-acl", "-"], - stdin=f, cwd=deploy_dir, check=True, + "--clean", "--if-exists", "--no-owner", "--no-acl", container_dump], + cwd=deploy_dir, check=True, + ) + finally: + subprocess.run( + compose + ["exec", "-T", service, "rm", "-f", container_dump], + cwd=deploy_dir, check=False, ) if do_vol: for entry in config.get("volumes") or []: diff --git a/tasks/Taskfile.terraform.yml b/tasks/Taskfile.terraform.yml index 2fde271..72407a6 100644 --- a/tasks/Taskfile.terraform.yml +++ b/tasks/Taskfile.terraform.yml @@ -10,6 +10,7 @@ tasks: cmds: - | TFC_ORG=$(SOPS_AGE_KEY_FILE="{{.SOPS_KEY_FILE}}" sops -d ../app/.iac/iac.yml | yq -r '.terraform_cloud_organization') + export TF_WORKSPACE='{{.WORKSPACE | default "dev"}}' if ! output=$(terraform init -backend-config="organization=${TFC_ORG}" 2>&1); then echo "$output" exit 1 @@ -24,6 +25,7 @@ tasks: deps: [":_check:sops-key", ":_check:workspace"] cmds: - task: init + vars: { WORKSPACE: "{{.WORKSPACE}}" } - | echo "📋 Planning Terraform changes for workspace: platform-{{.WORKSPACE}}..." terraform workspace select "{{.WORKSPACE}}" @@ -45,6 +47,7 @@ tasks: deps: [":_check:sops-key", ":_check:workspace"] cmds: - task: init + vars: { WORKSPACE: "{{.WORKSPACE}}" } - | echo "✨ Applying Terraform changes to workspace: platform-{{.WORKSPACE}}" terraform workspace select "{{.WORKSPACE}}" @@ -71,6 +74,7 @@ tasks: deps: [":_check:sops-key", ":_check:workspace"] cmds: - task: init + vars: { WORKSPACE: "{{.WORKSPACE}}" } - | echo "⚠️ WARNING: This will DESTROY all resources in workspace: platform-{{.WORKSPACE}}" echo "Terraform will ask for confirmation..." @@ -96,6 +100,7 @@ tasks: deps: [":_check:workspace"] cmds: - task: init + vars: { WORKSPACE: "{{.WORKSPACE}}" } - | terraform workspace select "{{.WORKSPACE}}" echo "📤 Getting Terraform outputs for workspace: platform-{{.WORKSPACE}}..."