command.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import contextlib
  4. import logging
  5. import os
  6. import re
  7. import six
  8. from requests.exceptions import ConnectionError
  9. from requests.exceptions import SSLError
  10. from . import errors
  11. from . import verbose_proxy
  12. from .. import __version__
  13. from .. import config
  14. from ..project import Project
  15. from ..service import ConfigError
  16. from .docker_client import docker_client
  17. from .utils import call_silently
  18. from .utils import is_mac
  19. from .utils import is_ubuntu
  20. log = logging.getLogger(__name__)
  21. @contextlib.contextmanager
  22. def friendly_error_message():
  23. try:
  24. yield
  25. except SSLError as e:
  26. raise errors.UserError('SSL error: %s' % e)
  27. except ConnectionError:
  28. if call_silently(['which', 'docker']) != 0:
  29. if is_mac():
  30. raise errors.DockerNotFoundMac()
  31. elif is_ubuntu():
  32. raise errors.DockerNotFoundUbuntu()
  33. else:
  34. raise errors.DockerNotFoundGeneric()
  35. elif call_silently(['which', 'docker-machine']) == 0:
  36. raise errors.ConnectionErrorDockerMachine()
  37. else:
  38. raise errors.ConnectionErrorGeneric(get_client().base_url)
  39. def project_from_options(base_dir, options):
  40. return get_project(
  41. base_dir,
  42. get_config_path(options.get('--file')),
  43. project_name=options.get('--project-name'),
  44. verbose=options.get('--verbose'),
  45. use_networking=options.get('--x-networking'),
  46. network_driver=options.get('--x-network-driver'),
  47. )
  48. def get_config_path(file_option):
  49. if file_option:
  50. return file_option
  51. if 'FIG_FILE' in os.environ:
  52. log.warn('The FIG_FILE environment variable is deprecated.')
  53. log.warn('Please use COMPOSE_FILE instead.')
  54. config_file = os.environ.get('COMPOSE_FILE') or os.environ.get('FIG_FILE')
  55. return [config_file] if config_file else None
  56. def get_client(verbose=False, version=None):
  57. client = docker_client(version=version)
  58. if verbose:
  59. version_info = six.iteritems(client.version())
  60. log.info("Compose version %s", __version__)
  61. log.info("Docker base_url: %s", client.base_url)
  62. log.info("Docker version: %s",
  63. ", ".join("%s=%s" % item for item in version_info))
  64. return verbose_proxy.VerboseProxy('docker', client)
  65. return client
  66. def get_project(base_dir, config_path=None, project_name=None, verbose=False,
  67. use_networking=False, network_driver=None):
  68. config_details = config.find(base_dir, config_path)
  69. api_version = '1.21' if use_networking else None
  70. try:
  71. return Project.from_dicts(
  72. get_project_name(config_details.working_dir, project_name),
  73. config.load(config_details),
  74. get_client(verbose=verbose, version=api_version),
  75. use_networking=use_networking,
  76. network_driver=network_driver,
  77. )
  78. except ConfigError as e:
  79. raise errors.UserError(six.text_type(e))
  80. def get_project_name(working_dir, project_name=None):
  81. def normalize_name(name):
  82. return re.sub(r'[^a-z0-9]', '', name.lower())
  83. if 'FIG_PROJECT_NAME' in os.environ:
  84. log.warn('The FIG_PROJECT_NAME environment variable is deprecated.')
  85. log.warn('Please use COMPOSE_PROJECT_NAME instead.')
  86. project_name = (
  87. project_name or
  88. os.environ.get('COMPOSE_PROJECT_NAME') or
  89. os.environ.get('FIG_PROJECT_NAME'))
  90. if project_name is not None:
  91. return normalize_name(project_name)
  92. project = os.path.basename(os.path.abspath(working_dir))
  93. if project:
  94. return normalize_name(project)
  95. return 'default'