Files
ethereum-rpc-docker/list-port-forwards.py
Brain🧠 dd662dfdd0 home
2025-05-22 20:33:57 +03:00

179 lines
6.6 KiB
Python

#!/usr/bin/env python3
import os
import yaml
import re
import pwd
import grp
from pathlib import Path
def load_env_file(env_file_path='.env'):
"""Load environment variables from .env file."""
env_vars = {}
if not os.path.exists(env_file_path):
print(f"Warning: {env_file_path} file not found in current directory")
return env_vars
try:
with open(env_file_path, 'r') as f:
for line in f:
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith('#'):
continue
# Parse KEY=VALUE format
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
# Remove quotes if present
if (value.startswith('"') and value.endswith('"')) or \
(value.startswith("'") and value.endswith("'")):
value = value[1:-1]
env_vars[key] = value
print(f"Loaded {len(env_vars)} variables from {env_file_path}")
return env_vars
except Exception as e:
print(f"Error reading {env_file_path}: {e}")
return env_vars
def extract_ports_from_yaml(yaml_file):
"""Extract port mappings from a single YAML file."""
try:
if not os.path.exists(yaml_file):
print(f"Warning: File {yaml_file} not found")
return []
with open(yaml_file, 'r') as f:
data = yaml.safe_load(f)
if not data or 'services' not in data:
return []
port_mappings = []
for service_name, service_config in data['services'].items():
if 'ports' in service_config:
for port_mapping in service_config['ports']:
# Handle different port mapping formats
if isinstance(port_mapping, str):
# Format: "host_port:container_port" or "host_port:container_port/protocol"
port_parts = port_mapping.split(':')
if len(port_parts) >= 2:
host_port = port_parts[0]
container_port = port_parts[1]
# Remove protocol suffix if present (e.g., "/udp")
host_port = re.sub(r'/\w+$', '', host_port)
container_port = re.sub(r'/\w+$', '', container_port)
port_mappings.append((service_name, host_port))
elif isinstance(port_mapping, int):
# Single port number
port_mappings.append((service_name, str(port_mapping)))
elif isinstance(port_mapping, dict):
# Long form port mapping
if 'published' in port_mapping:
port_mappings.append((service_name, str(port_mapping['published'])))
elif 'target' in port_mapping:
port_mappings.append((service_name, str(port_mapping['target'])))
return port_mappings
except Exception as e:
print(f"Error parsing {yaml_file}: {e}")
return []
def main():
# Load .env file from current working directory
env_vars = load_env_file()
# Get COMPOSE_FILE from .env file or environment variable as fallback
compose_file_env = env_vars.get('COMPOSE_FILE') or os.getenv('COMPOSE_FILE', '')
if not compose_file_env:
print("COMPOSE_FILE not found in .env file or environment variables")
return
print(f"Found COMPOSE_FILE: {compose_file_env[:100]}{'...' if len(compose_file_env) > 100 else ''}")
print()
# Split by colon to get individual YAML files
yaml_files = compose_file_env.split(':')
# Filter out excluded files
excluded_files = {'home.yml', 'base.yml', 'rpc.yml'}
filtered_files = []
for yaml_file in yaml_files:
yaml_file = yaml_file.strip()
if yaml_file and Path(yaml_file).name not in excluded_files:
filtered_files.append(yaml_file)
print(f"Processing {len(filtered_files)} YAML files...")
print("=" * 50)
# Extract ports from each file
all_port_mappings = []
for yaml_file in filtered_files:
port_mappings = extract_ports_from_yaml(yaml_file)
all_port_mappings.extend(port_mappings)
if port_mappings:
print(f"\n{yaml_file}:")
for service_name, port in port_mappings:
print(f" {service_name} : {port}")
# Remove duplicates by converting to set then back to list
unique_port_mappings = list(set(all_port_mappings))
# Sort the unique mappings
sorted_mappings = sorted(unique_port_mappings, key=lambda x: (x[0], int(x[1]) if x[1].isdigit() else x[1]))
# Summary to console
print("\n" + "=" * 50)
print("SUMMARY - Unique Port Mappings:")
print("=" * 50)
for service_name, port in sorted_mappings:
print(f"{service_name} : {port}")
print(f"\nTotal unique port mappings found: {len(sorted_mappings)}")
print(f"Duplicates removed: {len(all_port_mappings) - len(sorted_mappings)}")
# Save to file (clean format, no whitespaces)
output_file = os.path.expanduser("~payne/port-forward.txt")
try:
# Write the file
with open(output_file, 'w') as f:
for service_name, port in sorted_mappings:
f.write(f"{service_name}:{port}\n")
# Set ownership to payne:payne
try:
payne_user = pwd.getpwnam('payne')
payne_group = grp.getgrnam('payne')
os.chown(output_file, payne_user.pw_uid, payne_group.gr_gid)
except KeyError:
print("Warning: User or group 'payne' not found, skipping ownership change")
except PermissionError:
print("Warning: Permission denied setting ownership (you may need to run as root)")
# Set read permissions for user payne (644: owner read/write, group read, others read)
os.chmod(output_file, 0o644)
print(f"\nResults saved to: {output_file}")
print("File ownership set to payne:payne with read permissions")
except Exception as e:
print(f"\nError saving to {output_file}: {e}")
print("You may need to run with sudo or check file permissions")
if __name__ == "__main__":
main()