Merge pull request #14974 from nicrowe00/kubedown1
add "podman kube down" command
This commit is contained in:
		
						commit
						1139cd9b81
					
				|  | @ -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 { | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue