diff --git a/list_cert_based_kubernetes_clusters.py b/list_cert_based_kubernetes_clusters.py index 07cb5978c1c1ecc14c1d5f6ac3fb9b825dfb14a3..67c238dd52b0e0e0ee91005e1ecc30858f89f787 100644 --- a/list_cert_based_kubernetes_clusters.py +++ b/list_cert_based_kubernetes_clusters.py @@ -1,22 +1,76 @@ #!/usr/bin/env python -# Description: Fetch all sub-groups and projects from a given group ID, and print all certificate based Kubernetes clusters. This helps planning the migration after the deprecation. -# Requirements: python-gitlab Python libraries. GitLab API read access, and maintainer access to all configured groups/projects. -# Author: Michael Friedrich -# License: MIT, (c) 2023-present GitLab B.V. +""" +GitLab Kubernetes Cluster Scanner +--------------------------------- +Fetches all certificate-based Kubernetes clusters from a given GitLab group and its subgroups/projects. +Helps with planning migration after deprecation. + +Requirements: +- python-gitlab library +- GitLab API read access +- Maintainer access to configured groups/projects + +Author: Michael Friedrich +License: MIT, (c) 2023-present GitLab B.V. +""" import gitlab import os import sys +from datetime import datetime + +def format_cluster_info(cluster): + """Format cluster information in a readable way""" + # Extract the most relevant information + cluster_dict = cluster.asdict() + + # Create a more readable output format + output = [] + output.append(f"Name: {cluster_dict.get('name', 'N/A')}") + output.append(f"Created: {cluster_dict.get('created_at', 'N/A')}") + output.append(f"Status: {'Active' if cluster_dict.get('enabled', False) else 'Disabled'}") + output.append(f"Provider: {cluster_dict.get('provider_type', 'N/A')}") + output.append(f"Platform: {cluster_dict.get('platform_type', 'N/A')}") + + # Add user information + user = cluster_dict.get('user', {}) + if user: + output.append(f"Created by: {user.get('name', 'N/A')} (@{user.get('username', 'N/A')})") + + # Add Kubernetes platform details if available + k8s = cluster_dict.get('platform_kubernetes', {}) + if k8s: + output.append(f"API URL: {k8s.get('api_url', 'N/A')}") + output.append(f"Auth Type: {k8s.get('authorization_type', 'N/A')}") + + # Show only the first line of the certificate to avoid clutter + ca_cert = k8s.get('ca_cert', '') + if ca_cert: + cert_preview = ca_cert.split('\n')[0] + output.append(f"CA Cert: {cert_preview}... (truncated)") + + # Add GCP provider details if available + gcp = cluster_dict.get('provider_gcp', {}) + if gcp: + output.append(f"GCP Project: {gcp.get('gcp_project_id', 'N/A')}") + output.append(f"Zone: {gcp.get('zone', 'N/A')}") + output.append(f"Machine Type: {gcp.get('machine_type', 'N/A')}") + output.append(f"Nodes: {gcp.get('num_nodes', 'N/A')}") + output.append(f"Status: {gcp.get('status_name', 'N/A')}") + + return "\n".join(output) def print_clusters(clusters): - for c in clusters: - print(c) - print("\n\n") + for i, cluster in enumerate(clusters): + print(f"Cluster #{i+1}:") + print("─" * 40) + print(format_cluster_info(cluster)) + print("─" * 40) + print() GITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com') -# https://gitlab.com/everyonecancontribute -GROUP_ID = os.environ.get('GL_GROUP_ID', 8034603) +GROUP_ID = int(os.environ.get('GL_GROUP_ID', 8034603)) GITLAB_TOKEN = os.environ.get('GL_TOKEN') if not GITLAB_TOKEN: @@ -26,13 +80,8 @@ if not GITLAB_TOKEN: # TOKEN requires maintainer+ permissions gl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN) -# All groups on gitlab.com takes too long; scope it down to your group namespace via GROUP_ID. For self-managed, try experimenting with the line below to fetch all groups. -#groups = gl.groups.list(get_all=True) -groups = [ ] - -# get GROUP_ID group -groups.append(gl.groups.get(GROUP_ID)) - +# Get all groups +groups = [gl.groups.get(GROUP_ID)] for group in groups: for sg in group.subgroups.list(include_subgroups=True, all=True): real_group = gl.groups.get(sg.id) @@ -41,49 +90,65 @@ for group in groups: group_clusters = {} project_clusters = {} +print(f"Scanning {len(groups)} groups for Kubernetes clusters...") +print() + for group in groups: - #Collect group clusters + # Collect group clusters g_clusters = group.clusters.list() - - if len(g_clusters) > 0: + if g_clusters: group_clusters[group.id] = g_clusters # Collect all projects in group and subgroups and their clusters projects = group.projects.list(include_subgroups=True, all=True) - for project in projects: - # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples - manageable_project = gl.projects.get(project.id) - - # skip archived projects + # Skip archived projects if project.archived: continue - + + manageable_project = gl.projects.get(project.id) p_clusters = manageable_project.clusters.list() - - if len(p_clusters) > 0: + if p_clusters: project_clusters[project.id] = p_clusters # Print summary -print("## Group clusters\n\n") - -for g_id, g_clusters in group_clusters.items(): - url = gl.groups.get(g_id).web_url +print("=" * 80) +print(f"SCAN RESULTS - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") +print("=" * 80) +print() - print("Group ID {g_id}: {u}\n\n".format(g_id=g_id, u=url)) +# Print group clusters +print("GROUP CLUSTERS") +print("=" * 80) +print(f"Found {len(group_clusters)} groups with clusters") +print() +for g_id, g_clusters in group_clusters.items(): + group = gl.groups.get(g_id) + print(f"Group: {group.name}") + print(f"ID: {g_id}") + print(f"URL: {group.web_url}") + print(f"Clusters: {len(g_clusters)}") + print("─" * 80) print_clusters(g_clusters) + print() - -print("## Project clusters\n\n") +# Print project clusters +print("PROJECT CLUSTERS") +print("=" * 80) +print(f"Found {len(project_clusters)} projects with clusters") +print() for p_id, p_clusters in project_clusters.items(): - url = gl.projects.get(p_id).web_url - - print("Project ID {p_id}: {u}\n\n".format(p_id=p_id, u=url)) - + project = gl.projects.get(p_id) + print(f"Project: {project.name}") + print(f"ID: {p_id}") + print(f"URL: {project.web_url}") + print(f"Clusters: {len(p_clusters)}") + print("─" * 80) print_clusters(p_clusters) + print() - - - +print("=" * 80) +print(f"SCAN COMPLETE - Total clusters: {sum(len(c) for c in group_clusters.values()) + sum(len(c) for c in project_clusters.values())}") +print("=" * 80) \ No newline at end of file