From ba841aa326a09109a8324ca8dea4d8217080d932 Mon Sep 17 00:00:00 2001 From: Christian Stewart Date: Wed, 23 Mar 2022 00:21:48 -0700 Subject: [PATCH] play: kube: add support for in-memory kubefile The PlayKube and PlayKubeDown commands accept a "path" argument to a YAML file to play. This requires the caller to write the YAML to a file path. The file is opened & used as the body of the HTTP request, so it should be possible to instead pass a io.Reader and use a fully in-memory request body. This commit adds a new backwards-compatible option to PlayKubeOptions and PlayKubeDownOptions - "Body" - which is an io.Reader for the request body. If it is set (non-nil) it will be used instead of os.Open() for the yaml file path. Signed-off-by: Christian Stewart --- pkg/bindings/play/play.go | 39 +++++++++++++++++++++------------ pkg/domain/entities/play.go | 10 ++++++++- pkg/domain/infra/abi/play.go | 11 ++++++++-- pkg/domain/infra/tunnel/play.go | 11 +++++++++- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go index d4018b6b3955..8058a8514fce 100644 --- a/pkg/bindings/play/play.go +++ b/pkg/bindings/play/play.go @@ -2,6 +2,7 @@ package play import ( "context" + "io" "net/http" "os" "strconv" @@ -14,20 +15,25 @@ import ( ) func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.PlayKubeReport, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + return KubeWithBody(ctx, f, options) +} + +func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*entities.PlayKubeReport, error) { var report entities.PlayKubeReport if options == nil { options = new(KubeOptions) } - conn, err := bindings.GetClient(ctx) - if err != nil { - return nil, err - } - f, err := os.Open(path) + conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - defer f.Close() params, err := options.ToParams() if err != nil { @@ -46,7 +52,7 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla return nil, err } - response, err := conn.DoRequest(ctx, f, http.MethodPost, "/play/kube", params, header) + response, err := conn.DoRequest(ctx, body, http.MethodPost, "/play/kube", params, header) if err != nil { return nil, err } @@ -60,12 +66,6 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla } func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error) { - var report entities.PlayKubeReport - conn, err := bindings.GetClient(ctx) - if err != nil { - return nil, err - } - f, err := os.Open(path) if err != nil { return nil, err @@ -75,7 +75,18 @@ func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error logrus.Warn(err) } }() - response, err := conn.DoRequest(ctx, f, http.MethodDelete, "/play/kube", nil, nil) + + return KubeDownWithBody(ctx, f) +} + +func KubeDownWithBody(ctx context.Context, body io.Reader) (*entities.PlayKubeReport, error) { + var report entities.PlayKubeReport + conn, err := bindings.GetClient(ctx) + if err != nil { + return nil, err + } + + response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil) if err != nil { return nil, err } diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go index c9dc3f08c2de..9bc9f64f9185 100644 --- a/pkg/domain/entities/play.go +++ b/pkg/domain/entities/play.go @@ -1,6 +1,7 @@ package entities import ( + "io" "net" "github.com/containers/image/v5/types" @@ -54,6 +55,9 @@ type PlayKubeOptions struct { LogOptions []string // Start - don't start the pod if false Start types.OptionalBool + // Body is a reader to read the body of the request from. + // Overrides the "path" variable if set. + Body io.Reader } // PlayKubePod represents a single pod and associated containers created by play kube @@ -87,7 +91,11 @@ type PlayKubeReport struct { } // PlayKubeDownOptions are options for tearing down pods -type PlayKubeDownOptions struct{} +type PlayKubeDownOptions struct { + // Body is a reader to read the body of the request from. + // Overrides the "path" variable if set. + Body io.Reader +} // PlayKubeDownReport contains the results of tearing down play kube type PlayKubeTeardown struct { diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 236d56053c5c..b7ea3a862a78 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -37,8 +37,15 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en report := &entities.PlayKubeReport{} validKinds := 0 - // read yaml document - content, err := ioutil.ReadFile(path) + var content []byte + var err error + if body := options.Body; body != nil { + // read body io.reader + content, err = ioutil.ReadAll(body) + } else { + // read yaml document + content, err = ioutil.ReadFile(path) + } if err != nil { return nil, err } diff --git a/pkg/domain/infra/tunnel/play.go b/pkg/domain/infra/tunnel/play.go index cd51262d022b..b81e90f92892 100644 --- a/pkg/domain/infra/tunnel/play.go +++ b/pkg/domain/infra/tunnel/play.go @@ -26,9 +26,18 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entit if start := opts.Start; start != types.OptionalBoolUndefined { options.WithStart(start == types.OptionalBoolTrue) } + + if body := opts.Body; body != nil { + return play.KubeWithBody(ctx, body, options) + } + return play.Kube(ic.ClientCtx, path, options) } -func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, opts entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { + if opts.Body != nil { + return play.KubeDownWithBody(ctx, opts.Body) + } + return play.KubeDown(ic.ClientCtx, path) }