mirror of
https://github.com/fscotto/infra.git
synced 2026-10-05 22:39:49 +00:00
Remove completed Atlas Gitea migration tooling
This commit is contained in:
@@ -47,8 +47,8 @@
|
||||
- atlas_gitea_dataset_owner.stat.uid | int == atlas_admin_uid | int
|
||||
- atlas_gitea_dataset_owner.stat.gid | int == atlas_admin_gid | int
|
||||
fail_msg: >-
|
||||
Run the explicit Gitea owner migration before enabling the admin
|
||||
Quadlet; never chown an active legacy service in a normal run.
|
||||
The production dataset must already belong to admin before enabling
|
||||
the Quadlet; normal provisioning must not chown an active legacy service.
|
||||
when: atlas_gitea_production_enabled | bool
|
||||
|
||||
- name: Remove the retired account's parent-dataset traverse ACL
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
---
|
||||
# Run only in an approved outage with -e atlas_gitea_owner_migration=true.
|
||||
- name: Move live Gitea from the legacy host account to admin
|
||||
tags: [atlas, gitea_owner_migration]
|
||||
when: atlas_gitea_owner_migration | bool
|
||||
block:
|
||||
- name: Refuse a check-mode owner migration
|
||||
ansible.builtin.assert:
|
||||
that: not ansible_check_mode
|
||||
fail_msg: The owner migration requires an explicit live outage.
|
||||
|
||||
- name: Inspect the Gitea dataset owner
|
||||
ansible.builtin.stat:
|
||||
path: "{{ atlas_gitea_mountpoint }}"
|
||||
register: atlas_gitea_migration_owner
|
||||
|
||||
- name: Require either the legacy owner or an already migrated dataset
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_gitea_migration_owner.stat.isdir | default(false)
|
||||
- atlas_gitea_migration_owner.stat.uid | int in [atlas_gitea_legacy_uid | int, atlas_admin_uid | int]
|
||||
fail_msg: Refusing to modify a Gitea dataset with an unexpected owner.
|
||||
|
||||
- name: Migrate only a legacy-owned Gitea dataset
|
||||
when: atlas_gitea_migration_owner.stat.uid | int == atlas_gitea_legacy_uid | int
|
||||
block:
|
||||
- name: Require the final cutover marker and configuration
|
||||
ansible.builtin.stat:
|
||||
path: "{{ item }}"
|
||||
loop:
|
||||
- "{{ atlas_gitea_mountpoint }}/.final-sha256"
|
||||
- "{{ atlas_gitea_mountpoint }}/config/app.ini"
|
||||
register: atlas_gitea_migration_files
|
||||
|
||||
- name: Refuse migration without both final data and configuration
|
||||
ansible.builtin.assert:
|
||||
that: atlas_gitea_migration_files.results | map(attribute='stat.isreg') | min
|
||||
|
||||
- name: Check that admin has no existing Gitea Quadlet
|
||||
ansible.builtin.stat:
|
||||
path: "{{ atlas_gitea_quadlet_dir }}/atlas-gitea.container"
|
||||
register: atlas_gitea_admin_quadlet
|
||||
|
||||
- name: Refuse to overwrite an existing admin Quadlet
|
||||
ansible.builtin.assert:
|
||||
that: not atlas_gitea_admin_quadlet.stat.exists
|
||||
|
||||
- name: Check pool health before the outage
|
||||
ansible.builtin.command:
|
||||
argv: [zpool, status, -x, "{{ atlas_zfs_pool }}"]
|
||||
register: atlas_gitea_pool_before
|
||||
changed_when: false
|
||||
failed_when: "'is healthy' not in atlas_gitea_pool_before.stdout"
|
||||
|
||||
- name: Ensure the admin Gitea image is available before stopping the source
|
||||
ansible.builtin.import_tasks: gitea_image.yml
|
||||
|
||||
- name: Stop, snapshot and test the admin-owned staging service
|
||||
block:
|
||||
- name: Stop and disable the legacy Gitea user service
|
||||
become_user: "{{ atlas_gitea_legacy_username }}"
|
||||
ansible.builtin.systemd:
|
||||
name: atlas-gitea.service
|
||||
scope: user
|
||||
state: stopped
|
||||
enabled: false
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_gitea_legacy_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_gitea_legacy_uid }}/bus"
|
||||
|
||||
- name: Record the migration snapshot name
|
||||
ansible.builtin.set_fact:
|
||||
atlas_gitea_migration_snapshot: >-
|
||||
{{ atlas_gitea_dataset }}@gitea-owner-migration-{{ ansible_facts.date_time.iso8601_basic_short }}
|
||||
|
||||
- name: Snapshot the stopped Gitea dataset for manual recovery
|
||||
ansible.builtin.command:
|
||||
argv: [zfs, snapshot, "{{ atlas_gitea_migration_snapshot }}"]
|
||||
|
||||
- name: Transfer only the Gitea dataset to admin
|
||||
ansible.builtin.file:
|
||||
path: "{{ atlas_gitea_mountpoint }}"
|
||||
state: directory
|
||||
owner: "{{ atlas_admin_username }}"
|
||||
group: "{{ atlas_admin_group }}"
|
||||
recurse: true
|
||||
|
||||
- name: Set the actual internal Unix process user
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ atlas_gitea_mountpoint }}/config/app.ini"
|
||||
regexp: '^RUN_USER\s*='
|
||||
line: RUN_USER = gitea
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
diff: false
|
||||
|
||||
- name: Preserve public git clone URLs independently of the Unix user
|
||||
community.general.ini_file:
|
||||
path: "{{ atlas_gitea_mountpoint }}/config/app.ini"
|
||||
section: server
|
||||
option: "{{ item }}"
|
||||
value: git
|
||||
mode: "0600"
|
||||
no_extra_spaces: false
|
||||
loop: [BUILTIN_SSH_SERVER_USER, SSH_USER]
|
||||
no_log: true
|
||||
diff: false
|
||||
|
||||
- name: Render admin's loopback-only staging Quadlet
|
||||
ansible.builtin.template:
|
||||
src: atlas-gitea.container.j2
|
||||
dest: "{{ atlas_gitea_quadlet_dir }}/atlas-gitea.container"
|
||||
owner: "{{ atlas_admin_username }}"
|
||||
group: "{{ atlas_admin_group }}"
|
||||
mode: "0644"
|
||||
vars:
|
||||
atlas_gitea_production_enabled: false
|
||||
|
||||
- name: Reload the admin user manager for staging
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.systemd:
|
||||
scope: user
|
||||
daemon_reload: true
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
|
||||
|
||||
- name: Start admin's loopback-only staging service
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.systemd:
|
||||
name: atlas-gitea.service
|
||||
scope: user
|
||||
state: started
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
|
||||
|
||||
- name: Verify staging HTTP before promotion
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1:{{ atlas_gitea_staging_http_port }}/"
|
||||
status_code: 200
|
||||
register: atlas_gitea_staging_http
|
||||
retries: 30
|
||||
delay: 2
|
||||
until: atlas_gitea_staging_http is succeeded
|
||||
|
||||
- name: Verify the container really runs as internal gitea
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.command:
|
||||
argv: [podman, exec, atlas-gitea, id, -un]
|
||||
environment:
|
||||
HOME: "{{ atlas_admin_home }}"
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
register: atlas_gitea_internal_user
|
||||
changed_when: false
|
||||
failed_when: atlas_gitea_internal_user.stdout != 'gitea'
|
||||
|
||||
- name: Verify the migrated SQLite database
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- sqlite3
|
||||
- "{{ atlas_gitea_mountpoint }}/data/gitea/gitea.db"
|
||||
- PRAGMA quick_check;
|
||||
register: atlas_gitea_migration_sqlite
|
||||
changed_when: false
|
||||
failed_when: atlas_gitea_migration_sqlite.stdout != 'ok'
|
||||
|
||||
rescue:
|
||||
- name: Stop admin's failed staging service
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.systemd:
|
||||
name: atlas-gitea.service
|
||||
scope: user
|
||||
state: stopped
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
|
||||
failed_when: false
|
||||
|
||||
- name: Restore the original Gitea configuration from the safety snapshot
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- cp
|
||||
- -a
|
||||
- "{{ atlas_gitea_mountpoint }}/.zfs/snapshot/{{ atlas_gitea_migration_snapshot.split('@')[1] }}/config/app.ini"
|
||||
- "{{ atlas_gitea_mountpoint }}/config/app.ini"
|
||||
when: atlas_gitea_migration_snapshot is defined
|
||||
|
||||
- name: Return the Gitea dataset to the legacy account
|
||||
ansible.builtin.file:
|
||||
path: "{{ atlas_gitea_mountpoint }}"
|
||||
state: directory
|
||||
owner: "{{ atlas_gitea_legacy_username }}"
|
||||
group: "{{ atlas_gitea_legacy_username }}"
|
||||
recurse: true
|
||||
|
||||
- name: Restart the legacy Gitea service
|
||||
become_user: "{{ atlas_gitea_legacy_username }}"
|
||||
ansible.builtin.systemd:
|
||||
name: atlas-gitea.service
|
||||
scope: user
|
||||
state: started
|
||||
enabled: true
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_gitea_legacy_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_gitea_legacy_uid }}/bus"
|
||||
|
||||
- name: Report the failed migration and preserved snapshot
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
Admin staging failed; legacy Gitea was restarted. Inspect
|
||||
{{ atlas_gitea_migration_snapshot | default('the host journal') }}.
|
||||
|
||||
- name: Stop admin's validated staging service
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.systemd:
|
||||
name: atlas-gitea.service
|
||||
scope: user
|
||||
state: stopped
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
|
||||
|
||||
- name: Render admin's production Gitea Quadlet
|
||||
ansible.builtin.template:
|
||||
src: atlas-gitea.container.j2
|
||||
dest: "{{ atlas_gitea_quadlet_dir }}/atlas-gitea.container"
|
||||
owner: "{{ atlas_admin_username }}"
|
||||
group: "{{ atlas_admin_group }}"
|
||||
mode: "0644"
|
||||
vars:
|
||||
atlas_gitea_production_enabled: true
|
||||
|
||||
- name: Reload admin's production user manager
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.systemd:
|
||||
scope: user
|
||||
daemon_reload: true
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
|
||||
|
||||
- name: Enable and start admin's production Gitea
|
||||
become_user: "{{ atlas_admin_username }}"
|
||||
ansible.builtin.systemd:
|
||||
name: atlas-gitea.service
|
||||
scope: user
|
||||
state: started
|
||||
enabled: true
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
|
||||
|
||||
- name: Verify production HTTP before retiring the old Quadlet
|
||||
ansible.builtin.uri:
|
||||
url: "http://{{ atlas_gitea_bind_address }}:{{ atlas_gitea_http_port }}/"
|
||||
status_code: 200
|
||||
register: atlas_gitea_production_http
|
||||
retries: 30
|
||||
delay: 2
|
||||
until: atlas_gitea_production_http is succeeded
|
||||
|
||||
- name: Remove only the disabled legacy Quadlet
|
||||
ansible.builtin.file:
|
||||
path: "{{ atlas_gitea_legacy_home }}/.config/containers/systemd/atlas-gitea.container"
|
||||
state: absent
|
||||
|
||||
- name: Reload the legacy user manager after Quadlet removal
|
||||
become_user: "{{ atlas_gitea_legacy_username }}"
|
||||
ansible.builtin.systemd:
|
||||
scope: user
|
||||
daemon_reload: true
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_gitea_legacy_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_gitea_legacy_uid }}/bus"
|
||||
@@ -1,107 +0,0 @@
|
||||
---
|
||||
- name: Restore Gitea from a verified Prometheus backup only on explicit request
|
||||
tags: [atlas, gitea_restore, gitea_final_restore]
|
||||
when: atlas_gitea_restore_test | bool or atlas_gitea_final_restore | bool
|
||||
block:
|
||||
- name: Require the prepared rootless Gitea target
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_manage_gitea | bool
|
||||
- not (atlas_gitea_restore_test | bool and atlas_gitea_final_restore | bool)
|
||||
- atlas_gitea_staging_bind_address == '127.0.0.1'
|
||||
- atlas_gitea_mountpoint == atlas_app_data_mountpoint ~ '/gitea'
|
||||
fail_msg: Prepare the isolated, loopback-only rootless Gitea target first.
|
||||
|
||||
- name: Confirm the rootless Gitea service is inactive
|
||||
become_user: "{{ atlas_gitea_username }}"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- systemctl
|
||||
- --user
|
||||
- is-active
|
||||
- atlas-gitea.service
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_gitea_uid }}"
|
||||
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_gitea_uid }}/bus"
|
||||
register: atlas_gitea_restore_service_state
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Refuse to overwrite an active rootless Gitea service
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_gitea_restore_service_state.stdout == 'inactive'
|
||||
fail_msg: The rootless Gitea user service must be known and inactive before restoring data.
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Check for a manually running rootless Gitea container
|
||||
become_user: "{{ atlas_gitea_username }}"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- podman
|
||||
- ps
|
||||
- --quiet
|
||||
- --filter
|
||||
- name=atlas-gitea
|
||||
args:
|
||||
chdir: "{{ atlas_gitea_home }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ atlas_gitea_uid }}"
|
||||
register: atlas_gitea_restore_container_state
|
||||
changed_when: false
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Refuse to overwrite a running rootless Gitea container
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- atlas_gitea_restore_container_state.stdout | length == 0
|
||||
fail_msg: Stop every rootless Atlas Gitea container before restoring data.
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Install the selective rootless Gitea restore helper
|
||||
ansible.builtin.copy:
|
||||
src: atlas-gitea-restore-test.py
|
||||
dest: "{{ atlas_gitea_restore_helper }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Restore only Gitea data into the isolated target
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "{{ atlas_gitea_restore_helper }}"
|
||||
- --backup
|
||||
- "{{ atlas_backup_prometheus_mountpoint }}/latest"
|
||||
- --target
|
||||
- "{{ atlas_gitea_mountpoint }}"
|
||||
- --uid
|
||||
- "{{ atlas_gitea_uid | string }}"
|
||||
- --gid
|
||||
- "{{ atlas_gitea_gid | string }}"
|
||||
register: atlas_gitea_restore_result
|
||||
changed_when: atlas_gitea_restore_result.stdout == 'restored'
|
||||
no_log: true
|
||||
when:
|
||||
- atlas_gitea_restore_test | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Replace the marked rehearsal with the final consistent Gitea export
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "{{ atlas_gitea_restore_helper }}"
|
||||
- --backup
|
||||
- "{{ atlas_backup_prometheus_mountpoint }}/latest"
|
||||
- --target
|
||||
- "{{ atlas_gitea_mountpoint }}"
|
||||
- --uid
|
||||
- "{{ atlas_gitea_uid | string }}"
|
||||
- --gid
|
||||
- "{{ atlas_gitea_gid | string }}"
|
||||
- --replace-rehearsal
|
||||
register: atlas_gitea_final_restore_result
|
||||
changed_when: atlas_gitea_final_restore_result.stdout == 'restored'
|
||||
no_log: true
|
||||
when:
|
||||
- atlas_gitea_final_restore | bool
|
||||
- not ansible_check_mode
|
||||
@@ -14,9 +14,6 @@
|
||||
- name: Import Atlas storage tasks
|
||||
ansible.builtin.import_tasks: storage.yml
|
||||
|
||||
- name: Import explicit Atlas Gitea owner migration
|
||||
ansible.builtin.import_tasks: gitea_owner_migration.yml
|
||||
|
||||
- name: Import staged Atlas rootless Gitea tasks
|
||||
ansible.builtin.import_tasks: gitea.yml
|
||||
|
||||
@@ -26,9 +23,6 @@
|
||||
- name: Import Atlas iCloudPD storage and boot-started Quadlet tasks
|
||||
ansible.builtin.import_tasks: icloudpd.yml
|
||||
|
||||
- name: Import explicit Atlas Gitea restore rehearsal tasks
|
||||
ansible.builtin.import_tasks: gitea_restore.yml
|
||||
|
||||
- name: Import Atlas ZFS maintenance tasks
|
||||
ansible.builtin.import_tasks: zfs_maintenance.yml
|
||||
|
||||
|
||||
Reference in New Issue
Block a user