mirror of
https://github.com/containers/podman.git
synced 2025-11-28 17:18:58 +08:00
feat(cmd): podman kube play support multiple arguments
Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> fix: update kube play command cobra use Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> Add multi-file support to podman kube play/down - Support multiple YAML files and URLs in single command - Combine files with YAML document separators (---) - Refactor for better testability with dependency injection - Update documentation with examples for multiple inputs - Improve memory efficiency with streaming I/O operations Fixes: https://github.com/containers/podman/issues/26274 Fixes: https://issues.redhat.com/browse/RUN-3586 Signed-off-by: Jan Rodák <hony.com@seznam.cz>
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
package kube
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containers/podman/v5/cmd/podman/common"
|
|
||||||
"github.com/containers/podman/v5/cmd/podman/registry"
|
"github.com/containers/podman/v5/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v5/cmd/podman/utils"
|
"github.com/containers/podman/v5/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"go.podman.io/common/pkg/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
type downKubeOptions struct {
|
type downKubeOptions struct {
|
||||||
@@ -18,12 +18,12 @@ var (
|
|||||||
Removes pods that have been based on the Kubernetes kind described in the YAML.`
|
Removes pods that have been based on the Kubernetes kind described in the YAML.`
|
||||||
|
|
||||||
downCmd = &cobra.Command{
|
downCmd = &cobra.Command{
|
||||||
Use: "down [options] KUBEFILE|-",
|
Use: "down [options] [KUBEFILE [KUBEFILE...]]|-",
|
||||||
Short: "Remove pods based on Kubernetes YAML",
|
Short: "Remove pods based on Kubernetes YAML",
|
||||||
Long: downDescription,
|
Long: downDescription,
|
||||||
RunE: down,
|
RunE: down,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
ValidArgsFunction: completion.AutocompleteDefault,
|
||||||
Example: `podman kube down nginx.yml
|
Example: `podman kube down nginx.yml
|
||||||
cat nginx.yml | podman kube down -
|
cat nginx.yml | podman kube down -
|
||||||
podman kube down https://example.com/nginx.yml`,
|
podman kube down https://example.com/nginx.yml`,
|
||||||
@@ -48,7 +48,7 @@ func downFlags(cmd *cobra.Command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func down(_ *cobra.Command, args []string) error {
|
func down(_ *cobra.Command, args []string) error {
|
||||||
reader, err := readerFromArg(args[0])
|
reader, err := readerFromArgs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ type playKubeOptionsWrapper struct {
|
|||||||
macs []string
|
macs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const yamlFileSeparator = "\n---\n"
|
||||||
|
|
||||||
var (
|
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"
|
||||||
@@ -51,12 +53,12 @@ var (
|
|||||||
Creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments, DaemonSets, Jobs, and PersistentVolumeClaims.`
|
Creates pods or volumes based on the Kubernetes kind described in the YAML. Supported kinds are Pods, Deployments, DaemonSets, Jobs, and PersistentVolumeClaims.`
|
||||||
|
|
||||||
playCmd = &cobra.Command{
|
playCmd = &cobra.Command{
|
||||||
Use: "play [options] KUBEFILE|-",
|
Use: "play [options] [KUBEFILE [KUBEFILE...]]|-",
|
||||||
Short: "Play a pod or volume based on Kubernetes YAML",
|
Short: "Play a pod or volume based on Kubernetes YAML",
|
||||||
Long: playDescription,
|
Long: playDescription,
|
||||||
RunE: play,
|
RunE: play,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
ValidArgsFunction: completion.AutocompleteDefault,
|
||||||
Example: `podman kube play nginx.yml
|
Example: `podman kube play nginx.yml
|
||||||
cat nginx.yml | podman kube play -
|
cat nginx.yml | podman kube play -
|
||||||
podman kube play --creds user:password --seccomp-profile-root /custom/path apache.yml
|
podman kube play --creds user:password --seccomp-profile-root /custom/path apache.yml
|
||||||
@@ -66,13 +68,13 @@ var (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
playKubeCmd = &cobra.Command{
|
playKubeCmd = &cobra.Command{
|
||||||
Use: "kube [options] KUBEFILE|-",
|
Use: "kube [options] [KUBEFILE [KUBEFILE...]]|-",
|
||||||
Short: "Play a pod or volume based on Kubernetes YAML",
|
Short: "Play a pod or volume based on Kubernetes YAML",
|
||||||
Long: playDescription,
|
Long: playDescription,
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
RunE: playKube,
|
RunE: playKube,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
ValidArgsFunction: completion.AutocompleteDefault,
|
||||||
Example: `podman play kube nginx.yml
|
Example: `podman play kube nginx.yml
|
||||||
cat nginx.yml | podman play kube -
|
cat nginx.yml | podman play kube -
|
||||||
podman play kube --creds user:password --seccomp-profile-root /custom/path apache.yml
|
podman play kube --creds user:password --seccomp-profile-root /custom/path apache.yml
|
||||||
@@ -276,7 +278,7 @@ func play(cmd *cobra.Command, args []string) error {
|
|||||||
return errors.New("--force may be specified only with --down")
|
return errors.New("--force may be specified only with --down")
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, err := readerFromArg(args[0])
|
reader, err := readerFromArgs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -306,7 +308,7 @@ func play(cmd *cobra.Command, args []string) error {
|
|||||||
playOptions.ServiceContainer = true
|
playOptions.ServiceContainer = true
|
||||||
|
|
||||||
// Read the kube yaml file again so that a reader can be passed down to the teardown function
|
// Read the kube yaml file again so that a reader can be passed down to the teardown function
|
||||||
teardownReader, err = readerFromArg(args[0])
|
teardownReader, err = readerFromArgs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -364,31 +366,54 @@ func playKube(cmd *cobra.Command, args []string) error {
|
|||||||
return play(cmd, args)
|
return play(cmd, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readerFromArg(fileName string) (*bytes.Reader, error) {
|
func readerFromArgs(args []string) (*bytes.Reader, error) {
|
||||||
var reader io.Reader
|
return readerFromArgsWithStdin(args, os.Stdin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readerFromArgsWithStdin(args []string, stdin io.Reader) (*bytes.Reader, error) {
|
||||||
|
// if user tried to pipe, shortcut the reading
|
||||||
|
if len(args) == 1 && args[0] == "-" {
|
||||||
|
data, err := io.ReadAll(stdin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bytes.NewReader(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var combined bytes.Buffer
|
||||||
|
|
||||||
|
for i, arg := range args {
|
||||||
|
reader, err := readerFromArg(arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(&combined, reader)
|
||||||
|
reader.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if i < len(args)-1 {
|
||||||
|
// separate multiple files with YAML document separator
|
||||||
|
combined.WriteString(yamlFileSeparator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes.NewReader(combined.Bytes()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readerFromArg(fileOrURL string) (io.ReadCloser, error) {
|
||||||
switch {
|
switch {
|
||||||
case fileName == "-": // Read from stdin
|
case parse.ValidWebURL(fileOrURL) == nil:
|
||||||
reader = os.Stdin
|
response, err := http.Get(fileOrURL)
|
||||||
case parse.ValidWebURL(fileName) == nil:
|
|
||||||
response, err := http.Get(fileName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer response.Body.Close()
|
return response.Body, nil
|
||||||
reader = response.Body
|
|
||||||
default:
|
default:
|
||||||
f, err := os.Open(fileName)
|
return os.Open(fileOrURL)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
reader = f
|
|
||||||
}
|
}
|
||||||
data, err := io.ReadAll(reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return bytes.NewReader(data), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func teardown(body io.Reader, options entities.PlayKubeDownOptions) error {
|
func teardown(body io.Reader, options entities.PlayKubeDownOptions) error {
|
||||||
|
|||||||
149
cmd/podman/kube/play_test.go
Normal file
149
cmd/podman/kube/play_test.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
package kube
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configMapYAML = strings.Join([]string{
|
||||||
|
"apiVersion: v1",
|
||||||
|
"kind: ConfigMap",
|
||||||
|
"metadata:",
|
||||||
|
" name: my-config",
|
||||||
|
"data:",
|
||||||
|
" key: value",
|
||||||
|
}, "\n")
|
||||||
|
|
||||||
|
var podYAML = strings.Join([]string{
|
||||||
|
"apiVersion: v1",
|
||||||
|
"kind: Pod",
|
||||||
|
"metadata:",
|
||||||
|
" name: my-pod",
|
||||||
|
}, "\n")
|
||||||
|
|
||||||
|
var serviceYAML = strings.Join([]string{
|
||||||
|
"apiVersion: v1",
|
||||||
|
"kind: Service",
|
||||||
|
"metadata:",
|
||||||
|
" name: my-service",
|
||||||
|
}, "\n")
|
||||||
|
|
||||||
|
var secretYAML = strings.Join([]string{
|
||||||
|
"apiVersion: v1",
|
||||||
|
"kind: Secret",
|
||||||
|
"metadata:",
|
||||||
|
" name: my-secret",
|
||||||
|
}, "\n")
|
||||||
|
|
||||||
|
var namespaceYAML = strings.Join([]string{
|
||||||
|
"apiVersion: v1",
|
||||||
|
"kind: Namespace",
|
||||||
|
"metadata:",
|
||||||
|
" name: my-namespace",
|
||||||
|
}, "\n")
|
||||||
|
|
||||||
|
// createTempFile writes content to a temp file and returns its path.
|
||||||
|
func createTempFile(t *testing.T, content string) string {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
tmp, err := os.CreateTemp(t.TempDir(), "testfile-*.yaml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := tmp.WriteString(content); err != nil {
|
||||||
|
t.Fatalf("failed to write to temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmp.Close(); err != nil {
|
||||||
|
t.Fatalf("failed to close temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReaderFromArgs(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
files []string // file contents
|
||||||
|
expected string // expected concatenated output
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "single file",
|
||||||
|
files: []string{configMapYAML},
|
||||||
|
expected: configMapYAML,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "two files",
|
||||||
|
files: []string{
|
||||||
|
podYAML,
|
||||||
|
serviceYAML,
|
||||||
|
},
|
||||||
|
expected: podYAML + "\n---\n" + serviceYAML,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty file and normal file",
|
||||||
|
files: []string{
|
||||||
|
"",
|
||||||
|
secretYAML,
|
||||||
|
},
|
||||||
|
expected: "---\n" + secretYAML,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "files with only whitespace",
|
||||||
|
files: []string{
|
||||||
|
"\n \n",
|
||||||
|
namespaceYAML,
|
||||||
|
},
|
||||||
|
expected: "---\n" + namespaceYAML,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var paths []string
|
||||||
|
for _, content := range tt.files {
|
||||||
|
path := createTempFile(t, content)
|
||||||
|
defer os.Remove(path)
|
||||||
|
paths = append(paths, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader, err := readerFromArgsWithStdin(paths, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("readerFromArgsWithStdin failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := io.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to read result: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := strings.TrimSpace(string(output))
|
||||||
|
want := strings.TrimSpace(tt.expected)
|
||||||
|
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("unexpected output:\n--- got ---\n%s\n--- want ---\n%s", got, want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReaderFromArgs_Stdin(t *testing.T) {
|
||||||
|
stdinReader := strings.NewReader(namespaceYAML)
|
||||||
|
|
||||||
|
reader, err := readerFromArgsWithStdin([]string{"-"}, stdinReader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("readerFromArgsWithStdin failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := io.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to read from stdin: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := string(data); got != namespaceYAML {
|
||||||
|
t.Errorf("unexpected stdin result:\n--- got ---\n%s\n--- want ---\n%s", got, namespaceYAML)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,16 +4,18 @@
|
|||||||
podman-kube-down - Remove containers and pods based on Kubernetes YAML
|
podman-kube-down - Remove containers and pods based on Kubernetes YAML
|
||||||
|
|
||||||
## SYNOPSIS
|
## SYNOPSIS
|
||||||
**podman kube down** [*options*] *file.yml|-|https://website.io/file.yml*
|
**podman kube down** [*options*] *file.yml|-|https://website.io/file.yml* [*file2.yml|https://website.io/file2.yml* ...]
|
||||||
|
|
||||||
## DESCRIPTION
|
## 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
|
**podman kube down** reads one or more specified Kubernetes YAML files, 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 unless the `--force` options is used. If the YAML file is
|
files. 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.
|
specified as `-`, `podman kube down` reads the YAML from stdin. The inputs can also be URLs that point to YAML files such as https://podman.io/demo.yml.
|
||||||
`podman kube down` tears down the pods and containers created by `podman kube play` via the same Kubernetes YAML from the URL. However,
|
`podman kube down` tears down the pods and containers created by `podman kube play` via the same Kubernetes YAML from the URLs. However,
|
||||||
`podman kube down` does 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 down` does 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`.
|
`podman kube play`.
|
||||||
|
|
||||||
|
When multiple YAML files are specified (local files, URLs, or a combination), they are processed sequentially and combined with YAML document separators (`---`), just like with `podman kube play`.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
|
|
||||||
#### **--force**
|
#### **--force**
|
||||||
@@ -67,5 +69,32 @@ Pods removed:
|
|||||||
`podman kube down` does not work with a URL if the YAML file the URL points to has been changed
|
`podman kube down` does not work with a URL if the YAML file the URL points to has been changed
|
||||||
or altered since it was used to create the pods and containers.
|
or altered since it was used to create the pods and containers.
|
||||||
|
|
||||||
|
Remove the pods and containers that were created from multiple YAML files
|
||||||
|
```
|
||||||
|
$ podman kube down pod.yml service.yml configmap.yml
|
||||||
|
Pods stopped:
|
||||||
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
|
Pods removed:
|
||||||
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the pods and containers that were created from multiple URLs
|
||||||
|
```
|
||||||
|
$ podman kube down https://example.com/pod.yml https://example.com/service.yml https://example.com/configmap.yml
|
||||||
|
Pods stopped:
|
||||||
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
|
Pods removed:
|
||||||
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the pods and containers that were created from a combination of local files and URLs
|
||||||
|
```
|
||||||
|
$ podman kube down local-pod.yml https://example.com/service.yml local-configmap.yml
|
||||||
|
Pods stopped:
|
||||||
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
|
Pods removed:
|
||||||
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
|
```
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
**[podman(1)](podman.1.md)**, **[podman-kube(1)](podman-kube.1.md)**, **[podman-kube-play(1)](podman-kube-play.1.md)**, **[podman-kube-generate(1)](podman-kube-generate.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-play(1)](podman-kube-play.1.md)**, **[podman-kube-generate(1)](podman-kube-generate.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**
|
||||||
|
|||||||
@@ -2381,6 +2381,45 @@ var _ = Describe("Podman kube play", func() {
|
|||||||
kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml")
|
kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("all arguments should be read", func() {
|
||||||
|
pods := []string{"testPod1", "testPod2", "testPod3", "testPod4"}
|
||||||
|
cmd := []string{"kube", "play"}
|
||||||
|
|
||||||
|
for _, name := range pods {
|
||||||
|
kubeYaml = filepath.Join(podmanTest.TempDir, name+".yaml")
|
||||||
|
|
||||||
|
cmd = append(cmd, kubeYaml)
|
||||||
|
|
||||||
|
pod := getPod(withPodName(name))
|
||||||
|
|
||||||
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
podmanTest.PodmanExitCleanly(cmd...)
|
||||||
|
|
||||||
|
ids := []string{}
|
||||||
|
for _, name := range pods {
|
||||||
|
inspect := podmanTest.PodmanExitCleanly(
|
||||||
|
"pod", "inspect", "--format", "{{.ID}}@{{.Name}}:{{.State}}", name,
|
||||||
|
)
|
||||||
|
output := inspect.OutputToString()
|
||||||
|
id, state, found := strings.Cut(output, "@")
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(state).To(Equal(name + ":Running"))
|
||||||
|
ids = append(ids, id)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
teardownCmd := []string{"kube", "down"}
|
||||||
|
teardownCmd = append(teardownCmd, cmd[2:]...)
|
||||||
|
teardown := podmanTest.PodmanExitCleanly(teardownCmd...)
|
||||||
|
teardownOutput := teardown.OutputToString()
|
||||||
|
for _, id := range ids {
|
||||||
|
Expect(teardownOutput).Should(ContainSubstring(id))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
It("[play kube] fail with yaml of unsupported kind", func() {
|
It("[play kube] fail with yaml of unsupported kind", func() {
|
||||||
err := writeYaml(unknownKindYaml, kubeYaml)
|
err := writeYaml(unknownKindYaml, kubeYaml)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|||||||
Reference in New Issue
Block a user