mirror of
https://github.com/docker/compose.git
synced 2025-07-16 18:24:26 +02:00
Add working dir, config files and env file in service labels
Signed-off-by: Guillaume Rose <guillaume.rose@docker.com>
This commit is contained in:
parent
1678a4fbe4
commit
dbe4d7323e
@ -13,6 +13,9 @@ from .. import config
|
|||||||
from .. import parallel
|
from .. import parallel
|
||||||
from ..config.environment import Environment
|
from ..config.environment import Environment
|
||||||
from ..const import API_VERSIONS
|
from ..const import API_VERSIONS
|
||||||
|
from ..const import LABEL_CONFIG_FILES
|
||||||
|
from ..const import LABEL_ENVIRONMENT_FILE
|
||||||
|
from ..const import LABEL_WORKING_DIR
|
||||||
from ..project import Project
|
from ..project import Project
|
||||||
from .docker_client import docker_client
|
from .docker_client import docker_client
|
||||||
from .docker_client import get_tls_version
|
from .docker_client import get_tls_version
|
||||||
@ -57,7 +60,8 @@ def project_from_options(project_dir, options, additional_options={}):
|
|||||||
environment=environment,
|
environment=environment,
|
||||||
override_dir=override_dir,
|
override_dir=override_dir,
|
||||||
compatibility=options.get('--compatibility'),
|
compatibility=options.get('--compatibility'),
|
||||||
interpolate=(not additional_options.get('--no-interpolate'))
|
interpolate=(not additional_options.get('--no-interpolate')),
|
||||||
|
environment_file=environment_file
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -125,7 +129,7 @@ def get_client(environment, verbose=False, version=None, tls_config=None, host=N
|
|||||||
|
|
||||||
def get_project(project_dir, config_path=None, project_name=None, verbose=False,
|
def get_project(project_dir, config_path=None, project_name=None, verbose=False,
|
||||||
host=None, tls_config=None, environment=None, override_dir=None,
|
host=None, tls_config=None, environment=None, override_dir=None,
|
||||||
compatibility=False, interpolate=True):
|
compatibility=False, interpolate=True, environment_file=None):
|
||||||
if not environment:
|
if not environment:
|
||||||
environment = Environment.from_env_file(project_dir)
|
environment = Environment.from_env_file(project_dir)
|
||||||
config_details = config.find(project_dir, config_path, environment, override_dir)
|
config_details = config.find(project_dir, config_path, environment, override_dir)
|
||||||
@ -145,10 +149,30 @@ def get_project(project_dir, config_path=None, project_name=None, verbose=False,
|
|||||||
|
|
||||||
with errors.handle_connection_errors(client):
|
with errors.handle_connection_errors(client):
|
||||||
return Project.from_config(
|
return Project.from_config(
|
||||||
project_name, config_data, client, environment.get('DOCKER_DEFAULT_PLATFORM')
|
project_name,
|
||||||
|
config_data,
|
||||||
|
client,
|
||||||
|
environment.get('DOCKER_DEFAULT_PLATFORM'),
|
||||||
|
execution_context_labels(config_details, environment_file),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def execution_context_labels(config_details, environment_file):
|
||||||
|
extra_labels = [
|
||||||
|
'{0}={1}'.format(LABEL_WORKING_DIR, os.path.abspath(config_details.working_dir)),
|
||||||
|
'{0}={1}'.format(LABEL_CONFIG_FILES, config_files_label(config_details)),
|
||||||
|
]
|
||||||
|
if environment_file is not None:
|
||||||
|
extra_labels.append('{0}={1}'.format(LABEL_ENVIRONMENT_FILE,
|
||||||
|
os.path.normpath(environment_file)))
|
||||||
|
return extra_labels
|
||||||
|
|
||||||
|
|
||||||
|
def config_files_label(config_details):
|
||||||
|
return ",".join(
|
||||||
|
map(str, (os.path.normpath(c.filename) for c in config_details.config_files)))
|
||||||
|
|
||||||
|
|
||||||
def get_project_name(working_dir, project_name=None, environment=None):
|
def get_project_name(working_dir, project_name=None, environment=None):
|
||||||
def normalize_name(name):
|
def normalize_name(name):
|
||||||
return re.sub(r'[^-_a-z0-9]', '', name.lower())
|
return re.sub(r'[^-_a-z0-9]', '', name.lower())
|
||||||
|
@ -11,6 +11,9 @@ IS_WINDOWS_PLATFORM = (sys.platform == "win32")
|
|||||||
LABEL_CONTAINER_NUMBER = 'com.docker.compose.container-number'
|
LABEL_CONTAINER_NUMBER = 'com.docker.compose.container-number'
|
||||||
LABEL_ONE_OFF = 'com.docker.compose.oneoff'
|
LABEL_ONE_OFF = 'com.docker.compose.oneoff'
|
||||||
LABEL_PROJECT = 'com.docker.compose.project'
|
LABEL_PROJECT = 'com.docker.compose.project'
|
||||||
|
LABEL_WORKING_DIR = 'com.docker.compose.project.working_dir'
|
||||||
|
LABEL_CONFIG_FILES = 'com.docker.compose.project.config_files'
|
||||||
|
LABEL_ENVIRONMENT_FILE = 'com.docker.compose.project.environment_file'
|
||||||
LABEL_SERVICE = 'com.docker.compose.service'
|
LABEL_SERVICE = 'com.docker.compose.service'
|
||||||
LABEL_NETWORK = 'com.docker.compose.network'
|
LABEL_NETWORK = 'com.docker.compose.network'
|
||||||
LABEL_VERSION = 'com.docker.compose.version'
|
LABEL_VERSION = 'com.docker.compose.version'
|
||||||
|
@ -83,7 +83,7 @@ class Project(object):
|
|||||||
return labels
|
return labels
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_config(cls, name, config_data, client, default_platform=None):
|
def from_config(cls, name, config_data, client, default_platform=None, extra_labels=[]):
|
||||||
"""
|
"""
|
||||||
Construct a Project from a config.Config object.
|
Construct a Project from a config.Config object.
|
||||||
"""
|
"""
|
||||||
@ -136,6 +136,7 @@ class Project(object):
|
|||||||
pid_mode=pid_mode,
|
pid_mode=pid_mode,
|
||||||
platform=service_dict.pop('platform', None),
|
platform=service_dict.pop('platform', None),
|
||||||
default_platform=default_platform,
|
default_platform=default_platform,
|
||||||
|
extra_labels=extra_labels,
|
||||||
**service_dict)
|
**service_dict)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -68,7 +68,6 @@ else:
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
HOST_CONFIG_KEYS = [
|
HOST_CONFIG_KEYS = [
|
||||||
'cap_add',
|
'cap_add',
|
||||||
'cap_drop',
|
'cap_drop',
|
||||||
@ -137,7 +136,6 @@ class NoSuchImageError(Exception):
|
|||||||
|
|
||||||
ServiceName = namedtuple('ServiceName', 'project service number')
|
ServiceName = namedtuple('ServiceName', 'project service number')
|
||||||
|
|
||||||
|
|
||||||
ConvergencePlan = namedtuple('ConvergencePlan', 'action containers')
|
ConvergencePlan = namedtuple('ConvergencePlan', 'action containers')
|
||||||
|
|
||||||
|
|
||||||
@ -173,20 +171,21 @@ class BuildAction(enum.Enum):
|
|||||||
|
|
||||||
class Service(object):
|
class Service(object):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name,
|
name,
|
||||||
client=None,
|
client=None,
|
||||||
project='default',
|
project='default',
|
||||||
use_networking=False,
|
use_networking=False,
|
||||||
links=None,
|
links=None,
|
||||||
volumes_from=None,
|
volumes_from=None,
|
||||||
network_mode=None,
|
network_mode=None,
|
||||||
networks=None,
|
networks=None,
|
||||||
secrets=None,
|
secrets=None,
|
||||||
scale=1,
|
scale=1,
|
||||||
pid_mode=None,
|
pid_mode=None,
|
||||||
default_platform=None,
|
default_platform=None,
|
||||||
**options
|
extra_labels=[],
|
||||||
|
**options
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.client = client
|
self.client = client
|
||||||
@ -201,6 +200,7 @@ class Service(object):
|
|||||||
self.scale_num = scale
|
self.scale_num = scale
|
||||||
self.default_platform = default_platform
|
self.default_platform = default_platform
|
||||||
self.options = options
|
self.options = options
|
||||||
|
self.extra_labels = extra_labels
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Service: {}>'.format(self.name)
|
return '<Service: {}>'.format(self.name)
|
||||||
@ -215,7 +215,7 @@ class Service(object):
|
|||||||
for container in self.client.containers(
|
for container in self.client.containers(
|
||||||
all=stopped,
|
all=stopped,
|
||||||
filters=filters)])
|
filters=filters)])
|
||||||
)
|
)
|
||||||
if result:
|
if result:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -404,8 +404,8 @@ class Service(object):
|
|||||||
return ConvergencePlan('start', containers)
|
return ConvergencePlan('start', containers)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
strategy is ConvergenceStrategy.always or
|
strategy is ConvergenceStrategy.always or
|
||||||
self._containers_have_diverged(containers)
|
self._containers_have_diverged(containers)
|
||||||
):
|
):
|
||||||
return ConvergencePlan('recreate', containers)
|
return ConvergencePlan('recreate', containers)
|
||||||
|
|
||||||
@ -482,6 +482,7 @@ class Service(object):
|
|||||||
container, timeout=timeout, attach_logs=not detached,
|
container, timeout=timeout, attach_logs=not detached,
|
||||||
start_new_container=start, renew_anonymous_volumes=renew_anonymous_volumes
|
start_new_container=start, renew_anonymous_volumes=renew_anonymous_volumes
|
||||||
)
|
)
|
||||||
|
|
||||||
containers, errors = parallel_execute(
|
containers, errors = parallel_execute(
|
||||||
containers,
|
containers,
|
||||||
recreate,
|
recreate,
|
||||||
@ -705,11 +706,11 @@ class Service(object):
|
|||||||
net_name = self.network_mode.service_name
|
net_name = self.network_mode.service_name
|
||||||
pid_namespace = self.pid_mode.service_name
|
pid_namespace = self.pid_mode.service_name
|
||||||
return (
|
return (
|
||||||
self.get_linked_service_names() +
|
self.get_linked_service_names() +
|
||||||
self.get_volumes_from_names() +
|
self.get_volumes_from_names() +
|
||||||
([net_name] if net_name else []) +
|
([net_name] if net_name else []) +
|
||||||
([pid_namespace] if pid_namespace else []) +
|
([pid_namespace] if pid_namespace else []) +
|
||||||
list(self.options.get('depends_on', {}).keys())
|
list(self.options.get('depends_on', {}).keys())
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_dependency_configs(self):
|
def get_dependency_configs(self):
|
||||||
@ -899,7 +900,7 @@ class Service(object):
|
|||||||
|
|
||||||
container_options['labels'] = build_container_labels(
|
container_options['labels'] = build_container_labels(
|
||||||
container_options.get('labels', {}),
|
container_options.get('labels', {}),
|
||||||
self.labels(one_off=one_off),
|
self.labels(one_off=one_off) + self.extra_labels,
|
||||||
number,
|
number,
|
||||||
self.config_hash if add_config_hash else None,
|
self.config_hash if add_config_hash else None,
|
||||||
slug
|
slug
|
||||||
@ -1552,9 +1553,9 @@ def warn_on_masked_volume(volumes_option, container_volumes, service):
|
|||||||
|
|
||||||
for volume in volumes_option:
|
for volume in volumes_option:
|
||||||
if (
|
if (
|
||||||
volume.external and
|
volume.external and
|
||||||
volume.internal in container_volumes and
|
volume.internal in container_volumes and
|
||||||
container_volumes.get(volume.internal) != volume.external
|
container_volumes.get(volume.internal) != volume.external
|
||||||
):
|
):
|
||||||
log.warning((
|
log.warning((
|
||||||
"Service \"{service}\" is using volume \"{volume}\" from the "
|
"Service \"{service}\" is using volume \"{volume}\" from the "
|
||||||
@ -1601,6 +1602,7 @@ def build_mount(mount_spec):
|
|||||||
read_only=mount_spec.read_only, consistency=mount_spec.consistency, **kwargs
|
read_only=mount_spec.read_only, consistency=mount_spec.consistency, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Labels
|
# Labels
|
||||||
|
|
||||||
|
|
||||||
@ -1655,6 +1657,7 @@ def format_environment(environment):
|
|||||||
if isinstance(value, six.binary_type):
|
if isinstance(value, six.binary_type):
|
||||||
value = value.decode('utf-8')
|
value = value.decode('utf-8')
|
||||||
return '{key}={value}'.format(key=key, value=value)
|
return '{key}={value}'.format(key=key, value=value)
|
||||||
|
|
||||||
return [format_env(*item) for item in environment.items()]
|
return [format_env(*item) for item in environment.items()]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user