mirror of
https://github.com/docker/compose.git
synced 2026-02-16 21:42:33 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff3a5451fe |
17
CHANGES.md
17
CHANGES.md
@@ -1,8 +1,17 @@
|
||||
Change log
|
||||
==========
|
||||
|
||||
1.2.0 (2015-04-16)
|
||||
------------------
|
||||
1.2.0rc2 (2015-03-24)
|
||||
---------------------
|
||||
|
||||
This is a release candidate for Compose 1.2.0.
|
||||
|
||||
On top of the changes listed below for RC1, a bug has been fixed where containers were being created with blank entries for "Dns" and "DnsSearch", causing DNS lookups from within a container to fail.
|
||||
|
||||
1.2.0rc1 (2015-03-23)
|
||||
---------------------
|
||||
|
||||
This is a release candidate for Compose 1.2.0.
|
||||
|
||||
- `docker-compose.yml` now supports an `extends` option, which enables a service to inherit configuration from another service in another configuration file. This is really good for sharing common configuration between apps, or for configuring the same app for different environments. Here's the [documentation](https://github.com/docker/compose/blob/master/docs/yml.md#extends).
|
||||
|
||||
@@ -10,12 +19,14 @@ Change log
|
||||
|
||||
- Repeated invocations of `docker-compose up` when using Compose with a Swarm cluster now work reliably.
|
||||
|
||||
- Directories passed to `build`, filenames passed to `env_file` and volume host paths passed to `volumes` are now treated as relative to the *directory of the configuration file*, not the directory that `docker-compose` is being run in. In the majority of cases, those are the same, but if you use the `-f|--file` argument to specify a configuration file in another directory, **this is a breaking change**.
|
||||
- Filenames in `env_file` and volume host paths in `volumes` are now treated as relative to the *directory of the configuration file*, not the directory that `docker-compose` is being run in. In the majority of cases, those are the same, but if you use the `-f|--file` argument to specify a configuration file in another directory, **this is a breaking change**.
|
||||
|
||||
- A service can now share another service's network namespace with `net: container:<service>`.
|
||||
|
||||
- `volumes_from` and `net: container:<service>` entries are taken into account when resolving dependencies, so `docker-compose up <service>` will correctly start all dependencies of `<service>`.
|
||||
|
||||
- Problems with authentication when using images from third-party registries have been fixed.
|
||||
|
||||
- `docker-compose run` now accepts a `--user` argument to specify a user to run the command as, just like `docker run`.
|
||||
|
||||
- The `up`, `stop` and `restart` commands now accept a `--timeout` (or `-t`) argument to specify how long to wait when attempting to gracefully stop containers, just like `docker stop`.
|
||||
|
||||
@@ -23,9 +23,6 @@ RUN set -ex; \
|
||||
chmod +x /usr/local/bin/docker-$v; \
|
||||
done
|
||||
|
||||
# Set the default Docker to be run
|
||||
RUN ln -s /usr/local/bin/docker-1.3.3 /usr/local/bin/docker
|
||||
|
||||
RUN useradd -d /home/user -m -s /bin/bash user
|
||||
WORKDIR /code/
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from __future__ import unicode_literals
|
||||
from .service import Service # noqa:flake8
|
||||
|
||||
__version__ = '1.2.0'
|
||||
__version__ = '1.2.0rc2'
|
||||
|
||||
@@ -171,9 +171,6 @@ def process_container_options(service_dict, working_dir=None):
|
||||
if 'volumes' in service_dict:
|
||||
service_dict['volumes'] = resolve_host_paths(service_dict['volumes'], working_dir=working_dir)
|
||||
|
||||
if 'build' in service_dict:
|
||||
service_dict['build'] = resolve_build_path(service_dict['build'], working_dir=working_dir)
|
||||
|
||||
return service_dict
|
||||
|
||||
|
||||
@@ -192,29 +189,10 @@ def merge_service_dicts(base, override):
|
||||
override.get('volumes'),
|
||||
)
|
||||
|
||||
if 'image' in override and 'build' in d:
|
||||
del d['build']
|
||||
|
||||
if 'build' in override and 'image' in d:
|
||||
del d['image']
|
||||
|
||||
list_keys = ['ports', 'expose', 'external_links']
|
||||
|
||||
for key in list_keys:
|
||||
if key in base or key in override:
|
||||
d[key] = base.get(key, []) + override.get(key, [])
|
||||
|
||||
list_or_string_keys = ['dns', 'dns_search']
|
||||
|
||||
for key in list_or_string_keys:
|
||||
if key in base or key in override:
|
||||
d[key] = to_list(base.get(key)) + to_list(override.get(key))
|
||||
|
||||
already_merged_keys = ['environment', 'volumes'] + list_keys + list_or_string_keys
|
||||
|
||||
for k in set(ALLOWED_KEYS) - set(already_merged_keys):
|
||||
if k in override:
|
||||
d[k] = override[k]
|
||||
for k in ALLOWED_KEYS:
|
||||
if k not in ['environment', 'volumes']:
|
||||
if k in override:
|
||||
d[k] = override[k]
|
||||
|
||||
return d
|
||||
|
||||
@@ -328,24 +306,11 @@ def resolve_host_paths(volumes, working_dir=None):
|
||||
def resolve_host_path(volume, working_dir):
|
||||
container_path, host_path = split_volume(volume)
|
||||
if host_path is not None:
|
||||
host_path = os.path.expanduser(host_path)
|
||||
host_path = os.path.expandvars(host_path)
|
||||
return "%s:%s" % (expand_path(working_dir, host_path), container_path)
|
||||
else:
|
||||
return container_path
|
||||
|
||||
|
||||
def resolve_build_path(build_path, working_dir=None):
|
||||
if working_dir is None:
|
||||
raise Exception("No working_dir passed to resolve_build_path")
|
||||
|
||||
_path = expand_path(working_dir, build_path)
|
||||
if not os.path.exists(_path) or not os.access(_path, os.R_OK):
|
||||
raise ConfigurationError("build path %s either does not exist or is not accessible." % _path)
|
||||
else:
|
||||
return _path
|
||||
|
||||
|
||||
def merge_volumes(base, override):
|
||||
d = dict_from_volumes(base)
|
||||
d.update(dict_from_volumes(override))
|
||||
@@ -383,15 +348,6 @@ def expand_path(working_dir, path):
|
||||
return os.path.abspath(os.path.join(working_dir, path))
|
||||
|
||||
|
||||
def to_list(value):
|
||||
if value is None:
|
||||
return []
|
||||
elif isinstance(value, six.string_types):
|
||||
return [value]
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def get_service_name_from_net(net_config):
|
||||
if not net_config:
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import absolute_import
|
||||
from collections import namedtuple
|
||||
import logging
|
||||
import re
|
||||
import os
|
||||
from operator import attrgetter
|
||||
import sys
|
||||
import six
|
||||
@@ -585,7 +586,8 @@ def parse_repository_tag(s):
|
||||
|
||||
def build_volume_binding(volume_spec):
|
||||
internal = {'bind': volume_spec.internal, 'ro': volume_spec.mode == 'ro'}
|
||||
return volume_spec.external, internal
|
||||
external = os.path.expanduser(volume_spec.external)
|
||||
return os.path.abspath(os.path.expandvars(external)), internal
|
||||
|
||||
|
||||
def build_port_bindings(ports):
|
||||
|
||||
@@ -232,14 +232,14 @@ _docker-compose_run() {
|
||||
compopt -o nospace
|
||||
return
|
||||
;;
|
||||
--entrypoint|--user|-u)
|
||||
--entrypoint)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--allow-insecure-ssl -d --entrypoint -e --no-deps --rm --service-ports -T --user -u" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--allow-insecure-ssl -d --entrypoint -e --no-deps --rm --service-ports -T" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
__docker-compose_services_all
|
||||
|
||||
@@ -17,7 +17,7 @@ On a Mac, install with `brew install bash-completion`
|
||||
|
||||
Place the completion script in `/etc/bash_completion.d/` (`/usr/local/etc/bash_completion.d/` on a Mac), using e.g.
|
||||
|
||||
curl -L https://raw.githubusercontent.com/docker/compose/1.2.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
|
||||
curl -L https://raw.githubusercontent.com/docker/compose/1.2.0rc2/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
|
||||
|
||||
Completion will be available upon next login.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ First, install Docker version 1.3 or greater:
|
||||
|
||||
To install Compose, run the following commands:
|
||||
|
||||
curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
|
||||
curl -L https://github.com/docker/compose/releases/download/1.2.0rc2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
Optionally, you can also install [command completion](completion.md) for the
|
||||
|
||||
@@ -29,9 +29,8 @@ image: a4bc65fd
|
||||
|
||||
### build
|
||||
|
||||
Path to a directory containing a Dockerfile. When the value supplied is a
|
||||
relative path, it is interpreted as relative to the location of the yml file
|
||||
itself. This directory is also the build context that is sent to the Docker daemon.
|
||||
Path to a directory containing a Dockerfile. This directory is also the
|
||||
build context that is sent to the Docker daemon.
|
||||
|
||||
Compose will build and tag it with a generated name, and use that image thereafter.
|
||||
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
TAG="docker-compose"
|
||||
docker build -t "$TAG" .
|
||||
docker run \
|
||||
--rm \
|
||||
--user=user \
|
||||
--volume="$(pwd):/code" \
|
||||
--entrypoint="script/build-linux-inner" \
|
||||
"$TAG"
|
||||
mkdir -p `pwd`/dist
|
||||
chmod 777 `pwd`/dist
|
||||
docker build -t docker-compose .
|
||||
docker run -u user -v `pwd`/dist:/code/dist --rm --entrypoint pyinstaller docker-compose -F bin/docker-compose
|
||||
mv dist/docker-compose dist/docker-compose-Linux-x86_64
|
||||
docker run -u user -v `pwd`/dist:/code/dist --rm --entrypoint dist/docker-compose-Linux-x86_64 docker-compose --version
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
mkdir -p `pwd`/dist
|
||||
chmod 777 `pwd`/dist
|
||||
|
||||
pyinstaller -F bin/docker-compose
|
||||
mv dist/docker-compose dist/docker-compose-Linux-x86_64
|
||||
dist/docker-compose-Linux-x86_64 --version
|
||||
18
script/ci
18
script/ci
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This should be run inside a container built from the Dockerfile
|
||||
# at the root of the repo:
|
||||
#
|
||||
# $ TAG="docker-compose:$(git rev-parse --short HEAD)"
|
||||
# $ docker build -t "$TAG" .
|
||||
# $ docker run --rm --volume="/var/run/docker.sock:/var/run/docker.sock" --volume="$(pwd)/.git:/code/.git" -e "TAG=$TAG" --entrypoint="script/ci" "$TAG"
|
||||
|
||||
set -e
|
||||
|
||||
>&2 echo "Validating DCO"
|
||||
script/validate-dco
|
||||
|
||||
export DOCKER_VERSIONS=all
|
||||
. script/test-versions
|
||||
|
||||
>&2 echo "Building Linux binary"
|
||||
su -c script/build-linux-inner user
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
set -e
|
||||
|
||||
>&2 echo "Validating DCO"
|
||||
script/validate-dco
|
||||
|
||||
>&2 echo "Running lint checks"
|
||||
flake8 compose
|
||||
|
||||
@@ -15,7 +18,7 @@ fi
|
||||
|
||||
for version in $DOCKER_VERSIONS; do
|
||||
>&2 echo "Running tests against Docker $version"
|
||||
docker run \
|
||||
docker-1.5.0 run \
|
||||
--rm \
|
||||
--privileged \
|
||||
--volume="/var/lib/docker" \
|
||||
|
||||
@@ -4,7 +4,7 @@ if [ "$DOCKER_VERSION" == "" ]; then
|
||||
DOCKER_VERSION="1.5.0"
|
||||
fi
|
||||
|
||||
ln -fs "/usr/local/bin/docker-$DOCKER_VERSION" "/usr/local/bin/docker"
|
||||
ln -s "/usr/local/bin/docker-$DOCKER_VERSION" "/usr/local/bin/docker"
|
||||
|
||||
# If a pidfile is still around (for example after a container restart),
|
||||
# delete it so that docker can start.
|
||||
|
||||
2
tests/fixtures/build-ctx/Dockerfile
vendored
2
tests/fixtures/build-ctx/Dockerfile
vendored
@@ -1,2 +0,0 @@
|
||||
FROM busybox:latest
|
||||
CMD echo "success"
|
||||
2
tests/fixtures/build-path/docker-compose.yml
vendored
2
tests/fixtures/build-path/docker-compose.yml
vendored
@@ -1,2 +0,0 @@
|
||||
foo:
|
||||
build: ../build-ctx/
|
||||
@@ -1,2 +1,2 @@
|
||||
service:
|
||||
build: .
|
||||
build: tests/fixtures/dockerfile_with_entrypoint
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
simple:
|
||||
build: .
|
||||
build: tests/fixtures/simple-dockerfile
|
||||
|
||||
@@ -123,24 +123,6 @@ class ServiceTest(DockerClientTestCase):
|
||||
self.assertTrue(path.basename(actual_host_path) == path.basename(host_path),
|
||||
msg=("Last component differs: %s, %s" % (actual_host_path, host_path)))
|
||||
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_create_container_with_home_and_env_var_in_volume_path(self):
|
||||
os.environ['VOLUME_NAME'] = 'my-volume'
|
||||
os.environ['HOME'] = '/tmp/home-dir'
|
||||
expected_host_path = os.path.join(os.environ['HOME'], os.environ['VOLUME_NAME'])
|
||||
|
||||
host_path = '~/${VOLUME_NAME}'
|
||||
container_path = '/container-path'
|
||||
|
||||
service = self.create_service('db', volumes=['%s:%s' % (host_path, container_path)])
|
||||
container = service.create_container()
|
||||
service.start_container(container)
|
||||
|
||||
actual_host_path = container.get('Volumes')[container_path]
|
||||
components = actual_host_path.split('/')
|
||||
self.assertTrue(components[-2:] == ['home-dir', 'my-volume'],
|
||||
msg="Last two components differ: %s, %s" % (actual_host_path, expected_host_path))
|
||||
|
||||
def test_create_container_with_volumes_from(self):
|
||||
volume_service = self.create_service('data')
|
||||
volume_container_1 = volume_service.create_container()
|
||||
|
||||
@@ -39,150 +39,46 @@ class ConfigTest(unittest.TestCase):
|
||||
config.make_service_dict('foo', {'ports': ['8000']})
|
||||
|
||||
|
||||
class VolumePathTest(unittest.TestCase):
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_volume_binding_with_environ(self):
|
||||
os.environ['VOLUME_PATH'] = '/host/path'
|
||||
d = config.make_service_dict('foo', {'volumes': ['${VOLUME_PATH}:/container/path']}, working_dir='.')
|
||||
self.assertEqual(d['volumes'], ['/host/path:/container/path'])
|
||||
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_volume_binding_with_home(self):
|
||||
os.environ['HOME'] = '/home/user'
|
||||
d = config.make_service_dict('foo', {'volumes': ['~:/container/path']}, working_dir='.')
|
||||
self.assertEqual(d['volumes'], ['/home/user:/container/path'])
|
||||
|
||||
|
||||
class MergeVolumesTest(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
class MergeTest(unittest.TestCase):
|
||||
def test_merge_volumes_empty(self):
|
||||
service_dict = config.merge_service_dicts({}, {})
|
||||
self.assertNotIn('volumes', service_dict)
|
||||
|
||||
def test_no_override(self):
|
||||
def test_merge_volumes_no_override(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'volumes': ['/foo:/code', '/data']},
|
||||
{},
|
||||
)
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/foo:/code', '/data']))
|
||||
|
||||
def test_no_base(self):
|
||||
def test_merge_volumes_no_base(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{},
|
||||
{'volumes': ['/bar:/code']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/bar:/code']))
|
||||
|
||||
def test_override_explicit_path(self):
|
||||
def test_merge_volumes_override_explicit_path(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'volumes': ['/foo:/code', '/data']},
|
||||
{'volumes': ['/bar:/code']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/bar:/code', '/data']))
|
||||
|
||||
def test_add_explicit_path(self):
|
||||
def test_merge_volumes_add_explicit_path(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'volumes': ['/foo:/code', '/data']},
|
||||
{'volumes': ['/bar:/code', '/quux:/data']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/bar:/code', '/quux:/data']))
|
||||
|
||||
def test_remove_explicit_path(self):
|
||||
def test_merge_volumes_remove_explicit_path(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'volumes': ['/foo:/code', '/quux:/data']},
|
||||
{'volumes': ['/bar:/code', '/data']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/bar:/code', '/data']))
|
||||
|
||||
def test_merge_build_or_image_no_override(self):
|
||||
self.assertEqual(
|
||||
config.merge_service_dicts({'build': '.'}, {}),
|
||||
{'build': '.'},
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
config.merge_service_dicts({'image': 'redis'}, {}),
|
||||
{'image': 'redis'},
|
||||
)
|
||||
|
||||
def test_merge_build_or_image_override_with_same(self):
|
||||
self.assertEqual(
|
||||
config.merge_service_dicts({'build': '.'}, {'build': './web'}),
|
||||
{'build': './web'},
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
config.merge_service_dicts({'image': 'redis'}, {'image': 'postgres'}),
|
||||
{'image': 'postgres'},
|
||||
)
|
||||
|
||||
def test_merge_build_or_image_override_with_other(self):
|
||||
self.assertEqual(
|
||||
config.merge_service_dicts({'build': '.'}, {'image': 'redis'}),
|
||||
{'image': 'redis'}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
config.merge_service_dicts({'image': 'redis'}, {'build': '.'}),
|
||||
{'build': '.'}
|
||||
)
|
||||
|
||||
|
||||
class MergeListsTest(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
service_dict = config.merge_service_dicts({}, {})
|
||||
self.assertNotIn('ports', service_dict)
|
||||
|
||||
def test_no_override(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'ports': ['10:8000', '9000']},
|
||||
{},
|
||||
)
|
||||
self.assertEqual(set(service_dict['ports']), set(['10:8000', '9000']))
|
||||
|
||||
def test_no_base(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{},
|
||||
{'ports': ['10:8000', '9000']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['ports']), set(['10:8000', '9000']))
|
||||
|
||||
def test_add_item(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'ports': ['10:8000', '9000']},
|
||||
{'ports': ['20:8000']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['ports']), set(['10:8000', '9000', '20:8000']))
|
||||
|
||||
|
||||
class MergeStringsOrListsTest(unittest.TestCase):
|
||||
def test_no_override(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'dns': '8.8.8.8'},
|
||||
{},
|
||||
)
|
||||
self.assertEqual(set(service_dict['dns']), set(['8.8.8.8']))
|
||||
|
||||
def test_no_base(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{},
|
||||
{'dns': '8.8.8.8'},
|
||||
)
|
||||
self.assertEqual(set(service_dict['dns']), set(['8.8.8.8']))
|
||||
|
||||
def test_add_string(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'dns': ['8.8.8.8']},
|
||||
{'dns': '9.9.9.9'},
|
||||
)
|
||||
self.assertEqual(set(service_dict['dns']), set(['8.8.8.8', '9.9.9.9']))
|
||||
|
||||
def test_add_list(self):
|
||||
service_dict = config.merge_service_dicts(
|
||||
{'dns': '8.8.8.8'},
|
||||
{'dns': ['9.9.9.9']},
|
||||
)
|
||||
self.assertEqual(set(service_dict['dns']), set(['8.8.8.8', '9.9.9.9']))
|
||||
|
||||
|
||||
class EnvTest(unittest.TestCase):
|
||||
def test_parse_environment_as_list(self):
|
||||
@@ -395,36 +291,3 @@ class ExtendsTest(unittest.TestCase):
|
||||
]
|
||||
|
||||
self.assertEqual(set(dicts[0]['volumes']), set(paths))
|
||||
|
||||
|
||||
class BuildPathTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.abs_context_path = os.path.join(os.getcwd(), 'tests/fixtures/build-ctx')
|
||||
|
||||
def test_nonexistent_path(self):
|
||||
options = {'build': 'nonexistent.path'}
|
||||
self.assertRaises(
|
||||
config.ConfigurationError,
|
||||
lambda: config.make_service_dict('foo', options, 'tests/fixtures/build-path'),
|
||||
)
|
||||
|
||||
def test_relative_path(self):
|
||||
relative_build_path = '../build-ctx/'
|
||||
service_dict = config.make_service_dict(
|
||||
'relpath',
|
||||
{'build': relative_build_path},
|
||||
working_dir='tests/fixtures/build-path'
|
||||
)
|
||||
self.assertEquals(service_dict['build'], self.abs_context_path)
|
||||
|
||||
def test_absolute_path(self):
|
||||
service_dict = config.make_service_dict(
|
||||
'abspath',
|
||||
{'build': self.abs_context_path},
|
||||
working_dir='tests/fixtures/build-path'
|
||||
)
|
||||
self.assertEquals(service_dict['build'], self.abs_context_path)
|
||||
|
||||
def test_from_file(self):
|
||||
service_dict = config.load('tests/fixtures/build-path/docker-compose.yml')
|
||||
self.assertEquals(service_dict, [{'name': 'foo', 'build': self.abs_context_path}])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
|
||||
from .. import unittest
|
||||
import mock
|
||||
@@ -300,3 +301,18 @@ class ServiceVolumesTest(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
binding,
|
||||
('/outside', dict(bind='/inside', ro=False)))
|
||||
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_build_volume_binding_with_environ(self):
|
||||
os.environ['VOLUME_PATH'] = '/opt'
|
||||
binding = build_volume_binding(parse_volume_spec('${VOLUME_PATH}:/opt'))
|
||||
self.assertEqual(binding, ('/opt', dict(bind='/opt', ro=False)))
|
||||
|
||||
@mock.patch.dict(os.environ)
|
||||
def test_building_volume_binding_with_home(self):
|
||||
os.environ['HOME'] = '/home/user'
|
||||
binding = build_volume_binding(parse_volume_spec('~:/home/user'))
|
||||
self.assertEqual(
|
||||
binding,
|
||||
('/home/user', dict(bind='/home/user', ro=False)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user