Skip to content

Commit

Permalink
Merge pull request #18538 from ygalblum/play-multiple-configmaps
Browse files Browse the repository at this point in the history
Kube Play - Support multi-doc YAML files for configmap argument
  • Loading branch information
openshift-merge-robot authored May 11, 2023
2 parents 50db106 + 26f1e95 commit 20b15f0
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 35 deletions.
1 change: 1 addition & 0 deletions docs/source/markdown/podman-kube-play.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Build images even if they are found in the local storage. Use `--build=false` to
Use Kubernetes configmap YAML at path to provide a source for environment variable values within the containers of the pod. (This option is not available with the remote Podman client)

Note: The *--configmap* option can be used multiple times or a comma-separated list of paths can be used to pass multiple Kubernetes configmap YAMLs.
The YAML file may be in a multi-doc YAML format. But, it must container only configmaps

#### **--context-dir**=*path*

Expand Down
43 changes: 30 additions & 13 deletions pkg/domain/infra/abi/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,16 +524,18 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
defer f.Close()

cm, err := readConfigMapFromFile(f)
cms, err := readConfigMapFromFile(f)
if err != nil {
return nil, nil, fmt.Errorf("%q: %w", p, err)
}

if _, present := configMapIndex[cm.Name]; present {
return nil, nil, fmt.Errorf("ambiguous configuration: the same config map %s is present in YAML and in --configmaps %s file", cm.Name, p)
}
for _, cm := range cms {
if _, present := configMapIndex[cm.Name]; present {
return nil, nil, fmt.Errorf("ambiguous configuration: the same config map %s is present in YAML and in --configmaps %s file", cm.Name, p)
}

configMaps = append(configMaps, cm)
configMaps = append(configMaps, cm)
}
}

mountLabel, err := getMountLabel(podYAML.Spec.SecurityContext)
Expand Down Expand Up @@ -1152,23 +1154,38 @@ func (ic *ContainerEngine) importVolume(ctx context.Context, vol *libpod.Volume,
}

// readConfigMapFromFile returns a kubernetes configMap obtained from --configmap flag
func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) {
var cm v1.ConfigMap
func readConfigMapFromFile(r io.Reader) ([]v1.ConfigMap, error) {
configMaps := make([]v1.ConfigMap, 0)

content, err := io.ReadAll(r)
if err != nil {
return cm, fmt.Errorf("unable to read ConfigMap YAML content: %w", err)
return nil, fmt.Errorf("unable to read ConfigMap YAML content: %w", err)
}

if err := yaml.Unmarshal(content, &cm); err != nil {
return cm, fmt.Errorf("unable to read YAML as Kube ConfigMap: %w", err)
// split yaml document
documentList, err := splitMultiDocYAML(content)
if err != nil {
return nil, fmt.Errorf("unable to read as kube YAML: %w", err)
}

if cm.Kind != "ConfigMap" {
return cm, fmt.Errorf("invalid YAML kind: %q. [ConfigMap] is the only supported by --configmap", cm.Kind)
for _, document := range documentList {
kind, err := getKubeKind(document)
if err != nil {
return nil, fmt.Errorf("unable to read as kube YAML: %w", err)
}

if kind != "ConfigMap" {
return nil, fmt.Errorf("invalid YAML kind: %q. [ConfigMap] is the only supported by --configmap", kind)
}

var configMap v1.ConfigMap
if err := yaml.Unmarshal(document, &configMap); err != nil {
return nil, fmt.Errorf("unable to read YAML as Kube ConfigMap: %w", err)
}
configMaps = append(configMaps, configMap)
}

return cm, nil
return configMaps, nil
}

// splitMultiDocYAML reads multiple documents in a YAML file and
Expand Down
97 changes: 75 additions & 22 deletions pkg/domain/infra/abi/play_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestReadConfigMapFromFile(t *testing.T) {
configMapContent string
expectError bool
expectedErrorMsg string
expected v1.ConfigMap
expected []v1.ConfigMap
}{
{
"ValidConfigMap",
Expand All @@ -29,16 +29,18 @@ data:
`,
false,
"",
v1.ConfigMap{
TypeMeta: v12.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: v12.ObjectMeta{
Name: "foo",
},
Data: map[string]string{
"myvar": "foo",
[]v1.ConfigMap{
{
TypeMeta: v12.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: v12.ObjectMeta{
Name: "foo",
},
Data: map[string]string{
"myvar": "foo",
},
},
},
},
Expand All @@ -54,8 +56,8 @@ data:
myvar: foo
`,
true,
"unable to read YAML as Kube ConfigMap",
v1.ConfigMap{},
"unable to read as kube YAML",
[]v1.ConfigMap{},
},
{
"InvalidKind",
Expand All @@ -69,7 +71,7 @@ data:
`,
true,
"invalid YAML kind",
v1.ConfigMap{},
[]v1.ConfigMap{},
},
{
"ValidBinaryDataConfigMap",
Expand All @@ -83,15 +85,64 @@ binaryData:
`,
false,
"",
v1.ConfigMap{
TypeMeta: v12.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
[]v1.ConfigMap{
{
TypeMeta: v12.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: v12.ObjectMeta{
Name: "foo",
},
BinaryData: map[string][]byte{"data.zip": {0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0xc9, 0xbb, 0x4a, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, 0x54, 0x0d, 0x00, 0x07, 0xea, 0x8e, 0x44, 0x63, 0x3b, 0x8f, 0x44, 0x63, 0xea, 0x8e, 0x44, 0x63, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x4b, 0xca, 0xcc, 0x4b, 0x2c, 0xaa, 0x54, 0x48, 0x49, 0x2c, 0x49, 0xe4, 0x02, 0x00, 0x50, 0x4b, 0x07, 0x08, 0xdd, 0x09, 0xd9, 0xa0, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0xc9, 0xbb, 0x4a, 0x55, 0xdd, 0x09, 0xd9, 0xa0, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, 0x54, 0x0d, 0x00, 0x07, 0xea, 0x8e, 0x44, 0x63, 0x3b, 0x8f, 0x44, 0x63, 0xea, 0x8e, 0x44, 0x63, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x56, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00}},
},
},
},
{
"MultiDocConfigMapFile",
`
---
apiVersion: v1
kind: ConfigMap
metadata:
name: foo
data:
myvar: foo
---
apiVersion: v1
kind: ConfigMap
metadata:
name: bar
data:
myvar: bar
`,
false,
"",
[]v1.ConfigMap{
{
TypeMeta: v12.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: v12.ObjectMeta{
Name: "foo",
},
Data: map[string]string{
"myvar": "foo",
},
},
ObjectMeta: v12.ObjectMeta{
Name: "foo",
{
TypeMeta: v12.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: v12.ObjectMeta{
Name: "bar",
},
Data: map[string]string{
"myvar": "bar",
},
},
BinaryData: map[string][]byte{"data.zip": {0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0xc9, 0xbb, 0x4a, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, 0x54, 0x0d, 0x00, 0x07, 0xea, 0x8e, 0x44, 0x63, 0x3b, 0x8f, 0x44, 0x63, 0xea, 0x8e, 0x44, 0x63, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x4b, 0xca, 0xcc, 0x4b, 0x2c, 0xaa, 0x54, 0x48, 0x49, 0x2c, 0x49, 0xe4, 0x02, 0x00, 0x50, 0x4b, 0x07, 0x08, 0xdd, 0x09, 0xd9, 0xa0, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0xc9, 0xbb, 0x4a, 0x55, 0xdd, 0x09, 0xd9, 0xa0, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, 0x54, 0x0d, 0x00, 0x07, 0xea, 0x8e, 0x44, 0x63, 0x3b, 0x8f, 0x44, 0x63, 0xea, 0x8e, 0x44, 0x63, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x04, 0xe8, 0x03, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x56, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00}},
},
},
}
Expand All @@ -107,7 +158,9 @@ binaryData:
assert.Contains(t, err.Error(), test.expectedErrorMsg)
} else {
assert.NoError(t, err)
assert.Equal(t, test.expected, cm)
for _, expected := range test.expected {
assert.Contains(t, cm, expected)
}
}
})
}
Expand Down
60 changes: 60 additions & 0 deletions test/system/700-play.bats
Original file line number Diff line number Diff line change
Expand Up @@ -651,3 +651,63 @@ spec:
run_podman pod ps
run_podman rmi $(pause_image)
}

@test "podman kube play with configmaps" {
skip_if_remote "the configmap argument is supported only locally"

configmap_file=${PODMAN_TMPDIR}/play_kube_configmap_configmaps$(random_string 6).yaml
echo "
---
apiVersion: v1
kind: ConfigMap
metadata:
name: foo
data:
value: foo
---
apiVersion: v1
kind: ConfigMap
metadata:
name: bar
data:
value: bar
" > $configmap_file

pod_file=${PODMAN_TMPDIR}/play_kube_configmap_pod$(random_string 6).yaml
echo "
apiVersion: v1
kind: Pod
metadata:
labels:
app: test
name: test_pod
spec:
restartPolicy: Never
containers:
- name: server
image: $IMAGE
env:
- name: FOO
valueFrom:
configMapKeyRef:
name: foo
key: value
- name: BAR
valueFrom:
configMapKeyRef:
name: bar
key: value
command:
- /bin/sh
args:
- -c
- "echo \$FOO:\$BAR"
" > $pod_file

run_podman kube play --configmap=$configmap_file $pod_file
run_podman wait test_pod-server
run_podman logs test_pod-server
is $output "foo:bar"

run_podman kube down $pod_file
}

0 comments on commit 20b15f0

Please sign in to comment.