diff options
-rw-r--r-- | .cirrus.yml | 16 | ||||
-rw-r--r-- | cmd/podman/imagefilters/filters.go | 24 | ||||
-rw-r--r-- | cmd/podman/images.go | 3 | ||||
-rw-r--r-- | cmd/podman/kill.go | 73 | ||||
-rw-r--r-- | cmd/podman/play_kube.go | 51 | ||||
-rw-r--r-- | contrib/cirrus/lib.sh | 15 | ||||
-rw-r--r-- | contrib/cirrus/packer/centos_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/fedora_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/rhel_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/ubuntu_setup.sh | 1 | ||||
-rwxr-xr-x | contrib/cirrus/setup_environment.sh | 4 | ||||
-rw-r--r-- | libpod/container_internal.go | 17 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 48 | ||||
-rw-r--r-- | libpod/runtime.go | 25 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 24 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 25 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 4 | ||||
-rw-r--r-- | test/e2e/images_test.go | 27 | ||||
-rw-r--r-- | test/e2e/pod_infra_container_test.go | 17 |
19 files changed, 293 insertions, 84 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 4521866d1..b473980ea 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -27,11 +27,11 @@ env: #### #### Cache-image names to test with ### - FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-7f4cd1f7" - PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-7f4cd1f7" - UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-84514d8b" + FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-d6d53e40" + PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-d6d53e40" + UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-d6d53e40" # RHEL_CACHE_IMAGE_NAME: "rhel-8-notready" - PRIOR_RHEL_CACHE_IMAGE_NAME: "rhel-7-libpod-7f4cd1f7" + PRIOR_RHEL_CACHE_IMAGE_NAME: "rhel-7-libpod-d6d53e40" # CENTOS_CACHE_IMAGE_NAME: "centos-7-notready" #### @@ -169,9 +169,9 @@ testing_task: image_name: "${FEDORA_CACHE_IMAGE_NAME}" image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}" image_name: "${UBUNTU_CACHE_IMAGE_NAME}" - image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}" - # TODO: tests fail + # TODO: Make these work (also optional_testing_task below) + # image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}" # image_name: "${RHEL_CACHE_IMAGE_NAME}" # image_name: "${CENTOS_CACHE_IMAGE_NAME}" @@ -206,9 +206,9 @@ optional_testing_task: image_name: "${FEDORA_CACHE_IMAGE_NAME}" image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}" image_name: "${UBUNTU_CACHE_IMAGE_NAME}" - image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}" - # TODO: Make these work (also build_images_task below) + # TODO: Make these work (also testing_task above) # image_name: "${RHEL_CACHE_IMAGE_NAME}" + # image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}" # image_name: "${CENTOS_CACHE_IMAGE_NAME}" timeout_in: 60m diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go index d01eb7436..2932d61c0 100644 --- a/cmd/podman/imagefilters/filters.go +++ b/cmd/podman/imagefilters/filters.go @@ -2,11 +2,14 @@ package imagefilters import ( "context" + "fmt" + "path/filepath" "strings" "time" "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/inspect" + "github.com/sirupsen/logrus" ) // ResultFilter is a mock function for image filtering @@ -61,6 +64,27 @@ func LabelFilter(ctx context.Context, labelfilter string) ResultFilter { } } +// ReferenceFilter allows you to filter by image name +// Replacing all '/' with '|' so that filepath.Match() can work +// '|' character is not valid in image name, so this is safe +func ReferenceFilter(ctx context.Context, referenceFilter string) ResultFilter { + filter := fmt.Sprintf("*%s*", referenceFilter) + filter = strings.Replace(filter, "/", "|", -1) + return func(i *adapter.ContainerImage) bool { + for _, name := range i.Names() { + newName := strings.Replace(name, "/", "|", -1) + match, err := filepath.Match(filter, newName) + if err != nil { + logrus.Errorf("failed to match %s and %s, %q", name, referenceFilter, err) + } + if match { + return true + } + } + return false + } +} + // OutputImageFilter allows you to filter by an a specific image name func OutputImageFilter(userImage *adapter.ContainerImage) ResultFilter { return func(i *adapter.ContainerImage) bool { diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 26e51bef7..a4f2e5e10 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -375,6 +375,9 @@ func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, filters []s case "label": labelFilter := strings.Join(splitFilter[1:], "=") filterFuncs = append(filterFuncs, imagefilters.LabelFilter(ctx, labelFilter)) + case "reference": + referenceFilter := strings.Join(splitFilter[1:], "=") + filterFuncs = append(filterFuncs, imagefilters.ReferenceFilter(ctx, referenceFilter)) default: return nil, errors.Errorf("invalid filter %s ", splitFilter[0]) } diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go index 76d2516b7..82a257e23 100644 --- a/cmd/podman/kill.go +++ b/cmd/podman/kill.go @@ -2,16 +2,15 @@ package main import ( "fmt" - "syscall" + "reflect" + + "github.com/containers/libpod/pkg/adapter" + "github.com/opentracing/opentracing-go" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/cmd/podman/shared" - "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/rootless" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -51,54 +50,44 @@ func init() { // killCmd kills one or more containers with a signal func killCmd(c *cliconfig.KillValues) error { - var ( - killFuncs []shared.ParallelWorkerInput - killSignal uint = uint(syscall.SIGTERM) - ) + if c.Bool("trace") { + span, _ := opentracing.StartSpanFromContext(Ctx, "killCmd") + defer span.Finish() + } + + // Check if the signalString provided by the user is valid + // Invalid signals will return err + killSignal, err := signal.ParseSignal(c.Signal) + if err != nil { + return err + } rootless.SetSkipStorageSetup(true) - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - if c.Signal != "" { - // Check if the signalString provided by the user is valid - // Invalid signals will return err - sysSignal, err := signal.ParseSignal(c.Signal) - if err != nil { - return err - } - killSignal = uint(sysSignal) - } - - containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running") + ok, failures, err := runtime.KillContainers(getContext(), c, killSignal) if err != nil { - if len(containers) == 0 { - return err - } - fmt.Println(err.Error()) + return err } - for _, ctr := range containers { - con := ctr - f := func() error { - return con.Kill(killSignal) - } - - killFuncs = append(killFuncs, shared.ParallelWorkerInput{ - ContainerID: con.ID(), - ParallelFunc: f, - }) + for _, id := range ok { + fmt.Println(id) } - maxWorkers := shared.Parallelize("kill") - if c.GlobalIsSet("max-workers") { - maxWorkers = c.GlobalFlags.MaxWorks - } - logrus.Debugf("Setting maximum workers to %d", maxWorkers) + if len(failures) > 0 { + keys := reflect.ValueOf(failures).MapKeys() + lastKey := keys[len(keys)-1].String() + lastErr := failures[lastKey] + delete(failures, lastKey) - killErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, killFuncs) - return printParallelOutput(killErrors, errCount) + for _, err := range failures { + outputError(err) + } + return lastErr + } + return nil } diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index ac46ad5c6..1910b68b5 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -25,6 +25,11 @@ import ( "k8s.io/api/core/v1" ) +const ( + // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + createDirectoryPermission = 0755 +) + var ( playKubeCommand cliconfig.KubePlayValues playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML" @@ -144,12 +149,41 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error { dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify) } + // map from name to mount point + volumes := make(map[string]string) + for _, volume := range podYAML.Spec.Volumes { + hostPath := volume.VolumeSource.HostPath + if hostPath == nil { + return errors.Errorf("HostPath is currently the only supported VolumeSource") + } + if hostPath.Type != nil { + switch *hostPath.Type { + case v1.HostPathDirectoryOrCreate: + if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) { + if err := os.Mkdir(hostPath.Path, createDirectoryPermission); err != nil { + return errors.Errorf("Error creating HostPath %s at %s", volume.Name, hostPath.Path) + } + } + case v1.HostPathDirectory: + // do nothing here because we will verify the path exists in validateVolumeHostDir + break + default: + return errors.Errorf("Directories are the only supported HostPath type") + } + } + if err := validateVolumeHostDir(hostPath.Path); err != nil { + return errors.Wrapf(err, "Error in parsing HostPath in YAML") + } + fmt.Println(volume.Name) + volumes[volume.Name] = hostPath.Path + } + for _, container := range podYAML.Spec.Containers { newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil) if err != nil { return err } - createConfig := kubeContainerToCreateConfig(container, runtime, newImage, namespaces) + createConfig, err := kubeContainerToCreateConfig(container, runtime, newImage, namespaces, volumes) if err != nil { return err } @@ -194,7 +228,7 @@ func getPodPorts(containers []v1.Container) []ocicni.PortMapping { } // kubeContainerToCreateConfig takes a v1.Container and returns a createconfig describing a container -func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Runtime, newImage *image2.Image, namespaces map[string]string) *createconfig.CreateConfig { +func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Runtime, newImage *image2.Image, namespaces map[string]string, volumes map[string]string) (*createconfig.CreateConfig, error) { var ( containerConfig createconfig.CreateConfig envs map[string]string @@ -239,6 +273,17 @@ func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Run for _, e := range containerYAML.Env { envs[e.Name] = e.Value } + + for _, volume := range containerYAML.VolumeMounts { + host_path, exists := volumes[volume.Name] + if !exists { + return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name) + } + if err := validateVolumeCtrDir(volume.MountPath); err != nil { + return nil, errors.Wrapf(err, "error in parsing MountPath") + } + containerConfig.Volumes = append(containerConfig.Volumes, fmt.Sprintf("%s:%s", host_path, volume.MountPath)) + } containerConfig.Env = envs - return &containerConfig + return &containerConfig, nil } diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 8be696933..acd2447c0 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -300,21 +300,6 @@ EOF fi } -# Runs in testing VM, not image building -install_testing_dependencies() { - echo "Installing ginkgo, gomega, and easyjson into \$GOPATH=$GOPATH" - req_env_var " - GOPATH $GOPATH - GOSRC $GOSRC - " - cd "$GOSRC" - ooe.sh go get -u github.com/onsi/ginkgo/ginkgo - ooe.sh install -D -m 755 "$GOPATH"/bin/ginkgo /usr/bin/ - ooe.sh go get github.com/onsi/gomega/... - ooe.sh go get -u github.com/mailru/easyjson/... - sudo install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/ -} - install_packer_copied_files(){ # Install cni config, policy and registry config sudo install -D -m 755 /tmp/libpod/cni/87-podman-bridge.conflist \ diff --git a/contrib/cirrus/packer/centos_setup.sh b/contrib/cirrus/packer/centos_setup.sh index 923f2563b..d947a1d7f 100644 --- a/contrib/cirrus/packer/centos_setup.sh +++ b/contrib/cirrus/packer/centos_setup.sh @@ -27,6 +27,7 @@ ooe.sh sudo yum -y install centos-release-scl epel-release ooe.sh sudo yum -y install \ PyYAML \ atomic-registries \ + bats \ btrfs-progs-devel \ bzip2 \ device-mapper-devel \ diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh index de7ad4506..84aee7667 100644 --- a/contrib/cirrus/packer/fedora_setup.sh +++ b/contrib/cirrus/packer/fedora_setup.sh @@ -26,6 +26,7 @@ ooe.sh sudo dnf update -y ooe.sh sudo dnf install -y \ atomic-registries \ + bats \ btrfs-progs-devel \ bzip2 \ device-mapper-devel \ diff --git a/contrib/cirrus/packer/rhel_setup.sh b/contrib/cirrus/packer/rhel_setup.sh index ac6866a57..20be97f9b 100644 --- a/contrib/cirrus/packer/rhel_setup.sh +++ b/contrib/cirrus/packer/rhel_setup.sh @@ -33,6 +33,7 @@ ooe.sh sudo yum -y update ooe.sh sudo yum -y install \ PyYAML \ atomic-registries \ + bats \ btrfs-progs-devel \ bzip2 \ device-mapper-devel \ diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh index 5b7e1d714..24f1cce21 100644 --- a/contrib/cirrus/packer/ubuntu_setup.sh +++ b/contrib/cirrus/packer/ubuntu_setup.sh @@ -38,6 +38,7 @@ ooe.sh sudo -E apt-get -qq install \ apparmor \ autoconf \ automake \ + bats \ bison \ btrfs-tools \ build-essential \ diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 77c20d9bd..c3276bb6f 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -78,10 +78,6 @@ then cd "${GOSRC}/" source "$SCRIPT_BASE/lib.sh" - - # Only testing-VMs need deps installed, not image-builder VM - echo "$CIRRUS_TASK_NAME" | grep -q 'image' || \ - install_testing_dependencies # must exist in $GOPATH fi record_timestamp "env. setup end" diff --git a/libpod/container_internal.go b/libpod/container_internal.go index e3753d825..08945c410 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1231,6 +1231,23 @@ func (c *Container) writeStringToRundir(destFile, output string) (string, error) return filepath.Join(c.state.DestinationRunDir, destFile), nil } +// appendStringToRundir appends the provided string to the runtimedir file +func (c *Container) appendStringToRundir(destFile, output string) (string, error) { + destFileName := filepath.Join(c.state.RunDir, destFile) + + f, err := os.OpenFile(destFileName, os.O_APPEND|os.O_WRONLY, 0600) + if err != nil { + return "", errors.Wrapf(err, "unable to open %s", destFileName) + } + defer f.Close() + + if _, err := f.WriteString(output); err != nil { + return "", errors.Wrapf(err, "unable to write %s", destFileName) + } + + return filepath.Join(c.state.DestinationRunDir, destFile), nil +} + // Save OCI spec to disk, replacing any existing specs for the container func (c *Container) saveSpec(spec *spec.Spec) error { // If the OCI spec already exists, we need to replace it diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 0e9a5124e..5f9e5a20c 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -698,13 +698,29 @@ func (c *Container) makeBindMounts() error { // If it doesn't, don't copy them resolvPath, exists := bindMounts["/etc/resolv.conf"] if exists { - c.state.BindMounts["/etc/resolv.conf"] = resolvPath } + + // check if dependency container has an /etc/hosts file hostsPath, exists := bindMounts["/etc/hosts"] - if exists { - c.state.BindMounts["/etc/hosts"] = hostsPath + if !exists { + return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID()) + } + + depCtr.lock.Lock() + // generate a hosts file for the dependency container, + // based on either its old hosts file, or the default, + // and add the relevant information from the new container (hosts and IP) + hostsPath, err = depCtr.appendHosts(hostsPath, c) + + if err != nil { + depCtr.lock.Unlock() + return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID()) } + depCtr.lock.Unlock() + + // finally, save it in the new container + c.state.BindMounts["/etc/hosts"] = hostsPath } else { newResolv, err := c.generateResolvConf() if err != nil { @@ -712,7 +728,7 @@ func (c *Container) makeBindMounts() error { } c.state.BindMounts["/etc/resolv.conf"] = newResolv - newHosts, err := c.generateHosts() + newHosts, err := c.generateHosts("/etc/hosts") if err != nil { return errors.Wrapf(err, "error creating hosts file for container %s", c.ID()) } @@ -854,12 +870,28 @@ func (c *Container) generateResolvConf() (string, error) { } // generateHosts creates a containers hosts file -func (c *Container) generateHosts() (string, error) { - orig, err := ioutil.ReadFile("/etc/hosts") +func (c *Container) generateHosts(path string) (string, error) { + orig, err := ioutil.ReadFile(path) if err != nil { - return "", errors.Wrapf(err, "unable to read /etc/hosts") + return "", errors.Wrapf(err, "unable to read %s", path) } hosts := string(orig) + hosts += c.getHosts() + return c.writeStringToRundir("hosts", hosts) +} + +// appendHosts appends a container's config and state pertaining to hosts to a container's +// local hosts file. netCtr is the container from which the netNS information is +// taken. +// path is the basis of the hosts file, into which netCtr's netNS information will be appended. +func (c *Container) appendHosts(path string, netCtr *Container) (string, error) { + return c.appendStringToRundir("hosts", netCtr.getHosts()) +} + +// getHosts finds the pertinent information for a container's host file in its config and state +// and returns a string in a format that can be written to the host file +func (c *Container) getHosts() string { + var hosts string if len(c.config.HostAdd) > 0 { for _, host := range c.config.HostAdd { // the host format has already been verified at this point @@ -871,7 +903,7 @@ func (c *Container) generateHosts() (string, error) { ipAddress := strings.Split(c.state.NetworkStatus[0].IPs[0].Address.String(), "/")[0] hosts += fmt.Sprintf("%s\t%s\n", ipAddress, c.Hostname()) } - return c.writeStringToRundir("hosts", hosts) + return hosts } // generatePasswd generates a container specific passwd file, diff --git a/libpod/runtime.go b/libpod/runtime.go index 112b6820a..482cd9d73 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -333,7 +333,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { storageConf, err := util.GetDefaultStoreOptions() if err != nil { - return nil, errors.Wrapf(err, "error retrieving rootless storage config") + return nil, errors.Wrapf(err, "error retrieving storage config") } runtime.config.StorageConfig = storageConf runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod") @@ -365,8 +365,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { // containers/image uses XDG_RUNTIME_DIR to locate the auth file. // So make sure the env variable is set. - err = SetXdgRuntimeDir(runtimeDir) - if err != nil { + if err := SetXdgRuntimeDir(runtimeDir); err != nil { return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") } @@ -475,13 +474,31 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime // Set three fields not in the TOML config runtime.config.StateType = defaultRuntimeConfig.StateType runtime.config.OCIRuntime = defaultRuntimeConfig.OCIRuntime - runtime.config.StorageConfig = storage.StoreOptions{} + + storageConf, err := util.GetDefaultStoreOptions() + if err != nil { + return nil, errors.Wrapf(err, "error retrieving storage config") + } + runtime.config.StorageConfig = storageConf + runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod") + runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes") tmpDir, err := getDefaultTmpDir() if err != nil { return nil, err } runtime.config.TmpDir = tmpDir + if rootless.IsRootless() { + runtimeDir, err := util.GetRootlessRuntimeDir() + if err != nil { + return nil, err + } + // containers/image uses XDG_RUNTIME_DIR to locate the auth file. + // So make sure the env variable is set. + if err := SetXdgRuntimeDir(runtimeDir); err != nil { + return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") + } + } // Check to see if the given configuration file exists if _, err := os.Stat(configPath); err != nil { diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 7514f30d2..fcce9bb86 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -4,6 +4,7 @@ package adapter import ( "context" + "syscall" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod" @@ -79,3 +80,26 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa } return ok, failures, nil } + +// KillContainers sends signal to container(s) based on CLI inputs. +// Returns list of successful id(s), map of failed id(s) + error, or error not from container +func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ) + + ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + return ok, failures, err + } + + for _, c := range ctrs { + if err := c.Kill(uint(signal)); err == nil { + ok = append(ok, c.ID()) + } else { + failures[c.ID()] = err + } + } + return ok, failures, nil +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index df40c8efd..45926ccf9 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -6,6 +6,7 @@ import ( "context" "encoding/json" "errors" + "syscall" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" @@ -148,6 +149,30 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa return ok, failures, nil } +// KillContainers sends signal to container(s) based on CLI inputs. +// Returns list of successful id(s), map of failed id(s) + error, or error not from container +func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ) + + ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) + if err != nil { + return ok, failures, err + } + + for _, id := range ids { + killed, err := iopodman.KillContainer().Call(r.Conn, id, int64(signal)) + if err != nil { + failures[id] = err + } else { + ok = append(ok, killed) + } + } + return ok, failures, nil +} + // BatchContainerOp is wrapper func to mimic shared's function with a similar name meant for libpod func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContainerStruct, error) { // TODO If pod ps ever shows container's sizes, re-enable this code; otherwise it isn't needed diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index dfbc7fe33..41acd3475 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -32,7 +32,11 @@ syscall_setresgid (gid_t rgid, gid_t egid, gid_t sgid) static int syscall_clone (unsigned long flags, void *child_stack) { +#if defined(__s390__) || defined(__CRIS__) + return (int) syscall (__NR_clone, child_stack, flags); +#else return (int) syscall (__NR_clone, flags, child_stack); +#endif } static char ** diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go index e26f4affd..4cf58e5bf 100644 --- a/test/e2e/images_test.go +++ b/test/e2e/images_test.go @@ -114,6 +114,33 @@ var _ = Describe("Podman images", func() { Expect(len(session.OutputToStringArray())).To(Equal(1)) }) + It("podman images filter reference", func() { + if podmanTest.RemoteTest { + Skip("Does not work on remote client") + } + result := podmanTest.Podman([]string{"images", "-q", "-f", "reference=docker.io*"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(Equal(2)) + + retapline := podmanTest.Podman([]string{"images", "-f", "reference=a*pine"}) + retapline.WaitWithDefaultTimeout() + Expect(retapline.ExitCode()).To(Equal(0)) + Expect(len(retapline.OutputToStringArray())).To(Equal(2)) + Expect(retapline.LineInOutputContains("alpine")) + + retapline = podmanTest.Podman([]string{"images", "-f", "reference=alpine"}) + retapline.WaitWithDefaultTimeout() + Expect(retapline.ExitCode()).To(Equal(0)) + Expect(len(retapline.OutputToStringArray())).To(Equal(2)) + Expect(retapline.LineInOutputContains("alpine")) + + retnone := podmanTest.Podman([]string{"images", "-q", "-f", "reference=bogus"}) + retnone.WaitWithDefaultTimeout() + Expect(retnone.ExitCode()).To(Equal(0)) + Expect(len(retnone.OutputToStringArray())).To(Equal(0)) + }) + It("podman images filter before image", func() { if podmanTest.RemoteTest { Skip("Does not work on remote client") diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go index ed5002ca7..d9e5d380a 100644 --- a/test/e2e/pod_infra_container_test.go +++ b/test/e2e/pod_infra_container_test.go @@ -360,4 +360,21 @@ var _ = Describe("Podman pod create", func() { Expect(result.OutputToString()).To(ContainSubstring(infraID)) }) + + It("podman run --add-host in pod", func() { + session := podmanTest.Podman([]string{"pod", "create"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + podID := session.OutputToString() + + // verify we can add a host to the infra's /etc/hosts + session = podmanTest.Podman([]string{"run", "--pod", podID, "--add-host", "foobar:127.0.0.1", BB, "ping", "-c", "1", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // verify we can see the other hosts of infra's /etc/hosts + session = podmanTest.Podman([]string{"run", "--pod", podID, BB, "ping", "-c", "1", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) |