From 87a83e14b0554fb395f0f55b16acde014487c00a Mon Sep 17 00:00:00 2001 From: Crazykev Date: Wed, 26 Oct 2016 19:23:53 +0800 Subject: [PATCH 1/4] return pod metadata in container list and status APIs Signed-off-by: Crazykev --- oci/oci.go | 10 +++++++++- server/container.go | 16 +++++++++++++--- server/sandbox.go | 12 ++++++++++-- server/server.go | 14 ++++++++++++-- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/oci/oci.go b/oci/oci.go index fb4db197..0ce2fa36 100644 --- a/oci/oci.go +++ b/oci/oci.go @@ -19,6 +19,7 @@ import ( "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sys/unix" "k8s.io/kubernetes/pkg/fields" + pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" ) const ( @@ -228,6 +229,7 @@ type Container struct { sandbox string terminal bool state *ContainerState + metadata *pb.ContainerMetadata stateLock sync.Mutex } @@ -241,7 +243,7 @@ type ContainerState struct { } // NewContainer creates a container object. -func NewContainer(id string, name string, bundlePath string, logPath string, labels map[string]string, sandbox string, terminal bool) (*Container, error) { +func NewContainer(id string, name string, bundlePath string, logPath string, labels map[string]string, metadata *pb.ContainerMetadata, sandbox string, terminal bool) (*Container, error) { c := &Container{ id: id, name: name, @@ -250,6 +252,7 @@ func NewContainer(id string, name string, bundlePath string, logPath string, lab labels: labels, sandbox: sandbox, terminal: terminal, + metadata: metadata, } return c, nil } @@ -292,6 +295,11 @@ func (c *Container) NetNsPath() (string, error) { return fmt.Sprintf("/proc/%d/ns/net", c.state.Pid), nil } +// Metadata returns the metadata of the container. +func (c *Container) Metadata() *pb.ContainerMetadata { + return c.metadata +} + // newPipe creates a unix socket pair for communication func newPipe() (parent *os.File, child *os.File, err error) { fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) diff --git a/server/container.go b/server/container.go index 1cd2a742..43dc3ecd 100644 --- a/server/container.go +++ b/server/container.go @@ -205,6 +205,8 @@ func (s *Server) createSandboxContainer(containerID string, containerName string labels := containerConfig.GetLabels() + metadata := containerConfig.GetMetadata() + annotations := containerConfig.GetAnnotations() if annotations != nil { for k, v := range annotations { @@ -312,11 +314,17 @@ func (s *Server) createSandboxContainer(containerID string, containerName string specgen.AddAnnotation("ocid/sandbox_id", sb.id) specgen.AddAnnotation("ocid/log_path", logPath) specgen.AddAnnotation("ocid/tty", fmt.Sprintf("%v", containerConfig.GetTty())) + + metadataJSON, err := json.Marshal(metadata) + if err != nil { + return nil, err + } + specgen.AddAnnotation("ocid/metadata", string(metadataJSON)) + labelsJSON, err := json.Marshal(labels) if err != nil { return nil, err } - specgen.AddAnnotation("ocid/labels", string(labelsJSON)) if err = specgen.SaveToFile(filepath.Join(containerDir, "config.json")); err != nil { @@ -339,7 +347,7 @@ func (s *Server) createSandboxContainer(containerID string, containerName string return nil, err } - container, err := oci.NewContainer(containerID, containerName, containerDir, logPath, labels, sb.id, containerConfig.GetTty()) + container, err := oci.NewContainer(containerID, containerName, containerDir, logPath, labels, metadata, sb.id, containerConfig.GetTty()) if err != nil { return nil, err } @@ -491,6 +499,7 @@ func (s *Server) ListContainers(ctx context.Context, req *pb.ListContainersReque PodSandboxId: &podSandboxID, CreatedAt: int64Ptr(created), Labels: ctr.Labels(), + Metadata: ctr.Metadata(), } switch cState.Status { @@ -531,7 +540,8 @@ func (s *Server) ContainerStatus(ctx context.Context, req *pb.ContainerStatusReq containerID := c.ID() resp := &pb.ContainerStatusResponse{ Status: &pb.ContainerStatus{ - Id: &containerID, + Id: &containerID, + Metadata: c.Metadata(), }, } diff --git a/server/sandbox.go b/server/sandbox.go index 0eafe97f..98c71d5e 100644 --- a/server/sandbox.go +++ b/server/sandbox.go @@ -175,6 +175,13 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest g.AddBindMount(resolvPath, "/etc/resolv.conf", "ro") + // add metadata + metadata := req.GetConfig().GetMetadata() + metadataJSON, err := json.Marshal(metadata) + if err != nil { + return nil, err + } + // add labels labels := req.GetConfig().GetLabels() labelsJSON, err := json.Marshal(labels) @@ -221,6 +228,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest } }() + g.AddAnnotation("ocid/metadata", string(metadataJSON)) g.AddAnnotation("ocid/labels", string(labelsJSON)) g.AddAnnotation("ocid/annotations", string(annotationsJSON)) g.AddAnnotation("ocid/log_path", logDir) @@ -237,7 +245,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest containers: oci.NewMemoryStore(), processLabel: processLabel, mountLabel: mountLabel, - metadata: req.GetConfig().GetMetadata(), + metadata: metadata, } s.addSandbox(sb) @@ -290,7 +298,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest } } - container, err := oci.NewContainer(containerID, containerName, podSandboxDir, podSandboxDir, labels, id, false) + container, err := oci.NewContainer(containerID, containerName, podSandboxDir, podSandboxDir, labels, nil, id, false) if err != nil { return nil, err } diff --git a/server/server.go b/server/server.go index 1fa57250..b16755b6 100644 --- a/server/server.go +++ b/server/server.go @@ -16,6 +16,7 @@ import ( "github.com/opencontainers/runc/libcontainer/label" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/rajatchopra/ocicni" + pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" ) const ( @@ -53,6 +54,10 @@ func (s *Server) loadContainer(id string) error { if err != nil { return err } + var metadata pb.ContainerMetadata + if err = json.Unmarshal([]byte(m.Annotations["ocid/metadata"]), &metadata); err != nil { + return err + } sb := s.getSandbox(m.Annotations["ocid/sandbox_id"]) if sb == nil { logrus.Warnf("could not get sandbox with id %s, skipping", m.Annotations["ocid/sandbox_id"]) @@ -65,7 +70,7 @@ func (s *Server) loadContainer(id string) error { } containerPath := filepath.Join(s.runtime.ContainerDir(), id) - ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations["ocid/log_path"], labels, sb.id, tty) + ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations["ocid/log_path"], labels, &metadata, sb.id, tty) if err != nil { return err } @@ -97,6 +102,10 @@ func (s *Server) loadSandbox(id string) error { if err != nil { return err } + var metadata pb.PodSandboxMetadata + if err = json.Unmarshal([]byte(m.Annotations["ocid/metadata"]), &metadata); err != nil { + return err + } processLabel, mountLabel, err := label.InitLabels(label.DupSecOpt(m.Process.SelinuxLabel)) if err != nil { @@ -117,6 +126,7 @@ func (s *Server) loadSandbox(id string) error { processLabel: processLabel, mountLabel: mountLabel, annotations: annotations, + metadata: &metadata, } s.addSandbox(sb) @@ -130,7 +140,7 @@ func (s *Server) loadSandbox(id string) error { if err != nil { return err } - scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], cname, sandboxPath, sandboxPath, labels, id, false) + scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], cname, sandboxPath, sandboxPath, labels, nil, id, false) if err != nil { return err } From ca59eaf1a43e1bf754d0301f5a9534917149aaae Mon Sep 17 00:00:00 2001 From: Crazykev Date: Wed, 26 Oct 2016 19:32:59 +0800 Subject: [PATCH 2/4] display container metadata on the client for container list and status Signed-off-by: Crazykev --- cmd/client/container.go | 17 +++++++++++++++++ cmd/client/sandbox.go | 1 + 2 files changed, 18 insertions(+) diff --git a/cmd/client/container.go b/cmd/client/container.go index ac10c570..a738195a 100644 --- a/cmd/client/container.go +++ b/cmd/client/container.go @@ -364,6 +364,14 @@ func ContainerStatus(client pb.RuntimeServiceClient, ID string) error { return err } fmt.Printf("ID: %s\n", *r.Status.Id) + if r.Status.Metadata != nil { + if r.Status.Metadata.Name != nil { + fmt.Printf("Name: %s\n", *r.Status.Metadata.Name) + } + if r.Status.Metadata.Attempt != nil { + fmt.Printf("Attempt: %v\n", *r.Status.Metadata.Attempt) + } + } if r.Status.State != nil { fmt.Printf("Status: %s\n", r.Status.State) } @@ -428,6 +436,14 @@ func ListContainers(client pb.RuntimeServiceClient, opts listOptions) error { } fmt.Printf("ID: %s\n", *c.Id) fmt.Printf("Pod: %s\n", *c.PodSandboxId) + if c.Metadata != nil { + if c.Metadata.Name != nil { + fmt.Printf("Name: %s\n", *c.Metadata.Name) + } + if c.Metadata.Attempt != nil { + fmt.Printf("Attempt: %v\n", *c.Metadata.Attempt) + } + } if c.State != nil { fmt.Printf("Status: %s\n", *c.State) } @@ -447,6 +463,7 @@ func ListContainers(client pb.RuntimeServiceClient, opts listOptions) error { fmt.Printf("\t%s -> %s\n", k, v) } } + fmt.Println() } return nil } diff --git a/cmd/client/sandbox.go b/cmd/client/sandbox.go index 7722a2b7..feef50d5 100644 --- a/cmd/client/sandbox.go +++ b/cmd/client/sandbox.go @@ -379,6 +379,7 @@ func ListPodSandboxes(client pb.RuntimeServiceClient, opts listOptions) error { fmt.Printf("\t%s -> %s\n", k, v) } } + fmt.Println() } return nil } From 018c4db06d9edc6ee4f605af5f0173b95806621e Mon Sep 17 00:00:00 2001 From: HaoZhang Date: Thu, 27 Oct 2016 14:24:27 +0800 Subject: [PATCH 3/4] add test for container/pod metadata in status/list APIs Signed-off-by: HaoZhang --- test/ctr.bats | 35 +++++++++++++++++++++++++ test/pod.bats | 36 +++++++++++++++++++++++++- test/restore.bats | 40 +++++++++++++++++++++++++++++ test/testdata/container_config.json | 3 ++- test/testdata/sandbox_config.json | 5 +++- 5 files changed, 116 insertions(+), 3 deletions(-) diff --git a/test/ctr.bats b/test/ctr.bats index f6101988..4b435934 100644 --- a/test/ctr.bats +++ b/test/ctr.bats @@ -292,3 +292,38 @@ function teardown() { cleanup_pods stop_ocid } + +@test "ctr metadata in list & status" { + # this test requires docker, thus it can't yet be run in a container + if [ "$TRAVIS" = "true" ]; then # instead of $TRAVIS, add a function is_containerized to skip here + skip "cannot yet run this test in a container, use sudo make localintegration" + fi + + start_ocid + run ocic pod create --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run ocic ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + + run ocic ctr list --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + # TODO: expected value should not hard coded here + [[ "$output" =~ "Name: container1" ]] + [[ "$output" =~ "Attempt: 1" ]] + + run ocic ctr status --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + # TODO: expected value should not hard coded here + [[ "$output" =~ "Name: container1" ]] + [[ "$output" =~ "Attempt: 1" ]] + + cleanup_ctrs + cleanup_pods + stop_ocid +} diff --git a/test/pod.bats b/test/pod.bats index d266d402..a62ceac2 100644 --- a/test/pod.bats +++ b/test/pod.bats @@ -152,4 +152,38 @@ function teardown() { [ "$status" -eq 0 ] cleanup_pods stop_ocid -} \ No newline at end of file +} + +@test "pod metadata in list & status" { + # this test requires docker, thus it can't yet be run in a container + if [ "$TRAVIS" = "true" ]; then # instead of $TRAVIS, add a function is_containerized to skip here + skip "cannot yet run this test in a container, use sudo make localintegration" + fi + + start_ocid + run ocic pod create --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + + run ocic pod list --id "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + # TODO: expected value should not hard coded here + [[ "$output" =~ "Name: podsandbox1" ]] + [[ "$output" =~ "UID: redhat-test-ocid" ]] + [[ "$output" =~ "Namespace: redhat.test.ocid" ]] + [[ "$output" =~ "Attempt: 1" ]] + + run ocic pod status --id "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + # TODO: expected value should not hard coded here + [[ "$output" =~ "Name: podsandbox1" ]] + [[ "$output" =~ "UID: redhat-test-ocid" ]] + [[ "$output" =~ "Namespace: redhat.test.ocid" ]] + [[ "$output" =~ "Attempt: 1" ]] + + cleanup_pods + stop_ocid +} diff --git a/test/restore.bats b/test/restore.bats index b3950a9a..d6dcd16e 100644 --- a/test/restore.bats +++ b/test/restore.bats @@ -18,11 +18,31 @@ function teardown() { [ "$status" -eq 0 ] pod_id="$output" + run ocic pod list --id "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + pod_list_info="$output" + + run ocic pod status --id "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + pod_status_info="$output" + run ocic ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" echo "$output" [ "$status" -eq 0 ] ctr_id="$output" + run ocic ctr list --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_list_info="$output" + + run ocic ctr status --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_status_info="$output" + stop_ocid start_ocid @@ -32,12 +52,32 @@ function teardown() { [[ "${output}" != "" ]] [[ "${output}" =~ "${pod_id}" ]] + run ocic pod list --id "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + [[ "${output}" == "${pod_list_info}" ]] + + run ocic pod status --id "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + [[ "${output}" == "${pod_status_info}" ]] + run ocic ctr list echo "$output" [ "$status" -eq 0 ] [[ "${output}" != "" ]] [[ "${output}" =~ "${pod_id}" ]] + run ocic ctr list --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + [[ "${output}" == "${ctr_list_info}" ]] + + run ocic ctr status --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + [[ "${output}" == "${ctr_status_info}" ]] + cleanup_ctrs cleanup_pods stop_ocid diff --git a/test/testdata/container_config.json b/test/testdata/container_config.json index 4b28cf7c..d1a83698 100644 --- a/test/testdata/container_config.json +++ b/test/testdata/container_config.json @@ -1,6 +1,7 @@ { "metadata": { - "name": "container1" + "name": "container1", + "attempt": 1 }, "image": { "image": "docker://redis:latest" diff --git a/test/testdata/sandbox_config.json b/test/testdata/sandbox_config.json index 6e39966d..d1acda59 100644 --- a/test/testdata/sandbox_config.json +++ b/test/testdata/sandbox_config.json @@ -1,6 +1,9 @@ { "metadata": { - "name": "podsandbox1" + "name": "podsandbox1", + "uid": "redhat-test-ocid", + "namespace": "redhat.test.ocid", + "attempt": 1 }, "hostname": "ocic_host", "log_directory": ".", From 295c32331ad2fefbf8fd599436102d0f5c56a9e8 Mon Sep 17 00:00:00 2001 From: Crazykev Date: Wed, 2 Nov 2016 14:36:42 +0800 Subject: [PATCH 4/4] sort all map type result in ocic Signed-off-by: Crazykev --- cmd/client/container.go | 8 ++++---- cmd/client/sandbox.go | 27 +++++++++++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/cmd/client/container.go b/cmd/client/container.go index a738195a..c70388b9 100644 --- a/cmd/client/container.go +++ b/cmd/client/container.go @@ -453,14 +453,14 @@ func ListContainers(client pb.RuntimeServiceClient, opts listOptions) error { } if c.Labels != nil { fmt.Println("Labels:") - for k, v := range c.Labels { - fmt.Printf("\t%s -> %s\n", k, v) + for _, k := range getSortedKeys(c.Labels) { + fmt.Printf("\t%s -> %s\n", k, c.Labels[k]) } } if c.Annotations != nil { fmt.Println("Annotations:") - for k, v := range c.Annotations { - fmt.Printf("\t%s -> %s\n", k, v) + for _, k := range getSortedKeys(c.Annotations) { + fmt.Printf("\t%s -> %s\n", k, c.Annotations[k]) } } fmt.Println() diff --git a/cmd/client/sandbox.go b/cmd/client/sandbox.go index feef50d5..0e547281 100644 --- a/cmd/client/sandbox.go +++ b/cmd/client/sandbox.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "sort" "strings" "time" @@ -302,14 +303,14 @@ func PodSandboxStatus(client pb.RuntimeServiceClient, ID string) error { } if r.Status.Labels != nil { fmt.Println("Labels:") - for k, v := range r.Status.Labels { - fmt.Printf("\t%s -> %s\n", k, v) + for _, k := range getSortedKeys(r.Status.Labels) { + fmt.Printf("\t%s -> %s\n", k, r.Status.Labels[k]) } } if r.Status.Annotations != nil { fmt.Println("Annotations:") - for k, v := range r.Status.Annotations { - fmt.Printf("\t%s -> %s\n", k, v) + for _, k := range getSortedKeys(r.Status.Annotations) { + fmt.Printf("\t%s -> %s\n", k, r.Status.Annotations[k]) } } return nil @@ -369,17 +370,27 @@ func ListPodSandboxes(client pb.RuntimeServiceClient, opts listOptions) error { fmt.Printf("Created: %v\n", ctm) if pod.Labels != nil { fmt.Println("Labels:") - for k, v := range pod.Labels { - fmt.Printf("\t%s -> %s\n", k, v) + for _, k := range getSortedKeys(pod.Labels) { + fmt.Printf("\t%s -> %s\n", k, pod.Labels[k]) } } if pod.Annotations != nil { fmt.Println("Annotations:") - for k, v := range pod.Annotations { - fmt.Printf("\t%s -> %s\n", k, v) + for _, k := range getSortedKeys(pod.Annotations) { + fmt.Printf("\t%s -> %s\n", k, pod.Annotations[k]) } } fmt.Println() } return nil } + +func getSortedKeys(m map[string]string) []string { + var keys []string + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + + return keys +}