Let's just rewrite to not use requests...

This commit is contained in:
2025-08-07 13:11:39 -05:00
parent dc266538a4
commit bc69e83674

View File

@@ -1,9 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import json import json
import requests
import sys import sys
import os import os
import urllib.request
import urllib.error
from argparse import ArgumentParser from argparse import ArgumentParser
class LinodeInventory: class LinodeInventory:
@@ -13,17 +14,43 @@ class LinodeInventory:
raise ValueError("LINODE_API_TOKEN environment variable is required") raise ValueError("LINODE_API_TOKEN environment variable is required")
self.base_url = "https://api.linode.com/v4" self.base_url = "https://api.linode.com/v4"
self.headers = {
"Authorization": f"Bearer {self.api_token}", def make_request(self, endpoint):
"Content-Type": "application/json" """Make HTTP request to Linode API using urllib"""
} url = f"{self.base_url}{endpoint}"
req = urllib.request.Request(url)
req.add_header('Authorization', f'Bearer {self.api_token}')
req.add_header('Content-Type', 'application/json')
try:
with urllib.request.urlopen(req, timeout=30) as response:
data = response.read().decode('utf-8')
return json.loads(data)
except urllib.error.HTTPError as e:
error_msg = e.read().decode('utf-8') if e.fp else str(e)
raise Exception(f"HTTP Error {e.code}: {error_msg}")
except urllib.error.URLError as e:
raise Exception(f"URL Error: {e}")
except Exception as e:
raise Exception(f"Request failed: {e}")
def get_instances(self): def get_instances(self):
"""Fetch all Linode instances""" """Fetch all Linode instances"""
url = f"{self.base_url}/linode/instances" try:
response = requests.get(url, headers=self.headers) # Get first page to check pagination
response.raise_for_status() response = self.make_request("/linode/instances?page=1")
return response.json()['data'] instances = response['data']
# Handle pagination if there are more pages
if response.get('pages', 1) > 1:
for page in range(2, response['pages'] + 1):
page_response = self.make_request(f"/linode/instances?page={page}")
instances.extend(page_response['data'])
return instances
except Exception as e:
print(f"Error fetching instances: {e}", file=sys.stderr)
return []
def generate_inventory(self): def generate_inventory(self):
"""Generate Ansible inventory from Linode instances""" """Generate Ansible inventory from Linode instances"""
@@ -47,14 +74,22 @@ class LinodeInventory:
try: try:
instances = self.get_instances() instances = self.get_instances()
if not instances:
print("No instances found or API request failed", file=sys.stderr)
return inventory
for instance in instances: for instance in instances:
# Use Linode label as hostname (this is what you wanted!) # Use Linode label as hostname
hostname = instance['label'] hostname = instance['label']
# Get primary IPv4 address # Get primary IPv4 address
ipv4_addresses = instance.get('ipv4', []) ipv4_addresses = instance.get('ipv4', [])
primary_ip = ipv4_addresses[0] if ipv4_addresses else None primary_ip = ipv4_addresses[0] if ipv4_addresses else None
if not primary_ip:
print(f"Warning: No IPv4 address found for {hostname}", file=sys.stderr)
continue
# Add to ungrouped hosts # Add to ungrouped hosts
inventory['ungrouped']['hosts'].append(hostname) inventory['ungrouped']['hosts'].append(hostname)
@@ -72,7 +107,10 @@ class LinodeInventory:
'linode_specs': instance.get('specs', {}), 'linode_specs': instance.get('specs', {}),
'linode_hypervisor': instance.get('hypervisor'), 'linode_hypervisor': instance.get('hypervisor'),
'linode_created': instance.get('created'), 'linode_created': instance.get('created'),
'linode_updated': instance.get('updated') 'linode_updated': instance.get('updated'),
'linode_group': instance.get('group', ''),
'linode_image': instance.get('image', {}).get('id', '') if instance.get('image') else '',
'linode_backups': instance.get('backups', {}).get('enabled', False)
} }
# Group by region # Group by region
@@ -95,14 +133,21 @@ class LinodeInventory:
# Group by tags # Group by tags
for tag in instance.get('tags', []): for tag in instance.get('tags', []):
tag_group = f"tag_{tag.replace('-', '_').replace(' ', '_')}" tag_group = f"tag_{tag.replace('-', '_').replace(' ', '_').replace('.', '_')}"
if tag_group not in inventory: if tag_group not in inventory:
inventory[tag_group] = {'hosts': []} inventory[tag_group] = {'hosts': []}
inventory[tag_group]['hosts'].append(hostname) inventory[tag_group]['hosts'].append(hostname)
except requests.exceptions.RequestException as e: # Group by Linode group (if set)
print(f"Error fetching Linode instances: {e}", file=sys.stderr) if instance.get('group'):
return {} group_name = f"group_{instance['group'].replace('-', '_').replace(' ', '_')}"
if group_name not in inventory:
inventory[group_name] = {'hosts': []}
inventory[group_name]['hosts'].append(hostname)
except Exception as e:
print(f"Error generating inventory: {e}", file=sys.stderr)
return inventory
# Add all groups to inventory # Add all groups to inventory
inventory.update(regions) inventory.update(regions)
@@ -112,7 +157,9 @@ class LinodeInventory:
# Add group children to 'all' # Add group children to 'all'
all_groups = list(regions.keys()) + list(types.keys()) + list(statuses.keys()) all_groups = list(regions.keys()) + list(types.keys()) + list(statuses.keys())
tag_groups = [k for k in inventory.keys() if k.startswith('tag_')] tag_groups = [k for k in inventory.keys() if k.startswith('tag_')]
group_groups = [k for k in inventory.keys() if k.startswith('group_')]
all_groups.extend(tag_groups) all_groups.extend(tag_groups)
all_groups.extend(group_groups)
if all_groups: if all_groups:
inventory['all']['children'].extend(all_groups) inventory['all']['children'].extend(all_groups)
@@ -135,9 +182,11 @@ def main():
inventory = LinodeInventory() inventory = LinodeInventory()
if args.list: if args.list:
print(json.dumps(inventory.generate_inventory(), indent=2)) result = inventory.generate_inventory()
print(json.dumps(result, indent=2))
elif args.host: elif args.host:
print(json.dumps(inventory.get_host_vars(args.host), indent=2)) result = inventory.get_host_vars(args.host)
print(json.dumps(result, indent=2))
else: else:
parser.print_help() parser.print_help()