|
@@ -6,7 +6,6 @@ import logging
|
|
|
from functools import reduce
|
|
|
|
|
|
from docker.errors import APIError
|
|
|
-from docker.errors import NotFound
|
|
|
|
|
|
from . import parallel
|
|
|
from .config import ConfigurationError
|
|
@@ -28,7 +27,7 @@ from .service import NetworkMode
|
|
|
from .service import Service
|
|
|
from .service import ServiceNetworkMode
|
|
|
from .utils import microseconds_from_time_nano
|
|
|
-from .volume import Volume
|
|
|
+from .volume import ProjectVolumes
|
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
@@ -42,7 +41,7 @@ class Project(object):
|
|
|
self.name = name
|
|
|
self.services = services
|
|
|
self.client = client
|
|
|
- self.volumes = volumes or {}
|
|
|
+ self.volumes = volumes or ProjectVolumes({})
|
|
|
self.networks = networks or ProjectNetworks({}, False)
|
|
|
|
|
|
def labels(self, one_off=False):
|
|
@@ -62,16 +61,8 @@ class Project(object):
|
|
|
config_data.services,
|
|
|
networks,
|
|
|
use_networking)
|
|
|
- project = cls(name, [], client, project_networks)
|
|
|
-
|
|
|
- if config_data.volumes:
|
|
|
- for vol_name, data in config_data.volumes.items():
|
|
|
- project.volumes[vol_name] = Volume(
|
|
|
- client=client, project=name, name=vol_name,
|
|
|
- driver=data.get('driver'),
|
|
|
- driver_opts=data.get('driver_opts'),
|
|
|
- external_name=data.get('external_name')
|
|
|
- )
|
|
|
+ volumes = ProjectVolumes.from_config(name, config_data, client)
|
|
|
+ project = cls(name, [], client, project_networks, volumes)
|
|
|
|
|
|
for service_dict in config_data.services:
|
|
|
service_dict = dict(service_dict)
|
|
@@ -86,13 +77,10 @@ class Project(object):
|
|
|
volumes_from = get_volumes_from(project, service_dict)
|
|
|
|
|
|
if config_data.version != V1:
|
|
|
- service_volumes = service_dict.get('volumes', [])
|
|
|
- for volume_spec in service_volumes:
|
|
|
- if volume_spec.is_named_volume:
|
|
|
- declared_volume = project.volumes[volume_spec.external]
|
|
|
- service_volumes[service_volumes.index(volume_spec)] = (
|
|
|
- volume_spec._replace(external=declared_volume.full_name)
|
|
|
- )
|
|
|
+ service_dict['volumes'] = [
|
|
|
+ volumes.namespace_spec(volume_spec)
|
|
|
+ for volume_spec in service_dict.get('volumes', [])
|
|
|
+ ]
|
|
|
|
|
|
project.services.append(
|
|
|
Service(
|
|
@@ -233,49 +221,13 @@ class Project(object):
|
|
|
def remove_stopped(self, service_names=None, **options):
|
|
|
parallel.parallel_remove(self.containers(service_names, stopped=True), options)
|
|
|
|
|
|
- def initialize_volumes(self):
|
|
|
- try:
|
|
|
- for volume in self.volumes.values():
|
|
|
- if volume.external:
|
|
|
- log.debug(
|
|
|
- 'Volume {0} declared as external. No new '
|
|
|
- 'volume will be created.'.format(volume.name)
|
|
|
- )
|
|
|
- if not volume.exists():
|
|
|
- raise ConfigurationError(
|
|
|
- 'Volume {name} declared as external, but could'
|
|
|
- ' not be found. Please create the volume manually'
|
|
|
- ' using `{command}{name}` and try again.'.format(
|
|
|
- name=volume.full_name,
|
|
|
- command='docker volume create --name='
|
|
|
- )
|
|
|
- )
|
|
|
- continue
|
|
|
- volume.create()
|
|
|
- except NotFound:
|
|
|
- raise ConfigurationError(
|
|
|
- 'Volume %s specifies nonexistent driver %s' % (volume.name, volume.driver)
|
|
|
- )
|
|
|
- except APIError as e:
|
|
|
- if 'Choose a different volume name' in str(e):
|
|
|
- raise ConfigurationError(
|
|
|
- 'Configuration for volume {0} specifies driver {1}, but '
|
|
|
- 'a volume with the same name uses a different driver '
|
|
|
- '({3}). If you wish to use the new configuration, please '
|
|
|
- 'remove the existing volume "{2}" first:\n'
|
|
|
- '$ docker volume rm {2}'.format(
|
|
|
- volume.name, volume.driver, volume.full_name,
|
|
|
- volume.inspect()['Driver']
|
|
|
- )
|
|
|
- )
|
|
|
-
|
|
|
def down(self, remove_image_type, include_volumes):
|
|
|
self.stop()
|
|
|
self.remove_stopped(v=include_volumes)
|
|
|
self.networks.remove()
|
|
|
|
|
|
if include_volumes:
|
|
|
- self.remove_volumes()
|
|
|
+ self.volumes.remove()
|
|
|
|
|
|
self.remove_images(remove_image_type)
|
|
|
|
|
@@ -283,10 +235,6 @@ class Project(object):
|
|
|
for service in self.get_services():
|
|
|
service.remove_image(remove_image_type)
|
|
|
|
|
|
- def remove_volumes(self):
|
|
|
- for volume in self.volumes.values():
|
|
|
- volume.remove()
|
|
|
-
|
|
|
def restart(self, service_names=None, **options):
|
|
|
containers = self.containers(service_names, stopped=True)
|
|
|
parallel.parallel_restart(containers, options)
|
|
@@ -371,7 +319,7 @@ class Project(object):
|
|
|
|
|
|
def initialize(self):
|
|
|
self.networks.initialize()
|
|
|
- self.initialize_volumes()
|
|
|
+ self.volumes.initialize()
|
|
|
|
|
|
def _get_convergence_plans(self, services, strategy):
|
|
|
plans = {}
|