Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: we should get a container's execids from inspect #2699

Merged
merged 1 commit into from
Jan 30, 2019
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
1 change: 1 addition & 0 deletions apis/server/container_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (s *Server) getContainer(ctx context.Context, rw http.ResponseWriter, req *
Driver: c.Driver,
MountLabel: c.MountLabel,
ProcessLabel: c.ProcessLabel,
ExecIds: c.ExecIds,
}

return EncodeResponse(rw, http.StatusOK, container)
Expand Down
20 changes: 19 additions & 1 deletion daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,24 @@ func (mgr *ContainerManager) Get(ctx context.Context, name string) (*Container,
if err != nil {
return nil, err
}
cID := c.Key()

// get all execids belongs to this container
fn := func(v interface{}) bool {
execConfig, ok := v.(*ContainerExecConfig)
if !ok || execConfig.ContainerID != cID {
return false
}

return true
}

var execIDs []string
execProcesses := mgr.ExecProcesses.Values(fn)
for k := range execProcesses {
execIDs = append(execIDs, k)
}
c.ExecIds = execIDs

return c, nil
}
Expand Down Expand Up @@ -1914,7 +1932,7 @@ func (mgr *ContainerManager) setBaseFS(ctx context.Context, c *Container) {
// execProcessGC cleans unused exec processes config every 5 minutes.
func (mgr *ContainerManager) execProcessGC() {
for range time.Tick(time.Duration(GCExecProcessTick) * time.Minute) {
execProcesses := mgr.ExecProcesses.Values()
execProcesses := mgr.ExecProcesses.Values(nil)
cleaned := 0

for id, v := range execProcesses {
Expand Down
2 changes: 1 addition & 1 deletion daemon/mgr/container_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ type Container struct {
Driver string `json:"Driver,omitempty"`

// exec ids
ExecIds string `json:"ExecIDs,omitempty"`
ExecIds []string `json:"ExecIDs,omitempty"`

// Snapshotter, GraphDriver is same, keep both
// just for compatibility
Expand Down
9 changes: 7 additions & 2 deletions pkg/collect/safe_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ type SafeMap struct {
inner map[string]interface{}
}

// ValueFilter defines a function to filter values in map
type ValueFilter func(interface{}) bool

// NewSafeMap generates a instance of SafeMap type.
func NewSafeMap() *SafeMap {
return &SafeMap{
Expand All @@ -26,13 +29,15 @@ func (m *SafeMap) Get(k string) *Value {
}

// Values returns all key-values stored in map
func (m *SafeMap) Values() map[string]interface{} {
func (m *SafeMap) Values(filter ValueFilter) map[string]interface{} {
m.RLock()
defer m.RUnlock()

nmap := make(map[string]interface{})
for k, v := range m.inner {
nmap[k] = v
if filter == nil || filter(v) {
nmap[k] = v
}
}

return nmap
Expand Down
55 changes: 54 additions & 1 deletion pkg/collect/safe_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,62 @@ package collect
import (
"testing"

"github.com/alibaba/pouch/pkg/utils"

"github.com/stretchr/testify/assert"
)

// TestSafeMapValues is to valid the Values function
func TestSafeMapValues(t *testing.T) {
safeMap := NewSafeMap()
assert.Equal(t, len(safeMap.inner), 0)

safeMap.Put("key", "value")
assert.Equal(t, len(safeMap.inner), 1)

safeMap.Put("key1", "value1")
assert.Equal(t, len(safeMap.inner), 2)

// first not specify filter
values := safeMap.Values(nil)
assert.Equal(t, len(values), 2)
for k, v := range values {
if !utils.StringInSlice([]string{"key", "key1"}, k) {
t.Errorf("got unexpected key: %v", k)
}

if k == "key" && v != "value" {
t.Errorf("expected 'value', but got %v", v)
}

if k == "key1" && v != "value1" {
t.Errorf("expected 'value1', but got %v", v)
}
}

// test filter function
fn := func(obj interface{}) bool {
v, ok := obj.(string)
if !ok || v != "value" {
return false
}

return true
}

values = safeMap.Values(fn)
assert.Equal(t, len(values), 1)
v, ok := values["key"]
if !ok {
t.Errorf("expected 'key' in map, but got: %v", values)
}

stringVar, ok := v.(string)
if !ok || stringVar != "value" {
t.Errorf("expected map's value is 'value', but got: %v", stringVar)
}
}

func TestSafeMapPutAndGet(t *testing.T) {
safeMap := NewSafeMap()
assert.Equal(t, len(safeMap.inner), 0)
Expand Down Expand Up @@ -67,7 +120,7 @@ func TestSafeMapDirectNew(t *testing.T) {
sm.Remove("k")

// test Values not panic
values := sm.Values()
values := sm.Values(nil)
assert.Equal(values, map[string]interface{}{})
}

Expand Down
32 changes: 32 additions & 0 deletions test/cli_inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,35 @@ func (suite *PouchInspectSuite) TestContainerInspectHostRootPath(c *check.C) {

c.Assert(strings.TrimSpace(hostRootPathOutput), check.Equals, containers[0].GraphDriver.Data["MergedDir"])
}

// TestContainerInspectExecIds is to valid if we can normally inspect ExecIds
func (suite *PouchInspectSuite) TestContainerInspectExecIds(c *check.C) {
name := "TestContainerInspectExecIds"
command.PouchRun("run", "-d",
"--name", name,
busyboxImage, "top",
).Assert(c, icmd.Success)
defer DelContainerForceMultyTime(c, name)

// first check `ExecIds` when the container created
output := command.PouchRun("inspect", "-f", "{{.ExecIds}}", name).Stdout()
c.Assert(string(output), check.Equals, "[]\n")

// then check `ExecIds` when execute a exec command
command.PouchRun("exec", name, "echo", "hi").Assert(c, icmd.Success)
output = command.PouchRun("inspect", name).Stdout()
containers := make([]types.ContainerJSON, 1)
err := json.Unmarshal([]byte(output), &containers)
if err != nil || len(containers) != 1 {
c.Fatal("fail to format container json")
}

execIDs := containers[0].ExecIds
if len(execIDs) != 1 {
c.Errorf("expected one exec id, but got: %v", execIDs)
}

output = command.PouchRun("inspect", "-f", "{{.ExecIds}}", name).Stdout()
expected := fmt.Sprintf("[%v]\n", execIDs[0])
c.Assert(string(output), check.Equals, expected)
}