#!/usr/bin/env python3 """Search entire config tree for any server-like structures""" import asyncio import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) from api.protos import configuration_pb2, configuration_pb2_grpc import grpc def analyze_folder(folder, depth=0, max_depth=3): """Recursively analyze folder structure""" indent = " " * depth results = [] if depth > max_depth: return results for child in folder.children: if child.type == "folder": # Check if this looks like a server definition child_fields = {c.name for c in child.children} # Server indicators: Has Host, User, Password, Alias fields server_indicators = {'Host', 'User', 'Password', 'Alias', 'Enabled'} matching_fields = child_fields & server_indicators if len(matching_fields) >= 3: # At least 3 matching fields results.append({ 'parent': folder.name, 'name': child.name, 'depth': depth, 'fields': list(child_fields), 'match_score': len(matching_fields) }) # Recurse into subfolder results.extend(analyze_folder(child, depth + 1, max_depth)) return results async def search_servers(): """Search for all server-like structures""" channel = grpc.aio.insecure_channel('localhost:50051') stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) try: request = configuration_pb2.ReadConfigurationTreeRequest() response = await stub.ReadConfigurationTree(request, timeout=10.0) print("=" * 70) print("Searching for Server-like Structures (with Host/User/Password fields)") print("=" * 70) all_servers = [] # Search in all top-level folders for top_folder in response.root.children: servers_in_folder = analyze_folder(top_folder, depth=0, max_depth=2) all_servers.extend(servers_in_folder) # Group by parent folder by_parent = {} for server in all_servers: parent = server['parent'] if parent not in by_parent: by_parent[parent] = [] by_parent[parent].append(server) # Display results for parent, servers in sorted(by_parent.items()): print(f"\n[{parent}] - {len(servers)} server(s)") for server in servers[:3]: # Show first 3 print(f" Server: {server['name']}") print(f" Match score: {server['match_score']}/5") print(f" Fields: {', '.join(sorted(server['fields']))}") if len(servers) > 3: print(f" ... and {len(servers) - 3} more servers") if not all_servers: print("\nNo server-like structures found besides GeViGCoreServer!") print("\nLet me list ALL top-level folders with their immediate children:") print("=" * 70) for top_folder in response.root.children: if top_folder.type == "folder" and len(top_folder.children) > 0: print(f"\n{top_folder.name}:") # Check if children are folders or values folder_children = [c for c in top_folder.children if c.type == "folder"] if folder_children: print(f" Contains {len(folder_children)} sub-folders") if len(folder_children) <= 5: for child in folder_children: fields = [c.name for c in child.children[:8]] print(f" - {child.name}: {', '.join(fields)}") await channel.close() except Exception as e: print(f"ERROR: {e}") import traceback traceback.print_exc() await channel.close() if __name__ == "__main__": asyncio.run(search_servers())