--- - name: Update Linode Dynamic Inventory hosts: localhost gather_facts: true connection: local vars: # Override these variables as needed linode_inventory_output_dir: "/tmp/linode_inventory" inventory_format: "json" # or "ini" awx_integration: true cleanup_temp_files: false # Git integration settings push_to_git: true # AWX API integration (optional - for automatic project sync) awx_api_integration: false # Set to true if you want automatic project refresh # awx_host: "https://your-awx-host" # awx_project_id: "8" # Your project ID in AWX # awx_token: "{{ lookup('env', 'AWX_TOKEN') }}" # Set via credential or env var # Optional filters include_only_running: false specific_regions: [] # e.g., ['us-east', 'us-west'] specific_tags: [] # e.g., ['production', 'web'] pre_tasks: - name: Check for Linode API token (will be injected by AWX credential) ansible.builtin.fail: msg: "Linode API Token credential must be attached to this job template in AWX" when: linode_api_token is undefined or linode_api_token == "" - name: Display configuration ansible.builtin.debug: msg: | Linode Inventory Configuration: Output directory: {{ linode_inventory_output_dir }} Output format: {{ inventory_format }} AWX integration: {{ awx_integration }} Include only running: {{ include_only_running }} roles: - role: roles/inventory/linode vars: linode_api_token: "{{ linode_api_token }}" post_tasks: - name: Display next steps ansible.builtin.debug: msg: | Inventory update complete! ✅ Inventory file created: /runner/project/inventory/linode_hosts.json ✅ Changes committed to Git: {{ 'Yes' if git_commit_result.rc == 0 else 'Failed - check logs' }} ✅ Repository: git@git.ewnix.net:phlux/ewnix-automation.git Next steps: 1. {% if not awx_api_integration %}Manually sync your AWX project to pull the latest inventory{% else %}Project sync triggered automatically{% endif %} 2. Create a new inventory source in AWX: - Source: "Sourced from a Project" - Inventory File: "inventory/linode_hosts.json" - No credential needed (it's a static file) 3. Sync the inventory source to import your Linode hosts Your {{ linode_inventory_data._meta.hostvars | length }} Linode hosts will be available in groups: - tag_k3s (k3s cluster nodes) - tag_control_plane ({{ hostvars[groups['localhost'][0]]['linode_inventory_data']._meta.hostvars | selectattr('is_control_plane', 'equalto', true) | list | length }} control plane nodes) - tag_worker_node ({{ hostvars[groups['localhost'][0]]['linode_inventory_data']._meta.hostvars | selectattr('is_worker_node', 'equalto', true) | list | length }} worker nodes) - region_us_southeast (regional grouping) - type_* (by instance type) # Optional: Run against discovered Linode hosts - name: Debug and use discovered Linode hosts hosts: localhost gather_facts: false tasks: - name: Check if inventory file exists ansible.builtin.stat: path: "{{ linode_inventory_output_dir | default('/tmp/linode_inventory') }}/{{ linode_inventory_output_file | default('linode_inventory.json') }}" register: inventory_file_stat - name: Display inventory file status ansible.builtin.debug: msg: | Inventory file path: {{ linode_inventory_output_dir | default('/tmp/linode_inventory') }}/{{ linode_inventory_output_file | default('linode_inventory.json') }} File exists: {{ inventory_file_stat.stat.exists }} File size: {{ inventory_file_stat.stat.size | default(0) }} bytes - name: Load and display inventory contents ansible.builtin.slurp: src: "{{ linode_inventory_output_dir | default('/tmp/linode_inventory') }}/{{ linode_inventory_output_file | default('linode_inventory.json') }}" register: inventory_content when: inventory_file_stat.stat.exists - name: Parse inventory JSON ansible.builtin.set_fact: dynamic_inventory: "{{ inventory_content.content | b64decode | from_json }}" when: inventory_file_stat.stat.exists - name: Display parsed inventory summary ansible.builtin.debug: msg: | Inventory loaded successfully! Total hostvars: {{ dynamic_inventory._meta.hostvars | length }} Groups: {{ dynamic_inventory.keys() | reject('equalto', '_meta') | list }} Hosts in hostvars: {{ dynamic_inventory._meta.hostvars.keys() | list }} when: dynamic_inventory is defined - name: Add discovered hosts to in-memory inventory ansible.builtin.add_host: name: "{{ item.key }}" groups: discovered_linodes ansible_host: "{{ item.value.ansible_host }}" linode_id: "{{ item.value.linode_id }}" linode_region: "{{ item.value.linode_region }}" linode_type: "{{ item.value.linode_type }}" linode_status: "{{ item.value.linode_status }}" linode_tags: "{{ item.value.linode_tags }}" is_debian: "{{ item.value.is_debian }}" is_ubuntu: "{{ item.value.is_ubuntu }}" is_k3s: "{{ item.value.is_k3s }}" is_control_plane: "{{ item.value.is_control_plane }}" is_worker_node: "{{ item.value.is_worker_node }}" tag_string: "{{ item.value.tag_string }}" loop: "{{ dynamic_inventory._meta.hostvars | dict2items }}" when: - dynamic_inventory is defined - item.value.linode_status == "running" - name: Display added hosts with tag information ansible.builtin.debug: msg: | Added {{ groups['discovered_linodes'] | default([]) | length }} running Linode hosts to inventory Host details: {% for host in groups['discovered_linodes'] | default([]) %} - {{ host }} ({{ hostvars[host]['ansible_host'] }}) Tags: {{ hostvars[host]['linode_tags'] | join(', ') }} K3s: {{ hostvars[host]['is_k3s'] }} Control Plane: {{ hostvars[host]['is_control_plane'] }} Worker: {{ hostvars[host]['is_worker_node'] }} {% endfor %} - name: Test connection to discovered Linode hosts hosts: discovered_linodes gather_facts: false vars: ansible_user: phlux ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ConnectTimeout=10' tasks: - name: Test connectivity ansible.builtin.ping: register: ping_result ignore_errors: true - name: Display connectivity status with tag info ansible.builtin.debug: msg: | {{ inventory_hostname }} ({{ ansible_host }}): {{ 'REACHABLE' if ping_result is succeeded else 'UNREACHABLE' }} Tags: {{ linode_tags | join(', ') }} Role: {{ 'Control Plane' if is_control_plane else 'Worker Node' if is_worker_node else 'Other' }} # Example: Run tasks only on k3s control plane nodes - name: Example - Control Plane specific tasks hosts: discovered_linodes gather_facts: false vars: ansible_user: phlux tasks: - name: Control plane specific task ansible.builtin.debug: msg: "This would run control plane specific commands on {{ inventory_hostname }}" when: is_control_plane | bool # Example: Run tasks only on k3s worker nodes - name: Example - Worker Node specific tasks hosts: discovered_linodes gather_facts: false vars: ansible_user: phlux tasks: - name: Worker node specific task ansible.builtin.debug: msg: "This would run worker node specific commands on {{ inventory_hostname }}" when: is_worker_node | bool # Example: Run tasks on all k3s nodes (control plane + workers) - name: Example - All K3s nodes hosts: discovered_linodes gather_facts: false vars: ansible_user: phlux tasks: - name: K3s cluster task ansible.builtin.debug: msg: "This would run on all k3s nodes: {{ inventory_hostname }}" when: is_k3s | bool