diff --git a/custom_scripts/linode_inventory.py b/custom_scripts/linode_inventory.py new file mode 100755 index 0000000..283ffc0 --- /dev/null +++ b/custom_scripts/linode_inventory.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 + +import os +import sys +import json +import requests + +API_URL = "https://api.linode.com/v4/linode/instances" +TOKEN = os.getenv("LINODE_TOKEN") + +if not TOKEN: + print("ERROR: LINODE_TOKEN environment variable not set", file=sys.stderr) + sys.exit(1) + +headers = { + "Authorization": f"Bearer {TOKEN}", + "Content-Type": "application/json" +} + +def get_linode_instances(): + instances = [] + page = 1 + while True: + r = requests.get(API_URL, headers=headers, params={"page": page}) + if r.status_code != 200: + print(f"ERROR: Failed to fetch Linodes (status code {r.status_code})", file=sys.stderr) + sys.exit(1) + data = r.json() + instances.extend(data["data"]) + if not data["pages"] or page >= data["pages"]: + break + page += 1 + return instances + +def build_inventory(): + instances = get_linode_instances() + + inventory = { + "_meta": { + "hostvars": {} + } + } + + for linode in instances: + label = linode["label"] + ipv4 = linode["ipv4"][0] if linode["ipv4"] else None + region = linode["region"] + tags = linode.get("tags", []) + + if not ipv4: + continue + + inventory["_meta"]["hostvars"][label] = { + "ansible_host": ipv4, + "linode_id": linode["id"], + "region": region, + "tags": tags, + "type": linode["type"] + } + + # Group by region + region_group = f"region_{region}" + inventory.setdefault(region_group, {"hosts": []})["hosts"].append(label) + + # Group by tag + for tag in tags: + tag_group = f"tag_{tag}" + inventory.setdefault(tag_group, {"hosts": []})["hosts"].append(label) + + return inventory + +def main(): + if len(sys.argv) == 2 and sys.argv[1] == "--list": + print(json.dumps(build_inventory(), indent=2)) + elif len(sys.argv) == 2 and sys.argv[1] == "--host": + print(json.dumps({})) # Not used + else: + print("Usage: linode_inventory.py --list", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/playbooks/inventory/linode.yaml b/playbooks/inventory/linode.yaml new file mode 100644 index 0000000..07dfc28 --- /dev/null +++ b/playbooks/inventory/linode.yaml @@ -0,0 +1,9 @@ +--- +- name: Generate Linode inventory file + hosts: localhost + gather_facts: false + roles: + - role: inventory/linode + vars: + linode_token: "{{ lookup('env', 'LINODE_TOKEN') }}" + diff --git a/roles/inventory/linode/tasks/main.yaml b/roles/inventory/linode/tasks/main.yaml new file mode 100644 index 0000000..11a01f4 --- /dev/null +++ b/roles/inventory/linode/tasks/main.yaml @@ -0,0 +1,19 @@ +--- +- name: Fetch Linode instances + linode.cloud.linode_instance_info: + api_token: "{{ linode_token }}" + register: linodes + +- name: Build inventory lines + set_fact: + linode_inventory: | + {% for linode in linodes.data %} + {{ linode.label }} ansible_host={{ linode.ipv4[0] }} {% for tag in linode.tags %}group_{{ tag }}=true {% endfor %} + {% endfor %} + +- name: Write dynamic inventory to file + copy: + dest: /tmp/linode_inventory.ini + content: | + [all] + {{ linode_inventory }}