Files
charm-watcher/unit_tests/test_lib_charm_openstack_watcher.py
Hervé Beraud 628ec6b449 Stop to use the __future__ module.
The __future__ module [1] was used in this context to ensure compatibility
between python 2 and python 3.

We previously dropped the support of python 2.7 [2] and now we only support
python 3 so we don't need to continue to use this module and the imports
listed below.

Imports commonly used and their related PEPs:
- `division` is related to PEP 238 [3]
- `print_function` is related to PEP 3105 [4]
- `unicode_literals` is related to PEP 3112 [5]
- `with_statement` is related to PEP 343 [6]
- `absolute_import` is related to PEP 328 [7]

[1] https://docs.python.org/3/library/__future__.html
[2] https://governance.openstack.org/tc/goals/selected/ussuri/drop-py27.html
[3] https://www.python.org/dev/peps/pep-0238
[4] https://www.python.org/dev/peps/pep-3105
[5] https://www.python.org/dev/peps/pep-3112
[6] https://www.python.org/dev/peps/pep-0343
[7] https://www.python.org/dev/peps/pep-0328

Change-Id: Ie8a7acebd0e0192a676b440d9479c0f64f5e8a9a
2020-06-02 20:05:46 +02:00

332 lines
12 KiB
Python

# Copyright 2020 GRNET SA
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from collections import OrderedDict
from unittest import mock
import charmhelpers
import charm.openstack.watcher as watcher
import charms_openstack.test_utils as test_utils
class Helper(test_utils.PatchHelper):
def setUp(self):
super().setUp()
self.patch_release(watcher.WatcherCharm.release)
class TestWatcherCharmConfigProperties(Helper):
def test_planner_weights(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = [
'weight',
'{"weights": "change_node_power_state:9,'
'change_nova_service_state:50"}']
conf_dict = OrderedDict()
conf_dict['weights'] = \
'change_node_power_state:9,change_nova_service_state:50'
self.config_flags_parser.return_value = conf_dict
self.assertEqual(
watcher.planner_weights(cls),
'change_node_power_state:9,change_nova_service_state:50')
def test_planner_weights_invalid(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch('charm.openstack.watcher.WARNING', 'WARNING')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = ['weight', '{}']
self.config_flags_parser.return_value = OrderedDict()
self.assertEqual(watcher.planner_weights(cls), None)
self.log.assert_called_once_with(
'Provided planner-config dictionary does not contain '
'key weights - ignoring', level=self.WARNING)
def test_planner_parallelization(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = [
'weight',
'{"parallelization": "change_node_power_state:9,'
'change_nova_service_state:50"}']
conf_dict = OrderedDict()
conf_dict['parallelization'] = \
'change_node_power_state:9,change_nova_service_state:50'
self.config_flags_parser.return_value = conf_dict
self.assertEqual(
watcher.planner_parallelization(cls),
'change_node_power_state:9,change_nova_service_state:50')
def test_planner_parallelization_invalid(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch('charm.openstack.watcher.WARNING', 'WARNING')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = ['weight', '{}']
self.config_flags_parser.return_value = OrderedDict()
self.assertEqual(watcher.planner_parallelization(cls), None)
self.log.assert_called_once_with(
'Provided planner-config dictionary does not contain '
'key parallelization - ignoring', level=self.WARNING)
def test_planner_check_optimize_metadata(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = [
'basic', '{"check_optimize_metadata": "true"}']
conf_dict = OrderedDict()
conf_dict['check_optimize_metadata'] = 'true'
self.config_flags_parser.return_value = conf_dict
self.assertEqual(
watcher.planner_check_optimize_metadata(cls), 'true')
def test_planner_check_optimize_metadata_invalid(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch('charm.openstack.watcher.WARNING', 'WARNING')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = ['basic', '{}']
self.config_flags_parser.return_value = OrderedDict()
self.assertEqual(watcher.planner_check_optimize_metadata(cls), None)
self.log.assert_called_once_with(
'Provided planner-config dictionary does not contain '
'key check_optimize_metadata - ignoring', level=self.WARNING)
def test_planner_ex_pools(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = [
'storage_capacity_balance', '{"ex_pools": "local_vstorage"}']
conf_dict = OrderedDict()
conf_dict['ex_pools'] = 'local_vstorage'
self.config_flags_parser.return_value = conf_dict
self.assertEqual(
watcher.planner_ex_pools(cls), 'local_vstorage')
def test_planner_ex_pools_invalid(self):
cls = mock.MagicMock()
self.patch('charm.openstack.watcher.config', 'config')
self.patch('charm.openstack.watcher.log', 'log')
self.patch('charm.openstack.watcher.WARNING', 'WARNING')
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config.side_effect = ['storage_capacity_balance', '{}']
self.config_flags_parser.return_value = OrderedDict()
self.assertEqual(watcher.planner_ex_pools(cls), None)
self.log.assert_called_once_with(
'Provided planner-config dictionary does not contain key ex_pools '
'- ignoring', level=self.WARNING)
class TestWatcherCharm(Helper):
def _patch_config_and_charm(self, config):
self.patch_object(charmhelpers.core.hookenv, 'config')
def cf(key=None):
if key is not None:
return config[key]
return config
self.config.side_effect = cf
c = watcher.WatcherCharm()
return c
def _patch_get_adapter(self, c):
self.patch_object(c, 'get_adapter')
def _helper(x):
self.var = x
return self.out
self.get_adapter.side_effect = _helper
def test_get_amqp_credentials(self):
c = watcher.WatcherCharm()
result = c.get_amqp_credentials()
self.assertEqual(result, ('watcher', 'openstack'))
def test_get_database_setup(self):
c = watcher.WatcherCharm()
result = c.get_database_setup()
self.assertEqual(result, [{'database': 'watcher',
'username': 'watcher'}])
def test_custom_assess_status_check1(self):
config = {
'datasources': 'gnocchi',
'planner': 'weight',
'planner-config': '{"weights": "42", "parallelization": "42"}'
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
conf_dict = OrderedDict()
conf_dict['weights'] = '42'
conf_dict['parallelization'] = '42'
self.config_flags_parser.return_value = conf_dict
self.assertEqual(c.options.datasources, config['datasources'])
self.assertEqual(c.options.planner, config['planner'])
self.assertEqual(c.options.planner_config, config['planner-config'])
self.assertEqual(c.custom_assess_status_check(), (None, None))
def test_custom_assess_status_check2(self):
config = {
'datasources': 'gnocchi',
'planner': 'invalid',
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.assertEqual(c.options.datasources, config['datasources'])
self.assertEqual(c.options.planner, config['planner'])
self.assertEqual(
c.custom_assess_status_check(),
('blocked',
'Invalid planner: {}. Available options are: '
'weights, workload_stabilization, basic, '
'storage_capacity_balance'.format(config['planner'])))
def test_custom_assess_status_check3(self):
config = {
'datasources': 'gnocchi',
'planner': 'basic',
'planner-config': 'invalid'
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.patch(
'charm.openstack.watcher.config_flags_parser',
'config_flags_parser')
self.config_flags_parser.return_value = OrderedDict()
self.assertEqual(c.options.datasources, config['datasources'])
self.assertEqual(c.options.planner, config['planner'])
self.assertEqual(c.options.planner_config, config['planner-config'])
self.assertEqual(
c.custom_assess_status_check(),
('blocked',
'Provided planner {} must contain only the following '
'configuration attributes: check_optimize_metadata'.format(
config['planner'])))
def test_custom_assess_status_check4(self):
config = {
'datasources': None,
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.assertEqual(c.options.datasources, config['datasources'])
self.assertEqual(
c.custom_assess_status_check(),
('blocked',
'datasources not set'))
def test_custom_assess_status_check5(self):
config = {
'datasources': 'invalid',
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.assertEqual(c.options.datasources, config['datasources'])
self.assertEqual(
c.custom_assess_status_check(),
('blocked',
'Provided datasources {} does not contain valid options'.format(
config['datasources'])))
def test_custom_assess_status_check6(self):
config = {
'datasources': 'grafana',
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.patch_object(c, 'grafana_configuration_complete')
self.grafana_configuration_complete.return_value = False
self.assertEqual(c.options.datasources, config['datasources'])
self.assertEqual(
c.custom_assess_status_check(),
('blocked',
'grafana datasource requires all grafana related options to be '
'set'))
def test_grafana_configuration_complete(self):
config = {
'grafana-auth-token': 1,
'grafana-base-url': 2,
'grafana-project-id-map': 3,
'grafana-database-map': 4,
'grafana-attribute-map': 5,
'grafana-translator-map': 6,
'grafana-query-map': 7,
'grafana-retention-periods': 8,
}
c = self._patch_config_and_charm(config)
self._patch_get_adapter(c)
self.assertEqual(c.options.grafana_auth_token, 1)
self.assertEqual(c.options.grafana_base_url, 2)
self.assertEqual(c.options.grafana_project_id_map, 3)
self.assertEqual(c.options.grafana_database_map, 4)
self.assertEqual(c.options.grafana_attribute_map, 5)
self.assertEqual(c.options.grafana_translator_map, 6)
self.assertEqual(c.options.grafana_query_map, 7)
self.assertEqual(c.options.grafana_retention_periods, 8)
self.assertEqual(c.grafana_configuration_complete(), True)