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

kube play: update the handling of PersistentVolumeClaim #16420

Merged
merged 1 commit into from
Nov 8, 2022
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
20 changes: 18 additions & 2 deletions cmd/podman/kube/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@ package kube
import (
"github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/utils"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/spf13/cobra"
)

type downKubeOptions struct {
Force bool
}

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|-",
Use: "down [options] KUBEFILE|-",
Short: "Remove pods based on Kubernetes YAML.",
Long: downDescription,
RunE: down,
Expand All @@ -22,19 +28,29 @@ var (
cat nginx.yml | podman kube down -
podman kube down https://example.com/nginx.yml`,
}

downOptions = downKubeOptions{}
)

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: downCmd,
Parent: kubeCmd,
})
downFlags(downCmd)
}

func downFlags(cmd *cobra.Command) {
flags := cmd.Flags()
flags.SetNormalizeFunc(utils.AliasFlags)

flags.BoolVar(&downOptions.Force, "force", false, "remove volumes")
ygalblum marked this conversation as resolved.
Show resolved Hide resolved
}

func down(cmd *cobra.Command, args []string) error {
reader, err := readerFromArg(args[0])
if err != nil {
return err
}
return teardown(reader)
return teardown(reader, entities.PlayKubeDownOptions{Force: downOptions.Force})
}
32 changes: 26 additions & 6 deletions cmd/podman/kube/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ func playFlags(cmd *cobra.Command) {
flags.BoolVarP(&playOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.BoolVar(&playOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
flags.BoolVar(&playOptions.StartCLI, "start", true, "Start the pod after creating it")
flags.BoolVar(&playOptions.Force, "force", false, "Remove volumes as part of --down")

authfileFlagName := "authfile"
flags.StringVar(&playOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
Expand Down Expand Up @@ -242,17 +243,21 @@ func play(cmd *cobra.Command, args []string) error {
playOptions.StaticMACs = append(playOptions.StaticMACs, m)
}

if playOptions.Force && !playOptions.Down {
return errors.New("--force may be specified only with --down")
}

reader, err := readerFromArg(args[0])
if err != nil {
return err
}

if playOptions.Down {
return teardown(reader)
return teardown(reader, entities.PlayKubeDownOptions{Force: playOptions.Force})
}

if playOptions.Replace {
if err := teardown(reader); err != nil && !errorhandling.Contains(err, define.ErrNoSuchPod) {
if err := teardown(reader, entities.PlayKubeDownOptions{Force: playOptions.Force}); err != nil && !errorhandling.Contains(err, define.ErrNoSuchPod) {
return err
}
if _, err := reader.Seek(0, 0); err != nil {
Expand Down Expand Up @@ -302,13 +307,13 @@ func readerFromArg(fileName string) (*bytes.Reader, error) {
return bytes.NewReader(data), nil
}

func teardown(body io.Reader) error {
func teardown(body io.Reader, options entities.PlayKubeDownOptions) error {
var (
podStopErrors utils.OutputErrors
podRmErrors utils.OutputErrors
volRmErrors utils.OutputErrors
)
options := new(entities.PlayKubeDownOptions)
reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), body, *options)
reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), body, options)
if err != nil {
return err
}
Expand Down Expand Up @@ -338,7 +343,22 @@ func teardown(body io.Reader) error {
}
}

return podRmErrors.PrintErrors()
lastPodRmError := podRmErrors.PrintErrors()
if lastPodRmError != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", lastPodRmError)
}

// Output rm'd volumes
fmt.Println("Volumes removed:")
for _, removed := range reports.VolumeRmReport {
if removed.Err == nil {
fmt.Println(removed.Id)
} else {
volRmErrors = append(volRmErrors, removed.Err)
}
}

return volRmErrors.PrintErrors()
}

func kubeplay(body io.Reader) error {
Expand Down
17 changes: 12 additions & 5 deletions docs/source/markdown/podman-kube-down.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
podman-kube-down - Remove containers and pods based on Kubernetes YAML

## SYNOPSIS
**podman kube down** *file.yml|-|https://website.io/file.yml*
**podman kube down** [*options*] *file.yml|-|https://website.io/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. The input can also be a URL that points to a YAML file such as https://podman.io/demo.yml. `podman kube down` will then teardown the pods and
containers created by `podman kube play` via the same Kubernetes YAML from the URL. However, `podman kube down` will not work with a URL if the YAML file the URL
points to has been changed or altered since the creation of the pods and containers using `podman kube play`.
file. Any volumes that were created by the previous `podman kube play` command remain intact unless the `--force` options is used. If the YAML file is
specified as `-`, `podman kube down` reads the YAML from stdin. The input can also be a URL that points to a YAML file such as https://podman.io/demo.yml.
`podman kube down` will then teardown the pods and containers created by `podman kube play` via the same Kubernetes YAML from the URL. However,
`podman kube down` will not work with a URL if the YAML file the URL points to has been changed or altered since the creation of the pods and containers using
`podman kube play`.

## OPTIONS

#### **--force**

Tear down the volumes linked to the PersistentVolumeClaims as part --down

## EXAMPLES

Expand Down
5 changes: 5 additions & 0 deletions docs/source/markdown/podman-kube-play.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ Use *path* as the build context directory for each image. Requires --build optio

@@option creds

#### **--force**

Tear down the volumes linked to the PersistentVolumeClaims as part of --down

#### **--help**, **-h**

Print usage statement
Expand Down Expand Up @@ -185,6 +189,7 @@ Start the pod after creating it, set to false to only create it.
@@option tls-verify

@@option userns.container

## EXAMPLES

Recreate the pod and containers as described in a file called `demo.yml`
Expand Down
15 changes: 13 additions & 2 deletions pkg/api/handlers/libpod/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,20 @@ func KubePlay(w http.ResponseWriter, r *http.Request) {

func KubePlayDown(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
}{
Force: false,
}

if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
return
}

containerEngine := abi.ContainerEngine{Libpod: runtime}
options := new(entities.PlayKubeDownOptions)
report, err := containerEngine.PlayKubeDown(r.Context(), r.Body, *options)
report, err := containerEngine.PlayKubeDown(r.Context(), r.Body, entities.PlayKubeDownOptions{Force: query.Force})
_ = r.Body.Close()
if err != nil {
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("tearing down YAML file: %w", err))
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/server/register_kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
// - pods
// summary: Remove pods from kube play
// description: Tears down pods defined in a YAML file
// parameters:
// - in: query
// name: force
// type: boolean
// default: false
// description: Remove volumes.
// produces:
// - application/json
// responses:
Expand Down
13 changes: 9 additions & 4 deletions pkg/bindings/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func PlayWithBody(ctx context.Context, body io.Reader, options *PlayOptions) (*e
return &report, nil
}

func Down(ctx context.Context, path string) (*entities.KubePlayReport, error) {
func Down(ctx context.Context, path string, options DownOptions) (*entities.KubePlayReport, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
Expand All @@ -78,17 +78,22 @@ func Down(ctx context.Context, path string) (*entities.KubePlayReport, error) {
}
}()

return DownWithBody(ctx, f)
return DownWithBody(ctx, f, options)
}

func DownWithBody(ctx context.Context, body io.Reader) (*entities.KubePlayReport, error) {
func DownWithBody(ctx context.Context, body io.Reader, options DownOptions) (*entities.KubePlayReport, error) {
var report entities.KubePlayReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}

response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil)
params, err := options.ToParams()
if err != nil {
return nil, err
}

response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", params, nil)
if err != nil {
return nil, err
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/bindings/kube/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type PlayOptions struct {
Start *bool
// Userns - define the user namespace to use.
Userns *string
// Force - remove volumes on --down
Force *bool
}

// ApplyOptions are optional options for applying kube YAML files to a k8s cluster
Expand All @@ -63,3 +65,11 @@ type ApplyOptions struct {
// Service - creates a service for the container being deployed.
Service *bool
}

// DownOptions are optional options for tearing down kube YAML files to a k8s cluster
//
//go:generate go run ../generator/generator.go DownOptions
type DownOptions struct {
// Force - remove volumes on --down
Force *bool
}
33 changes: 33 additions & 0 deletions pkg/bindings/kube/types_down_options.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions pkg/bindings/kube/types_play_options.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pkg/bindings/play/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*e
return kube.PlayWithBody(ctx, body, options)
}

func Down(ctx context.Context, path string) (*entities.PlayKubeReport, error) {
return kube.Down(ctx, path)
func Down(ctx context.Context, path string, options kube.DownOptions) (*entities.PlayKubeReport, error) {
return kube.Down(ctx, path, options)
}

func DownWithBody(ctx context.Context, body io.Reader) (*entities.PlayKubeReport, error) {
return kube.DownWithBody(ctx, body)
func DownWithBody(ctx context.Context, body io.Reader, options kube.DownOptions) (*entities.PlayKubeReport, error) {
return kube.DownWithBody(ctx, body, options)
}
12 changes: 9 additions & 3 deletions pkg/domain/entities/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ type PlayKubeOptions struct {
Userns string
// IsRemote - was the request triggered by running podman-remote
IsRemote bool
// Force - remove volumes on --down
Force bool
}

// PlayKubePod represents a single pod and associated containers created by play kube
Expand Down Expand Up @@ -96,12 +98,16 @@ type PlayKubeReport struct {
type KubePlayReport = PlayKubeReport

// PlayKubeDownOptions are options for tearing down pods
type PlayKubeDownOptions struct{}
type PlayKubeDownOptions struct {
// Force - remove volumes if passed
Force bool
}

// PlayKubeDownReport contains the results of tearing down play kube
type PlayKubeTeardown struct {
StopReport []*PodStopReport
RmReport []*PodRmReport
StopReport []*PodStopReport
RmReport []*PodRmReport
VolumeRmReport []*VolumeRmReport
}

type PlaySecret struct {
Expand Down
Loading