Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for play/generate kube PersistentVolumeClaims and Podman volumes #9935

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions cmd/podman/common/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,20 @@ func AutocompletePodsRunning(cmd *cobra.Command, args []string, toComplete strin
return getPods(cmd, toComplete, completeDefault, "running", "degraded")
}

// AutocompleteForKube - Autocomplete all Podman objects supported by kube generate.
func AutocompleteForKube(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
containers, _ := getContainers(cmd, toComplete, completeDefault)
pods, _ := getPods(cmd, toComplete, completeDefault)
volumes, _ := getVolumes(cmd, toComplete)
objs := containers
objs = append(objs, pods...)
objs = append(objs, volumes...)
return objs, cobra.ShellCompDirectiveNoFileComp
}

// AutocompleteContainersAndPods - Autocomplete container names and pod names.
func AutocompleteContainersAndPods(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/podman/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ var (
// Command: podman _generate_
generateCmd = &cobra.Command{
Use: "generate",
Short: "Generate structured data based on containers and pods.",
Long: "Generate structured data (e.g., Kubernetes yaml or systemd units) based on containers and pods.",
Short: "Generate structured data based on containers, pods or volumes.",
Long: "Generate structured data (e.g., Kubernetes YAML or systemd units) based on containers, pods or volumes.",
RunE: validate.SubCommandExists,
}
containerConfig = util.DefaultContainerConfig()
Expand Down
14 changes: 8 additions & 6 deletions cmd/podman/generate/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,22 @@ import (
var (
kubeOptions = entities.GenerateKubeOptions{}
kubeFile = ""
kubeDescription = `Command generates Kubernetes pod and service YAML (v1 specification) from Podman containers or a pod.
kubeDescription = `Command generates Kubernetes Pod, Service or PersistenVolumeClaim YAML (v1 specification) from Podman containers, pods or volumes.

Whether the input is for a container or pod, Podman will always generate the specification as a pod.`
Whether the input is for a container or pod, Podman will always generate the specification as a pod.`

kubeCmd = &cobra.Command{
Use: "kube [options] {CONTAINER...|POD}",
Short: "Generate Kubernetes YAML from a container or pod.",
Use: "kube [options] {CONTAINER...|POD...|VOLUME...}",
Short: "Generate Kubernetes YAML from containers, pods or volumes.",
Long: kubeDescription,
RunE: kube,
Args: cobra.MinimumNArgs(1),
ValidArgsFunction: common.AutocompleteContainersAndPods,
ValidArgsFunction: common.AutocompleteForKube,
Example: `podman generate kube ctrID
podman generate kube podID
podman generate kube --service podID`,
podman generate kube --service podID
podman generate kube volumeName
podman generate kube ctrID podID volumeName --service`,
}
)

Expand Down
13 changes: 11 additions & 2 deletions cmd/podman/play/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ var (
kubeOptions = playKubeOptionsWrapper{}
kubeDescription = `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.`
It creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments and PersistentVolumeClaims.`

kubeCmd = &cobra.Command{
Use: "kube [options] KUBEFILE|-",
Short: "Play a pod based on Kubernetes YAML.",
Short: "Play a pod or volume based on Kubernetes YAML.",
Long: kubeDescription,
RunE: kube,
Args: cobra.ExactArgs(1),
Expand Down Expand Up @@ -129,6 +129,15 @@ func kube(cmd *cobra.Command, args []string) error {
return err
}

// Print volumes report
for i, volume := range report.Volumes {
if i == 0 {
fmt.Println("Volumes:")
}
fmt.Println(volume.Name)
}

// Print pods report
for _, pod := range report.Pods {
for _, l := range pod.Logs {
fmt.Fprint(os.Stderr, l)
Expand Down
4 changes: 2 additions & 2 deletions cmd/podman/play/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ var (
// Command: podman _play_
playCmd = &cobra.Command{
Use: "play",
Short: "Play a pod and its containers from a structured file.",
Long: "Play structured data (e.g., Kubernetes pod or service yaml) based on containers and pods.",
Short: "Play containers, pods or volumes from a structured file.",
Long: "Play structured data (e.g., Kubernetes YAML) based on containers, pods or volumes.",
RunE: validate.SubCommandExists,
}
)
Expand Down
12 changes: 7 additions & 5 deletions docs/source/markdown/podman-generate-kube.1.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
% podman-generate-kube(1)
## NAME
podman-generate-kube - Generate Kubernetes YAML based on a pod or container
podman-generate-kube - Generate Kubernetes YAML based on containers, pods or volumes

## SYNOPSIS
**podman generate kube** [*options*] *container...* | *pod*
**podman generate kube** [*options*] *container...* | *pod...* | *volume...*

## DESCRIPTION
**podman generate kube** will generate Kubernetes Pod YAML (v1 specification) from Podman from one or more containers or a single pod. Whether
the input is for containers or a pod, Podman will always generate the specification as a Pod. The input may be in the form
of a pod or one or more container names or IDs.
**podman generate kube** will generate Kubernetes YAML (v1 specification) from Podman containers, pods or volumes. Whether
the input is for containers or pods, Podman will always generate the specification as a Pod. The input may be in the form
of one or more containers, pods or volumes names or IDs.

`Podman Containers or Pods`

Volumes appear in the generated YAML according to two different volume types. Bind-mounted volumes become *hostPath* volume types and named volumes become *persistentVolumeClaim* volume types. Generated *hostPath* volume types will be one of three subtypes depending on the state of the host path: *DirectoryOrCreate* when no file or directory exists at the host, *Directory* when host path is a directory, or *File* when host path is a file. The value for *claimName* for a *persistentVolumeClaim* is the name of the named volume registered in Podman.

Expand Down
6 changes: 3 additions & 3 deletions docs/source/markdown/podman-generate.1.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
% podman-generate(1)

## NAME
podman\-generate - Generate structured data based for a containers and pods
podman\-generate - Generate structured data based on containers, pods or volumes

## SYNOPSIS
**podman generate** *subcommand*

## DESCRIPTION
The generate command will create structured output (like YAML) based on a container or pod.
The generate command will create structured output (like YAML) based on a container, pod or volume.

## COMMANDS

| Command | Man Page | Description |
|---------|------------------------------------------------------------|-------------------------------------------------------------------------------------|
| kube | [podman-generate-kube(1)](podman-generate-kube.1.md) | Generate Kubernetes YAML based on a pod or container. |
| kube | [podman-generate-kube(1)](podman-generate-kube.1.md) | Generate Kubernetes YAML based on containers, pods or volumes. |
| systemd | [podman-generate-systemd(1)](podman-generate-systemd.1.md) | Generate systemd unit file(s) for a container or pod. |


Expand Down
22 changes: 20 additions & 2 deletions docs/source/markdown/podman-play-kube.1.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
% podman-play-kube(1)

## NAME
podman-play-kube - Create pods and containers based on Kubernetes YAML
podman-play-kube - Create containers, pods or volumes based on Kubernetes YAML

## SYNOPSIS
**podman play kube** [*options*] *file.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. If the yaml file is specified as "-" then `podman play kube` with read the yaml file from stdin.
**podman play kube** will read in a structured file of Kubernetes YAML. It will then recreate the containers, pods or volumes described in the YAML. Containers within a pod are then started and the ID of the new Pod or the name of the new Volume is output. If the yaml file is specified as "-" then `podman play kube` will read the YAML file from stdin.

Ideally the input file would be one created by Podman (see podman-generate-kube(1)). This would guarantee a smooth import and expected results.

Currently, the supported Kubernetes kinds are:
- Pod
- Deployment
- PersistentVolumeClaim

`Kubernetes Pods or Deployments`

Only two volume types are supported by play kube, the *hostPath* and *persistentVolumeClaim* volume types. For the *hostPath* volume type, only the *default (empty)*, *DirectoryOrCreate*, *Directory*, *FileOrCreate*, *File*, and *Socket* subtypes are supported. The *CharDevice* and *BlockDevice* subtypes are not supported. Podman interprets the value of *hostPath* *path* as a file path when it contains at least one forward slash, otherwise Podman treats the value as the name of a named volume. When using a *persistentVolumeClaim*, the value for *claimName* is the name for the Podman named volume.

Note: *hostPath* volume types created by play kube will be given an SELinux private label (Z)

Note: If the `:latest` tag is used, Podman will attempt to pull the image from a registry. If the image was built locally with Podman or Buildah, it will have `localhost` as the domain, in that case, Podman will use the image from the local store even if it has the `:latest` tag.

`Kubernetes PersistentVolumeClaims`

A Kubernetes PersistentVolumeClaim represents a Podman named volume. Only the PersistentVolumeClaim name is required by Podman to create a volume. Kubernetes annotations can be used to make use of the available options for Podman volumes.

- volume.podman.io/driver
- volume.podman.io/device
- volume.podman.io/type
- volume.podman.io/uid
- volume.podman.io/gid
- volume.podman.io/mount-options

## OPTIONS

#### **\-\-authfile**=*path*
Expand Down
6 changes: 3 additions & 3 deletions docs/source/markdown/podman-play.1.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
% podman-play(1)

## NAME
podman\-play - Play pods and containers based on a structured input file
podman\-play - Play containers, pods or volumes 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)
The play command will recreate containers, pods or volumes 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) | Create pods and containers based on Kubernetes YAML. |
| kube | [podman-play-kube(1)](podman-play-kube.1.md) | Create containers, pods or volumes based on Kubernetes YAML. |

## SEE ALSO
podman, podman-pod(1), podman-container(1), podman-generate(1), podman-play(1), podman-play-kube(1)
4 changes: 2 additions & 2 deletions docs/source/markdown/podman.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-events(1)](podman-events.1.md) | Monitor Podman events |
| [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. |
| [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
| [podman-generate(1)](podman-generate.1.md) | Generate structured data based for a containers and pods. |
| [podman-generate(1)](podman-generate.1.md) | Generate structured data based on containers, pods or volumes. |
| [podman-healthcheck(1)](podman-healthcheck.1.md) | Manage healthchecks for containers |
| [podman-history(1)](podman-history.1.md) | Show the history of an image. |
| [podman-image(1)](podman-image.1.md) | Manage images. |
Expand All @@ -242,7 +242,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
| [podman-network(1)](podman-network.1.md) | Manage Podman CNI networks. |
| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. |
| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. |
| [podman-play(1)](podman-play.1.md) | Play containers, pods or volumes based on a structured input file. |
| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. |
| [podman-port(1)](podman-port.1.md) | List port mappings for a container. |
| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. |
Expand Down
45 changes: 45 additions & 0 deletions libpod/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -113,6 +114,50 @@ func (p *Pod) getInfraContainer() (*Container, error) {
return p.runtime.GetContainer(infraID)
}

// GenerateForKube generates a v1.PersistentVolumeClaim from a libpod volume.
func (v *Volume) GenerateForKube() *v1.PersistentVolumeClaim {
annotations := make(map[string]string)
annotations[util.VolumeDriverAnnotation] = v.Driver()

for k, v := range v.Options() {
switch k {
case "o":
annotations[util.VolumeMountOptsAnnotation] = v
case "device":
annotations[util.VolumeDeviceAnnotation] = v
case "type":
annotations[util.VolumeTypeAnnotation] = v
case "UID":
annotations[util.VolumeUIDAnnotation] = v
case "GID":
annotations[util.VolumeGIDAnnotation] = v
}
}

return &v1.PersistentVolumeClaim{
TypeMeta: v12.TypeMeta{
Kind: "PersistentVolumeClaim",
APIVersion: "v1",
},
ObjectMeta: v12.ObjectMeta{
Name: v.Name(),
Labels: v.Labels(),
Annotations: annotations,
CreationTimestamp: v12.Now(),
},
Spec: v1.PersistentVolumeClaimSpec{
Resources: v1.ResourceRequirements{
Requests: map[v1.ResourceName]resource.Quantity{
v1.ResourceStorage: resource.MustParse("1Gi"),
},
},
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
},
},
}
}

// GenerateKubeServiceFromV1Pod creates a v1 service object from a v1 pod object
func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) v1.Service {
service := v1.Service{}
Expand Down
8 changes: 8 additions & 0 deletions pkg/domain/entities/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,16 @@ type PlayKubePod struct {
ContainerErrors []string
}

// PlayKubeVolume represents a single volume created by play kube.
type PlayKubeVolume struct {
// Name - Name of the volume created by play kube.
Name string
}

// PlayKubeReport contains the results of running play kube.
type PlayKubeReport struct {
// Pods - pods created by play kube.
Pods []PlayKubePod
// Volumes - volumes created by play kube.
Volumes []PlayKubeVolume
}
Loading