mirror of https://github.com/docker/docs.git
Add enum34 and use it to create a ConvergenceStrategy enum.
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
This commit is contained in:
parent
d4372bc98f
commit
0484e22a84
|
@ -19,6 +19,7 @@ from ..progress_stream import StreamOutputError
|
||||||
from ..project import ConfigurationError
|
from ..project import ConfigurationError
|
||||||
from ..project import NoSuchService
|
from ..project import NoSuchService
|
||||||
from ..service import BuildError
|
from ..service import BuildError
|
||||||
|
from ..service import ConvergenceStrategy
|
||||||
from ..service import NeedsBuildError
|
from ..service import NeedsBuildError
|
||||||
from .command import Command
|
from .command import Command
|
||||||
from .docopt_command import NoSuchCommand
|
from .docopt_command import NoSuchCommand
|
||||||
|
@ -332,7 +333,7 @@ class TopLevelCommand(Command):
|
||||||
project.up(
|
project.up(
|
||||||
service_names=deps,
|
service_names=deps,
|
||||||
start_deps=True,
|
start_deps=True,
|
||||||
allow_recreate=False,
|
strategy=ConvergenceStrategy.never,
|
||||||
)
|
)
|
||||||
|
|
||||||
tty = True
|
tty = True
|
||||||
|
@ -515,29 +516,20 @@ class TopLevelCommand(Command):
|
||||||
if options['--allow-insecure-ssl']:
|
if options['--allow-insecure-ssl']:
|
||||||
log.warn(INSECURE_SSL_WARNING)
|
log.warn(INSECURE_SSL_WARNING)
|
||||||
|
|
||||||
detached = options['-d']
|
|
||||||
|
|
||||||
monochrome = options['--no-color']
|
monochrome = options['--no-color']
|
||||||
|
|
||||||
start_deps = not options['--no-deps']
|
start_deps = not options['--no-deps']
|
||||||
allow_recreate = not options['--no-recreate']
|
|
||||||
force_recreate = options['--force-recreate']
|
|
||||||
service_names = options['SERVICE']
|
service_names = options['SERVICE']
|
||||||
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
|
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
|
||||||
|
|
||||||
if force_recreate and not allow_recreate:
|
|
||||||
raise UserError("--force-recreate and --no-recreate cannot be combined.")
|
|
||||||
|
|
||||||
to_attach = project.up(
|
to_attach = project.up(
|
||||||
service_names=service_names,
|
service_names=service_names,
|
||||||
start_deps=start_deps,
|
start_deps=start_deps,
|
||||||
allow_recreate=allow_recreate,
|
strategy=convergence_strategy_from_opts(options),
|
||||||
force_recreate=force_recreate,
|
|
||||||
do_build=not options['--no-build'],
|
do_build=not options['--no-build'],
|
||||||
timeout=timeout
|
timeout=timeout
|
||||||
)
|
)
|
||||||
|
|
||||||
if not detached:
|
if not options['-d']:
|
||||||
log_printer = build_log_printer(to_attach, service_names, monochrome)
|
log_printer = build_log_printer(to_attach, service_names, monochrome)
|
||||||
attach_to_logs(project, log_printer, service_names, timeout)
|
attach_to_logs(project, log_printer, service_names, timeout)
|
||||||
|
|
||||||
|
@ -582,6 +574,21 @@ class TopLevelCommand(Command):
|
||||||
print(get_version_info('full'))
|
print(get_version_info('full'))
|
||||||
|
|
||||||
|
|
||||||
|
def convergence_strategy_from_opts(options):
|
||||||
|
no_recreate = options['--no-recreate']
|
||||||
|
force_recreate = options['--force-recreate']
|
||||||
|
if force_recreate and no_recreate:
|
||||||
|
raise UserError("--force-recreate and --no-recreate cannot be combined.")
|
||||||
|
|
||||||
|
if force_recreate:
|
||||||
|
return ConvergenceStrategy.always
|
||||||
|
|
||||||
|
if no_recreate:
|
||||||
|
return ConvergenceStrategy.never
|
||||||
|
|
||||||
|
return ConvergenceStrategy.changed
|
||||||
|
|
||||||
|
|
||||||
def build_log_printer(containers, service_names, monochrome):
|
def build_log_printer(containers, service_names, monochrome):
|
||||||
if service_names:
|
if service_names:
|
||||||
containers = [c for c in containers if c.service in service_names]
|
containers = [c for c in containers if c.service in service_names]
|
||||||
|
|
|
@ -15,6 +15,7 @@ from .const import LABEL_SERVICE
|
||||||
from .container import Container
|
from .container import Container
|
||||||
from .legacy import check_for_legacy_containers
|
from .legacy import check_for_legacy_containers
|
||||||
from .service import ContainerNet
|
from .service import ContainerNet
|
||||||
|
from .service import ConvergenceStrategy
|
||||||
from .service import Net
|
from .service import Net
|
||||||
from .service import Service
|
from .service import Service
|
||||||
from .service import ServiceNet
|
from .service import ServiceNet
|
||||||
|
@ -266,24 +267,16 @@ class Project(object):
|
||||||
def up(self,
|
def up(self,
|
||||||
service_names=None,
|
service_names=None,
|
||||||
start_deps=True,
|
start_deps=True,
|
||||||
allow_recreate=True,
|
strategy=ConvergenceStrategy.changed,
|
||||||
force_recreate=False,
|
|
||||||
do_build=True,
|
do_build=True,
|
||||||
timeout=DEFAULT_TIMEOUT):
|
timeout=DEFAULT_TIMEOUT):
|
||||||
|
|
||||||
if force_recreate and not allow_recreate:
|
|
||||||
raise ValueError("force_recreate and allow_recreate are in conflict")
|
|
||||||
|
|
||||||
services = self.get_services(service_names, include_deps=start_deps)
|
services = self.get_services(service_names, include_deps=start_deps)
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
service.remove_duplicate_containers()
|
service.remove_duplicate_containers()
|
||||||
|
|
||||||
plans = self._get_convergence_plans(
|
plans = self._get_convergence_plans(services, strategy)
|
||||||
services,
|
|
||||||
allow_recreate=allow_recreate,
|
|
||||||
force_recreate=force_recreate,
|
|
||||||
)
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
container
|
container
|
||||||
|
@ -295,11 +288,7 @@ class Project(object):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
def _get_convergence_plans(self,
|
def _get_convergence_plans(self, services, strategy):
|
||||||
services,
|
|
||||||
allow_recreate=True,
|
|
||||||
force_recreate=False):
|
|
||||||
|
|
||||||
plans = {}
|
plans = {}
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
|
@ -310,20 +299,13 @@ class Project(object):
|
||||||
and plans[name].action == 'recreate'
|
and plans[name].action == 'recreate'
|
||||||
]
|
]
|
||||||
|
|
||||||
if updated_dependencies and allow_recreate:
|
if updated_dependencies and strategy.allows_recreate:
|
||||||
log.debug(
|
log.debug('%s has upstream changes (%s)',
|
||||||
'%s has upstream changes (%s)',
|
service.name,
|
||||||
service.name, ", ".join(updated_dependencies),
|
", ".join(updated_dependencies))
|
||||||
)
|
plan = service.convergence_plan(ConvergenceStrategy.always)
|
||||||
plan = service.convergence_plan(
|
|
||||||
allow_recreate=allow_recreate,
|
|
||||||
force_recreate=True,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
plan = service.convergence_plan(
|
plan = service.convergence_plan(strategy)
|
||||||
allow_recreate=allow_recreate,
|
|
||||||
force_recreate=force_recreate,
|
|
||||||
)
|
|
||||||
|
|
||||||
plans[service.name] = plan
|
plans[service.name] = plan
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import sys
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
|
import enum
|
||||||
import six
|
import six
|
||||||
from docker.errors import APIError
|
from docker.errors import APIError
|
||||||
from docker.utils import create_host_config
|
from docker.utils import create_host_config
|
||||||
|
@ -86,6 +87,20 @@ ServiceName = namedtuple('ServiceName', 'project service number')
|
||||||
ConvergencePlan = namedtuple('ConvergencePlan', 'action containers')
|
ConvergencePlan = namedtuple('ConvergencePlan', 'action containers')
|
||||||
|
|
||||||
|
|
||||||
|
@enum.unique
|
||||||
|
class ConvergenceStrategy(enum.Enum):
|
||||||
|
"""Enumeration for all possible convergence strategies. Values refer to
|
||||||
|
when containers should be recreated.
|
||||||
|
"""
|
||||||
|
changed = 1
|
||||||
|
always = 2
|
||||||
|
never = 3
|
||||||
|
|
||||||
|
@property
|
||||||
|
def allows_recreate(self):
|
||||||
|
return self is not type(self).never
|
||||||
|
|
||||||
|
|
||||||
class Service(object):
|
class Service(object):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -326,22 +341,19 @@ class Service(object):
|
||||||
else:
|
else:
|
||||||
return self.options['image']
|
return self.options['image']
|
||||||
|
|
||||||
def convergence_plan(self,
|
def convergence_plan(self, strategy=ConvergenceStrategy.changed):
|
||||||
allow_recreate=True,
|
|
||||||
force_recreate=False):
|
|
||||||
|
|
||||||
if force_recreate and not allow_recreate:
|
|
||||||
raise ValueError("force_recreate and allow_recreate are in conflict")
|
|
||||||
|
|
||||||
containers = self.containers(stopped=True)
|
containers = self.containers(stopped=True)
|
||||||
|
|
||||||
if not containers:
|
if not containers:
|
||||||
return ConvergencePlan('create', [])
|
return ConvergencePlan('create', [])
|
||||||
|
|
||||||
if not allow_recreate:
|
if strategy is ConvergenceStrategy.never:
|
||||||
return ConvergencePlan('start', containers)
|
return ConvergencePlan('start', containers)
|
||||||
|
|
||||||
if force_recreate or self._containers_have_diverged(containers):
|
if (
|
||||||
|
strategy is ConvergenceStrategy.always or
|
||||||
|
self._containers_have_diverged(containers)
|
||||||
|
):
|
||||||
return ConvergencePlan('recreate', containers)
|
return ConvergencePlan('recreate', containers)
|
||||||
|
|
||||||
stopped = [c for c in containers if not c.is_running]
|
stopped = [c for c in containers if not c.is_running]
|
||||||
|
|
|
@ -206,7 +206,7 @@ At this point, you have seen the basics of how Compose works.
|
||||||
|
|
||||||
## Release Notes
|
## Release Notes
|
||||||
|
|
||||||
To see a detailed list of changes for past and current releases of Docker
|
To see a detailed list of changes for past and current releases of Docker
|
||||||
Compose, please refer to the [CHANGELOG](https://github.com/docker/compose/blob/master/CHANGELOG.md).
|
Compose, please refer to the [CHANGELOG](https://github.com/docker/compose/blob/master/CHANGELOG.md).
|
||||||
|
|
||||||
## Getting help
|
## Getting help
|
||||||
|
|
|
@ -2,6 +2,7 @@ PyYAML==3.10
|
||||||
docker-py==1.3.1
|
docker-py==1.3.1
|
||||||
dockerpty==0.3.4
|
dockerpty==0.3.4
|
||||||
docopt==0.6.1
|
docopt==0.6.1
|
||||||
|
enum34==1.0.4
|
||||||
jsonschema==2.5.1
|
jsonschema==2.5.1
|
||||||
requests==2.7.0
|
requests==2.7.0
|
||||||
six==1.7.3
|
six==1.7.3
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -45,8 +45,9 @@ tests_require = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[:1] < (3,):
|
if sys.version_info[:2] < (3, 4):
|
||||||
tests_require.append('mock >= 1.0.1')
|
tests_require.append('mock >= 1.0.1')
|
||||||
|
install_requires.append('enum34 >= 1.0.4, < 2')
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
|
|
@ -223,7 +223,7 @@ class CLITestCase(DockerClientTestCase):
|
||||||
self.assertTrue(config['AttachStdin'])
|
self.assertTrue(config['AttachStdin'])
|
||||||
|
|
||||||
@mock.patch('dockerpty.start')
|
@mock.patch('dockerpty.start')
|
||||||
def test_run_service_with_links(self, __):
|
def test_run_service_with_links(self, _):
|
||||||
self.command.base_dir = 'tests/fixtures/links-composefile'
|
self.command.base_dir = 'tests/fixtures/links-composefile'
|
||||||
self.command.dispatch(['run', 'web', '/bin/true'], None)
|
self.command.dispatch(['run', 'web', '/bin/true'], None)
|
||||||
db = self.project.get_service('db')
|
db = self.project.get_service('db')
|
||||||
|
@ -232,14 +232,14 @@ class CLITestCase(DockerClientTestCase):
|
||||||
self.assertEqual(len(console.containers()), 0)
|
self.assertEqual(len(console.containers()), 0)
|
||||||
|
|
||||||
@mock.patch('dockerpty.start')
|
@mock.patch('dockerpty.start')
|
||||||
def test_run_with_no_deps(self, __):
|
def test_run_with_no_deps(self, _):
|
||||||
self.command.base_dir = 'tests/fixtures/links-composefile'
|
self.command.base_dir = 'tests/fixtures/links-composefile'
|
||||||
self.command.dispatch(['run', '--no-deps', 'web', '/bin/true'], None)
|
self.command.dispatch(['run', '--no-deps', 'web', '/bin/true'], None)
|
||||||
db = self.project.get_service('db')
|
db = self.project.get_service('db')
|
||||||
self.assertEqual(len(db.containers()), 0)
|
self.assertEqual(len(db.containers()), 0)
|
||||||
|
|
||||||
@mock.patch('dockerpty.start')
|
@mock.patch('dockerpty.start')
|
||||||
def test_run_does_not_recreate_linked_containers(self, __):
|
def test_run_does_not_recreate_linked_containers(self, _):
|
||||||
self.command.base_dir = 'tests/fixtures/links-composefile'
|
self.command.base_dir = 'tests/fixtures/links-composefile'
|
||||||
self.command.dispatch(['up', '-d', 'db'], None)
|
self.command.dispatch(['up', '-d', 'db'], None)
|
||||||
db = self.project.get_service('db')
|
db = self.project.get_service('db')
|
||||||
|
|
|
@ -5,6 +5,7 @@ from compose import config
|
||||||
from compose.const import LABEL_PROJECT
|
from compose.const import LABEL_PROJECT
|
||||||
from compose.container import Container
|
from compose.container import Container
|
||||||
from compose.project import Project
|
from compose.project import Project
|
||||||
|
from compose.service import ConvergenceStrategy
|
||||||
|
|
||||||
|
|
||||||
def build_service_dicts(service_config):
|
def build_service_dicts(service_config):
|
||||||
|
@ -224,7 +225,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
old_db_id = project.containers()[0].id
|
old_db_id = project.containers()[0].id
|
||||||
db_volume_path = project.containers()[0].get('Volumes./etc')
|
db_volume_path = project.containers()[0].get('Volumes./etc')
|
||||||
|
|
||||||
project.up(force_recreate=True)
|
project.up(strategy=ConvergenceStrategy.always)
|
||||||
self.assertEqual(len(project.containers()), 2)
|
self.assertEqual(len(project.containers()), 2)
|
||||||
|
|
||||||
db_container = [c for c in project.containers() if 'db' in c.name][0]
|
db_container = [c for c in project.containers() if 'db' in c.name][0]
|
||||||
|
@ -243,7 +244,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
old_db_id = project.containers()[0].id
|
old_db_id = project.containers()[0].id
|
||||||
db_volume_path = project.containers()[0].inspect()['Volumes']['/var/db']
|
db_volume_path = project.containers()[0].inspect()['Volumes']['/var/db']
|
||||||
|
|
||||||
project.up(allow_recreate=False)
|
project.up(strategy=ConvergenceStrategy.never)
|
||||||
self.assertEqual(len(project.containers()), 2)
|
self.assertEqual(len(project.containers()), 2)
|
||||||
|
|
||||||
db_container = [c for c in project.containers() if 'db' in c.name][0]
|
db_container = [c for c in project.containers() if 'db' in c.name][0]
|
||||||
|
@ -267,7 +268,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
old_db_id = old_containers[0].id
|
old_db_id = old_containers[0].id
|
||||||
db_volume_path = old_containers[0].inspect()['Volumes']['/var/db']
|
db_volume_path = old_containers[0].inspect()['Volumes']['/var/db']
|
||||||
|
|
||||||
project.up(allow_recreate=False)
|
project.up(strategy=ConvergenceStrategy.never)
|
||||||
|
|
||||||
new_containers = project.containers(stopped=True)
|
new_containers = project.containers(stopped=True)
|
||||||
self.assertEqual(len(new_containers), 2)
|
self.assertEqual(len(new_containers), 2)
|
||||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
||||||
from .. import mock
|
from .. import mock
|
||||||
from .testcases import DockerClientTestCase
|
from .testcases import DockerClientTestCase
|
||||||
from compose.project import Project
|
from compose.project import Project
|
||||||
|
from compose.service import ConvergenceStrategy
|
||||||
|
|
||||||
|
|
||||||
class ResilienceTest(DockerClientTestCase):
|
class ResilienceTest(DockerClientTestCase):
|
||||||
|
@ -16,14 +17,14 @@ class ResilienceTest(DockerClientTestCase):
|
||||||
self.host_path = container.get('Volumes')['/var/db']
|
self.host_path = container.get('Volumes')['/var/db']
|
||||||
|
|
||||||
def test_successful_recreate(self):
|
def test_successful_recreate(self):
|
||||||
self.project.up(force_recreate=True)
|
self.project.up(strategy=ConvergenceStrategy.always)
|
||||||
container = self.db.containers()[0]
|
container = self.db.containers()[0]
|
||||||
self.assertEqual(container.get('Volumes')['/var/db'], self.host_path)
|
self.assertEqual(container.get('Volumes')['/var/db'], self.host_path)
|
||||||
|
|
||||||
def test_create_failure(self):
|
def test_create_failure(self):
|
||||||
with mock.patch('compose.service.Service.create_container', crash):
|
with mock.patch('compose.service.Service.create_container', crash):
|
||||||
with self.assertRaises(Crash):
|
with self.assertRaises(Crash):
|
||||||
self.project.up(force_recreate=True)
|
self.project.up(strategy=ConvergenceStrategy.always)
|
||||||
|
|
||||||
self.project.up()
|
self.project.up()
|
||||||
container = self.db.containers()[0]
|
container = self.db.containers()[0]
|
||||||
|
@ -32,7 +33,7 @@ class ResilienceTest(DockerClientTestCase):
|
||||||
def test_start_failure(self):
|
def test_start_failure(self):
|
||||||
with mock.patch('compose.service.Service.start_container', crash):
|
with mock.patch('compose.service.Service.start_container', crash):
|
||||||
with self.assertRaises(Crash):
|
with self.assertRaises(Crash):
|
||||||
self.project.up(force_recreate=True)
|
self.project.up(strategy=ConvergenceStrategy.always)
|
||||||
|
|
||||||
self.project.up()
|
self.project.up()
|
||||||
container = self.db.containers()[0]
|
container = self.db.containers()[0]
|
||||||
|
|
|
@ -12,6 +12,7 @@ from .testcases import DockerClientTestCase
|
||||||
from compose import config
|
from compose import config
|
||||||
from compose.const import LABEL_CONFIG_HASH
|
from compose.const import LABEL_CONFIG_HASH
|
||||||
from compose.project import Project
|
from compose.project import Project
|
||||||
|
from compose.service import ConvergenceStrategy
|
||||||
|
|
||||||
|
|
||||||
class ProjectTestCase(DockerClientTestCase):
|
class ProjectTestCase(DockerClientTestCase):
|
||||||
|
@ -151,7 +152,9 @@ class ProjectWithDependenciesTest(ProjectTestCase):
|
||||||
old_containers = self.run_up(self.cfg)
|
old_containers = self.run_up(self.cfg)
|
||||||
|
|
||||||
self.cfg['db']['environment'] = {'NEW_VAR': '1'}
|
self.cfg['db']['environment'] = {'NEW_VAR': '1'}
|
||||||
new_containers = self.run_up(self.cfg, allow_recreate=False)
|
new_containers = self.run_up(
|
||||||
|
self.cfg,
|
||||||
|
strategy=ConvergenceStrategy.never)
|
||||||
|
|
||||||
self.assertEqual(new_containers - old_containers, set())
|
self.assertEqual(new_containers - old_containers, set())
|
||||||
|
|
||||||
|
@ -175,23 +178,11 @@ class ProjectWithDependenciesTest(ProjectTestCase):
|
||||||
|
|
||||||
|
|
||||||
def converge(service,
|
def converge(service,
|
||||||
allow_recreate=True,
|
strategy=ConvergenceStrategy.changed,
|
||||||
force_recreate=False,
|
|
||||||
do_build=True):
|
do_build=True):
|
||||||
"""
|
"""Create a converge plan from a strategy and execute the plan."""
|
||||||
If a container for this service doesn't exist, create and start one. If there are
|
plan = service.convergence_plan(strategy)
|
||||||
any, stop them, create+start new ones, and remove the old containers.
|
return service.execute_convergence_plan(plan, do_build=do_build, timeout=1)
|
||||||
"""
|
|
||||||
plan = service.convergence_plan(
|
|
||||||
allow_recreate=allow_recreate,
|
|
||||||
force_recreate=force_recreate,
|
|
||||||
)
|
|
||||||
|
|
||||||
return service.execute_convergence_plan(
|
|
||||||
plan,
|
|
||||||
do_build=do_build,
|
|
||||||
timeout=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceStateTest(DockerClientTestCase):
|
class ServiceStateTest(DockerClientTestCase):
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from compose import container
|
from compose import container
|
||||||
|
from compose.cli.errors import UserError
|
||||||
from compose.cli.log_printer import LogPrinter
|
from compose.cli.log_printer import LogPrinter
|
||||||
from compose.cli.main import attach_to_logs
|
from compose.cli.main import attach_to_logs
|
||||||
from compose.cli.main import build_log_printer
|
from compose.cli.main import build_log_printer
|
||||||
|
from compose.cli.main import convergence_strategy_from_opts
|
||||||
from compose.project import Project
|
from compose.project import Project
|
||||||
|
from compose.service import ConvergenceStrategy
|
||||||
from tests import mock
|
from tests import mock
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
|
||||||
|
@ -55,3 +58,32 @@ class CLIMainTestCase(unittest.TestCase):
|
||||||
project.stop.assert_called_once_with(
|
project.stop.assert_called_once_with(
|
||||||
service_names=service_names,
|
service_names=service_names,
|
||||||
timeout=timeout)
|
timeout=timeout)
|
||||||
|
|
||||||
|
|
||||||
|
class ConvergeStrategyFromOptsTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_invalid_opts(self):
|
||||||
|
options = {'--force-recreate': True, '--no-recreate': True}
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
convergence_strategy_from_opts(options)
|
||||||
|
|
||||||
|
def test_always(self):
|
||||||
|
options = {'--force-recreate': True, '--no-recreate': False}
|
||||||
|
self.assertEqual(
|
||||||
|
convergence_strategy_from_opts(options),
|
||||||
|
ConvergenceStrategy.always
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_never(self):
|
||||||
|
options = {'--force-recreate': False, '--no-recreate': True}
|
||||||
|
self.assertEqual(
|
||||||
|
convergence_strategy_from_opts(options),
|
||||||
|
ConvergenceStrategy.never
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_changed(self):
|
||||||
|
options = {'--force-recreate': False, '--no-recreate': False}
|
||||||
|
self.assertEqual(
|
||||||
|
convergence_strategy_from_opts(options),
|
||||||
|
ConvergenceStrategy.changed
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue