Merge "Remove get_repo_tag"
[functest.git] / functest / tests / unit / ci / test_prepare_env.py
1 #!/usr/bin/env python
2
3 # All rights reserved. This program and the accompanying materials
4 # are made available under the terms of the Apache License, Version 2.0
5 # which accompanies this distribution, and is available at
6 # http://www.apache.org/licenses/LICENSE-2.0
7
8 import logging
9 import unittest
10
11 import mock
12
13 from functest.ci import prepare_env
14 from functest.tests.unit import test_utils
15 from functest.utils.constants import CONST
16 from opnfv.utils import constants as opnfv_constants
17
18
19 class PrepareEnvTesting(unittest.TestCase):
20
21     def setUp(self):
22         self.prepare_envparser = prepare_env.PrepareEnvParser()
23         self.db_url_env = 'http://foo/testdb'
24
25     @mock.patch('functest.ci.prepare_env.logger.info')
26     def test_print_separator(self, mock_logger_info):
27         str = "=============================================="
28         prepare_env.print_separator()
29         mock_logger_info.assert_called_once_with(str)
30
31     @mock.patch('functest.ci.prepare_env.logger.info')
32     @mock.patch('functest.ci.prepare_env.logger.warning')
33     def test_check_env_variables_missing_inst_type(self, mock_logger_warn,
34                                                    mock_logger_info):
35         CONST.__setattr__('INSTALLER_TYPE', None)
36         prepare_env.check_env_variables()
37         mock_logger_info.assert_any_call("Checking environment variables"
38                                          "...")
39         mock_logger_warn.assert_any_call("The env variable 'INSTALLER_TYPE'"
40                                          " is not defined.")
41
42     @mock.patch('functest.ci.prepare_env.logger.info')
43     @mock.patch('functest.ci.prepare_env.logger.warning')
44     def test_check_env_variables_missing_inst_ip(self, mock_logger_warn,
45                                                  mock_logger_info):
46         CONST.__setattr__('INSTALLER_IP', None)
47         prepare_env.check_env_variables()
48         mock_logger_info.assert_any_call("Checking environment variables"
49                                          "...")
50         mock_logger_warn.assert_any_call(
51             "The env variable 'INSTALLER_IP' is not defined. It is recommended"
52             " to extract some information from the deployment")
53
54     @mock.patch('functest.ci.prepare_env.logger.info')
55     @mock.patch('functest.ci.prepare_env.logger.warning')
56     def test_check_env_variables_with_inst_ip(self, mock_logger_warn,
57                                               mock_logger_info):
58         CONST.__setattr__('INSTALLER_IP', mock.Mock())
59         prepare_env.check_env_variables()
60         mock_logger_info.assert_any_call("Checking environment variables"
61                                          "...")
62         mock_logger_info.assert_any_call(test_utils.
63                                          SubstrMatch("    INSTALLER_IP="))
64
65     @mock.patch('functest.ci.prepare_env.logger.info')
66     @mock.patch('functest.ci.prepare_env.logger.warning')
67     def test_check_env_variables_missing_scenario(self, mock_logger_warn,
68                                                   mock_logger_info):
69         CONST.__setattr__('DEPLOY_SCENARIO', None)
70         prepare_env.check_env_variables()
71         mock_logger_info.assert_any_call("Checking environment variables"
72                                          "...")
73         mock_logger_warn.assert_any_call("The env variable"
74                                          " 'DEPLOY_SCENARIO' is not defined"
75                                          ". Setting CI_SCENARIO=undefined.")
76
77     @mock.patch('functest.ci.prepare_env.logger.info')
78     @mock.patch('functest.ci.prepare_env.logger.warning')
79     def test_check_env_variables_with_scenario(self, mock_logger_warn,
80                                                mock_logger_info):
81         CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
82         prepare_env.check_env_variables()
83         mock_logger_info.assert_any_call("Checking environment variables"
84                                          "...")
85         mock_logger_info.assert_any_call(test_utils.
86                                          SubstrMatch("DEPLOY_SCENARIO="))
87
88     @mock.patch('functest.ci.prepare_env.logger.info')
89     @mock.patch('functest.ci.prepare_env.logger.warning')
90     def test_check_env_variables_with_ci_debug(self, mock_logger_warn,
91                                                mock_logger_info):
92         CONST.__setattr__('CI_DEBUG', mock.Mock())
93         prepare_env.check_env_variables()
94         mock_logger_info.assert_any_call("Checking environment variables"
95                                          "...")
96         mock_logger_info.assert_any_call(test_utils.
97                                          SubstrMatch("    CI_DEBUG="))
98
99     @mock.patch('functest.ci.prepare_env.logger.info')
100     @mock.patch('functest.ci.prepare_env.logger.warning')
101     def test_check_env_variables_with_node(self, mock_logger_warn,
102                                            mock_logger_info):
103         CONST.__setattr__('NODE_NAME', mock.Mock())
104         prepare_env.check_env_variables()
105         mock_logger_info.assert_any_call("Checking environment variables"
106                                          "...")
107         mock_logger_info.assert_any_call(test_utils.
108                                          SubstrMatch("    NODE_NAME="))
109
110     @mock.patch('functest.ci.prepare_env.logger.info')
111     @mock.patch('functest.ci.prepare_env.logger.warning')
112     def test_check_env_variables_with_build_tag(self, mock_logger_warn,
113                                                 mock_logger_info):
114         CONST.__setattr__('BUILD_TAG', mock.Mock())
115         prepare_env.check_env_variables()
116         mock_logger_info.assert_any_call("Checking environment variables"
117                                          "...")
118
119         mock_logger_info.assert_any_call(test_utils.
120                                          SubstrMatch("    BUILD_TAG="))
121
122     @mock.patch('functest.ci.prepare_env.logger.info')
123     @mock.patch('functest.ci.prepare_env.logger.warning')
124     def test_check_env_variables_with_is_ci_run(self, mock_logger_warn,
125                                                 mock_logger_info):
126         CONST.__setattr__('IS_CI_RUN', mock.Mock())
127         prepare_env.check_env_variables()
128         mock_logger_info.assert_any_call("Checking environment variables"
129                                          "...")
130
131         mock_logger_info.assert_any_call(test_utils.
132                                          SubstrMatch("    IS_CI_RUN="))
133
134     def test_get_deployment_handler_missing_const_vars(self):
135         with mock.patch('functest.ci.prepare_env.'
136                         'factory.Factory.get_handler') as m:
137             CONST.__setattr__('INSTALLER_IP', None)
138             prepare_env.get_deployment_handler()
139             self.assertFalse(m.called)
140
141             CONST.__setattr__('INSTALLER_TYPE', None)
142             prepare_env.get_deployment_handler()
143             self.assertFalse(m.called)
144
145     @mock.patch('functest.ci.prepare_env.logger.debug')
146     def test_get_deployment_handler_missing_print_deploy_info(self,
147                                                               mock_debug):
148         with mock.patch('functest.ci.prepare_env.'
149                         'factory.Factory.get_handler') as m, \
150             mock.patch('functest.ci.prepare_env.'
151                        'ft_utils.get_parameter_from_yaml',
152                        side_effect=ValueError):
153             CONST.__setattr__('INSTALLER_IP', 'test_ip')
154             CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
155             opnfv_constants.INSTALLERS = ['test_inst_type']
156             prepare_env.get_deployment_handler()
157             msg = ('Printing deployment info is not supported for '
158                    'test_inst_type')
159             mock_debug.assert_any_call(msg)
160             self.assertFalse(m.called)
161
162     @mock.patch('functest.ci.prepare_env.logger.debug')
163     def test_get_deployment_handler_exception(self, mock_debug):
164         with mock.patch('functest.ci.prepare_env.'
165                         'factory.Factory.get_handler',
166                         side_effect=Exception), \
167             mock.patch('functest.ci.prepare_env.'
168                        'ft_utils.get_parameter_from_yaml'):
169             CONST.__setattr__('INSTALLER_IP', 'test_ip')
170             CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
171             opnfv_constants.INSTALLERS = ['test_inst_type']
172             prepare_env.get_deployment_handler()
173             self.assertTrue(mock_debug.called)
174
175     @mock.patch('functest.ci.prepare_env.logger.info')
176     @mock.patch('functest.ci.prepare_env.logger.debug')
177     def test_create_directories_missing_dir(self, mock_logger_debug,
178                                             mock_logger_info):
179         with mock.patch('functest.ci.prepare_env.os.path.exists',
180                         return_value=False), \
181                 mock.patch('functest.ci.prepare_env.os.makedirs') \
182                 as mock_method:
183             prepare_env.create_directories()
184             mock_logger_info.assert_any_call("Creating needed directories...")
185             mock_method.assert_any_call(
186                 CONST.__getattribute__('dir_functest_conf'))
187             mock_method.assert_any_call(
188                 CONST.__getattribute__('dir_functest_data'))
189             mock_method.assert_any_call(
190                 CONST.__getattribute__('dir_functest_images'))
191             mock_logger_info.assert_any_call("    %s created." %
192                                              CONST.__getattribute__(
193                                                  'dir_functest_conf'))
194             mock_logger_info.assert_any_call("    %s created." %
195                                              CONST.__getattribute__(
196                                                  'dir_functest_data'))
197             mock_logger_info.assert_any_call("    %s created." %
198                                              CONST.__getattribute__(
199                                                  'dir_functest_images'))
200
201     @mock.patch('functest.ci.prepare_env.logger.info')
202     @mock.patch('functest.ci.prepare_env.logger.debug')
203     def test_create_directories_with_dir(self, mock_logger_debug,
204                                          mock_logger_info):
205         with mock.patch('functest.ci.prepare_env.os.path.exists',
206                         return_value=True):
207             prepare_env.create_directories()
208             mock_logger_info.assert_any_call("Creating needed directories...")
209             mock_logger_debug.assert_any_call("   %s already exists." %
210                                               CONST.__getattribute__(
211                                                   'dir_functest_conf'))
212             mock_logger_debug.assert_any_call("   %s already exists." %
213                                               CONST.__getattribute__(
214                                                   'dir_functest_data'))
215             mock_logger_debug.assert_any_call("   %s already exists." %
216                                               CONST.__getattribute__(
217                                                   'dir_functest_images'))
218
219     def _get_env_cred_dict(self, os_prefix=''):
220         return {'OS_USERNAME': os_prefix + 'username',
221                 'OS_PASSWORD': os_prefix + 'password',
222                 'OS_AUTH_URL': 'http://test_ip:test_port/v2.0',
223                 'OS_TENANT_NAME': os_prefix + 'tenant_name',
224                 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name',
225                 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name',
226                 'OS_PROJECT_NAME': os_prefix + 'project_name',
227                 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
228                 'OS_REGION_NAME': os_prefix + 'region_name'}
229
230     @mock.patch('functest.ci.prepare_env.logger.error')
231     @mock.patch('functest.ci.prepare_env.logger.info')
232     @mock.patch('functest.ci.prepare_env.logger.warning')
233     def test_source_rc_missing_rc_file(self, mock_logger_warn,
234                                        mock_logger_info,
235                                        mock_logger_error):
236         with mock.patch('functest.ci.prepare_env.os.path.isfile',
237                         return_value=True), \
238                 mock.patch('functest.ci.prepare_env.os.path.getsize',
239                            return_value=0), \
240                 self.assertRaises(Exception):
241             CONST.__setattr__('openstack_creds', 'test_creds')
242             prepare_env.source_rc_file()
243
244     def test_source_rc_missing_installer_ip(self):
245         with mock.patch('functest.ci.prepare_env.os.path.isfile',
246                         return_value=False), \
247                 self.assertRaises(Exception):
248             CONST.__setattr__('INSTALLER_IP', None)
249             CONST.__setattr__('openstack_creds', 'test_creds')
250             prepare_env.source_rc_file()
251
252     def test_source_rc_missing_installer_type(self):
253         with mock.patch('functest.ci.prepare_env.os.path.isfile',
254                         return_value=False), \
255                 self.assertRaises(Exception):
256             CONST.__setattr__('INSTALLER_IP', 'test_ip')
257             CONST.__setattr__('openstack_creds', 'test_creds')
258             CONST.__setattr__('INSTALLER_TYPE', 'test_type')
259             opnfv_constants.INSTALLERS = []
260             prepare_env.source_rc_file()
261
262     def test_source_rc_missing_os_credfile_ci_inst(self):
263         with mock.patch('functest.ci.prepare_env.os.path.isfile',
264                         return_value=False), \
265                 mock.patch('functest.ci.prepare_env.os.path.getsize'), \
266                 mock.patch('functest.ci.prepare_env.os.path.join'), \
267                 mock.patch('functest.ci.prepare_env.subprocess.Popen') \
268                 as mock_subproc_popen, \
269                 self.assertRaises(Exception):
270             CONST.__setattr__('openstack_creds', None)
271             CONST.__setattr__('INSTALLER_IP', 'test_ip')
272             CONST.__setattr__('INSTALLER_TYPE', 'test_type')
273             opnfv_constants.INSTALLERS = ['test_type']
274
275             process_mock = mock.Mock()
276             attrs = {'communicate.return_value': ('output', 'error'),
277                      'return_code': 1}
278             process_mock.configure_mock(**attrs)
279             mock_subproc_popen.return_value = process_mock
280
281             prepare_env.source_rc_file()
282
283     @mock.patch('functest.ci.prepare_env.logger.debug')
284     def test_patch_file(self, mock_logger_debug):
285         with mock.patch("__builtin__.open", mock.mock_open()), \
286             mock.patch('functest.ci.prepare_env.yaml.safe_load',
287                        return_value={'test_scenario': {'tkey': 'tvalue'}}), \
288             mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
289                        return_value={'tkey1': 'tvalue1'}), \
290             mock.patch('functest.ci.prepare_env.os.remove') as m, \
291                 mock.patch('functest.ci.prepare_env.yaml.dump'):
292             CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
293             prepare_env.patch_file('test_file')
294             self.assertTrue(m.called)
295
296     @mock.patch('functest.ci.prepare_env.ft_utils.get_functest_yaml',
297                 return_value={'tkey1': 'tvalue1'})
298     @mock.patch('functest.ci.prepare_env.yaml.safe_load',
299                 return_value={'test_scenario': {'tkey': 'tvalue'}})
300     @mock.patch('functest.ci.prepare_env.update_db_url')
301     def test_update_db_url(self, mock_db_url, mock_safe_load,
302                            mock_get_functest_yaml):
303         CONST.__setattr__('DEPLOY_SCENARIO', 'default_scenario')
304         with mock.patch("__builtin__.open", mock.mock_open()), \
305             mock.patch('functest.ci.prepare_env.yaml.dump'), \
306                 mock.patch.dict('functest.ci.prepare_env.os.environ',
307                                 {'TEST_DB_URL': self.db_url_env},
308                                 clear=True):
309             prepare_env.update_config_file()
310             self.assertTrue(mock_db_url.called)
311
312     def test_verify_deployment(self):
313         with mock.patch('functest.ci.check_deployment.CheckDeployment') \
314                 as mock_check_deployment:
315             prepare_env.verify_deployment()
316             self.assertTrue(mock_check_deployment.called)
317
318     def test_verify_deployment_error(self):
319         with mock.patch('functest.ci.prepare_env.'
320                         'check_deployment.CheckDeployment',
321                         return_value=('test_', None)), \
322                 self.assertRaises(Exception):
323             prepare_env.verify_deployment()
324
325     def _get_rally_creds(self):
326         return {"type": "ExistingCloud",
327                 "admin": {"username": 'test_user_name',
328                           "password": 'test_password',
329                           "tenant": 'test_tenant'}}
330
331     @mock.patch('functest.ci.prepare_env.os_utils.get_credentials_for_rally')
332     @mock.patch('functest.ci.prepare_env.logger.info')
333     @mock.patch('functest.ci.prepare_env.ft_utils.execute_command_raise')
334     @mock.patch('functest.ci.prepare_env.ft_utils.execute_command')
335     def test_install_rally(self, mock_exec, mock_exec_raise, mock_logger_info,
336                            mock_os_utils):
337
338         mock_os_utils.return_value = self._get_rally_creds()
339
340         prepare_env.install_rally()
341
342         cmd = "rally deployment destroy opnfv-rally"
343         error_msg = "Deployment %s does not exist." % \
344                     CONST.__getattribute__('rally_deployment_name')
345         mock_logger_info.assert_any_call("Creating Rally environment...")
346         mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
347
348         cmd = "rally deployment create --file=rally_conf.json --name="
349         cmd += CONST.__getattribute__('rally_deployment_name')
350         error_msg = "Problem while creating Rally deployment"
351         mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
352
353         cmd = "rally deployment check"
354         error_msg = ("OpenStack not responding or "
355                      "faulty Rally deployment.")
356         mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
357
358         cmd = "rally deployment list"
359         error_msg = ("Problem while listing "
360                      "Rally deployment.")
361         mock_exec.assert_any_call(cmd, error_msg=error_msg)
362
363         cmd = "rally plugin list | head -5"
364         error_msg = ("Problem while showing "
365                      "Rally plugins.")
366         mock_exec.assert_any_call(cmd, error_msg=error_msg)
367
368     @mock.patch('functest.ci.prepare_env.logger.debug')
369     def test_install_tempest(self, mock_logger_debug):
370         mock_popen = mock.Mock()
371         attrs = {'poll.return_value': None,
372                  'stdout.readline.return_value': '0'}
373         mock_popen.configure_mock(**attrs)
374
375         CONST.__setattr__('tempest_deployment_name', 'test_dep_name')
376         with mock.patch('functest.ci.prepare_env.'
377                         'ft_utils.execute_command_raise',
378                         side_effect=Exception), \
379             mock.patch('functest.ci.prepare_env.subprocess.Popen',
380                        return_value=mock_popen), \
381                 self.assertRaises(Exception):
382             prepare_env.install_tempest()
383             mock_logger_debug.assert_any_call("Tempest test_dep_name"
384                                               " does not exist")
385
386     def test_create_flavor(self):
387         with mock.patch('functest.ci.prepare_env.'
388                         'os_utils.get_or_create_flavor',
389                         return_value=('test_', None)), \
390                 self.assertRaises(Exception) as context:
391             prepare_env.create_flavor()
392             msg = 'Failed to create flavor'
393             self.assertTrue(msg in context)
394
395     @mock.patch('functest.ci.prepare_env.sys.exit')
396     @mock.patch('functest.ci.prepare_env.logger.error')
397     def test_check_environment_missing_file(self, mock_logger_error,
398                                             mock_sys_exit):
399         with mock.patch('functest.ci.prepare_env.os.path.isfile',
400                         return_value=False), \
401                 self.assertRaises(Exception):
402             prepare_env.check_environment()
403
404     @mock.patch('functest.ci.prepare_env.sys.exit')
405     @mock.patch('functest.ci.prepare_env.logger.error')
406     def test_check_environment_with_error(self, mock_logger_error,
407                                           mock_sys_exit):
408         with mock.patch('functest.ci.prepare_env.os.path.isfile',
409                         return_value=True), \
410             mock.patch("__builtin__.open", mock.mock_open(read_data='0')), \
411                 self.assertRaises(Exception):
412             prepare_env.check_environment()
413
414     @mock.patch('functest.ci.prepare_env.logger.info')
415     def test_check_environment_default(self, mock_logger_info):
416         with mock.patch('functest.ci.prepare_env.os.path.isfile',
417                         return_value=True):
418             with mock.patch("__builtin__.open", mock.mock_open(read_data='1')):
419                 prepare_env.check_environment()
420                 mock_logger_info.assert_any_call("Functest environment"
421                                                  " is installed.")
422
423     @mock.patch('functest.ci.prepare_env.check_environment')
424     @mock.patch('functest.ci.prepare_env.create_flavor')
425     @mock.patch('functest.ci.prepare_env.install_tempest')
426     @mock.patch('functest.ci.prepare_env.install_rally')
427     @mock.patch('functest.ci.prepare_env.verify_deployment')
428     @mock.patch('functest.ci.prepare_env.update_config_file')
429     @mock.patch('functest.ci.prepare_env.source_rc_file')
430     @mock.patch('functest.ci.prepare_env.create_directories')
431     @mock.patch('functest.ci.prepare_env.check_env_variables')
432     @mock.patch('functest.ci.prepare_env.logger.info')
433     def test_main_start(self, mock_logger_info, mock_env_var,
434                         mock_create_dir, mock_source_rc, mock_update_config,
435                         mock_verify_depl, mock_install_rally,
436                         mock_install_temp, mock_create_flavor,
437                         mock_check_env):
438         with mock.patch("__builtin__.open", mock.mock_open()) as m:
439             args = {'action': 'start'}
440             self.assertEqual(prepare_env.prepare_env(**args), 0)
441             mock_logger_info.assert_any_call("######### Preparing Functest "
442                                              "environment #########\n")
443             self.assertTrue(mock_env_var.called)
444             self.assertTrue(mock_create_dir.called)
445             self.assertTrue(mock_source_rc.called)
446             self.assertTrue(mock_update_config.called)
447             self.assertTrue(mock_verify_depl.called)
448             self.assertTrue(mock_install_rally.called)
449             self.assertTrue(mock_install_temp.called)
450             self.assertTrue(mock_create_flavor.called)
451             m.assert_called_once_with(
452                 CONST.__getattribute__('env_active'), "w")
453             self.assertTrue(mock_check_env.called)
454
455     @mock.patch('functest.ci.prepare_env.check_environment')
456     def test_main_check(self, mock_check_env):
457         args = {'action': 'check'}
458         self.assertEqual(prepare_env.prepare_env(**args), 0)
459         self.assertTrue(mock_check_env.called)
460
461     @mock.patch('functest.ci.prepare_env.logger.error')
462     def test_main_no_arg(self, mock_logger_error):
463         args = {'action': 'not_valid'}
464         self.assertEqual(prepare_env.prepare_env(**args), -1)
465         mock_logger_error.assert_called_once_with('Argument not valid.')
466
467
468 if __name__ == "__main__":
469     logging.disable(logging.CRITICAL)
470     unittest.main(verbosity=2)