summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--cmd/podman/common/create_opts.go13
-rw-r--r--cmd/podman/diff/diff.go2
-rw-r--r--cmd/podman/root.go10
-rwxr-xr-xdocs/dckrman.sh2
-rw-r--r--docs/source/markdown/podman-build.1.md42
-rw-r--r--docs/source/markdown/podman-remote.1.md22
-rw-r--r--docs/source/markdown/podman-search.1.md2
-rw-r--r--docs/source/markdown/podman.1.md57
-rw-r--r--libpod/container_copy_linux.go2
-rw-r--r--libpod/container_internal_linux.go5
-rw-r--r--libpod/kube.go21
-rw-r--r--libpod/network/cni/cni_types.go2
-rw-r--r--libpod/network/cni/config_test.go18
-rw-r--r--pkg/machine/pull.go2
-rw-r--r--pkg/specgen/specgen.go2
-rw-r--r--test/apiv2/20-containers.at18
-rw-r--r--test/e2e/checkpoint_test.go11
-rw-r--r--test/e2e/generate_kube_test.go113
-rw-r--r--test/e2e/network_create_test.go6
-rw-r--r--test/e2e/run_volume_test.go12
-rw-r--r--test/system/001-basic.bats9
-rw-r--r--troubleshooting.md2
23 files changed, 301 insertions, 83 deletions
diff --git a/Makefile b/Makefile
index 7c8c6f1c5..3b70c4f4f 100644
--- a/Makefile
+++ b/Makefile
@@ -176,6 +176,15 @@ define go-get
$(GO) get -u ${1}
endef
+# Need to use CGO for mDNS resolution, but cross builds need CGO disabled
+# See https://github.com/golang/go/issues/12524 for details
+DARWIN_GCO := 0
+ifeq ($(NATIVE_GOOS),darwin)
+ifdef HOMEBREW_PREFIX
+ DARWIN_GCO := 1
+endif
+endif
+
###
### Primary entry-point targets
###
@@ -351,7 +360,7 @@ podman-remote-windows: ## Build podman-remote for Windows
.PHONY: podman-remote-darwin
podman-remote-darwin: ## Build podman-remote for macOS
$(MAKE) \
- CGO_ENABLED=0 \
+ CGO_ENABLED=$(DARWIN_GCO) \
GOOS=darwin \
GOARCH=$(GOARCH) \
bin/darwin/podman
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index 09ac61f2e..50d7c446d 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -104,15 +104,18 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c
addField(&builder, "target", m.Target)
addField(&builder, "ro", strconv.FormatBool(m.ReadOnly))
addField(&builder, "consistency", string(m.Consistency))
-
// Map any specialized mount options that intersect between *Options and cli options
switch m.Type {
case mount.TypeBind:
- addField(&builder, "bind-propagation", string(m.BindOptions.Propagation))
- addField(&builder, "bind-nonrecursive", strconv.FormatBool(m.BindOptions.NonRecursive))
+ if m.BindOptions != nil {
+ addField(&builder, "bind-propagation", string(m.BindOptions.Propagation))
+ addField(&builder, "bind-nonrecursive", strconv.FormatBool(m.BindOptions.NonRecursive))
+ }
case mount.TypeTmpfs:
- addField(&builder, "tmpfs-size", strconv.FormatInt(m.TmpfsOptions.SizeBytes, 10))
- addField(&builder, "tmpfs-mode", strconv.FormatUint(uint64(m.TmpfsOptions.Mode), 10))
+ if m.TmpfsOptions != nil {
+ addField(&builder, "tmpfs-size", strconv.FormatInt(m.TmpfsOptions.SizeBytes, 10))
+ addField(&builder, "tmpfs-mode", strconv.FormatUint(uint64(m.TmpfsOptions.Mode), 10))
+ }
case mount.TypeVolume:
// All current VolumeOpts are handled above
// See vendor/github.com/containers/common/pkg/parse/parse.go:ValidateVolumeOpts()
diff --git a/cmd/podman/diff/diff.go b/cmd/podman/diff/diff.go
index 81bbb6c43..fba4ea540 100644
--- a/cmd/podman/diff/diff.go
+++ b/cmd/podman/diff/diff.go
@@ -8,7 +8,7 @@ import (
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/pkg/domain/entities"
- "github.com/docker/docker/pkg/archive"
+ "github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index eb30f1ef6..734636646 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -314,7 +314,15 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
lFlags.StringVar(&opts.Identity, identityFlagName, ident, "path to SSH identity file, (CONTAINER_SSHKEY)")
_ = cmd.RegisterFlagCompletionFunc(identityFlagName, completion.AutocompleteDefault)
- lFlags.BoolVarP(&opts.Remote, "remote", "r", false, "Access remote Podman service (default false)")
+ remote := false
+ if env, ok := os.LookupEnv("CONTAINER_HOST"); ok {
+ logrus.Infof("CONTAINER_HOST==%q, defaulting to '--remote=true'", env)
+ remote = true
+ } else if env, ok := os.LookupEnv("CONTAINER_CONNECTION"); ok {
+ logrus.Infof("CONTAINER_CONNECTION==%q, defaulting to '--remote=true'", env)
+ remote = true
+ }
+ lFlags.BoolVarP(&opts.Remote, "remote", "r", remote, "Access remote Podman service")
pFlags := cmd.PersistentFlags()
if registry.IsRemote() {
if err := lFlags.MarkHidden("remote"); err != nil {
diff --git a/docs/dckrman.sh b/docs/dckrman.sh
index 18fb364bf..48685a14b 100755
--- a/docs/dckrman.sh
+++ b/docs/dckrman.sh
@@ -5,3 +5,5 @@ for i in $@; do
echo .so man1/$b > $filename
done
echo .so man5/containerfile.5 > $(dirname $1)/dockerfile.5
+echo .so man5/containerignore.5 > $(dirname $1)/.dockerignore.5
+echo .so man5/containerignore.5 > $(dirname $1)/dockerignore.5
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 15d936d17..fd36166b6 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -35,8 +35,8 @@ location.
When a Git repository is set as the URL, the repository is cloned locally and
then set as the context.
-NOTE: `podman build` uses code sourced from the `buildah` project to build
-container images. This `buildah` code creates `buildah` containers for the
+NOTE: `podman build` uses code sourced from the `Buildah` project to build
+container images. This `Buildah` code creates `Buildah` containers for the
`RUN` options in container storage. In certain situations, when the
`podman build` crashes or users kill the `podman build` process, these external
containers can be left in container storage. Use the `podman ps --all --storage`
@@ -256,7 +256,7 @@ specifying **--disable-compression=false**.
#### **--disable-content-trust**
-This is a Docker specific option to disable image verification to a Docker
+This is a Docker specific option to disable image verification to a container
registry and is not supported by Podman. This flag is a NOOP and provided
solely for scripting compatibility. (This option is not available with the remote Podman client)
@@ -328,7 +328,7 @@ than once, attempting to use this option will trigger an error.
#### **--ignorefile**
-Path to an alternative .dockerignore file.
+Path to an alternative .containerignore file.
#### **--ipc**=*how*
@@ -845,15 +845,15 @@ $ podman build .
$ podman build -f Containerfile.simple .
-$ cat $HOME/Dockerfile | podman build -f - .
+$ cat $HOME/Containerfile | podman build -f - .
-$ podman build -f Dockerfile.simple -f Containerfile.notsosimple .
+$ podman build -f Containerfile.simple -f Containerfile.notsosimple .
-$ podman build -f Dockerfile.in $HOME
+$ podman build -f Containerfile.in $HOME
$ podman build -t imageName .
-$ podman build --tls-verify=true -t imageName -f Dockerfile.simple .
+$ podman build --tls-verify=true -t imageName -f Containerfile.simple .
$ podman build --tls-verify=false -t imageName .
@@ -861,7 +861,7 @@ $ podman build --runtime-flag log-format=json .
$ podman build --runtime-flag debug .
-$ podman build --authfile /tmp/auths/myauths.json --cert-dir $HOME/auth --tls-verify=true --creds=username:password -t imageName -f Dockerfile.simple .
+$ podman build --authfile /tmp/auths/myauths.json --cert-dir $HOME/auth --tls-verify=true --creds=username:password -t imageName -f Containerfile.simple .
$ podman build --memory 40m --cpu-period 10000 --cpu-quota 50000 --ulimit nofile=1024:1028 -t imageName .
@@ -940,22 +940,26 @@ $ podman build -f dev/Containerfile https://10.10.10.1/podman/context.tar.gz
## Files
-### `.dockerignore`
+### .containerignore/.dockerignore
-If the file .dockerignore exists in the context directory, `buildah copy` reads
-its contents. Use the `--ignorefile` flag to override .dockerignore path location.
+If the file *.containerignore* or *.dockerignore* exists in the context directory,
+`podman build` reads its contents. Use the `--ignorefile` flag to override the
+.containerignore path location.
Podman uses the content to exclude files and directories from the context
directory, when executing COPY and ADD directives in the
Containerfile/Dockerfile
-Users can specify a series of Unix shell globals in a .dockerignore file to
+The .containerignore and .dockerignore files use the same syntax; if both
+are in the context directory, podman build will only use .containerignore.
+
+Users can specify a series of Unix shell globs in a .containerignore file to
identify files/directories to exclude.
Podman supports a special wildcard string `**` which matches any number of
directories (including zero). For example, **/*.go will exclude all files that
end with .go that are found in all directories.
-Example .dockerignore file:
+Example .containerignore file:
```
# exclude this content for image
@@ -975,7 +979,7 @@ Excludes files and directories starting with `output` from any directory.
Excludes files named src and the directory src as well as any content in it.
Lines starting with ! (exclamation mark) can be used to make exceptions to
-exclusions. The following is an example .dockerignore file that uses this
+exclusions. The following is an example .containerignore file that uses this
mechanism:
```
*.doc
@@ -984,10 +988,10 @@ mechanism:
Exclude all doc files except Help.doc from the image.
-This functionality is compatible with the handling of .dockerignore files
+This functionality is compatible with the handling of .containerignore files
described here:
-https://docs.docker.com/engine/reference/builder/#dockerignore-file
+https://github.com/containers/buildah/blob/main/docs/containerignore.5.md
**registries.conf** (`/etc/containers/registries.conf`)
@@ -1009,10 +1013,10 @@ If you are using `useradd` within your build script, you should pass the
useradd to stop creating the lastlog file.
## SEE ALSO
-podman(1), buildah(1), containers-certs.d(5), containers-registries.conf(5), crun(8), runc(8), useradd(8), podman-ps(1), podman-rm(1)
+podman(1), buildah(1), containers-certs.d(5), containers-registries.conf(5), crun(8), runc(8), useradd(8), podman-ps(1), podman-rm(1), Containerfile(5), containerignore(5)
## HISTORY
-Aug 2020, Additional options and .dockerignore added by Dan Walsh `<dwalsh@redhat.com>`
+Aug 2020, Additional options and .containerignore added by Dan Walsh `<dwalsh@redhat.com>`
May 2018, Minor revisions added by Joe Doss `<joe@solidadmin.com>`
diff --git a/docs/source/markdown/podman-remote.1.md b/docs/source/markdown/podman-remote.1.md
index 1a6c7d3cc..fb77f3300 100644
--- a/docs/source/markdown/podman-remote.1.md
+++ b/docs/source/markdown/podman-remote.1.md
@@ -29,6 +29,8 @@ The `containers.conf` file should be placed under `$HOME/.config/containers/cont
Remote connection name
+Overrides environment variable `CONTAINER_CONNECTION` if set.
+
#### **--help**, **-h**
Print usage statement
@@ -71,6 +73,26 @@ URL value resolution precedence:
Print the version
+## Environment Variables
+
+Podman can set up environment variables from env of [engine] table in containers.conf. These variables can be overridden by passing environment variables before the `podman` commands.
+
+#### **CONTAINERS_CONF**
+
+Set default locations of containers.conf file
+
+#### **CONTAINER_CONNECTION**
+
+Set default `--connection` value to access Podman service.
+
+#### **CONTAINER_HOST**
+
+Set default `--url` value to access Podman service.
+
+#### **CONTAINER_SSHKEY**
+
+Set default `--identity` path to ssh key file value used to access Podman service.
+
## Exit Status
The exit code from `podman` gives information about why the container
diff --git a/docs/source/markdown/podman-search.1.md b/docs/source/markdown/podman-search.1.md
index 7c37e389c..911bbcb4b 100644
--- a/docs/source/markdown/podman-search.1.md
+++ b/docs/source/markdown/podman-search.1.md
@@ -40,7 +40,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--compatible**
After the name and the description, also show the stars, official and automated descriptors as Docker does.
-Podman does not show these decsriptors by default since they are not supported by most public container registries.
+Podman does not show these descriptors by default since they are not supported by most public container registries.
#### **--filter**, **-f**=*filter*
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index 4de8b6ea6..beb6e26d8 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -93,8 +93,9 @@ When namespace is set, created containers and pods will join the given namespace
Path to the command binary to use for setting up a network. It is currently only used for setting up a slirp4netns network. If "" is used then the binary is looked up using the $PATH environment variable.
#### **--remote**, **-r**
-Access Podman service will be remote
-Remote connections use local containers.conf for default.
+When true, access to the Podman service will be remote. Defaults to false.
+Settings can be modified in the containers.conf file. If the CONTAINER_HOST
+environment variable is set, the remote option defaults to true.
#### **--url**=*value*
URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`).
@@ -172,6 +173,58 @@ Print the version
Podman can set up environment variables from env of [engine] table in containers.conf. These variables can be overridden by passing environment variables before the `podman` commands.
+#### **CONTAINERS_CONF**
+
+Set default locations of containers.conf file
+
+#### **CONTAINERS_REGISTRIES_CONF**
+
+Set default location of the registries.conf file.
+
+#### **CONTAINERS_STORAGE_CONF**
+
+Set default location of the storage.conf file.
+
+#### **CONTAINER_CONNECTION**
+
+Override default `--connection` value to access Podman service. Also enabled --remote option.
+
+#### **CONTAINER_HOST**
+
+Set default `--url` value to access Podman service. Also enabled --remote option.
+
+#### **CONTAINER_SSHKEY**
+
+Set default `--identity` path to ssh key file value used to access Podman service.
+
+#### **STORAGE_DRIVER**
+
+Set default `--storage-driver` value.
+
+#### **STORAGE_OPTS**
+
+Set default `--storage-opts` value.
+
+#### **TMPDIR**
+
+Set the the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`.
+
+#### **XDG_CONFIG_HOME**
+
+In Rootless mode configuration files are read from `XDG_CONFIG_HOME` when
+specified, otherwise in the home directory of the user under
+`$HOME/.config/containers`.
+
+#### **XDG_DATA_HOME**
+
+In Rootless mode images are pulled under `XDG_DATA_HOME` when specified,
+otherwise in the home directory of the user under
+`$HOME/.local/share/containers/storage`.
+
+#### **XDG_RUNTIME_DIR**
+
+In Rootless mode temporary configuration data is stored in `${XDG_RUNTIME_DIR}/containers`.
+
## Remote Access
The Podman command can be used with remote services using the `--remote` flag. Connections can
diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go
index 7d4dd0d46..954d54a1d 100644
--- a/libpod/container_copy_linux.go
+++ b/libpod/container_copy_linux.go
@@ -15,8 +15,8 @@ import (
"github.com/containers/buildah/util"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/idtools"
- "github.com/docker/docker/pkg/archive"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index f652a3ebb..d8385961f 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1008,12 +1008,15 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
includeFiles := []string{
"artifacts",
- "ctr.log",
metadata.ConfigDumpFile,
metadata.SpecDumpFile,
metadata.NetworkStatusFile,
}
+ if c.LogDriver() == define.KubernetesLogging ||
+ c.LogDriver() == define.JSONLogging {
+ includeFiles = append(includeFiles, "ctr.log")
+ }
if options.PreCheckPoint {
includeFiles = append(includeFiles, preCheckpointDir)
} else {
diff --git a/libpod/kube.go b/libpod/kube.go
index eb7743886..d47f47f1c 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -25,6 +25,7 @@ import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/util/intstr"
)
// GenerateForKube takes a slice of libpod containers and generates
@@ -196,10 +197,11 @@ func containerPortsToServicePorts(containerPorts []v1.ContainerPort) []v1.Servic
for _, cp := range containerPorts {
nodePort := 30000 + rand.Intn(32767-30000+1)
servicePort := v1.ServicePort{
- Protocol: cp.Protocol,
- Port: cp.ContainerPort,
- NodePort: int32(nodePort),
- Name: strconv.Itoa(int(cp.ContainerPort)),
+ Protocol: cp.Protocol,
+ Port: cp.ContainerPort,
+ NodePort: int32(nodePort),
+ Name: strconv.Itoa(int(cp.ContainerPort)),
+ TargetPort: intstr.Parse(strconv.Itoa(int(cp.ContainerPort))),
}
sps = append(sps, servicePort)
}
@@ -481,10 +483,16 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
if err != nil {
return kubeContainer, kubeVolumes, nil, annotations, err
}
- if reflect.DeepEqual(imgData.Config.Cmd, kubeContainer.Command) {
+ // If the user doesn't set a command/entrypoint when creating the container with podman and
+ // is using the image command or entrypoint from the image, don't add it to the generated kube yaml
+ if reflect.DeepEqual(imgData.Config.Cmd, kubeContainer.Command) || reflect.DeepEqual(imgData.Config.Entrypoint, kubeContainer.Command) {
kubeContainer.Command = nil
}
+ if imgData.User == c.User() {
+ kubeSec.RunAsGroup, kubeSec.RunAsUser = nil, nil
+ }
+
kubeContainer.WorkingDir = c.WorkingDir()
kubeContainer.Ports = ports
// This should not be applicable
@@ -572,7 +580,8 @@ func ocicniPortMappingToContainerPort(portMappings []types.OCICNIPortMapping) ([
var protocol v1.Protocol
switch strings.ToUpper(p.Protocol) {
case "TCP":
- protocol = v1.ProtocolTCP
+ // do nothing as it is the default protocol in k8s, there is no need to explicitly
+ // add it to the generated yaml
case "UDP":
protocol = v1.ProtocolUDP
default:
diff --git a/libpod/network/cni/cni_types.go b/libpod/network/cni/cni_types.go
index fbf917c2d..87beceff3 100644
--- a/libpod/network/cni/cni_types.go
+++ b/libpod/network/cni/cni_types.go
@@ -182,7 +182,7 @@ func newIPAMLocalHostRange(subnet types.IPNet, leaseRange *types.LeaseRange, gw
hostRange.RangeStart = leaseRange.StartIP.String()
}
if leaseRange.EndIP != nil {
- hostRange.RangeStart = leaseRange.EndIP.String()
+ hostRange.RangeEnd = leaseRange.EndIP.String()
}
}
diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go
index 5181cd900..0dfc6173c 100644
--- a/libpod/network/cni/config_test.go
+++ b/libpod/network/cni/config_test.go
@@ -621,7 +621,7 @@ var _ = Describe("Config", func() {
err = libpodNet.NetworkRemove(network1.Name)
Expect(err).To(BeNil())
- endIP := "10.0.0.10"
+ endIP := "10.0.0.30"
network = types.Network{
Driver: "bridge",
Subnets: []types.Subnet{
@@ -665,6 +665,22 @@ var _ = Describe("Config", func() {
Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
+
+ // create a new interface to force a config load from disk
+ libpodNet, err = getNetworkInterface(cniConfDir, false)
+ Expect(err).To(BeNil())
+
+ network1, err = libpodNet.NetworkInspect(network1.Name)
+ Expect(err).To(BeNil())
+ Expect(network1.Name).ToNot(BeEmpty())
+ Expect(network1.ID).ToNot(BeEmpty())
+ Expect(network1.NetworkInterface).ToNot(BeEmpty())
+ Expect(network1.Driver).To(Equal("bridge"))
+ Expect(network1.Subnets).To(HaveLen(1))
+ Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
+ Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
+ Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
+ Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
})
It("create bridge with subnet and invalid lease range", func() {
diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go
index f79ac6ec4..3c8422a30 100644
--- a/pkg/machine/pull.go
+++ b/pkg/machine/pull.go
@@ -15,7 +15,7 @@ import (
"time"
"github.com/containers/image/v5/pkg/compression"
- "github.com/docker/docker/pkg/archive"
+ "github.com/containers/storage/pkg/archive"
"github.com/sirupsen/logrus"
"github.com/vbauerster/mpb/v6"
"github.com/vbauerster/mpb/v6/decor"
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index 07995b2df..79185db04 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -551,7 +551,7 @@ func NewSpecGenerator(arg string, rootfs bool) *SpecGenerator {
csc := ContainerStorageConfig{}
if rootfs {
csc.Rootfs = arg
- // check if rootfs is actually overlayed
+ // check if rootfs should use overlay
lastColonIndex := strings.LastIndex(csc.Rootfs, ":")
if lastColonIndex != -1 && lastColonIndex+1 < len(csc.Rootfs) && csc.Rootfs[lastColonIndex+1:] == "O" {
csc.RootfsOverlay = true
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index afff68c22..748a0750f 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -379,3 +379,21 @@ t GET containers/$cid/json 200 \
.HostConfig.Tmpfs['"/mnt/scratch"']~.*mode=755.*
t DELETE containers/$cid?v=true 204
+
+# compat api: tmpfs without mount options
+payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch"}]}'
+t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+t GET containers/$cid/json 200 \
+ .HostConfig.Tmpfs['"/mnt/scratch"']~.*tmpcopyup.* \
+
+t DELETE containers/$cid?v=true 204
+
+# compat api: bind mount without mount options
+payload='{"Mounts":[{"Type":"bind","Source":"/tmp","Target":"/mnt"}]}'
+t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+t GET containers/$cid/json 200 \
+ .HostConfig.Binds[0]~/tmp:/mnt:.* \
+
+t DELETE containers/$cid?v=true 204
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 993987f34..770a7c7bd 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -249,16 +249,19 @@ var _ = Describe("Podman checkpoint", func() {
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+ if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
+ Fail("Container failed to get ready")
+ }
IP := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
IP.WaitWithDefaultTimeout()
Expect(IP).Should(Exit(0))
// Open a network connection to the redis server
- conn, err := net.Dial("tcp", IP.OutputToString()+":6379")
- if err != nil {
- os.Exit(1)
- }
+ conn, err := net.DialTimeout("tcp4", IP.OutputToString()+":6379", time.Duration(3)*time.Second)
+ Expect(err).To(BeNil())
+
// This should fail as the container has established TCP connections
result := podmanTest.Podman([]string{"container", "checkpoint", "-l"})
result.WaitWithDefaultTimeout()
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 3e6f1e8c4..69941494b 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"strconv"
+ "strings"
"github.com/containers/podman/v3/libpod/define"
@@ -119,20 +120,28 @@ var _ = Describe("Podman generate kube", func() {
Expect(kube.OutputToString()).To(ContainSubstring("type: foo_bar_t"))
})
- It("podman generate service kube on container", func() {
- session := podmanTest.RunTopContainer("top")
+ It("podman generate service kube on container - targetPort should match port name", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "test-ctr", "-p", "3890:3890", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "-s", "top"})
+ kube := podmanTest.Podman([]string{"generate", "kube", "-s", "test-ctr"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // TODO - test generated YAML - service produces multiple
- // structs.
- // pod := new(v1.Pod)
- // err := yaml.Unmarshal([]byte(kube.OutputToString()), pod)
- // Expect(err).To(BeNil())
+ // Separate out the Service and Pod yaml
+ arr := strings.Split(string(kube.Out.Contents()), "---")
+ Expect(len(arr)).To(Equal(2))
+
+ svc := new(v1.Service)
+ err := yaml.Unmarshal([]byte(arr[0]), svc)
+ Expect(err).To(BeNil())
+ Expect(len(svc.Spec.Ports)).To(Equal(1))
+ Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(3890))
+
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal([]byte(arr[1]), pod)
+ Expect(err).To(BeNil())
})
It("podman generate kube on pod", func() {
@@ -315,21 +324,28 @@ var _ = Describe("Podman generate kube", func() {
})
It("podman generate service kube on pod", func() {
- _, rc, _ := podmanTest.CreatePod(map[string][]string{"--name": {"toppod"}})
- Expect(rc).To(Equal(0))
-
- session := podmanTest.RunTopContainerInPod("topcontainer", "toppod")
+ session := podmanTest.Podman([]string{"create", "--pod", "new:test-pod", "-p", "4000:4000/udp", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "-s", "toppod"})
+ kube := podmanTest.Podman([]string{"generate", "kube", "-s", "test-pod"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // TODO: How do we test unmarshal with a service? We have two
- // structs that need to be unmarshalled...
- // _, err := yaml.Marshal(kube.OutputToString())
- // Expect(err).To(BeNil())
+ // Separate out the Service and Pod yaml
+ arr := strings.Split(string(kube.Out.Contents()), "---")
+ Expect(len(arr)).To(Equal(2))
+
+ svc := new(v1.Service)
+ err := yaml.Unmarshal([]byte(arr[0]), svc)
+ Expect(err).To(BeNil())
+ Expect(len(svc.Spec.Ports)).To(Equal(1))
+ Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(4000))
+ Expect(svc.Spec.Ports[0].Protocol).To(Equal(v1.ProtocolUDP))
+
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal([]byte(arr[1]), pod)
+ Expect(err).To(BeNil())
})
It("podman generate kube on pod with restartPolicy", func() {
@@ -451,6 +467,10 @@ var _ = Describe("Podman generate kube", func() {
foundOtherPort := 0
for _, ctr := range pod.Spec.Containers {
for _, port := range ctr.Ports {
+ // Since we are using tcp here, the generated kube yaml shouldn't
+ // have anything for protocol under the ports as tcp is the default
+ // for k8s
+ Expect(port.Protocol).To(BeEmpty())
if port.HostPort == 4000 {
foundPort4000 = foundPort4000 + 1
} else if port.HostPort == 5000 {
@@ -463,6 +483,24 @@ var _ = Describe("Podman generate kube", func() {
Expect(foundPort4000).To(Equal(1))
Expect(foundPort5000).To(Equal(1))
Expect(foundOtherPort).To(Equal(0))
+
+ // Create container with UDP port and check the generated kube yaml
+ ctrWithUDP := podmanTest.Podman([]string{"create", "--pod", "new:test-pod", "-p", "6666:66/udp", ALPINE, "top"})
+ ctrWithUDP.WaitWithDefaultTimeout()
+ Expect(ctrWithUDP).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "test-pod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ containers := pod.Spec.Containers
+ Expect(len(containers)).To(Equal(1))
+ Expect(len(containers[0].Ports)).To(Equal(1))
+ Expect(containers[0].Ports[0].Protocol).To(Equal(v1.ProtocolUDP))
})
It("podman generate and reimport kube on pod", func() {
@@ -803,7 +841,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(containers[0].Args).To(Equal([]string{"10s"}))
})
- It("podman generate kube - no command", func() {
+ It("podman generate kube - use command from image unless explicitly set in the podman command", func() {
session := podmanTest.Podman([]string{"create", "--name", "test", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -812,8 +850,8 @@ var _ = Describe("Podman generate kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // Now make sure that the container's command is not set to the
- // entrypoint and it's arguments to "10s".
+ // Now make sure that the container's command in the kube yaml is not set to the
+ // image command.
pod := new(v1.Pod)
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
@@ -831,8 +869,8 @@ var _ = Describe("Podman generate kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // Now make sure that the container's command is not set to the
- // entrypoint and it's arguments to "10s".
+ // Now make sure that the container's command in the kube yaml is set to the
+ // command passed via the cli to podman create.
pod = new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
@@ -842,10 +880,10 @@ var _ = Describe("Podman generate kube", func() {
Expect(containers[0].Command).To(Equal(cmd))
})
- It("podman generate kube - use entrypoint from image", func() {
+ It("podman generate kube - use entrypoint from image unless --entrypoint is set", func() {
// Build an image with an entrypoint.
containerfile := `FROM quay.io/libpod/alpine:latest
-ENTRYPOINT /bin/sleep`
+ENTRYPOINT ["sleep"]`
targetPath, err := CreateTempDirInTempDir()
Expect(err).To(BeNil())
@@ -866,17 +904,34 @@ ENTRYPOINT /bin/sleep`
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // Now make sure that the container's command is set to the
- // entrypoint and it's arguments to "10s".
+ // Now make sure that the container's command in the kube yaml is NOT set to the
+ // entrypoint but the arguments should be set to "10s".
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
containers := pod.Spec.Containers
Expect(len(containers)).To(Equal(1))
-
- Expect(containers[0].Command).To(Equal([]string{"/bin/sh", "-c", "/bin/sleep"}))
Expect(containers[0].Args).To(Equal([]string{"10s"}))
+
+ session = podmanTest.Podman([]string{"create", "--pod", "new:testpod-2", "--entrypoint", "echo", image, "hello"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "testpod-2"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ // Now make sure that the container's command in the kube yaml is set to the
+ // entrypoint defined by the --entrypoint flag and the arguments should be set to "hello".
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ containers = pod.Spec.Containers
+ Expect(len(containers)).To(Equal(1))
+ Expect(containers[0].Command).To(Equal([]string{"echo"}))
+ Expect(containers[0].Args).To(Equal([]string{"hello"}))
})
It("podman generate kube - --privileged container", func() {
@@ -942,7 +997,7 @@ USER test1`
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
- Expect(*pod.Spec.Containers[0].SecurityContext.RunAsUser).To(Equal(int64(10001)))
+ Expect(pod.Spec.Containers[0].SecurityContext.RunAsUser).To(BeNil())
})
It("podman generate kube on named volume", func() {
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index ae9f112b5..c9e13e7d2 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -43,7 +43,7 @@ var _ = Describe("Podman network create", func() {
It("podman network create with name and subnet", func() {
netName := "subnet-" + stringid.GenerateNonCryptoID()
- nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", netName})
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ip-range", "10.11.12.0/26", netName})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeCNINetwork(netName)
Expect(nc).Should(Exit(0))
@@ -61,7 +61,11 @@ var _ = Describe("Podman network create", func() {
result := results[0]
Expect(result.Name).To(Equal(netName))
Expect(result.Subnets).To(HaveLen(1))
+ Expect(result.Subnets[0].Subnet.String()).To(Equal("10.11.12.0/24"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.11.12.1"))
+ Expect(result.Subnets[0].LeaseRange).ToNot(BeNil())
+ Expect(result.Subnets[0].LeaseRange.StartIP.String()).To(Equal("10.11.12.1"))
+ Expect(result.Subnets[0].LeaseRange.EndIP.String()).To(Equal("10.11.12.63"))
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index f1baa7780..634a498b9 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -222,7 +222,7 @@ var _ = Describe("Podman run with volumes", func() {
Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
})
- // Container should start when workdir is overlayed volume
+ // Container should start when workdir is overlay volume
It("podman run with volume mounted as overlay and used as workdir", func() {
SkipIfRemote("Overlay volumes only work locally")
if os.Getenv("container") != "" {
@@ -236,7 +236,7 @@ var _ = Describe("Podman run with volumes", func() {
mountPath := filepath.Join(podmanTest.TempDir, "secrets")
os.Mkdir(mountPath, 0755)
- //Container should be able to start with custom overlayed volume
+ //Container should be able to start with custom overlay volume
session := podmanTest.Podman([]string{"run", "--rm", "-v", mountPath + ":/data:O", "--workdir=/data", ALPINE, "echo", "hello"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -262,15 +262,15 @@ var _ = Describe("Podman run with volumes", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- // create file on overlayed volume
- session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlayed"})
+ // create file on overlay volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlay"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- // volume should contain only `test` not `overlayed`
+ // volume should contain only `test` not `overlay`
session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "ls /data"})
session.WaitWithDefaultTimeout()
- Expect(session.OutputToString()).To(Not(ContainSubstring("overlayed")))
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlay")))
Expect(session.OutputToString()).To(ContainSubstring("test"))
})
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index 2e5ebe4a3..2de96a01a 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -93,6 +93,15 @@ function setup() {
is "$output" "Error: unknown flag: --remote" "podman version --remote"
}
+@test "podman-remote: defaults" {
+ if is_remote; then
+ skip "only applicable on a local run"
+ fi
+
+ CONTAINER_HOST=foobar run_podman --log-level=info --help
+ is "$output" ".*defaulting to '--remote=true'" "CONTAINER_HOST sets --remote true"
+}
+
# Check that just calling "podman-remote" prints the usage message even
# without a running endpoint. Use "podman --remote" for this as this works the same.
@test "podman-remote: check for command usage message without a running endpoint" {
diff --git a/troubleshooting.md b/troubleshooting.md
index a6c014625..b335eaaa8 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -875,7 +875,7 @@ def signal_listener():
sys.exit(0)
except Exception as e:
loop.quit()
- sys.stderr.write(f"Error occured {e}")
+ sys.stderr.write(f"Error occurred {e}")
sys.exit(1)
if __name__ == "__main__":