From c995b54607a53d692ea2491771233895ff2c75a7 Mon Sep 17 00:00:00 2001
From: Valentin Rothberg <rothberg@redhat.com>
Date: Wed, 3 Feb 2021 16:36:46 +0100
Subject: [PATCH] generate kube: handle entrypoint

The spec of a Kube Container has a `Command` and `Args`.  While both are
slices, the `Command` is the counterpart of the entrypoint of a libpod
container.  Kube is also happily accepting the arguments to as following
items in the slice but it's cleaner to move those to `Args`.

Fixes: #9211
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
---
 libpod/kube.go                 | 21 ++++++------
 test/e2e/generate_kube_test.go | 60 ++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/libpod/kube.go b/libpod/kube.go
index bf314b9a3a..f9ead027d2 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -353,22 +353,21 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNS
 		return kubeContainer, kubeVolumes, nil, err
 	}
 
-	containerCommands := c.Command()
-	kubeContainer.Name = removeUnderscores(c.Name())
+	// Handle command and arguments.
+	if ep := c.Entrypoint(); len(ep) > 0 {
+		// If we have an entrypoint, set the container's command as
+		// arguments.
+		kubeContainer.Command = ep
+		kubeContainer.Args = c.Command()
+	} else {
+		kubeContainer.Command = c.Command()
+	}
 
+	kubeContainer.Name = removeUnderscores(c.Name())
 	_, image := c.Image()
 	kubeContainer.Image = image
 	kubeContainer.Stdin = c.Stdin()
 
-	// prepend the entrypoint of the container to command
-	if ep := c.Entrypoint(); len(c.Entrypoint()) > 0 {
-		ep = append(ep, containerCommands...)
-		containerCommands = ep
-	}
-	kubeContainer.Command = containerCommands
-	// TODO need to figure out how we handle command vs entry point.  Kube appears to prefer entrypoint.
-	// right now we just take the container's command
-	//container.Args = args
 	kubeContainer.WorkingDir = c.WorkingDir()
 	kubeContainer.Ports = ports
 	// This should not be applicable
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 83b9cfb14c..632e30d1fe 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -1,6 +1,7 @@
 package integration
 
 import (
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -639,4 +640,63 @@ var _ = Describe("Podman generate kube", func() {
 		Expect(pod.Spec.DNSConfig.Options[0].Name).To(Equal("color"))
 		Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue"))
 	})
+
+	It("podman generate kube - set entrypoint as command", func() {
+		session := podmanTest.Podman([]string{"create", "--pod", "new:testpod", "--entrypoint", "/bin/sleep", ALPINE, "10s"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+
+		kube := podmanTest.Podman([]string{"generate", "kube", "testpod"})
+		kube.WaitWithDefaultTimeout()
+		Expect(kube.ExitCode()).To(Equal(0))
+
+		// Now make sure that the container's command is set to the
+		// entrypoint and it's arguments 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/sleep"}))
+		Expect(containers[0].Args).To(Equal([]string{"10s"}))
+	})
+
+	It("podman generate kube - use entrypoint from image", func() {
+		// Build an image with an entrypoint.
+		containerfile := `FROM quay.io/libpod/alpine:latest
+ENTRYPOINT /bin/sleep`
+
+		targetPath, err := CreateTempDirInTempDir()
+		Expect(err).To(BeNil())
+		containerfilePath := filepath.Join(targetPath, "Containerfile")
+		err = ioutil.WriteFile(containerfilePath, []byte(containerfile), 0644)
+		Expect(err).To(BeNil())
+
+		image := "generatekube:test"
+		session := podmanTest.Podman([]string{"build", "-f", containerfilePath, "-t", image})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+
+		session = podmanTest.Podman([]string{"create", "--pod", "new:testpod", image, "10s"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+
+		kube := podmanTest.Podman([]string{"generate", "kube", "testpod"})
+		kube.WaitWithDefaultTimeout()
+		Expect(kube.ExitCode()).To(Equal(0))
+
+		// Now make sure that the container's command is set to the
+		// entrypoint and it's arguments 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"}))
+	})
 })