aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands-demo.md2
-rwxr-xr-xcontrib/cirrus/logformatter20
-rw-r--r--contrib/remote/containers.conf2
-rw-r--r--docs/source/markdown/podman-run.1.md12
-rw-r--r--libpod/container_internal.go10
-rw-r--r--libpod/container_internal_linux.go7
-rw-r--r--libpod/define/container_inspect.go6
-rw-r--r--libpod/define/errors.go2
-rw-r--r--libpod/define/volume_inspect.go2
-rw-r--r--libpod/events/nullout.go2
-rw-r--r--libpod/kube.go53
-rw-r--r--libpod/oci_conmon_linux.go6
-rw-r--r--libpod/runtime_volume_linux.go4
-rw-r--r--pkg/domain/infra/abi/generate.go21
-rw-r--r--test/e2e/generate_kube_test.go103
-rw-r--r--test/e2e/stop_test.go2
-rw-r--r--test/system/helpers.bash4
17 files changed, 200 insertions, 58 deletions
diff --git a/commands-demo.md b/commands-demo.md
index 50e2873b2..c1413dd9e 100644
--- a/commands-demo.md
+++ b/commands-demo.md
@@ -12,7 +12,7 @@
| [podman-container(1)](https://podman.readthedocs.io/en/latest/managecontainers.html) | Manage Containers |
| [podman-container-checkpoint(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-checkpoint.1.html) | Checkpoints one or more running containers |
| [podman-container-cleanup(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-cleanup.1.html) | Clean up the container's network and mountpoints |
-| [podman-container-exists(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-exists.1.html) | Check if an container exists in local storage |
+| [podman-container-exists(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-exists.1.html) | Check if a container exists in local storage |
| [podman-container-prune(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-prune.1.html) | Remove all stopped containers from local storage |
| [podman-container-restore(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-restore.1.html) | Restores one or more containers from a checkpoint |
| [podman-container-runlabel(1)](https://podman.readthedocs.io/en/latest/markdown/podman-container-runlabel.1.html) | Executes a command as described by a container image label |
diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter
index 59969c3e7..1dc618768 100755
--- a/contrib/cirrus/logformatter
+++ b/contrib/cirrus/logformatter
@@ -560,18 +560,14 @@ END_HTML
# See #14569 for more info.
#
# [1] https://cirrus-ci.org/guide/writing-tasks/#latest-build-artifacts
- if ($have_formatted_log && $ENV{CIRRUS_BUILD_ID} && $ENV{CIRRUS_TASK_NAME}) {
- my $URL_BASE = "https://api.cirrus-ci.com";
- my $build_id = $ENV{CIRRUS_BUILD_ID};
- my $task_name = $ENV{CIRRUS_TASK_NAME};
-
- # Escape spaces in task names ("int fedora 35 podman root etc")
- $task_name =~ s/\s/%20/g;
-
- # URL is long and cumbersome and duplicaty. The task name cannot be
- # reduced; the file name could, but I choose to leave it because I
- # sometimes download HTML logs and oh how I hate "log.html" filenames.
- my $URL = "${URL_BASE}/v1/artifact/build/$build_id/$task_name/html/${outfile}";
+ if ($have_formatted_log && $ENV{CIRRUS_TASK_ID}) {
+ my $URL_BASE = "https://api.cirrus-ci.com";
+ my $task_id = $ENV{CIRRUS_TASK_ID};
+
+ # Link by *taskID*, not buildID + taskname. First, this is shorter
+ # and less duplicaty. Second, and more important, buildID + taskname
+ # is non-unique, and a link to a flake log will be clobbered.
+ my $URL = "${URL_BASE}/v1/artifact/task/$task_id/html/${outfile}";
print "\n\nAnnotated results:\n $URL\n";
}
diff --git a/contrib/remote/containers.conf b/contrib/remote/containers.conf
index 9b0b62c42..70710be04 100644
--- a/contrib/remote/containers.conf
+++ b/contrib/remote/containers.conf
@@ -1,4 +1,4 @@
-# The containers configuration file specifies all of the available configuration
+# The container's configuration file specifies all of the available configuration
# command-line options/flags for container engine tools like Podman
# but in a TOML format that can be easily modified and versioned.
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index e628a806a..a389be2a8 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -288,7 +288,7 @@ detached container with **podman attach**.
When attached in the tty mode, you can detach from the container (and leave it
running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`.
-Configure the keys sequence using the **--detach-keys** option, or specifying
+Specify the key sequence using the **--detach-keys** option, or configure
it in the **containers.conf** file: see **containers.conf(5)** for more information.
#### **--detach-keys**=*sequence*
@@ -300,7 +300,7 @@ This option can also be set in **containers.conf**(5) file.
#### **--device**=_host-device_[**:**_container-device_][**:**_permissions_]
Add a host device to the container. Optional *permissions* parameter
-can be used to specify device permissions, it is combination of
+can be used to specify device permissions by combining
**r** for read, **w** for write, and **m** for **mknod**(2).
Example: **--device=/dev/sdc:/dev/xvdc:rwm**.
@@ -1158,7 +1158,7 @@ $ podman run -d --tmpfs /tmp:rw,size=787448k,mode=1777 my_image
This command mounts a **tmpfs** at _/tmp_ within the container. The supported mount
options are the same as the Linux default mount flags. If you do not specify
-any options, the systems uses the following options:
+any options, the system uses the following options:
**rw,noexec,nosuid,nodev**.
#### **--tty**, **-t**
@@ -1598,7 +1598,7 @@ content. Installing packages into _/usr_, for example. In production,
applications seldom need to write to the image. Container applications write
to volumes if they need to write to file systems at all. Applications can be
made more secure by running them in read-only mode using the **--read-only** switch.
-This protects the containers image from modification. Read-only containers may
+This protects the container's image from modification. Read-only containers may
still need to write temporary data. The best way to handle this is to mount
tmpfs directories on _/run_ and _/tmp_.
@@ -1879,7 +1879,7 @@ $ podman run --uidmap 0:30000:7000 --gidmap 0:30000:7000 fedora echo hello
Podman allows for the configuration of storage by changing the values
in the _/etc/container/storage.conf_ or by using global options. This
-shows how to set up and use fuse-overlayfs for a one time run of busybox
+shows how to set up and use fuse-overlayfs for a one-time run of busybox
using global options.
```
@@ -1975,7 +1975,7 @@ in the following order of precedence (later entries override earlier entries):
- Container image: Any environment variables specified in the container image.
- **--http-proxy**: By default, several environment variables will be passed in from the host, such as **http_proxy** and **no_proxy**. See **--http-proxy** for details.
- **--env-host**: Host environment of the process executing Podman is added.
-- **--env-file**: Any environment variables specified via env-files. If multiple files specified, then they override each other in order of entry.
+- **--env-file**: Any environment variables specified via env-files. If multiple files are specified, then they override each other in order of entry.
- **--env**: Any environment variables specified will override previous settings.
Run containers and set the environment ending with a __*__.
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 6a98466c2..caf7f3849 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -130,7 +130,7 @@ func (c *Container) bundlePath() string {
return c.config.StaticDir
}
-// ControlSocketPath returns the path to the containers control socket for things like tty
+// ControlSocketPath returns the path to the container's control socket for things like tty
// resizing
func (c *Container) ControlSocketPath() string {
return filepath.Join(c.bundlePath(), "ctl")
@@ -513,8 +513,8 @@ func (c *Container) setupStorage(ctx context.Context) error {
return fmt.Errorf("error creating container storage: %w", containerInfoErr)
}
- // only reconfig IDMappings if layer was mounted from storage
- // if its a external overlay do not reset IDmappings
+ // Only reconfig IDMappings if layer was mounted from storage.
+ // If it's an external overlay do not reset IDmappings.
if !c.config.RootfsOverlay {
c.config.IDMappings.UIDMap = containerInfo.UIDMap
c.config.IDMappings.GIDMap = containerInfo.GIDMap
@@ -794,7 +794,7 @@ func (c *Container) save() error {
}
// Checks the container is in the right state, then initializes the container in preparation to start the container.
-// If recursive is true, each of the containers dependencies will be started.
+// If recursive is true, each of the container's dependencies will be started.
// Otherwise, this function will return with error if there are dependencies of this container that aren't running.
func (c *Container) prepareToStart(ctx context.Context, recursive bool) (retErr error) {
// Container must be created or stopped to be started
@@ -1255,7 +1255,7 @@ func (c *Container) stop(timeout uint) error {
// If the container is running in a PID Namespace, then killing the
// primary pid is enough to kill the container. If it is not running in
// a pid namespace then the OCI Runtime needs to kill ALL processes in
- // the containers cgroup in order to make sure the container is stopped.
+ // the container's cgroup in order to make sure the container is stopped.
all := !c.hasNamespace(spec.PIDNamespace)
// We can't use --all if Cgroups aren't present.
// Rootless containers with Cgroups v1 and NoCgroups are both cases
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 390e95258..46e525add 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -184,11 +184,8 @@ func (c *Container) prepare() error {
func (c *Container) isWorkDirSymlink(resolvedPath string) bool {
// We cannot create workdir since explicit --workdir is
// set in config but workdir could also be a symlink.
- // If its a symlink lets check if resolved link is present
- // on the container or not.
-
- // If we can resolve symlink and resolved link is present on the container
- // then return nil cause its a valid use-case.
+ // If it's a symlink, check if the resolved target is present in the container.
+ // If so, that's a valid use case: return nil.
maxSymLinks := 0
for {
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index ccc4ae00f..e6a34ba61 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -506,8 +506,8 @@ type InspectContainerHostConfig struct {
// CpuRealtimeRuntime is the length of time (in microseconds) allocated
// for realtime tasks within every CpuRealtimePeriod.
CpuRealtimeRuntime int64 `json:"CpuRealtimeRuntime"`
- // CpusetCpus is the is the set of CPUs that the container will execute
- // on. Formatted as `0-3` or `0,2`. Default (if unset) is all CPUs.
+ // CpusetCpus is the set of CPUs that the container will execute on.
+ // Formatted as `0-3` or `0,2`. Default (if unset) is all CPUs.
CpusetCpus string `json:"CpusetCpus"`
// CpusetMems is the set of memory nodes the container will use.
// Formatted as `0-3` or `0,2`. Default (if unset) is all memory nodes.
@@ -544,7 +544,7 @@ type InspectContainerHostConfig struct {
OomKillDisable bool `json:"OomKillDisable"`
// Init indicates whether the container has an init mounted into it.
Init bool `json:"Init,omitempty"`
- // PidsLimit is the maximum number of PIDs what may be created within
+ // PidsLimit is the maximum number of PIDs that may be created within
// the container. 0, the default, indicates no limit.
PidsLimit int64 `json:"PidsLimit"`
// Ulimits is a set of ulimits that will be set within the container.
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index b858e1989..fd27e89de 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -205,7 +205,7 @@ var (
// Useful for potentially long running tasks.
ErrCanceled = errors.New("cancelled by user")
- // ErrConmonVersionFormat is used when the expected versio-format of conmon
+ // ErrConmonVersionFormat is used when the expected version format of conmon
// has changed.
ErrConmonVersionFormat = "conmon version changed format"
)
diff --git a/libpod/define/volume_inspect.go b/libpod/define/volume_inspect.go
index f731a8735..9279812da 100644
--- a/libpod/define/volume_inspect.go
+++ b/libpod/define/volume_inspect.go
@@ -45,7 +45,7 @@ type InspectVolumeData struct {
// GID is the GID that the volume was created with.
GID int `json:"GID,omitempty"`
// Anonymous indicates that the volume was created as an anonymous
- // volume for a specific container, and will be be removed when any
+ // volume for a specific container, and will be removed when any
// container using it is removed.
Anonymous bool `json:"Anonymous,omitempty"`
// MountCount is the number of times this volume has been mounted.
diff --git a/libpod/events/nullout.go b/libpod/events/nullout.go
index 3eca9e8db..587a1b98b 100644
--- a/libpod/events/nullout.go
+++ b/libpod/events/nullout.go
@@ -19,7 +19,7 @@ func (e EventToNull) Read(ctx context.Context, options ReadOptions) error {
}
// NewNullEventer returns a new null eventer. You should only do this for
-// the purposes on internal libpod testing.
+// the purposes of internal libpod testing.
func NewNullEventer() Eventer {
return EventToNull{}
}
diff --git a/libpod/kube.go b/libpod/kube.go
index 3cb0489b3..8c09a6bb5 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -353,6 +353,7 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
podInitCtrs := []v1.Container{}
podAnnotations := make(map[string]string)
dnsInfo := v1.PodDNSConfig{}
+ var hostname string
// Let's sort the containers in order of created time
// This will ensure that the init containers are defined in the correct order in the kube yaml
@@ -368,6 +369,14 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
podAnnotations[k] = TruncateKubeAnnotation(v)
}
isInit := ctr.IsInitCtr()
+ // Since hostname is only set at pod level, set the hostname to the hostname of the first container we encounter
+ if hostname == "" {
+ // Only set the hostname if it is not set to the truncated container ID, which we do by default if no
+ // hostname is specified for the container
+ if !strings.Contains(ctr.ID(), ctr.Hostname()) {
+ hostname = ctr.Hostname()
+ }
+ }
ctr, volumes, _, annotations, err := containerToV1Container(ctx, ctr)
if err != nil {
@@ -377,17 +386,21 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
podAnnotations[define.BindMountPrefix+k] = TruncateKubeAnnotation(v)
}
// Since port bindings for the pod are handled by the
- // infra container, wipe them here.
- ctr.Ports = nil
-
- // We add the original port declarations from the libpod infra container
- // to the first kubernetes container description because otherwise we loose
- // the original container/port bindings.
- // Add the port configuration to the first regular container or the first
- // init container if only init containers have been created in the pod.
- if first && len(ports) > 0 && (!isInit || len(containers) == 2) {
- ctr.Ports = ports
- first = false
+ // infra container, wipe them here only if we are sharing the net namespace
+ // If the network namespace is not being shared in the pod, then containers
+ // can have their own network configurations
+ if p.SharesNet() {
+ ctr.Ports = nil
+
+ // We add the original port declarations from the libpod infra container
+ // to the first kubernetes container description because otherwise we loose
+ // the original container/port bindings.
+ // Add the port configuration to the first regular container or the first
+ // init container if only init containers have been created in the pod.
+ if first && len(ports) > 0 && (!isInit || len(containers) == 2) {
+ ctr.Ports = ports
+ first = false
+ }
}
if isInit {
podInitCtrs = append(podInitCtrs, ctr)
@@ -430,10 +443,11 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
podContainers,
podVolumes,
&dnsInfo,
- hostNetwork), nil
+ hostNetwork,
+ hostname), nil
}
-func newPodObject(podName string, annotations map[string]string, initCtrs, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod {
+func newPodObject(podName string, annotations map[string]string, initCtrs, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool, hostname string) *v1.Pod {
tm := v12.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
@@ -454,6 +468,7 @@ func newPodObject(podName string, annotations map[string]string, initCtrs, conta
}
ps := v1.PodSpec{
Containers: containers,
+ Hostname: hostname,
HostNetwork: hostNetwork,
InitContainers: initCtrs,
Volumes: volumes,
@@ -479,6 +494,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
podDNS := v1.PodDNSConfig{}
kubeAnnotations := make(map[string]string)
ctrNames := make([]string, 0, len(ctrs))
+ var hostname string
for _, ctr := range ctrs {
ctrNames = append(ctrNames, removeUnderscores(ctr.Name()))
for k, v := range ctr.config.Spec.Annotations {
@@ -491,6 +507,14 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
}
isInit := ctr.IsInitCtr()
+ // Since hostname is only set at pod level, set the hostname to the hostname of the first container we encounter
+ if hostname == "" {
+ // Only set the hostname if it is not set to the truncated container ID, which we do by default if no
+ // hostname is specified for the container
+ if !strings.Contains(ctr.ID(), ctr.Hostname()) {
+ hostname = ctr.Hostname()
+ }
+ }
if !ctr.HostNetwork() {
hostNetwork = false
@@ -555,7 +579,8 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
kubeCtrs,
kubeVolumes,
&podDNS,
- hostNetwork), nil
+ hostNetwork,
+ hostname), nil
}
// containerToV1Container converts information we know about a libpod container
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 121e750f4..cb76de72c 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -133,7 +133,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
continue
}
foundPath = true
- logrus.Tracef("found runtime %q", runtime.path)
+ logrus.Tracef("found runtime %q", path)
runtime.path = path
break
}
@@ -1388,7 +1388,7 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
}
func startCommand(cmd *exec.Cmd, ctr *Container) error {
- // Make sure to unset the NOTIFY_SOCKET and reset if afterwards if needed.
+ // Make sure to unset the NOTIFY_SOCKET and reset it afterwards if needed.
switch ctr.config.SdNotifyMode {
case define.SdNotifyModeContainer, define.SdNotifyModeIgnore:
if ctr.notifySocket != "" {
@@ -1667,7 +1667,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter,
// multiplexing by Conmon).
headerLen := uint32(numR - 1)
// Practically speaking, we could make this buf[0] - 1,
- // but we need to validate it anyways...
+ // but we need to validate it anyway.
switch buf[0] {
case AttachPipeStdin:
headerBuf = makeHTTPAttachHeader(0, headerLen)
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index a751d75d2..d2fe9f2fb 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -31,7 +31,7 @@ func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption)
// newVolume creates a new empty volume with the given options.
// The createPluginVolume can be set to true to make it not create the volume in the volume plugin,
-// this is required for the UpdateVolumePlugins() function. If you are not sure set this to false.
+// this is required for the UpdateVolumePlugins() function. If you are not sure, set this to false.
func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOption) (_ *Volume, deferredErr error) {
volume := newVolume(r)
for _, option := range options {
@@ -216,7 +216,7 @@ func (r *Runtime) UpdateVolumePlugins(ctx context.Context) *define.VolumeReload
for _, vol := range libpodVolumes {
if vol.UsesVolumeDriver() {
if _, ok := allPluginVolumes[vol.Name()]; !ok {
- // The volume is no longer in the plugin, lets remove it from the libpod db.
+ // The volume is no longer in the plugin. Let's remove it from the libpod db.
if err := r.removeVolume(ctx, vol, false, nil, true); err != nil {
if errors.Is(err, define.ErrVolumeBeingUsed) {
// Volume is still used by at least one container. This is very bad,
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index 5c1047b74..31885ce54 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -50,6 +50,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
content [][]byte
)
+ defaultKubeNS := true
// Lookup for podman objects.
for _, nameOrID := range nameOrIDs {
// Let's assume it's a container, so get the container.
@@ -75,6 +76,17 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
return nil, err
}
} else {
+ // Get the pod config to see if the user has modified the default
+ // namespace sharing values as this might affect the pods when run
+ // in a k8s cluster
+ podConfig, err := pod.Config()
+ if err != nil {
+ return nil, err
+ }
+ if !(podConfig.UsePodIPC && podConfig.UsePodNet && podConfig.UsePodUTS) {
+ defaultKubeNS = false
+ }
+
pods = append(pods, pod)
continue
}
@@ -94,6 +106,15 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
return nil, fmt.Errorf("name or ID %q not found", nameOrID)
}
+ if !defaultKubeNS {
+ warning := `
+# NOTE: The namespace sharing for a pod has been modified by the user and is not the same as the
+# default settings for kubernetes. This can lead to unexpected behavior when running the generated
+# kube yaml in a kubernetes cluster.
+`
+ content = append(content, []byte(warning))
+ }
+
// Generate kube persistent volume claims from volumes.
if len(vols) >= 1 {
pvs, err := getKubePVCs(vols)
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 2ca774a03..845aa60ce 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -328,6 +328,109 @@ var _ = Describe("Podman generate kube", func() {
Expect(pod.Spec.HostAliases[1]).To(HaveField("IP", testIP))
})
+ It("podman generate kube with network sharing", func() {
+ // Expect error with default sharing options as Net namespace is shared
+ podName := "testPod"
+ podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession).Should(Exit(0))
+
+ ctrSession := podmanTest.Podman([]string{"create", "--name", "testCtr", "--pod", podName, "-p", "9000:8000", ALPINE, "top"})
+ ctrSession.WaitWithDefaultTimeout()
+ Expect(ctrSession).Should(Exit(125))
+
+ // Ports without Net sharing should work with ports being set for each container in the generated kube yaml
+ podName = "testNet"
+ podSession = podmanTest.Podman([]string{"pod", "create", "--name", podName, "--share", "ipc"})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession).Should(Exit(0))
+
+ ctr1Name := "ctr1"
+ ctr1Session := podmanTest.Podman([]string{"create", "--name", ctr1Name, "--pod", podName, "-p", "9000:8000", ALPINE, "top"})
+ ctr1Session.WaitWithDefaultTimeout()
+ Expect(ctr1Session).Should(Exit(0))
+
+ ctr2Name := "ctr2"
+ ctr2Session := podmanTest.Podman([]string{"create", "--name", ctr2Name, "--pod", podName, "-p", "6000:5000", ALPINE, "top"})
+ ctr2Session.WaitWithDefaultTimeout()
+ Expect(ctr2Session).Should(Exit(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", podName})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod := new(v1.Pod)
+ err := yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ Expect(pod.Spec.Containers).To(HaveLen(2))
+ Expect(pod.Spec.Containers[0].Ports[0].ContainerPort).To(Equal(int32(8000)))
+ Expect(pod.Spec.Containers[1].Ports[0].ContainerPort).To(Equal(int32(5000)))
+ Expect(pod.Spec.Containers[0].Ports[0].HostPort).To(Equal(int32(9000)))
+ Expect(pod.Spec.Containers[1].Ports[0].HostPort).To(Equal(int32(6000)))
+ })
+
+ It("podman generate kube with and without hostname", func() {
+ // Expect error with default sharing options as UTS namespace is shared
+ podName := "testPod"
+ podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession).Should(Exit(0))
+
+ ctrSession := podmanTest.Podman([]string{"create", "--name", "testCtr", "--pod", podName, "--hostname", "test-hostname", ALPINE, "top"})
+ ctrSession.WaitWithDefaultTimeout()
+ Expect(ctrSession).Should(Exit(125))
+
+ // Hostname without uts sharing should work, but generated kube yaml will have pod hostname
+ // set to the hostname of the first container
+ podName = "testHostname"
+ podSession = podmanTest.Podman([]string{"pod", "create", "--name", podName, "--share", "ipc"})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession).Should(Exit(0))
+
+ ctr1Name := "ctr1"
+ ctr1HostName := "ctr1-hostname"
+ ctr1Session := podmanTest.Podman([]string{"create", "--name", ctr1Name, "--pod", podName, "--hostname", ctr1HostName, ALPINE, "top"})
+ ctr1Session.WaitWithDefaultTimeout()
+ Expect(ctr1Session).Should(Exit(0))
+
+ ctr2Name := "ctr2"
+ ctr2Session := podmanTest.Podman([]string{"create", "--name", ctr2Name, "--pod", podName, ALPINE, "top"})
+ ctr2Session.WaitWithDefaultTimeout()
+ Expect(ctr2Session).Should(Exit(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", podName})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod := new(v1.Pod)
+ err := yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ Expect(pod.Spec.Containers).To(HaveLen(2))
+ Expect(pod.Spec.Hostname).To(Equal(ctr1HostName))
+
+ // No hostname
+
+ podName = "testNoHostname"
+ podSession = podmanTest.Podman([]string{"pod", "create", "--name", podName, "--share", "ipc"})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession).Should(Exit(0))
+
+ ctr3Name := "ctr3"
+ ctr3Session := podmanTest.Podman([]string{"create", "--name", ctr3Name, "--pod", podName, ALPINE, "top"})
+ ctr3Session.WaitWithDefaultTimeout()
+ Expect(ctr3Session).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", podName})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ Expect(pod.Spec.Containers).To(HaveLen(1))
+ Expect(pod.Spec.Hostname).To(BeEmpty())
+ })
+
It("podman generate service kube on pod", func() {
session := podmanTest.Podman([]string{"create", "--pod", "new:test-pod", "-p", "4000:4000/udp", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index 8864ba5fd..97d8ba701 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -247,7 +247,7 @@ var _ = Describe("Podman stop", func() {
It("podman stop should return silent success on stopping configured containers", func() {
// following container is not created on OCI runtime
- // so we return success and assume that is is stopped
+ // so we return success and assume that it is stopped
session2 := podmanTest.Podman([]string{"create", "--name", "stopctr", ALPINE, "/bin/sh"})
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index ceac48036..b9da2d89a 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -640,7 +640,7 @@ function assert() {
fi
# This is a multi-line message, which may in turn contain multi-line
- # output, so let's format it ourself, readably
+ # output, so let's format it ourself to make it more readable.
local actual_split
IFS=$'\n' read -rd '' -a actual_split <<<"$actual_string" || true
printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2
@@ -690,7 +690,7 @@ function is() {
fi
# This is a multi-line message, which may in turn contain multi-line
- # output, so let's format it ourself, readably
+ # output, so let's format it ourself to make it more readable.
local -a actual_split
readarray -t actual_split <<<"$actual"
printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2