mirror of
https://github.com/containers/podman.git
synced 2025-10-16 10:43:52 +08:00
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>
This commit is contained in:
24
API.md
24
API.md
@ -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 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 GetAttachSockets(name: string) Sockets](#GetAttachSockets)
|
||||||
|
|
||||||
[func GetContainer(name: string) ListContainerData](#GetContainer)
|
[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 RenameContainer() NotImplemented](#RenameContainer)
|
||||||
|
|
||||||
|
[func ReplayKube() NotImplemented](#ReplayKube)
|
||||||
|
|
||||||
[func ResizeContainerTty() NotImplemented](#ResizeContainerTty)
|
[func ResizeContainerTty() NotImplemented](#ResizeContainerTty)
|
||||||
|
|
||||||
[func RestartContainer(name: string, timeout: int) string](#RestartContainer)
|
[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
|
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)
|
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).
|
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
|
### <a name="GetAttachSockets"></a>func GetAttachSockets
|
||||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
<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>
|
method RenameContainer() [NotImplemented](#NotImplemented)</div>
|
||||||
This method has not be implemented yet.
|
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
|
### <a name="ResizeContainerTty"></a>func ResizeContainerTty
|
||||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||||
|
|
||||||
|
@ -146,37 +146,10 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
|
ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
options, err := createConfig.GetContainerCreateOptions(runtime)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, runtime)
|
|
||||||
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 {
|
if cidFile != nil {
|
||||||
_, err = cidFile.WriteString(ctr.ID())
|
_, err = cidFile.WriteString(ctr.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -913,3 +886,37 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l
|
|||||||
}
|
}
|
||||||
return rootless.BecomeRootInUserNS()
|
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
|
||||||
|
}
|
||||||
|
@ -33,7 +33,6 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// generateKubeYAMLCmdgenerates or replays kube
|
|
||||||
func generateKubeYAMLCmd(c *cli.Context) error {
|
func generateKubeYAMLCmd(c *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
podYAML *v1.Pod
|
podYAML *v1.Pod
|
||||||
|
@ -90,6 +90,7 @@ func main() {
|
|||||||
portCommand,
|
portCommand,
|
||||||
pullCommand,
|
pullCommand,
|
||||||
pushCommand,
|
pushCommand,
|
||||||
|
playCommand,
|
||||||
restartCommand,
|
restartCommand,
|
||||||
rmCommand,
|
rmCommand,
|
||||||
rmiCommand,
|
rmiCommand,
|
||||||
|
23
cmd/podman/play.go
Normal file
23
cmd/podman/play.go
Normal file
@ -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,
|
||||||
|
}
|
||||||
|
)
|
245
cmd/podman/play_kube.go
Normal file
245
cmd/podman/play_kube.go
Normal file
@ -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
|
||||||
|
}
|
@ -1016,6 +1016,18 @@ method UnmountContainer(name: string, force: bool) -> ()
|
|||||||
# This function is not implemented yet.
|
# This function is not implemented yet.
|
||||||
method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
|
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.
|
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
|
||||||
error ImageNotFound (name: string)
|
error ImageNotFound (name: string)
|
||||||
|
|
||||||
|
@ -895,6 +895,26 @@ _podman_generate() {
|
|||||||
;;
|
;;
|
||||||
esac
|
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() {
|
_podman_container() {
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--help
|
--help
|
||||||
@ -2247,6 +2267,22 @@ _podman_generate_kube() {
|
|||||||
--service
|
--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() {
|
_podman_container_runlabel() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
--authfile
|
--authfile
|
||||||
@ -2750,6 +2786,7 @@ _podman_podman() {
|
|||||||
ps
|
ps
|
||||||
pull
|
pull
|
||||||
push
|
push
|
||||||
|
play
|
||||||
restart
|
restart
|
||||||
rm
|
rm
|
||||||
rmi
|
rmi
|
||||||
|
@ -145,7 +145,7 @@ status:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-container, podman-pod
|
podman(1), podman-container, podman-pod, podman-play
|
||||||
|
|
||||||
# HISTORY
|
# HISTORY
|
||||||
Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
|
Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
|
||||||
|
78
docs/podman-play-kube.1.md
Normal file
78
docs/podman-play-kube.1.md
Normal file
@ -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)
|
20
docs/podman-play.1.md
Normal file
20
docs/podman-play.1.md
Normal file
@ -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)
|
@ -30,7 +30,10 @@ func (c *Container) GenerateForKube() (*v1.Pod, error) {
|
|||||||
// one v1.Pod description
|
// one v1.Pod description
|
||||||
func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
|
func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
|
||||||
// Generate the v1.Pod yaml description
|
// Generate the v1.Pod yaml description
|
||||||
var servicePorts []v1.ServicePort
|
var (
|
||||||
|
servicePorts []v1.ServicePort
|
||||||
|
ports []v1.ContainerPort
|
||||||
|
)
|
||||||
|
|
||||||
allContainers, err := p.allContainers()
|
allContainers, err := p.allContainers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -51,13 +54,13 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
|
|||||||
return nil, servicePorts, err
|
return nil, servicePorts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ports, err := ocicniPortMappingToContainerPort(infraContainer.config.PortMappings)
|
ports, err = ocicniPortMappingToContainerPort(infraContainer.config.PortMappings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, servicePorts, err
|
return nil, servicePorts, err
|
||||||
}
|
}
|
||||||
servicePorts = containerPortsToServicePorts(ports)
|
servicePorts = containerPortsToServicePorts(ports)
|
||||||
}
|
}
|
||||||
pod, err := p.podWithContainers(allContainers)
|
pod, err := p.podWithContainers(allContainers, ports)
|
||||||
return pod, servicePorts, err
|
return pod, servicePorts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,18 +127,27 @@ func containersToServicePorts(containers []v1.Container) []v1.ServicePort {
|
|||||||
return sps
|
return sps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pod) podWithContainers(containers []*Container) (*v1.Pod, error) {
|
func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort) (*v1.Pod, error) {
|
||||||
var podContainers []v1.Container
|
var (
|
||||||
|
podContainers []v1.Container
|
||||||
|
)
|
||||||
|
first := true
|
||||||
for _, ctr := range containers {
|
for _, ctr := range containers {
|
||||||
result, err := containerToV1Container(ctr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !ctr.IsInfra() {
|
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)
|
podContainers = append(podContainers, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return addContainersToPodObject(podContainers, p.Name()), nil
|
return addContainersToPodObject(podContainers, p.Name()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +162,7 @@ func addContainersToPodObject(containers []v1.Container, podName string) *v1.Pod
|
|||||||
labels["app"] = removeUnderscores(podName)
|
labels["app"] = removeUnderscores(podName)
|
||||||
om := v12.ObjectMeta{
|
om := v12.ObjectMeta{
|
||||||
// The name of the pod is container_name-libpod
|
// The name of the pod is container_name-libpod
|
||||||
Name: fmt.Sprintf("%s-libpod", removeUnderscores(podName)),
|
Name: fmt.Sprintf("%s", removeUnderscores(podName)),
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
// CreationTimestamp seems to be required, so adding it; in doing so, the timestamp
|
// 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
|
// will reflect time this is run (not container create time) because the conversion
|
||||||
|
Reference in New Issue
Block a user