mirror of
https://github.com/containers/podman-compose.git
synced 2024-11-28 19:03:40 +01:00
9a4af0ce62
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
409 lines
12 KiB
Python
409 lines
12 KiB
Python
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
import os
|
|
import unittest
|
|
|
|
from parameterized import parameterized
|
|
|
|
from podman_compose import container_to_args
|
|
from tests.unit.test_container_to_args import create_compose_mock
|
|
from tests.unit.test_container_to_args import get_minimal_container
|
|
|
|
|
|
def repo_root():
|
|
return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
|
|
|
|
|
class TestContainerToArgsSecrets(unittest.IsolatedAsyncioTestCase):
|
|
async def test_pass_secret_as_env_variable(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret": {"external": "true"} # must have external or name value
|
|
}
|
|
|
|
cnt = get_minimal_container()
|
|
cnt["secrets"] = [
|
|
{
|
|
"source": "my_secret",
|
|
"target": "ENV_SECRET",
|
|
"type": "env",
|
|
},
|
|
]
|
|
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--secret",
|
|
"my_secret,type=env,target=ENV_SECRET",
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
async def test_secret_as_env_external_true_has_no_name(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret": {
|
|
"name": "my_secret", # must have external or name value
|
|
}
|
|
}
|
|
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{
|
|
"source": "my_secret",
|
|
"target": "ENV_SECRET",
|
|
"type": "env",
|
|
}
|
|
]
|
|
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--secret",
|
|
"my_secret,type=env,target=ENV_SECRET",
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
async def test_pass_secret_as_env_variable_no_external(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret": {} # must have external or name value
|
|
}
|
|
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{
|
|
"source": "my_secret",
|
|
"target": "ENV_SECRET",
|
|
"type": "env",
|
|
}
|
|
]
|
|
|
|
with self.assertRaises(ValueError) as context:
|
|
await container_to_args(c, cnt)
|
|
self.assertIn('ERROR: unparsable secret: ', str(context.exception))
|
|
|
|
@parameterized.expand([
|
|
(
|
|
"secret_no_name",
|
|
{"my_secret": "my_secret_name", "external": "true"},
|
|
{}, # must have a name
|
|
),
|
|
(
|
|
"no_secret_name_in_declared_secrets",
|
|
{}, # must have a name
|
|
{
|
|
"source": "my_secret_name",
|
|
},
|
|
),
|
|
(
|
|
"secret_name_does_not_match_declared_secrets_name",
|
|
{
|
|
"wrong_name": "my_secret_name",
|
|
},
|
|
{
|
|
"source": "name", # secret name must match the one in declared_secrets
|
|
},
|
|
),
|
|
(
|
|
"secret_name_empty_string",
|
|
{"": "my_secret_name"},
|
|
{
|
|
"source": "", # can not be empty string
|
|
},
|
|
),
|
|
])
|
|
async def test_secret_name(self, test_name, declared_secrets, add_to_minimal_container):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = declared_secrets
|
|
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [add_to_minimal_container]
|
|
|
|
with self.assertRaises(ValueError) as context:
|
|
await container_to_args(c, cnt)
|
|
self.assertIn('ERROR: undeclared secret: ', str(context.exception))
|
|
|
|
async def test_secret_string_no_external_name_in_declared_secrets(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {"my_secret_name": {"external": "true"}}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
"my_secret_name",
|
|
]
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--secret",
|
|
"my_secret_name",
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
async def test_secret_string_options_external_name_in_declared_secrets(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret_name": {
|
|
"external": "true",
|
|
"name": "my_secret_name",
|
|
}
|
|
}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{
|
|
"source": "my_secret_name",
|
|
"target": "my_secret_name",
|
|
"uid": "103",
|
|
"gid": "103",
|
|
"mode": "400",
|
|
}
|
|
]
|
|
|
|
with self.assertLogs() as cm:
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(len(cm.output), 1)
|
|
self.assertIn('That is un-supported and a no-op and is ignored.', cm.output[0])
|
|
self.assertIn('my_secret_name', cm.output[0])
|
|
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--secret",
|
|
"my_secret_name,uid=103,gid=103,mode=400",
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
async def test_secret_string_external_name_in_declared_secrets_does_not_match_secret(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret_name": {
|
|
"external": "true",
|
|
"name": "wrong_secret_name",
|
|
}
|
|
}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
"my_secret_name",
|
|
]
|
|
|
|
with self.assertRaises(ValueError) as context:
|
|
await container_to_args(c, cnt)
|
|
self.assertIn('ERROR: Custom name/target reference ', str(context.exception))
|
|
|
|
async def test_secret_target_does_not_match_secret_name_secret_type_not_env(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret_name": {
|
|
"external": "true",
|
|
}
|
|
}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{
|
|
"source": "my_secret_name",
|
|
"target": "does_not_equal_secret_name",
|
|
"type": "does_not_equal_env",
|
|
}
|
|
]
|
|
|
|
with self.assertRaises(ValueError) as context:
|
|
await container_to_args(c, cnt)
|
|
self.assertIn('ERROR: Custom name/target reference ', str(context.exception))
|
|
|
|
async def test_secret_target_does_not_match_secret_name_secret_type_env(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret_name": {
|
|
"external": "true",
|
|
}
|
|
}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{"source": "my_secret_name", "target": "does_not_equal_secret_name", "type": "env"}
|
|
]
|
|
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--secret",
|
|
"my_secret_name,type=env,target=does_not_equal_secret_name",
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
async def test_secret_target_matches_secret_name_secret_type_not_env(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"my_secret_name": {
|
|
"external": "true",
|
|
}
|
|
}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{"source": "my_secret_name", "target": "my_secret_name", "type": "does_not_equal_env"}
|
|
]
|
|
|
|
with self.assertLogs() as cm:
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(len(cm.output), 1)
|
|
self.assertIn('That is un-supported and a no-op and is ignored.', cm.output[0])
|
|
self.assertIn('my_secret_name', cm.output[0])
|
|
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--secret",
|
|
"my_secret_name,type=does_not_equal_env",
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
@parameterized.expand([
|
|
(
|
|
"no_secret_target",
|
|
{
|
|
"file_secret": {
|
|
"file": "./my_secret",
|
|
}
|
|
},
|
|
"file_secret",
|
|
repo_root() + "/test_dirname/my_secret:/run/secrets/file_secret:ro,rprivate,rbind",
|
|
),
|
|
(
|
|
"custom_target_name",
|
|
{
|
|
"file_secret": {
|
|
"file": "./my_secret",
|
|
}
|
|
},
|
|
{
|
|
"source": "file_secret",
|
|
"target": "custom_name",
|
|
},
|
|
repo_root() + "/test_dirname/my_secret:/run/secrets/custom_name:ro,rprivate,rbind",
|
|
),
|
|
(
|
|
"no_custom_target_name",
|
|
{
|
|
"file_secret": {
|
|
"file": "./my_secret",
|
|
}
|
|
},
|
|
{
|
|
"source": "file_secret",
|
|
},
|
|
repo_root() + "/test_dirname/my_secret:/run/secrets/file_secret:ro,rprivate,rbind",
|
|
),
|
|
(
|
|
"custom_location",
|
|
{
|
|
"file_secret": {
|
|
"file": "./my_secret",
|
|
}
|
|
},
|
|
{
|
|
"source": "file_secret",
|
|
"target": "/etc/custom_location",
|
|
},
|
|
repo_root() + "/test_dirname/my_secret:/etc/custom_location:ro,rprivate,rbind",
|
|
),
|
|
])
|
|
async def test_file_secret(
|
|
self, test_name, declared_secrets, add_to_minimal_container, expected_volume_ref
|
|
):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = declared_secrets
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [add_to_minimal_container]
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--volume",
|
|
expected_volume_ref,
|
|
"busybox",
|
|
],
|
|
)
|
|
|
|
async def test_file_secret_unused_params_warning(self):
|
|
c = create_compose_mock()
|
|
c.declared_secrets = {
|
|
"file_secret": {
|
|
"file": "./my_secret",
|
|
}
|
|
}
|
|
cnt = get_minimal_container()
|
|
cnt["_service"] = "test-service"
|
|
cnt["secrets"] = [
|
|
{
|
|
"source": "file_secret",
|
|
"target": "unused_params_warning",
|
|
"uid": "103",
|
|
"gid": "103",
|
|
"mode": "400",
|
|
}
|
|
]
|
|
with self.assertLogs() as cm:
|
|
args = await container_to_args(c, cnt)
|
|
self.assertEqual(len(cm.output), 1)
|
|
self.assertIn('with uid, gid, or mode.', cm.output[0])
|
|
self.assertIn('unused_params_warning', cm.output[0])
|
|
|
|
self.assertEqual(
|
|
args,
|
|
[
|
|
"--name=project_name_service_name1",
|
|
"-d",
|
|
"--network=bridge",
|
|
"--network-alias=service_name",
|
|
"--volume",
|
|
repo_root()
|
|
+ "/test_dirname/my_secret:/run/secrets/unused_params_warning:ro,rprivate,rbind",
|
|
"busybox",
|
|
],
|
|
)
|