# generating-gateway-topology > Generates and displays Kubernetes Gateway API topology diagrams showing GatewayClasses, Gateways, Routes, and backend Services in Mermaid format - Author: Ali Syed - Repository: Thealisyed/ai-helpers - Version: 20251219114132 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/Thealisyed/ai-helpers - Web: https://mule.run/skillshub/@@Thealisyed/ai-helpers~generating-gateway-topology:20251219114132 --- --- name: generating-gateway-topology description: Generates and displays Kubernetes Gateway API topology diagrams showing GatewayClasses, Gateways, Routes, and backend Services in Mermaid format tools: [Bash, Read, Write] --- # Quick Start - Gateway API Topology Generation **IMMEDIATE ACTIONS** (follow these steps in order): 1. **Detect Cluster**: Find a cluster with Gateway API CRDs installed Run: `scripts/detect-gateway-cluster.sh 2>/dev/null` The script discovers clusters with Gateway API: - Scans all kubeconfig files: current KUBECONFIG env, ~/.kube/kind-config, ~/.kube/config - Tests ALL contexts in each kubeconfig - Returns parseable list to stdout: `index|kubeconfig|cluster_name|gateway_count|installed_crds` - Diagnostics go to stderr - Exit code: 0=success, 1=no clusters found **How to handle the output:** The script returns pipe-delimited lines to stdout, one per cluster found, e.g.: ```text 1|/home/user/.kube/config|prod-cluster|5|gateways,httproutes,gatewayclasses 2|/home/user/.kube/kind-config|dev-cluster|2|gateways,httproutes ``` **Decision logic:** - If **one cluster** found → automatically use it (extract kubeconfig path from column 2) - If **multiple clusters** found → show the list to user and ask them to choose by number - After selection, extract the kubeconfig path from column 2 of the chosen line - Store the selected kubeconfig path in variable `KC` for use in subsequent steps **Example output format parsing:** - Column 1: Index number (for user selection) - Column 2: Kubeconfig file path (this is what you need for `$KC`) - Column 3: Cluster display name - Column 4: Number of Gateway resources - Column 5: Installed Gateway API CRDs 2. **Check Permissions**: Verify user's Kubernetes access level and inform about write permissions Run: `scripts/check_permissions.py "$KC"` The script returns: - **Exit 0**: Read-only access or user confirmed → proceed - **Exit 1**: Error or user cancelled → stop - **Exit 2**: Write permissions detected → AI must ask user for confirmation **When exit code 2 is returned:** 1. Parse the stdout to get the list of write permissions 2. Display the permissions clearly to the user using a formatted message 3. Explain that: - This skill performs ONLY read-only operations - No cluster modifications will be made - The warning is for transparency about their access level - List read-only operations: kubectl get (gateways, httproutes, services, etc.) - List forbidden operations: kubectl create/delete/patch, no Gateway modifications 4. **Ask the user explicitly**: "You have cluster admin permissions. This command will only perform read-only operations. Do you want to proceed?" 5. If user says yes → continue, if no → stop 3. **Check Output File**: Ask user if `gateway-topology-diagram.md` exists: - (1) Overwrite, (2) Custom path, (3) Timestamp, (4) Cancel 4. **Create Private Temp Directory**: Create a private temporary directory using `mkdtemp` and use it for all temporary files. ```bash TMPDIR=$(mktemp -d) ``` 5. **Collect Gateway Data**: Get all Gateway API resources from the cluster Run: `scripts/collect_gateway_data.py "$KC" "$TMPDIR"` Detail files written to `$TMPDIR`: - `gateway_classes_detail.txt` - name|controller|description|status - `gateways_detail.txt` - namespace|name|class|listeners|addresses|status - `httproutes_detail.txt` - namespace|name|hostnames|parent_refs|backend_refs - `grpcroutes_detail.txt` - namespace|name|parent_refs|backend_refs - `tcproutes_detail.txt` - namespace|name|parent_refs|backend_refs - `tlsroutes_detail.txt` - namespace|name|hostnames|parent_refs|backend_refs - `backends_detail.txt` - namespace|name|type|ports|pod_count - `reference_grants_detail.txt` - namespace|name|from_refs|to_refs - `route_rules_detail.txt` - route_ns|route_name|rule_idx|match_condition|backends_with_weights - `endpoints_detail.txt` - svc_namespace|svc_name|pod_name|pod_ip|ready 6. **Analyze Topology**: Build relationship graph from collected data Run: `scripts/analyze_topology.py "$TMPDIR"` Relationships written to `$TMPDIR`: - `gateway_relationships.txt` - source_type|source_id|relation|target_type|target_id 7. **Generate Diagram**: Create Mermaid `graph TB` diagram - Read `$TMPDIR/gateway_relationships.txt` to determine connections - Read detail files directly for resource attributes - Group resources by type in subgraphs 8. **Save & Report**: Write diagram to file, show summary, clean up temporary files **CRITICAL RULES**: - ❌ NO codebase searching for IPs/ports - ❌ NO synthetic/example data - ❌ NO inline multi-line bash (use helper scripts) - ❌ NO direct kubectl commands (must use helper scripts only) - ✅ Use helper scripts for all kubectl interactions - ✅ **SECURITY**: Create private temp directory with `TMPDIR=$(mktemp -d)` - never use `/tmp` directly - ✅ Temporary files use `$TMPDIR` (private directory created with mkdtemp) - ✅ Clean up temporary files when done: `rm -rf "$TMPDIR"` ## Safety & Security Guarantees ### Read-Only Operations This skill performs **ONLY read-only operations** against your Kubernetes cluster. No cluster state is modified. **Allowed Operations:** - ✅ `kubectl get` - Query Gateway API resources - ✅ `gwctl get/describe` - Query resources if gwctl is available - ✅ Local file writes (temporary files in `$TMPDIR`, output diagram) **Forbidden Operations (NEVER used):** - ❌ `kubectl create/apply/delete/patch` - No resource modifications - ❌ `gwctl apply/delete` - No resource modifications - ❌ No Gateway/Route creation or deletion - ❌ No service disruptions **Privacy Consideration**: The generated diagram contains Gateway API topology information including hostnames and backend services. Control sharing appropriately based on your security policies. --- # Gateway API Concepts ## Resource Hierarchy The Gateway API follows a hierarchical model: 1. **GatewayClass** (cluster-scoped) - Defines a type of Gateway managed by a controller - Examples: istio, nginx, envoy, kong 2. **Gateway** (namespace-scoped) - Represents an actual load balancer or proxy - Has listeners (ports, protocols, hostnames) - References a GatewayClass 3. **Routes** (namespace-scoped) - HTTPRoute, GRPCRoute, TCPRoute, TLSRoute - Define routing rules from Gateway to backends - Reference parent Gateways 4. **Backend Services** (namespace-scoped) - Kubernetes Services referenced by Routes - May include port and weight configurations 5. **ReferenceGrants** (namespace-scoped) - Allow cross-namespace references - Required when Route in namespace A references Service in namespace B ## Helper Scripts All helper scripts are in the `scripts/` directory. | Script | Purpose | Input | Output | |--------|---------|-------|--------| | [detect-gateway-cluster.sh](scripts/detect-gateway-cluster.sh) | Find cluster with Gateway API CRDs across all contexts | None | Parseable list to stdout: `index\|kubeconfig\|cluster\|gateways\|crds`. Exit: 0=success, 1=none found | | [check_permissions.py](scripts/check_permissions.py) | Check user permissions and warn if write access detected | KUBECONFIG path | Exit: 0=proceed, 1=cancelled/error, 2=write perms (needs user confirmation) | | [collect_gateway_data.py](scripts/collect_gateway_data.py) | Collect all Gateway API resources from cluster | KUBECONFIG path, TMPDIR | Detail files: `gateway_classes_detail.txt`, `gateways_detail.txt`, `httproutes_detail.txt`, etc. | | [analyze_topology.py](scripts/analyze_topology.py) | Build relationship graph from collected data | TMPDIR (reads detail files) | Relationships file: `gateway_relationships.txt` | --- # Diagram Generation Rules ## Structure Options There are two diagram modes based on complexity: ### Mode 1: Per-Gateway Subgraphs (Detailed - for clusters with 1-3 Gateways) Use this mode for detailed visualization showing listeners, rules, and endpoints within each Gateway. ```mermaid graph TB %% GatewayClass at top (cluster-scoped) GC_ocp["GatewayClass: openshift-default
Controller: openshift.io/gateway-controller
Status: Accepted"] %% Per-Gateway subgraph (like per-node in OVN topology) subgraph gw1["Gateway: prod-gateway (10.0.0.50)"] direction TB %% Listener Layer (like ports in OVN) subgraph listeners1["Listeners"] L1_https["HTTPS:443
TLS: terminate"] L1_http["HTTP:80"] end %% Routes attached to this gateway subgraph routes1["Attached Routes"] HR1_api["HTTPRoute: api-route
Host: api.example.com"] HR1_web["HTTPRoute: web-route
Host: www.example.com"] end %% Route Rules with match conditions subgraph rules1["Routing Rules"] R1_1["Rule 0: PathPrefix:/api
Headers: x-version=2"] R1_2["Rule 1: PathPrefix:/"] end %% Backend Services with weights subgraph backends1["Backends"] SVC1_api["api-service:8080
Weight: 80%"] SVC1_api_canary["api-service-canary:8080
Weight: 20%"] SVC1_web["web-service:80"] end %% Pod Endpoints subgraph pods1["Endpoints"] POD1_1["api-pod-abc
10.244.1.5 ready"] POD1_2["api-pod-def
10.244.2.3 ready"] POD1_3["web-pod-xyz
10.244.1.8 ready"] end %% Connections within gateway L1_https --> HR1_api L1_http --> HR1_web HR1_api --> R1_1 HR1_web --> R1_2 R1_1 -->|80%| SVC1_api R1_1 -->|20%| SVC1_api_canary R1_2 --> SVC1_web SVC1_api --> POD1_1 SVC1_api --> POD1_2 SVC1_web --> POD1_3 end %% GatewayClass to Gateway connection GC_ocp --> gw1 %% Styles classDef gatewayclass fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#000 classDef listener fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#000 classDef route fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000 classDef rule fill:#fce4ec,stroke:#c2185b,stroke-width:1px,color:#000 classDef service fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#000 classDef pod fill:#fff9c4,stroke:#f57f17,stroke-width:1px,color:#000 class GC_ocp gatewayclass class L1_https,L1_http listener class HR1_api,HR1_web route class R1_1,R1_2 rule class SVC1_api,SVC1_api_canary,SVC1_web service class POD1_1,POD1_2,POD1_3 pod %% Subgraph Styling style listeners1 fill:#e1f5fe,stroke:#0277bd,stroke-width:2px style routes1 fill:#fff8e1,stroke:#ff8f00,stroke-width:2px style rules1 fill:#fce4ec,stroke:#c2185b,stroke-width:1px,stroke-dasharray: 3 3 style backends1 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px style pods1 fill:#fffde7,stroke:#fbc02d,stroke-width:1px,stroke-dasharray: 3 3 ``` ### Mode 2: Layered Overview (Simple - for clusters with 4+ Gateways) Use this mode for high-level overview when there are many Gateways. ```mermaid graph TB %% Title subgraph title["Gateway API Topology"] direction TB %% Layer 1: GatewayClasses (cluster-scoped) subgraph gc_layer["GatewayClasses"] GC_istio["GatewayClass: istio
Controller: istio.io/gateway-controller
Status: Accepted"] end %% Layer 2: Gateways subgraph gw_layer["Gateways"] GW_api["Gateway: default/api-gateway
Listeners: HTTPS:443, HTTP:80
Address: 10.0.0.50"] end %% Layer 3: Routes subgraph route_layer["Routes"] HR_api["HTTPRoute: default/api-routes
Hostnames: api.example.com"] HR_web["HTTPRoute: default/web-routes
Hostnames: www.example.com"] end %% Layer 4: Backend Services subgraph backend_layer["Backend Services"] SVC_api["Service: default/api-svc
Type: ClusterIP
Ports: 8080→8080/TCP"] SVC_web["Service: default/web-svc
Type: ClusterIP
Ports: 80→80/TCP"] end %% Connections GC_istio -->|implements| GW_api GW_api -->|attaches| HR_api GW_api -->|attaches| HR_web HR_api -->|references| SVC_api HR_web -->|references| SVC_web end %% Styles classDef gatewayclass fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#000 classDef gateway fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#000 classDef route fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000 classDef service fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#000 class GC_istio gatewayclass class GW_api gateway class HR_api,HR_web route class SVC_api,SVC_web service ``` ## Key Requirements 1. **Graph Direction**: Always `graph TB` (top-to-bottom) 2. **Mode Selection**: - **Per-Gateway Subgraphs** (Mode 1): Use when 1-3 Gateways exist - shows detailed listeners, rules, weights, and endpoints - **Layered Overview** (Mode 2): Use when 4+ Gateways exist - shows high-level relationships only 3. **Resource Layers** (top to bottom): - Layer 1: GatewayClasses (cluster-scoped, at top) - Layer 2: Gateways (with Listeners sub-layer in Mode 1) - Layer 3: Routes (HTTPRoute, GRPCRoute, TCPRoute, TLSRoute) - Layer 4: Route Rules (Mode 1 only - with path/header matches) - Layer 5: Backend Services (with weights in Mode 1) - Layer 6: Pod Endpoints (Mode 1 only - with IPs and ready status) 4. **Node Identifiers**: Use unique IDs based on resource type and name: - GatewayClass: `GC_{name}` (e.g., `GC_istio`) - Gateway: `GW_{namespace}_{name}` (e.g., `GW_default_api_gateway`) - Listener: `L{gw_idx}_{protocol}` (e.g., `L1_https`) - HTTPRoute: `HR_{namespace}_{name}` or `HR{gw_idx}_{name}` in Mode 1 - GRPCRoute: `GR_{namespace}_{name}` - TCPRoute: `TR_{namespace}_{name}` - TLSRoute: `TL_{namespace}_{name}` - RouteRule: `R{gw_idx}_{rule_idx}` (e.g., `R1_0`) - Service: `SVC_{namespace}_{name}` or `SVC{gw_idx}_{name}` in Mode 1 - Pod: `POD{gw_idx}_{idx}` (e.g., `POD1_1`) 5. **Node Labels**: Include key information: - GatewayClass: `GatewayClass: {name}
Controller: {controller}
Status: {status}` - Gateway (subgraph title): `Gateway: {name} ({address})` - Listener: `{protocol}:{port}
TLS: {tls_mode}` (if applicable) - HTTPRoute: `HTTPRoute: {name}
Host: {hostname}` - RouteRule: `Rule {idx}: {match_type}:{match_value}
Headers: {headers}` (if applicable) - Service: `{name}:{port}
Weight: {weight}%` (with weight in Mode 1) - Pod: `{pod_name}
{pod_ip} {ready_status}` 6. **Connection Labels**: Use relationship types from `gateway_relationships.txt`: - `implements`: GatewayClass → Gateway - `attaches`: Gateway → Route - `references`: Route → Service (Mode 2) - `has-rule`: HTTPRoute → RouteRule (Mode 1) - `routes-to@{weight}`: RouteRule → Service with weight (Mode 1) - `endpoint@{ready|not-ready}`: Service → Pod (Mode 1) 7. **Colors** (apply using classDef with **color:#000** for black text): - GatewayClasses: `fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#000` (green) - Listeners: `fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#000` (blue) - Gateways: `fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#000` (blue) - Routes (all types): `fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000` (orange) - RouteRules: `fill:#fce4ec,stroke:#c2185b,stroke-width:1px,color:#000` (pink) - Services: `fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#000` (purple) - Pods: `fill:#fff9c4,stroke:#f57f17,stroke-width:1px,color:#000` (yellow) 8. **Subgraph Styling** (apply at END of diagram): - Listeners: `style listeners{idx} fill:#e1f5fe,stroke:#0277bd,stroke-width:2px` - Routes: `style routes{idx} fill:#fff8e1,stroke:#ff8f00,stroke-width:2px` - Rules: `style rules{idx} fill:#fce4ec,stroke:#c2185b,stroke-width:1px,stroke-dasharray: 3 3` - Backends: `style backends{idx} fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px` - Pods: `style pods{idx} fill:#fffde7,stroke:#fbc02d,stroke-width:1px,stroke-dasharray: 3 3` For Mode 2 (layered): - GatewayClass layer: `style gc_layer fill:#f1f8e9,stroke:#558b2f,stroke-width:2px,stroke-dasharray: 5 5` - Gateway layer: `style gw_layer fill:#e1f5fe,stroke:#0277bd,stroke-width:2px,stroke-dasharray: 5 5` - Route layer: `style route_layer fill:#fff8e1,stroke:#ff8f00,stroke-width:2px,stroke-dasharray: 5 5` - Backend layer: `style backend_layer fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,stroke-dasharray: 5 5` ## Cross-Namespace References When routes reference services in different namespaces: 1. Check `reference_grants_detail.txt` for ReferenceGrant allowing the reference 2. Show cross-namespace connections with dashed lines: ```mermaid HR_prod_api -.->|references (cross-ns)| SVC_backend_api ``` 3. Optionally show ReferenceGrant that permits the reference ## Special Cases ### Multiple GatewayClasses If cluster has multiple GatewayClasses (e.g., istio, nginx): - Group Gateways by their GatewayClass - Use different subgraphs or color coding ### No Routes Attached If Gateway has no routes attached: - Still show the Gateway - Add a note: "No routes attached" ### No Gateways Defined If only GatewayClasses exist (no Gateways): - Show only GatewayClasses layer - Add a note: "No Gateways defined" --- # Final Steps 1. **Determine Mode**: Check Gateway count from collected data - 1-3 Gateways → Use Mode 1 (Per-Gateway Subgraphs) with detailed visualization - 4+ Gateways → Use Mode 2 (Layered Overview) for high-level view 2. Generate complete Mermaid diagram following structure above 3. Save to file chosen by user 4. Show summary: ``` ✅ Successfully generated Gateway API topology diagram 📄 Diagram saved to: gateway-topology-diagram.md 📊 Mode: Per-Gateway Subgraphs (detailed view) Summary: - 1 GatewayClass (openshift-default) - 1 Gateway (prod-gateway) - 2 Listeners (HTTP:80, HTTPS:443) - 2 HTTPRoutes (api-route, web-route) - 4 Route Rules with path/header matches - 2 Backend Services - Traffic weights: api-service (80%), api-service-canary (20%) - 2 Pod Endpoints (all ready) - 0 ReferenceGrants 💡 Open the file in your IDE to view the full rendered Mermaid diagram! ``` 5. Clean up temporary directory: ```bash rm -rf "$TMPDIR" ``` 6. Tell user to open file in IDE to view rendered diagram