teuthology 1.1.0__py3-none-any.whl → 1.2.0__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 +16 -5
- teuthology/orchestra/console.py +111 -50
- teuthology/orchestra/daemon/cephadmunit.py +17 -4
- 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/task/tests/__init__.py +137 -77
- teuthology/task/tests/test_fetch_coredumps.py +116 -0
- teuthology/task/tests/test_run.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.0.data/scripts/adjust-ulimits +16 -0
- teuthology-1.2.0.data/scripts/daemon-helper +114 -0
- teuthology-1.2.0.data/scripts/stdin-killer +263 -0
- teuthology-1.2.0.dist-info/METADATA +89 -0
- teuthology-1.2.0.dist-info/RECORD +174 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/WHEEL +1 -1
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/entry_points.txt +3 -2
- scripts/nuke.py +0 -47
- scripts/worker.py +0 -37
- 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/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.0.dist-info}/LICENSE +0 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/top_level.txt +0 -0
@@ -1,624 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import os
|
3
|
-
import yaml
|
4
|
-
|
5
|
-
from mock import patch, DEFAULT, Mock
|
6
|
-
from pytest import raises, mark
|
7
|
-
from teuthology.util.compat import PY3
|
8
|
-
if PY3:
|
9
|
-
from io import StringIO as StringIO
|
10
|
-
else:
|
11
|
-
from io import BytesIO as StringIO
|
12
|
-
|
13
|
-
from teuthology.config import config, FakeNamespace
|
14
|
-
from teuthology.exceptions import CommandFailedError
|
15
|
-
from teuthology.orchestra.cluster import Cluster
|
16
|
-
from teuthology.orchestra.remote import Remote
|
17
|
-
from teuthology.task import ansible
|
18
|
-
from teuthology.task.ansible import Ansible, CephLab
|
19
|
-
|
20
|
-
from teuthology.test.task import TestTask
|
21
|
-
|
22
|
-
class TestAnsibleTask(TestTask):
|
23
|
-
klass = Ansible
|
24
|
-
task_name = 'ansible'
|
25
|
-
|
26
|
-
def setup(self):
|
27
|
-
pass
|
28
|
-
|
29
|
-
def setup_method(self, method):
|
30
|
-
self.ctx = FakeNamespace()
|
31
|
-
self.ctx.cluster = Cluster()
|
32
|
-
self.ctx.cluster.add(Remote('user@remote1'), ['role1'])
|
33
|
-
self.ctx.cluster.add(Remote('user@remote2'), ['role2'])
|
34
|
-
self.ctx.config = dict()
|
35
|
-
self.ctx.summary = dict()
|
36
|
-
self.task_config = dict(playbook=[])
|
37
|
-
self.start_patchers()
|
38
|
-
|
39
|
-
def start_patchers(self):
|
40
|
-
self.patchers = dict()
|
41
|
-
self.mocks = dict()
|
42
|
-
self.patchers['mkdtemp'] = patch(
|
43
|
-
'teuthology.task.ansible.mkdtemp', return_value='/tmp/'
|
44
|
-
)
|
45
|
-
m_NTF = Mock()
|
46
|
-
m_file = Mock()
|
47
|
-
m_file.name = 'file_name'
|
48
|
-
m_NTF.return_value = m_file
|
49
|
-
self.patchers['NTF'] = patch(
|
50
|
-
'teuthology.task.ansible.NamedTemporaryFile',
|
51
|
-
m_NTF,
|
52
|
-
)
|
53
|
-
self.patchers['file'] = patch(
|
54
|
-
'teuthology.task.ansible.open', create=True)
|
55
|
-
self.patchers['os_mkdir'] = patch(
|
56
|
-
'teuthology.task.ansible.os.mkdir',
|
57
|
-
)
|
58
|
-
self.patchers['os_remove'] = patch(
|
59
|
-
'teuthology.task.ansible.os.remove',
|
60
|
-
)
|
61
|
-
self.patchers['shutil_rmtree'] = patch(
|
62
|
-
'teuthology.task.ansible.shutil.rmtree',
|
63
|
-
)
|
64
|
-
for name in self.patchers.keys():
|
65
|
-
self.start_patcher(name)
|
66
|
-
|
67
|
-
def start_patcher(self, name):
|
68
|
-
if name not in self.mocks.keys():
|
69
|
-
self.mocks[name] = self.patchers[name].start()
|
70
|
-
|
71
|
-
def teardown_method(self, method):
|
72
|
-
self.stop_patchers()
|
73
|
-
|
74
|
-
def stop_patchers(self):
|
75
|
-
for name in list(self.mocks):
|
76
|
-
self.stop_patcher(name)
|
77
|
-
|
78
|
-
def stop_patcher(self, name):
|
79
|
-
self.patchers[name].stop()
|
80
|
-
del self.mocks[name]
|
81
|
-
|
82
|
-
def test_setup(self):
|
83
|
-
self.task_config.update(dict(
|
84
|
-
playbook=[]
|
85
|
-
))
|
86
|
-
|
87
|
-
def fake_get_playbook(self):
|
88
|
-
self.playbook_file = 'fake'
|
89
|
-
|
90
|
-
with patch.multiple(
|
91
|
-
self.klass,
|
92
|
-
find_repo=DEFAULT,
|
93
|
-
get_playbook=fake_get_playbook,
|
94
|
-
get_inventory=DEFAULT,
|
95
|
-
generate_inventory=DEFAULT,
|
96
|
-
generate_playbook=Mock(side_effect=Exception),
|
97
|
-
):
|
98
|
-
task = self.klass(self.ctx, self.task_config)
|
99
|
-
task.setup()
|
100
|
-
|
101
|
-
def test_setup_generate_playbook(self):
|
102
|
-
self.task_config.update(dict(
|
103
|
-
playbook=[]
|
104
|
-
))
|
105
|
-
with patch.multiple(
|
106
|
-
self.klass,
|
107
|
-
find_repo=DEFAULT,
|
108
|
-
get_playbook=DEFAULT,
|
109
|
-
get_inventory=DEFAULT,
|
110
|
-
generate_inventory=DEFAULT,
|
111
|
-
generate_playbook=DEFAULT,
|
112
|
-
):
|
113
|
-
task = self.klass(self.ctx, self.task_config)
|
114
|
-
task.setup()
|
115
|
-
task.generate_playbook.assert_called_once_with()
|
116
|
-
|
117
|
-
def test_find_repo_path(self):
|
118
|
-
self.task_config.update(dict(
|
119
|
-
repo='~/my/repo',
|
120
|
-
))
|
121
|
-
task = self.klass(self.ctx, self.task_config)
|
122
|
-
task.find_repo()
|
123
|
-
assert task.repo_path == os.path.expanduser(self.task_config['repo'])
|
124
|
-
|
125
|
-
@patch('teuthology.task.ansible.fetch_repo')
|
126
|
-
def test_find_repo_path_remote(self, m_fetch_repo):
|
127
|
-
self.task_config.update(dict(
|
128
|
-
repo='git://fake_host/repo.git',
|
129
|
-
))
|
130
|
-
m_fetch_repo.return_value = '/tmp/repo'
|
131
|
-
task = self.klass(self.ctx, self.task_config)
|
132
|
-
task.find_repo()
|
133
|
-
assert task.repo_path == os.path.expanduser('/tmp/repo')
|
134
|
-
|
135
|
-
@patch('teuthology.task.ansible.fetch_repo')
|
136
|
-
def test_find_repo_http(self, m_fetch_repo):
|
137
|
-
self.task_config.update(dict(
|
138
|
-
repo='http://example.com/my/repo',
|
139
|
-
))
|
140
|
-
task = self.klass(self.ctx, self.task_config)
|
141
|
-
task.find_repo()
|
142
|
-
m_fetch_repo.assert_called_once_with(self.task_config['repo'],
|
143
|
-
'master')
|
144
|
-
|
145
|
-
@patch('teuthology.task.ansible.fetch_repo')
|
146
|
-
def test_find_repo_git(self, m_fetch_repo):
|
147
|
-
self.task_config.update(dict(
|
148
|
-
repo='git@example.com/my/repo',
|
149
|
-
))
|
150
|
-
task = self.klass(self.ctx, self.task_config)
|
151
|
-
task.find_repo()
|
152
|
-
m_fetch_repo.assert_called_once_with(self.task_config['repo'],
|
153
|
-
'master')
|
154
|
-
|
155
|
-
def test_playbook_none(self):
|
156
|
-
del self.task_config['playbook']
|
157
|
-
task = self.klass(self.ctx, self.task_config)
|
158
|
-
with raises(KeyError):
|
159
|
-
task.get_playbook()
|
160
|
-
|
161
|
-
def test_playbook_wrong_type(self):
|
162
|
-
self.task_config.update(dict(
|
163
|
-
playbook=dict(),
|
164
|
-
))
|
165
|
-
task = self.klass(self.ctx, self.task_config)
|
166
|
-
with raises(TypeError):
|
167
|
-
task.get_playbook()
|
168
|
-
|
169
|
-
def test_playbook_list(self):
|
170
|
-
playbook = [
|
171
|
-
dict(
|
172
|
-
roles=['role1'],
|
173
|
-
),
|
174
|
-
]
|
175
|
-
self.task_config.update(dict(
|
176
|
-
playbook=playbook,
|
177
|
-
))
|
178
|
-
task = self.klass(self.ctx, self.task_config)
|
179
|
-
task.get_playbook()
|
180
|
-
assert task.playbook == playbook
|
181
|
-
|
182
|
-
@patch.object(ansible.requests, 'get')
|
183
|
-
def test_playbook_http(self, m_get):
|
184
|
-
m_get.return_value = Mock()
|
185
|
-
m_get.return_value.text = 'fake playbook text'
|
186
|
-
playbook = "http://example.com/my_playbook.yml"
|
187
|
-
self.task_config.update(dict(
|
188
|
-
playbook=playbook,
|
189
|
-
))
|
190
|
-
task = self.klass(self.ctx, self.task_config)
|
191
|
-
task.get_playbook()
|
192
|
-
m_get.assert_called_once_with(playbook)
|
193
|
-
|
194
|
-
def test_playbook_file(self):
|
195
|
-
fake_playbook = [dict(fake_playbook=True)]
|
196
|
-
fake_playbook_obj = StringIO(yaml.safe_dump(fake_playbook))
|
197
|
-
self.task_config.update(dict(
|
198
|
-
playbook='~/fake/playbook',
|
199
|
-
))
|
200
|
-
task = self.klass(self.ctx, self.task_config)
|
201
|
-
self.mocks['file'].return_value = fake_playbook_obj
|
202
|
-
task.get_playbook()
|
203
|
-
assert task.playbook == fake_playbook
|
204
|
-
|
205
|
-
def test_playbook_file_missing(self):
|
206
|
-
self.task_config.update(dict(
|
207
|
-
playbook='~/fake/playbook',
|
208
|
-
))
|
209
|
-
task = self.klass(self.ctx, self.task_config)
|
210
|
-
self.mocks['file'].side_effect = IOError
|
211
|
-
with raises(IOError):
|
212
|
-
task.get_playbook()
|
213
|
-
|
214
|
-
def test_inventory_none(self):
|
215
|
-
self.task_config.update(dict(
|
216
|
-
playbook=[]
|
217
|
-
))
|
218
|
-
task = self.klass(self.ctx, self.task_config)
|
219
|
-
with patch.object(ansible.os.path, 'exists') as m_exists:
|
220
|
-
m_exists.return_value = False
|
221
|
-
task.get_inventory()
|
222
|
-
assert task.inventory is None
|
223
|
-
|
224
|
-
def test_inventory_path(self):
|
225
|
-
inventory = '/my/inventory'
|
226
|
-
self.task_config.update(dict(
|
227
|
-
playbook=[],
|
228
|
-
inventory=inventory,
|
229
|
-
))
|
230
|
-
task = self.klass(self.ctx, self.task_config)
|
231
|
-
task.get_inventory()
|
232
|
-
assert task.inventory == inventory
|
233
|
-
assert task.generated_inventory is False
|
234
|
-
|
235
|
-
def test_inventory_etc(self):
|
236
|
-
self.task_config.update(dict(
|
237
|
-
playbook=[]
|
238
|
-
))
|
239
|
-
task = self.klass(self.ctx, self.task_config)
|
240
|
-
with patch.object(ansible.os.path, 'exists') as m_exists:
|
241
|
-
m_exists.return_value = True
|
242
|
-
task.get_inventory()
|
243
|
-
assert task.inventory == '/etc/ansible/hosts'
|
244
|
-
assert task.generated_inventory is False
|
245
|
-
|
246
|
-
@mark.parametrize(
|
247
|
-
'group_vars',
|
248
|
-
[
|
249
|
-
dict(),
|
250
|
-
dict(all=dict(var0=0, var1=1)),
|
251
|
-
dict(foo=dict(var0=0), bar=dict(var0=1)),
|
252
|
-
]
|
253
|
-
)
|
254
|
-
def test_generate_inventory(self, group_vars):
|
255
|
-
self.task_config.update(dict(
|
256
|
-
playbook=[]
|
257
|
-
))
|
258
|
-
if group_vars:
|
259
|
-
self.task_config.update(dict(group_vars=group_vars))
|
260
|
-
task = self.klass(self.ctx, self.task_config)
|
261
|
-
hosts_file_path = '/my/hosts/inventory'
|
262
|
-
hosts_file_obj = StringIO()
|
263
|
-
hosts_file_obj.name = hosts_file_path
|
264
|
-
inventory_dir = os.path.dirname(hosts_file_path)
|
265
|
-
gv_dir = os.path.join(inventory_dir, 'group_vars')
|
266
|
-
self.mocks['mkdtemp'].return_value = inventory_dir
|
267
|
-
m_file = self.mocks['file']
|
268
|
-
fake_files = [hosts_file_obj]
|
269
|
-
# Create StringIO object for each group_vars file
|
270
|
-
if group_vars:
|
271
|
-
fake_files += [StringIO() for i in sorted(group_vars)]
|
272
|
-
m_file.side_effect = fake_files
|
273
|
-
task.generate_inventory()
|
274
|
-
file_calls = m_file.call_args_list
|
275
|
-
# Verify the inventory file was created
|
276
|
-
assert file_calls[0][0][0] == hosts_file_path
|
277
|
-
# Verify each group_vars file was created
|
278
|
-
for gv_name, call_obj in zip(sorted(group_vars), file_calls[1:]):
|
279
|
-
gv_path = call_obj[0][0]
|
280
|
-
assert gv_path == os.path.join(gv_dir, '%s.yml' % gv_name)
|
281
|
-
# Verify the group_vars dir was created
|
282
|
-
if group_vars:
|
283
|
-
mkdir_call = self.mocks['os_mkdir'].call_args_list
|
284
|
-
assert mkdir_call[0][0][0] == gv_dir
|
285
|
-
assert task.generated_inventory is True
|
286
|
-
assert task.inventory == inventory_dir
|
287
|
-
# Verify the content of the inventory *file*
|
288
|
-
hosts_file_obj.seek(0)
|
289
|
-
assert hosts_file_obj.readlines() == [
|
290
|
-
'remote1\n',
|
291
|
-
'remote2\n',
|
292
|
-
]
|
293
|
-
# Verify the contents of each group_vars file
|
294
|
-
gv_names = sorted(group_vars)
|
295
|
-
for i in range(len(gv_names)):
|
296
|
-
gv_name = gv_names[i]
|
297
|
-
in_val = group_vars[gv_name]
|
298
|
-
gv_stringio = fake_files[1 + i]
|
299
|
-
gv_stringio.seek(0)
|
300
|
-
out_val = yaml.safe_load(gv_stringio)
|
301
|
-
assert in_val == out_val
|
302
|
-
|
303
|
-
def test_generate_playbook(self):
|
304
|
-
playbook = [
|
305
|
-
dict(
|
306
|
-
roles=['role1', 'role2'],
|
307
|
-
),
|
308
|
-
]
|
309
|
-
self.task_config.update(dict(
|
310
|
-
playbook=playbook
|
311
|
-
))
|
312
|
-
task = self.klass(self.ctx, self.task_config)
|
313
|
-
playbook_file_path = '/my/playbook/file'
|
314
|
-
playbook_file_obj = StringIO()
|
315
|
-
playbook_file_obj.name = playbook_file_path
|
316
|
-
with patch.object(ansible, 'NamedTemporaryFile') as m_NTF:
|
317
|
-
m_NTF.return_value = playbook_file_obj
|
318
|
-
task.find_repo()
|
319
|
-
task.get_playbook()
|
320
|
-
task.generate_playbook()
|
321
|
-
m_NTF.assert_called_once_with(
|
322
|
-
prefix="teuth_ansible_playbook_",
|
323
|
-
dir=task.repo_path,
|
324
|
-
delete=False,
|
325
|
-
)
|
326
|
-
assert task.generated_playbook is True
|
327
|
-
assert task.playbook_file == playbook_file_obj
|
328
|
-
playbook_file_obj.seek(0)
|
329
|
-
playbook_result = yaml.safe_load(playbook_file_obj)
|
330
|
-
assert playbook_result == playbook
|
331
|
-
|
332
|
-
def test_execute_playbook(self):
|
333
|
-
playbook = '/my/playbook'
|
334
|
-
self.task_config.update(dict(
|
335
|
-
playbook=playbook
|
336
|
-
))
|
337
|
-
fake_playbook = [dict(fake_playbook=True)]
|
338
|
-
fake_playbook_obj = StringIO(yaml.safe_dump(fake_playbook))
|
339
|
-
fake_playbook_obj.name = playbook
|
340
|
-
self.mocks['mkdtemp'].return_value = '/inventory/dir'
|
341
|
-
|
342
|
-
task = self.klass(self.ctx, self.task_config)
|
343
|
-
self.mocks['file'].return_value = fake_playbook_obj
|
344
|
-
task.setup()
|
345
|
-
args = task._build_args()
|
346
|
-
logger = StringIO()
|
347
|
-
with patch.object(ansible.pexpect, 'run') as m_run:
|
348
|
-
m_run.return_value = ('', 0)
|
349
|
-
with patch.object(Remote, 'reconnect') as m_reconnect:
|
350
|
-
m_reconnect.return_value = True
|
351
|
-
task.execute_playbook(_logfile=logger)
|
352
|
-
m_run.assert_called_once_with(
|
353
|
-
' '.join(args),
|
354
|
-
cwd=task.repo_path,
|
355
|
-
logfile=logger,
|
356
|
-
withexitstatus=True,
|
357
|
-
timeout=None,
|
358
|
-
)
|
359
|
-
|
360
|
-
def test_execute_playbook_fail(self):
|
361
|
-
self.task_config.update(dict(
|
362
|
-
playbook=[],
|
363
|
-
))
|
364
|
-
self.mocks['mkdtemp'].return_value = '/inventory/dir'
|
365
|
-
task = self.klass(self.ctx, self.task_config)
|
366
|
-
task.setup()
|
367
|
-
with patch.object(ansible.pexpect, 'run') as m_run:
|
368
|
-
with patch('teuthology.task.ansible.open') as m_open:
|
369
|
-
fake_failure_log = Mock()
|
370
|
-
fake_failure_log.__enter__ = Mock()
|
371
|
-
fake_failure_log.__exit__ = Mock()
|
372
|
-
m_open.return_value = fake_failure_log
|
373
|
-
m_run.return_value = ('', 1)
|
374
|
-
with raises(CommandFailedError):
|
375
|
-
task.execute_playbook()
|
376
|
-
assert task.ctx.summary.get('status') is None
|
377
|
-
|
378
|
-
def test_build_args_no_tags(self):
|
379
|
-
self.task_config.update(dict(
|
380
|
-
playbook=[],
|
381
|
-
))
|
382
|
-
task = self.klass(self.ctx, self.task_config)
|
383
|
-
task.setup()
|
384
|
-
args = task._build_args()
|
385
|
-
assert '--tags' not in args
|
386
|
-
|
387
|
-
def test_build_args_tags(self):
|
388
|
-
self.task_config.update(dict(
|
389
|
-
playbook=[],
|
390
|
-
tags="user,pubkeys"
|
391
|
-
))
|
392
|
-
task = self.klass(self.ctx, self.task_config)
|
393
|
-
task.setup()
|
394
|
-
args = task._build_args()
|
395
|
-
assert args.count('--tags') == 1
|
396
|
-
assert args[args.index('--tags') + 1] == 'user,pubkeys'
|
397
|
-
|
398
|
-
def test_build_args_skip_tags(self):
|
399
|
-
self.task_config.update(dict(
|
400
|
-
playbook=[],
|
401
|
-
skip_tags="user,pubkeys"
|
402
|
-
))
|
403
|
-
task = self.klass(self.ctx, self.task_config)
|
404
|
-
task.setup()
|
405
|
-
args = task._build_args()
|
406
|
-
assert args.count('--skip-tags') == 1
|
407
|
-
assert args[args.index('--skip-tags') + 1] == 'user,pubkeys'
|
408
|
-
|
409
|
-
def test_build_args_no_vars(self):
|
410
|
-
self.task_config.update(dict(
|
411
|
-
playbook=[],
|
412
|
-
))
|
413
|
-
task = self.klass(self.ctx, self.task_config)
|
414
|
-
task.setup()
|
415
|
-
args = task._build_args()
|
416
|
-
assert args.count('--extra-vars') == 1
|
417
|
-
vars_str = args[args.index('--extra-vars') + 1].strip("'")
|
418
|
-
extra_vars = json.loads(vars_str)
|
419
|
-
assert list(extra_vars) == ['ansible_ssh_user']
|
420
|
-
|
421
|
-
def test_build_args_vars(self):
|
422
|
-
extra_vars = dict(
|
423
|
-
string1='value1',
|
424
|
-
list1=['item1'],
|
425
|
-
dict1=dict(key='value'),
|
426
|
-
)
|
427
|
-
|
428
|
-
self.task_config.update(dict(
|
429
|
-
playbook=[],
|
430
|
-
vars=extra_vars,
|
431
|
-
))
|
432
|
-
task = self.klass(self.ctx, self.task_config)
|
433
|
-
task.setup()
|
434
|
-
args = task._build_args()
|
435
|
-
assert args.count('--extra-vars') == 1
|
436
|
-
vars_str = args[args.index('--extra-vars') + 1].strip("'")
|
437
|
-
got_extra_vars = json.loads(vars_str)
|
438
|
-
assert 'ansible_ssh_user' in got_extra_vars
|
439
|
-
assert got_extra_vars['string1'] == extra_vars['string1']
|
440
|
-
assert got_extra_vars['list1'] == extra_vars['list1']
|
441
|
-
assert got_extra_vars['dict1'] == extra_vars['dict1']
|
442
|
-
|
443
|
-
def test_teardown_inventory(self):
|
444
|
-
self.task_config.update(dict(
|
445
|
-
playbook=[],
|
446
|
-
))
|
447
|
-
task = self.klass(self.ctx, self.task_config)
|
448
|
-
task.generated_inventory = True
|
449
|
-
task.inventory = 'fake'
|
450
|
-
with patch.object(ansible.shutil, 'rmtree') as m_rmtree:
|
451
|
-
task.teardown()
|
452
|
-
assert m_rmtree.called_once_with('fake')
|
453
|
-
|
454
|
-
def test_teardown_playbook(self):
|
455
|
-
self.task_config.update(dict(
|
456
|
-
playbook=[],
|
457
|
-
))
|
458
|
-
task = self.klass(self.ctx, self.task_config)
|
459
|
-
task.generated_playbook = True
|
460
|
-
task.playbook_file = Mock()
|
461
|
-
task.playbook_file.name = 'fake'
|
462
|
-
with patch.object(ansible.os, 'remove') as m_remove:
|
463
|
-
task.teardown()
|
464
|
-
assert m_remove.called_once_with('fake')
|
465
|
-
|
466
|
-
def test_teardown_cleanup_with_vars(self):
|
467
|
-
self.task_config.update(dict(
|
468
|
-
playbook=[],
|
469
|
-
cleanup=True,
|
470
|
-
vars=dict(yum_repos="testing"),
|
471
|
-
))
|
472
|
-
task = self.klass(self.ctx, self.task_config)
|
473
|
-
task.inventory = "fake"
|
474
|
-
task.generated_playbook = True
|
475
|
-
task.playbook_file = Mock()
|
476
|
-
task.playbook_file.name = 'fake'
|
477
|
-
with patch.object(self.klass, 'execute_playbook') as m_execute:
|
478
|
-
with patch.object(ansible.os, 'remove'):
|
479
|
-
task.teardown()
|
480
|
-
task._build_args()
|
481
|
-
assert m_execute.called
|
482
|
-
assert 'cleanup' in task.config['vars']
|
483
|
-
assert 'yum_repos' in task.config['vars']
|
484
|
-
|
485
|
-
def test_teardown_cleanup_with_no_vars(self):
|
486
|
-
self.task_config.update(dict(
|
487
|
-
playbook=[],
|
488
|
-
cleanup=True,
|
489
|
-
))
|
490
|
-
task = self.klass(self.ctx, self.task_config)
|
491
|
-
task.inventory = "fake"
|
492
|
-
task.generated_playbook = True
|
493
|
-
task.playbook_file = Mock()
|
494
|
-
task.playbook_file.name = 'fake'
|
495
|
-
with patch.object(self.klass, 'execute_playbook') as m_execute:
|
496
|
-
with patch.object(ansible.os, 'remove'):
|
497
|
-
task.teardown()
|
498
|
-
task._build_args()
|
499
|
-
assert m_execute.called
|
500
|
-
assert 'cleanup' in task.config['vars']
|
501
|
-
|
502
|
-
|
503
|
-
class TestCephLabTask(TestAnsibleTask):
|
504
|
-
klass = CephLab
|
505
|
-
task_name = 'ansible.cephlab'
|
506
|
-
|
507
|
-
def setup(self):
|
508
|
-
super(TestCephLabTask, self).setup()
|
509
|
-
self.task_config = dict()
|
510
|
-
|
511
|
-
def start_patchers(self):
|
512
|
-
super(TestCephLabTask, self).start_patchers()
|
513
|
-
self.patchers['fetch_repo'] = patch(
|
514
|
-
'teuthology.task.ansible.fetch_repo',
|
515
|
-
)
|
516
|
-
self.patchers['fetch_repo'].return_value = 'PATH'
|
517
|
-
|
518
|
-
def fake_get_playbook(self):
|
519
|
-
self.playbook_file = Mock()
|
520
|
-
self.playbook_file.name = 'cephlab.yml'
|
521
|
-
|
522
|
-
self.patchers['get_playbook'] = patch(
|
523
|
-
'teuthology.task.ansible.CephLab.get_playbook',
|
524
|
-
new=fake_get_playbook,
|
525
|
-
)
|
526
|
-
for name in self.patchers.keys():
|
527
|
-
self.start_patcher(name)
|
528
|
-
|
529
|
-
@patch('teuthology.task.ansible.fetch_repo')
|
530
|
-
def test_find_repo_http(self, m_fetch_repo):
|
531
|
-
repo = os.path.join(config.ceph_git_base_url,
|
532
|
-
'ceph-cm-ansible.git')
|
533
|
-
task = self.klass(self.ctx, dict())
|
534
|
-
task.find_repo()
|
535
|
-
m_fetch_repo.assert_called_once_with(repo, 'master')
|
536
|
-
|
537
|
-
def test_playbook_file(self):
|
538
|
-
fake_playbook = [dict(fake_playbook=True)]
|
539
|
-
fake_playbook_obj = StringIO(yaml.safe_dump(fake_playbook))
|
540
|
-
playbook = 'cephlab.yml'
|
541
|
-
fake_playbook_obj.name = playbook
|
542
|
-
task = self.klass(self.ctx, dict())
|
543
|
-
task.repo_path = '/tmp/fake/repo'
|
544
|
-
self.mocks['file'].return_value = fake_playbook_obj
|
545
|
-
task.get_playbook()
|
546
|
-
assert task.playbook_file.name == playbook
|
547
|
-
|
548
|
-
def test_generate_inventory(self):
|
549
|
-
self.task_config.update(dict(
|
550
|
-
playbook=[]
|
551
|
-
))
|
552
|
-
task = self.klass(self.ctx, self.task_config)
|
553
|
-
hosts_file_path = '/my/hosts/file'
|
554
|
-
hosts_file_obj = StringIO()
|
555
|
-
hosts_file_obj.name = hosts_file_path
|
556
|
-
self.mocks['mkdtemp'].return_value = os.path.dirname(hosts_file_path)
|
557
|
-
self.mocks['file'].return_value = hosts_file_obj
|
558
|
-
task.generate_inventory()
|
559
|
-
assert task.generated_inventory is True
|
560
|
-
assert task.inventory == os.path.dirname(hosts_file_path)
|
561
|
-
hosts_file_obj.seek(0)
|
562
|
-
assert hosts_file_obj.readlines() == [
|
563
|
-
'[testnodes]\n',
|
564
|
-
'remote1\n',
|
565
|
-
'remote2\n',
|
566
|
-
]
|
567
|
-
|
568
|
-
def test_fail_status_dead(self):
|
569
|
-
self.task_config.update(dict(
|
570
|
-
playbook=[],
|
571
|
-
))
|
572
|
-
self.mocks['mkdtemp'].return_value = '/inventory/dir'
|
573
|
-
task = self.klass(self.ctx, self.task_config)
|
574
|
-
task.ctx.summary = dict()
|
575
|
-
task.setup()
|
576
|
-
with patch.object(ansible.pexpect, 'run') as m_run:
|
577
|
-
with patch('teuthology.task.ansible.open') as m_open:
|
578
|
-
fake_failure_log = Mock()
|
579
|
-
fake_failure_log.__enter__ = Mock()
|
580
|
-
fake_failure_log.__exit__ = Mock()
|
581
|
-
m_open.return_value = fake_failure_log
|
582
|
-
m_run.return_value = ('', 1)
|
583
|
-
with raises(CommandFailedError):
|
584
|
-
task.execute_playbook()
|
585
|
-
assert task.ctx.summary.get('status') == 'dead'
|
586
|
-
|
587
|
-
def test_execute_playbook_fail(self):
|
588
|
-
self.mocks['mkdtemp'].return_value = '/inventory/dir'
|
589
|
-
task = self.klass(self.ctx, self.task_config)
|
590
|
-
task.setup()
|
591
|
-
with patch.object(ansible.pexpect, 'run') as m_run:
|
592
|
-
with patch('teuthology.task.ansible.open') as m_open:
|
593
|
-
fake_failure_log = Mock()
|
594
|
-
fake_failure_log.__enter__ = Mock()
|
595
|
-
fake_failure_log.__exit__ = Mock()
|
596
|
-
m_open.return_value = fake_failure_log
|
597
|
-
m_run.return_value = ('', 1)
|
598
|
-
with raises(CommandFailedError):
|
599
|
-
task.execute_playbook()
|
600
|
-
assert task.ctx.summary.get('status') == 'dead'
|
601
|
-
|
602
|
-
@mark.skip("Unsupported")
|
603
|
-
def test_generate_playbook(self):
|
604
|
-
pass
|
605
|
-
|
606
|
-
@mark.skip("Unsupported")
|
607
|
-
def test_playbook_http(self):
|
608
|
-
pass
|
609
|
-
|
610
|
-
@mark.skip("Unsupported")
|
611
|
-
def test_playbook_none(self):
|
612
|
-
pass
|
613
|
-
|
614
|
-
@mark.skip("Unsupported")
|
615
|
-
def test_playbook_wrong_type(self):
|
616
|
-
pass
|
617
|
-
|
618
|
-
@mark.skip("Unsupported")
|
619
|
-
def test_playbook_list(self):
|
620
|
-
pass
|
621
|
-
|
622
|
-
@mark.skip("Test needs to be reimplemented for this class")
|
623
|
-
def test_playbook_file_missing(self):
|
624
|
-
pass
|