home
This commit is contained in:
178
list-port-forwards.py
Normal file
178
list-port-forwards.py
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user