summaryrefslogtreecommitdiff
path: root/cmd/podman/play_kube.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/play_kube.go')
-rw-r--r--cmd/podman/play_kube.go104
1 files changed, 87 insertions, 17 deletions
diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go
index 6f23e340e..10221a339 100644
--- a/cmd/podman/play_kube.go
+++ b/cmd/podman/play_kube.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"fmt"
"io"
"io/ioutil"
@@ -25,10 +26,17 @@ import (
"k8s.io/api/core/v1"
)
+const (
+ // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
+ createDirectoryPermission = 0755
+)
+
var (
playKubeCommand cliconfig.KubePlayValues
- playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML"
- _playKubeCommand = &cobra.Command{
+ playKubeDescription = `Command reads in a structured file of Kubernetes YAML.
+
+ It creates 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.`
+ _playKubeCommand = &cobra.Command{
Use: "kube [flags] KUBEFILE",
Short: "Play a pod based on Kubernetes YAML",
Long: playKubeDescription,
@@ -44,6 +52,7 @@ var (
func init() {
playKubeCommand.Command = _playKubeCommand
+ playKubeCommand.SetHelpTemplate(HelpTemplate())
playKubeCommand.SetUsageTemplate(UsageTemplate())
flags := playKubeCommand.Flags()
flags.StringVar(&playKubeCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
@@ -51,7 +60,7 @@ func init() {
flags.StringVar(&playKubeCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.BoolVarP(&playKubeCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
- flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
+ flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
}
func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
@@ -90,11 +99,20 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
return errors.Wrapf(err, "unable to read %s as YAML", args[0])
}
+ // check for name collision between pod and container
+ podName := podYAML.ObjectMeta.Name
+ for _, n := range podYAML.Spec.Containers {
+ if n.Name == podName {
+ fmt.Printf("a container exists with the same name (%s) as the pod in your YAML file; changing pod name to %s_pod\n", podName, podName)
+ podName = fmt.Sprintf("%s_pod", podName)
+ }
+ }
+
podOptions = append(podOptions, libpod.WithInfraContainer())
- podOptions = append(podOptions, libpod.WithPodName(podYAML.ObjectMeta.Name))
+ podOptions = append(podOptions, libpod.WithPodName(podName))
// 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, ","))
+ nsOptions, err := shared.GetNamespaceOptions(strings.Split(shared.DefaultKernelNamespaces, ","))
if err != nil {
return err
}
@@ -135,16 +153,45 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
+ // map from name to mount point
+ volumes := make(map[string]string)
+ for _, volume := range podYAML.Spec.Volumes {
+ hostPath := volume.VolumeSource.HostPath
+ if hostPath == nil {
+ return errors.Errorf("HostPath is currently the only supported VolumeSource")
+ }
+ if hostPath.Type != nil {
+ switch *hostPath.Type {
+ case v1.HostPathDirectoryOrCreate:
+ if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
+ if err := os.Mkdir(hostPath.Path, createDirectoryPermission); err != nil {
+ return errors.Errorf("Error creating HostPath %s at %s", volume.Name, hostPath.Path)
+ }
+ }
+ case v1.HostPathDirectory:
+ // do nothing here because we will verify the path exists in validateVolumeHostDir
+ break
+ default:
+ return errors.Errorf("Directories are the only supported HostPath type")
+ }
+ }
+ if err := shared.ValidateVolumeHostDir(hostPath.Path); err != nil {
+ return errors.Wrapf(err, "Error in parsing HostPath in YAML")
+ }
+ fmt.Println(volume.Name)
+ volumes[volume.Name] = hostPath.Path
+ }
+
for _, container := range podYAML.Spec.Containers {
newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
if err != nil {
return err
}
- createConfig := kubeContainerToCreateConfig(container, runtime, newImage, namespaces)
+ createConfig, err := kubeContainerToCreateConfig(ctx, container, runtime, newImage, namespaces, volumes)
if err != nil {
return err
}
- ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx, pod)
+ ctr, err := shared.CreateContainerFromCreateConfig(runtime, createConfig, ctx, pod)
if err != nil {
return err
}
@@ -185,7 +232,7 @@ func getPodPorts(containers []v1.Container) []ocicni.PortMapping {
}
// 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 {
+func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container, runtime *libpod.Runtime, newImage *image2.Image, namespaces map[string]string, volumes map[string]string) (*createconfig.CreateConfig, error) {
var (
containerConfig createconfig.CreateConfig
envs map[string]string
@@ -197,15 +244,25 @@ func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Run
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
+
+ imageData, _ := newImage.Inspect(ctx)
+
+ containerConfig.User = "0"
+ if imageData != nil {
+ containerConfig.User = imageData.Config.User
}
- if containerYAML.SecurityContext.AllowPrivilegeEscalation != nil {
- containerConfig.NoNewPrivs = !*containerYAML.SecurityContext.AllowPrivilegeEscalation
+ if containerConfig.SecurityOpts != nil {
+ 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
@@ -222,7 +279,9 @@ func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Run
// disabled in code review per mheon
//containerConfig.PidMode = ns.PidMode(namespaces["pid"])
containerConfig.UsernsMode = ns.UsernsMode(namespaces["user"])
-
+ if len(containerConfig.WorkDir) == 0 {
+ containerConfig.WorkDir = "/"
+ }
if len(containerYAML.Env) > 0 {
envs = make(map[string]string)
}
@@ -231,5 +290,16 @@ func kubeContainerToCreateConfig(containerYAML v1.Container, runtime *libpod.Run
envs[e.Name] = e.Value
}
containerConfig.Env = envs
- return &containerConfig
+
+ for _, volume := range containerYAML.VolumeMounts {
+ host_path, exists := volumes[volume.Name]
+ if !exists {
+ return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
+ }
+ if err := shared.ValidateVolumeCtrDir(volume.MountPath); err != nil {
+ return nil, errors.Wrapf(err, "error in parsing MountPath")
+ }
+ containerConfig.Volumes = append(containerConfig.Volumes, fmt.Sprintf("%s:%s", host_path, volume.MountPath))
+ }
+ return &containerConfig, nil
}