Răsfoiți Sursa

Merge pull request #1158 from chernjie/addhosts

Add extra_hosts to yml configuration --add-hosts
Aanand Prasad 10 ani în urmă
părinte
comite
16f8106149
4 a modificat fișierele cu 111 adăugiri și 1 ștergeri
  1. 4 0
      compose/config.py
  2. 29 0
      compose/service.py
  3. 17 0
      docs/yml.md
  4. 61 1
      tests/integration/service_test.py

+ 4 - 0
compose/config.py

@@ -15,6 +15,7 @@ DOCKER_CONFIG_KEYS = [
     'entrypoint',
     'env_file',
     'environment',
+    'extra_hosts',
     'hostname',
     'image',
     'links',
@@ -41,6 +42,9 @@ ALLOWED_KEYS = DOCKER_CONFIG_KEYS + [
 
 DOCKER_CONFIG_HINTS = {
     'cpu_share': 'cpu_shares',
+    'add_host': 'extra_hosts',
+    'hosts': 'extra_hosts',
+    'extra_host': 'extra_hosts',
     'link': 'links',
     'port': 'ports',
     'privilege': 'privileged',

+ 29 - 0
compose/service.py

@@ -23,6 +23,7 @@ DOCKER_START_KEYS = [
     'dns',
     'dns_search',
     'env_file',
+    'extra_hosts',
     'net',
     'pid',
     'privileged',
@@ -448,6 +449,8 @@ class Service(object):
 
         restart = parse_restart_spec(options.get('restart', None))
 
+        extra_hosts = build_extra_hosts(options.get('extra_hosts', None))
+
         return create_host_config(
             links=self._get_links(link_to_self=one_off),
             port_bindings=port_bindings,
@@ -460,6 +463,7 @@ class Service(object):
             restart_policy=restart,
             cap_add=cap_add,
             cap_drop=cap_drop,
+            extra_hosts=extra_hosts,
             pid_mode=pid
         )
 
@@ -619,3 +623,28 @@ def split_port(port):
 
     external_ip, external_port, internal_port = parts
     return internal_port, (external_ip, external_port or None)
+
+
+def build_extra_hosts(extra_hosts_config):
+    if not extra_hosts_config:
+        return {}
+
+    if isinstance(extra_hosts_config, list):
+        extra_hosts_dict = {}
+        for extra_hosts_line in extra_hosts_config:
+            if not isinstance(extra_hosts_line, six.string_types):
+                raise ConfigError(
+                    "extra_hosts_config \"%s\" must be either a list of strings or a string->string mapping," %
+                    extra_hosts_config
+                )
+            host, ip = extra_hosts_line.split(':')
+            extra_hosts_dict.update({host.strip(): ip.strip()})
+        extra_hosts_config = extra_hosts_dict
+
+    if isinstance(extra_hosts_config, dict):
+        return extra_hosts_config
+
+    raise ConfigError(
+        "extra_hosts_config \"%s\" must be either a list of strings or a string->string mapping," %
+        extra_hosts_config
+    )

+ 17 - 0
docs/yml.md

@@ -87,6 +87,23 @@ external_links:
  - project_db_1:postgresql
 ```
 
+### extra_hosts
+
+Add hostname mappings. Use the same values as the docker client `--add-host` parameter.
+
+```
+extra_hosts:
+ - "somehost:162.242.195.82"
+ - "otherhost:50.31.209.229"
+```
+
+An entry with the ip address and hostname will be created in `/etc/hosts` inside containers for this service, e.g:
+
+```
+162.242.195.82  somehost
+50.31.209.229   otherhost
+```
+
 ### ports
 
 Expose ports. Either specify both ports (`HOST:CONTAINER`), or just the container

+ 61 - 1
tests/integration/service_test.py

@@ -5,7 +5,11 @@ from os import path
 import mock
 
 from compose import Service
-from compose.service import CannotBeScaledError
+from compose.service import (
+    CannotBeScaledError,
+    build_extra_hosts,
+    ConfigError,
+)
 from compose.container import Container
 from docker.errors import APIError
 from .testcases import DockerClientTestCase
@@ -107,6 +111,62 @@ class ServiceTest(DockerClientTestCase):
         service.start_container(container)
         self.assertEqual(container.inspect()['Config']['CpuShares'], 73)
 
+    def test_build_extra_hosts(self):
+        # string
+        self.assertRaises(ConfigError, lambda: build_extra_hosts("www.example.com: 192.168.0.17"))
+
+        # list of strings
+        self.assertEqual(build_extra_hosts(
+            ["www.example.com:192.168.0.17"]),
+            {'www.example.com': '192.168.0.17'})
+        self.assertEqual(build_extra_hosts(
+            ["www.example.com: 192.168.0.17"]),
+            {'www.example.com': '192.168.0.17'})
+        self.assertEqual(build_extra_hosts(
+            ["www.example.com: 192.168.0.17",
+             "static.example.com:192.168.0.19",
+             "api.example.com: 192.168.0.18"]),
+            {'www.example.com': '192.168.0.17',
+             'static.example.com': '192.168.0.19',
+             'api.example.com': '192.168.0.18'})
+
+        # list of dictionaries
+        self.assertRaises(ConfigError, lambda: build_extra_hosts(
+            [{'www.example.com': '192.168.0.17'},
+             {'api.example.com': '192.168.0.18'}]))
+
+        # dictionaries
+        self.assertEqual(build_extra_hosts(
+            {'www.example.com': '192.168.0.17',
+             'api.example.com': '192.168.0.18'}),
+            {'www.example.com': '192.168.0.17',
+             'api.example.com': '192.168.0.18'})
+
+    def test_create_container_with_extra_hosts_list(self):
+        extra_hosts = ['somehost:162.242.195.82', 'otherhost:50.31.209.229']
+        service = self.create_service('db', extra_hosts=extra_hosts)
+        container = service.create_container()
+        service.start_container(container)
+        self.assertEqual(set(container.get('HostConfig.ExtraHosts')), set(extra_hosts))
+
+    def test_create_container_with_extra_hosts_string(self):
+        extra_hosts = 'somehost:162.242.195.82'
+        service = self.create_service('db', extra_hosts=extra_hosts)
+        self.assertRaises(ConfigError, lambda: service.create_container())
+
+    def test_create_container_with_extra_hosts_list_of_dicts(self):
+        extra_hosts = [{'somehost': '162.242.195.82'}, {'otherhost': '50.31.209.229'}]
+        service = self.create_service('db', extra_hosts=extra_hosts)
+        self.assertRaises(ConfigError, lambda: service.create_container())
+
+    def test_create_container_with_extra_hosts_dicts(self):
+        extra_hosts = {'somehost': '162.242.195.82', 'otherhost': '50.31.209.229'}
+        extra_hosts_list = ['somehost:162.242.195.82', 'otherhost:50.31.209.229']
+        service = self.create_service('db', extra_hosts=extra_hosts)
+        container = service.create_container()
+        service.start_container(container)
+        self.assertEqual(set(container.get('HostConfig.ExtraHosts')), set(extra_hosts_list))
+
     def test_create_container_with_specified_volume(self):
         host_path = '/tmp/host-path'
         container_path = '/container-path'