# Rocky Linux Testing Framework - Ansible Guide This guide covers the Ansible-based implementation of the Rocky Linux Testing Framework. ## Table of Contents - [Overview](#overview) - [Prerequisites](#prerequisites) - [Quick Start](#quick-start) - [Ansible Structure](#ansible-structure) - [Playbooks](#playbooks) - [Roles](#roles) - [Configuration](#configuration) - [Usage Examples](#usage-examples) - [Advanced Usage](#advanced-usage) - [Troubleshooting](#troubleshooting) ## Overview The Ansible implementation provides the same functionality as the shell scripts, but with: - Better error handling and idempotency - Structured configuration management - Parallel test execution with better control - Reusable roles for composability ## Prerequisites ```bash # Install required packages sudo dnf install -y ansible qemu-kvm libvirt virt-install guestfs-tools rakudo # Enable libvirtd sudo systemctl enable --now libvirtd sudo usermod -a -G libvirt $(whoami) # Generate SSH keys if not present ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "" # Install Ansible collections (if needed) ansible-galaxy collection install community.libvirt ``` ## Quick Start ### 1. Build Golden Image ```bash cd ansible # Build with defaults (Rocky 9) ansible-playbook playbooks/build-golden-image.yml # Build with custom URL ansible-playbook playbooks/build-golden-image.yml \ -e "qcow2_url=https://download.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base.latest.x86_64.qcow2" ``` ### 2. Run Single Test ```bash ansible-playbook playbooks/run-single-test.yml \ -e "test_name=my-test" \ -e "test_repo_url=https://github.com/your-org/test-repo.git" ``` ### 3. Run Test Suite ```bash # Edit playbooks/run-test-suite.yml to define your test matrix # Then run: ansible-playbook playbooks/run-test-suite.yml ``` ## Ansible Structure ``` ansible/ ├── ansible.cfg # Ansible configuration ├── inventory/ │ ├── hosts.yml # Inventory file │ └── group_vars/ │ └── all.yml # Global variables ├── playbooks/ │ ├── build-golden-image.yml # Build golden image workflow │ ├── run-single-test.yml # Run single test │ └── run-test-suite.yml # Run multiple tests └── roles/ ├── download_image/ # Download and cache QCOW2 ├── golden_image/ # Build golden image ├── bootstrap_sparrowdo/ # Bootstrap Sparrowdo ├── provision_vm/ # Provision test VM ├── run_test/ # Run Sparrowdo test └── cleanup_vm/ # Cleanup VMs ``` ## Playbooks ### build-golden-image.yml Complete workflow to create a golden image ready for testing. **Variables:** - `qcow2_url`: URL of base QCOW2 image - `images_dir`: Directory for images (default: /var/lib/libvirt/images) - `golden_image_path`: Output path for golden image - `force_download`: Force re-download of base image **Example:** ```bash ansible-playbook playbooks/build-golden-image.yml \ -e "qcow2_url=https://..." \ -e "force_download=true" ``` ### run-single-test.yml Run a single Sparrowdo test against the golden image. **Required Variables:** - `test_name`: Name of the test - `test_repo_url`: Git repository URL containing the test **Optional Variables:** - `test_repo_branch`: Branch to use (default: main) - `golden_image_path`: Path to golden image **Example:** ```bash ansible-playbook playbooks/run-single-test.yml \ -e "test_name=webserver-test" \ -e "test_repo_url=https://github.com/org/webserver-test.git" \ -e "test_repo_branch=develop" ``` ### run-test-suite.yml Run multiple tests in parallel from a test matrix. **Variables:** - `test_matrix`: List of tests to run - `max_parallel`: Maximum parallel tests - `test_filter`: Regex to filter tests **Example:** ```yaml # Edit the playbook to define your tests: test_matrix: - name: "ssh-test" url: "https://github.com/org/ssh-test.git" branch: "main" description: "SSH service validation" - name: "network-test" url: "https://github.com/org/network-test.git" branch: "main" description: "Network configuration test" ``` Then run: ```bash ansible-playbook playbooks/run-test-suite.yml # Or filter tests: ansible-playbook playbooks/run-test-suite.yml -e "test_filter=ssh.*" ``` ## Roles ### download_image Downloads and caches QCOW2 images. **Variables:** - `qcow2_url`: URL to download - `images_dir`: Cache directory - `force_download`: Force re-download - `image_path_var`: Variable name to store result **Example:** ```yaml - include_role: name: download_image vars: qcow2_url: "https://..." image_path_var: "my_image_path" ``` ### golden_image Creates a golden image using virt-customize. **Variables:** - `base_image_path`: Source QCOW2 image (required) - `golden_image_path`: Output path - `ssh_public_key_path`: SSH key to inject - `custom_prep_script`: Custom preparation script - `use_default_prep`: Use default prep script **Example:** ```yaml - include_role: name: golden_image vars: base_image_path: "/path/to/base.qcow2" golden_image_path: "/path/to/golden.qcow2" ``` ### bootstrap_sparrowdo Bootstraps Sparrowdo on a golden image. **Variables:** - `golden_image_path`: Golden image to bootstrap - `ssh_private_key_path`: SSH key for connection - `ssh_user`: User to connect as - `vm_boot_timeout`: Boot timeout in seconds - `bootstrap_timeout`: Bootstrap timeout **Example:** ```yaml - include_role: name: bootstrap_sparrowdo vars: golden_image_path: "/path/to/golden.qcow2" ``` ### provision_vm Provisions a VM as a linked clone. **Variables:** - `vm_name`: VM name (required) - `golden_image_path`: Base image - `vm_memory`: Memory in MB - `vm_vcpus`: Number of vCPUs - `max_wait_ip`: Timeout for IP assignment - `vm_ip_var`: Variable name for returned IP **Example:** ```yaml - include_role: name: provision_vm vars: vm_name: "test-vm-1" vm_ip_var: "test_vm_ip" - debug: msg: "VM IP: {{ test_vm_ip }}" ``` ### run_test Runs a complete test: provision -> test -> cleanup. **Variables:** - `test_name`: Test name (required) - `test_repo_url`: Git repository (required) - `test_repo_branch`: Branch to use - `golden_image_path`: Golden image - `cleanup_after_test`: Cleanup VM after test - `save_logs`: Save test logs **Example:** ```yaml - include_role: name: run_test vars: test_name: "my-test" test_repo_url: "https://github.com/org/test.git" ``` ### cleanup_vm Cleans up VMs and disk images. **Variables:** - `vm_name`: Single VM to cleanup - `cleanup_pattern`: Regex pattern for multiple VMs - `cleanup_vm_list`: List of VMs to cleanup - `force_destroy`: Force destroy running VMs - `remove_disk`: Remove disk images **Example:** ```yaml # Cleanup single VM - include_role: name: cleanup_vm vars: vm_name: "test-vm-1" # Cleanup by pattern - include_role: name: cleanup_vm vars: cleanup_pattern: "test-.*" # Cleanup list - include_role: name: cleanup_vm vars: cleanup_vm_list: - "vm1" - "vm2" ``` ## Configuration ### Inventory Variables Edit `ansible/inventory/group_vars/all.yml`: ```yaml # VM defaults vm_memory: 4096 # Increase for heavy tests vm_vcpus: 4 # Parallel execution max_parallel: 5 # Run 5 tests concurrently # Sparrowdo options sparrowdo_timeout: 1200 # Increase timeout sparrowdo_verbose: false # Less output ``` ### Per-Test Configuration Override variables when running playbooks: ```bash ansible-playbook playbooks/run-single-test.yml \ -e "test_name=my-test" \ -e "test_repo_url=https://..." \ -e "vm_memory=4096" \ -e "vm_vcpus=4" \ -e "sparrowdo_timeout=1800" ``` ## Usage Examples ### Example 1: Build Golden Image for Rocky 8 ```bash ansible-playbook playbooks/build-golden-image.yml \ -e "qcow2_url=https://download.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base.latest.x86_64.qcow2" \ -e "golden_image_path=/var/lib/libvirt/images/golden-rocky8.qcow2" ``` ### Example 2: Run Test with Custom Resources ```bash ansible-playbook playbooks/run-single-test.yml \ -e "test_name=heavy-test" \ -e "test_repo_url=https://github.com/org/test.git" \ -e "vm_memory=8192" \ -e "vm_vcpus=8" ``` ### Example 3: Custom Test Suite Create `my-test-suite.yml`: ```yaml --- - name: My Custom Test Suite hosts: localhost connection: local gather_facts: true vars: golden_image_path: "/var/lib/libvirt/images/golden.qcow2" my_tests: - name: "database-test" url: "https://github.com/org/db-test.git" - name: "web-test" url: "https://github.com/org/web-test.git" tasks: - name: Run each test include_role: name: run_test vars: test_name: "{{ item.name }}" test_repo_url: "{{ item.url }}" loop: "{{ my_tests }}" ``` Run it: ```bash ansible-playbook my-test-suite.yml ``` ### Example 4: Custom Golden Image Preparation Create custom prep script `custom-prep.sh`: ```bash #!/bin/bash dnf install -y postgresql nginx redis systemctl enable postgresql nginx redis ``` Then: ```bash ansible-playbook playbooks/build-golden-image.yml \ -e "custom_prep_script=/path/to/custom-prep.sh" ``` ## Advanced Usage ### Using Tags Add tags to control execution: ```bash # Only download image ansible-playbook playbooks/build-golden-image.yml --tags download # Skip bootstrap ansible-playbook playbooks/build-golden-image.yml --skip-tags bootstrap ``` ### Ansible Vault for Secrets Store sensitive data in vault: ```bash ansible-vault create ansible/inventory/group_vars/secrets.yml ``` Add passwords: ```yaml root_password: "my-secure-password" rocky_user_password: "another-secure-password" ``` Use it: ```bash ansible-playbook playbooks/build-golden-image.yml --ask-vault-pass ``` ### Cleanup Orphaned VMs ```bash ansible-playbook -m include_role -a name=cleanup_vm \ -e "cleanup_pattern=test-.*" \ localhost, ``` ## Troubleshooting ### Check Ansible Syntax ```bash ansible-playbook playbooks/build-golden-image.yml --syntax-check ``` ### Dry Run (Check Mode) ```bash ansible-playbook playbooks/build-golden-image.yml --check ``` ### Verbose Output ```bash ansible-playbook playbooks/run-single-test.yml -vvv \ -e "test_name=my-test" \ -e "test_repo_url=https://..." ``` ### List Tasks ```bash ansible-playbook playbooks/build-golden-image.yml --list-tasks ``` ### Debugging Failed Tests ```bash # Keep VM after failure ansible-playbook playbooks/run-single-test.yml \ -e "test_name=my-test" \ -e "test_repo_url=https://..." \ -e "cleanup_after_test=false" # Then SSH to investigate ssh -i ~/.ssh/id_rsa rocky@ ``` ### Common Issues **Issue: "Golden image not found"** ```bash # Build golden image first ansible-playbook playbooks/build-golden-image.yml ``` **Issue: "VM failed to get IP"** ```bash # Check libvirt network sudo virsh net-list --all sudo virsh net-start default # Increase timeout ansible-playbook ... -e "max_wait_ip=60" ``` **Issue: "Bootstrap timeout"** ```bash # Increase timeout ansible-playbook playbooks/build-golden-image.yml \ -e "bootstrap_timeout=1800" ``` **Issue: "Parallel tests failing"** ```bash # Reduce parallelism ansible-playbook playbooks/run-test-suite.yml \ -e "max_parallel=1" ``` ## Performance Tips 1. **Cache base images**: First download is slow, subsequent runs are fast 2. **Reuse golden images**: Build once, test many times 3. **Tune parallel execution**: Balance between speed and resource usage 4. **Use local mirrors**: Speed up package installation in prep scripts 5. **Disable verbose logging**: For faster execution in production ## Migration from Shell Scripts | Shell Script | Ansible Equivalent | |--------------|-------------------| | `download-image.sh` | Role: `download_image` | | `setup_base.sh` | Role: `golden_image` | | `bootstrap_golden.sh` | Role: `bootstrap_sparrowdo` | | `provision_vm.sh` | Role: `provision_vm` | | `run-test.sh` | Role: `run_test` | | `cleanup_vm.sh` | Role: `cleanup_vm` | | `cleanup-all.sh` | Role: `cleanup_vm` with pattern | | Manual workflow | Playbook: `build-golden-image.yml` | | Test execution | Playbooks: `run-single-test.yml`, `run-test-suite.yml` | ## Contributing When adding new functionality: 1. Create a new role in `ansible/roles/` 2. Add defaults in `defaults/main.yml` 3. Document variables in role README 4. Create example playbook in `playbooks/` 5. Update this documentation ## License [Your License Here] ## Authors Rocky Linux Testing Team