generate_dbeaver_connections.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #!/usr/bin/env python3
  2. """
  3. Generate DBeaver data-sources.json from sdm status --json output
  4. Organizes PostgreSQL connections by customer folders
  5. Excludes readonly connections, includes activate connections
  6. """
  7. import subprocess
  8. import json
  9. import re
  10. import uuid
  11. import os
  12. from collections import defaultdict
  13. def run_sdm_status():
  14. try:
  15. result = subprocess.run(['sdm', 'status', '--json'], capture_output=True, text=True)
  16. if result.returncode != 0:
  17. print(f"Error running sdm status: {result.stderr}")
  18. return None
  19. return json.loads(result.stdout)
  20. except FileNotFoundError:
  21. print("Error: sdm command not found")
  22. return None
  23. except json.JSONDecodeError as e:
  24. print(f"Error parsing JSON: {e}")
  25. return None
  26. def parse_postgres_connections(sdm_data):
  27. connections = []
  28. for item in sdm_data:
  29. if item.get('type') == 'postgres':
  30. name = item.get('name', '')
  31. address = item.get('address', '')
  32. if 'readonly' in name:
  33. continue
  34. if ':' in address:
  35. addr, port = address.split(':')
  36. port = int(port)
  37. else:
  38. continue
  39. env_info = parse_connection_name(name)
  40. if env_info:
  41. connections.append({
  42. 'name': name,
  43. 'addr': addr,
  44. 'port': port,
  45. 'environment': env_info['environment'],
  46. 'customer': env_info['customer'],
  47. 'stage': env_info['stage']
  48. })
  49. return connections
  50. def parse_connection_name(name):
  51. pattern = r'oc-([^-]+)-([^-]+)-.*'
  52. match = re.match(pattern, name)
  53. if not match:
  54. return None
  55. environment = match.group(1)
  56. customer = match.group(2)
  57. if environment in ['dev', 'nextrc', 'nextrc2']:
  58. stage = 'internal'
  59. elif environment in ['stage', 'stage2', 'uat']:
  60. stage = 'stage'
  61. elif environment in ['prod', 'prod2']:
  62. stage = 'production'
  63. else:
  64. stage = 'unknown'
  65. return {
  66. 'environment': environment,
  67. 'customer': customer,
  68. 'stage': stage
  69. }
  70. def create_dbeaver_connection(conn, connection_id):
  71. if conn['customer'] == 'internal' or conn['customer'].startswith('feature'):
  72. folder = 'internal'
  73. elif conn['stage'] == 'stage':
  74. folder = conn['customer']
  75. elif conn['stage'] == 'production':
  76. folder = conn['customer']
  77. else:
  78. folder = 'other'
  79. display_name = conn['name'].replace('oc-', '').replace('-rds', '').replace('-activate', '')
  80. if 'activate' in conn['name']:
  81. display_name = f"activate-{display_name}"
  82. if 'activate' in conn['name']:
  83. default_db = "postgres"
  84. db_url = f"jdbc:postgresql://{conn['addr']}:{conn['port']}/postgres"
  85. else:
  86. default_db = "member_dossier"
  87. db_url = f"jdbc:postgresql://{conn['addr']}:{conn['port']}/member_dossier"
  88. return {
  89. "provider": "postgresql",
  90. "driver": "postgres-jdbc",
  91. "name": display_name,
  92. "save-password": True,
  93. "folder": folder,
  94. "configuration": {
  95. "host": conn['addr'],
  96. "port": str(conn['port']),
  97. "database": default_db,
  98. "url": db_url,
  99. "configurationType": "MANUAL",
  100. "home": "/bin",
  101. "type": conn['environment'],
  102. "closeIdleConnection": False,
  103. "provider-properties": {
  104. "@dbeaver-show-non-default-db@": "true",
  105. "@dbeaver-show-template-db@": "true",
  106. "@dbeaver-show-unavailable-db@": "true",
  107. "show-database-statistics": "false",
  108. "@dbeaver-read-all-data-types-db@": "false",
  109. "@dbeaver-use-prepared-statements-db@": "false",
  110. "postgresql.dd.plain.string": "false",
  111. "postgresql.dd.tag.string": "false"
  112. },
  113. "auth-model": "native"
  114. }
  115. }
  116. def group_connections(connections):
  117. folders = defaultdict(list)
  118. for conn in connections:
  119. if conn['customer'] == 'internal' or conn['customer'].startswith('feature'):
  120. folder = 'internal'
  121. elif conn['stage'] == 'stage':
  122. folder = conn['customer']
  123. elif conn['stage'] == 'production':
  124. folder = conn['customer']
  125. else:
  126. folder = 'other'
  127. folders[folder].append(conn)
  128. return folders
  129. def generate_dbeaver_config(connections):
  130. folders = group_connections(connections)
  131. folders_config = {}
  132. for folder_name in folders.keys():
  133. folders_config[folder_name] = {}
  134. connections_config = {}
  135. for conn in connections:
  136. connection_id = f"postgres-jdbc-{uuid.uuid4().hex[:8]}-{uuid.uuid4().hex[:8]}"
  137. conn_config = create_dbeaver_connection(conn, connection_id)
  138. connections_config[connection_id] = conn_config
  139. return {
  140. "folders": folders_config,
  141. "connections": connections_config
  142. }
  143. def main():
  144. print("Generating DBeaver data-sources.json from sdm status --json...")
  145. sdm_data = run_sdm_status()
  146. if not sdm_data:
  147. return
  148. connections = parse_postgres_connections(sdm_data)
  149. print(f"Found {len(connections)} PostgreSQL connections")
  150. folders = group_connections(connections)
  151. for folder_name, conns in folders.items():
  152. print(f" {folder_name}: {len(conns)} connections")
  153. dbeaver_config = generate_dbeaver_config(connections)
  154. output_file = os.path.expanduser('~/.local/share/DBeaverData/workspace6/Stuzo/.dbeaver/data-sources.json')
  155. try:
  156. with open(output_file, 'w') as f:
  157. json.dump(dbeaver_config, f, indent='\t')
  158. print(f"✅ Successfully generated {output_file}")
  159. print("📝 Note: You may need to restart DBeaver to see the new connections")
  160. except Exception as e:
  161. print(f"❌ Error writing file: {e}")
  162. if __name__ == '__main__':
  163. main()