Merge "Allow Bay templates to include Heat environments"

This commit is contained in:
Jenkins 2016-06-29 05:05:29 +00:00 committed by Gerrit Code Review
commit af7cd43652
6 changed files with 168 additions and 29 deletions

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import uuid
from heatclient.common import template_utils
@ -73,10 +74,25 @@ def _extract_template_definition(context, bay, scale_manager=None):
scale_manager=scale_manager)
def _get_env_files(template_path, env_rel_paths):
template_dir = os.path.dirname(template_path)
env_abs_paths = [os.path.join(template_dir, f) for f in env_rel_paths]
environment_files = []
env_map, merged_env = (
template_utils.process_multiple_environments_and_files(
env_paths=env_abs_paths, env_list_tracker=environment_files))
return environment_files, env_map
def _create_stack(context, osc, bay, bay_create_timeout):
template_path, heat_params = _extract_template_definition(context, bay)
template_path, heat_params, env_files = (
_extract_template_definition(context, bay))
tpl_files, template = template_utils.get_template_contents(template_path)
environment_files, env_map = _get_env_files(template_path, env_files)
tpl_files.update(env_map)
# Make sure no duplicate stack name
stack_name = '%s-%s' % (bay.name, short_id.generate_id())
if bay_create_timeout:
@ -90,6 +106,7 @@ def _create_stack(context, osc, bay, bay_create_timeout):
fields = {
'stack_name': stack_name,
'parameters': heat_params,
'environment_files': environment_files,
'template': template,
'files': tpl_files,
'timeout_mins': heat_timeout
@ -100,12 +117,16 @@ def _create_stack(context, osc, bay, bay_create_timeout):
def _update_stack(context, osc, bay, scale_manager=None):
template_path, heat_params = _extract_template_definition(
template_path, heat_params, env_files = _extract_template_definition(
context, bay, scale_manager=scale_manager)
tpl_files, template = template_utils.get_template_contents(template_path)
environment_files, env_map = _get_env_files(template_path, env_files)
tpl_files.update(env_map)
fields = {
'parameters': heat_params,
'environment_files': environment_files,
'template': template,
'files': tpl_files
}

View File

@ -305,6 +305,18 @@ class TemplateDefinition(object):
return template_params
def get_env_files(self, baymodel):
"""Collects stack environment files based upon Baymodel attributes.
Base implementation returns no files (empty list). Meant to be
overridden by subclasses.
:param baymodel: Baymodel to collect environment files for
:return: list of relative paths to environment files
"""
return []
def get_heat_param(self, bay_attr=None, baymodel_attr=None):
"""Returns stack param name.
@ -331,8 +343,9 @@ class TemplateDefinition(object):
pass
def extract_definition(self, context, baymodel, bay, **kwargs):
return self.template_path, self.get_params(context, baymodel, bay,
**kwargs)
return (self.template_path,
self.get_params(context, baymodel, bay, **kwargs),
self.get_env_files(baymodel))
class BaseTemplateDefinition(TemplateDefinition):

View File

@ -367,6 +367,87 @@ class TestHandler(db_base.DbTestCase):
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[1].payload['outcome'])
@patch('magnum.conductor.handlers.bay_conductor.HeatPoller')
@patch('heatclient.common.template_utils'
'.process_multiple_environments_and_files')
@patch('heatclient.common.template_utils.get_template_contents')
@patch('magnum.conductor.handlers.bay_conductor'
'._extract_template_definition')
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.bay_conductor.short_id')
@patch('magnum.conductor.handlers.bay_conductor.uuid')
@patch('magnum.common.clients.OpenStackClients')
def test_create_with_environment(self,
mock_openstack_client_class,
mock_uuid,
mock_short_id,
mock_cert_manager,
mock_trust_manager,
mock_extract_tmpl_def,
mock_get_template_contents,
mock_process_mult,
mock_heat_poller_class):
timeout = 15
self.bay.baymodel_id = self.baymodel.uuid
test_uuid = uuid.uuid4()
mock_uuid.uuid4.return_value = test_uuid
bay_name = self.bay.name
mock_short_id.generate_id.return_value = 'short_id'
mock_poller = mock.MagicMock()
mock_poller.poll_and_check.return_value = loopingcall.LoopingCallDone()
mock_heat_poller_class.return_value = mock_poller
mock_extract_tmpl_def.return_value = (
'the/template/path.yaml',
{'heat_param_1': 'foo', 'heat_param_2': 'bar'},
['env_file_1', 'env_file_2'])
mock_get_template_contents.return_value = (
{'tmpl_file_1': 'some content',
'tmpl_file_2': 'some more content'},
'some template yaml')
def do_mock_process_mult(env_paths=None, env_list_tracker=None):
self.assertEqual(env_list_tracker, [])
for f in env_paths:
env_list_tracker.append('file:///' + f)
env_map = {path: 'content of ' + path for path in env_list_tracker}
return (env_map, None)
mock_process_mult.side_effect = do_mock_process_mult
mock_hc = mock.Mock()
mock_hc.stacks.create.return_value = {'stack': {'id': 'stack-id'}}
osc = mock.Mock()
osc.heat.return_value = mock_hc
mock_openstack_client_class.return_value = osc
self.handler.bay_create(self.context, self.bay, timeout)
mock_extract_tmpl_def.assert_called_once_with(self.context, self.bay)
mock_get_template_contents.assert_called_once_with(
'the/template/path.yaml')
mock_process_mult.assert_called_once_with(
env_paths=['the/template/env_file_1', 'the/template/env_file_2'],
env_list_tracker=mock.ANY)
mock_hc.stacks.create.assert_called_once_with(
environment_files=['file:///the/template/env_file_1',
'file:///the/template/env_file_2'],
files={
'tmpl_file_1': 'some content',
'tmpl_file_2': 'some more content',
'file:///the/template/env_file_1':
'content of file:///the/template/env_file_1',
'file:///the/template/env_file_2':
'content of file:///the/template/env_file_2'
},
parameters={'heat_param_1': 'foo', 'heat_param_2': 'bar'},
stack_name=('%s-short_id' % bay_name),
template='some template yaml',
timeout_mins=timeout)
@patch('magnum.common.clients.OpenStackClients')
def test_bay_delete(self, mock_openstack_client_class):
osc = mock.MagicMock()

View File

@ -101,8 +101,9 @@ class TestBayConductorWithK8s(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
mapping = {
'dns_nameserver': 'dns_nameserver',
@ -167,6 +168,7 @@ class TestBayConductorWithK8s(base.TestCase):
expected.pop(mapping[missing_attr], None)
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_with_registry(
@ -182,8 +184,9 @@ class TestBayConductorWithK8s(base.TestCase):
group='docker_registry')
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'auth_url': 'http://192.168.10.10:5000/v3',
@ -224,6 +227,7 @@ class TestBayConductorWithK8s(base.TestCase):
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_coreos_with_disovery(
@ -235,8 +239,9 @@ class TestBayConductorWithK8s(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -269,6 +274,7 @@ class TestBayConductorWithK8s(base.TestCase):
'insecure_registry_url': '10.0.0.1:5000',
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
@ -285,8 +291,9 @@ class TestBayConductorWithK8s(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -319,6 +326,7 @@ class TestBayConductorWithK8s(base.TestCase):
'insecure_registry_url': '10.0.0.1:5000',
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_dns(
@ -411,8 +419,9 @@ class TestBayConductorWithK8s(base.TestCase):
reqget.return_value = mock_req
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -450,6 +459,7 @@ class TestBayConductorWithK8s(base.TestCase):
'insecure_registry_url': '10.0.0.1:5000',
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
reqget.assert_called_once_with('http://etcd/test?size=1')
@patch('magnum.common.short_id.generate_id')
@ -471,7 +481,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_get_template_contents.return_value = [
mock_tpl_files, expected_template_contents]
mock_extract_template_definition.return_value = ('template/path',
{})
{}, [])
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
@ -486,6 +496,7 @@ class TestBayConductorWithK8s(base.TestCase):
'parameters': {},
'template': expected_template_contents,
'files': {},
'environment_files': [],
'timeout_mins': expected_timeout
}
mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
@ -510,7 +521,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_get_template_contents.return_value = [
mock_tpl_files, expected_template_contents]
mock_extract_template_definition.return_value = ('template/path',
{})
{}, [])
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
@ -525,6 +536,7 @@ class TestBayConductorWithK8s(base.TestCase):
'parameters': {},
'template': expected_template_contents,
'files': {},
'environment_files': [],
'timeout_mins': expected_timeout
}
mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
@ -550,7 +562,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_get_template_contents.return_value = [
mock_tpl_files, expected_template_contents]
mock_extract_template_definition.return_value = ('template/path',
{})
{}, [])
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
@ -565,6 +577,7 @@ class TestBayConductorWithK8s(base.TestCase):
'parameters': {},
'template': expected_template_contents,
'files': {},
'environment_files': [],
'timeout_mins': expected_timeout
}
mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
@ -583,7 +596,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_get_template_contents.return_value = [
mock_tpl_files, expected_template_contents]
mock_extract_template_definition.return_value = ('template/path',
{})
{}, [])
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
@ -595,7 +608,8 @@ class TestBayConductorWithK8s(base.TestCase):
expected_args = {
'parameters': {},
'template': expected_template_contents,
'files': {}
'files': {},
'environment_files': []
}
mock_heat_client.stacks.update.assert_called_once_with(mock_stack_id,
**expected_args)

View File

@ -85,8 +85,9 @@ class TestBayConductorWithMesos(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -119,6 +120,7 @@ class TestBayConductorWithMesos(base.TestCase):
'mesos_slave_image_providers': 'docker'
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_only_required(
@ -135,8 +137,9 @@ class TestBayConductorWithMesos(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -161,6 +164,7 @@ class TestBayConductorWithMesos(base.TestCase):
'mesos_slave_image_providers': 'docker'
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.conductor.utils.retrieve_baymodel')
@patch('oslo_config.cfg')

View File

@ -84,8 +84,9 @@ class TestBayConductorWithSwarm(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -118,6 +119,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'auth_url': 'http://192.168.10.10:5000/v3'
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_with_registry(
@ -133,8 +135,9 @@ class TestBayConductorWithSwarm(base.TestCase):
group='docker_registry')
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -169,6 +172,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'docker_storage_driver': 'devicemapper'
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_only_required(
@ -188,8 +192,9 @@ class TestBayConductorWithSwarm(base.TestCase):
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
definition) = bay_conductor._extract_template_definition(self.context,
bay)
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
expected = {
'ssh_key_name': 'keypair_id',
@ -212,6 +217,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'auth_url': 'http://192.168.10.10:5000/v3'
}
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('magnum.conductor.utils.retrieve_baymodel')
@patch('oslo_config.cfg')