mirror of
https://github.com/containers/podman.git
synced 2025-05-20 08:36:23 +08:00
Kube Play - Support multi-doc YAML files for configmap argument
Read the entire YAML file in case of a multi-doc file Adjust the unit test Add a system test Add comment in the man page Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
This commit is contained in:
@ -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*
|
||||
|
||||
|
@ -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)
|
||||
@ -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
|
||||
|
@ -15,7 +15,7 @@ func TestReadConfigMapFromFile(t *testing.T) {
|
||||
configMapContent string
|
||||
expectError bool
|
||||
expectedErrorMsg string
|
||||
expected v1.ConfigMap
|
||||
expected []v1.ConfigMap
|
||||
}{
|
||||
{
|
||||
"ValidConfigMap",
|
||||
@ -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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -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",
|
||||
@ -69,7 +71,7 @@ data:
|
||||
`,
|
||||
true,
|
||||
"invalid YAML kind",
|
||||
v1.ConfigMap{},
|
||||
[]v1.ConfigMap{},
|
||||
},
|
||||
{
|
||||
"ValidBinaryDataConfigMap",
|
||||
@ -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}},
|
||||
},
|
||||
ObjectMeta: v12.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
"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",
|
||||
},
|
||||
},
|
||||
{
|
||||
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}},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user