teuthology 1.1.0__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scripts/describe.py +1 -0
- scripts/dispatcher.py +55 -26
- scripts/exporter.py +18 -0
- scripts/lock.py +1 -1
- scripts/node_cleanup.py +58 -0
- scripts/openstack.py +9 -9
- scripts/results.py +12 -11
- scripts/schedule.py +4 -0
- scripts/suite.py +57 -16
- scripts/supervisor.py +44 -0
- scripts/update_inventory.py +10 -4
- teuthology/__init__.py +24 -26
- teuthology/beanstalk.py +4 -3
- teuthology/config.py +16 -6
- teuthology/contextutil.py +18 -14
- teuthology/describe_tests.py +25 -18
- teuthology/dispatcher/__init__.py +210 -35
- teuthology/dispatcher/supervisor.py +140 -58
- teuthology/exceptions.py +43 -0
- teuthology/exporter.py +347 -0
- teuthology/kill.py +76 -81
- teuthology/lock/cli.py +3 -3
- teuthology/lock/ops.py +135 -61
- teuthology/lock/query.py +61 -44
- teuthology/ls.py +1 -1
- teuthology/misc.py +61 -75
- teuthology/nuke/__init__.py +12 -353
- teuthology/openstack/__init__.py +4 -3
- teuthology/openstack/openstack-centos-7.0-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.1-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.2-user-data.txt +1 -1
- teuthology/openstack/openstack-debian-8.0-user-data.txt +1 -1
- teuthology/openstack/openstack-opensuse-42.1-user-data.txt +1 -1
- teuthology/openstack/openstack-teuthology.cron +0 -1
- teuthology/orchestra/cluster.py +49 -7
- teuthology/orchestra/connection.py +17 -4
- teuthology/orchestra/console.py +111 -50
- teuthology/orchestra/daemon/cephadmunit.py +15 -2
- teuthology/orchestra/daemon/state.py +8 -1
- teuthology/orchestra/daemon/systemd.py +4 -4
- teuthology/orchestra/opsys.py +30 -11
- teuthology/orchestra/remote.py +405 -338
- teuthology/orchestra/run.py +3 -3
- teuthology/packaging.py +19 -16
- teuthology/provision/__init__.py +30 -10
- teuthology/provision/cloud/openstack.py +12 -6
- teuthology/provision/cloud/util.py +1 -2
- teuthology/provision/downburst.py +4 -3
- teuthology/provision/fog.py +68 -20
- teuthology/provision/openstack.py +5 -4
- teuthology/provision/pelagos.py +1 -1
- teuthology/repo_utils.py +43 -13
- teuthology/report.py +57 -35
- teuthology/results.py +5 -3
- teuthology/run.py +13 -14
- teuthology/run_tasks.py +27 -43
- teuthology/schedule.py +4 -3
- teuthology/scrape.py +28 -22
- teuthology/suite/__init__.py +74 -45
- teuthology/suite/build_matrix.py +34 -24
- teuthology/suite/fragment-merge.lua +105 -0
- teuthology/suite/matrix.py +31 -2
- teuthology/suite/merge.py +175 -0
- teuthology/suite/placeholder.py +6 -9
- teuthology/suite/run.py +175 -100
- teuthology/suite/util.py +64 -218
- teuthology/task/__init__.py +1 -1
- teuthology/task/ansible.py +101 -32
- teuthology/task/buildpackages.py +2 -2
- teuthology/task/ceph_ansible.py +13 -6
- teuthology/task/cephmetrics.py +2 -1
- teuthology/task/clock.py +33 -14
- teuthology/task/exec.py +18 -0
- teuthology/task/hadoop.py +2 -2
- teuthology/task/install/__init__.py +29 -7
- teuthology/task/install/bin/adjust-ulimits +16 -0
- teuthology/task/install/bin/daemon-helper +114 -0
- teuthology/task/install/bin/stdin-killer +263 -0
- teuthology/task/install/deb.py +1 -1
- teuthology/task/install/rpm.py +17 -5
- teuthology/task/install/util.py +3 -3
- teuthology/task/internal/__init__.py +41 -10
- teuthology/task/internal/edit_sudoers.sh +10 -0
- teuthology/task/internal/lock_machines.py +2 -9
- teuthology/task/internal/redhat.py +31 -1
- teuthology/task/internal/syslog.py +31 -8
- teuthology/task/kernel.py +152 -145
- teuthology/task/lockfile.py +1 -1
- teuthology/task/mpi.py +10 -10
- teuthology/task/pcp.py +1 -1
- teuthology/task/selinux.py +16 -8
- teuthology/task/ssh_keys.py +4 -4
- teuthology/timer.py +3 -3
- teuthology/util/loggerfile.py +19 -0
- teuthology/util/scanner.py +159 -0
- teuthology/util/sentry.py +52 -0
- teuthology/util/time.py +52 -0
- teuthology-1.2.1.data/scripts/adjust-ulimits +16 -0
- teuthology-1.2.1.data/scripts/daemon-helper +114 -0
- teuthology-1.2.1.data/scripts/stdin-killer +263 -0
- teuthology-1.2.1.dist-info/METADATA +88 -0
- teuthology-1.2.1.dist-info/RECORD +168 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.1.dist-info}/WHEEL +1 -1
- {teuthology-1.1.0.dist-info → teuthology-1.2.1.dist-info}/entry_points.txt +3 -2
- scripts/nuke.py +0 -47
- scripts/worker.py +0 -37
- teuthology/lock/test/__init__.py +0 -0
- teuthology/lock/test/test_lock.py +0 -7
- teuthology/nuke/actions.py +0 -456
- teuthology/openstack/test/__init__.py +0 -0
- teuthology/openstack/test/openstack-integration.py +0 -286
- teuthology/openstack/test/test_config.py +0 -35
- teuthology/openstack/test/test_openstack.py +0 -1695
- teuthology/orchestra/test/__init__.py +0 -0
- teuthology/orchestra/test/integration/__init__.py +0 -0
- teuthology/orchestra/test/integration/test_integration.py +0 -94
- teuthology/orchestra/test/test_cluster.py +0 -240
- teuthology/orchestra/test/test_connection.py +0 -106
- teuthology/orchestra/test/test_console.py +0 -217
- teuthology/orchestra/test/test_opsys.py +0 -404
- teuthology/orchestra/test/test_remote.py +0 -185
- teuthology/orchestra/test/test_run.py +0 -286
- teuthology/orchestra/test/test_systemd.py +0 -54
- teuthology/orchestra/test/util.py +0 -12
- teuthology/task/tests/__init__.py +0 -110
- teuthology/task/tests/test_locking.py +0 -25
- teuthology/task/tests/test_run.py +0 -40
- teuthology/test/__init__.py +0 -0
- teuthology/test/fake_archive.py +0 -107
- teuthology/test/fake_fs.py +0 -92
- teuthology/test/integration/__init__.py +0 -0
- teuthology/test/integration/test_suite.py +0 -86
- teuthology/test/task/__init__.py +0 -205
- teuthology/test/task/test_ansible.py +0 -624
- teuthology/test/task/test_ceph_ansible.py +0 -176
- teuthology/test/task/test_console_log.py +0 -88
- teuthology/test/task/test_install.py +0 -337
- teuthology/test/task/test_internal.py +0 -57
- teuthology/test/task/test_kernel.py +0 -243
- teuthology/test/task/test_pcp.py +0 -379
- teuthology/test/task/test_selinux.py +0 -35
- teuthology/test/test_config.py +0 -189
- teuthology/test/test_contextutil.py +0 -68
- teuthology/test/test_describe_tests.py +0 -316
- teuthology/test/test_email_sleep_before_teardown.py +0 -81
- teuthology/test/test_exit.py +0 -97
- teuthology/test/test_get_distro.py +0 -47
- teuthology/test/test_get_distro_version.py +0 -47
- teuthology/test/test_get_multi_machine_types.py +0 -27
- teuthology/test/test_job_status.py +0 -60
- teuthology/test/test_ls.py +0 -48
- teuthology/test/test_misc.py +0 -391
- teuthology/test/test_nuke.py +0 -290
- teuthology/test/test_packaging.py +0 -763
- teuthology/test/test_parallel.py +0 -28
- teuthology/test/test_repo_utils.py +0 -225
- teuthology/test/test_report.py +0 -77
- teuthology/test/test_results.py +0 -155
- teuthology/test/test_run.py +0 -239
- teuthology/test/test_safepath.py +0 -55
- teuthology/test/test_schedule.py +0 -45
- teuthology/test/test_scrape.py +0 -167
- teuthology/test/test_timer.py +0 -80
- teuthology/test/test_vps_os_vers_parameter_checking.py +0 -84
- teuthology/test/test_worker.py +0 -303
- teuthology/worker.py +0 -354
- teuthology-1.1.0.dist-info/METADATA +0 -76
- teuthology-1.1.0.dist-info/RECORD +0 -213
- {teuthology-1.1.0.dist-info → teuthology-1.2.1.dist-info}/LICENSE +0 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.1.dist-info}/top_level.txt +0 -0
teuthology/test/fake_fs.py
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
from io import BytesIO
|
2
|
-
from contextlib import closing
|
3
|
-
|
4
|
-
|
5
|
-
try:
|
6
|
-
FileNotFoundError, NotADirectoryError
|
7
|
-
except NameError:
|
8
|
-
FileNotFoundError = NotADirectoryError = OSError
|
9
|
-
|
10
|
-
|
11
|
-
def make_fake_fstools(fake_filesystem):
|
12
|
-
"""
|
13
|
-
Build fake versions of os.listdir(), os.isfile(), etc. for use in
|
14
|
-
unit tests
|
15
|
-
|
16
|
-
An example fake_filesystem value:
|
17
|
-
>>> fake_fs = {\
|
18
|
-
'a_directory': {\
|
19
|
-
'another_directory': {\
|
20
|
-
'empty_file': None,\
|
21
|
-
'another_empty_file': None,\
|
22
|
-
},\
|
23
|
-
'random_file': None,\
|
24
|
-
'yet_another_directory': {\
|
25
|
-
'empty_directory': {},\
|
26
|
-
},\
|
27
|
-
'file_with_contents': 'data',\
|
28
|
-
},\
|
29
|
-
}
|
30
|
-
>>> fake_listdir, fake_isfile, _, _ = \
|
31
|
-
make_fake_fstools(fake_fs)
|
32
|
-
>>> fake_listdir('a_directory/yet_another_directory')
|
33
|
-
['empty_directory']
|
34
|
-
>>> fake_isfile('a_directory/yet_another_directory')
|
35
|
-
False
|
36
|
-
|
37
|
-
:param fake_filesystem: A dict representing a filesystem
|
38
|
-
"""
|
39
|
-
assert isinstance(fake_filesystem, dict)
|
40
|
-
|
41
|
-
def fake_listdir(path, fsdict=False):
|
42
|
-
if fsdict is False:
|
43
|
-
fsdict = fake_filesystem
|
44
|
-
|
45
|
-
remainder = path.strip('/') + '/'
|
46
|
-
subdict = fsdict
|
47
|
-
while '/' in remainder:
|
48
|
-
next_dir, remainder = remainder.split('/', 1)
|
49
|
-
if next_dir not in subdict:
|
50
|
-
raise FileNotFoundError(
|
51
|
-
'[Errno 2] No such file or directory: %s' % next_dir)
|
52
|
-
subdict = subdict.get(next_dir)
|
53
|
-
if not isinstance(subdict, dict):
|
54
|
-
raise NotADirectoryError('[Errno 20] Not a directory: %s' % next_dir)
|
55
|
-
if subdict and not remainder:
|
56
|
-
return list(subdict)
|
57
|
-
return []
|
58
|
-
|
59
|
-
def fake_isfile(path, fsdict=False):
|
60
|
-
if fsdict is False:
|
61
|
-
fsdict = fake_filesystem
|
62
|
-
|
63
|
-
components = path.strip('/').split('/')
|
64
|
-
subdict = fsdict
|
65
|
-
for component in components:
|
66
|
-
if component not in subdict:
|
67
|
-
raise FileNotFoundError(
|
68
|
-
'[Errno 2] No such file or directory: %s' % component)
|
69
|
-
subdict = subdict.get(component)
|
70
|
-
return subdict is None or isinstance(subdict, str)
|
71
|
-
|
72
|
-
def fake_isdir(path, fsdict=False):
|
73
|
-
return not fake_isfile(path)
|
74
|
-
|
75
|
-
def fake_exists(path, fsdict=False):
|
76
|
-
return fake_isfile(path, fsdict) or fake_isdir(path, fsdict)
|
77
|
-
|
78
|
-
def fake_open(path, mode=None, buffering=None):
|
79
|
-
components = path.strip('/').split('/')
|
80
|
-
subdict = fake_filesystem
|
81
|
-
for component in components:
|
82
|
-
if component not in subdict:
|
83
|
-
raise IOError(
|
84
|
-
'[Errno 2] No such file or directory: %s' % component)
|
85
|
-
subdict = subdict.get(component)
|
86
|
-
if isinstance(subdict, dict):
|
87
|
-
raise IOError('[Errno 21] Is a directory: %s' % path)
|
88
|
-
elif subdict is None:
|
89
|
-
return closing(BytesIO(b''))
|
90
|
-
return closing(BytesIO(subdict.encode()))
|
91
|
-
|
92
|
-
return fake_exists, fake_listdir, fake_isfile, fake_isdir, fake_open
|
File without changes
|
@@ -1,86 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import requests
|
3
|
-
from pytest import raises, skip
|
4
|
-
|
5
|
-
from teuthology.config import config
|
6
|
-
from teuthology import suite
|
7
|
-
|
8
|
-
|
9
|
-
class TestSuiteOnline(object):
|
10
|
-
def setup(self):
|
11
|
-
if 'TEST_ONLINE' not in os.environ:
|
12
|
-
skip("To run these sets, set the environment variable TEST_ONLINE")
|
13
|
-
|
14
|
-
def test_ceph_hash_simple(self):
|
15
|
-
resp = requests.get(
|
16
|
-
'https://api.github.com/repos/ceph/ceph/git/refs/heads/master')
|
17
|
-
ref_hash = resp.json()['object']['sha']
|
18
|
-
assert suite.get_hash('ceph') == ref_hash
|
19
|
-
|
20
|
-
def test_kernel_hash_saya(self):
|
21
|
-
# We don't currently have these packages.
|
22
|
-
assert suite.get_hash('kernel', 'master', 'basic', 'saya') is None
|
23
|
-
|
24
|
-
def test_all_master_branches(self):
|
25
|
-
# Don't attempt to send email
|
26
|
-
config.results_email = None
|
27
|
-
job_config = suite.create_initial_config('suite', 'master',
|
28
|
-
'master', 'master', 'testing',
|
29
|
-
'basic', 'centos', 'plana')
|
30
|
-
assert ((job_config.branch, job_config.teuthology_branch,
|
31
|
-
job_config.suite_branch) == ('master', 'master', 'master'))
|
32
|
-
|
33
|
-
def test_config_bogus_kernel_branch(self):
|
34
|
-
# Don't attempt to send email
|
35
|
-
config.results_email = None
|
36
|
-
with raises(suite.ScheduleFailError):
|
37
|
-
suite.create_initial_config('s', None, 'master', 't',
|
38
|
-
'bogus_kernel_branch', 'f', 'd', 'm')
|
39
|
-
|
40
|
-
def test_config_bogus_kernel_flavor(self):
|
41
|
-
# Don't attempt to send email
|
42
|
-
config.results_email = None
|
43
|
-
with raises(suite.ScheduleFailError):
|
44
|
-
suite.create_initial_config('s', None, 'master', 't', 'k',
|
45
|
-
'bogus_kernel_flavor', 'd', 'm')
|
46
|
-
|
47
|
-
def test_config_bogus_ceph_branch(self):
|
48
|
-
# Don't attempt to send email
|
49
|
-
config.results_email = None
|
50
|
-
with raises(suite.ScheduleFailError):
|
51
|
-
suite.create_initial_config('s', None, 'bogus_ceph_branch', 't',
|
52
|
-
'k', 'f', 'd', 'm')
|
53
|
-
|
54
|
-
def test_config_bogus_suite_branch(self):
|
55
|
-
# Don't attempt to send email
|
56
|
-
config.results_email = None
|
57
|
-
with raises(suite.ScheduleFailError):
|
58
|
-
suite.create_initial_config('s', 'bogus_suite_branch', 'master',
|
59
|
-
't', 'k', 'f', 'd', 'm')
|
60
|
-
|
61
|
-
def test_config_bogus_teuthology_branch(self):
|
62
|
-
# Don't attempt to send email
|
63
|
-
config.results_email = None
|
64
|
-
with raises(suite.ScheduleFailError):
|
65
|
-
suite.create_initial_config('s', None, 'master',
|
66
|
-
'bogus_teuth_branch', 'k', 'f', 'd',
|
67
|
-
'm')
|
68
|
-
|
69
|
-
def test_config_substitution(self):
|
70
|
-
# Don't attempt to send email
|
71
|
-
config.results_email = None
|
72
|
-
job_config = suite.create_initial_config('MY_SUITE', 'master',
|
73
|
-
'master', 'master', 'testing',
|
74
|
-
'basic', 'centos', 'plana')
|
75
|
-
assert job_config['suite'] == 'MY_SUITE'
|
76
|
-
|
77
|
-
def test_config_kernel_section(self):
|
78
|
-
# Don't attempt to send email
|
79
|
-
config.results_email = None
|
80
|
-
job_config = suite.create_initial_config('MY_SUITE', 'master',
|
81
|
-
'master', 'master', 'testing',
|
82
|
-
'basic', 'centos', 'plana')
|
83
|
-
assert job_config['kernel']['kdb'] is True
|
84
|
-
|
85
|
-
|
86
|
-
# maybe use notario for the above?
|
teuthology/test/task/__init__.py
DELETED
@@ -1,205 +0,0 @@
|
|
1
|
-
from mock import patch, DEFAULT
|
2
|
-
from pytest import raises
|
3
|
-
|
4
|
-
from teuthology.config import FakeNamespace
|
5
|
-
from teuthology.orchestra.cluster import Cluster
|
6
|
-
from teuthology.orchestra.remote import Remote
|
7
|
-
from teuthology.task import Task
|
8
|
-
|
9
|
-
|
10
|
-
class TestTask(object):
|
11
|
-
klass = Task
|
12
|
-
task_name = 'task'
|
13
|
-
|
14
|
-
def setup(self):
|
15
|
-
self.ctx = FakeNamespace()
|
16
|
-
self.ctx.config = dict()
|
17
|
-
self.task_config = dict()
|
18
|
-
|
19
|
-
def test_overrides(self):
|
20
|
-
self.ctx.config['overrides'] = dict()
|
21
|
-
self.ctx.config['overrides'][self.task_name] = dict(
|
22
|
-
key_1='overridden',
|
23
|
-
)
|
24
|
-
self.task_config.update(dict(
|
25
|
-
key_1='default',
|
26
|
-
key_2='default',
|
27
|
-
))
|
28
|
-
with patch.multiple(
|
29
|
-
self.klass,
|
30
|
-
begin=DEFAULT,
|
31
|
-
end=DEFAULT,
|
32
|
-
):
|
33
|
-
with self.klass(self.ctx, self.task_config) as task:
|
34
|
-
assert task.config['key_1'] == 'overridden'
|
35
|
-
assert task.config['key_2'] == 'default'
|
36
|
-
|
37
|
-
def test_hosts_no_filter(self):
|
38
|
-
self.ctx.cluster = Cluster()
|
39
|
-
self.ctx.cluster.add(Remote('user@remote1'), ['role1'])
|
40
|
-
self.ctx.cluster.add(Remote('user@remote2'), ['role2'])
|
41
|
-
with patch.multiple(
|
42
|
-
self.klass,
|
43
|
-
begin=DEFAULT,
|
44
|
-
end=DEFAULT,
|
45
|
-
):
|
46
|
-
with self.klass(self.ctx, self.task_config) as task:
|
47
|
-
task_hosts = list(task.cluster.remotes)
|
48
|
-
assert len(task_hosts) == 2
|
49
|
-
assert sorted(host.shortname for host in task_hosts) == \
|
50
|
-
['remote1', 'remote2']
|
51
|
-
|
52
|
-
def test_hosts_no_results(self):
|
53
|
-
self.ctx.cluster = Cluster()
|
54
|
-
self.ctx.cluster.add(Remote('user@remote1'), ['role1'])
|
55
|
-
self.task_config.update(dict(
|
56
|
-
hosts=['role2'],
|
57
|
-
))
|
58
|
-
with patch.multiple(
|
59
|
-
self.klass,
|
60
|
-
begin=DEFAULT,
|
61
|
-
end=DEFAULT,
|
62
|
-
):
|
63
|
-
with raises(RuntimeError):
|
64
|
-
with self.klass(self.ctx, self.task_config):
|
65
|
-
pass
|
66
|
-
|
67
|
-
def test_hosts_one_role(self):
|
68
|
-
self.ctx.cluster = Cluster()
|
69
|
-
self.ctx.cluster.add(Remote('user@remote1'), ['role1'])
|
70
|
-
self.ctx.cluster.add(Remote('user@remote2'), ['role2'])
|
71
|
-
self.task_config.update(dict(
|
72
|
-
hosts=['role1'],
|
73
|
-
))
|
74
|
-
with patch.multiple(
|
75
|
-
self.klass,
|
76
|
-
begin=DEFAULT,
|
77
|
-
end=DEFAULT,
|
78
|
-
):
|
79
|
-
with self.klass(self.ctx, self.task_config) as task:
|
80
|
-
task_hosts = list(task.cluster.remotes)
|
81
|
-
assert len(task_hosts) == 1
|
82
|
-
assert task_hosts[0].shortname == 'remote1'
|
83
|
-
|
84
|
-
def test_hosts_two_roles(self):
|
85
|
-
self.ctx.cluster = Cluster()
|
86
|
-
self.ctx.cluster.add(Remote('user@remote1'), ['role1'])
|
87
|
-
self.ctx.cluster.add(Remote('user@remote2'), ['role2'])
|
88
|
-
self.ctx.cluster.add(Remote('user@remote3'), ['role3'])
|
89
|
-
self.task_config.update(dict(
|
90
|
-
hosts=['role1', 'role3'],
|
91
|
-
))
|
92
|
-
with patch.multiple(
|
93
|
-
self.klass,
|
94
|
-
begin=DEFAULT,
|
95
|
-
end=DEFAULT,
|
96
|
-
):
|
97
|
-
with self.klass(self.ctx, self.task_config) as task:
|
98
|
-
task_hosts = list(task.cluster.remotes)
|
99
|
-
assert len(task_hosts) == 2
|
100
|
-
hostnames = [host.shortname for host in task_hosts]
|
101
|
-
assert sorted(hostnames) == ['remote1', 'remote3']
|
102
|
-
|
103
|
-
def test_hosts_two_hostnames(self):
|
104
|
-
self.ctx.cluster = Cluster()
|
105
|
-
self.ctx.cluster.add(Remote('user@remote1.example.com'), ['role1'])
|
106
|
-
self.ctx.cluster.add(Remote('user@remote2.example.com'), ['role2'])
|
107
|
-
self.ctx.cluster.add(Remote('user@remote3.example.com'), ['role3'])
|
108
|
-
self.task_config.update(dict(
|
109
|
-
hosts=['remote1', 'remote2.example.com'],
|
110
|
-
))
|
111
|
-
with patch.multiple(
|
112
|
-
self.klass,
|
113
|
-
begin=DEFAULT,
|
114
|
-
end=DEFAULT,
|
115
|
-
):
|
116
|
-
with self.klass(self.ctx, self.task_config) as task:
|
117
|
-
task_hosts = list(task.cluster.remotes)
|
118
|
-
assert len(task_hosts) == 2
|
119
|
-
hostnames = [host.hostname for host in task_hosts]
|
120
|
-
assert sorted(hostnames) == ['remote1.example.com',
|
121
|
-
'remote2.example.com']
|
122
|
-
|
123
|
-
def test_hosts_one_role_one_hostname(self):
|
124
|
-
self.ctx.cluster = Cluster()
|
125
|
-
self.ctx.cluster.add(Remote('user@remote1.example.com'), ['role1'])
|
126
|
-
self.ctx.cluster.add(Remote('user@remote2.example.com'), ['role2'])
|
127
|
-
self.ctx.cluster.add(Remote('user@remote3.example.com'), ['role3'])
|
128
|
-
self.task_config.update(dict(
|
129
|
-
hosts=['role1', 'remote2.example.com'],
|
130
|
-
))
|
131
|
-
with patch.multiple(
|
132
|
-
self.klass,
|
133
|
-
begin=DEFAULT,
|
134
|
-
end=DEFAULT,
|
135
|
-
):
|
136
|
-
with self.klass(self.ctx, self.task_config) as task:
|
137
|
-
task_hosts = list(task.cluster.remotes)
|
138
|
-
assert len(task_hosts) == 2
|
139
|
-
hostnames = [host.hostname for host in task_hosts]
|
140
|
-
assert sorted(hostnames) == ['remote1.example.com',
|
141
|
-
'remote2.example.com']
|
142
|
-
|
143
|
-
def test_setup_called(self):
|
144
|
-
with patch.multiple(
|
145
|
-
self.klass,
|
146
|
-
setup=DEFAULT,
|
147
|
-
begin=DEFAULT,
|
148
|
-
end=DEFAULT,
|
149
|
-
teardown=DEFAULT,
|
150
|
-
):
|
151
|
-
with self.klass(self.ctx, self.task_config) as task:
|
152
|
-
task.setup.assert_called_once_with()
|
153
|
-
|
154
|
-
def test_begin_called(self):
|
155
|
-
with patch.multiple(
|
156
|
-
self.klass,
|
157
|
-
setup=DEFAULT,
|
158
|
-
begin=DEFAULT,
|
159
|
-
end=DEFAULT,
|
160
|
-
teardown=DEFAULT,
|
161
|
-
):
|
162
|
-
with self.klass(self.ctx, self.task_config) as task:
|
163
|
-
task.begin.assert_called_once_with()
|
164
|
-
|
165
|
-
def test_end_called(self):
|
166
|
-
self.task_config.update(dict())
|
167
|
-
with patch.multiple(
|
168
|
-
self.klass,
|
169
|
-
begin=DEFAULT,
|
170
|
-
end=DEFAULT,
|
171
|
-
):
|
172
|
-
with self.klass(self.ctx, self.task_config) as task:
|
173
|
-
pass
|
174
|
-
task.end.assert_called_once_with()
|
175
|
-
|
176
|
-
def test_teardown_called(self):
|
177
|
-
self.task_config.update(dict())
|
178
|
-
with patch.multiple(
|
179
|
-
self.klass,
|
180
|
-
setup=DEFAULT,
|
181
|
-
begin=DEFAULT,
|
182
|
-
end=DEFAULT,
|
183
|
-
teardown=DEFAULT,
|
184
|
-
):
|
185
|
-
with self.klass(self.ctx, self.task_config) as task:
|
186
|
-
pass
|
187
|
-
task.teardown.assert_called_once_with()
|
188
|
-
|
189
|
-
def test_skip_teardown(self):
|
190
|
-
self.task_config.update(dict(
|
191
|
-
skip_teardown=True,
|
192
|
-
))
|
193
|
-
|
194
|
-
def fake_teardown(self):
|
195
|
-
assert False
|
196
|
-
|
197
|
-
with patch.multiple(
|
198
|
-
self.klass,
|
199
|
-
setup=DEFAULT,
|
200
|
-
begin=DEFAULT,
|
201
|
-
end=DEFAULT,
|
202
|
-
teardown=fake_teardown,
|
203
|
-
):
|
204
|
-
with self.klass(self.ctx, self.task_config):
|
205
|
-
pass
|