diff options
author | baude <bbaude@redhat.com> | 2018-12-09 14:26:21 -0600 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2018-12-19 14:20:55 -0600 |
commit | 9b03cacc87c4d59fc301c21ef73ddc301ec753fb (patch) | |
tree | ec7318272db56a8a3ba11b5ac1b01d262b21742c | |
parent | eddfe6ba628d17435559ba32a8ef748c386105aa (diff) | |
download | podman-9b03cacc87c4d59fc301c21ef73ddc301ec753fb.tar.gz podman-9b03cacc87c4d59fc301c21ef73ddc301ec753fb.tar.bz2 podman-9b03cacc87c4d59fc301c21ef73ddc301ec753fb.zip |
Add Play
podman play kube adds the ability for the user to recreate pods and containers
from a Kubernetes YAML file in libpod.
Signed-off-by: baude <bbaude@redhat.com>
-rwxr-xr-x | API.md | 24 | ||||
-rw-r--r-- | cmd/podman/create.go | 63 | ||||
-rw-r--r-- | cmd/podman/generate_kube.go | 1 | ||||
-rw-r--r-- | cmd/podman/main.go | 1 | ||||
-rw-r--r-- | cmd/podman/play.go | 23 | ||||
-rw-r--r-- | cmd/podman/play_kube.go | 245 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 12 | ||||
-rw-r--r-- | completions/bash/podman | 37 | ||||
-rw-r--r-- | docs/podman-generate-kube.1.md | 2 | ||||
-rw-r--r-- | docs/podman-play-kube.1.md | 78 | ||||
-rw-r--r-- | docs/podman-play.1.md | 20 | ||||
-rw-r--r-- | libpod/kube.go | 34 |
12 files changed, 499 insertions, 41 deletions
@@ -31,6 +31,10 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func ExportImage(name: string, destination: string, compress: bool, tags: []string) string](#ExportImage) +[func GenerateKube() NotImplemented](#GenerateKube) + +[func GenerateKubeService() NotImplemented](#GenerateKubeService) + [func GetAttachSockets(name: string) Sockets](#GetAttachSockets) [func GetContainer(name: string) ListContainerData](#GetContainer) @@ -99,6 +103,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func RenameContainer() NotImplemented](#RenameContainer) +[func ReplayKube() NotImplemented](#ReplayKube) + [func ResizeContainerTty() NotImplemented](#ResizeContainerTty) [func RestartContainer(name: string, timeout: int) string](#RestartContainer) @@ -358,6 +364,18 @@ a booleon option to force compression. It also takes in a string array of tags tags of the same image to a tarball (each tag should be of the form <image>:<tag>). Upon completion, the ID of the image is returned. If the image cannot be found in local storage, an [ImageNotFound](#ImageNotFound) error will be returned. See also [ImportImage](ImportImage). +### <a name="GenerateKube"></a>func GenerateKube +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method GenerateKube() [NotImplemented](#NotImplemented)</div> +GenerateKube generates a Kubernetes v1 Pod description of a Podman container or pod +and its containers. The description is in YAML. See also [ReplayKube](ReplayKube). +### <a name="GenerateKubeService"></a>func GenerateKubeService +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method GenerateKubeService() [NotImplemented](#NotImplemented)</div> +GenerateKubeService generates a Kubernetes v1 Service description of a Podman container or pod +and its containers. The description is in YAML. See also [GenerateKube](GenerateKube). ### <a name="GetAttachSockets"></a>func GetAttachSockets <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> @@ -808,6 +826,12 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.RemovePod '{"name": "62f4 method RenameContainer() [NotImplemented](#NotImplemented)</div> This method has not be implemented yet. +### <a name="ReplayKube"></a>func ReplayKube +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method ReplayKube() [NotImplemented](#NotImplemented)</div> +ReplayKube recreates a pod and its containers based on a Kubernetes v1 Pod description (in YAML) +like that created by GenerateKube. See also [GenerateKube](GenerateKube). ### <a name="ResizeContainerTty"></a>func ResizeContainerTty <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 870eb28d6..2b31a6423 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -146,37 +146,10 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container return nil, nil, err } - runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig) - if err != nil { - return nil, nil, err - } - - options, err := createConfig.GetContainerCreateOptions(runtime) - if err != nil { - return nil, nil, err - } - - became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, runtime) + ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx) if err != nil { return nil, nil, err } - if became { - os.Exit(ret) - } - - ctr, err := runtime.NewContainer(ctx, runtimeSpec, options...) - if err != nil { - return nil, nil, err - } - - createConfigJSON, err := json.Marshal(createConfig) - if err != nil { - return nil, nil, err - } - if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil { - return nil, nil, err - } - if cidFile != nil { _, err = cidFile.WriteString(ctr.ID()) if err != nil { @@ -913,3 +886,37 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l } return rootless.BecomeRootInUserNS() } + +func createContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context) (*libpod.Container, error) { + runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig) + if err != nil { + return nil, err + } + + options, err := createConfig.GetContainerCreateOptions(r) + if err != nil { + return nil, err + } + + became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, r) + if err != nil { + return nil, err + } + if became { + os.Exit(ret) + } + + ctr, err := r.NewContainer(ctx, runtimeSpec, options...) + if err != nil { + return nil, err + } + + createConfigJSON, err := json.Marshal(createConfig) + if err != nil { + return nil, err + } + if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil { + return nil, err + } + return ctr, nil +} diff --git a/cmd/podman/generate_kube.go b/cmd/podman/generate_kube.go index 8f2f0de32..f63bd431b 100644 --- a/cmd/podman/generate_kube.go +++ b/cmd/podman/generate_kube.go @@ -33,7 +33,6 @@ var ( } ) -// generateKubeYAMLCmdgenerates or replays kube func generateKubeYAMLCmd(c *cli.Context) error { var ( podYAML *v1.Pod diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 2db6c5dec..f47a75761 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -90,6 +90,7 @@ func main() { portCommand, pullCommand, pushCommand, + playCommand, restartCommand, rmCommand, rmiCommand, diff --git a/cmd/podman/play.go b/cmd/podman/play.go new file mode 100644 index 000000000..adbab3480 --- /dev/null +++ b/cmd/podman/play.go @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/urfave/cli" +) + +var ( + playSubCommands = []cli.Command{ + playKubeCommand, + } + + playDescription = "Play a pod and its containers from a structured file." + playCommand = cli.Command{ + Name: "play", + Usage: "play a container or pod", + Description: playDescription, + ArgsUsage: "", + Subcommands: playSubCommands, + UseShortOptionHandling: true, + OnUsageError: usageErrorHandler, + Hidden: true, + } +) diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go new file mode 100644 index 000000000..f165c5f0f --- /dev/null +++ b/cmd/podman/play_kube.go @@ -0,0 +1,245 @@ +package main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "strings" + + "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/cmd/podman/shared" + "github.com/containers/libpod/libpod" + image2 "github.com/containers/libpod/libpod/image" + ns "github.com/containers/libpod/pkg/namespaces" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/spec" + "github.com/containers/storage" + "github.com/cri-o/ocicni/pkg/ocicni" + "github.com/ghodss/yaml" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" + "k8s.io/api/core/v1" +) + +var ( + playKubeFlags = []cli.Flag{ + cli.StringFlag{ + Name: "authfile", + Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ", + }, + cli.StringFlag{ + Name: "cert-dir", + Usage: "`pathname` of a directory containing TLS certificates and keys", + }, + cli.StringFlag{ + Name: "creds", + Usage: "`credentials` (USERNAME:PASSWORD) to use for authenticating to a registry", + }, + cli.BoolFlag{ + Name: "quiet, q", + Usage: "Suppress output information when pulling images", + }, + cli.StringFlag{ + Name: "signature-policy", + Usage: "`pathname` of signature policy file (not usually used)", + }, + cli.BoolTFlag{ + Name: "tls-verify", + Usage: "require HTTPS and verify certificates when contacting registries (default: true)", + }, + } + playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML" + playKubeCommand = cli.Command{ + Name: "kube", + Usage: "Play a pod based on Kubernetes YAML", + Description: playKubeDescription, + Action: playKubeYAMLCmd, + Flags: sortFlags(playKubeFlags), + ArgsUsage: "kubernetes YAML file", + UseShortOptionHandling: true, + OnUsageError: usageErrorHandler, + } +) + +func playKubeYAMLCmd(c *cli.Context) error { + var ( + podOptions []libpod.PodCreateOption + podYAML v1.Pod + registryCreds *types.DockerAuthConfig + containers []*libpod.Container + writer io.Writer + ) + + ctx := getContext() + if rootless.IsRootless() { + return errors.Wrapf(libpod.ErrNotImplemented, "rootless users") + } + args := c.Args() + if len(args) > 1 { + return errors.New("you can only play one kubernetes file at a time") + } + if len(args) < 1 { + return errors.New("you must supply at least one file") + } + + runtime, err := libpodruntime.GetRuntime(c) + if err != nil { + return errors.Wrapf(err, "could not get runtime") + } + defer runtime.Shutdown(false) + + content, err := ioutil.ReadFile(args[0]) + if err != nil { + return err + } + + if err := yaml.Unmarshal(content, &podYAML); err != nil { + return errors.Wrapf(err, "unable to read %s as YAML", args[0]) + } + + podOptions = append(podOptions, libpod.WithInfraContainer()) + podOptions = append(podOptions, libpod.WithPodName(podYAML.ObjectMeta.Name)) + // TODO for now we just used the default kernel namespaces; we need to add/subtract this from yaml + + nsOptions, err := shared.GetNamespaceOptions(strings.Split(DefaultKernelNamespaces, ",")) + if err != nil { + return err + } + podOptions = append(podOptions, nsOptions...) + podPorts := getPodPorts(podYAML.Spec.Containers) + podOptions = append(podOptions, libpod.WithInfraContainerPorts(podPorts)) + + // Create the Pod + pod, err := runtime.NewPod(ctx, podOptions...) + if err != nil { + return err + } + // Print the Pod's ID + fmt.Println(pod.ID()) + + podInfraID, err := pod.InfraContainerID() + if err != nil { + return err + } + + namespaces := map[string]string{ + // Disabled during code review per mheon + //"pid": fmt.Sprintf("container:%s", podInfraID), + "net": fmt.Sprintf("container:%s", podInfraID), + "user": fmt.Sprintf("container:%s", podInfraID), + "ipc": fmt.Sprintf("container:%s", podInfraID), + "uts": fmt.Sprintf("container:%s", podInfraID), + } + if !c.Bool("quiet") { + writer = os.Stderr + } + + dockerRegistryOptions := image2.DockerRegistryOptions{ + DockerRegistryCreds: registryCreds, + DockerCertPath: c.String("cert-dir"), + } + if c.IsSet("tls-verify") { + dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) + } + + for _, container := range podYAML.Spec.Containers { + newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.String("signature-policy"), c.String("authfile"), writer, &dockerRegistryOptions, image2.SigningOptions{}, false) + if err != nil { + return err + } + createConfig := kubeContainerToCreateConfig(container, runtime, newImage, namespaces) + if err != nil { + return err + } + ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx) + if err != nil { + return err + } + containers = append(containers, ctr) + } + + // start the containers + for _, ctr := range containers { + if err := ctr.Start(ctx); err != nil { + // Making this a hard failure here to avoid a mess + // the other containers are in created status + return err + } + fmt.Println(ctr.ID()) + } + + return nil +} + +// getPodPorts converts a slice of kube container descriptions to an +// array of ocicni portmapping descriptions usable in libpod +func getPodPorts(containers []v1.Container) []ocicni.PortMapping { + var infraPorts []ocicni.PortMapping + for _, container := range containers { + for _, p := range container.Ports { + portBinding := ocicni.PortMapping{ + HostPort: p.HostPort, + ContainerPort: p.ContainerPort, + Protocol: strings.ToLower(string(p.Protocol)), + } + if p.HostIP != "" { + logrus.Debug("HostIP on port bindings is not supported") + } + infraPorts = append(infraPorts, portBinding) + } + } + return infraPorts +} + +// kubeContainerToCreateConfig takes a v1.Container and returns a createconfig describing a container +func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Runtime, newImage *image2.Image, namespaces map[string]string) *createconfig.CreateConfig { + var ( + containerConfig createconfig.CreateConfig + envs map[string]string + ) + + containerConfig.Runtime = runtime + containerConfig.Image = containerYAML.Image + containerConfig.ImageID = newImage.ID() + containerConfig.Name = containerYAML.Name + containerConfig.Tty = containerYAML.TTY + containerConfig.WorkDir = containerYAML.WorkingDir + if containerYAML.SecurityContext.ReadOnlyRootFilesystem != nil { + containerConfig.ReadOnlyRootfs = *containerYAML.SecurityContext.ReadOnlyRootFilesystem + } + if containerYAML.SecurityContext.Privileged != nil { + containerConfig.Privileged = *containerYAML.SecurityContext.Privileged + } + + if containerYAML.SecurityContext.AllowPrivilegeEscalation != nil { + containerConfig.NoNewPrivs = !*containerYAML.SecurityContext.AllowPrivilegeEscalation + } + + containerConfig.Command = containerYAML.Command + containerConfig.StopSignal = 15 + + // If the user does not pass in ID mappings, just set to basics + if containerConfig.IDMappings == nil { + containerConfig.IDMappings = &storage.IDMappingOptions{} + } + + containerConfig.NetMode = ns.NetworkMode(namespaces["net"]) + containerConfig.IpcMode = ns.IpcMode(namespaces["ipc"]) + containerConfig.UtsMode = ns.UTSMode(namespaces["uts"]) + // disabled in code review per mheon + //containerConfig.PidMode = ns.PidMode(namespaces["pid"]) + containerConfig.UsernsMode = ns.UsernsMode(namespaces["user"]) + + if len(containerYAML.Env) > 0 { + envs = make(map[string]string) + } + // Environment Variables + for _, e := range containerYAML.Env { + envs[e.Name] = e.Value + } + containerConfig.Env = envs + return &containerConfig +} diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 376bbc950..c1b7c703a 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -1016,6 +1016,18 @@ method UnmountContainer(name: string, force: bool) -> () # This function is not implemented yet. method ListContainerPorts(name: string) -> (notimplemented: NotImplemented) +# GenerateKube generates a Kubernetes v1 Pod description of a Podman container or pod +# and its containers. The description is in YAML. See also [ReplayKube](ReplayKube). +method GenerateKube() -> (notimplemented: NotImplemented) + +# GenerateKubeService generates a Kubernetes v1 Service description of a Podman container or pod +# and its containers. The description is in YAML. See also [GenerateKube](GenerateKube). +method GenerateKubeService() -> (notimplemented: NotImplemented) + +# ReplayKube recreates a pod and its containers based on a Kubernetes v1 Pod description (in YAML) +# like that created by GenerateKube. See also [GenerateKube](GenerateKube). +method ReplayKube() -> (notimplemented: NotImplemented) + # ImageNotFound means the image could not be found by the provided name or ID in local storage. error ImageNotFound (name: string) diff --git a/completions/bash/podman b/completions/bash/podman index 4702ae0e0..2ce70a1f5 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -895,6 +895,26 @@ _podman_generate() { ;; esac } + +_podman_play() { + local boolean_options=" + --help + -h + " + subcommands=" + kube + " + __podman_subcommands "$subcommands $aliases" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} _podman_container() { local boolean_options=" --help @@ -2247,6 +2267,22 @@ _podman_generate_kube() { --service " +_podman_play_kube() { + local options_with_args=" + --authfile + --cert-dir + --creds + --signature-policy + " + + local boolean_options=" + -h + --help + --quiet + -q + --tls-verify + " + _podman_container_runlabel() { local options_with_args=" --authfile @@ -2750,6 +2786,7 @@ _podman_podman() { ps pull push + play restart rm rmi diff --git a/docs/podman-generate-kube.1.md b/docs/podman-generate-kube.1.md index 396f69615..5236f23fe 100644 --- a/docs/podman-generate-kube.1.md +++ b/docs/podman-generate-kube.1.md @@ -145,7 +145,7 @@ status: ``` ## SEE ALSO -podman(1), podman-container, podman-pod +podman(1), podman-container, podman-pod, podman-play # HISTORY Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) diff --git a/docs/podman-play-kube.1.md b/docs/podman-play-kube.1.md new file mode 100644 index 000000000..3fd9746a5 --- /dev/null +++ b/docs/podman-play-kube.1.md @@ -0,0 +1,78 @@ +% podman-play-kube Podman Man Pages +% Brent Baude +% December 2018 +# NAME +podman-play-kube - Create pods and containers based on Kubernetes YAML + +# SYNOPSIS +**podman play kube ** +[**-h**|**--help**] +[**--authfile**] +[**--cert-dir**] +[**--creds**] +[***-q** | **--quiet**] +[**--signature-policy**] +[**--tls-verify**] +kubernetes_input.yml + +# DESCRIPTION +**podman play kube** will read in a structured file of Kubernetes YAML. It will then recreate +the pod and containers described in the YAML. The containers within the pod are then started and +the ID of the new Pod is output. + +Ideally the input file would be one created by Podman. This would guarantee a smooth import and expected results. + +# OPTIONS: + +**--authfile** + +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`. + +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` + +**--cert-dir** *path* + +Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. +Default certificates directory is _/etc/containers/certs.d_. + +**--creds** + +The [username[:password]] to use to authenticate with the registry if required. +If one or both values are not supplied, a command line prompt will appear and the +value can be entered. The password is entered without echo. + +**--quiet, -q** + +Suppress output information when pulling images + +**--signature-policy="PATHNAME"** + +Pathname of a signature policy file to use. It is not recommended that this +option be used, as the default behavior of using the system-wide default policy +(frequently */etc/containers/policy.json*) is most often preferred. + +**--tls-verify** + +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. + +**--help**, **-h** + +Print usage statement + +## Examples ## + +Recreate the pod and containers as described in a file called `demo.yml` +``` +$ podman play kube demo.yml +52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6 +``` + +## SEE ALSO +podman(1), podman-container(1), podman-pod(1), podman-generate(1), podman-play(1) + +# HISTORY +Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) diff --git a/docs/podman-play.1.md b/docs/podman-play.1.md new file mode 100644 index 000000000..c703c1455 --- /dev/null +++ b/docs/podman-play.1.md @@ -0,0 +1,20 @@ +% podman-play(1) + +## NAME +podman\-container - play pods and containers based on a structured input file + +## SYNOPSIS +**podman play** *subcommand* + +## DESCRIPTION +The play command will recreate pods and containers based on the input from a structured (like YAML) +file input. Containers will be automatically started. + +## COMMANDS + +| Command | Man Page | Description | +| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- | +| kube | [podman-play-kube(1)](podman-play-kube.1.md) | Recreate pods and containers based on Kubernetes YAML. + +## SEE ALSO +podman, podman-pod(1), podman-container(1), podman-generate(1), podman-play(1), podman-play-kube(1) diff --git a/libpod/kube.go b/libpod/kube.go index c164ca0c5..f34805e39 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -30,7 +30,10 @@ func (c *Container) GenerateForKube() (*v1.Pod, error) { // one v1.Pod description func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { // Generate the v1.Pod yaml description - var servicePorts []v1.ServicePort + var ( + servicePorts []v1.ServicePort + ports []v1.ContainerPort + ) allContainers, err := p.allContainers() if err != nil { @@ -51,13 +54,13 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { return nil, servicePorts, err } - ports, err := ocicniPortMappingToContainerPort(infraContainer.config.PortMappings) + ports, err = ocicniPortMappingToContainerPort(infraContainer.config.PortMappings) if err != nil { return nil, servicePorts, err } servicePorts = containerPortsToServicePorts(ports) } - pod, err := p.podWithContainers(allContainers) + pod, err := p.podWithContainers(allContainers, ports) return pod, servicePorts, err } @@ -124,18 +127,27 @@ func containersToServicePorts(containers []v1.Container) []v1.ServicePort { return sps } -func (p *Pod) podWithContainers(containers []*Container) (*v1.Pod, error) { - var podContainers []v1.Container +func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort) (*v1.Pod, error) { + var ( + podContainers []v1.Container + ) + first := true for _, ctr := range containers { - result, err := containerToV1Container(ctr) - if err != nil { - return nil, err - } if !ctr.IsInfra() { + result, err := containerToV1Container(ctr) + if err != nil { + return nil, err + } + // 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. + if first && len(ports) > 0 { + result.Ports = ports + first = false + } podContainers = append(podContainers, result) } } - return addContainersToPodObject(podContainers, p.Name()), nil } @@ -150,7 +162,7 @@ func addContainersToPodObject(containers []v1.Container, podName string) *v1.Pod labels["app"] = removeUnderscores(podName) om := v12.ObjectMeta{ // The name of the pod is container_name-libpod - Name: fmt.Sprintf("%s-libpod", removeUnderscores(podName)), + Name: fmt.Sprintf("%s", removeUnderscores(podName)), Labels: labels, // CreationTimestamp seems to be required, so adding it; in doing so, the timestamp // will reflect time this is run (not container create time) because the conversion |