mirror of https://github.com/docker/compose.git
Merge pull request #1232 from aleksandr-vin/add-parent-directories-search-for-default-compose-files
Add parent directories search for default compose-files
This commit is contained in:
commit
89789c54ad
|
@ -10,7 +10,7 @@ from .. import config
|
||||||
from ..project import Project
|
from ..project import Project
|
||||||
from ..service import ConfigError
|
from ..service import ConfigError
|
||||||
from .docopt_command import DocoptCommand
|
from .docopt_command import DocoptCommand
|
||||||
from .utils import call_silently, is_mac, is_ubuntu
|
from .utils import call_silently, is_mac, is_ubuntu, find_candidates_in_parent_dirs
|
||||||
from .docker_client import docker_client
|
from .docker_client import docker_client
|
||||||
from . import verbose_proxy
|
from . import verbose_proxy
|
||||||
from . import errors
|
from . import errors
|
||||||
|
@ -18,6 +18,13 @@ from .. import __version__
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SUPPORTED_FILENAMES = [
|
||||||
|
'docker-compose.yml',
|
||||||
|
'docker-compose.yaml',
|
||||||
|
'fig.yml',
|
||||||
|
'fig.yaml',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Command(DocoptCommand):
|
class Command(DocoptCommand):
|
||||||
base_dir = '.'
|
base_dir = '.'
|
||||||
|
@ -100,20 +107,10 @@ class Command(DocoptCommand):
|
||||||
if file_path:
|
if file_path:
|
||||||
return os.path.join(self.base_dir, file_path)
|
return os.path.join(self.base_dir, file_path)
|
||||||
|
|
||||||
supported_filenames = [
|
(candidates, path) = find_candidates_in_parent_dirs(SUPPORTED_FILENAMES, self.base_dir)
|
||||||
'docker-compose.yml',
|
|
||||||
'docker-compose.yaml',
|
|
||||||
'fig.yml',
|
|
||||||
'fig.yaml',
|
|
||||||
]
|
|
||||||
|
|
||||||
def expand(filename):
|
|
||||||
return os.path.join(self.base_dir, filename)
|
|
||||||
|
|
||||||
candidates = [filename for filename in supported_filenames if os.path.exists(expand(filename))]
|
|
||||||
|
|
||||||
if len(candidates) == 0:
|
if len(candidates) == 0:
|
||||||
raise errors.ComposeFileNotFound(supported_filenames)
|
raise errors.ComposeFileNotFound(SUPPORTED_FILENAMES)
|
||||||
|
|
||||||
winner = candidates[0]
|
winner = candidates[0]
|
||||||
|
|
||||||
|
@ -130,4 +127,4 @@ class Command(DocoptCommand):
|
||||||
log.warning("%s is deprecated and will not be supported in future. "
|
log.warning("%s is deprecated and will not be supported in future. "
|
||||||
"Please rename your config file to docker-compose.yml\n" % winner)
|
"Please rename your config file to docker-compose.yml\n" % winner)
|
||||||
|
|
||||||
return expand(winner)
|
return os.path.join(path, winner)
|
||||||
|
|
|
@ -58,7 +58,7 @@ class ConnectionErrorGeneric(UserError):
|
||||||
class ComposeFileNotFound(UserError):
|
class ComposeFileNotFound(UserError):
|
||||||
def __init__(self, supported_filenames):
|
def __init__(self, supported_filenames):
|
||||||
super(ComposeFileNotFound, self).__init__("""
|
super(ComposeFileNotFound, self).__init__("""
|
||||||
Can't find a suitable configuration file. Are you in the right directory?
|
Can't find a suitable configuration file in this directory or any parent. Are you in the right directory?
|
||||||
|
|
||||||
Supported filenames: %s
|
Supported filenames: %s
|
||||||
""" % ", ".join(supported_filenames))
|
""" % ", ".join(supported_filenames))
|
||||||
|
|
|
@ -62,6 +62,25 @@ def mkdir(path, permissions=0o700):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def find_candidates_in_parent_dirs(filenames, path):
|
||||||
|
"""
|
||||||
|
Given a directory path to start, looks for filenames in the
|
||||||
|
directory, and then each parent directory successively,
|
||||||
|
until found.
|
||||||
|
|
||||||
|
Returns tuple (candidates, path).
|
||||||
|
"""
|
||||||
|
candidates = [filename for filename in filenames
|
||||||
|
if os.path.exists(os.path.join(path, filename))]
|
||||||
|
|
||||||
|
if len(candidates) == 0:
|
||||||
|
parent_dir = os.path.join(path, '..')
|
||||||
|
if os.path.abspath(parent_dir) != os.path.abspath(path):
|
||||||
|
return find_candidates_in_parent_dirs(filenames, parent_dir)
|
||||||
|
|
||||||
|
return (candidates, path)
|
||||||
|
|
||||||
|
|
||||||
def split_buffer(reader, separator):
|
def split_buffer(reader, separator):
|
||||||
"""
|
"""
|
||||||
Given a generator which yields strings and a separator string,
|
Given a generator which yields strings and a separator string,
|
||||||
|
|
|
@ -136,7 +136,10 @@ By default, if there are existing containers for a service, `docker-compose up`
|
||||||
|
|
||||||
### -f, --file FILE
|
### -f, --file FILE
|
||||||
|
|
||||||
Specifies an alternate Compose yaml file (default: `docker-compose.yml`)
|
Specify what file to read configuration from. If not provided, Compose will look
|
||||||
|
for `docker-compose.yml` in the current working directory, and then each parent
|
||||||
|
directory successively, until found.
|
||||||
|
|
||||||
|
|
||||||
### -p, --project-name NAME
|
### -p, --project-name NAME
|
||||||
|
|
||||||
|
@ -157,7 +160,9 @@ Sets the project name, which is prepended to the name of every container started
|
||||||
|
|
||||||
### COMPOSE\_FILE
|
### COMPOSE\_FILE
|
||||||
|
|
||||||
Sets the path to the `docker-compose.yml` to use. Defaults to `docker-compose.yml` in the current working directory.
|
Specify what file to read configuration from. If not provided, Compose will look
|
||||||
|
for `docker-compose.yml` in the current working directory, and then each parent
|
||||||
|
directory successively, until found.
|
||||||
|
|
||||||
### DOCKER\_HOST
|
### DOCKER\_HOST
|
||||||
|
|
||||||
|
|
|
@ -62,30 +62,32 @@ class CLITestCase(unittest.TestCase):
|
||||||
self.assertEquals(project_name, name)
|
self.assertEquals(project_name, name)
|
||||||
|
|
||||||
def test_filename_check(self):
|
def test_filename_check(self):
|
||||||
self.assertEqual('docker-compose.yml', get_config_filename_for_files([
|
files = [
|
||||||
'docker-compose.yml',
|
'docker-compose.yml',
|
||||||
'docker-compose.yaml',
|
'docker-compose.yaml',
|
||||||
'fig.yml',
|
'fig.yml',
|
||||||
'fig.yaml',
|
'fig.yaml',
|
||||||
]))
|
]
|
||||||
|
|
||||||
self.assertEqual('docker-compose.yaml', get_config_filename_for_files([
|
"""Test with files placed in the basedir"""
|
||||||
'docker-compose.yaml',
|
|
||||||
'fig.yml',
|
|
||||||
'fig.yaml',
|
|
||||||
]))
|
|
||||||
|
|
||||||
self.assertEqual('fig.yml', get_config_filename_for_files([
|
|
||||||
'fig.yml',
|
|
||||||
'fig.yaml',
|
|
||||||
]))
|
|
||||||
|
|
||||||
self.assertEqual('fig.yaml', get_config_filename_for_files([
|
|
||||||
'fig.yaml',
|
|
||||||
]))
|
|
||||||
|
|
||||||
|
self.assertEqual('docker-compose.yml', get_config_filename_for_files(files[0:]))
|
||||||
|
self.assertEqual('docker-compose.yaml', get_config_filename_for_files(files[1:]))
|
||||||
|
self.assertEqual('fig.yml', get_config_filename_for_files(files[2:]))
|
||||||
|
self.assertEqual('fig.yaml', get_config_filename_for_files(files[3:]))
|
||||||
self.assertRaises(ComposeFileNotFound, lambda: get_config_filename_for_files([]))
|
self.assertRaises(ComposeFileNotFound, lambda: get_config_filename_for_files([]))
|
||||||
|
|
||||||
|
"""Test with files placed in the subdir"""
|
||||||
|
|
||||||
|
def get_config_filename_for_files_in_subdir(files):
|
||||||
|
return get_config_filename_for_files(files, subdir=True)
|
||||||
|
|
||||||
|
self.assertEqual('docker-compose.yml', get_config_filename_for_files_in_subdir(files[0:]))
|
||||||
|
self.assertEqual('docker-compose.yaml', get_config_filename_for_files_in_subdir(files[1:]))
|
||||||
|
self.assertEqual('fig.yml', get_config_filename_for_files_in_subdir(files[2:]))
|
||||||
|
self.assertEqual('fig.yaml', get_config_filename_for_files_in_subdir(files[3:]))
|
||||||
|
self.assertRaises(ComposeFileNotFound, lambda: get_config_filename_for_files_in_subdir([]))
|
||||||
|
|
||||||
def test_get_project(self):
|
def test_get_project(self):
|
||||||
command = TopLevelCommand()
|
command = TopLevelCommand()
|
||||||
command.base_dir = 'tests/fixtures/longer-filename-composefile'
|
command.base_dir = 'tests/fixtures/longer-filename-composefile'
|
||||||
|
@ -184,11 +186,14 @@ class CLITestCase(unittest.TestCase):
|
||||||
self.assertFalse('RestartPolicy' in call_kwargs['host_config'])
|
self.assertFalse('RestartPolicy' in call_kwargs['host_config'])
|
||||||
|
|
||||||
|
|
||||||
def get_config_filename_for_files(filenames):
|
def get_config_filename_for_files(filenames, subdir=None):
|
||||||
project_dir = tempfile.mkdtemp()
|
project_dir = tempfile.mkdtemp()
|
||||||
try:
|
try:
|
||||||
make_files(project_dir, filenames)
|
make_files(project_dir, filenames)
|
||||||
command = TopLevelCommand()
|
command = TopLevelCommand()
|
||||||
|
if subdir:
|
||||||
|
command.base_dir = tempfile.mkdtemp(dir=project_dir)
|
||||||
|
else:
|
||||||
command.base_dir = project_dir
|
command.base_dir = project_dir
|
||||||
return os.path.basename(command.get_config_path())
|
return os.path.basename(command.get_config_path())
|
||||||
finally:
|
finally:
|
||||||
|
|
Loading…
Reference in New Issue