diff options
-rw-r--r-- | cmd/podman/main.go | 1 | ||||
-rw-r--r-- | cmd/podman/pod_inspect.go | 9 | ||||
-rw-r--r-- | cmd/podman/pod_top.go | 26 | ||||
-rw-r--r-- | cmd/podman/tree.go | 2 | ||||
-rwxr-xr-x | contrib/cirrus/notice_master_failure.sh | 3 | ||||
-rwxr-xr-x | contrib/cirrus/setup_environment.sh | 2 | ||||
-rw-r--r-- | docs/podman-image.1.md | 2 | ||||
-rw-r--r-- | docs/podman-ps.1.md | 9 | ||||
-rw-r--r-- | libpod/container_log.go | 7 | ||||
-rw-r--r-- | libpod/runtime.go | 37 | ||||
-rw-r--r-- | pkg/util/utils.go | 53 | ||||
-rw-r--r-- | test/e2e/logs_test.go | 10 | ||||
-rw-r--r-- | test/e2e/rootless_test.go | 15 |
13 files changed, 129 insertions, 47 deletions
diff --git a/cmd/podman/main.go b/cmd/podman/main.go index b130f3232..ef300ef75 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -76,6 +76,7 @@ var cmdsNotRequiringRootless = map[*cobra.Command]bool{ _podKillCommand: true, _podStatsCommand: true, _podStopCommand: true, + _podTopCommand: true, _restartCommand: true, _rmCommand: true, _runCommand: true, diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go index 79ffe2e6f..851f39aa0 100644 --- a/cmd/podman/pod_inspect.go +++ b/cmd/podman/pod_inspect.go @@ -14,7 +14,7 @@ var ( podInspectCommand cliconfig.PodInspectValues podInspectDescription = `Display the configuration for a pod by name or id - By default, this will render all results in a JSON array. If the container and image have the same name, this command returns the container JSON.` + By default, this will render all results in a JSON array.` _podInspectCommand = &cobra.Command{ Use: "inspect [flags] POD", @@ -34,7 +34,7 @@ func init() { podInspectCommand.SetHelpTemplate(HelpTemplate()) podInspectCommand.SetUsageTemplate(UsageTemplate()) flags := podInspectCommand.Flags() - flags.BoolVarP(&podInspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") + flags.BoolVarP(&podInspectCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") markFlagHiddenForRemoteClient("latest", flags) } @@ -44,6 +44,11 @@ func podInspectCmd(c *cliconfig.PodInspectValues) error { pod *adapter.Pod ) args := c.InputArgs + + if len(args) < 1 && !c.Latest { + return errors.Errorf("you must provide the name or id of a pod") + } + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") diff --git a/cmd/podman/pod_top.go b/cmd/podman/pod_top.go index c9a6d8822..f65d66df6 100644 --- a/cmd/podman/pod_top.go +++ b/cmd/podman/pod_top.go @@ -9,6 +9,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -53,6 +54,10 @@ func podTopCmd(c *cliconfig.PodTopValues) error { ) args := c.InputArgs + if os.Geteuid() != 0 { + rootless.SetSkipStorageSetup(true) + } + if c.ListDescriptors { descriptors, err := libpod.GetContainerPidInformationDescriptors() if err != nil { @@ -77,6 +82,27 @@ func podTopCmd(c *cliconfig.PodTopValues) error { } else { descriptors = args[1:] } + + if os.Geteuid() != 0 { + var pod *adapter.Pod + var err error + if c.Latest { + pod, err = runtime.GetLatestPod() + } else { + pod, err = runtime.LookupPod(c.InputArgs[0]) + } + if err != nil { + return errors.Wrapf(err, "unable to lookup requested container") + } + became, ret, err := runtime.JoinOrCreateRootlessPod(pod) + if err != nil { + return err + } + if became { + os.Exit(ret) + } + } + w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) psOutput, err := runtime.PodTop(c, descriptors) if err != nil { diff --git a/cmd/podman/tree.go b/cmd/podman/tree.go index ebda18cdb..c56e35aef 100644 --- a/cmd/podman/tree.go +++ b/cmd/podman/tree.go @@ -23,7 +23,7 @@ var ( treeDescription = "Prints layer hierarchy of an image in a tree format" _treeCommand = &cobra.Command{ - Use: "tree", + Use: "tree [flags] IMAGE", Short: treeDescription, Long: treeDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/contrib/cirrus/notice_master_failure.sh b/contrib/cirrus/notice_master_failure.sh index e18460a54..4b09331d3 100755 --- a/contrib/cirrus/notice_master_failure.sh +++ b/contrib/cirrus/notice_master_failure.sh @@ -12,8 +12,7 @@ NOR="$(echo -n -e '\x0f')" if [[ "$CIRRUS_BRANCH" =~ "master" ]] then BURL="https://cirrus-ci.com/build/$CIRRUS_BUILD_ID" - echo "Monitoring execution of $CIRRUS_TASK_NAME and notifying on failure" - MSG="${RED}[Action Recommended]: ${NOR}Post-merge testing ${RED}$CIRRUS_BRANCH failed${NOR} in $CIRRUS_TASK_NAME on $(os_release_id)-$(os_release_ver): $BURL. Please investigate, and re-run if appropriate." + ircmsg "${RED}[Action Recommended]: ${NOR}Post-merge testing ${RED}$CIRRUS_BRANCH failed${NOR} in $CIRRUS_TASK_NAME on $(os_release_id)-$(os_release_ver): $BURL. Please investigate, and re-run if appropriate." fi # This script assumed to be executed on failure diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index d8d97904b..04c19b3af 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -88,4 +88,6 @@ then fi fi +show_env_vars + record_timestamp "env. setup end" diff --git a/docs/podman-image.1.md b/docs/podman-image.1.md index 54960045f..333a75b69 100644 --- a/docs/podman-image.1.md +++ b/docs/podman-image.1.md @@ -27,8 +27,8 @@ The image command allows you to manage images | save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. | | sign | [podman-image-sign(1)](podman-image-sign.1.md) | Sign an image. | | tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | +| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. | | trust | [podman-image-trust(1)](podman-image-trust.1.md)| Manage container image trust policy. | -| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format | ## SEE ALSO podman diff --git a/docs/podman-ps.1.md b/docs/podman-ps.1.md index b8b1c3d62..811fbbc2f 100644 --- a/docs/podman-ps.1.md +++ b/docs/podman-ps.1.md @@ -148,6 +148,15 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS 69ed779d8ef9f redis:alpine "redis-server" 25 hours ago Created 6379/tcp k8s_container1_podsandbox1_redhat.test.crio_redhat-test-crio_1 02f65160e14ca redis:alpine "redis-server" 19 hours ago Exited (-1) 19 hours ago 6379/tcp k8s_podsandbox1-redis_podsandbox1_redhat.test.crio_redhat-test-crio_0 ``` + +``` +$ podman ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +4089df24d4f3 docker.io/library/centos:latest /bin/bash 2 minutes ago Up 2 minutes ago 0.0.0.0:80->8080/tcp, 0.0.0.0:2000-2006->2000-2006/tcp manyports +92f58933c28c docker.io/library/centos:latest /bin/bash 3 minutes ago Up 3 minutes ago 192.168.99.100:1000-1006->1000-1006/tcp zen_sanderson + +``` + ## ps Print a list of containers diff --git a/libpod/container_log.go b/libpod/container_log.go index 7964e4022..e998ad316 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -3,6 +3,7 @@ package libpod import ( "fmt" "io/ioutil" + "os" "strings" "sync" "time" @@ -54,6 +55,10 @@ func (r *Runtime) Log(containers []*Container, options *LogOptions, logChannel c func (c *Container) ReadLog(options *LogOptions, logChannel chan *LogLine) error { t, tailLog, err := getLogFile(c.LogPath(), options) if err != nil { + // If the log file does not exist, this is not fatal. + if os.IsNotExist(errors.Cause(err)) { + return nil + } return errors.Wrapf(err, "unable to read log file %s for %s ", c.ID(), c.LogPath()) } options.WaitGroup.Add(1) @@ -111,7 +116,7 @@ func getLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error Whence: whence, } - t, err := tail.TailFile(path, tail.Config{Poll: true, Follow: options.Follow, Location: &seek, Logger: tail.DiscardingLogger}) + t, err := tail.TailFile(path, tail.Config{MustExist: true, Poll: true, Follow: options.Follow, Location: &seek, Logger: tail.DiscardingLogger}) return t, logTail, err } diff --git a/libpod/runtime.go b/libpod/runtime.go index 9836b7aab..b3b75d791 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -505,24 +505,33 @@ func newRuntimeFromConfig(userConfigPath string, options ...RuntimeOption) (runt return nil, errors.Wrapf(err, "error configuring runtime") } } - if err := makeRuntime(runtime); err != nil { - return nil, err - } - - if !foundConfig && rootlessConfigPath != "" { - os.MkdirAll(filepath.Dir(rootlessConfigPath), 0755) - file, err := os.OpenFile(rootlessConfigPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) - if err != nil && !os.IsExist(err) { - return nil, errors.Wrapf(err, "cannot open file %s", rootlessConfigPath) + if rootlessConfigPath != "" { + // storage.conf + storageConfFile := util.StorageConfigFile() + if _, err := os.Stat(storageConfFile); os.IsNotExist(err) { + if err := util.WriteStorageConfigFile(&runtime.config.StorageConfig, storageConfFile); err != nil { + return nil, errors.Wrapf(err, "cannot write config file %s", storageConfFile) + } } - if err == nil { - defer file.Close() - enc := toml.NewEncoder(file) - if err := enc.Encode(runtime.config); err != nil { - os.Remove(rootlessConfigPath) + + if !foundConfig { + os.MkdirAll(filepath.Dir(rootlessConfigPath), 0755) + file, err := os.OpenFile(rootlessConfigPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if err != nil && !os.IsExist(err) { + return nil, errors.Wrapf(err, "cannot open file %s", rootlessConfigPath) + } + if err == nil { + defer file.Close() + enc := toml.NewEncoder(file) + if err := enc.Encode(runtime.config); err != nil { + os.Remove(rootlessConfigPath) + } } } } + if err := makeRuntime(runtime); err != nil { + return nil, err + } return runtime, nil } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 73dddf2ac..a408ad34b 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -195,7 +195,7 @@ func GetRootlessRuntimeDir() (string, error) { } } if runtimeDir == "" { - tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("libpod-rundir-%s", uid)) + tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid)) os.MkdirAll(tmpDir, 0700) st, err := os.Stat(tmpDir) if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { @@ -311,36 +311,37 @@ func GetDefaultStoreOptions() (storage.StoreOptions, error) { storageOpts = storage.StoreOptions{} storage.ReloadConfigurationFile(storageConf, &storageOpts) } - - if rootless.IsRootless() { - if os.IsNotExist(err) { - os.MkdirAll(filepath.Dir(storageConf), 0755) - file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) - if err != nil { - return storageOpts, errors.Wrapf(err, "cannot open %s", storageConf) - } - - tomlConfiguration := getTomlStorage(&storageOpts) - defer file.Close() - enc := toml.NewEncoder(file) - if err := enc.Encode(tomlConfiguration); err != nil { - os.Remove(storageConf) - } - } else if err == nil { - // If the file did not specify a graphroot or runroot, - // set sane defaults so we don't try and use root-owned - // directories - if storageOpts.RunRoot == "" { - storageOpts.RunRoot = defaultRootlessRunRoot - } - if storageOpts.GraphRoot == "" { - storageOpts.GraphRoot = defaultRootlessGraphRoot - } + if rootless.IsRootless() && err == nil { + // If the file did not specify a graphroot or runroot, + // set sane defaults so we don't try and use root-owned + // directories + if storageOpts.RunRoot == "" { + storageOpts.RunRoot = defaultRootlessRunRoot + } + if storageOpts.GraphRoot == "" { + storageOpts.GraphRoot = defaultRootlessGraphRoot } } return storageOpts, nil } +// WriteStorageConfigFile writes the configuration to a file +func WriteStorageConfigFile(storageOpts *storage.StoreOptions, storageConf string) error { + os.MkdirAll(filepath.Dir(storageConf), 0755) + file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + return errors.Wrapf(err, "cannot open %s", storageConf) + } + tomlConfiguration := getTomlStorage(storageOpts) + defer file.Close() + enc := toml.NewEncoder(file) + if err := enc.Encode(tomlConfiguration); err != nil { + os.Remove(storageConf) + return err + } + return nil +} + // StorageConfigFile returns the path to the storage config file used func StorageConfigFile() string { if rootless.IsRootless() { diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index d383a83b3..d051e3dba 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -132,4 +132,14 @@ var _ = Describe("Podman logs", func() { Expect(len(output)).To(Equal(6)) Expect(strings.Contains(output[0], cid1[:12]) || strings.Contains(output[0], cid2[:12])).To(BeTrue()) }) + + It("podman logs on a created container should result in 0 exit code", func() { + session := podmanTest.Podman([]string{"create", "-dt", "--name", "log", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(BeZero()) + + results := podmanTest.Podman([]string{"logs", "log"}) + results.WaitWithDefaultTimeout() + Expect(results.ExitCode()).To(BeZero()) + }) }) diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go index cd771e2ba..57146bca0 100644 --- a/test/e2e/rootless_test.go +++ b/test/e2e/rootless_test.go @@ -138,6 +138,21 @@ var _ = Describe("Podman rootless", func() { cmd.WaitWithDefaultTimeout() Expect(cmd.ExitCode()).To(Equal(0)) Expect(cmd.LineInOutputContains("hello")).To(BeTrue()) + + args = []string{"pod", "top", podId} + cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Not(Equal(0))) + + args = []string{"run", "--pod", podId, "-d", "--rootfs", mountPath, "sleep", "100"} + cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Equal(0)) + + args = []string{"pod", "top", podId} + cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Equal(0)) } runInRootlessContext(f) }) |