[Heat] Pass parameters, files and env for heat stacks
Some heat templates can contain parameters, files and environment dependencies that cannot be used with the current scenario realization in rally. So the patch provides "parameters", "files" and "environment" input parameters in rally scenarios that allow to use these inputs for stack create/update operations. Change-Id: I6639d002a140659f677a6ed6f08b7741713a4e5f
This commit is contained in:
parent
b1ee60eef2
commit
a1b5aa7bc5
@ -353,3 +353,23 @@ class FileType(ResourceType):
|
||||
|
||||
with open(resource_config, "r") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
class FileTypeDict(ResourceType):
|
||||
|
||||
@classmethod
|
||||
def transform(cls, clients, resource_config):
|
||||
"""Returns the dictionary of items with file path and file content.
|
||||
|
||||
:param clients: openstack admin client handles
|
||||
:param resource_config: list of file paths
|
||||
|
||||
:return: dictionary {file_path: file_content, ...}
|
||||
"""
|
||||
|
||||
file_type_dict = {}
|
||||
for file_path in resource_config:
|
||||
with open(file_path, "r") as f:
|
||||
file_type_dict[file_path] = f.read()
|
||||
|
||||
return file_type_dict
|
@ -26,19 +26,23 @@ class HeatStacks(utils.HeatScenario):
|
||||
RESOURCE_NAME_PREFIX = "rally_stack_"
|
||||
RESOURCE_NAME_LENGTH = 7
|
||||
|
||||
@types.set(template_path=types.FileType)
|
||||
@types.set(template_path=types.FileType, files=types.FileTypeDict)
|
||||
@validation.required_services(consts.Service.HEAT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["heat"]})
|
||||
def create_and_list_stack(self, template_path):
|
||||
def create_and_list_stack(self, template_path, parameters=None,
|
||||
files=None, environment=None):
|
||||
"""Add a stack and then list all stacks.
|
||||
|
||||
Measure the "heat stack-create" and "heat stack-list" commands
|
||||
performance.
|
||||
|
||||
:param template_path: path to stack template file
|
||||
:param parameters: parameters to use in heat template
|
||||
:param files: files used in template
|
||||
:param environment: stack environment definition
|
||||
"""
|
||||
self._create_stack(template_path)
|
||||
self._create_stack(template_path, parameters, files, environment)
|
||||
self._list_stacks()
|
||||
|
||||
@validation.required_services(consts.Service.HEAT)
|
||||
@ -53,27 +57,33 @@ class HeatStacks(utils.HeatScenario):
|
||||
for stack in stacks:
|
||||
self.clients("heat").resources.list(stack.id)
|
||||
|
||||
@types.set(template_path=types.FileType)
|
||||
@types.set(template_path=types.FileType, files=types.FileTypeDict)
|
||||
@validation.required_services(consts.Service.HEAT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["heat"]})
|
||||
def create_and_delete_stack(self, template_path):
|
||||
def create_and_delete_stack(self, template_path, parameters=None,
|
||||
files=None, environment=None):
|
||||
"""Add and then delete a stack.
|
||||
|
||||
Measure the "heat stack-create" and "heat stack-delete" commands
|
||||
performance.
|
||||
|
||||
:param template_path: path to stack template file
|
||||
:param parameters: parameters to use in heat template
|
||||
:param files: files used in template
|
||||
:param environment: stack environment definition
|
||||
"""
|
||||
|
||||
stack = self._create_stack(template_path)
|
||||
stack = self._create_stack(template_path, parameters,
|
||||
files, environment)
|
||||
self._delete_stack(stack)
|
||||
|
||||
@types.set(template_path=types.FileType)
|
||||
@types.set(template_path=types.FileType, files=types.FileTypeDict)
|
||||
@validation.required_services(consts.Service.HEAT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["heat"]})
|
||||
def create_check_delete_stack(self, template_path):
|
||||
def create_check_delete_stack(self, template_path, parameters=None,
|
||||
files=None, environment=None):
|
||||
"""Create, check and delete a stack.
|
||||
|
||||
Measure the performance of the following commands:
|
||||
@ -82,18 +92,28 @@ class HeatStacks(utils.HeatScenario):
|
||||
- heat stack-delete
|
||||
|
||||
:param template_path: path to stack template file
|
||||
:param parameters: parameters to use in heat template
|
||||
:param files: files used in template
|
||||
:param environment: stack environment definition
|
||||
"""
|
||||
|
||||
stack = self._create_stack(template_path)
|
||||
stack = self._create_stack(template_path, parameters,
|
||||
files, environment)
|
||||
self._check_stack(stack)
|
||||
self._delete_stack(stack)
|
||||
|
||||
@types.set(template_path=types.FileType,
|
||||
updated_template_path=types.FileType)
|
||||
updated_template_path=types.FileType,
|
||||
files=types.FileTypeDict,
|
||||
updated_files=types.FileTypeDict)
|
||||
@validation.required_services(consts.Service.HEAT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["heat"]})
|
||||
def create_update_delete_stack(self, template_path, updated_template_path):
|
||||
def create_update_delete_stack(self, template_path,
|
||||
updated_template_path,
|
||||
parameters=None, updated_parameters=None,
|
||||
files=None, updated_files=None,
|
||||
environment=None, updated_environment=None):
|
||||
"""Add, update and then delete a stack.
|
||||
|
||||
Measure the "heat stack-create", "heat stack-update"
|
||||
@ -101,17 +121,32 @@ class HeatStacks(utils.HeatScenario):
|
||||
|
||||
:param template_path: path to stack template file
|
||||
:param updated_template_path: path to updated stack template file
|
||||
:param parameters: parameters to use in heat template
|
||||
:param updated_parameters: parameters to use in updated heat template
|
||||
If not specified then parameters will be
|
||||
used instead
|
||||
:param files: files used in template
|
||||
:param updated_files: files used in updated template. If not specified
|
||||
files value will be used instead
|
||||
:param environment: stack environment definition
|
||||
:param updated_environment: environment definition for updated stack
|
||||
"""
|
||||
|
||||
stack = self._create_stack(template_path)
|
||||
self._update_stack(stack, updated_template_path)
|
||||
stack = self._create_stack(template_path, parameters,
|
||||
files, environment)
|
||||
self._update_stack(stack, updated_template_path,
|
||||
updated_parameters or parameters,
|
||||
updated_files or files,
|
||||
updated_environment or environment)
|
||||
self._delete_stack(stack)
|
||||
|
||||
@types.set(template_path=types.FileType)
|
||||
@types.set(template_path=types.FileType, files=types.FileTypeDict)
|
||||
@validation.required_services(consts.Service.HEAT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["heat"]})
|
||||
def create_suspend_resume_delete_stack(self, template_path):
|
||||
def create_suspend_resume_delete_stack(self, template_path,
|
||||
parameters=None, files=None,
|
||||
environment=None):
|
||||
"""Create, suspend-resume and then delete a stack.
|
||||
|
||||
Measure performance of the following commands:
|
||||
@ -121,9 +156,12 @@ class HeatStacks(utils.HeatScenario):
|
||||
heat stack-delete
|
||||
|
||||
:param template_path: path to stack template file
|
||||
:param parameters: parameters to use in heat template
|
||||
:param files: files used in template
|
||||
:param environment: stack environment definition
|
||||
"""
|
||||
|
||||
s = self._create_stack(template_path)
|
||||
s = self._create_stack(template_path, parameters, files, environment)
|
||||
self._suspend_stack(s)
|
||||
self._resume_stack(s)
|
||||
self._delete_stack(s)
|
||||
|
@ -89,10 +89,14 @@ class HeatScenario(base.Scenario):
|
||||
return list(self.clients("heat").stacks.list())
|
||||
|
||||
@base.atomic_action_timer("heat.create_stack")
|
||||
def _create_stack(self, template):
|
||||
def _create_stack(self, template, parameters=None,
|
||||
files=None, environment=None):
|
||||
"""Create a new stack.
|
||||
|
||||
:param template: template with stack description.
|
||||
:param parameters: template parameters used during stack creation
|
||||
:param files: additional files used in template
|
||||
:param environment: stack environment definition
|
||||
|
||||
:returns: object of stack
|
||||
"""
|
||||
@ -100,10 +104,10 @@ class HeatScenario(base.Scenario):
|
||||
kw = {
|
||||
"stack_name": stack_name,
|
||||
"disable_rollback": True,
|
||||
"parameters": {},
|
||||
"parameters": parameters or {},
|
||||
"template": template,
|
||||
"files": {},
|
||||
"environment": {}
|
||||
"files": files or {},
|
||||
"environment": environment or {}
|
||||
}
|
||||
|
||||
# heat client returns body instead manager object, so we should
|
||||
@ -123,21 +127,26 @@ class HeatScenario(base.Scenario):
|
||||
return stack
|
||||
|
||||
@base.atomic_action_timer("heat.update_stack")
|
||||
def _update_stack(self, stack, template):
|
||||
def _update_stack(self, stack, template, parameters=None,
|
||||
files=None, environment=None):
|
||||
"""Update an existing stack
|
||||
|
||||
:param stack: stack that need to be updated
|
||||
:param template: Updated template
|
||||
:param parameters: template parameters for stack update
|
||||
:param files: additional files used in template
|
||||
:param environment: stack environment definition
|
||||
|
||||
:returns: object of updated stack
|
||||
"""
|
||||
|
||||
kw = {
|
||||
"stack_name": stack.stack_name,
|
||||
"disable_rollback": True,
|
||||
"parameters": {},
|
||||
"parameters": parameters or {},
|
||||
"template": template,
|
||||
"files": {},
|
||||
"environment": {}
|
||||
"files": files or {},
|
||||
"environment": environment or {}
|
||||
}
|
||||
self.clients("heat").stacks.update(stack.id, **kw)
|
||||
|
||||
|
@ -381,3 +381,25 @@ class FileTypeTestCase(test.TestCase):
|
||||
types.FileType.transform,
|
||||
clients=None,
|
||||
resource_config=resource_config)
|
||||
|
||||
|
||||
class FileTypeDictTestCase(test.TestCase):
|
||||
|
||||
@mock.patch("rally.benchmark.types.open",
|
||||
side_effect=mock.mock_open(read_data="file_context"),
|
||||
create=True)
|
||||
def test_transform_by_path(self, mock_open):
|
||||
resource_config = ["file.yaml"]
|
||||
file_context = types.FileTypeDict.transform(
|
||||
clients=None,
|
||||
resource_config=resource_config)
|
||||
self.assertEqual(file_context, {"file.yaml": "file_context"})
|
||||
|
||||
@mock.patch("rally.benchmark.types.open",
|
||||
side_effect=IOError, create=True)
|
||||
def test_transform_by_path_no_match(self, mock_open):
|
||||
resource_config = ["nonexistant.yaml"]
|
||||
self.assertRaises(IOError,
|
||||
types.FileTypeDict.transform,
|
||||
clients=None,
|
||||
resource_config=resource_config)
|
||||
|
@ -26,6 +26,9 @@ class HeatStacksTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(HeatStacksTestCase, self).setUp()
|
||||
self.default_template = "heat_template_version: 2013-05-23"
|
||||
self.default_parameters = {"dummy_param": "dummy_key"}
|
||||
self.default_files = ["dummy_file.yaml"]
|
||||
self.default_environment = {"env": "dummy_env"}
|
||||
|
||||
@mock.patch(HEAT_STACKS + "._generate_random_name")
|
||||
@mock.patch(HEAT_STACKS + "._list_stacks")
|
||||
@ -35,8 +38,15 @@ class HeatStacksTestCase(test.TestCase):
|
||||
heat_scenario = stacks.HeatStacks()
|
||||
mock_random_name.return_value = "test-rally-stack"
|
||||
heat_scenario.create_and_list_stack(
|
||||
template_path=self.default_template)
|
||||
mock_create.assert_called_once_with(self.default_template)
|
||||
template_path=self.default_template,
|
||||
parameters=self.default_parameters,
|
||||
files=self.default_files,
|
||||
environment=self.default_environment
|
||||
)
|
||||
mock_create.assert_called_once_with(self.default_template,
|
||||
self.default_parameters,
|
||||
self.default_files,
|
||||
self.default_environment)
|
||||
mock_list.assert_called_once_with()
|
||||
|
||||
@mock.patch(HEAT_STACKS + ".clients")
|
||||
@ -71,9 +81,16 @@ class HeatStacksTestCase(test.TestCase):
|
||||
mock_create.return_value = fake_stack
|
||||
mock_random_name.return_value = "test-rally-stack"
|
||||
heat_scenario.create_and_delete_stack(
|
||||
template_path=self.default_template)
|
||||
template_path=self.default_template,
|
||||
parameters=self.default_parameters,
|
||||
files=self.default_files,
|
||||
environment=self.default_environment
|
||||
)
|
||||
|
||||
mock_create.assert_called_once_with(self.default_template)
|
||||
mock_create.assert_called_once_with(self.default_template,
|
||||
self.default_parameters,
|
||||
self.default_files,
|
||||
self.default_environment)
|
||||
mock_delete.assert_called_once_with(fake_stack)
|
||||
|
||||
@mock.patch(HEAT_STACKS + "._delete_stack")
|
||||
@ -84,8 +101,15 @@ class HeatStacksTestCase(test.TestCase):
|
||||
heat_scenario = stacks.HeatStacks()
|
||||
mock_create.return_value = "fake_stack_create_check_delete"
|
||||
heat_scenario.create_check_delete_stack(
|
||||
template_path=self.default_template)
|
||||
mock_create.assert_called_once_with(self.default_template)
|
||||
template_path=self.default_template,
|
||||
parameters=self.default_parameters,
|
||||
files=self.default_files,
|
||||
environment=self.default_environment
|
||||
)
|
||||
mock_create.assert_called_once_with(self.default_template,
|
||||
self.default_parameters,
|
||||
self.default_files,
|
||||
self.default_environment)
|
||||
mock_check.assert_called_once_with("fake_stack_create_check_delete")
|
||||
mock_delete.assert_called_once_with("fake_stack_create_check_delete")
|
||||
|
||||
@ -101,10 +125,20 @@ class HeatStacksTestCase(test.TestCase):
|
||||
mock_random_name.return_value = "test-rally-stack"
|
||||
heat_scenario.create_update_delete_stack(
|
||||
template_path=self.default_template,
|
||||
updated_template_path=self.default_template)
|
||||
parameters=self.default_parameters,
|
||||
updated_template_path=self.default_template,
|
||||
files=self.default_files,
|
||||
environment=self.default_environment
|
||||
)
|
||||
|
||||
mock_create.assert_called_once_with(self.default_template)
|
||||
mock_update.assert_called_once_with(fake_stack, self.default_template)
|
||||
mock_create.assert_called_once_with(self.default_template,
|
||||
self.default_parameters,
|
||||
self.default_files,
|
||||
self.default_environment)
|
||||
mock_update.assert_called_once_with(fake_stack, self.default_template,
|
||||
self.default_parameters,
|
||||
self.default_files,
|
||||
self.default_environment)
|
||||
mock_delete.assert_called_once_with(fake_stack)
|
||||
|
||||
@mock.patch(HEAT_STACKS + "._delete_stack")
|
||||
@ -119,9 +153,16 @@ class HeatStacksTestCase(test.TestCase):
|
||||
heat_scenario = stacks.HeatStacks()
|
||||
mock_create.return_value = "fake_stack_create_suspend_resume_delete"
|
||||
heat_scenario.create_suspend_resume_delete_stack(
|
||||
template_path=self.default_template)
|
||||
template_path=self.default_template,
|
||||
parameters=self.default_parameters,
|
||||
files=self.default_files,
|
||||
environment=self.default_environment
|
||||
)
|
||||
|
||||
mock_create.assert_called_once_with(self.default_template)
|
||||
mock_create.assert_called_once_with(self.default_template,
|
||||
self.default_parameters,
|
||||
self.default_files,
|
||||
self.default_environment)
|
||||
mock_suspend.assert_called_once_with(
|
||||
"fake_stack_create_suspend_resume_delete")
|
||||
mock_resume.assert_called_once_with(
|
||||
|
@ -43,6 +43,9 @@ class HeatScenarioTestCase(test.TestCase):
|
||||
self.useFixture(mockpatch.Patch("time.sleep"))
|
||||
self.scenario = utils.HeatScenario()
|
||||
self.default_template = "heat_template_version: 2013-05-23"
|
||||
self.dummy_parameters = {"dummy_param": "dummy_key"}
|
||||
self.dummy_files = ["dummy_file.yaml"]
|
||||
self.dummy_environment = {"dummy_env": "dummy_env_value"}
|
||||
|
||||
@mock.patch(HEAT_UTILS + ".HeatScenario.clients")
|
||||
def test_list_stacks(self, mock_clients):
|
||||
@ -61,7 +64,15 @@ class HeatScenarioTestCase(test.TestCase):
|
||||
}
|
||||
mock_clients("heat").stacks.get.return_value = self.stack
|
||||
scenario = utils.HeatScenario()
|
||||
return_stack = scenario._create_stack(self.default_template)
|
||||
return_stack = scenario._create_stack(self.default_template,
|
||||
self.dummy_parameters,
|
||||
self.dummy_files,
|
||||
self.dummy_environment)
|
||||
args, kwargs = mock_clients("heat").stacks.create.call_args
|
||||
self.assertIn(self.dummy_parameters, kwargs.values())
|
||||
self.assertIn(self.default_template, kwargs.values())
|
||||
self.assertIn(self.dummy_files, kwargs.values())
|
||||
self.assertIn(self.dummy_environment, kwargs.values())
|
||||
self.wait_for.mock.assert_called_once_with(
|
||||
self.stack,
|
||||
update_resource=self.gfm(),
|
||||
@ -77,7 +88,15 @@ class HeatScenarioTestCase(test.TestCase):
|
||||
def test_update_stack(self, mock_clients):
|
||||
mock_clients("heat").stacks.update.return_value = None
|
||||
scenario = utils.HeatScenario()
|
||||
scenario._update_stack(self.stack, self.default_template)
|
||||
scenario._update_stack(self.stack, self.default_template,
|
||||
self.dummy_parameters, self.dummy_files,
|
||||
self.dummy_environment)
|
||||
args, kwargs = mock_clients("heat").stacks.update.call_args
|
||||
self.assertIn(self.dummy_parameters, kwargs.values())
|
||||
self.assertIn(self.default_template, kwargs.values())
|
||||
self.assertIn(self.dummy_files, kwargs.values())
|
||||
self.assertIn(self.dummy_environment, kwargs.values())
|
||||
self.assertIn(self.stack.id, args)
|
||||
self.wait_for.mock.assert_called_once_with(
|
||||
self.stack,
|
||||
update_resource=self.gfm(),
|
||||
|
Loading…
Reference in New Issue
Block a user