Skip to content

Commit f5b2520

Browse files
Iceberclaude
andcommitted
refactor: Rename test subcommands and add new diagnostic commands
Replace CRI-O-specific subcommands with generic runtime-agnostic alternatives (runtime-info, pod-info, container-process-stats, container-image). Inline CRI-O storage introspection into container-storage and image-info as auto-detected extensions. Add conmon info display and requireArgN helper for multi-argument commands. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7c4fdf6 commit f5b2520

1 file changed

Lines changed: 164 additions & 66 deletions

File tree

cmd/cray/test.go

Lines changed: 164 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,19 @@ func runTests(args []string) {
7979
fmt.Println(" container-network <id> Show container network")
8080
fmt.Println(" container-storage <id> Show container storage / layers")
8181
fmt.Println(" container-processes <id> Show container processes")
82-
fmt.Println(" crio-container-storage <id> Show CRI-O storage object details")
82+
fmt.Println(" container-process-stats <id> <pid> Show single process stats")
83+
fmt.Println(" container-image <id> Show container's image info")
8384
fmt.Println(" container-all <id> Show all container details")
8485
fmt.Println("\n Images:")
8586
fmt.Println(" list-images List all images")
8687
fmt.Println(" image-info <ref> Show image info")
8788
fmt.Println(" image-config <ref> Show image config")
8889
fmt.Println(" image-layers <ref> [snapshotter] Show image layers")
89-
fmt.Println(" crio-image-storage <ref> Show CRI-O image storage details")
9090
fmt.Println("\n Pods:")
9191
fmt.Println(" list-pods List all pods")
92+
fmt.Println(" pod-info <uid> Show pod details")
9293
fmt.Println("\n Runtime:")
93-
fmt.Println(" crio-store-info Show CRI-O containers/storage profile")
94+
fmt.Println(" runtime-info Show runtime / storage backend info")
9495
os.Exit(1)
9596
}
9697

@@ -138,9 +139,12 @@ func runTests(args []string) {
138139
case "container-processes":
139140
requireArg(args, "container-processes <id>")
140141
containerProcesses(ctx, rt, args[1])
141-
case "crio-container-storage":
142-
requireArg(args, "crio-container-storage <id>")
143-
crioContainerStorage(ctx, rt, args[1])
142+
case "container-process-stats":
143+
requireArgN(args, 3, "container-process-stats <id> <pid>")
144+
containerProcessStatsByPID(ctx, rt, args[1], args[2])
145+
case "container-image":
146+
requireArg(args, "container-image <id>")
147+
containerImage(ctx, rt, args[1])
144148
case "container-all":
145149
requireArg(args, "container-all <id>")
146150
containerAll(ctx, rt, args[1])
@@ -159,13 +163,13 @@ func runTests(args []string) {
159163
snap = args[2]
160164
}
161165
imageLayers(ctx, rt, args[1], snap)
162-
case "crio-image-storage":
163-
requireArg(args, "crio-image-storage <ref>")
164-
crioImageStorage(ctx, rt, args[1])
165166
case "list-pods":
166167
listPods(ctx, rt)
167-
case "crio-store-info":
168-
crioStoreInfo(ctx, rt)
168+
case "pod-info":
169+
requireArg(args, "pod-info <uid>")
170+
podInfo(ctx, rt, args[1])
171+
case "runtime-info":
172+
runtimeInfo(ctx, rt)
169173
default:
170174
fmt.Fprintf(os.Stderr, "Unknown test command: %s\n", command)
171175
os.Exit(1)
@@ -179,6 +183,13 @@ func requireArg(args []string, usage string) {
179183
}
180184
}
181185

186+
func requireArgN(args []string, n int, usage string) {
187+
if len(args) < n {
188+
fmt.Fprintf(os.Stderr, "Usage: cray test %s\n", usage)
189+
os.Exit(1)
190+
}
191+
}
192+
182193
// ---------------------------------------------------------------------------
183194
// Container commands
184195
// ---------------------------------------------------------------------------
@@ -333,6 +344,22 @@ func containerRuntime(ctx context.Context, rt runtime.Runtime, id string) {
333344
fmt.Printf("Sandbox Bundle: %s\n", shim.SandboxBundleDir)
334345
}
335346
}
347+
if conmon := profile.Conmon; conmon != nil {
348+
fmt.Println("\n--- Conmon ---")
349+
fmt.Printf("PID: %d\n", conmon.PID)
350+
if conmon.BinaryPath != "" {
351+
fmt.Printf("Binary: %s\n", conmon.BinaryPath)
352+
}
353+
if len(conmon.Cmdline) > 0 {
354+
fmt.Printf("Cmdline: %s\n", strings.Join(conmon.Cmdline, " "))
355+
}
356+
if conmon.LogDriver != "" {
357+
fmt.Printf("Log Driver: %s\n", conmon.LogDriver)
358+
}
359+
if conmon.LogPath != "" {
360+
fmt.Printf("Log Path: %s\n", conmon.LogPath)
361+
}
362+
}
336363
}
337364

338365
func containerMounts(ctx context.Context, rt runtime.Runtime, id string) {
@@ -448,6 +475,14 @@ func containerStorage(ctx context.Context, rt runtime.Runtime, id string) {
448475
}
449476
}
450477
}
478+
479+
// CRI-O extended storage introspection (auto-detected).
480+
if inspector, ok := c.(runtimecrio.ContainerIntrospector); ok {
481+
crioInfo, err := inspector.CRIOContainerInfo(ctx)
482+
if err == nil {
483+
printCRIOContainerStorage(id, crioInfo)
484+
}
485+
}
451486
}
452487

453488
func containerProcesses(ctx context.Context, rt runtime.Runtime, id string) {
@@ -472,6 +507,35 @@ func containerProcesses(ctx context.Context, rt runtime.Runtime, id string) {
472507
}
473508
}
474509

510+
func containerProcessStatsByPID(ctx context.Context, rt runtime.Runtime, id, pid string) {
511+
c := mustGetContainer(ctx, rt, id)
512+
stats, err := c.GetProcessStats(ctx, pid)
513+
exitOnErr("GetProcessStats", err)
514+
515+
fmt.Printf("=== Process Stats: container=%s pid=%s ===\n", shortID(id), pid)
516+
if stats == nil {
517+
fmt.Println("No stats available.")
518+
return
519+
}
520+
printProcessStats(stats, 0)
521+
}
522+
523+
func containerImage(ctx context.Context, rt runtime.Runtime, id string) {
524+
c := mustGetContainer(ctx, rt, id)
525+
img, err := c.Image(ctx)
526+
exitOnErr("Image", err)
527+
528+
info, err := img.Info(ctx)
529+
exitOnErr("Image.Info", err)
530+
531+
fmt.Printf("=== Container Image: %s ===\n", shortID(id))
532+
fmt.Printf("Ref: %s\n", img.Ref())
533+
fmt.Printf("Name: %s\n", info.Name)
534+
fmt.Printf("Digest: %s\n", info.Digest)
535+
fmt.Printf("Size: %s\n", formatBytes(info.Size))
536+
fmt.Printf("Created: %s\n", info.CreatedAt.Format("2006-01-02 15:04:05"))
537+
}
538+
475539
func containerAll(ctx context.Context, rt runtime.Runtime, id string) {
476540
containerInfo(ctx, rt, id)
477541
fmt.Println()
@@ -487,9 +551,9 @@ func containerAll(ctx context.Context, rt runtime.Runtime, id string) {
487551
fmt.Println()
488552
containerStorage(ctx, rt, id)
489553
fmt.Println()
490-
crioContainerStorage(ctx, rt, id)
491-
fmt.Println()
492554
containerProcesses(ctx, rt, id)
555+
fmt.Println()
556+
containerImage(ctx, rt, id)
493557
}
494558

495559
// ---------------------------------------------------------------------------
@@ -530,6 +594,14 @@ func imageInfo(ctx context.Context, rt runtime.Runtime, ref string) {
530594
fmt.Printf("Digest: %s\n", info.Digest)
531595
fmt.Printf("Size: %s\n", formatBytes(info.Size))
532596
fmt.Printf("Created: %s\n", info.CreatedAt.Format("2006-01-02 15:04:05"))
597+
598+
// CRI-O extended image introspection (auto-detected).
599+
if inspector, ok := img.(runtimecrio.ImageIntrospector); ok {
600+
crioInfo, err := inspector.CRIOImageInfo(ctx)
601+
if err == nil {
602+
printCRIOImageStorage(ref, crioInfo)
603+
}
604+
}
533605
}
534606

535607
func imageConfig(ctx context.Context, rt runtime.Runtime, ref string) {
@@ -583,52 +655,43 @@ func imageLayers(ctx context.Context, rt runtime.Runtime, ref, snapshotter strin
583655
}
584656
}
585657

586-
func crioStoreInfo(ctx context.Context, rt runtime.Runtime) {
587-
inspector, ok := rt.(runtimecrio.StoreIntrospector)
588-
if !ok {
589-
fmt.Println("Current runtime does not expose CRI-O store introspection.")
590-
return
591-
}
592-
info, err := inspector.CRIOStoreInfo(ctx)
593-
exitOnErr("CRI-O store info", err)
594-
595-
fmt.Println("=== CRI-O Store Info ===")
596-
fmt.Printf("Graph Root: %s\n", info.GraphRoot)
597-
fmt.Printf("Run Root: %s\n", info.RunRoot)
598-
fmt.Printf("Image Store: %s\n", emptyDash(info.ImageStore))
599-
fmt.Printf("Driver: %s\n", info.GraphDriverName)
600-
fmt.Printf("Transient Store: %v\n", info.TransientStore)
601-
if len(info.GraphOptions) > 0 {
602-
fmt.Printf("Graph Options: %s\n", strings.Join(info.GraphOptions, ", "))
603-
}
604-
if len(info.PullOptions) > 0 {
605-
fmt.Printf("Pull Options: %s\n", formatStringMap(info.PullOptions))
606-
}
607-
if len(info.AdditionalImageStores) > 0 {
608-
fmt.Printf("Additional Image Stores: %s\n", strings.Join(info.AdditionalImageStores, ", "))
609-
}
610-
if len(info.AdditionalLayerStores) > 0 {
611-
fmt.Printf("Additional Layer Stores: %s\n", strings.Join(info.AdditionalLayerStores, ", "))
612-
}
613-
if len(info.DriverStatus) > 0 {
614-
fmt.Println("\nDriver Status:")
615-
for _, key := range sortedStringKeys(info.DriverStatus) {
616-
fmt.Printf(" %-20s %s\n", key, info.DriverStatus[key])
658+
func runtimeInfo(ctx context.Context, rt runtime.Runtime) {
659+
if inspector, ok := rt.(runtimecrio.StoreIntrospector); ok {
660+
info, err := inspector.CRIOStoreInfo(ctx)
661+
exitOnErr("CRI-O store info", err)
662+
663+
fmt.Println("=== Runtime Info (CRI-O) ===")
664+
fmt.Printf("Graph Root: %s\n", info.GraphRoot)
665+
fmt.Printf("Run Root: %s\n", info.RunRoot)
666+
fmt.Printf("Image Store: %s\n", emptyDash(info.ImageStore))
667+
fmt.Printf("Driver: %s\n", info.GraphDriverName)
668+
fmt.Printf("Transient Store: %v\n", info.TransientStore)
669+
if len(info.GraphOptions) > 0 {
670+
fmt.Printf("Graph Options: %s\n", strings.Join(info.GraphOptions, ", "))
671+
}
672+
if len(info.PullOptions) > 0 {
673+
fmt.Printf("Pull Options: %s\n", formatStringMap(info.PullOptions))
617674
}
675+
if len(info.AdditionalImageStores) > 0 {
676+
fmt.Printf("Additional Image Stores: %s\n", strings.Join(info.AdditionalImageStores, ", "))
677+
}
678+
if len(info.AdditionalLayerStores) > 0 {
679+
fmt.Printf("Additional Layer Stores: %s\n", strings.Join(info.AdditionalLayerStores, ", "))
680+
}
681+
if len(info.DriverStatus) > 0 {
682+
fmt.Println("\nDriver Status:")
683+
for _, key := range sortedStringKeys(info.DriverStatus) {
684+
fmt.Printf(" %-20s %s\n", key, info.DriverStatus[key])
685+
}
686+
}
687+
} else {
688+
fmt.Println("=== Runtime Info ===")
689+
fmt.Println("No extended runtime introspection available for current backend.")
618690
}
619691
}
620692

621-
func crioContainerStorage(ctx context.Context, rt runtime.Runtime, id string) {
622-
c := mustGetContainer(ctx, rt, id)
623-
inspector, ok := c.(runtimecrio.ContainerIntrospector)
624-
if !ok {
625-
fmt.Println("Container does not expose CRI-O storage introspection.")
626-
return
627-
}
628-
info, err := inspector.CRIOContainerInfo(ctx)
629-
exitOnErr("CRI-O container storage", err)
630-
631-
fmt.Printf("=== CRI-O Container Storage: %s ===\n", shortID(id))
693+
func printCRIOContainerStorage(id string, info *runtimecrio.ContainerInfo) {
694+
fmt.Printf("\n--- CRI-O Container Storage ---\n")
632695
fmt.Printf("Storage ID: %s\n", info.ID)
633696
fmt.Printf("Names: %s\n", joinOrDash(info.Names))
634697
fmt.Printf("Image ID: %s\n", emptyDash(info.ImageID))
@@ -682,17 +745,8 @@ func crioContainerStorage(ctx context.Context, rt runtime.Runtime, id string) {
682745
}
683746
}
684747

685-
func crioImageStorage(ctx context.Context, rt runtime.Runtime, ref string) {
686-
img := mustGetImage(ctx, rt, ref)
687-
inspector, ok := img.(runtimecrio.ImageIntrospector)
688-
if !ok {
689-
fmt.Println("Image does not expose CRI-O storage introspection.")
690-
return
691-
}
692-
info, err := inspector.CRIOImageInfo(ctx)
693-
exitOnErr("CRI-O image storage", err)
694-
695-
fmt.Printf("=== CRI-O Image Storage: %s ===\n", ref)
748+
func printCRIOImageStorage(ref string, info *runtimecrio.ImageInfo) {
749+
fmt.Printf("\n--- CRI-O Image Storage ---\n")
696750
fmt.Printf("Storage ID: %s\n", info.ID)
697751
fmt.Printf("Names: %s\n", joinOrDash(info.Names))
698752
if len(info.NamesHistory) > 0 {
@@ -894,6 +948,50 @@ func listPods(ctx context.Context, rt runtime.Runtime) {
894948
}
895949
}
896950

951+
func podInfo(ctx context.Context, rt runtime.Runtime, uid string) {
952+
pods, err := rt.ListPods(ctx)
953+
exitOnErr("ListPods", err)
954+
955+
var target runtime.Pod
956+
for _, pod := range pods {
957+
if pod.UID() == uid {
958+
target = pod
959+
break
960+
}
961+
}
962+
if target == nil {
963+
fmt.Fprintf(os.Stderr, "Pod not found: %s\n", uid)
964+
os.Exit(1)
965+
}
966+
967+
info, err := target.Info(ctx)
968+
exitOnErr("Pod.Info", err)
969+
970+
fmt.Printf("=== Pod Info: %s ===\n", uid)
971+
fmt.Printf("Name: %s\n", info.Name)
972+
fmt.Printf("Namespace: %s\n", info.Namespace)
973+
fmt.Printf("UID: %s\n", info.UID)
974+
975+
containers, err := target.Containers(ctx)
976+
exitOnErr("Pod.Containers", err)
977+
978+
fmt.Printf("Containers: %d\n\n", len(containers))
979+
for i, c := range containers {
980+
cInfo, err := c.Info(ctx)
981+
if err != nil {
982+
fmt.Printf("[%d] %s (info error: %v)\n", i+1, c.ID(), err)
983+
continue
984+
}
985+
fmt.Printf("[%d] Container:\n", i+1)
986+
fmt.Printf(" ID: %s\n", shortID(cInfo.ID))
987+
fmt.Printf(" Name: %s\n", cInfo.Name)
988+
fmt.Printf(" Image: %s\n", cInfo.Image)
989+
fmt.Printf(" Status: %s\n", cInfo.Status)
990+
fmt.Printf(" PID: %d\n", cInfo.PID)
991+
fmt.Println()
992+
}
993+
}
994+
897995
// ---------------------------------------------------------------------------
898996
// Helpers
899997
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)