* Add the ability to wait for bespoke statuses This change adds the ability to wait for bespoke work load statuses and messages. These are defined in the charms tests.yaml * Add unit tests * Remove debug print * Fix typos and add checks for errored units * Restore juju_wait as openstack_utils imports it
201 lines
8.5 KiB
Python
201 lines
8.5 KiB
Python
import jinja2
|
|
import mock
|
|
|
|
import zaza.charm_lifecycle.deploy as lc_deploy
|
|
import unit_tests.utils as ut_utils
|
|
|
|
|
|
class TestCharmLifecycleDeploy(ut_utils.BaseTestCase):
|
|
|
|
def test_is_valid_env_key(self):
|
|
self.assertTrue(lc_deploy.is_valid_env_key('OS_VIP04'))
|
|
self.assertTrue(lc_deploy.is_valid_env_key('FIP_RANGE'))
|
|
self.assertTrue(lc_deploy.is_valid_env_key('GATEWAY'))
|
|
self.assertTrue(lc_deploy.is_valid_env_key('NAME_SERVER'))
|
|
self.assertTrue(lc_deploy.is_valid_env_key('NET_ID'))
|
|
self.assertTrue(lc_deploy.is_valid_env_key('VIP_RANGE'))
|
|
self.assertFalse(lc_deploy.is_valid_env_key('AMULET_OS_VIP'))
|
|
self.assertFalse(lc_deploy.is_valid_env_key('ZAZA_TEMPLATE_VIP00'))
|
|
self.assertFalse(lc_deploy.is_valid_env_key('PATH'))
|
|
|
|
def test_get_template_context_from_env(self):
|
|
self.patch_object(lc_deploy.os, 'environ')
|
|
self.environ.items.return_value = [
|
|
('AMULET_OS_VIP', '10.10.0.2'),
|
|
('OS_VIP04', '10.10.0.2'),
|
|
('ZAZA_TEMPLATE_VIP00', '20.3.4.5'),
|
|
('PATH', 'aa')]
|
|
self.assertEqual(
|
|
lc_deploy.get_template_context_from_env(),
|
|
{'OS_VIP04': '10.10.0.2'}
|
|
)
|
|
|
|
def test_get_charm_config_context(self):
|
|
self.patch_object(lc_deploy.utils, 'get_charm_config')
|
|
self.get_charm_config.return_value = {
|
|
'charm_name': 'mycharm'}
|
|
self.assertEqual(
|
|
lc_deploy.get_charm_config_context(),
|
|
{'charm_location': '../../../mycharm', 'charm_name': 'mycharm'})
|
|
|
|
def test_get_template_overlay_context(self):
|
|
self.patch_object(lc_deploy, 'get_template_context_from_env')
|
|
self.patch_object(lc_deploy, 'get_charm_config_context')
|
|
self.get_template_context_from_env.return_value = {
|
|
'OS_VIP04': '10.10.0.2'}
|
|
self.get_charm_config_context.return_value = {
|
|
'charm_location': '../../../mycharm',
|
|
'charm_name': 'mycharm'}
|
|
self.assertEqual(
|
|
lc_deploy.get_template_overlay_context(),
|
|
{
|
|
'OS_VIP04': '10.10.0.2',
|
|
'charm_location': '../../../mycharm',
|
|
'charm_name': 'mycharm'})
|
|
|
|
def test_get_overlay_template_dir(self):
|
|
self.assertEqual(
|
|
lc_deploy.get_overlay_template_dir(),
|
|
'tests/bundles/overlays')
|
|
|
|
def test_get_jinja2_env(self):
|
|
self.patch_object(lc_deploy, 'get_overlay_template_dir')
|
|
self.get_overlay_template_dir.return_value = 'mytemplatedir'
|
|
self.patch_object(lc_deploy.jinja2, 'Environment')
|
|
self.patch_object(lc_deploy.jinja2, 'FileSystemLoader')
|
|
jinja_env_mock = mock.MagicMock()
|
|
self.Environment.return_value = jinja_env_mock
|
|
self.assertEqual(
|
|
lc_deploy.get_jinja2_env(),
|
|
jinja_env_mock)
|
|
self.FileSystemLoader.assert_called_once_with('mytemplatedir')
|
|
|
|
def test_get_template_name(self):
|
|
self.assertEqual(
|
|
lc_deploy.get_template_name('mybundles/mybundle.yaml'),
|
|
'mybundle.yaml.j2')
|
|
|
|
def test_get_template(self):
|
|
self.patch_object(lc_deploy, 'get_jinja2_env')
|
|
jinja_env_mock = mock.MagicMock()
|
|
self.get_jinja2_env.return_value = jinja_env_mock
|
|
jinja_env_mock.get_template.return_value = 'mytemplate'
|
|
self.assertEqual(
|
|
lc_deploy.get_template('mybundle.yaml'),
|
|
'mytemplate')
|
|
|
|
def test_get_template_missing_template(self):
|
|
self.patch_object(lc_deploy, 'get_jinja2_env')
|
|
jinja_env_mock = mock.MagicMock()
|
|
self.get_jinja2_env.return_value = jinja_env_mock
|
|
jinja_env_mock.get_template.side_effect = \
|
|
jinja2.exceptions.TemplateNotFound(name='bob')
|
|
self.assertIsNone(lc_deploy.get_template('mybundle.yaml'))
|
|
|
|
def test_render_template(self):
|
|
self.patch_object(lc_deploy, 'get_template_overlay_context')
|
|
template_mock = mock.MagicMock()
|
|
template_mock.render.return_value = 'Template contents'
|
|
m = mock.mock_open()
|
|
with mock.patch('zaza.charm_lifecycle.deploy.open', m, create=True):
|
|
lc_deploy.render_template(template_mock, '/tmp/mybundle.yaml')
|
|
m.assert_called_once_with('/tmp/mybundle.yaml', 'w')
|
|
handle = m()
|
|
handle.write.assert_called_once_with('Template contents')
|
|
|
|
def test_render_overlay(self):
|
|
self.patch_object(lc_deploy, 'render_template')
|
|
template_mock = mock.MagicMock()
|
|
self.patch_object(lc_deploy, 'get_template')
|
|
self.get_template.return_value = template_mock
|
|
lc_deploy.render_overlay('my_overlay.yaml', '/tmp/special-dir')
|
|
self.render_template.assert_called_once_with(
|
|
template_mock,
|
|
'/tmp/special-dir/my_overlay.yaml')
|
|
|
|
def test_render_overlay_no_template(self):
|
|
self.patch_object(lc_deploy, 'get_template')
|
|
self.get_template.return_value = None
|
|
self.assertIsNone(lc_deploy.render_overlay('mybundle.yaml', '/tmp/'))
|
|
|
|
def test_render_overlays(self):
|
|
RESP = {
|
|
'mybundles/mybundle.yaml': '/tmp/mybundle.yaml'}
|
|
self.patch_object(lc_deploy, 'render_local_overlay')
|
|
self.render_local_overlay.return_value = '/tmp/local-overlay.yaml'
|
|
self.patch_object(lc_deploy, 'render_overlay')
|
|
self.render_overlay.side_effect = lambda x, y: RESP[x]
|
|
self.assertEqual(
|
|
lc_deploy.render_overlays('mybundles/mybundle.yaml', '/tmp'),
|
|
['/tmp/local-overlay.yaml', '/tmp/mybundle.yaml'])
|
|
|
|
def test_render_overlays_missing(self):
|
|
RESP = {'mybundles/mybundle.yaml': None}
|
|
self.patch_object(lc_deploy, 'render_overlay')
|
|
self.patch_object(lc_deploy, 'render_local_overlay')
|
|
self.render_local_overlay.return_value = '/tmp/local.yaml'
|
|
self.render_overlay.side_effect = lambda x, y: RESP[x]
|
|
self.assertEqual(
|
|
lc_deploy.render_overlays('mybundles/mybundle.yaml', '/tmp'),
|
|
['/tmp/local.yaml'])
|
|
|
|
def test_deploy_bundle(self):
|
|
self.patch_object(lc_deploy.utils, 'get_charm_config')
|
|
self.get_charm_config.return_value = {}
|
|
self.patch_object(lc_deploy, 'render_overlays')
|
|
self.patch_object(lc_deploy.subprocess, 'check_call')
|
|
self.render_overlays.return_value = []
|
|
lc_deploy.deploy_bundle('bun.yaml', 'newmodel')
|
|
self.check_call.assert_called_once_with(
|
|
['juju', 'deploy', '-m', 'newmodel', 'bun.yaml'])
|
|
|
|
def test_deploy(self):
|
|
self.patch_object(lc_deploy.zaza.model, 'wait_for_application_states')
|
|
self.patch_object(lc_deploy.utils, 'get_charm_config')
|
|
self.get_charm_config.return_value = {}
|
|
self.patch_object(lc_deploy, 'deploy_bundle')
|
|
lc_deploy.deploy('bun.yaml', 'newmodel')
|
|
self.deploy_bundle.assert_called_once_with('bun.yaml', 'newmodel')
|
|
self.wait_for_application_states.assert_called_once_with(
|
|
'newmodel',
|
|
{})
|
|
|
|
def test_deploy_bespoke_states(self):
|
|
self.patch_object(lc_deploy.zaza.model, 'wait_for_application_states')
|
|
self.patch_object(lc_deploy.utils, 'get_charm_config')
|
|
self.get_charm_config.return_value = {
|
|
'target_deploy_status': {
|
|
'vault': {
|
|
'workload-status': 'blocked',
|
|
'workload-status-message': 'Vault needs to be inited'}}}
|
|
self.patch_object(lc_deploy, 'deploy_bundle')
|
|
lc_deploy.deploy('bun.yaml', 'newmodel')
|
|
self.deploy_bundle.assert_called_once_with('bun.yaml', 'newmodel')
|
|
self.wait_for_application_states.assert_called_once_with(
|
|
'newmodel',
|
|
{'vault': {
|
|
'workload-status': 'blocked',
|
|
'workload-status-message': 'Vault needs to be inited'}})
|
|
|
|
def test_deploy_nowait(self):
|
|
self.patch_object(lc_deploy.zaza.model, 'wait_for_application_states')
|
|
self.patch_object(lc_deploy, 'deploy_bundle')
|
|
lc_deploy.deploy('bun.yaml', 'newmodel', wait=False)
|
|
self.deploy_bundle.assert_called_once_with('bun.yaml', 'newmodel')
|
|
self.assertFalse(self.wait_for_application_states.called)
|
|
|
|
def test_parser(self):
|
|
args = lc_deploy.parse_args([
|
|
'-m', 'mymodel',
|
|
'-b', 'bun.yaml'])
|
|
self.assertEqual(args.model, 'mymodel')
|
|
self.assertEqual(args.bundle, 'bun.yaml')
|
|
self.assertTrue(args.wait)
|
|
|
|
def test_parser_nowait(self):
|
|
args = lc_deploy.parse_args([
|
|
'-m', 'mymodel',
|
|
'-b', 'bun.yaml',
|
|
'--no-wait'])
|
|
self.assertFalse(args.wait)
|