Interpret 'build:' as relative to the yml file

* This fix introduces one side-effect: the build parameter is now
validated early, when the service dicionary is first constructed.
That leads to less scary stack traces when the path is not valid.

* The tests for the changes introduced here alter the fixtures
of those (otherwise unrelated) tests that make use of the 'build:'
parameter)

Signed-off-by: Moysés Borges Furtado <moyses.furtado@wplex.com.br>
This commit is contained in:
Moysés Borges 2015-03-29 17:06:35 -03:00 committed by Moysés Borges Furtado
parent e3e2247159
commit 8584525e8d
7 changed files with 56 additions and 4 deletions

View File

@ -171,6 +171,9 @@ 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
@ -330,6 +333,17 @@ def resolve_host_path(volume, working_dir):
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))

View File

@ -29,8 +29,9 @@ image: a4bc65fd
### build
Path to a directory containing a Dockerfile. This directory is also the
build context that is sent to the Docker daemon.
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.
Compose will build and tag it with a generated name, and use that image thereafter.

2
tests/fixtures/build-ctx/Dockerfile vendored Normal file
View File

@ -0,0 +1,2 @@
FROM busybox:latest
CMD echo "success"

View File

@ -0,0 +1,2 @@
foo:
build: ../build-ctx/

View File

@ -1,2 +1,2 @@
service:
build: tests/fixtures/dockerfile_with_entrypoint
build: .

View File

@ -1,2 +1,2 @@
simple:
build: tests/fixtures/simple-dockerfile
build: .

View File

@ -383,3 +383,36 @@ 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}])