From ec971ddbfa22ce065f0dbd5016c6a624f990eb7d Mon Sep 17 00:00:00 2001 From: Exar04 Date: Thu, 23 Apr 2026 22:57:45 +0530 Subject: [PATCH] feat:namespace:inspect inspect namespace now gives info of containers in that namespace Signed-off-by: Exar04 --- cmd/nerdctl/namespace/namespace_test.go | 85 +++++++++++++++++++++++++ pkg/cmd/namespace/inspect.go | 23 ++++++- pkg/inspecttypes/native/namespace.go | 5 +- 3 files changed, 109 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/namespace/namespace_test.go b/cmd/nerdctl/namespace/namespace_test.go index bad2c633371..e1273d87a39 100644 --- a/cmd/nerdctl/namespace/namespace_test.go +++ b/cmd/nerdctl/namespace/namespace_test.go @@ -17,11 +17,96 @@ package namespace import ( + "encoding/json" "testing" + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/mod/tigron/test" + "github.com/containerd/nerdctl/mod/tigron/tig" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestMain(m *testing.M) { testutil.M(m) } + +// TestNamespaceInspect verifies that `nerdctl namespace inspect ` +// returns correctly populated JSON for a namespace. +func TestNamespaceInspect(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "namespace inspect returns populated metadata for a namespace", + + Setup: func(data test.Data, helpers test.Helpers) { + ns := data.Identifier() + + helpers.Ensure("namespace", "create", ns) + + helpers.Ensure("--namespace", ns, "run", "-d", "--name", "test-cnt", testutil.CommonImage, "sleep", "3600") + + helpers.Ensure("--namespace", ns, "ps", "-a") + }, + + Cleanup: func(data test.Data, helpers test.Helpers) { + ns := data.Identifier() + helpers.Anyhow("--namespace", ns, "rm", "-f", "test-cnt") + helpers.Anyhow("--namespace", ns, "rmi", "-f", testutil.CommonImage) + helpers.Anyhow("namespace", "remove", ns) + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("namespace", "inspect", "--format", "json", data.Identifier()) + }, + + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, t tig.T) { + type NamespaceResult struct { + Name string `json:"Name"` + Containers []struct { + ID string `json:"id"` + Name string `json:"name"` + Image string `json:"image"` + } `json:"Containers"` + } + + var results []NamespaceResult + + err := json.Unmarshal([]byte(stdout), &results) + if err != nil { + var single NamespaceResult + if errObj := json.Unmarshal([]byte(stdout), &single); errObj == nil { + results = []NamespaceResult{single} + } else { + assert.NilError(t, err, "CLI output is neither a JSON array nor a valid object: %s", stdout) + } + } + + assert.Assert(t, len(results) > 0, "Expected at least one namespace result") + + var target *NamespaceResult + for i := range results { + if results[i].Name == data.Identifier() { + target = &results[i] + break + } + } + + assert.Assert(t, target != nil, "Namespace %s not found in results", data.Identifier()) + + assert.Assert(t, len(target.Containers) > 0, "Containers list should not be empty for namespace %s", target.Name) + + c := target.Containers[0] + assert.Assert(t, c.ID != "", "Container ID should not be empty") + assert.Equal(t, c.Image, testutil.CommonImage, "Image mismatch") + }, + } + }, + } + + testCase.Run(t) +} diff --git a/pkg/cmd/namespace/inspect.go b/pkg/cmd/namespace/inspect.go index ebe327da3d0..7239f319890 100644 --- a/pkg/cmd/namespace/inspect.go +++ b/pkg/cmd/namespace/inspect.go @@ -43,9 +43,28 @@ func Inspect(ctx context.Context, client *containerd.Client, inspectedNamespaces if err != nil { return err } + containers, err := client.Containers(ctx) + if err != nil { + return err + } + var containersList []map[string]string + for _, container := range containers { + containerInfo, err := container.Info(ctx) + if err != nil { + return err + } + containersList = append(containersList, + map[string]string{ + "id": containerInfo.ID, + "name": containerInfo.Runtime.Name, + "image": containerInfo.Image, + }, + ) + } nsInspect := native.Namespace{ - Name: ns, - Labels: &labels, + Name: ns, + Labels: &labels, + Containers: containersList, } result = append(result, nsInspect) } diff --git a/pkg/inspecttypes/native/namespace.go b/pkg/inspecttypes/native/namespace.go index 4e66a4d45d4..76e0001b1b4 100644 --- a/pkg/inspecttypes/native/namespace.go +++ b/pkg/inspecttypes/native/namespace.go @@ -17,6 +17,7 @@ package native type Namespace struct { - Name string `json:"Name"` - Labels *map[string]string `json:"Labels,omitempty"` + Name string `json:"Name"` + Labels *map[string]string `json:"Labels,omitempty"` + Containers []map[string]string `json:"Containers,omitempty"` }