Let's just rewrite to not use requests...
This commit is contained in:
@@ -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}",
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
def make_request(self, endpoint):
|
||||||
|
"""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)
|
||||||
|
|
||||||
|
# Group by Linode group (if set)
|
||||||
|
if instance.get('group'):
|
||||||
|
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 requests.exceptions.RequestException as e:
|
except Exception as e:
|
||||||
print(f"Error fetching Linode instances: {e}", file=sys.stderr)
|
print(f"Error generating inventory: {e}", file=sys.stderr)
|
||||||
return {}
|
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()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user