mirror of
https://github.com/containers/podman.git
synced 2025-08-06 11:32:07 +08:00
Support env variables based on ConfigMaps sent in payload
Fixes #12363 Signed-off-by: Jakub Dzon <jdzon@redhat.com>
This commit is contained in:
@ -16,6 +16,7 @@ Currently, the supported Kubernetes kinds are:
|
||||
- Pod
|
||||
- Deployment
|
||||
- PersistentVolumeClaim
|
||||
- ConfigMap
|
||||
|
||||
`Kubernetes Pods or Deployments`
|
||||
|
||||
@ -68,6 +69,40 @@ like:
|
||||
The build will consider `foobar` to be the context directory for the build. If there is an image in local storage
|
||||
called `foobar`, the image will not be built unless the `--build` flag is used.
|
||||
|
||||
`Kubernetes ConfigMap`
|
||||
|
||||
Kubernetes ConfigMap can be referred as a source of environment variables in Pods or Deployments.
|
||||
|
||||
For example ConfigMap defined in following YAML:
|
||||
```
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo
|
||||
data:
|
||||
FOO: bar
|
||||
```
|
||||
|
||||
can be referred in a Pod in following way:
|
||||
```
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
...
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- top
|
||||
name: container-1
|
||||
image: foobar
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: foo
|
||||
optional: false
|
||||
```
|
||||
|
||||
and as a result environment variable `FOO` will be set to `bar` for container `container-1`.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
#### **--authfile**=*path*
|
||||
|
@ -57,6 +57,8 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
|
||||
|
||||
ipIndex := 0
|
||||
|
||||
var configMaps []v1.ConfigMap
|
||||
|
||||
// create pod on each document if it is a pod or deployment
|
||||
// any other kube kind will be skipped
|
||||
for _, document := range documentList {
|
||||
@ -77,7 +79,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
|
||||
podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
|
||||
podTemplateSpec.Spec = podYAML.Spec
|
||||
|
||||
r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex, podYAML.Annotations)
|
||||
r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options, &ipIndex, podYAML.Annotations, configMaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -91,7 +93,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
|
||||
return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
|
||||
}
|
||||
|
||||
r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex)
|
||||
r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -112,6 +114,13 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
|
||||
|
||||
report.Volumes = append(report.Volumes, r.Volumes...)
|
||||
validKinds++
|
||||
case "ConfigMap":
|
||||
var configMap v1.ConfigMap
|
||||
|
||||
if err := yaml.Unmarshal(document, &configMap); err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to read YAML %q as Kube ConfigMap", path)
|
||||
}
|
||||
configMaps = append(configMaps, configMap)
|
||||
default:
|
||||
logrus.Infof("Kube kind %s not supported", kind)
|
||||
continue
|
||||
@ -125,7 +134,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int) (*entities.PlayKubeReport, error) {
|
||||
func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int, configMaps []v1.ConfigMap) (*entities.PlayKubeReport, error) {
|
||||
var (
|
||||
deploymentName string
|
||||
podSpec v1.PodTemplateSpec
|
||||
@ -147,7 +156,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM
|
||||
// create "replicas" number of pods
|
||||
for i = 0; i < numReplicas; i++ {
|
||||
podName := fmt.Sprintf("%s-pod-%d", deploymentName, i)
|
||||
podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, deploymentYAML.Annotations)
|
||||
podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, deploymentYAML.Annotations, configMaps)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error encountered while bringing up pod %s", podName)
|
||||
}
|
||||
@ -156,7 +165,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM
|
||||
return &report, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions, ipIndex *int, annotations map[string]string) (*entities.PlayKubeReport, error) {
|
||||
func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions, ipIndex *int, annotations map[string]string, configMaps []v1.ConfigMap) (*entities.PlayKubeReport, error) {
|
||||
var (
|
||||
writer io.Writer
|
||||
playKubePod entities.PlayKubePod
|
||||
@ -252,7 +261,10 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||
ctrRestartPolicy = define.RestartPolicyAlways
|
||||
}
|
||||
|
||||
configMaps := []v1.ConfigMap{}
|
||||
configMapIndex := make(map[string]struct{})
|
||||
for _, configMap := range configMaps {
|
||||
configMapIndex[configMap.Name] = struct{}{}
|
||||
}
|
||||
for _, p := range options.ConfigMaps {
|
||||
f, err := os.Open(p)
|
||||
if err != nil {
|
||||
@ -265,6 +277,10 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||
return nil, errors.Wrapf(err, "%q", p)
|
||||
}
|
||||
|
||||
if _, present := configMapIndex[cm.Name]; present {
|
||||
return nil, errors.Errorf("ambiguous configuration: the same config map %s is present in YAML and in --configmaps %s file", cm.Name, p)
|
||||
}
|
||||
|
||||
configMaps = append(configMaps, cm)
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,13 @@ package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/containers/podman/v3/pkg/bindings"
|
||||
"github.com/containers/podman/v3/pkg/bindings/play"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@ -436,6 +441,41 @@ spec:
|
||||
{{ end }}
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
{{ range .Env }}
|
||||
- name: {{ .Name }}
|
||||
{{ if (eq .ValueFrom "configmap") }}
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: {{ .RefName }}
|
||||
key: {{ .RefKey }}
|
||||
optional: {{ .Optional }}
|
||||
{{ end }}
|
||||
{{ if (eq .ValueFrom "secret") }}
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .RefName }}
|
||||
key: {{ .RefKey }}
|
||||
optional: {{ .Optional }}
|
||||
{{ end }}
|
||||
{{ if (eq .ValueFrom "") }}
|
||||
value: {{ .Value }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ with .EnvFrom}}
|
||||
envFrom:
|
||||
{{ range . }}
|
||||
{{ if (eq .From "configmap") }}
|
||||
- configMapRef:
|
||||
name: {{ .Name }}
|
||||
optional: {{ .Optional }}
|
||||
{{ end }}
|
||||
{{ if (eq .From "secret") }}
|
||||
- secretRef:
|
||||
name: {{ .Name }}
|
||||
optional: {{ .Optional }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
image: {{ .Image }}
|
||||
name: {{ .Name }}
|
||||
imagePullPolicy: {{ .PullPolicy }}
|
||||
@ -2908,4 +2948,277 @@ ENV OPENJ9_JAVA_OPTIONS=%q
|
||||
})
|
||||
})
|
||||
|
||||
Context("with configmap in multi-doc yaml", func() {
|
||||
It("podman play kube uses env value", func() {
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false))))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
||||
})
|
||||
|
||||
It("podman play kube fails for required env value with missing key", func() {
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", false))))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).To(ExitWithError())
|
||||
})
|
||||
|
||||
It("podman play kube succeeds for optional env value with missing key", func() {
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", true))))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`[FOO=]`))
|
||||
})
|
||||
|
||||
It("podman play kube uses all key-value pairs as envs", func() {
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2"))
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap", false))))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`))
|
||||
})
|
||||
|
||||
It("podman play kube deployment uses variable from config map", func() {
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false))))
|
||||
|
||||
deployment := getDeployment(withPod(pod))
|
||||
deploymentYaml, err := getKubeYaml("deployment", deployment)
|
||||
yamls := []string{cmYaml, deploymentYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", fmt.Sprintf("%s-%s-%s", deployment.Name, "pod-0", defaultCtrName), "--format", "'{{ .Config }}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
||||
|
||||
})
|
||||
|
||||
It("podman play kube uses env value from configmap for HTTP API client", func() {
|
||||
SkipIfRemote("cannot run in a remote setup")
|
||||
address := url.URL{
|
||||
Scheme: "tcp",
|
||||
Host: net.JoinHostPort("localhost", randomPort()),
|
||||
}
|
||||
|
||||
session := podmanTest.Podman([]string{
|
||||
"system", "service", "--log-level=debug", "--time=0", address.String(),
|
||||
})
|
||||
defer session.Kill()
|
||||
|
||||
WaitForService(address)
|
||||
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false))))
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
podmanConnection, err := bindings.NewConnection(context.Background(), address.String())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = play.Kube(podmanConnection, kubeYaml, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
||||
})
|
||||
})
|
||||
|
||||
Context("with configmap in multi-doc yaml and files", func() {
|
||||
It("podman play kube uses env values from both sources", func() {
|
||||
SkipIfRemote("--configmaps is not supported for remote")
|
||||
|
||||
fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
||||
fsCm := getConfigMap(withConfigMapName("fooFs"), withConfigMapData("FOO_FS", "fooFS"))
|
||||
err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(
|
||||
withEnv("FOO_FS", "", "configmap", "fooFs", "FOO_FS", false),
|
||||
withEnv("FOO", "", "configmap", "foo", "FOO", false),
|
||||
)))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", fsCmYamlPathname})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(And(
|
||||
ContainSubstring(`FOO=foo`),
|
||||
ContainSubstring(`FOO_FS=fooFS`),
|
||||
))
|
||||
})
|
||||
|
||||
It("podman play kube uses all env values from both sources", func() {
|
||||
SkipIfRemote("--configmaps is not supported for remote")
|
||||
|
||||
fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
||||
fsCm := getConfigMap(withConfigMapName("fooFs"),
|
||||
withConfigMapData("FOO_FS_1", "fooFS1"),
|
||||
withConfigMapData("FOO_FS_2", "fooFS2"))
|
||||
err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
cm := getConfigMap(withConfigMapName("foo"),
|
||||
withConfigMapData("FOO_1", "foo1"),
|
||||
withConfigMapData("FOO_2", "foo2"),
|
||||
)
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(
|
||||
withEnvFrom("foo", "configmap", false),
|
||||
withEnvFrom("fooFs", "configmap", false),
|
||||
)))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", fsCmYamlPathname})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(And(
|
||||
ContainSubstring(`FOO_1=foo1`),
|
||||
ContainSubstring(`FOO_2=foo2`),
|
||||
ContainSubstring(`FOO_FS_1=fooFS1`),
|
||||
ContainSubstring(`FOO_FS_2=fooFS2`),
|
||||
))
|
||||
})
|
||||
|
||||
It("podman play kube reports error when the same configmap name is present in both sources", func() {
|
||||
SkipIfRemote("--configmaps is not supported for remote")
|
||||
|
||||
fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
||||
fsCm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "fooFS"))
|
||||
err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||
|
||||
cmYaml, err := getKubeYaml("configmap", cm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
pod := getPod(withCtr(getCtr(
|
||||
withEnv("FOO", "", "configmap", "foo", "FOO", false),
|
||||
)))
|
||||
|
||||
podYaml, err := getKubeYaml("pod", pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
yamls := []string{cmYaml, podYaml}
|
||||
err = generateMultiDocKubeYaml(yamls, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", fsCmYamlPathname})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(125))
|
||||
Expect(kube.ErrorToString()).To(ContainSubstring("ambiguous configuration: the same config map foo is present in YAML and in --configmaps"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user