aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/create_opts.go291
-rw-r--r--cmd/podman/containers/create.go1
-rw-r--r--cmd/podman/containers/run.go1
-rw-r--r--cmd/podman/images/pull.go4
-rw-r--r--cmd/podman/images/push.go2
-rw-r--r--cmd/podman/manifest/add.go2
-rw-r--r--cmd/podman/manifest/push.go2
-rw-r--r--cmd/podman/play/kube.go4
-rwxr-xr-xcontrib/cirrus/setup_environment.sh4
-rw-r--r--docs/source/markdown/podman-auto-update.1.md2
-rw-r--r--docs/source/markdown/podman-build.1.md4
-rw-r--r--docs/source/markdown/podman-container-runlabel.1.md4
-rw-r--r--docs/source/markdown/podman-create.1.md2
-rw-r--r--docs/source/markdown/podman-login.1.md4
-rw-r--r--docs/source/markdown/podman-logout.1.md2
-rw-r--r--docs/source/markdown/podman-manifest-add.1.md4
-rw-r--r--docs/source/markdown/podman-manifest-push.1.md4
-rw-r--r--docs/source/markdown/podman-play-kube.1.md4
-rw-r--r--docs/source/markdown/podman-pull.1.md4
-rw-r--r--docs/source/markdown/podman-push.1.md4
-rw-r--r--docs/source/markdown/podman-run.1.md2
-rw-r--r--libpod/boltdb_state_internal.go30
-rw-r--r--libpod/container_internal_linux.go28
-rw-r--r--libpod/networking_linux.go14
-rw-r--r--libpod/runtime.go19
-rw-r--r--libpod/runtime_ctr.go5
-rw-r--r--libpod/shutdown/handler.go131
-rw-r--r--pkg/api/handlers/compat/containers_create.go237
-rw-r--r--pkg/api/handlers/compat/images_search.go20
-rw-r--r--pkg/api/handlers/libpod/images.go8
-rw-r--r--pkg/api/server/server.go24
-rw-r--r--pkg/domain/infra/abi/terminal/sigproxy_linux.go5
-rw-r--r--pkg/specgen/generate/namespaces.go2
-rw-r--r--pkg/specgen/generate/oci.go2
-rw-r--r--test/apiv2/01-basic.at8
-rw-r--r--test/apiv2/20-containers.at10
-rwxr-xr-xtest/apiv2/test-apiv233
-rw-r--r--test/e2e/common_test.go15
-rw-r--r--test/e2e/pod_create_test.go18
-rw-r--r--test/e2e/run_networking_test.go15
-rw-r--r--test/e2e/search_test.go23
-rw-r--r--test/e2e/toolbox_test.go8
-rw-r--r--test/endpoint/setup.go9
-rw-r--r--test/system/030-run.bats13
-rw-r--r--test/system/260-sdnotify.bats2
-rw-r--r--test/system/helpers.bash10
46 files changed, 707 insertions, 333 deletions
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index 83a25f4ab..f4fecf4b7 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -1,6 +1,15 @@
package common
-import "github.com/containers/podman/v2/pkg/domain/entities"
+import (
+ "fmt"
+ "net"
+ "strconv"
+ "strings"
+
+ "github.com/containers/podman/v2/pkg/api/handlers"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/specgen"
+)
type ContainerCLIOpts struct {
Annotation []string
@@ -111,3 +120,283 @@ type ContainerCLIOpts struct {
CgroupConf []string
}
+
+func stringMaptoArray(m map[string]string) []string {
+ a := make([]string, 0, len(m))
+ for k, v := range m {
+ a = append(a, fmt.Sprintf("%s=%s", k, v))
+ }
+ return a
+}
+
+// ContainerCreateToContainerCLIOpts converts a compat input struct to cliopts so it can be converted to
+// a specgen spec.
+func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig) (*ContainerCLIOpts, []string, error) {
+ var (
+ capAdd []string
+ cappDrop []string
+ entrypoint string
+ init bool
+ specPorts []specgen.PortMapping
+ )
+
+ if cc.HostConfig.Init != nil {
+ init = *cc.HostConfig.Init
+ }
+
+ // Iterate devices and convert back to string
+ devices := make([]string, 0, len(cc.HostConfig.Devices))
+ for _, dev := range cc.HostConfig.Devices {
+ devices = append(devices, fmt.Sprintf("%s:%s:%s", dev.PathOnHost, dev.PathInContainer, dev.CgroupPermissions))
+ }
+
+ // iterate blkreaddevicebps
+ readBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadBps))
+ for _, dev := range cc.HostConfig.BlkioDeviceReadBps {
+ readBps = append(readBps, dev.String())
+ }
+
+ // iterate blkreaddeviceiops
+ readIops := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadIOps))
+ for _, dev := range cc.HostConfig.BlkioDeviceReadIOps {
+ readIops = append(readIops, dev.String())
+ }
+
+ // iterate blkwritedevicebps
+ writeBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceWriteBps))
+ for _, dev := range cc.HostConfig.BlkioDeviceWriteBps {
+ writeBps = append(writeBps, dev.String())
+ }
+
+ // iterate blkwritedeviceiops
+ writeIops := make([]string, 0, len(cc.HostConfig.BlkioDeviceWriteIOps))
+ for _, dev := range cc.HostConfig.BlkioDeviceWriteIOps {
+ writeIops = append(writeIops, dev.String())
+ }
+
+ // entrypoint
+ // can be a string or slice. if it is a slice, we need to
+ // marshall it to json; otherwise it should just be the string
+ // value
+ if len(cc.Config.Entrypoint) > 0 {
+ entrypoint = cc.Config.Entrypoint[0]
+ if len(cc.Config.Entrypoint) > 1 {
+ b, err := json.Marshal(cc.Config.Entrypoint)
+ if err != nil {
+ return nil, nil, err
+ }
+ entrypoint = string(b)
+ }
+ }
+
+ // expose ports
+ expose := make([]string, 0, len(cc.Config.ExposedPorts))
+ for p := range cc.Config.ExposedPorts {
+ expose = append(expose, fmt.Sprintf("%s/%s", p.Port(), p.Proto()))
+ }
+
+ // mounts type=tmpfs/bind,source=,dest=,opt=val
+ // TODO options
+ mounts := make([]string, 0, len(cc.HostConfig.Mounts))
+ for _, m := range cc.HostConfig.Mounts {
+ mount := fmt.Sprintf("type=%s", m.Type)
+ if len(m.Source) > 0 {
+ mount += fmt.Sprintf("source=%s", m.Source)
+ }
+ if len(m.Target) > 0 {
+ mount += fmt.Sprintf("dest=%s", m.Target)
+ }
+ mounts = append(mounts, mount)
+ }
+
+ //volumes
+ volumes := make([]string, 0, len(cc.Config.Volumes))
+ for v := range cc.Config.Volumes {
+ volumes = append(volumes, v)
+ }
+
+ // dns
+ dns := make([]net.IP, 0, len(cc.HostConfig.DNS))
+ for _, d := range cc.HostConfig.DNS {
+ dns = append(dns, net.ParseIP(d))
+ }
+
+ // publish
+ for port, pbs := range cc.HostConfig.PortBindings {
+ for _, pb := range pbs {
+ hostport, err := strconv.Atoi(pb.HostPort)
+ if err != nil {
+ return nil, nil, err
+ }
+ tmpPort := specgen.PortMapping{
+ HostIP: pb.HostIP,
+ ContainerPort: uint16(port.Int()),
+ HostPort: uint16(hostport),
+ Range: 0,
+ Protocol: port.Proto(),
+ }
+ specPorts = append(specPorts, tmpPort)
+ }
+ }
+
+ // network names
+ endpointsConfig := cc.NetworkingConfig.EndpointsConfig
+ cniNetworks := make([]string, 0, len(endpointsConfig))
+ for netName := range endpointsConfig {
+ cniNetworks = append(cniNetworks, netName)
+ }
+
+ // netMode
+ nsmode, _, err := specgen.ParseNetworkNamespace(cc.HostConfig.NetworkMode.NetworkName())
+ if err != nil {
+ return nil, nil, err
+ }
+
+ netNS := specgen.Namespace{
+ NSMode: nsmode.NSMode,
+ Value: nsmode.Value,
+ }
+
+ // network
+ // Note: we cannot emulate compat exactly here. we only allow specifics of networks to be
+ // defined when there is only one network.
+ netInfo := entities.NetOptions{
+ AddHosts: cc.HostConfig.ExtraHosts,
+ CNINetworks: cniNetworks,
+ DNSOptions: cc.HostConfig.DNSOptions,
+ DNSSearch: cc.HostConfig.DNSSearch,
+ DNSServers: dns,
+ Network: netNS,
+ PublishPorts: specPorts,
+ }
+
+ // static IP and MAC
+ if len(endpointsConfig) == 1 {
+ for _, ep := range endpointsConfig {
+ // if IP address is provided
+ if len(ep.IPAddress) > 0 {
+ staticIP := net.ParseIP(ep.IPAddress)
+ netInfo.StaticIP = &staticIP
+ }
+ // If MAC address is provided
+ if len(ep.MacAddress) > 0 {
+ staticMac, err := net.ParseMAC(ep.MacAddress)
+ if err != nil {
+ return nil, nil, err
+ }
+ netInfo.StaticMAC = &staticMac
+ }
+ break
+ }
+ }
+
+ // Note: several options here are marked as "don't need". this is based
+ // on speculation by Matt and I. We think that these come into play later
+ // like with start. We believe this is just a difference in podman/compat
+ cliOpts := ContainerCLIOpts{
+ //Attach: nil, // dont need?
+ Authfile: "",
+ BlkIOWeight: strconv.Itoa(int(cc.HostConfig.BlkioWeight)),
+ BlkIOWeightDevice: nil, // TODO
+ CapAdd: append(capAdd, cc.HostConfig.CapAdd...),
+ CapDrop: append(cappDrop, cc.HostConfig.CapDrop...),
+ CGroupParent: cc.HostConfig.CgroupParent,
+ CIDFile: cc.HostConfig.ContainerIDFile,
+ CPUPeriod: uint64(cc.HostConfig.CPUPeriod),
+ CPUQuota: cc.HostConfig.CPUQuota,
+ CPURTPeriod: uint64(cc.HostConfig.CPURealtimePeriod),
+ CPURTRuntime: cc.HostConfig.CPURealtimeRuntime,
+ CPUShares: uint64(cc.HostConfig.CPUShares),
+ //CPUS: 0, // dont need?
+ CPUSetCPUs: cc.HostConfig.CpusetCpus,
+ CPUSetMems: cc.HostConfig.CpusetMems,
+ //Detach: false, // dont need
+ //DetachKeys: "", // dont need
+ Devices: devices,
+ DeviceCGroupRule: nil,
+ DeviceReadBPs: readBps,
+ DeviceReadIOPs: readIops,
+ DeviceWriteBPs: writeBps,
+ DeviceWriteIOPs: writeIops,
+ Entrypoint: &entrypoint,
+ Env: cc.Config.Env,
+ Expose: expose,
+ GroupAdd: cc.HostConfig.GroupAdd,
+ Hostname: cc.Config.Hostname,
+ ImageVolume: "bind",
+ Init: init,
+ Interactive: cc.Config.OpenStdin,
+ IPC: string(cc.HostConfig.IpcMode),
+ Label: stringMaptoArray(cc.Config.Labels),
+ LogDriver: cc.HostConfig.LogConfig.Type,
+ LogOptions: stringMaptoArray(cc.HostConfig.LogConfig.Config),
+ Memory: strconv.Itoa(int(cc.HostConfig.Memory)),
+ MemoryReservation: strconv.Itoa(int(cc.HostConfig.MemoryReservation)),
+ MemorySwap: strconv.Itoa(int(cc.HostConfig.MemorySwap)),
+ Name: cc.Name,
+ OOMScoreAdj: cc.HostConfig.OomScoreAdj,
+ OverrideArch: "",
+ OverrideOS: "",
+ OverrideVariant: "",
+ PID: string(cc.HostConfig.PidMode),
+ PIDsLimit: cc.HostConfig.PidsLimit,
+ Privileged: cc.HostConfig.Privileged,
+ PublishAll: cc.HostConfig.PublishAllPorts,
+ Quiet: false,
+ ReadOnly: cc.HostConfig.ReadonlyRootfs,
+ ReadOnlyTmpFS: true, // podman default
+ Rm: cc.HostConfig.AutoRemove,
+ SecurityOpt: cc.HostConfig.SecurityOpt,
+ ShmSize: strconv.Itoa(int(cc.HostConfig.ShmSize)),
+ StopSignal: cc.Config.StopSignal,
+ StoreageOpt: stringMaptoArray(cc.HostConfig.StorageOpt),
+ Sysctl: stringMaptoArray(cc.HostConfig.Sysctls),
+ Systemd: "true", // podman default
+ TmpFS: stringMaptoArray(cc.HostConfig.Tmpfs),
+ TTY: cc.Config.Tty,
+ //Ulimit: cc.HostConfig.Ulimits, // ask dan, no documented format
+ User: cc.Config.User,
+ UserNS: string(cc.HostConfig.UsernsMode),
+ UTS: string(cc.HostConfig.UTSMode),
+ Mount: mounts,
+ Volume: volumes,
+ VolumesFrom: cc.HostConfig.VolumesFrom,
+ Workdir: cc.Config.WorkingDir,
+ Net: &netInfo,
+ }
+
+ if cc.Config.StopTimeout != nil {
+ cliOpts.StopTimeout = uint(*cc.Config.StopTimeout)
+ }
+
+ if cc.HostConfig.KernelMemory > 0 {
+ cliOpts.KernelMemory = strconv.Itoa(int(cc.HostConfig.KernelMemory))
+ }
+ if len(cc.HostConfig.RestartPolicy.Name) > 0 {
+ policy := cc.HostConfig.RestartPolicy.Name
+ // only add restart count on failure
+ if cc.HostConfig.RestartPolicy.IsOnFailure() {
+ policy += fmt.Sprintf(":%d", cc.HostConfig.RestartPolicy.MaximumRetryCount)
+ }
+ cliOpts.Restart = policy
+ }
+
+ if cc.HostConfig.MemorySwappiness != nil {
+ cliOpts.MemorySwappiness = *cc.HostConfig.MemorySwappiness
+ }
+ if cc.HostConfig.OomKillDisable != nil {
+ cliOpts.OOMKillDisable = *cc.HostConfig.OomKillDisable
+ }
+ if cc.Config.Healthcheck != nil {
+ cliOpts.HealthCmd = strings.Join(cc.Config.Healthcheck.Test, " ")
+ cliOpts.HealthInterval = cc.Config.Healthcheck.Interval.String()
+ cliOpts.HealthRetries = uint(cc.Config.Healthcheck.Retries)
+ cliOpts.HealthStartPeriod = cc.Config.Healthcheck.StartPeriod.String()
+ cliOpts.HealthTimeout = cc.Config.Healthcheck.Timeout.String()
+ }
+
+ // specgen assumes the image name is arg[0]
+ cmd := []string{cc.Image}
+ cmd = append(cmd, cc.Config.Cmd...)
+ return &cliOpts, cmd, nil
+}
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 809162e76..eb96e22b5 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -63,7 +63,6 @@ func createFlags(flags *pflag.FlagSet) {
_ = flags.MarkHidden("signature-policy")
if registry.IsRemote() {
- _ = flags.MarkHidden("authfile")
_ = flags.MarkHidden("http-proxy")
}
}
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index 19c984bbf..cca0e8d1c 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -66,7 +66,6 @@ func runFlags(flags *pflag.FlagSet) {
_ = flags.MarkHidden("signature-policy")
if registry.IsRemote() {
- _ = flags.MarkHidden("authfile")
_ = flags.MarkHidden("http-proxy")
_ = flags.MarkHidden("preserve-fds")
}
diff --git a/cmd/podman/images/pull.go b/cmd/podman/images/pull.go
index 448543b4d..595a2165e 100644
--- a/cmd/podman/images/pull.go
+++ b/cmd/podman/images/pull.go
@@ -84,11 +84,11 @@ func pullFlags(flags *pflag.FlagSet) {
flags.Bool("disable-content-trust", false, "This is a Docker specific option and is a NOOP")
flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.StringVar(&pullOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
+ flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+ flags.StringVar(&pullOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
if !registry.IsRemote() {
- flags.StringVar(&pullOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&pullOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
- flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
}
_ = flags.MarkHidden("signature-policy")
}
diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go
index 2943cccc9..24192eccd 100644
--- a/cmd/podman/images/push.go
+++ b/cmd/podman/images/push.go
@@ -88,11 +88,9 @@ func pushFlags(flags *pflag.FlagSet) {
flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
if registry.IsRemote() {
- _ = flags.MarkHidden("authfile")
_ = flags.MarkHidden("cert-dir")
_ = flags.MarkHidden("compress")
_ = flags.MarkHidden("quiet")
- _ = flags.MarkHidden("tls-verify")
}
_ = flags.MarkHidden("signature-policy")
}
diff --git a/cmd/podman/manifest/add.go b/cmd/podman/manifest/add.go
index 128bf66a7..544d99c11 100644
--- a/cmd/podman/manifest/add.go
+++ b/cmd/podman/manifest/add.go
@@ -56,9 +56,7 @@ func init() {
flags.StringVar(&manifestAddOpts.Variant, "variant", "", "override the `Variant` of the specified image")
if registry.IsRemote() {
- _ = flags.MarkHidden("authfile")
_ = flags.MarkHidden("cert-dir")
- _ = flags.MarkHidden("tls-verify")
}
}
diff --git a/cmd/podman/manifest/push.go b/cmd/podman/manifest/push.go
index b43e4531a..fd3d51f37 100644
--- a/cmd/podman/manifest/push.go
+++ b/cmd/podman/manifest/push.go
@@ -51,9 +51,7 @@ func init() {
flags.BoolVarP(&manifestPushOpts.Quiet, "quiet", "q", false, "don't output progress information when pushing lists")
if registry.IsRemote() {
- _ = flags.MarkHidden("authfile")
_ = flags.MarkHidden("cert-dir")
- _ = flags.MarkHidden("tls-verify")
}
}
diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go
index 976d720ee..1235f75a8 100644
--- a/cmd/podman/play/kube.go
+++ b/cmd/podman/play/kube.go
@@ -54,10 +54,10 @@ func init() {
flags.StringVar(&kubeOptions.CredentialsCLI, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.StringVar(&kubeOptions.Network, "network", "", "Connect pod to CNI network(s)")
flags.BoolVarP(&kubeOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
+ flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+ flags.StringVar(&kubeOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
if !registry.IsRemote() {
- flags.StringVar(&kubeOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&kubeOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
- flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
flags.StringVar(&kubeOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.StringVar(&kubeOptions.SeccompProfileRoot, "seccomp-profile-root", defaultSeccompRoot, "Directory path for seccomp profiles")
flags.StringSliceVar(&kubeOptions.ConfigMaps, "configmap", []string{}, "`Pathname` of a YAML file containing a kubernetes configmap")
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 1b992711f..3135a5e65 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -52,7 +52,7 @@ case "$CG_FS_TYPE" in
if [[ "$OS_RELEASE_ID" == "ubuntu" ]]; then
echo "export OCI_RUNTIME=/usr/lib/cri-o-runc/sbin/runc" >> /etc/environment
else
- echo "export OCI_RUNTIME=/usr/bin/runc" >> /etc/environment
+ echo "export OCI_RUNTIME=runc" >> /etc/environment
fi
fi
;;
@@ -61,7 +61,7 @@ case "$CG_FS_TYPE" in
# This is necessary since we've built/installed from source,
# which uses runc as the default.
warn "Forcing testing with crun instead of runc"
- echo "export OCI_RUNTIME=/usr/bin/crun" >> /etc/environment
+ echo "export OCI_RUNTIME=crun" >> /etc/environment
fi
;;
*) die_unknown CG_FS_TYPE
diff --git a/docs/source/markdown/podman-auto-update.1.md b/docs/source/markdown/podman-auto-update.1.md
index b6941362a..3ab097388 100644
--- a/docs/source/markdown/podman-auto-update.1.md
+++ b/docs/source/markdown/podman-auto-update.1.md
@@ -31,7 +31,7 @@ Systemd units that start and stop a container cannot run a new image.
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 7d0aa5001..821324f84 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -46,7 +46,7 @@ Set the ARCH of the image to the provided value instead of the architecture of t
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -470,7 +470,7 @@ When --timestamp is set, the created timestamp is always set to the time specifi
**--tls-verify**=*true|false*
-Require HTTPS and verify certificates when talking to container registries (defaults to true). (Not available for remote commands)
+Require HTTPS and verify certificates when talking to container registries (defaults to true).
**--ulimit**=*type*=*soft-limit*[:*hard-limit*]
diff --git a/docs/source/markdown/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md
index f56fc7d7b..676ad12d0 100644
--- a/docs/source/markdown/podman-container-runlabel.1.md
+++ b/docs/source/markdown/podman-container-runlabel.1.md
@@ -44,7 +44,7 @@ Any additional arguments will be appended to the command.
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -85,7 +85,7 @@ created from this image.
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf (Not available for remote commands)
+TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
## EXAMPLES
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 3303ae572..f9a23d314 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -47,7 +47,7 @@ each of stdin, stdout, and stderr.
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
-environment variable. `export REGISTRY_AUTH_FILE=path` (Not available for remote commands)
+environment variable. `export REGISTRY_AUTH_FILE=path`
**--blkio-weight**=*weight*
diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md
index 9b4ff74ed..7c09d99fe 100644
--- a/docs/source/markdown/podman-login.1.md
+++ b/docs/source/markdown/podman-login.1.md
@@ -42,7 +42,7 @@ Username for registry
**--authfile**=*path*
-Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands)
+Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -60,7 +60,7 @@ Default certificates directory is _/etc/containers/certs.d_. (Not available for
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands)
+TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
**--help**, **-h**
diff --git a/docs/source/markdown/podman-logout.1.md b/docs/source/markdown/podman-logout.1.md
index 0ff954d43..25f6d97b1 100644
--- a/docs/source/markdown/podman-logout.1.md
+++ b/docs/source/markdown/podman-logout.1.md
@@ -23,7 +23,7 @@ All the cached credentials can be removed by setting the **all** flag.
**--authfile**=*path*
-Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands)
+Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
diff --git a/docs/source/markdown/podman-manifest-add.1.md b/docs/source/markdown/podman-manifest-add.1.md
index c4d4417c4..4c0bad2ae 100644
--- a/docs/source/markdown/podman-manifest-add.1.md
+++ b/docs/source/markdown/podman-manifest-add.1.md
@@ -36,7 +36,7 @@ retrieved from the image's configuration information.
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -71,7 +71,7 @@ image. This option is rarely used.
**--tls-verify**
-Require HTTPS and verify certificates when talking to container registries (defaults to true). (Not available for remote commands)
+Require HTTPS and verify certificates when talking to container registries (defaults to true).
**--variant**
diff --git a/docs/source/markdown/podman-manifest-push.1.md b/docs/source/markdown/podman-manifest-push.1.md
index 33b2a24c5..9cf0b159c 100644
--- a/docs/source/markdown/podman-manifest-push.1.md
+++ b/docs/source/markdown/podman-manifest-push.1.md
@@ -22,7 +22,7 @@ the list or index itself.
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -64,7 +64,7 @@ Sign the pushed images using the GPG key that matches the specified fingerprint.
**--tls-verify**
-Require HTTPS and verify certificates when talking to container registries (defaults to true) (Not available for remote commands)
+Require HTTPS and verify certificates when talking to container registries. (defaults to true)
## EXAMPLE
diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md
index 00ee7c1df..97b0dc09a 100644
--- a/docs/source/markdown/podman-play-kube.1.md
+++ b/docs/source/markdown/podman-play-kube.1.md
@@ -20,7 +20,7 @@ Note: HostPath volume types created by play kube will be given an SELinux privat
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -58,7 +58,7 @@ Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (Not
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands)
+TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
**--help**, **-h**
diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md
index c75cb18b4..46beb4c42 100644
--- a/docs/source/markdown/podman-pull.1.md
+++ b/docs/source/markdown/podman-pull.1.md
@@ -57,7 +57,7 @@ Note: When using the all-tags flag, Podman will not iterate over the search regi
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -97,7 +97,7 @@ Suppress output information when pulling images
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands)
+TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
**--help**, **-h**
diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md
index fffd76801..e9b63dc43 100644
--- a/docs/source/markdown/podman-push.1.md
+++ b/docs/source/markdown/podman-push.1.md
@@ -46,7 +46,7 @@ Images are pushed from those stored in local image storage.
**--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
-If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
@@ -98,7 +98,7 @@ Add a signature at the destination using the specified key
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. (Not available for remote commands)
+TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
## EXAMPLE
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 9ebf6649b..2c8aa3a26 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -57,7 +57,7 @@ each of **stdin**, **stdout**, and **stderr**.
**--authfile**[=*path*]
-Path to the authentication file. Default is *${XDG_RUNTIME_DIR}/containers/auth.json*. (Not available for remote commands)
+Path to the authentication file. Default is *${XDG_RUNTIME_DIR}/containers/auth.json*.
Note: You can also override the default path of the authentication file by setting the **REGISTRY_AUTH_FILE**
environment variable.
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index 9be753d26..e195ca314 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -2,7 +2,7 @@ package libpod
import (
"bytes"
- "path/filepath"
+ "os"
"runtime"
"strings"
@@ -400,14 +400,30 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.
// Handle legacy containers which might use a literal path for
// their OCI runtime name.
runtimeName := ctr.config.OCIRuntime
- if strings.HasPrefix(runtimeName, "/") {
- runtimeName = filepath.Base(runtimeName)
- }
-
ociRuntime, ok := s.runtime.ociRuntimes[runtimeName]
if !ok {
- // Use a MissingRuntime implementation
- ociRuntime = getMissingRuntime(runtimeName, s.runtime)
+ runtimeSet := false
+
+ // If the path starts with a / and exists, make a new
+ // OCI runtime for it using the full path.
+ if strings.HasPrefix(runtimeName, "/") {
+ if stat, err := os.Stat(runtimeName); err == nil && !stat.IsDir() {
+ newOCIRuntime, err := newConmonOCIRuntime(runtimeName, []string{runtimeName}, s.runtime.conmonPath, s.runtime.runtimeFlags, s.runtime.config)
+ if err == nil {
+ // The runtime lock should
+ // protect against concurrent
+ // modification of the map.
+ ociRuntime = newOCIRuntime
+ s.runtime.ociRuntimes[runtimeName] = ociRuntime
+ runtimeSet = true
+ }
+ }
+ }
+
+ if !runtimeSet {
+ // Use a MissingRuntime implementation
+ ociRuntime = getMissingRuntime(runtimeName, s.runtime)
+ }
}
ctr.ociRuntime = ociRuntime
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index eff390e46..ffb2f5b73 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1541,11 +1541,31 @@ func (c *Container) getHosts() string {
}
}
- if c.config.NetMode.IsSlirp4netns() {
- // When using slirp4netns, the interface gets a static IP
- hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", "10.0.2.100", c.Hostname(), c.Config().Name)
- }
hosts += c.cniHosts()
+
+ // If not making a network namespace, add our own hostname.
+ if c.Hostname() != "" {
+ if c.config.NetMode.IsSlirp4netns() {
+ // When using slirp4netns, the interface gets a static IP
+ hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", "10.0.2.100", c.Hostname(), c.config.Name)
+ } else {
+ hasNetNS := false
+ for _, ns := range c.config.Spec.Linux.Namespaces {
+ if ns.Type == spec.NetworkNamespace {
+ hasNetNS = true
+ break
+ }
+ }
+ if !hasNetNS {
+ // 127.0.1.1 and host's hostname to match Docker
+ osHostname, err := os.Hostname()
+ if err != nil {
+ osHostname = c.Hostname()
+ }
+ hosts += fmt.Sprintf("127.0.1.1 %s\n", osHostname)
+ }
+ }
+ }
return hosts
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index f87c311ce..df0ff6c32 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -823,6 +823,20 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) {
// Produce an InspectNetworkSettings containing information on the container
// network.
func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) {
+ if c.config.NetNsCtr != "" {
+ netNsCtr, err := c.runtime.GetContainer(c.config.NetNsCtr)
+ if err != nil {
+ return nil, err
+ }
+ // Have to sync to ensure that state is populated
+ if err := netNsCtr.syncContainer(); err != nil {
+ return nil, err
+ }
+ logrus.Debugf("Container %s shares network namespace, retrieving network info of container %s", c.ID(), c.config.NetNsCtr)
+
+ return netNsCtr.getContainerNetworkInfo()
+ }
+
settings := new(define.InspectNetworkSettings)
settings.Ports = makeInspectPortBindings(c.config.PortMappings)
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 7da8b181f..792492db6 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/libpod/lock"
+ "github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/registries"
"github.com/containers/podman/v2/pkg/rootless"
@@ -174,9 +175,21 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R
}
}
+ if err := shutdown.Start(); err != nil {
+ return nil, errors.Wrapf(err, "error starting shutdown signal handler")
+ }
+
if err := makeRuntime(ctx, runtime); err != nil {
return nil, err
}
+
+ if err := shutdown.Register("libpod", func(sig os.Signal) error {
+ os.Exit(1)
+ return nil
+ }); err != nil {
+ logrus.Errorf("Error registering shutdown handler for libpod: %v", err)
+ }
+
return runtime, nil
}
@@ -383,14 +396,12 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// If the string starts with / it's a path to a runtime
// executable.
if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") {
- name := filepath.Base(runtime.config.Engine.OCIRuntime)
-
- ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config)
+ ociRuntime, err := newConmonOCIRuntime(runtime.config.Engine.OCIRuntime, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config)
if err != nil {
return err
}
- runtime.ociRuntimes[name] = ociRuntime
+ runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] = ociRuntime
runtime.defaultOCIRuntime = ociRuntime
} else {
ociRuntime, ok := runtime.ociRuntimes[runtime.config.Engine.OCIRuntime]
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 51b4c5f03..de73a9ff3 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
+ "github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/storage"
@@ -149,6 +150,10 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
return nil, err
}
+ // Inhibit shutdown until creation succeeds
+ shutdown.Inhibit()
+ defer shutdown.Uninhibit()
+
// Allocate a lock for the container
lock, err := r.lockManager.AllocateLock()
if err != nil {
diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go
new file mode 100644
index 000000000..87538dec9
--- /dev/null
+++ b/libpod/shutdown/handler.go
@@ -0,0 +1,131 @@
+package shutdown
+
+import (
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+var (
+ stopped bool
+ sigChan chan os.Signal
+ cancelChan chan bool
+ // Definitions of all on-shutdown handlers
+ handlers map[string]func(os.Signal) error
+ // Ordering that on-shutdown handlers will be invoked.
+ handlerOrder []string
+ shutdownInhibit sync.RWMutex
+)
+
+// Start begins handling SIGTERM and SIGINT and will run the given on-signal
+// handlers when one is called. This can be cancelled by calling Stop().
+func Start() error {
+ if sigChan != nil {
+ // Already running, do nothing.
+ return nil
+ }
+
+ sigChan = make(chan os.Signal, 1)
+ cancelChan = make(chan bool, 1)
+ stopped = false
+
+ signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
+
+ go func() {
+ select {
+ case <-cancelChan:
+ signal.Stop(sigChan)
+ close(sigChan)
+ close(cancelChan)
+ stopped = true
+ return
+ case sig := <-sigChan:
+ logrus.Infof("Received shutdown signal %v, terminating!", sig)
+ shutdownInhibit.Lock()
+ for _, name := range handlerOrder {
+ handler, ok := handlers[name]
+ if !ok {
+ logrus.Errorf("Shutdown handler %s definition not found!", name)
+ continue
+ }
+ logrus.Infof("Invoking shutdown handler %s", name)
+ if err := handler(sig); err != nil {
+ logrus.Errorf("Error running shutdown handler %s: %v", name, err)
+ }
+ }
+ shutdownInhibit.Unlock()
+ return
+ }
+ }()
+
+ return nil
+}
+
+// Stop the shutdown signal handler.
+func Stop() error {
+ if cancelChan == nil {
+ return errors.New("shutdown signal handler has not yet been started")
+ }
+ if stopped {
+ return nil
+ }
+
+ cancelChan <- true
+
+ return nil
+}
+
+// Temporarily inhibit signals from shutting down Libpod.
+func Inhibit() {
+ shutdownInhibit.RLock()
+}
+
+// Stop inhibiting signals from shutting down Libpod.
+func Uninhibit() {
+ shutdownInhibit.RUnlock()
+}
+
+// Register registers a function that will be executed when Podman is terminated
+// by a signal. Handlers are invoked LIFO - the last handler registered is the
+// first run.
+func Register(name string, handler func(os.Signal) error) error {
+ if handlers == nil {
+ handlers = make(map[string]func(os.Signal) error)
+ }
+
+ if _, ok := handlers[name]; ok {
+ return errors.Errorf("handler with name %s already exists", name)
+ }
+
+ handlers[name] = handler
+ handlerOrder = append([]string{name}, handlerOrder...)
+
+ return nil
+}
+
+// Unregister un-registers a given shutdown handler.
+func Unregister(name string) error {
+ if handlers == nil {
+ return nil
+ }
+
+ if _, ok := handlers[name]; !ok {
+ return nil
+ }
+
+ delete(handlers, name)
+
+ newOrder := []string{}
+ for _, checkName := range handlerOrder {
+ if checkName != name {
+ newOrder = append(newOrder, checkName)
+ }
+ }
+ handlerOrder = newOrder
+
+ return nil
+}
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 8a0b3c922..87c95a24c 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -1,27 +1,19 @@
package compat
import (
- "context"
"encoding/json"
- "fmt"
"net/http"
- "strings"
- "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v2/cmd/podman/common"
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
- image2 "github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
- "github.com/containers/podman/v2/pkg/namespaces"
- "github.com/containers/podman/v2/pkg/rootless"
- "github.com/containers/podman/v2/pkg/signal"
- createconfig "github.com/containers/podman/v2/pkg/spec"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/infra/abi"
"github.com/containers/podman/v2/pkg/specgen"
- "github.com/containers/storage"
"github.com/gorilla/schema"
"github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
func CreateContainer(w http.ResponseWriter, r *http.Request) {
@@ -56,220 +48,27 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()"))
return
}
- containerConfig, err := runtime.GetConfig()
+
+ // Take input structure and convert to cliopts
+ cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(input)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()"))
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "make cli opts()"))
return
}
- cc, err := makeCreateConfig(r.Context(), containerConfig, input, newImage)
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()"))
+ sg := specgen.NewSpecGenerator(newImage.ID(), cliOpts.RootFS)
+ if err := common.FillOutSpecGen(sg, cliOpts, args); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "fill out specgen"))
return
}
- cc.Name = query.Name
- utils.CreateContainer(r.Context(), w, runtime, &cc)
-}
-
-func makeCreateConfig(ctx context.Context, containerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
- var (
- err error
- init bool
- )
- env := make(map[string]string)
- stopSignal := unix.SIGTERM
- if len(input.StopSignal) > 0 {
- stopSignal, err = signal.ParseSignal(input.StopSignal)
- if err != nil {
- return createconfig.CreateConfig{}, err
- }
- }
-
- workDir, err := newImage.WorkingDir(ctx)
+ ic := abi.ContainerEngine{Libpod: runtime}
+ report, err := ic.ContainerCreate(r.Context(), sg)
if err != nil {
- return createconfig.CreateConfig{}, err
- }
- if workDir == "" {
- workDir = "/"
- }
- if len(input.WorkingDir) > 0 {
- workDir = input.WorkingDir
- }
-
- // Only use image's Cmd when the user does not set the entrypoint
- if input.Entrypoint == nil && len(input.Cmd) == 0 {
- cmdSlice, err := newImage.Cmd(ctx)
- if err != nil {
- return createconfig.CreateConfig{}, err
- }
- input.Cmd = cmdSlice
- }
-
- if input.Entrypoint == nil {
- entrypointSlice, err := newImage.Entrypoint(ctx)
- if err != nil {
- return createconfig.CreateConfig{}, err
- }
- input.Entrypoint = entrypointSlice
- }
-
- stopTimeout := containerConfig.Engine.StopTimeout
- if input.StopTimeout != nil {
- stopTimeout = uint(*input.StopTimeout)
- }
- c := createconfig.CgroupConfig{
- Cgroups: "", // podman
- Cgroupns: "", // podman
- CgroupParent: "", // podman
- CgroupMode: "", // podman
- }
- security := createconfig.SecurityConfig{
- CapAdd: input.HostConfig.CapAdd,
- CapDrop: input.HostConfig.CapDrop,
- LabelOpts: nil, // podman
- NoNewPrivs: false, // podman
- ApparmorProfile: "", // podman
- SeccompProfilePath: "",
- SecurityOpts: input.HostConfig.SecurityOpt,
- Privileged: input.HostConfig.Privileged,
- ReadOnlyRootfs: input.HostConfig.ReadonlyRootfs,
- ReadOnlyTmpfs: false, // podman-only
- Sysctl: input.HostConfig.Sysctls,
- }
-
- var netmode namespaces.NetworkMode
- if rootless.IsRootless() {
- netmode = namespaces.NetworkMode(specgen.Slirp)
- }
-
- network := createconfig.NetworkConfig{
- DNSOpt: input.HostConfig.DNSOptions,
- DNSSearch: input.HostConfig.DNSSearch,
- DNSServers: input.HostConfig.DNS,
- ExposedPorts: input.ExposedPorts,
- HTTPProxy: false, // podman
- IP6Address: "",
- IPAddress: "",
- LinkLocalIP: nil, // docker-only
- MacAddress: input.MacAddress,
- NetMode: netmode,
- Network: input.HostConfig.NetworkMode.NetworkName(),
- NetworkAlias: nil, // docker-only now
- PortBindings: input.HostConfig.PortBindings,
- Publish: nil, // podmanseccompPath
- PublishAll: input.HostConfig.PublishAllPorts,
- }
-
- uts := createconfig.UtsConfig{
- UtsMode: namespaces.UTSMode(input.HostConfig.UTSMode),
- NoHosts: false, //podman
- HostAdd: input.HostConfig.ExtraHosts,
- Hostname: input.Hostname,
- }
-
- z := createconfig.UserConfig{
- GroupAdd: input.HostConfig.GroupAdd,
- IDMappings: &storage.IDMappingOptions{}, // podman //TODO <--- fix this,
- UsernsMode: namespaces.UsernsMode(input.HostConfig.UsernsMode),
- User: input.User,
- }
- pidConfig := createconfig.PidConfig{PidMode: namespaces.PidMode(input.HostConfig.PidMode)}
- // TODO: We should check that these binds are all listed in the `Volumes`
- // key since it doesn't make sense to define a `Binds` element for a
- // container path which isn't defined as a volume
- volumes := input.HostConfig.Binds
-
- // Docker is more flexible about its input where podman throws
- // away incorrectly formatted variables so we cannot reuse the
- // parsing of the env input
- // [Foo Other=one Blank=]
- imgEnv, err := newImage.Env(ctx)
- if err != nil {
- return createconfig.CreateConfig{}, err
- }
- input.Env = append(imgEnv, input.Env...)
- for _, e := range input.Env {
- splitEnv := strings.Split(e, "=")
- switch len(splitEnv) {
- case 0:
- continue
- case 1:
- env[splitEnv[0]] = ""
- default:
- env[splitEnv[0]] = strings.Join(splitEnv[1:], "=")
- }
- }
-
- // format the tmpfs mounts into a []string from map
- tmpfs := make([]string, 0, len(input.HostConfig.Tmpfs))
- for k, v := range input.HostConfig.Tmpfs {
- tmpfs = append(tmpfs, fmt.Sprintf("%s:%s", k, v))
- }
-
- if input.HostConfig.Init != nil && *input.HostConfig.Init {
- init = true
- }
-
- m := createconfig.CreateConfig{
- Annotations: nil, // podman
- Args: nil,
- Cgroup: c,
- CidFile: "",
- ConmonPidFile: "", // podman
- Command: input.Cmd,
- UserCommand: input.Cmd, // podman
- Detach: false, //
- // Devices: input.HostConfig.Devices,
- Entrypoint: input.Entrypoint,
- Env: env,
- HealthCheck: nil, //
- Init: init,
- InitPath: "", // tbd
- Image: input.Image,
- ImageID: newImage.ID(),
- BuiltinImgVolumes: nil, // podman
- ImageVolumeType: "", // podman
- Interactive: input.OpenStdin,
- // IpcMode: input.HostConfig.IpcMode,
- Labels: input.Labels,
- LogDriver: input.HostConfig.LogConfig.Type, // is this correct
- // LogDriverOpt: input.HostConfig.LogConfig.Config,
- Name: input.Name,
- Network: network,
- Pod: "", // podman
- PodmanPath: "", // podman
- Quiet: false, // front-end only
- Resources: createconfig.CreateResourceConfig{MemorySwappiness: -1},
- RestartPolicy: input.HostConfig.RestartPolicy.Name,
- Rm: input.HostConfig.AutoRemove,
- StopSignal: stopSignal,
- StopTimeout: stopTimeout,
- Systemd: false, // podman
- Tmpfs: tmpfs,
- User: z,
- Uts: uts,
- Tty: input.Tty,
- Mounts: nil, // we populate
- // MountsFlag: input.HostConfig.Mounts,
- NamedVolumes: nil, // we populate
- Volumes: volumes,
- VolumesFrom: input.HostConfig.VolumesFrom,
- WorkDir: workDir,
- Rootfs: "", // podman
- Security: security,
- Syslog: false, // podman
-
- Pid: pidConfig,
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "container create"))
+ return
}
-
- fullCmd := append(input.Entrypoint, input.Cmd...)
- if len(fullCmd) > 0 {
- m.PodmanPath = fullCmd[0]
- if len(fullCmd) == 1 {
- m.Args = fullCmd
- } else {
- m.Args = fullCmd[1:]
- }
+ createResponse := entities.ContainerCreateResponse{
+ ID: report.Id,
+ Warnings: []string{},
}
-
- return m, nil
+ utils.WriteResponse(w, http.StatusCreated, createResponse)
}
diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go
index 131fab69f..b3ceae3ee 100644
--- a/pkg/api/handlers/compat/images_search.go
+++ b/pkg/api/handlers/compat/images_search.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/auth"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
@@ -14,9 +15,10 @@ import (
func SearchImages(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
- Term string `json:"term"`
- Limit int `json:"limit"`
- Filters map[string][]string `json:"filters"`
+ Term string `json:"term"`
+ Limit int `json:"limit"`
+ Filters map[string][]string `json:"filters"`
+ TLSVerify bool `json:"tlsVerify"`
}{
// This is where you can override the golang default value for one of fields
}
@@ -58,6 +60,18 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
Limit: query.Limit,
}
+ if _, found := r.URL.Query()["tlsVerify"]; found {
+ options.InsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
+ }
+
+ _, authfile, key, err := auth.GetCredentials(r)
+ if err != nil {
+ utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String()))
+ return
+ }
+ defer auth.RemoveAuthfile(authfile)
+ options.Authfile = authfile
+
results, err := image.SearchImages(query.Term, options)
if err != nil {
utils.BadRequest(w, "term", query.Term, err)
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 1292090fb..3fb5d23c8 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -636,6 +636,14 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
options.Filter = *filter
}
+ _, authfile, key, err := auth.GetCredentials(r)
+ if err != nil {
+ utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String()))
+ return
+ }
+ defer auth.RemoveAuthfile(authfile)
+ options.Authfile = authfile
+
searchResults, err := image.SearchImages(query.Term, options)
if err != nil {
utils.BadRequest(w, "term", query.Term, err)
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 355a46fb7..64008767b 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -7,7 +7,6 @@ import (
"net"
"net/http"
"os"
- "os/signal"
goRuntime "runtime"
"strings"
"sync"
@@ -15,6 +14,7 @@ import (
"time"
"github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/server/idle"
"github.com/coreos/go-systemd/v22/activation"
@@ -180,8 +180,17 @@ func setupSystemd() {
// Serve starts responding to HTTP requests.
func (s *APIServer) Serve() error {
setupSystemd()
- sigChan := make(chan os.Signal, 1)
- signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
+
+ // Start the shutdown signal handler.
+ if err := shutdown.Start(); err != nil {
+ return err
+ }
+ if err := shutdown.Register("server", func(sig os.Signal) error {
+ return s.Shutdown()
+ }); err != nil {
+ return err
+ }
+
errChan := make(chan error, 1)
go func() {
@@ -217,14 +226,7 @@ func (s *APIServer) Serve() error {
errChan <- nil
}()
- select {
- case err := <-errChan:
- return err
- case sig := <-sigChan:
- logrus.Infof("APIServer terminated by signal %v", sig)
- }
-
- return nil
+ return <-errChan
}
// Shutdown is a clean shutdown waiting on existing clients
diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go
index f484e926c..0c586cf5c 100644
--- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go
+++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go
@@ -5,12 +5,17 @@ import (
"syscall"
"github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/signal"
"github.com/sirupsen/logrus"
)
// ProxySignals ...
func ProxySignals(ctr *libpod.Container) {
+ // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going
+ // to the container now.
+ shutdown.Stop()
+
sigBuffer := make(chan os.Signal, 128)
signal.CatchAll(sigBuffer)
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index 7adb8be6a..7e4f09dc4 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -342,7 +342,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
return errors.Wrapf(err, "error looking up container to share uts namespace with")
}
hostname = utsCtr.Hostname()
- case s.NetNS.NSMode == specgen.Host || s.UtsNS.NSMode == specgen.Host:
+ case (s.NetNS.NSMode == specgen.Host && hostname == "") || s.UtsNS.NSMode == specgen.Host:
tmpHostname, err := os.Hostname()
if err != nil {
return errors.Wrap(err, "unable to retrieve hostname of the host")
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index f02432f5b..8454458a8 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -110,7 +110,7 @@ func makeCommand(ctx context.Context, s *specgen.SpecGenerator, img *image.Image
// Only use image command if the user did not manually set an
// entrypoint.
command := s.Command
- if command == nil && img != nil && s.Entrypoint == nil {
+ if (command == nil || len(command) == 0) && img != nil && (s.Entrypoint == nil || len(s.Entrypoint) == 0) {
newCmd, err := img.Cmd(ctx)
if err != nil {
return nil, err
diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at
index 9d4b04edb..f550d5fc3 100644
--- a/test/apiv2/01-basic.at
+++ b/test/apiv2/01-basic.at
@@ -59,7 +59,10 @@ t GET info 200 \
.DefaultRuntime~.*$runtime \
.MemTotal~[0-9]\\+
-# Timing: make sure server stays responsive
+# Timing: make sure server stays responsive.
+# Because /info may need to check storage, it may be slow the first time.
+# Let's invoke it once to prime caches, then run ten queries in a timed loop.
+t GET info 200
t0=$SECONDS
for i in $(seq 1 10); do
# FIXME: someday: refactor t(), separate out the 'curl' logic so we
@@ -70,7 +73,8 @@ t1=$SECONDS
delta_t=$((t1 - t2))
# Desired number of seconds in which we expect to run.
-want=7
+# FIXME: 10 seconds is a lot! PR #8076 opened to investigate why.
+want=10
if [ $delta_t -le $want ]; then
_show_ok 1 "Time for ten /info requests ($delta_t seconds) <= ${want}s"
else
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index 7fbcd2e9c..c7055dfc4 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -206,16 +206,6 @@ t POST containers/${cid_top}/stop "" 204
t DELETE containers/$cid 204
t DELETE containers/$cid_top 204
-# test the apiv2 create, shouldn't ignore the ENV and WORKDIR from the image
-t POST containers/create '"Image":"'$ENV_WORKDIR_IMG'","Env":["testKey1"]' 201 \
- .Id~[0-9a-f]\\{64\\}
-cid=$(jq -r '.Id' <<<"$output")
-t GET containers/$cid/json 200 \
- .Config.Env~.*REDIS_VERSION= \
- .Config.Env~.*testKey1= \
- .Config.WorkingDir="/data" # default is /data
-t DELETE containers/$cid 204
-
# test the WORKDIR and StopSignal
t POST containers/create '"Image":"'$ENV_WORKDIR_IMG'","WorkingDir":"/dataDir","StopSignal":"9"' 201 \
.Id~[0-9a-f]\\{64\\}
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index 78325eb24..c8ca9df3f 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -179,7 +179,7 @@ function t() {
# POST requests require an extra params arg
if [[ $method = "POST" ]]; then
curl_args="-d $(jsonify $1)"
- testname="$testname [$1]"
+ testname="$testname [$curl_args]"
shift
fi
@@ -204,21 +204,30 @@ function t() {
echo "-------------------------------------------------------------" >>$LOG
echo "\$ $testname" >>$LOG
rm -f $WORKDIR/curl.*
- curl -s -X $method ${curl_args} \
- -H 'Content-type: application/json' \
- --dump-header $WORKDIR/curl.headers.out \
- -o $WORKDIR/curl.result.out "$url"
-
- if [[ $? -eq 7 ]]; then
- echo "FATAL: curl failure on $url - cannot continue" >&2
+ # -s = silent, but --write-out 'format' gives us important response data
+ response=$(curl -s -X $method ${curl_args} \
+ -H 'Content-type: application/json' \
+ --dump-header $WORKDIR/curl.headers.out \
+ --write-out '%{http_code}^%{content_type}^%{time_total}' \
+ -o $WORKDIR/curl.result.out "$url")
+
+ # Any error from curl is instant bad news, from which we can't recover
+ rc=$?
+ if [[ $rc -ne 0 ]]; then
+ echo "FATAL: curl failure ($rc) on $url - cannot continue" >&2
exit 1
fi
- cat $WORKDIR/curl.headers.out >>$LOG 2>/dev/null || true
+ # Show returned headers (without trailing ^M or empty lines) in log file.
+ # Sometimes -- I can't remember why! -- we don't get headers.
+ if [[ -e $WORKDIR/curl.headers.out ]]; then
+ tr -d '\015' < $WORKDIR/curl.headers.out | egrep '.' >>$LOG
+ fi
- # Log results, if text. If JSON, filter through jq for readability.
- content_type=$(sed -ne 's/^Content-Type:[ ]\+//pi' <$WORKDIR/curl.headers.out)
+ IFS='^' read actual_code content_type time_total <<<"$response"
+ printf "X-Response-Time: ${time_total}s\n\n" >>$LOG
+ # Log results, if text. If JSON, filter through jq for readability.
if [[ $content_type =~ /octet ]]; then
output="[$(file --brief $WORKDIR/curl.result.out)]"
echo "$output" >>$LOG
@@ -233,10 +242,8 @@ function t() {
fi
# Test return code
- actual_code=$(head -n1 $WORKDIR/curl.headers.out | awk '/^HTTP/ { print $2}')
is "$actual_code" "$expected_code" "$testname : status"
-
# Special case: 204/304, by definition, MUST NOT return content (rfc2616)
if [[ $expected_code = 204 || $expected_code = 304 ]]; then
if [ -n "$*" ]; then
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index e36c86690..206c66f9f 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -235,14 +235,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
ociRuntime := os.Getenv("OCI_RUNTIME")
if ociRuntime == "" {
- var err error
- ociRuntime, err = exec.LookPath("crun")
- // If we cannot find the crun binary, setting to something static as we have no way
- // to return an error. The tests will fail and point out that the runc binary could
- // not be found nicely.
- if err != nil {
- ociRuntime = "/usr/bin/runc"
- }
+ ociRuntime = "crun"
}
os.Setenv("DISABLE_HC_SYSTEMD", "true")
CNIConfigDir := "/etc/cni/net.d"
@@ -673,3 +666,9 @@ func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd
podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil)
return &PodmanSessionIntegration{podmanSession}
}
+
+// We don't support running Varlink when local
+func (p *PodmanTestIntegration) RestartRemoteService() {
+ p.StopRemoteService()
+ p.StartRemoteService()
+}
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index f69b6ca7b..83a66d2b9 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -245,6 +245,24 @@ var _ = Describe("Podman pod create", func() {
}
})
+ It("podman container in pod with IP address shares IP address", func() {
+ SkipIfRootless("Rootless does not support --ip")
+ podName := "test"
+ ctrName := "testCtr"
+ ip := GetRandomIPAddress()
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", podName})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+ podCtr := podmanTest.Podman([]string{"run", "--name", ctrName, "--pod", podName, "-d", "-t", ALPINE, "top"})
+ podCtr.WaitWithDefaultTimeout()
+ Expect(podCtr.ExitCode()).To(Equal(0))
+ ctrInspect := podmanTest.Podman([]string{"inspect", ctrName})
+ ctrInspect.WaitWithDefaultTimeout()
+ Expect(ctrInspect.ExitCode()).To(Equal(0))
+ ctrJSON := ctrInspect.InspectContainerToJSON()
+ Expect(ctrJSON[0].NetworkSettings.IPAddress).To(Equal(ip))
+ })
+
It("podman create pod with IP address and no infra should fail", func() {
name := "test"
ip := GetRandomIPAddress()
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index e14482db7..540ac5409 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -571,4 +571,19 @@ var _ = Describe("Podman run networking", func() {
podrm.WaitWithDefaultTimeout()
Expect(podrm.ExitCode()).To(BeZero())
})
+
+ It("podman run net=host adds entry to /etc/hosts", func() {
+ run := podmanTest.Podman([]string{"run", "--net=host", ALPINE, "cat", "/etc/hosts"})
+ run.WaitWithDefaultTimeout()
+ Expect(run.ExitCode()).To(BeZero())
+ Expect(strings.Contains(run.OutputToString(), "127.0.1.1")).To(BeTrue())
+ })
+
+ It("podman run with --net=host and --hostname sets correct hostname", func() {
+ hostname := "testctr"
+ run := podmanTest.Podman([]string{"run", "--net=host", "--hostname", hostname, ALPINE, "hostname"})
+ run.WaitWithDefaultTimeout()
+ Expect(run.ExitCode()).To(BeZero())
+ Expect(strings.Contains(run.OutputToString(), "testctr")).To(BeTrue())
+ })
})
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index 0cf005529..4f2751099 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -237,7 +237,6 @@ registries = ['{{.Host}}:{{.Port}}']`
})
It("podman search attempts HTTP if registry is in registries.insecure and force secure is false", func() {
- SkipIfRemote("--tls-verify is not supported on podman-remote search")
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
@@ -264,6 +263,10 @@ registries = ['{{.Host}}:{{.Port}}']`
registryFileTmpl.Execute(&buffer, registryEndpoints[4])
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry4.conf", tempdir), buffer.Bytes(), 0644)
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ defer podmanTest.RestartRemoteService()
+ }
search := podmanTest.PodmanNoCache([]string{"search", image})
search.WaitWithDefaultTimeout()
@@ -278,7 +281,7 @@ registries = ['{{.Host}}:{{.Port}}']`
})
It("podman search doesn't attempt HTTP if force secure is true", func() {
- SkipIfRemote("--tls-verify is not supported on podman-remote search")
+ SkipIfRemote("FIXME This should work on podman-remote")
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
@@ -303,6 +306,10 @@ registries = ['{{.Host}}:{{.Port}}']`
registryFileTmpl.Execute(&buffer, registryEndpoints[5])
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry5.conf", tempdir), buffer.Bytes(), 0644)
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ defer podmanTest.RestartRemoteService()
+ }
search := podmanTest.PodmanNoCache([]string{"search", image, "--tls-verify=true"})
search.WaitWithDefaultTimeout()
@@ -317,7 +324,7 @@ registries = ['{{.Host}}:{{.Port}}']`
})
It("podman search doesn't attempt HTTP if registry is not listed as insecure", func() {
- SkipIfRemote("--tls-verify is not supported on podman-remote search")
+ SkipIfRemote("FIXME This should work on podman-remote")
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
@@ -343,6 +350,11 @@ registries = ['{{.Host}}:{{.Port}}']`
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry6.conf", tempdir), buffer.Bytes(), 0644)
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ defer podmanTest.RestartRemoteService()
+ }
+
search := podmanTest.PodmanNoCache([]string{"search", image})
search.WaitWithDefaultTimeout()
@@ -393,6 +405,11 @@ registries = ['{{.Host}}:{{.Port}}']`
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry8.conf", tempdir), buffer.Bytes(), 0644)
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ defer podmanTest.RestartRemoteService()
+ }
+
search := podmanTest.PodmanNoCache([]string{"search", "my-alpine"})
search.WaitWithDefaultTimeout()
diff --git a/test/e2e/toolbox_test.go b/test/e2e/toolbox_test.go
index 4f4113bd4..fbff8d19e 100644
--- a/test/e2e/toolbox_test.go
+++ b/test/e2e/toolbox_test.go
@@ -222,7 +222,7 @@ var _ = Describe("Toolbox-specific testing", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue())
+ Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue())
expectedOutput := fmt.Sprintf("%s:x:%s:%s::%s:%s",
username, uid, gid, homeDir, shell)
@@ -257,7 +257,7 @@ var _ = Describe("Toolbox-specific testing", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue())
+ Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue())
session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/group"})
session.WaitWithDefaultTimeout()
@@ -301,7 +301,7 @@ var _ = Describe("Toolbox-specific testing", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue())
+ Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue())
expectedUser := fmt.Sprintf("%s:x:%s:%s::%s:%s",
username, uid, gid, homeDir, shell)
@@ -358,7 +358,7 @@ var _ = Describe("Toolbox-specific testing", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue())
+ Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue())
session = podmanTest.Podman([]string{"logs", "test"})
session.WaitWithDefaultTimeout()
diff --git a/test/endpoint/setup.go b/test/endpoint/setup.go
index 56cab06b0..6bbc8d2bc 100644
--- a/test/endpoint/setup.go
+++ b/test/endpoint/setup.go
@@ -51,14 +51,7 @@ func Setup(tempDir string) *EndpointTestIntegration {
ociRuntime := os.Getenv("OCI_RUNTIME")
if ociRuntime == "" {
- var err error
- ociRuntime, err = exec.LookPath("runc")
- // If we cannot find the runc binary, setting to something static as we have no way
- // to return an error. The tests will fail and point out that the runc binary could
- // not be found nicely.
- if err != nil {
- ociRuntime = "/usr/bin/runc"
- }
+ ociRuntime = "runc"
}
os.Setenv("DISABLE_HC_SYSTEMD", "true")
CNIConfigDir := "/etc/cni/net.d"
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 28dc7c7a7..9f4037730 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -460,4 +460,17 @@ json-file | f
is "$output" "$expect" "podman run with --tz=local, matches host"
}
+# run with --runtime should preserve the named runtime
+@test "podman run : full path to --runtime is preserved" {
+ skip_if_cgroupsv1
+ skip_if_remote
+ run_podman run -d --runtime '/usr/bin/crun' $IMAGE sleep 60
+ cid="$output"
+
+ run_podman inspect --format '{{.OCIRuntime}}' $cid
+ is "$output" "/usr/bin/crun"
+
+ run_podman kill $cid
+}
+
# vim: filetype=sh
diff --git a/test/system/260-sdnotify.bats b/test/system/260-sdnotify.bats
index 2ddeda96a..c99ba4fa6 100644
--- a/test/system/260-sdnotify.bats
+++ b/test/system/260-sdnotify.bats
@@ -107,6 +107,7 @@ function _assert_mainpid_is_conmon() {
# Done. Stop container, clean up.
run_podman exec $cid touch /stop
+ run_podman wait $cid
run_podman rm $cid
_stop_socat
}
@@ -142,6 +143,7 @@ function _assert_mainpid_is_conmon() {
# Done. Stop container, clean up.
run_podman exec $cid touch /stop
+ run_podman wait $cid
run_podman rm $cid
run_podman rmi $_FEDORA
_stop_socat
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 73cf1e5b2..2cced10c2 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -253,6 +253,7 @@ function is_cgroupsv1() {
! is_cgroupsv2
}
+# True if cgroups v2 are enabled
function is_cgroupsv2() {
cgroup_type=$(stat -f -c %T /sys/fs/cgroup)
test "$cgroup_type" = "cgroup2fs"
@@ -305,6 +306,15 @@ function skip_if_no_selinux() {
fi
}
+#######################
+# skip_if_cgroupsv1 # ...with an optional message
+#######################
+function skip_if_cgroupsv1() {
+ if ! is_cgroupsv2; then
+ skip "${1:-test requires cgroupsv2}"
+ fi
+}
+
#########
# die # Abort with helpful message
#########