diff --git a/cmd/podman/kube/play.go b/cmd/podman/kube/play.go index 1196ee4802..8ca7354dc6 100644 --- a/cmd/podman/kube/play.go +++ b/cmd/podman/kube/play.go @@ -158,6 +158,9 @@ func playFlags(cmd *cobra.Command) { flags.StringSliceVar(&playOptions.PublishPorts, publishPortsFlagName, []string{}, "Publish a container's port, or a range of ports, to the host") _ = cmd.RegisterFlagCompletionFunc(publishPortsFlagName, completion.AutocompleteNone) + publishAllPortsFlagName := "publish-all" + flags.BoolVar(&playOptions.PublishAllPorts, publishAllPortsFlagName, false, "Whether to publish all ports defined in the K8S YAML file (containerPort, hostPort), if false only hostPort will be published") + waitFlagName := "wait" flags.BoolVarP(&playOptions.Wait, waitFlagName, "w", false, "Clean up all objects created when a SIGTERM is received or pods exit") diff --git a/docs/source/markdown/podman-kube-play.1.md.in b/docs/source/markdown/podman-kube-play.1.md.in index 1b2cd5ec60..8576e8e351 100644 --- a/docs/source/markdown/podman-kube-play.1.md.in +++ b/docs/source/markdown/podman-kube-play.1.md.in @@ -221,6 +221,16 @@ Define or override a port definition in the YAML file. The lists of ports in the YAML file and the command line are merged. Matching is done by using the **containerPort** field. If **containerPort** exists in both the YAML file and the option, the latter takes precedence. +#### **--publish-all** + +Setting this option to `true` will expose all ports to the host, +even if only specified via **containerPort** in the K8 YAML. +In terms of which port will be exposed, **--publish** has higher priority than **hostPort**, has higher priority than +**containerPort**. + +If set to `false` (which is the default), only ports defined via **hostPort** +or **--publish** are published on the host. + #### **--quiet**, **-q** Suppress output information when pulling images diff --git a/pkg/bindings/kube/types.go b/pkg/bindings/kube/types.go index 79cddfbf8c..7dcc77dcea 100644 --- a/pkg/bindings/kube/types.go +++ b/pkg/bindings/kube/types.go @@ -53,6 +53,9 @@ type PlayOptions struct { Force *bool // PublishPorts - configure how to expose ports configured inside the K8S YAML file PublishPorts []string + // PublishAllPorts - whether to publish all ports defined in the K8S YAML file + // (containerPort, hostPort) otherwise only hostPort will be published + PublishAllPorts *bool // Wait - indicates whether to return after having created the pods Wait *bool ServiceContainer *bool diff --git a/pkg/bindings/kube/types_play_options.go b/pkg/bindings/kube/types_play_options.go index 37bfbc2835..49e6499ac8 100644 --- a/pkg/bindings/kube/types_play_options.go +++ b/pkg/bindings/kube/types_play_options.go @@ -333,6 +333,21 @@ func (o *PlayOptions) GetPublishPorts() []string { return o.PublishPorts } +// WithPublishAllPorts set field PublishAllPorts to given value +func (o *PlayOptions) WithPublishAllPorts(value bool) *PlayOptions { + o.PublishAllPorts = &value + return o +} + +// GetPublishAllPorts returns value of field PublishAllPorts +func (o *PlayOptions) GetPublishAllPorts() bool { + if o.PublishAllPorts == nil { + var z bool + return z + } + return *o.PublishAllPorts +} + // WithWait set field Wait to given value func (o *PlayOptions) WithWait(value bool) *PlayOptions { o.Wait = &value diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go index 3a247d4c2c..579fe8b7d6 100644 --- a/pkg/domain/entities/play.go +++ b/pkg/domain/entities/play.go @@ -70,6 +70,9 @@ type PlayKubeOptions struct { Force bool // PublishPorts - configure how to expose ports configured inside the K8S YAML file PublishPorts []string + // PublishAllPorts - whether to publish all ports defined in the K8S YAML file + // (containerPort, hostPort) otherwise only hostPort will be published + PublishAllPorts bool // Wait - indicates whether to return after having created the pods Wait bool } diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index f4ee8eb650..89223f356b 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -473,7 +473,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY Net: &entities.NetOptions{NoHosts: options.NoHosts}, ExitPolicy: string(config.PodExitPolicyStop), } - podOpt, err = kube.ToPodOpt(ctx, podName, podOpt, podYAML) + podOpt, err = kube.ToPodOpt(ctx, podName, podOpt, options.PublishAllPorts, podYAML) if err != nil { return nil, nil, err } diff --git a/pkg/domain/infra/tunnel/kube.go b/pkg/domain/infra/tunnel/kube.go index 802879e24b..e1e49d58df 100644 --- a/pkg/domain/infra/tunnel/kube.go +++ b/pkg/domain/infra/tunnel/kube.go @@ -73,6 +73,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, opts en options.WithStart(start == types.OptionalBoolTrue) } options.WithPublishPorts(opts.PublishPorts) + options.WithPublishAllPorts(opts.PublishAllPorts) options.WithNoTrunc(opts.UseLongAnnotations) return play.KubeWithBody(ic.ClientCtx, body, options) } diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 681c434ee6..bff697979e 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -43,7 +43,7 @@ import ( "sigs.k8s.io/yaml" ) -func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions, podYAML *v1.PodTemplateSpec) (entities.PodCreateOptions, error) { +func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions, publishAllPorts bool, podYAML *v1.PodTemplateSpec) (entities.PodCreateOptions, error) { p.Net = &entities.NetOptions{NoHosts: p.Net.NoHosts} p.Name = podName @@ -82,7 +82,7 @@ func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions, } p.Net.AddHosts = hosts } - podPorts := getPodPorts(podYAML.Spec.Containers) + podPorts := getPodPorts(podYAML.Spec.Containers, publishAllPorts) p.Net.PublishPorts = podPorts if dnsConfig := podYAML.Spec.DNSConfig; dnsConfig != nil { @@ -1143,14 +1143,14 @@ func getContainerResources(container v1.Container) (v1.ResourceRequirements, err // getPodPorts converts a slice of kube container descriptions to an // array of portmapping -func getPodPorts(containers []v1.Container) []types.PortMapping { +func getPodPorts(containers []v1.Container, publishAll bool) []types.PortMapping { var infraPorts []types.PortMapping for _, container := range containers { for _, p := range container.Ports { if p.HostPort != 0 && p.ContainerPort == 0 { p.ContainerPort = p.HostPort } - if p.HostPort == 0 && p.ContainerPort != 0 { + if p.HostPort == 0 && p.ContainerPort != 0 && publishAll { p.HostPort = p.ContainerPort } if p.Protocol == "" { diff --git a/pkg/specgen/generate/kube/kube_test.go b/pkg/specgen/generate/kube/kube_test.go index 005b4b1893..9e400c87b2 100644 --- a/pkg/specgen/generate/kube/kube_test.go +++ b/pkg/specgen/generate/kube/kube_test.go @@ -44,6 +44,39 @@ func TestParseMountPathRO(t *testing.T) { assert.NotContains(t, options, "ro") } +func TestGetPodPorts(t *testing.T) { + c1 := v1.Container{ + Name: "container1", + Ports: []v1.ContainerPort{{ + ContainerPort: 5000, + }, { + ContainerPort: 5001, + HostPort: 5002, + }}, + } + c2 := v1.Container{ + Name: "container2", + Ports: []v1.ContainerPort{{ + HostPort: 5004, + }}, + } + r := getPodPorts([]v1.Container{c1, c2}, false) + assert.Equal(t, 2, len(r)) + assert.Equal(t, uint16(5001), r[0].ContainerPort) + assert.Equal(t, uint16(5002), r[0].HostPort) + assert.Equal(t, uint16(5004), r[1].ContainerPort) + assert.Equal(t, uint16(5004), r[1].HostPort) + + r = getPodPorts([]v1.Container{c1, c2}, true) + assert.Equal(t, 3, len(r)) + assert.Equal(t, uint16(5000), r[0].ContainerPort) + assert.Equal(t, uint16(5000), r[0].HostPort) + assert.Equal(t, uint16(5001), r[1].ContainerPort) + assert.Equal(t, uint16(5002), r[1].HostPort) + assert.Equal(t, uint16(5004), r[2].ContainerPort) + assert.Equal(t, uint16(5004), r[2].HostPort) +} + func TestGetPortNumber(t *testing.T) { portSpec := intstr.IntOrString{Type: intstr.Int, IntVal: 3000, StrVal: "myport"} cp1 := v1.ContainerPort{Name: "myport", ContainerPort: 4000} diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index d0852058de..607ab5284a 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -5425,7 +5425,7 @@ spec: err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) Expect(err).ToNot(HaveOccurred()) - kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) + kube := podmanTest.Podman([]string{"kube", "play", "--publish-all=true", kubeYaml}) kube.WaitWithDefaultTimeout() Expect(kube).Should(Exit(125)) // The error message is printed only on local call @@ -5434,6 +5434,17 @@ spec: } }) + It("podman play kube should not publish containerPort by default", func() { + err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) + Expect(err).ToNot(HaveOccurred()) + + kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + testHTTPServer("80", true, "connection refused") + }) + It("with privileged containers ports and publish in command line - curl should succeed", func() { err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) Expect(err).ToNot(HaveOccurred()) diff --git a/test/system/700-play.bats b/test/system/700-play.bats index fd72508325..40a701d8ee 100644 --- a/test/system/700-play.bats +++ b/test/system/700-play.bats @@ -532,7 +532,7 @@ EOF image: $IMAGE ports: - name: hostp - containerPort: $HOST_PORT + hostPort: $HOST_PORT EOF run_podman kube play $PODMAN_TMPDIR/test.yaml