apply_port_offset.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #!/usr/bin/env python
  2. #ident "@(#)$Format:LocalFoodAI_lanfr144:apply_port_offset.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
  3. import os
  4. import socket
  5. import sys
  6. DEFAULT_PORTS = {
  7. "BACKEND_PORT": 5000,
  8. "MYSQL_PORT": 3306,
  9. "AIRFLOW_PORT": 8080,
  10. "ZABBIX_PORT": 8081,
  11. "JENKINS_PORT": 8088
  12. }
  13. def is_port_in_use(port):
  14. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  15. s.settimeout(1.0)
  16. return s.connect_ex(('127.0.0.1', port)) == 0
  17. def load_env(env_path):
  18. env_vars = {}
  19. if not os.path.exists(env_path):
  20. return env_vars
  21. with open(env_path, 'r', encoding='utf-8') as f:
  22. for line in f:
  23. line = line.strip()
  24. if line and not line.startswith('#') and '=' in line:
  25. key, val = line.split('=', 1)
  26. env_vars[key.strip()] = val.strip()
  27. return env_vars
  28. def write_env(env_path, updates):
  29. if not os.path.exists(env_path):
  30. with open(env_path, 'w', encoding='utf-8') as f:
  31. for k, v in updates.items():
  32. f.write(f"{k}={v}\n")
  33. return
  34. with open(env_path, 'r', encoding='utf-8') as f:
  35. lines = f.readlines()
  36. updated_keys = set()
  37. new_lines = []
  38. for line in lines:
  39. stripped = line.strip()
  40. if stripped and not stripped.startswith('#') and '=' in stripped:
  41. key, _ = stripped.split('=', 1)
  42. key = key.strip()
  43. if key in updates:
  44. new_lines.append(f"{key}={updates[key]}\n")
  45. updated_keys.add(key)
  46. continue
  47. new_lines.append(line)
  48. for k, v in updates.items():
  49. if k not in updated_keys:
  50. new_lines.append(f"{k}={updates[k]}\n")
  51. with open(env_path, 'w', encoding='utf-8') as f:
  52. f.writelines(new_lines)
  53. def main():
  54. base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  55. env_path = os.path.join(base_dir, ".env")
  56. if not os.path.exists(env_path):
  57. print(f"[ERROR] .env file not found at {env_path}")
  58. sys.exit(1)
  59. env_vars = load_env(env_path)
  60. offset_str = env_vars.get("PORT_OFFSET", "0")
  61. try:
  62. offset = int(offset_str)
  63. except ValueError:
  64. print(f"[ERROR] PORT_OFFSET in .env is not a valid integer: '{offset_str}'")
  65. sys.exit(1)
  66. print(f"[INFO] Using PORT_OFFSET={offset} loaded from .env")
  67. # Calculate ports and check availability
  68. calculated_ports = {}
  69. in_use_ports = []
  70. for name, default_port in DEFAULT_PORTS.items():
  71. target_port = default_port + offset
  72. calculated_ports[name] = target_port
  73. print(f"Checking target port {name}: {target_port} ... ", end="")
  74. sys.stdout.flush()
  75. if is_port_in_use(target_port):
  76. print("IN USE")
  77. in_use_ports.append((name, target_port))
  78. else:
  79. print("FREE")
  80. if in_use_ports:
  81. print("\n[ERROR] The following calculated ports are already in use on the host:")
  82. for name, port in in_use_ports:
  83. print(f" - {name}: {port}")
  84. print("Please resolve the conflict or change PORT_OFFSET in .env before proceeding.")
  85. sys.exit(1)
  86. # Write updates to .env
  87. updates = {name: str(port) for name, port in calculated_ports.items()}
  88. write_env(env_path, updates)
  89. print("\n[SUCCESS] Successfully verified and updated .env with offsetted ports:")
  90. for name, port in calculated_ports.items():
  91. print(f" - {name}: {port}")
  92. if __name__ == "__main__":
  93. main()