Files
homelab-optimized/ansible/automation/playbooks/service_inventory.yml
Gitea Mirror Bot 9fa5b7654e
Some checks failed
Documentation / Deploy to GitHub Pages (push) Has been cancelled
Documentation / Build Docusaurus (push) Has been cancelled
Sanitized mirror from private repository - 2026-04-16 07:18:01 UTC
2026-04-16 07:18:01 +00:00

332 lines
12 KiB
YAML

---
- name: Service Inventory and Documentation Generator
hosts: all
gather_facts: yes
vars:
inventory_timestamp: "{{ ansible_date_time.iso8601 }}"
inventory_dir: "/tmp/service_inventory"
documentation_dir: "/tmp/service_docs"
tasks:
- name: Create inventory directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- "{{ inventory_dir }}"
- "{{ documentation_dir }}"
delegate_to: localhost
run_once: true
- name: Check if Docker is available
shell: command -v docker >/dev/null 2>&1
register: docker_available
changed_when: false
ignore_errors: yes
- name: Skip Docker tasks if not available
set_fact:
skip_docker: "{{ docker_available.rc != 0 }}"
- name: Discover running services
shell: |
echo "=== SERVICE DISCOVERY ==="
# System services (systemd)
if command -v systemctl >/dev/null 2>&1; then
echo "SYSTEMD_SERVICES:"
systemctl list-units --type=service --state=active --no-legend | head -20 | while read service rest; do
port_info=""
# Try to extract port information from service files
if systemctl show "$service" --property=ExecStart 2>/dev/null | grep -qE ":[0-9]+"; then
port_info=$(systemctl show "$service" --property=ExecStart 2>/dev/null | grep -oE ":[0-9]+" | head -1)
fi
echo "$service$port_info"
done
echo ""
fi
# Synology services (if available)
if command -v synoservice >/dev/null 2>&1; then
echo "SYNOLOGY_SERVICES:"
synoservice --list 2>/dev/null | grep -E "^\[.*\].*running" | head -20
echo ""
fi
# Network services (listening ports)
echo "NETWORK_SERVICES:"
if command -v netstat >/dev/null 2>&1; then
netstat -tuln 2>/dev/null | grep LISTEN | head -20
elif command -v ss >/dev/null 2>&1; then
ss -tuln 2>/dev/null | grep LISTEN | head -20
fi
echo ""
register: system_services
changed_when: false
- name: Discover Docker services
shell: |
if ! command -v docker >/dev/null 2>&1; then
echo "Docker not available"
exit 0
fi
echo "=== DOCKER SERVICE DISCOVERY ==="
# Get detailed container information
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null | while IFS=$'\t' read name image status ports; do
if [ "$name" != "NAMES" ]; then
echo "CONTAINER: $name"
echo " Image: $image"
echo " Status: $status"
echo " Ports: $ports"
# Try to get more details
labels=$(docker inspect "$name" --format '{{range $key, $value := .Config.Labels}}{{$key}}={{$value}}{{"\n"}}{{end}}' 2>/dev/null | head -5)
if [ -n "$labels" ]; then
echo " Labels:"
echo "$labels" | sed 's/^/ /'
fi
# Check for health status
health=$(docker inspect "$name" --format '{{.State.Health.Status}}' 2>/dev/null)
if [ "$health" != "<no value>" ] && [ -n "$health" ]; then
echo " Health: $health"
fi
echo ""
fi
done
register: docker_services
changed_when: false
when: not skip_docker
- name: Analyze service configurations
shell: |
echo "=== CONFIGURATION ANALYSIS ==="
# Find common configuration directories
config_dirs="/etc /opt /home/*/config /volume1/docker"
echo "Configuration directories found:"
for dir in $config_dirs; do
if [ -d "$dir" ]; then
# Look for common config files
find "$dir" -maxdepth 3 -name "*.conf" -o -name "*.yaml" -o -name "*.yml" -o -name "*.json" -o -name "*.env" 2>/dev/null | head -10 | while read config_file; do
if [ -r "$config_file" ]; then
echo " $config_file"
fi
done
fi
done
echo ""
# Docker Compose files
echo "Docker Compose files:"
find /opt /home -name "docker-compose*.yml" -o -name "compose*.yml" 2>/dev/null | head -10 | while read compose_file; do
echo " $compose_file"
# Extract service names
services=$(grep -E "^ [a-zA-Z0-9_-]+:" "$compose_file" 2>/dev/null | sed 's/://g' | sed 's/^ //' | head -5)
if [ -n "$services" ]; then
echo " Services: $(echo $services | tr '\n' ' ')"
fi
done
register: config_analysis
changed_when: false
- name: Detect web interfaces and APIs
shell: |
echo "=== WEB INTERFACE DETECTION ==="
# Common web interface ports
web_ports="80 443 8080 8443 3000 5000 8000 9000 9090 3001 8081 8082 8083 8084 8085"
for port in $web_ports; do
# Check if port is listening
if netstat -tuln 2>/dev/null | grep -q ":$port " || ss -tuln 2>/dev/null | grep -q ":$port "; then
echo "Port $port is active"
# Try to detect service type
if curl -s -m 3 -I "http://localhost:$port" 2>/dev/null | head -1 | grep -q "200\|301\|302"; then
server_header=$(curl -s -m 3 -I "http://localhost:$port" 2>/dev/null | grep -i "server:" | head -1)
title=$(curl -s -m 3 "http://localhost:$port" 2>/dev/null | grep -i "<title>" | head -1 | sed 's/<[^>]*>//g' | xargs)
echo " HTTP Response: OK"
if [ -n "$server_header" ]; then
echo " $server_header"
fi
if [ -n "$title" ]; then
echo " Title: $title"
fi
# Check for common API endpoints
for endpoint in /api /health /status /metrics /version; do
if curl -s -m 2 "http://localhost:$port$endpoint" >/dev/null 2>&1; then
echo " API endpoint: http://localhost:$port$endpoint"
break
fi
done
fi
echo ""
fi
done
register: web_interfaces
changed_when: false
ignore_errors: yes
- name: Generate service catalog
set_fact:
service_catalog:
timestamp: "{{ inventory_timestamp }}"
hostname: "{{ inventory_hostname }}"
system_info:
os: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
kernel: "{{ ansible_kernel }}"
architecture: "{{ ansible_architecture }}"
services:
system: "{{ system_services.stdout }}"
docker: "{{ docker_services.stdout if not skip_docker else 'Docker not available' }}"
configurations: "{{ config_analysis.stdout }}"
web_interfaces: "{{ web_interfaces.stdout }}"
- name: Display service inventory
debug:
msg: |
==========================================
📋 SERVICE INVENTORY - {{ inventory_hostname }}
==========================================
🖥️ SYSTEM INFO:
- OS: {{ service_catalog.system_info.os }}
- Kernel: {{ service_catalog.system_info.kernel }}
- Architecture: {{ service_catalog.system_info.architecture }}
🔧 SYSTEM SERVICES:
{{ service_catalog.services.system }}
🐳 DOCKER SERVICES:
{{ service_catalog.services.docker }}
⚙️ CONFIGURATIONS:
{{ service_catalog.services.configurations }}
🌐 WEB INTERFACES:
{{ service_catalog.services.web_interfaces }}
==========================================
- name: Generate JSON service inventory
copy:
content: |
{
"timestamp": "{{ service_catalog.timestamp }}",
"hostname": "{{ service_catalog.hostname }}",
"system_info": {
"os": "{{ service_catalog.system_info.os }}",
"kernel": "{{ service_catalog.system_info.kernel }}",
"architecture": "{{ service_catalog.system_info.architecture }}"
},
"services": {
"system": {{ service_catalog.services.system | to_json }},
"docker": {{ service_catalog.services.docker | to_json }},
"configurations": {{ service_catalog.services.configurations | to_json }},
"web_interfaces": {{ service_catalog.services.web_interfaces | to_json }}
}
}
dest: "{{ inventory_dir }}/{{ inventory_hostname }}_inventory_{{ ansible_date_time.epoch }}.json"
delegate_to: localhost
- name: Generate Markdown documentation
copy:
content: |
# Service Documentation - {{ inventory_hostname }}
**Generated:** {{ inventory_timestamp }}
**System:** {{ service_catalog.system_info.os }} ({{ service_catalog.system_info.architecture }})
## 🔧 System Services
```
{{ service_catalog.services.system }}
```
## 🐳 Docker Services
```
{{ service_catalog.services.docker }}
```
## ⚙️ Configuration Files
```
{{ service_catalog.services.configurations }}
```
## 🌐 Web Interfaces & APIs
```
{{ service_catalog.services.web_interfaces }}
```
## 📊 Quick Stats
- **Hostname:** {{ inventory_hostname }}
- **OS:** {{ service_catalog.system_info.os }}
- **Kernel:** {{ service_catalog.system_info.kernel }}
- **Architecture:** {{ service_catalog.system_info.architecture }}
- **Docker Available:** {{ 'Yes' if not skip_docker else 'No' }}
---
*Auto-generated by Ansible service_inventory.yml playbook*
dest: "{{ documentation_dir }}/{{ inventory_hostname }}_services.md"
delegate_to: localhost
- name: Generate consolidated inventory (run once)
shell: |
cd "{{ inventory_dir }}"
echo "# Homelab Service Inventory" > consolidated_inventory.md
echo "" >> consolidated_inventory.md
echo "**Generated:** {{ inventory_timestamp }}" >> consolidated_inventory.md
echo "" >> consolidated_inventory.md
# Process all JSON files
for json_file in *_inventory_*.json; do
if [ -f "$json_file" ]; then
hostname=$(basename "$json_file" | cut -d'_' -f1)
echo "## 🖥️ $hostname" >> consolidated_inventory.md
echo "" >> consolidated_inventory.md
# Extract key information using basic tools
if command -v jq >/dev/null 2>&1; then
os=$(jq -r '.system_info.os' "$json_file" 2>/dev/null || echo "Unknown")
echo "- **OS:** $os" >> consolidated_inventory.md
echo "- **File:** [$json_file](./$json_file)" >> consolidated_inventory.md
echo "- **Documentation:** [${hostname}_services.md](../service_docs/${hostname}_services.md)" >> consolidated_inventory.md
else
echo "- **File:** [$json_file](./$json_file)" >> consolidated_inventory.md
fi
echo "" >> consolidated_inventory.md
fi
done
echo "---" >> consolidated_inventory.md
echo "*Auto-generated by Ansible service_inventory.yml playbook*" >> consolidated_inventory.md
delegate_to: localhost
run_once: true
- name: Summary message
debug:
msg: |
📋 Service inventory complete for {{ inventory_hostname }}
📄 JSON Report: {{ inventory_dir }}/{{ inventory_hostname }}_inventory_{{ ansible_date_time.epoch }}.json
📖 Markdown Doc: {{ documentation_dir }}/{{ inventory_hostname }}_services.md
📚 Consolidated: {{ inventory_dir }}/consolidated_inventory.md
💡 Use this playbook regularly to maintain up-to-date service documentation
💡 JSON files can be consumed by monitoring systems or dashboards