mirror of
https://github.com/containers/podman.git
synced 2025-05-22 09:36:57 +08:00
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:
39
cmd/podman/kube/down.go
Normal file
39
cmd/podman/kube/down.go
Normal 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)
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
package pods
|
package pods
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -37,9 +39,9 @@ var (
|
|||||||
// https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
|
// https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
|
||||||
defaultSeccompRoot = "/var/lib/kubelet/seccomp"
|
defaultSeccompRoot = "/var/lib/kubelet/seccomp"
|
||||||
playOptions = playKubeOptionsWrapper{}
|
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{
|
playCmd = &cobra.Command{
|
||||||
Use: "play [options] KUBEFILE|-",
|
Use: "play [options] KUBEFILE|-",
|
||||||
@ -139,6 +141,7 @@ func playFlags(cmd *cobra.Command) {
|
|||||||
|
|
||||||
downFlagName := "down"
|
downFlagName := "down"
|
||||||
flags.BoolVar(&playOptions.Down, downFlagName, false, "Stop pods defined in the YAML file")
|
flags.BoolVar(&playOptions.Down, downFlagName, false, "Stop pods defined in the YAML file")
|
||||||
|
_ = flags.MarkHidden("down")
|
||||||
|
|
||||||
replaceFlagName := "replace"
|
replaceFlagName := "replace"
|
||||||
flags.BoolVar(&playOptions.Replace, replaceFlagName, false, "Delete and recreate pods defined in the YAML file")
|
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)
|
_ = cmd.RegisterFlagCompletionFunc(contextDirFlagName, completion.AutocompleteDefault)
|
||||||
|
|
||||||
// NOTE: The service-container flag is marked as hidden as it
|
// 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.
|
// It is not something users should need to know or care about.
|
||||||
//
|
//
|
||||||
// Having a flag rather than an env variable is cleaner.
|
// 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
|
playOptions.Annotations[splitN[0]] = annotation
|
||||||
}
|
}
|
||||||
yamlfile := args[0]
|
|
||||||
if yamlfile == "-" {
|
|
||||||
yamlfile = "/dev/stdin"
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mac := range playOptions.macs {
|
for _, mac := range playOptions.macs {
|
||||||
m, err := net.ParseMAC(mac)
|
m, err := net.ParseMAC(mac)
|
||||||
@ -235,36 +234,62 @@ func Play(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
playOptions.StaticMACs = append(playOptions.StaticMACs, m)
|
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 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 err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return kubeplay(yamlfile)
|
return kubeplay(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func playKube(cmd *cobra.Command, args []string) error {
|
func playKube(cmd *cobra.Command, args []string) error {
|
||||||
return Play(cmd, args)
|
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 (
|
var (
|
||||||
podStopErrors utils.OutputErrors
|
podStopErrors utils.OutputErrors
|
||||||
podRmErrors utils.OutputErrors
|
podRmErrors utils.OutputErrors
|
||||||
)
|
)
|
||||||
options := new(entities.PlayKubeDownOptions)
|
options := new(entities.PlayKubeDownOptions)
|
||||||
f, err := os.Open(yamlfile)
|
reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), body, *options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// Output stopped pods
|
||||||
fmt.Println("Pods stopped:")
|
fmt.Println("Pods stopped:")
|
||||||
@ -290,19 +315,15 @@ func teardown(yamlfile string) error {
|
|||||||
podRmErrors = append(podRmErrors, removed.Err)
|
podRmErrors = append(podRmErrors, removed.Err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return podRmErrors.PrintErrors()
|
return podRmErrors.PrintErrors()
|
||||||
}
|
}
|
||||||
|
|
||||||
func kubeplay(yamlfile string) error {
|
func kubeplay(body io.Reader) error {
|
||||||
f, err := os.Open(yamlfile)
|
report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), body, playOptions.PlayKubeOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// Print volumes report
|
||||||
for i, volume := range report.Volumes {
|
for i, volume := range report.Volumes {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
43
docs/source/markdown/podman-kube-down.1.md
Normal file
43
docs/source/markdown/podman-kube-down.1.md
Normal 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)**
|
@ -1,7 +1,7 @@
|
|||||||
% podman-kube-play(1)
|
% podman-kube-play(1)
|
||||||
|
|
||||||
## NAME
|
## 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
|
## SYNOPSIS
|
||||||
**podman kube play** [*options*] *file.yml|-*
|
**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 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`
|
`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.
|
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
|
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.
|
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**
|
#### **--help**, **-h**
|
||||||
|
|
||||||
Print usage statement
|
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).
|
Please take into account that networks must be created first using podman-network-create(1).
|
||||||
|
|
||||||
## SEE ALSO
|
## 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
|
## HISTORY
|
||||||
December 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
|
December 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
|
||||||
|
@ -14,7 +14,8 @@ file input. Containers will be automatically started.
|
|||||||
|
|
||||||
| Command | Man Page | Description |
|
| 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
|
## 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)**
|
||||||
|
@ -182,8 +182,11 @@ EOF
|
|||||||
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
|
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
|
||||||
is "$output" "none" "network mode none is set for the container"
|
is "$output" "none" "network mode none is set for the container"
|
||||||
|
|
||||||
run_podman stop -a -t 0
|
run_podman kube down - < $PODMAN_TMPDIR/test.yaml
|
||||||
run_podman pod rm -t 0 -f test_pod
|
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" {
|
@test "podman play with user from image" {
|
||||||
@ -325,7 +328,6 @@ spec:
|
|||||||
- name: TERM
|
- name: TERM
|
||||||
value: xterm
|
value: xterm
|
||||||
- name: container
|
- name: container
|
||||||
|
|
||||||
value: podman
|
value: podman
|
||||||
image: quay.io/libpod/userimage
|
image: quay.io/libpod/userimage
|
||||||
name: test
|
name: test
|
||||||
@ -353,6 +355,9 @@ status: {}
|
|||||||
run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
|
run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
|
||||||
is "$output" "$default_driver" "play kube uses default log driver"
|
is "$output" "$default_driver" "play kube uses default log driver"
|
||||||
|
|
||||||
run_podman stop -a -t 0
|
run_podman kube down $PODMAN_TMPDIR/test.yaml
|
||||||
run_podman pod rm -t 0 -f test_pod
|
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
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user