summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/commit.go5
-rw-r--r--contrib/spec/podman.spec.in1
-rw-r--r--libpod/container_commit.go36
-rw-r--r--pkg/rootless/rootless_linux.c55
-rw-r--r--test/e2e/commit_test.go25
5 files changed, 95 insertions, 27 deletions
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 5963f8686..8d79c1e28 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -42,7 +42,7 @@ func init() {
commitCommand.SetHelpTemplate(HelpTemplate())
commitCommand.SetUsageTemplate(UsageTemplate())
flags := commitCommand.Flags()
- flags.StringSliceVarP(&commitCommand.Change, "change", "c", []string{}, fmt.Sprintf("Apply the following possible instructions to the created image (default []): %s", strings.Join(libpod.ChangeCmds, " | ")))
+ flags.StringArrayVarP(&commitCommand.Change, "change", "c", []string{}, fmt.Sprintf("Apply the following possible instructions to the created image (default []): %s", strings.Join(libpod.ChangeCmds, " | ")))
flags.StringVarP(&commitCommand.Format, "format", "f", "oci", "`Format` of the image manifest and metadata")
flags.StringVarP(&commitCommand.Message, "message", "m", "", "Set commit message for imported image")
flags.StringVarP(&commitCommand.Author, "author", "a", "", "Set the author for the image committed")
@@ -83,6 +83,9 @@ func commitCmd(c *cliconfig.CommitValues) error {
if c.Flag("change").Changed {
for _, change := range c.Change {
splitChange := strings.Split(strings.ToUpper(change), "=")
+ if len(splitChange) == 1 {
+ splitChange = strings.Split(strings.ToUpper(change), " ")
+ }
if !util.StringInSlice(splitChange[0], libpod.ChangeCmds) {
return errors.Errorf("invalid syntax for --change: %s", change)
}
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 396304f8d..4b9cbd4cf 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -66,6 +66,7 @@ BuildRequires: libselinux-devel
BuildRequires: ostree-devel
BuildRequires: pkgconfig
BuildRequires: make
+BuildRequires: systemd-devel
Requires: runc
Requires: skopeo-containers
Requires: containernetworking-plugins >= 0.6.0-3
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index 3cc4b2c92..ae04f67bb 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -125,23 +125,48 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
// Workdir
importBuilder.SetWorkDir(c.Spec().Process.Cwd)
+ genCmd := func(cmd string) []string {
+ trim := func(cmd []string) []string {
+ if len(cmd) == 0 {
+ return cmd
+ }
+
+ retCmd := []string{}
+ for _, c := range cmd {
+ if len(c) >= 2 {
+ if c[0] == '"' && c[len(c)-1] == '"' {
+ retCmd = append(retCmd, c[1:len(c)-1])
+ continue
+ }
+ }
+ retCmd = append(retCmd, c)
+ }
+ return retCmd
+ }
+ if strings.HasPrefix(cmd, "[") {
+ cmd = strings.TrimPrefix(cmd, "[")
+ cmd = strings.TrimSuffix(cmd, "]")
+ return trim(strings.Split(cmd, ","))
+ }
+ return []string{"/bin/sh", "-c", cmd}
+ }
// Process user changes
for _, change := range options.Changes {
- splitChange := strings.SplitN(change, " ", 2)
+ splitChange := strings.SplitN(change, "=", 2)
if len(splitChange) != 2 {
- splitChange = strings.SplitN(change, "=", 2)
+ splitChange = strings.SplitN(change, " ", 2)
if len(splitChange) < 2 {
return nil, errors.Errorf("invalid change %s format", change)
}
}
- change := strings.Split(splitChange[1], " ")
switch strings.ToUpper(splitChange[0]) {
case "CMD":
- importBuilder.SetCmd(change)
+ importBuilder.SetCmd(genCmd(splitChange[1]))
case "ENTRYPOINT":
- importBuilder.SetEntrypoint(change)
+ importBuilder.SetEntrypoint(genCmd(splitChange[1]))
case "ENV":
+ change := strings.Split(splitChange[1], " ")
name := change[0]
val := ""
if len(change) < 2 {
@@ -168,6 +193,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
}
importBuilder.SetPort(splitChange[1])
case "LABEL":
+ change := strings.Split(splitChange[1], " ")
if len(change) < 2 {
change = strings.Split(change[0], "=")
}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 9cb79ed4d..1d32b1adb 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -16,11 +16,13 @@
#include <sys/types.h>
#include <sys/prctl.h>
#include <dirent.h>
+#include <sys/select.h>
static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces";
static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
-static int n_files;
+static int open_files_max_fd;
+fd_set open_files_set;
static void __attribute__((constructor)) init()
{
@@ -32,11 +34,16 @@ static void __attribute__((constructor)) init()
{
struct dirent *ent;
+ FD_ZERO (&open_files_set);
for (ent = readdir (d); ent; ent = readdir (d))
{
int fd = atoi (ent->d_name);
- if (fd > n_files && fd != dirfd (d))
- n_files = fd;
+ if (fd != dirfd (d))
+ {
+ if (fd > open_files_max_fd)
+ open_files_max_fd = fd;
+ FD_SET (fd, &open_files_set);
+ }
}
closedir (d);
}
@@ -164,8 +171,11 @@ reexec_userns_join (int userns, int mountns)
{
/* We passed down these fds, close them. */
int f;
- for (f = 3; f < n_files; f++)
- close (f);
+ for (f = 3; f < open_files_max_fd; f++)
+ {
+ if (FD_ISSET (f, &open_files_set))
+ close (f);
+ }
return pid;
}
@@ -274,22 +284,25 @@ reexec_in_user_namespace (int ready)
check_proc_sys_userns_file (_max_user_namespaces);
check_proc_sys_userns_file (_unprivileged_user_namespaces);
}
- if (pid) {
- if (do_socket_activation) {
- long num_fds;
- num_fds = strtol(listen_fds, NULL, 10);
- if (num_fds != LONG_MIN && num_fds != LONG_MAX) {
- long i;
- for (i = 0; i < num_fds; i++) {
- close(3+i);
+ if (pid)
+ {
+ if (do_socket_activation)
+ {
+ long num_fds;
+ num_fds = strtol (listen_fds, NULL, 10);
+ if (num_fds != LONG_MIN && num_fds != LONG_MAX)
+ {
+ long i;
+ for (i = 3; i < num_fds + 3; i++)
+ if (FD_ISSET (i, &open_files_set))
+ close (i);
+ }
+ unsetenv ("LISTEN_PID");
+ unsetenv ("LISTEN_FDS");
+ unsetenv ("LISTEN_FDNAMES");
}
- }
- unsetenv("LISTEN_PID");
- unsetenv("LISTEN_FDS");
- unsetenv("LISTEN_FDNAMES");
+ return pid;
}
- return pid;
- }
argv = get_cmd_line_args (ppid);
if (argv == NULL)
@@ -300,8 +313,8 @@ reexec_in_user_namespace (int ready)
if (do_socket_activation) {
char s[32];
- sprintf(s, "%d", getpid());
- setenv("LISTEN_PID", s, true);
+ sprintf (s, "%d", getpid());
+ setenv ("LISTEN_PID", s, true);
}
setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index 93e1ea7af..3ece4887e 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -117,6 +117,31 @@ var _ = Describe("Podman commit", func() {
Expect(foundBlue).To(Equal(true))
})
+ It("podman commit container with change CMD flag", func() {
+ test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"})
+ test.WaitWithDefaultTimeout()
+ Expect(test.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(1))
+
+ session := podmanTest.Podman([]string{"commit", "--change", "CMD a b c", "test1", "foobar.com/test1-image:latest"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"inspect", "--format", "{{.Config.Cmd}}", "foobar.com/test1-image:latest"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("sh -c a b c"))
+
+ session = podmanTest.Podman([]string{"commit", "--change", "CMD=[\"a\",\"b\",\"c\"]", "test1", "foobar.com/test1-image:latest"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"inspect", "--format", "{{.Config.Cmd}}", "foobar.com/test1-image:latest"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Not(ContainSubstring("sh -c")))
+ })
+
It("podman commit container with pause flag", func() {
_, ec, _ := podmanTest.RunLsContainer("test1")
Expect(ec).To(Equal(0))