diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_test.go | 3 | ||||
-rw-r--r-- | libpod/container_top_linux.go | 88 | ||||
-rw-r--r-- | libpod/image/image_test.go | 12 | ||||
-rw-r--r-- | libpod/lock/file/file_lock_test.go | 4 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 16 | ||||
-rw-r--r-- | libpod/state_test.go | 137 |
6 files changed, 202 insertions, 58 deletions
diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go index f1e2b70a7..5428504ef 100644 --- a/libpod/container_internal_test.go +++ b/libpod/container_internal_test.go @@ -61,7 +61,8 @@ func TestPostDeleteHooks(t *testing.T) { } stateRegexp := `{"ociVersion":"1\.0\.1-dev","id":"123abc","status":"stopped","bundle":"` + strings.TrimSuffix(os.TempDir(), "/") + `/libpod_test_[0-9]*","annotations":{"a":"b"}}` - for _, path := range []string{statePath, copyPath} { + for _, p := range []string{statePath, copyPath} { + path := p t.Run(path, func(t *testing.T) { content, err := ioutil.ReadFile(path) if err != nil { diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go index 5f4f28130..98edc340a 100644 --- a/libpod/container_top_linux.go +++ b/libpod/container_top_linux.go @@ -3,6 +3,8 @@ package libpod import ( + "bufio" + "os" "strconv" "strings" @@ -10,6 +12,7 @@ import ( "github.com/containers/libpod/pkg/rootless" "github.com/containers/psgo" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) // Top gathers statistics about the running processes in a container. It returns a @@ -36,7 +39,34 @@ func (c *Container) Top(descriptors []string) ([]string, error) { } } } - return c.GetContainerPidInformation(psgoDescriptors) + + // If we encountered an ErrUnknownDescriptor error, fallback to executing + // ps(1). This ensures backwards compatibility to users depending on ps(1) + // and makes sure we're ~compatible with docker. + output, psgoErr := c.GetContainerPidInformation(psgoDescriptors) + if psgoErr == nil { + return output, nil + } + if errors.Cause(psgoErr) != psgo.ErrUnknownDescriptor { + return nil, psgoErr + } + + output, err = c.execPS(descriptors) + if err != nil { + return nil, errors.Wrapf(err, "error executing ps(1) in the container") + } + + // Trick: filter the ps command from the output instead of + // checking/requiring PIDs in the output. + filtered := []string{} + cmd := strings.Join(descriptors, " ") + for _, line := range output { + if !strings.Contains(line, cmd) { + filtered = append(filtered, line) + } + } + + return filtered, nil } // GetContainerPidInformation returns process-related data of all processes in @@ -65,3 +95,59 @@ func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, } return res, nil } + +// execPS executes ps(1) with the specified args in the container. +func (c *Container) execPS(args []string) ([]string, error) { + rPipe, wPipe, err := os.Pipe() + if err != nil { + return nil, err + } + defer wPipe.Close() + defer rPipe.Close() + + rErrPipe, wErrPipe, err := os.Pipe() + if err != nil { + return nil, err + } + defer wErrPipe.Close() + defer rErrPipe.Close() + + streams := new(AttachStreams) + streams.OutputStream = wPipe + streams.ErrorStream = wErrPipe + streams.AttachOutput = true + streams.AttachError = true + + stdout := []string{} + go func() { + scanner := bufio.NewScanner(rPipe) + for scanner.Scan() { + stdout = append(stdout, scanner.Text()) + } + }() + stderr := []string{} + go func() { + scanner := bufio.NewScanner(rErrPipe) + for scanner.Scan() { + stderr = append(stderr, scanner.Text()) + } + }() + + cmd := append([]string{"ps"}, args...) + ec, err := c.Exec(false, false, map[string]string{}, cmd, "", "", streams, 0, nil, "") + if err != nil { + return nil, err + } else if ec != 0 { + return nil, errors.Errorf("Runtime failed with exit status: %d and output: %s", ec, strings.Join(stderr, " ")) + } + + if logrus.GetLevel() >= logrus.DebugLevel { + // If we're running in debug mode or higher, we might want to have a + // look at stderr which includes debug logs from conmon. + for _, log := range stderr { + logrus.Debugf("%s", log) + } + } + + return stdout, nil +} diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go index 5aff7d860..3ff6210d9 100644 --- a/libpod/image/image_test.go +++ b/libpod/image/image_test.go @@ -3,7 +3,6 @@ package image import ( "context" "fmt" - "io" "io/ioutil" "os" "testing" @@ -91,8 +90,7 @@ func TestImage_NewFromLocal(t *testing.T) { RunRoot: workdir, GraphRoot: workdir, } - var writer io.Writer - writer = os.Stdout + writer := os.Stdout // Need images to be present for this test ir, err := NewImageRuntimeFromOptions(so) @@ -108,7 +106,7 @@ func TestImage_NewFromLocal(t *testing.T) { for _, image := range tm { // tag our images - image.img.TagImage(image.taggedName) + err = image.img.TagImage(image.taggedName) assert.NoError(t, err) for _, name := range image.names { newImage, err := ir.NewFromLocal(name) @@ -142,8 +140,7 @@ func TestImage_New(t *testing.T) { // Build the list of pull names names = append(names, bbNames...) names = append(names, fedoraNames...) - var writer io.Writer - writer = os.Stdout + writer := os.Stdout // Iterate over the names and delete the image // after the pull @@ -213,7 +210,7 @@ func TestImage_RepoDigests(t *testing.T) { t.Fatal(err) } - for _, test := range []struct { + for _, tt := range []struct { name string names []string expected []string @@ -234,6 +231,7 @@ func TestImage_RepoDigests(t *testing.T) { expected: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, }, } { + test := tt t.Run(test.name, func(t *testing.T) { image := &Image{ image: &storage.Image{ diff --git a/libpod/lock/file/file_lock_test.go b/libpod/lock/file/file_lock_test.go index 6320d6b70..7ac8bf31a 100644 --- a/libpod/lock/file/file_lock_test.go +++ b/libpod/lock/file/file_lock_test.go @@ -17,10 +17,10 @@ func TestCreateAndDeallocate(t *testing.T) { assert.NoError(t, err) defer os.RemoveAll(d) - l, err := OpenFileLock(filepath.Join(d, "locks")) + _, err = OpenFileLock(filepath.Join(d, "locks")) assert.Error(t, err) - l, err = CreateFileLock(filepath.Join(d, "locks")) + l, err := CreateFileLock(filepath.Join(d, "locks")) assert.NoError(t, err) lock, err := l.AllocateLock() diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 7cc43abc0..5ab0e73c4 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -149,9 +149,23 @@ func (r *ConmonOCIRuntime) Path() string { return r.path } +// hasCurrentUserMapped checks whether the current user is mapped inside the container user namespace +func hasCurrentUserMapped(ctr *Container) bool { + if len(ctr.config.IDMappings.UIDMap) == 0 && len(ctr.config.IDMappings.GIDMap) == 0 { + return true + } + uid := os.Geteuid() + for _, m := range ctr.config.IDMappings.UIDMap { + if uid >= m.HostID && uid < m.HostID+m.Size { + return true + } + } + return false +} + // CreateContainer creates a container. func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) (err error) { - if len(ctr.config.IDMappings.UIDMap) != 0 || len(ctr.config.IDMappings.GIDMap) != 0 { + if !hasCurrentUserMapped(ctr) { for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.VolumePath} { if err := makeAccessible(i, ctr.RootUID(), ctr.RootGID()); err != nil { return err diff --git a/libpod/state_test.go b/libpod/state_test.go index d4a4149f9..39937d8e4 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -350,7 +350,8 @@ func TestAddCtrSameNamespaceSucceeds(t *testing.T) { testCtr.config.Namespace = "test1" - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) err = state.AddContainer(testCtr) assert.NoError(t, err) @@ -369,12 +370,14 @@ func TestAddCtrDifferentNamespaceFails(t *testing.T) { testCtr.config.Namespace = "test1" - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.AddContainer(testCtr) assert.Error(t, err) - state.SetNamespace("") + err = state.SetNamespace("") + assert.NoError(t, err) ctrs, err := state.AllContainers() assert.NoError(t, err) @@ -406,7 +409,8 @@ func TestGetContainerInDifferentNamespaceFails(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) _, err = state.Container(testCtr.ID()) assert.Error(t, err) @@ -423,7 +427,8 @@ func TestGetContainerInSameNamespaceSucceeds(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) ctr, err := state.Container(testCtr.ID()) assert.NoError(t, err) @@ -586,7 +591,8 @@ func TestLookupCtrInSameNamespaceSucceeds(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) ctr, err := state.LookupContainer(testCtr.ID()) assert.NoError(t, err) @@ -608,7 +614,8 @@ func TestLookupCtrInDifferentNamespaceFails(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.LookupContainer(testCtr.ID()) assert.Error(t, err) @@ -633,7 +640,8 @@ func TestLookupContainerMatchInDifferentNamespaceSucceeds(t *testing.T) { err = state.AddContainer(testCtr2) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) ctr, err := state.LookupContainer("000") assert.NoError(t, err) @@ -698,7 +706,8 @@ func TestHasContainerSameNamespaceIsTrue(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) exists, err := state.HasContainer(testCtr.ID()) assert.NoError(t, err) @@ -716,7 +725,8 @@ func TestHasContainerDifferentNamespaceIsFalse(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) exists, err := state.HasContainer(testCtr.ID()) assert.NoError(t, err) @@ -759,7 +769,8 @@ func TestSaveAndUpdateContainerSameNamespaceSucceeds(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) retrievedCtr, err := state.Container(testCtr.ID()) assert.NoError(t, err) @@ -806,7 +817,8 @@ func TestUpdateContainerNotInNamespaceReturnsError(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.UpdateContainer(testCtr) assert.Error(t, err) @@ -841,7 +853,8 @@ func TestSaveContainerNotInNamespaceReturnsError(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.SaveContainer(testCtr) assert.Error(t, err) @@ -894,12 +907,14 @@ func TestRemoveContainerNotInNamespaceFails(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 1, len(ctrs)) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.RemoveContainer(testCtr) assert.Error(t, err) - state.SetNamespace("") + err = state.SetNamespace("") + assert.NoError(t, err) ctrs2, err := state.AllContainers() assert.NoError(t, err) @@ -960,7 +975,8 @@ func TestGetAllContainersNoContainerInNamespace(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) ctrs, err := state.AllContainers() assert.NoError(t, err) @@ -984,7 +1000,8 @@ func TestGetContainerOneContainerInNamespace(t *testing.T) { err = state.AddContainer(testCtr2) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) ctrs, err := state.AllContainers() assert.NoError(t, err) @@ -1020,7 +1037,8 @@ func TestContainerInUseCtrNotInNamespace(t *testing.T) { err = state.AddContainer(testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.ContainerInUse(testCtr) assert.Error(t, err) @@ -1497,7 +1515,8 @@ func TestGetPodInNamespaceSucceeds(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) statePod, err := state.Pod(testPod.ID()) assert.NoError(t, err) @@ -1516,7 +1535,8 @@ func TestGetPodPodNotInNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.Pod(testPod.ID()) assert.Error(t, err) @@ -1637,7 +1657,8 @@ func TestLookupPodInSameNamespaceSucceeds(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) statePod, err := state.LookupPod(testPod.ID()) assert.NoError(t, err) @@ -1656,7 +1677,8 @@ func TestLookupPodInDifferentNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.LookupPod(testPod.ID()) assert.Error(t, err) @@ -1681,7 +1703,8 @@ func TestLookupPodOneInDifferentNamespaceFindsRightPod(t *testing.T) { err = state.AddPod(testPod2) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) pod, err := state.LookupPod(strings.Repeat("1", 5)) assert.NoError(t, err) @@ -1757,7 +1780,8 @@ func TestHasPodSameNamespaceSucceeds(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) exist, err := state.HasPod(testPod.ID()) assert.NoError(t, err) @@ -1775,7 +1799,8 @@ func TestHasPodDifferentNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) exist, err := state.HasPod(testPod.ID()) assert.NoError(t, err) @@ -1913,7 +1938,8 @@ func TestAddPodSameNamespaceSucceeds(t *testing.T) { testPod.config.Namespace = "test1" - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) err = state.AddPod(testPod) assert.NoError(t, err) @@ -1933,12 +1959,14 @@ func TestAddPodDifferentNamespaceFails(t *testing.T) { testPod.config.Namespace = "test1" - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.AddPod(testPod) assert.Error(t, err) - state.SetNamespace("") + err = state.SetNamespace("") + assert.NoError(t, err) allPods, err := state.AllPods() assert.NoError(t, err) @@ -2067,12 +2095,14 @@ func TestRemovePodNotInNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.RemovePod(testPod) assert.Error(t, err) - state.SetNamespace("") + err = state.SetNamespace("") + assert.NoError(t, err) allPods, err := state.AllPods() assert.NoError(t, err) @@ -2152,7 +2182,8 @@ func TestAllPodsPodInDifferentNamespaces(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) allPods, err := state.AllPods() assert.NoError(t, err) @@ -2178,7 +2209,8 @@ func TestAllPodsOnePodInDifferentNamespace(t *testing.T) { err = state.AddPod(testPod2) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) allPods, err := state.AllPods() assert.NoError(t, err) @@ -2274,7 +2306,8 @@ func TestPodHasContainerPodNotInNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.PodHasContainer(testPod, strings.Repeat("2", 32)) assert.Error(t, err) @@ -2393,7 +2426,8 @@ func TestPodContainerByIDPodNotInNamespace(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.PodContainersByID(testPod) assert.Error(t, err) @@ -2513,7 +2547,8 @@ func TestPodContainersPodNotInNamespace(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) _, err = state.PodContainers(testPod) assert.Error(t, err) @@ -2686,7 +2721,8 @@ func TestRemoveContainersNotInNamespace(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.RemovePodContainers(testPod) assert.Error(t, err) @@ -3229,7 +3265,8 @@ func TestAddCtrToPodSameNamespaceSucceeds(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) err = state.AddContainerToPod(testPod, testCtr) assert.NoError(t, err) @@ -3253,15 +3290,17 @@ func TestAddCtrToPodDifferentNamespaceFails(t *testing.T) { testPod.config.Namespace = "test1" testCtr.config.Pod = testPod.ID() - state.AddPod(testPod) + err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.AddContainerToPod(testPod, testCtr) assert.Error(t, err) - state.SetNamespace("") + err = state.SetNamespace("") + assert.NoError(t, err) ctrs, err := state.AllContainers() assert.NoError(t, err) @@ -3461,7 +3500,8 @@ func TestRemoveContainerFromPodSameNamespaceSucceeds(t *testing.T) { err = state.AddContainerToPod(testPod, testCtr) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) err = state.RemoveContainerFromPod(testPod, testCtr) assert.NoError(t, err) @@ -3495,12 +3535,14 @@ func TestRemoveContainerFromPodDifferentNamespaceFails(t *testing.T) { err = state.AddContainerToPod(testPod, testCtr) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.RemoveContainerFromPod(testPod, testCtr) assert.Error(t, err) - state.SetNamespace("") + err = state.SetNamespace("") + assert.NoError(t, err) ctrs, err := state.PodContainers(testPod) assert.NoError(t, err) @@ -3539,7 +3581,8 @@ func TestUpdatePodNotInNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.UpdatePod(testPod) assert.Error(t, err) @@ -3573,7 +3616,8 @@ func TestSavePodNotInNamespaceFails(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test2") + err = state.SetNamespace("test2") + assert.NoError(t, err) err = state.SavePod(testPod) assert.Error(t, err) @@ -3615,7 +3659,8 @@ func TestSaveAndUpdatePodSameNamespace(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - state.SetNamespace("test1") + err = state.SetNamespace("test1") + assert.NoError(t, err) statePod, err := state.Pod(testPod.ID()) assert.NoError(t, err) |