add "podman kube down" command

The "podman kube down" reads in a structured file of
Kubernetes YAML and removes pods based on the Kubernetes kind described in the YAML,
similiar to "podman play kube --down". Users will still be able to use
"podman play kube --down" and "podman kube play --down" to
perform the same function.

Signed-off-by: Niall Crowe <nicrowe@redhat.com>
This commit is contained in:
Niall Crowe
2022-07-18 14:20:35 +01:00
parent c09457e34a
commit 1249cbb75f
6 changed files with 146 additions and 39 deletions

39
cmd/podman/kube/down.go Normal file
View File

@ -0,0 +1,39 @@
package pods
import (
"github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/spf13/cobra"
)
var (
downDescription = `Reads in a structured file of Kubernetes YAML.
Removes pods that have been based on the Kubernetes kind described in the YAML.`
downCmd = &cobra.Command{
Use: "down KUBEFILE|-",
Short: "Remove pods based on Kubernetes YAML.",
Long: downDescription,
RunE: down,
Args: cobra.ExactArgs(1),
ValidArgsFunction: common.AutocompleteDefaultOneArg,
Example: `podman kube down nginx.yml
cat nginx.yml | podman kube down -`,
}
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: downCmd,
Parent: kubeCmd,
})
}
func down(cmd *cobra.Command, args []string) error {
reader, err := readerFromArg(args[0])
if err != nil {
return err
}
return teardown(reader)
}

View File

@ -1,8 +1,10 @@
package pods
import (
"bytes"
"errors"
"fmt"
"io"
"net"
"os"
"strings"
@ -37,9 +39,9 @@ var (
// https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
defaultSeccompRoot = "/var/lib/kubelet/seccomp"
playOptions = playKubeOptionsWrapper{}
playDescription = `Command reads in a structured file of Kubernetes YAML.
playDescription = `Reads in a structured file of Kubernetes YAML.
It creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments and PersistentVolumeClaims.`
Creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments and PersistentVolumeClaims.`
playCmd = &cobra.Command{
Use: "play [options] KUBEFILE|-",
@ -139,6 +141,7 @@ func playFlags(cmd *cobra.Command) {
downFlagName := "down"
flags.BoolVar(&playOptions.Down, downFlagName, false, "Stop pods defined in the YAML file")
_ = flags.MarkHidden("down")
replaceFlagName := "replace"
flags.BoolVar(&playOptions.Replace, replaceFlagName, false, "Delete and recreate pods defined in the YAML file")
@ -164,7 +167,7 @@ func playFlags(cmd *cobra.Command) {
_ = cmd.RegisterFlagCompletionFunc(contextDirFlagName, completion.AutocompleteDefault)
// NOTE: The service-container flag is marked as hidden as it
// is purely designed for running kube-play or play-kube in systemd units.
// is purely designed for running kube-play in systemd units.
// It is not something users should need to know or care about.
//
// Having a flag rather than an env variable is cleaner.
@ -223,10 +226,6 @@ func Play(cmd *cobra.Command, args []string) error {
}
playOptions.Annotations[splitN[0]] = annotation
}
yamlfile := args[0]
if yamlfile == "-" {
yamlfile = "/dev/stdin"
}
for _, mac := range playOptions.macs {
m, err := net.ParseMAC(mac)
@ -235,36 +234,62 @@ func Play(cmd *cobra.Command, args []string) error {
}
playOptions.StaticMACs = append(playOptions.StaticMACs, m)
}
if playOptions.Down {
return teardown(yamlfile)
reader, err := readerFromArg(args[0])
if err != nil {
return err
}
if playOptions.Down {
return teardown(reader)
}
if playOptions.Replace {
if err := teardown(yamlfile); err != nil && !errorhandling.Contains(err, define.ErrNoSuchPod) {
if err := teardown(reader); err != nil && !errorhandling.Contains(err, define.ErrNoSuchPod) {
return err
}
if _, err := reader.Seek(0, 0); err != nil {
return err
}
}
return kubeplay(yamlfile)
return kubeplay(reader)
}
func playKube(cmd *cobra.Command, args []string) error {
return Play(cmd, args)
}
func teardown(yamlfile string) error {
func readerFromArg(fileName string) (*bytes.Reader, error) {
if fileName == "-" { // Read from stdin
data, err := io.ReadAll(os.Stdin)
if err != nil {
return nil, err
}
return bytes.NewReader(data), nil
}
f, err := os.Open(fileName)
if err != nil {
return nil, err
}
defer f.Close()
data, err := io.ReadAll(f)
if err != nil {
return nil, err
}
return bytes.NewReader(data), nil
}
func teardown(body io.Reader) error {
var (
podStopErrors utils.OutputErrors
podRmErrors utils.OutputErrors
)
options := new(entities.PlayKubeDownOptions)
f, err := os.Open(yamlfile)
reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), body, *options)
if err != nil {
return err
}
defer f.Close()
reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), f, *options)
if err != nil {
return fmt.Errorf("%v: %w", yamlfile, err)
}
// Output stopped pods
fmt.Println("Pods stopped:")
@ -290,19 +315,15 @@ func teardown(yamlfile string) error {
podRmErrors = append(podRmErrors, removed.Err)
}
}
return podRmErrors.PrintErrors()
}
func kubeplay(yamlfile string) error {
f, err := os.Open(yamlfile)
func kubeplay(body io.Reader) error {
report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), body, playOptions.PlayKubeOptions)
if err != nil {
return err
}
defer f.Close()
report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), f, playOptions.PlayKubeOptions)
if err != nil {
return fmt.Errorf("%s: %w", yamlfile, err)
}
// Print volumes report
for i, volume := range report.Volumes {
if i == 0 {

View File

@ -0,0 +1,43 @@
% podman-kube-down(1)
## NAME
podman-kube-down - Remove containers and pods based on Kubernetes YAML
## SYNOPSIS
**podman kube down** *file.yml|-*
## DESCRIPTION
**podman kube down** reads a specified Kubernetes YAML file, tearing down pods that were created by the `podman kube play` command via the same Kubernetes YAML file. Any volumes that were created by the previous `podman kube play` command remain intact. If the YAML file is specified as `-`, `podman kube down` reads the YAML from stdin.
## EXAMPLES
Example YAML file `demo.yml`:
```
apiVersion: v1
kind: Pod
metadata:
...
spec:
containers:
- command:
- top
- name: container
value: podman
image: foobar
...
```
Remove the pod and containers as described in the `demo.yml` file
```
$ podman kube down demo.yml
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
```
Remove the pod and containers as described in the`demo.yml` file YAML sent to stdin
```
$ cat demo.yml | podman kube play -
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
```
## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**, **[podman-generate-kube(1)](podman-generate-kube.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**

View File

@ -1,7 +1,7 @@
% podman-kube-play(1)
## NAME
podman-kube-play - Create containers, pods or volumes based on Kubernetes YAML
podman-kube-play - Create containers, pods and volumes based on Kubernetes YAML
## SYNOPSIS
**podman kube play** [*options*] *file.yml|-*
@ -30,6 +30,9 @@ Note: If the `:latest` tag is used, Podman will attempt to pull the image from a
Note: The command `podman play kube` is an alias of `podman kube play`, and will perform the same function.
Note: The command `podman kube down` can be used to stop and remove pods or containers based on the same Kubernetes YAML used
by `podman kube play` to create them.
`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.
@ -145,11 +148,6 @@ 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.
#### **--down**
Tears down the pods that were created by a previous run of `kube play`. The pods are stopped and then
removed. Any volumes created are left intact.
#### **--help**, **-h**
Print usage statement
@ -325,7 +323,7 @@ $ podman kube play demo.yml --network net1:ip=10.89.1.5 --network net2:ip=10.89.
Please take into account that networks must be created first using podman-network-create(1).
## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-network-create(1)](podman-network-create.1.md)**, **[podman-generate-kube(1)](podman-generate-kube.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**
**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-kube-down(1)](podman-kube-down.1.md)**, **[podman-network-create(1)](podman-network-create.1.md)**, **[podman-generate-kube(1)](podman-generate-kube.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**
## HISTORY
December 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)

View File

@ -14,7 +14,8 @@ file input. Containers will be automatically started.
| Command | Man Page | Description |
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
| play | [podman-kube-play(1)](podman-kube-play.1.md) | Create containers, pods or volumes based on Kubernetes YAML. |
| down | [podman-kube-down(1)](podman-kube-down.1.md) | Remove containers and pods based on Kubernetes YAML. |
| play | [podman-kube-play(1)](podman-kube-play.1.md) | Create containers, pods and volumes based on Kubernetes YAML. |
## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-pod(1)](podman-pod.1.md)**, **[podman-container(1)](podman-container.1.md)**, **[podman-generate(1)](podman-generate.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**
**[podman(1)](podman.1.md)**, **[podman-pod(1)](podman-pod.1.md)**, **[podman-container(1)](podman-container.1.md)**, **[podman-generate(1)](podman-generate.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**, **[podman-kube-down(1)](podman-kube-down.1.md)**

View File

@ -182,8 +182,11 @@ EOF
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "none" "network mode none is set for the container"
run_podman stop -a -t 0
run_podman pod rm -t 0 -f test_pod
run_podman kube down - < $PODMAN_TMPDIR/test.yaml
run_podman 125 inspect test_pod-test
is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\""
run_podman pod rm -a
run_podman rm -a
}
@test "podman play with user from image" {
@ -325,7 +328,6 @@ spec:
- name: TERM
value: xterm
- name: container
value: podman
image: quay.io/libpod/userimage
name: test
@ -353,6 +355,9 @@ status: {}
run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
is "$output" "$default_driver" "play kube uses default log driver"
run_podman stop -a -t 0
run_podman pod rm -t 0 -f test_pod
run_podman kube down $PODMAN_TMPDIR/test.yaml
run_podman 125 inspect test_pod-test
is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\""
run_podman pod rm -a
run_podman rm -a
}