Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE)

<p align="center">
<img src="docs/assets/image-pull-demo.en.gif" alt="Topology viewer showing an ImagePullBackOff diagnostic graph" width="100%">
<img src="docs/assets/kind-helm-storage-demo.en.gif" alt="Topology viewer showing a kind Helm storage topology graph" width="100%">
</p>
<p align="center">
<sub>Real topology viewer capture: a Pod diagnostic graph with workload, service, config, identity/RBAC, image, and event evidence.</sub>
<sub>Real topology viewer capture: a kind-style Helm workload graph with Service, config, identity/RBAC, PVC, PV, StorageClass, CSI driver, provisioner, Node, and Event evidence.</sub>
</p>

`kubernetes-ontology` is a read-only Kubernetes topology service for
Expand Down
4 changes: 2 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
[English](README.md) | [中文说明](README.zh-CN.md)

<p align="center">
<img src="docs/assets/image-pull-demo.gif" alt="Topology viewer 展示 ImagePullBackOff 诊断图" width="100%">
<img src="docs/assets/kind-helm-storage-demo.gif" alt="Topology viewer 展示 kind Helm 存储拓扑诊断图" width="100%">
</p>
<p align="center">
<sub>真实 viewer 页面捕获:从一个故障 Pod 展开 workloadService、配置、身份/RBAC、镜像和 Event 证据。</sub>
<sub>真实 viewer 页面捕获:kind 风格 Helm workloadService、配置、身份/RBAC、PVC、PV、StorageClass、CSI Driver、provisioner、Node 和 Event 证据同屏展开。</sub>
</p>

`kubernetes-ontology` 是一个只读的 Kubernetes 拓扑和诊断服务。它从
Expand Down
7 changes: 7 additions & 0 deletions cmd/kubernetes-ontology-viewer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/":
h.serveIndex(w)
case "/vendor/cytoscape.min.js":
h.serveCytoscape(w)
case "/topology":
h.serveTopology(w, r)
case "/diagnostic":
Expand All @@ -114,6 +116,11 @@ func (h *handler) serveIndex(w http.ResponseWriter) {
_, _ = io.WriteString(w, body)
}

func (h *handler) serveCytoscape(w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
_, _ = io.WriteString(w, visualize.CytoscapeJS)
}

func (h *handler) serveTopology(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
server := first(q, "server", h.defaultServer)
Expand Down
45 changes: 45 additions & 0 deletions cmd/kubernetes-ontology-viewer/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,58 @@ package main

import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
)

func TestServeIndexIncludesProfessionalRenderer(t *testing.T) {
viewer := httptest.NewServer(newHandler("http://kubernetes-ontology:18080", time.Second))
defer viewer.Close()

resp, err := http.Get(viewer.URL + "/")
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
text := string(body)
if !strings.Contains(text, "/vendor/cytoscape.min.js") || !strings.Contains(text, "Professional renderer") {
t.Fatalf("expected professional renderer assets in index")
}
if !strings.Contains(text, `value="http://kubernetes-ontology:18080"`) {
t.Fatalf("expected default ontology server to be injected")
}
}

func TestServeCytoscapeAsset(t *testing.T) {
viewer := httptest.NewServer(newHandler("http://kubernetes-ontology:18080", time.Second))
defer viewer.Close()

resp, err := http.Get(viewer.URL + "/vendor/cytoscape.min.js")
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if contentType := resp.Header.Get("Content-Type"); !strings.Contains(contentType, "application/javascript") {
t.Fatalf("expected javascript content type, got %q", contentType)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(body[:min(len(body), 300)]), "Cytoscape") {
t.Fatalf("expected cytoscape asset body")
}
}

func TestServeDiagnosticForwardsRecipeAndBudgets(t *testing.T) {
var got url.Values
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
Binary file added docs/assets/kind-helm-storage-demo.en.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/kind-helm-storage-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta name="description" content="kubernetes-ontology turns Kubernetes objects into a read-only evidence graph for diagnostics, topology exploration, and AI-agent workflows.">
<meta property="og:title" content="kubernetes-ontology">
<meta property="og:description" content="A read-only Kubernetes topology service for diagnostics, graph exploration, and AI-agent workflows.">
<meta property="og:image" content="/docs/assets/image-pull-demo.en.gif">
<meta property="og:image" content="/docs/assets/kind-helm-storage-demo.en.gif">
<meta name="theme-color" content="#05070a">
<style>
:root {
Expand Down Expand Up @@ -681,7 +681,7 @@
</nav>

<header id="top" class="hero">
<img class="hero-media" src="/docs/assets/image-pull-demo.en.gif" alt="kubernetes-ontology topology viewer showing a diagnostic graph">
<img class="hero-media" src="/docs/assets/kind-helm-storage-demo.en.gif" alt="kubernetes-ontology topology viewer showing a kind Helm storage graph">
<div class="hero-inner">
<div class="eyebrow">Read-only Kubernetes evidence graph</div>
<h1>kubernetes-<br class="mobile-break">ontology</h1>
Expand Down Expand Up @@ -858,9 +858,9 @@ <h2>Run it as a local diagnostic companion or install it in-cluster with Helm.</

<section class="viewer-band" aria-label="Topology viewer preview">
<div class="viewer-frame">
<img src="/docs/assets/image-pull-demo.en.gif" alt="Topology viewer graph with diagnostic signals">
<img src="/docs/assets/kind-helm-storage-demo.en.gif" alt="Topology viewer graph with Helm, PVC, PV, StorageClass, and CSI signals">
<div class="viewer-caption">
<p>Real viewer capture: an ImagePullBackOff diagnostic graph with workload, service, config, identity, image, event, and storage evidence in one place.</p>
<p>Real viewer capture: a kind-style Helm workload graph with Service, config, identity, PVC, PV, StorageClass, CSIDriver, provisioner, Node, and Event evidence in one place.</p>
<a class="button" href="https://github.com/Colvin-Y/kubernetes-ontology/blob/main/QUICKSTART.md#topology-viewer">Open viewer guide</a>
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Available samples:

- `image-pull-demo/`: a synthetic ImagePullBackOff diagnostic demo with
Kubernetes manifests, an offline viewer graph, and a Chinese walkthrough.
- `kind-helm-storage-demo/`: a kind-focused Helm workload sample with a
deterministic topology fixture covering PVC, PV, StorageClass, CSIDriver, and
local-path provisioner evidence.
- `helm-upgrade-failure/`: a synthetic Incident Context Pack v1 fixture for a
Helm upgrade failure that reached Kubernetes when Helm CLI output is missing.

Expand Down
Loading
Loading