diff options
-rw-r--r-- | .cirrus.yml | 45 | ||||
-rw-r--r-- | cmd/podman/pod_create.go | 2 | ||||
-rw-r--r-- | cmd/podman/pod_stats.go | 13 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 6 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 6 | ||||
-rw-r--r-- | cmd/podman/stats.go | 13 | ||||
-rwxr-xr-x | contrib/cirrus/setup_environment.sh | 5 | ||||
-rw-r--r-- | libpod/image/docker_registry_options.go | 7 | ||||
-rw-r--r-- | libpod/oci_internal_linux.go | 42 | ||||
-rw-r--r-- | libpod/runtime.go | 15 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 2 | ||||
-rw-r--r-- | pkg/adapter/runtime.go | 5 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 14 | ||||
-rw-r--r-- | pkg/spec/storage.go | 5 | ||||
-rw-r--r-- | test/e2e/exec_test.go | 4 | ||||
-rw-r--r-- | test/e2e/libpod_suite_remoteclient_test.go | 7 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 7 | ||||
-rw-r--r-- | test/e2e/run_exit_test.go | 4 | ||||
-rw-r--r-- | test/e2e/run_test.go | 3 | ||||
-rw-r--r-- | test/e2e/start_test.go | 4 |
20 files changed, 163 insertions, 46 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 204feb2fd..dfcd86a5d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -345,6 +345,49 @@ testing_task: audit_log_script: '$SCRIPT_BASE/logcollector.sh audit' journal_script: '$SCRIPT_BASE/logcollector.sh journal' +# Test crun on last Fedora +testing_crun_task: + + depends_on: + - "gating" + - "vendor" + - "varlink_api" + - "build_each_commit" + - "build_without_cgo" + + # Only test build cache-images, if that's what's requested + only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\*\*\*\s*CIRRUS:\s*TEST\s*IMAGES\s*\*\*\*.*' + + gce_instance: + matrix: + # Images are generated separately, from build_images_task (below) + image_name: "${FEDORA_CACHE_IMAGE_NAME}" + + timeout_in: 120m + + env: + ADD_SECOND_PARTITION: true + OCI_RUNTIME: "/usr/bin/crun" + matrix: + TEST_REMOTE_CLIENT: false + + setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}' + unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}' + integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}' + system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}' + cache_release_archive_script: >- + [[ "$TEST_REMOTE_CLIENT" == "false" ]] || \ + $SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP} + + on_failure: + failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh' + + always: &crunstandardlogs + ginkgo_node_logs_script: '$SCRIPT_BASE/logcollector.sh ginkgo' + df_script: '$SCRIPT_BASE/logcollector.sh df' + audit_log_script: '$SCRIPT_BASE/logcollector.sh audit' + journal_script: '$SCRIPT_BASE/logcollector.sh journal' + # This task executes tests under unique environments/conditions special_testing_rootless_task: @@ -518,6 +561,7 @@ success_task: - "meta" - "image_prune" - "testing" + - "testing_crun" - "special_testing_rootless" - "special_testing_in_podman" - "special_testing_cross" @@ -556,6 +600,7 @@ release_task: - "meta" - "image_prune" - "testing" + - "testing_crun" - "special_testing_rootless" - "special_testing_in_podman" - "special_testing_cross" diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go index b6154b4db..d04c85dba 100644 --- a/cmd/podman/pod_create.go +++ b/cmd/podman/pod_create.go @@ -78,7 +78,7 @@ func podCreateCmd(c *cliconfig.PodCreateValues) error { if !c.Infra && c.Flag("share").Changed && c.Share != "none" && c.Share != "" { return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container") } - if c.Flag("pod-id-file").Changed && os.Geteuid() == 0 { + if c.Flag("pod-id-file").Changed { podIdFile, err = util.OpenExclusiveFile(c.PodIDFile) if err != nil && os.IsExist(err) { return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.PodIDFile) diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go index 46cacc026..2f1ebd3ac 100644 --- a/cmd/podman/pod_stats.go +++ b/cmd/podman/pod_stats.go @@ -15,6 +15,8 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -53,9 +55,14 @@ func init() { } func podStatsCmd(c *cliconfig.PodStatsValues) error { - - if os.Geteuid() != 0 { - return errors.New("stats is not supported in rootless mode") + if rootless.IsRootless() { + unified, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return err + } + if !unified { + return errors.New("stats is not supported in rootless mode without cgroups v2") + } } format := c.Format diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index 7f53f5ec9..1d35ac17b 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -660,7 +660,7 @@ func formatGroup(key string, start, last int32) string { } // portsToString converts the ports used to a string of the from "port1, port2" -// and also groups continuous list of ports in readable format. +// and also groups a continuous list of ports into a readable format. func portsToString(ports []ocicni.PortMapping) string { type portGroup struct { first int32 @@ -750,7 +750,7 @@ func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtim return runLabel, imageName, err } -// GenerateRunlabelCommand generates the command that will eventually be execucted by podman. +// GenerateRunlabelCommand generates the command that will eventually be execucted by Podman. func GenerateRunlabelCommand(runLabel, imageName, name string, opts map[string]string, extraArgs []string, globalOpts string) ([]string, []string, error) { // If no name is provided, we use the image's basename instead. if name == "" { @@ -809,7 +809,7 @@ func envSliceToMap(env []string) map[string]string { return m } -// GenerateKube generates kubernetes yaml based on a pod or container +// GenerateKube generates kubernetes yaml based on a pod or container. func GenerateKube(name string, service bool, r *libpod.Runtime) (*v1.Pod, *v1.Service, error) { var ( pod *libpod.Pod diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 84cba4b75..e29e6b28e 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -55,7 +55,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. rootfs = c.InputArgs[0] } - if c.IsSet("cidfile") && os.Geteuid() == 0 { + if c.IsSet("cidfile") { cidFile, err = util.OpenExclusiveFile(c.String("cidfile")) if err != nil && os.IsExist(err) { return nil, nil, errors.Errorf("container id file exists. Ensure another container is not using it or delete %s", c.String("cidfile")) @@ -70,8 +70,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. imageName := "" var data *inspect.ImageData = nil - // Set the storage if we are running as euid == 0 and there is no rootfs specified - if rootfs == "" && os.Geteuid() == 0 { + // Set the storage if there is no rootfs specified + if rootfs == "" { var writer io.Writer if !c.Bool("quiet") { writer = os.Stderr diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go index 3accae1b6..2f696445e 100644 --- a/cmd/podman/stats.go +++ b/cmd/podman/stats.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "os" "reflect" "strings" "time" @@ -13,6 +12,8 @@ import ( "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -66,8 +67,14 @@ func init() { } func statsCmd(c *cliconfig.StatsValues) error { - if os.Geteuid() != 0 { - return errors.New("stats is not supported for rootless containers") + if rootless.IsRootless() { + unified, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return err + } + if !unified { + return errors.New("stats is not supported in rootless mode without cgroups v2") + } } all := c.All diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 5d350263e..ab7279b11 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -44,6 +44,11 @@ case "${OS_REL_VER}" in ;; fedora-30) ;& # continue to next item fedora-29) + # There is no crun package on Fedora29 + if test "${OS_REL_VER}" != "fedora-29"; then + yum install -y crun + fi + if [[ "$ADD_SECOND_PARTITION" == "true" ]]; then bash "$SCRIPT_BASE/add_second_partition.sh"; fi ;; diff --git a/libpod/image/docker_registry_options.go b/libpod/image/docker_registry_options.go index c191a3ca2..60bb3c33f 100644 --- a/libpod/image/docker_registry_options.go +++ b/libpod/image/docker_registry_options.go @@ -1,8 +1,12 @@ package image import ( + "fmt" + "github.com/containers/image/docker/reference" "github.com/containers/image/types" + + podmanVersion "github.com/containers/libpod/version" ) // DockerRegistryOptions encapsulates settings that affect how we connect or @@ -36,6 +40,7 @@ func (o DockerRegistryOptions) GetSystemContext(parent *types.SystemContext, add sc.SignaturePolicyPath = parent.SignaturePolicyPath sc.AuthFilePath = parent.AuthFilePath sc.DirForceCompress = parent.DirForceCompress + sc.DockerRegistryUserAgent = parent.DockerRegistryUserAgent } return sc } @@ -48,5 +53,7 @@ func GetSystemContext(signaturePolicyPath, authFilePath string, forceCompress bo } sc.AuthFilePath = authFilePath sc.DirForceCompress = forceCompress + sc.DockerRegistryUserAgent = fmt.Sprintf("libpod/%s", podmanVersion.Version) + return sc } diff --git a/libpod/oci_internal_linux.go b/libpod/oci_internal_linux.go index 52cebefab..e2c73f5ed 100644 --- a/libpod/oci_internal_linux.go +++ b/libpod/oci_internal_linux.go @@ -352,31 +352,29 @@ func startCommandGivenSelinux(cmd *exec.Cmd) error { // it then signals for conmon to start by sending nonse data down the start fd func (r *OCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec.Cmd, startFd *os.File, uuid string) error { cgroupParent := ctr.CgroupParent() - if os.Geteuid() == 0 { - if r.cgroupManager == SystemdCgroupsManager { - unitName := createUnitName("libpod-conmon", ctr.ID()) - - realCgroupParent := cgroupParent - splitParent := strings.Split(cgroupParent, "/") - if strings.HasSuffix(cgroupParent, ".slice") && len(splitParent) > 1 { - realCgroupParent = splitParent[len(splitParent)-1] - } + if r.cgroupManager == SystemdCgroupsManager { + unitName := createUnitName("libpod-conmon", ctr.ID()) - logrus.Infof("Running conmon under slice %s and unitName %s", realCgroupParent, unitName) - if err := utils.RunUnderSystemdScope(cmd.Process.Pid, realCgroupParent, unitName); err != nil { - logrus.Warnf("Failed to add conmon to systemd sandbox cgroup: %v", err) - } + realCgroupParent := cgroupParent + splitParent := strings.Split(cgroupParent, "/") + if strings.HasSuffix(cgroupParent, ".slice") && len(splitParent) > 1 { + realCgroupParent = splitParent[len(splitParent)-1] + } + + logrus.Infof("Running conmon under slice %s and unitName %s", realCgroupParent, unitName) + if err := utils.RunUnderSystemdScope(cmd.Process.Pid, realCgroupParent, unitName); err != nil { + logrus.Warnf("Failed to add conmon to systemd sandbox cgroup: %v", err) + } + } else { + cgroupPath := filepath.Join(ctr.config.CgroupParent, "conmon") + control, err := cgroups.New(cgroupPath, &spec.LinuxResources{}) + if err != nil { + logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err) } else { - cgroupPath := filepath.Join(ctr.config.CgroupParent, "conmon") - control, err := cgroups.New(cgroupPath, &spec.LinuxResources{}) - if err != nil { + // we need to remove this defer and delete the cgroup once conmon exits + // maybe need a conmon monitor? + if err := control.AddPid(cmd.Process.Pid); err != nil { logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err) - } else { - // we need to remove this defer and delete the cgroup once conmon exits - // maybe need a conmon monitor? - if err := control.AddPid(cmd.Process.Pid); err != nil { - logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err) - } } } } diff --git a/libpod/runtime.go b/libpod/runtime.go index 83799a52b..8a4eee081 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -274,6 +274,8 @@ type runtimeConfiguredFrom struct { runtimePath bool cniPluginDir bool noPivotRoot bool + runtimeSupportsJSON bool + ociRuntime bool } func defaultRuntimeConfig() (RuntimeConfig, error) { @@ -593,6 +595,12 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options .. if tmpConfig.NoPivotRoot { runtime.configuredFrom.noPivotRoot = true } + if tmpConfig.RuntimeSupportsJSON != nil { + runtime.configuredFrom.runtimeSupportsJSON = true + } + if tmpConfig.OCIRuntime != "" { + runtime.configuredFrom.ociRuntime = true + } if _, err := toml.Decode(string(contents), runtime.config); err != nil { return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath) @@ -633,6 +641,13 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options .. if !runtime.configuredFrom.noPivotRoot { runtime.config.NoPivotRoot = tmpConfig.NoPivotRoot } + if !runtime.configuredFrom.runtimeSupportsJSON { + runtime.config.RuntimeSupportsJSON = tmpConfig.RuntimeSupportsJSON + } + if !runtime.configuredFrom.ociRuntime { + runtime.config.OCIRuntime = tmpConfig.OCIRuntime + } + break } } diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index b712bd9aa..45a9a54a3 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -342,7 +342,7 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode if err := ctr.Start(ctx, c.IsSet("pod")); err != nil { // This means the command did not exist exitCode = 127 - if strings.Contains(err.Error(), "permission denied") { + if strings.Contains(err.Error(), "permission denied") || strings.Contains(err.Error(), "file not found") { exitCode = 126 } return exitCode, err diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index 4a3b41297..03419c0bd 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -288,9 +288,8 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti options.CommonBuildOpts = commonOpts options.SystemContext = systemContext - if c.Flag("runtime").Changed { - options.Runtime = r.GetOCIRuntimePath() - } + options.Runtime = r.GetOCIRuntimePath() + if c.Quiet { options.ReportWriter = ioutil.Discard } diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 19b76f387..94933ddd0 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -137,7 +137,7 @@ get_cmd_line_args (pid_t pid) { allocated += 512; char *tmp = realloc (buffer, allocated); - if (buffer == NULL) + if (tmp == NULL) { free (buffer); return NULL; @@ -276,7 +276,7 @@ static void __attribute__((constructor)) init() return; } - r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf))); + r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf) - 1)); close (fd); if (r < 0) { @@ -457,6 +457,11 @@ create_pause_process (const char *pause_pid_file_path, char **argv) } r = TEMP_FAILURE_RETRY (write (p[1], "0", 1)); + if (r < 0) + { + fprintf (stderr, "cannot write to pipe: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } close (p[1]); _exit (EXIT_SUCCESS); @@ -811,6 +816,11 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re } ret = TEMP_FAILURE_RETRY (write (ready, "0", 1)); + if (ret < 0) + { + fprintf (stderr, "cannot write to ready pipe: %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } close (ready); if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0) diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go index e0bb48a9c..a8dc7f4a8 100644 --- a/pkg/spec/storage.go +++ b/pkg/spec/storage.go @@ -238,11 +238,6 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount, // Conflicts are resolved simply - the last container specified wins. // Container names may be suffixed by mount options after a colon. func (config *CreateConfig) getVolumesFrom(runtime *libpod.Runtime) (map[string]spec.Mount, map[string]*libpod.ContainerNamedVolume, error) { - // TODO: This can probably be disabled now - if os.Geteuid() != 0 { - return nil, nil, nil - } - // Both of these are maps of mount destination to mount type. // We ensure that each destination is only mounted to once in this way. finalMounts := make(map[string]spec.Mount) diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index 6cf78a25c..3f9639fda 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -179,6 +179,8 @@ var _ = Describe("Podman exec", func() { }) It("podman exec cannot be invoked", func() { + SkipIfNotRunc() + setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) @@ -189,6 +191,8 @@ var _ = Describe("Podman exec", func() { }) It("podman exec command not found", func() { + SkipIfNotRunc() + setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go index 7f33fec87..a6cedfc58 100644 --- a/test/e2e/libpod_suite_remoteclient_test.go +++ b/test/e2e/libpod_suite_remoteclient_test.go @@ -28,6 +28,13 @@ func SkipIfRootless() { } } +func SkipIfNotRunc() { + runtime := os.Getenv("OCI_RUNTIME") + if runtime != "" && filepath.Base(runtime) != "runc" { + ginkgo.Skip("Not using runc as runtime") + } +} + // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { podmanSession := p.PodmanBase(args, false, false) diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 1df59dbe3..22cc14d6b 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -21,6 +21,13 @@ func SkipIfRootless() { } } +func SkipIfNotRunc() { + runtime := os.Getenv("OCI_RUNTIME") + if runtime != "" && filepath.Base(runtime) != "runc" { + ginkgo.Skip("Not using runc as runtime") + } +} + // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { podmanSession := p.PodmanBase(args, false, false) diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go index 861d6b3b7..b05849ddb 100644 --- a/test/e2e/run_exit_test.go +++ b/test/e2e/run_exit_test.go @@ -41,12 +41,16 @@ var _ = Describe("Podman run exit", func() { }) It("podman run exit 126", func() { + SkipIfNotRunc() + result := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(126)) }) It("podman run exit 127", func() { + SkipIfNotRunc() + result := podmanTest.Podman([]string{"run", ALPINE, "foobar"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(127)) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index f66d1d2fa..1420a8403 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -353,6 +353,8 @@ var _ = Describe("Podman run", func() { It("podman run notify_socket", func() { SkipIfRemote() + SkipIfNotRunc() + host := GetHostDistributionInfo() if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" { Skip("this test requires a working runc") @@ -563,6 +565,7 @@ var _ = Describe("Podman run", func() { }) It("podman run exit code on failure to exec", func() { + SkipIfNotRunc() session := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(126)) diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index fc1203ed1..2dbb9545b 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -101,6 +101,8 @@ var _ = Describe("Podman start", func() { }) It("podman failed to start with --rm should delete the container", func() { + SkipIfNotRunc() + session := podmanTest.Podman([]string{"create", "-it", "--rm", ALPINE, "foo"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -114,6 +116,8 @@ var _ = Describe("Podman start", func() { }) It("podman failed to start without --rm should NOT delete the container", func() { + SkipIfNotRunc() + session := podmanTest.Podman([]string{"create", "-it", ALPINE, "foo"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) |