diff --git a/docker/utils/__init__.py b/docker/utils/__init__.py index 81cc8a68..6189ed83 100644 --- a/docker/utils/__init__.py +++ b/docker/utils/__init__.py @@ -2,7 +2,7 @@ from .utils import ( compare_version, convert_port_bindings, convert_volume_binds, mkbuildcontext, tar, parse_repository_tag, parse_host, kwargs_from_env, convert_filters, create_host_config, - create_container_config, parse_bytes, ping_registry + create_container_config, parse_bytes, ping_registry, parse_env_file ) # flake8: noqa from .types import Ulimit, LogConfig # flake8: noqa diff --git a/docker/utils/utils.py b/docker/utils/utils.py index a714c97c..3cd6760a 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -518,6 +518,32 @@ def create_host_config( return host_config +def parse_env_file(env_file): + """ + Reads a line-separated environment file. + The format of each line should be "key=value". + """ + environment = {} + + with open(env_file, 'r') as f: + for line in f: + + if line[0] == '#': + continue + + parse_line = line.strip().split('=') + if len(parse_line) == 2: + k = parse_line[0] + v = parse_line[1] + environment[k] = v + else: + raise errors.DockerException( + 'Invalid line in environment file {0}:\n{1}'.format( + env_file, line)) + + return environment + + def create_container_config( version, image, command, hostname=None, user=None, detach=False, stdin_open=False, tty=False, mem_limit=None, ports=None, environment=None, @@ -528,6 +554,7 @@ def create_container_config( ): if isinstance(command, six.string_types): command = shlex.split(str(command)) + if isinstance(environment, dict): environment = [ six.text_type('{0}={1}').format(k, v) diff --git a/docs/api.md b/docs/api.md index bccd5268..b9b29c5a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -234,6 +234,27 @@ from. Optionally a single string joining container id's with commas 'Warnings': None} ``` +### parse_env_file + +A utility for parsing an environment file. + +The expected format of the file is as follows: + +``` +USERNAME=jdoe +PASSWORD=secret +``` + +The utility can be used as follows: + +```python +>> import docker.utils +>> my_envs = docker.utils.parse_env_file('/path/to/file') +>> docker.utils.create_container_config('1.18', '_mongodb', 'foobar', environment=my_envs) +``` + +You can now use this with 'environment' for `create_container`. + ## diff Inspect changes on a container's filesystem diff --git a/tests/utils_test.py b/tests/utils_test.py index 1c8729ca..a73d949e 100644 --- a/tests/utils_test.py +++ b/tests/utils_test.py @@ -1,12 +1,13 @@ import os import os.path import unittest +import tempfile from docker.client import Client from docker.errors import DockerException from docker.utils import ( parse_repository_tag, parse_host, convert_filters, kwargs_from_env, - create_host_config, Ulimit, LogConfig, parse_bytes + create_host_config, Ulimit, LogConfig, parse_bytes, parse_env_file ) from docker.utils.ports import build_port_bindings, split_port from docker.auth import resolve_repository_name, resolve_authconfig @@ -17,6 +18,17 @@ import base class UtilsTest(base.BaseTestCase): longMessage = True + def generate_tempfile(self, file_content=None): + """ + Generates a temporary file for tests with the content + of 'file_content' and returns the filename. + Don't forget to unlink the file with os.unlink() after. + """ + local_tempfile = tempfile.NamedTemporaryFile(delete=False) + local_tempfile.write(file_content.encode('UTF-8')) + local_tempfile.close() + return local_tempfile.name + def setUp(self): self.os_environ = os.environ.copy() @@ -95,6 +107,28 @@ class UtilsTest(base.BaseTestCase): except TypeError as e: self.fail(e) + def test_parse_env_file_proper(self): + env_file = self.generate_tempfile( + file_content='USER=jdoe\nPASS=secret') + get_parse_env_file = parse_env_file(env_file) + self.assertEqual(get_parse_env_file, + {'USER': 'jdoe', 'PASS': 'secret'}) + os.unlink(env_file) + + def test_parse_env_file_commented_line(self): + env_file = self.generate_tempfile( + file_content='USER=jdoe\n#PASS=secret') + get_parse_env_file = parse_env_file((env_file)) + self.assertEqual(get_parse_env_file, {'USER': 'jdoe'}) + os.unlink(env_file) + + def test_parse_env_file_invalid_line(self): + env_file = self.generate_tempfile( + file_content='USER jdoe') + self.assertRaises( + DockerException, parse_env_file, env_file) + os.unlink(env_file) + def test_convert_filters(self): tests = [ ({'dangling': True}, '{"dangling": ["true"]}'),