Add Heat Capabilities Actions
This patch adds the Actions for retrieving and updating the capabilites for a given deployment. Change-Id: I27b00613afc8d9ab07ac3270221d8dc58b0150dc
This commit is contained in:
@@ -56,3 +56,5 @@ mistral.actions =
|
||||
tripleo.upload_default_templates = tripleo_common.actions.templates:UploadTemplatesAction
|
||||
tripleo.create_container = tripleo_common.actions.plan:CreateContainerAction
|
||||
tripleo.create_plan = tripleo_common.actions.plan:CreatePlanAction
|
||||
tripleo.get_capabilities = tripleo_common.actions.heat_capabilities:GetCapabilitiesAction
|
||||
tripleo.update_capabilities = tripleo_common.actions.heat_capabilities:UpdateCapabilitiesAction
|
||||
|
||||
140
tripleo_common/actions/heat_capabilities.py
Normal file
140
tripleo_common/actions/heat_capabilities.py
Normal file
@@ -0,0 +1,140 @@
|
||||
# Copyright 2106 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
import logging
|
||||
import yaml
|
||||
|
||||
from mistral.workflow import utils as mistral_workflow_utils
|
||||
|
||||
from tripleo_common.actions import base
|
||||
from tripleo_common import constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GetCapabilitiesAction(base.TripleOAction):
|
||||
"""Gets list of available heat environments
|
||||
|
||||
Parses the capabilities_map.yaml file in a given plan and
|
||||
returns a list of environments
|
||||
|
||||
:param container: name of the swift container / plan name
|
||||
:return: list of environment files in swift container
|
||||
"""
|
||||
|
||||
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME):
|
||||
super(GetCapabilitiesAction, self).__init__()
|
||||
self.container = container
|
||||
|
||||
def run(self):
|
||||
environments = {}
|
||||
try:
|
||||
map_file = self._get_object_client().get_object(
|
||||
self.container, 'capabilities-map.yaml')
|
||||
capabilities = yaml.safe_load(map_file[1])
|
||||
except Exception:
|
||||
err_msg = (
|
||||
"Error parsing capabilities-map.yaml.")
|
||||
LOG.exception(err_msg)
|
||||
return mistral_workflow_utils.Result(
|
||||
None,
|
||||
err_msg
|
||||
)
|
||||
# identify all environments
|
||||
for topic in capabilities['topics']:
|
||||
for eg in topic['environment_groups']:
|
||||
for env in eg['environments']:
|
||||
environments[env['file']] = {'enabled': False}
|
||||
try:
|
||||
mistral_client = self._get_workflow_client()
|
||||
mistral_env = mistral_client.environments.get(self.container)
|
||||
except Exception as mistral_err:
|
||||
err_msg = ("Error retrieving mistral "
|
||||
"environment. %s" % mistral_err)
|
||||
LOG.exception(err_msg)
|
||||
return mistral_workflow_utils.Result(
|
||||
None,
|
||||
err_msg
|
||||
)
|
||||
|
||||
selected_envs = [item['path'] for item in
|
||||
mistral_env.variables['environments']
|
||||
if 'path' in item]
|
||||
for item in selected_envs:
|
||||
if item in environments:
|
||||
environments[item]['enabled'] = True
|
||||
else:
|
||||
environments[item] = {'enabled': False}
|
||||
|
||||
return environments
|
||||
|
||||
|
||||
class UpdateCapabilitiesAction(base.TripleOAction):
|
||||
"""Updates Mistral Environment with selected environments
|
||||
|
||||
Takes a list of environment files and depending on the value of the
|
||||
enabled flag, adds or removes them from the Mistral Environment.
|
||||
|
||||
:param environments: list of environments
|
||||
:param container: name of the swift container / plan name
|
||||
:return: the updated mistral environment
|
||||
"""
|
||||
|
||||
def __init__(self, environments,
|
||||
container=constants.DEFAULT_CONTAINER_NAME):
|
||||
super(UpdateCapabilitiesAction, self).__init__()
|
||||
self.container = container
|
||||
self.environments = environments
|
||||
|
||||
def run(self):
|
||||
mistral_client = self._get_workflow_client()
|
||||
mistral_env = None
|
||||
try:
|
||||
mistral_env = mistral_client.environments.get(self.container)
|
||||
except Exception as mistral_err:
|
||||
err_msg = (
|
||||
"Error retrieving mistral "
|
||||
"environment. %s" % mistral_err)
|
||||
LOG.exception(err_msg)
|
||||
return mistral_workflow_utils.Result(
|
||||
None,
|
||||
err_msg
|
||||
)
|
||||
|
||||
for k, v in self.environments.items():
|
||||
if v.get('enabled', False):
|
||||
mistral_env.variables['environments'].append(
|
||||
{'path': k}
|
||||
)
|
||||
else:
|
||||
# see if it resides in mistral env and if so, remove it
|
||||
if {'path': k} in mistral_env.variables['environments']:
|
||||
mistral_env.variables['environments'].pop({'path': k})
|
||||
|
||||
env_kwargs = {
|
||||
'name': mistral_env.name,
|
||||
'variables': mistral_env.variables
|
||||
}
|
||||
try:
|
||||
mistral_client.environments.update(**env_kwargs)
|
||||
except Exception as mistral_err:
|
||||
err_msg = (
|
||||
"Error retrieving mistral "
|
||||
"environment. %s" % mistral_err)
|
||||
LOG.exception(err_msg)
|
||||
return mistral_workflow_utils.Result(
|
||||
None,
|
||||
err_msg
|
||||
)
|
||||
return mistral_env
|
||||
176
tripleo_common/tests/actions/test_heat_capabilities.py
Normal file
176
tripleo_common/tests/actions/test_heat_capabilities.py
Normal file
@@ -0,0 +1,176 @@
|
||||
# Copyright 2016 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
import mock
|
||||
|
||||
from mistral.workflow import utils as mistral_workflow_utils
|
||||
|
||||
from tripleo_common.actions import heat_capabilities
|
||||
from tripleo_common.tests import base
|
||||
|
||||
|
||||
MAPPING_YAML_CONTENTS = """root_template: /path/to/overcloud.yaml
|
||||
root_environment: /path/to/environment.yaml
|
||||
topics:
|
||||
- title: Fake Single Environment Group Configuration
|
||||
description:
|
||||
environment_groups:
|
||||
- title:
|
||||
description: Random fake string of text
|
||||
environments:
|
||||
- file: /path/to/network-isolation.json
|
||||
title: Default Configuration
|
||||
description:
|
||||
|
||||
- title: Fake Multiple Environment Group Configuration
|
||||
description:
|
||||
environment_groups:
|
||||
- title: Random Fake 1
|
||||
description: Random fake string of text
|
||||
environments:
|
||||
- file: /path/to/ceph-storage-env.yaml
|
||||
title: Fake1
|
||||
description: Random fake string of text
|
||||
|
||||
- title: Random Fake 2
|
||||
description:
|
||||
environments:
|
||||
- file: /path/to/poc-custom-env.yaml
|
||||
title: Fake2
|
||||
description:
|
||||
"""
|
||||
|
||||
|
||||
class GetCapabilitiesActionTest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(GetCapabilitiesActionTest, self).setUp()
|
||||
self.container_name = 'test-container'
|
||||
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction._get_object_client')
|
||||
def test_run_yaml_error(self, get_obj_client_mock):
|
||||
# setup swift
|
||||
swift = mock.MagicMock()
|
||||
swift.get_object.return_value = mock.Mock(side_effect=ValueError)
|
||||
get_obj_client_mock.return_value = swift
|
||||
|
||||
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
||||
expected = mistral_workflow_utils.Result(
|
||||
data=None,
|
||||
error="Error parsing capabilities-map.yaml.")
|
||||
self.assertEqual(expected, action.run())
|
||||
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction._get_object_client')
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_workflow_client')
|
||||
def test_run_mistral_error(self, get_workflow_client_mock,
|
||||
get_obj_client_mock):
|
||||
|
||||
# setup swift
|
||||
swift = mock.MagicMock()
|
||||
swift.get_object.return_value = ({}, MAPPING_YAML_CONTENTS)
|
||||
get_obj_client_mock.return_value = swift
|
||||
|
||||
# setup mistral
|
||||
mistral = mock.MagicMock()
|
||||
mistral.environments.get = mock.Mock(
|
||||
side_effect=Exception)
|
||||
get_workflow_client_mock.return_value = mistral
|
||||
|
||||
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
||||
expected = mistral_workflow_utils.Result(
|
||||
data=None,
|
||||
error="Error retrieving mistral environment. ")
|
||||
self.assertEqual(expected, action.run())
|
||||
|
||||
@mock.patch('tripleo_common.actions.base.TripleOAction._get_object_client')
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_workflow_client')
|
||||
def test_run(self, get_workflow_client_mock, get_obj_client_mock):
|
||||
|
||||
# setup swift
|
||||
swift = mock.MagicMock()
|
||||
swift.get_object.return_value = ({}, MAPPING_YAML_CONTENTS)
|
||||
get_obj_client_mock.return_value = swift
|
||||
|
||||
# setup mistral
|
||||
mistral = mock.MagicMock()
|
||||
get_workflow_client_mock.return_value = mistral
|
||||
|
||||
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
||||
self.assertEqual({
|
||||
'/path/to/ceph-storage-env.yaml': {'enabled': False},
|
||||
'/path/to/network-isolation.json': {'enabled': False},
|
||||
'/path/to/poc-custom-env.yaml': {'enabled': False}},
|
||||
action.run())
|
||||
|
||||
|
||||
class UpdateCapabilitiesActionTest(base.TestCase):
|
||||
|
||||
def setUp(self,):
|
||||
super(UpdateCapabilitiesActionTest, self).setUp()
|
||||
self.container_name = 'test-container'
|
||||
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_workflow_client')
|
||||
def test_run(self, get_workflow_client_mock):
|
||||
|
||||
# setup mistral
|
||||
mistral = mock.MagicMock()
|
||||
mocked_env = mock.MagicMock()
|
||||
mocked_env.variables = {
|
||||
'environments': [
|
||||
{'path': '/path/to/overcloud-default-env.yaml'}
|
||||
]
|
||||
}
|
||||
mistral.environments.get.return_value = mocked_env
|
||||
get_workflow_client_mock.return_value = mistral
|
||||
|
||||
environments = {'/path/to/ceph-storage-env.yaml': {'enabled': False},
|
||||
'/path/to/network-isolation.json': {'enabled': False},
|
||||
'/path/to/poc-custom-env.yaml': {'enabled': True}}
|
||||
|
||||
action = heat_capabilities.UpdateCapabilitiesAction(
|
||||
environments, self.container_name)
|
||||
self.assertEqual({
|
||||
'environments': [
|
||||
{'path': '/path/to/overcloud-default-env.yaml'},
|
||||
{'path': '/path/to/poc-custom-env.yaml'}
|
||||
]},
|
||||
action.run().variables)
|
||||
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_object_client')
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_workflow_client')
|
||||
def test_run_mistral_error(self, get_workflow_client_mock,
|
||||
get_obj_client_mock):
|
||||
|
||||
# setup swift
|
||||
swift = mock.MagicMock()
|
||||
swift.get_object.return_value = ({}, MAPPING_YAML_CONTENTS)
|
||||
get_obj_client_mock.return_value = swift
|
||||
|
||||
# setup mistral
|
||||
mistral = mock.MagicMock()
|
||||
mistral.environments.get = mock.Mock(
|
||||
side_effect=Exception)
|
||||
get_workflow_client_mock.return_value = mistral
|
||||
|
||||
action = heat_capabilities.UpdateCapabilitiesAction(
|
||||
{}, self.container_name)
|
||||
expected = mistral_workflow_utils.Result(
|
||||
data=None,
|
||||
error="Error retrieving mistral environment. ")
|
||||
self.assertEqual(expected, action.run())
|
||||
Reference in New Issue
Block a user