Ansible meets UV

Camilo MATAJIRA Avatar

Introduction

Why hasn’t it been done before?

The UV solution and example

#!/usr/bin/env -S uv tool run --with "ansible==12.0.0" --from ansible-core@2.19.2 ansible-playbook -D -K -v
#
# Usage:
# - Assuming this file is called 'install', and you had already chmod +x install
# ./install
# ./install -CD # For dry-run
---
- hosts: localhost
  tasks:
    - name: Update apt cache
      become: true
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 21600
    - name: Check if running in a Docker container
      ansible.builtin.stat:
        path: /.dockerenv
      register: in_docker
    - name: Install OS dependencies
      become: true
      ansible.builtin.apt:
        name:
          - curl
          - "{{ 'libglib2.0-0t64' if (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('24.04', '>=') or ansible_distribution == 'Debian' and ansible_distribution_version is version('13', '>=')) else 'libglib2.0-0' }}"
        update_cache: false
        state: present
    - block:
        - name: Install python dependencies
          become: false
          shell: |
            uv venv --python 3.12.0 --relocatable
            uv sync --frozen --no-install-package
          args:
            creates: .venv
      rescue:
        - name: Cleanup .venv
          ansible.builtin.file:
            path: .venv
            state: absent
        - ansible.builtin.fail:
            msg: Error while creating the virtual environment
    - name: Ensure MariaDB server is enabled and running
      become: true
      ansible.builtin.service:
        name: mariadb
        state: started
        enabled: true
      when:
        - not in_docker.stat.exists
        - not lookup('ansible.builtin.env', 'GITHUB_ACTIONS') == "true"
    - name: Ensure MariaDB server is enabled and running (docker)
      become: true
      shell: |
        nohup mysqld_safe --user=mysql --datadir=/var/lib/mysql > /var/log/mysqld.log 2>&1 &
      when: in_docker.stat.exists or lookup('ansible.builtin.env', 'GITHUB_ACTIONS') == "true"
    - name: Create my_project root user with privileges
      become: true
      community.mysql.mysql_user:
        name: my_project_root_user
        password: my_project_root_password
        host: localhost
        priv: '*.*:ALL,GRANT'
        state: present
        login_unix_socket: /var/run/mysqld/mysqld.sock
      environment:
        PYTHONPATH: /usr/lib/python3/dist-packages/
    - name: Render /etc/my_conf/project.conf config file
      become: true
      ansible.builtin.copy:
        dest: /etc/my_conf/project.conf
        content: |
          (...)
          [api]
          path = {{ playbook_dir }}/.venv/lib/python3.12/site-packages/modules/
          (...)
    - name: Check if database already initialized
      become: true
      shell: |
        mysql -e "SHOW DATABASES" | grep target_database_to_check
      register: target_database_to_check_is_present
      ignore_errors: true
      changed_when: false
      failed_when: false
    - name: Long and destructive database initialization script
      shell: |
        uv run python3 install_databases.py
      args:
        executable: /bin/bash
      when: target_database_to_check_is_present.rc != 0

What we get for free

Conclusion

Tagged in :

Camilo MATAJIRA Avatar