Move roles functions to tripleo-common

In order to be able to leverage the roles work in other places, we need
to move the core functionality into tripleo-common for sharing. This
change updates the tripleoclient to use the functions out of
tripleo-common.

Change-Id: Ic6f9dd6417ea8ae62ba40cf8ff77b86d101d589f
Related-Blueprint: example-custom-role-environments
This commit is contained in:
Alex Schultz 2017-06-14 14:02:34 -06:00
parent 5a63435c37
commit 38153d1cd4
2 changed files with 56 additions and 70 deletions

View File

@ -15,7 +15,7 @@
import mock
from tripleoclient.exceptions import NotFound
from tripleo_common.exception import NotFound
from tripleoclient.tests.v1.overcloud_deploy import fakes
from tripleoclient.v1 import overcloud_roles
@ -26,10 +26,10 @@ class TestOvercloudRolesListAvailable(fakes.TestDeployOvercloud):
super(TestOvercloudRolesListAvailable, self).setUp()
self.cmd = overcloud_roles.RoleList(self.app, None)
@mock.patch('tripleo_common.utils.roles.get_roles_list_from_directory')
@mock.patch('os.path.realpath')
def test_action(self, realpath_mock):
def test_action(self, realpath_mock, get_roles_mock):
realpath_mock.return_value = '/foo'
get_roles_mock = mock.MagicMock()
get_roles_mock.return_value = ['a', 'b']
self.cmd._get_roles = get_roles_mock
@ -42,10 +42,10 @@ class TestOvercloudRolesListAvailable(fakes.TestDeployOvercloud):
self.cmd.take_action(parsed_args)
get_roles_mock.assert_called_once_with('/foo')
@mock.patch('tripleo_common.utils.roles.get_roles_list_from_directory')
@mock.patch('os.path.realpath')
def test_action_role_path(self, realpath_mock):
def test_action_role_path(self, realpath_mock, get_roles_mock):
realpath_mock.return_value = '/tmp'
get_roles_mock = mock.MagicMock()
get_roles_mock.return_value = ['a', 'b']
self.cmd._get_roles = get_roles_mock
@ -65,15 +65,17 @@ class TestOvercloudRolesGenerateData(fakes.TestDeployOvercloud):
super(TestOvercloudRolesGenerateData, self).setUp()
self.cmd = overcloud_roles.RolesGenerate(self.app, None)
@mock.patch('shutil.copyfileobj')
@mock.patch('tripleoclient.v1.overcloud_roles.open')
@mock.patch(
'tripleo_common.utils.roles.generate_roles_data_from_directory')
@mock.patch('tripleo_common.utils.roles.check_role_exists')
@mock.patch('tripleo_common.utils.roles.get_roles_list_from_directory')
@mock.patch('os.path.realpath')
def test_action(self, realpath_mock, open_mock, copy_mock):
def test_action(self, realpath_mock, get_roles_mock, check_mock,
generate_roles_mock):
realpath_mock.return_value = '/tmp'
get_roles_mock = mock.MagicMock()
get_roles_mock.return_value = ['Controller', 'Compute']
generate_roles_mock.return_value = 'foo'
capture_mock = mock.MagicMock()
self.cmd._get_roles = get_roles_mock
self.cmd._capture_output = capture_mock
arglist = ['--roles-path', '/tmp', 'Controller', 'Compute']
@ -84,20 +86,25 @@ class TestOvercloudRolesGenerateData(fakes.TestDeployOvercloud):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
capture_mock.assert_called_once_with(None)
get_roles_mock.assert_called_once_with('/tmp')
open_mock.assert_any_call('/tmp/Controller.yaml', 'r')
open_mock.assert_any_call('/tmp/Compute.yaml', 'r')
check_mock.assert_called_once_with(['Controller', 'Compute'],
['Controller', 'Compute'])
capture_mock.assert_called_once_with(None)
generate_roles_mock.assert_called_once_with('/tmp',
['Controller', 'Compute'],
True)
@mock.patch('shutil.copyfileobj')
@mock.patch('tripleoclient.v1.overcloud_roles.open')
@mock.patch(
'tripleo_common.utils.roles.generate_roles_data_from_directory')
@mock.patch('tripleo_common.utils.roles.check_role_exists')
@mock.patch('tripleo_common.utils.roles.get_roles_list_from_directory')
@mock.patch('os.path.realpath')
def test_action_with_outputfile(self, realpath_mock, open_mock, copy_mock):
def test_action_with_outputfile(self, realpath_mock, get_roles_mock,
check_mock, generate_roles_mock):
realpath_mock.return_value = '/tmp'
get_roles_mock = mock.MagicMock()
get_roles_mock.return_value = ['Controller', 'Compute']
generate_roles_mock.return_value = 'foo'
capture_mock = mock.MagicMock()
self.cmd._get_roles = get_roles_mock
self.cmd._capture_output = capture_mock
arglist = ['--roles-path', '/tmp', '-o', 'foo.yaml',
@ -110,19 +117,19 @@ class TestOvercloudRolesGenerateData(fakes.TestDeployOvercloud):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
capture_mock.assert_called_once_with('foo.yaml')
get_roles_mock.assert_called_once_with('/tmp')
open_mock.assert_any_call('/tmp/Controller.yaml', 'r')
open_mock.assert_any_call('/tmp/Compute.yaml', 'r')
check_mock.assert_called_once_with(['Controller', 'Compute'],
['Controller', 'Compute'])
capture_mock.assert_called_once_with('foo.yaml')
generate_roles_mock.assert_called_once_with('/tmp',
['Controller', 'Compute'],
True)
@mock.patch('tripleo_common.utils.roles.get_roles_list_from_directory')
@mock.patch('os.path.realpath')
def test_action_with_invald_roles(self, realpath_mock):
def test_action_with_invald_roles(self, realpath_mock, get_roles_mock):
realpath_mock.return_value = '/tmp'
get_roles_mock = mock.MagicMock()
get_roles_mock.return_value = ['Controller', 'Compute']
capture_mock = mock.MagicMock()
self.cmd._get_roles = get_roles_mock
self.cmd._capture_output = capture_mock
arglist = ['--roles-path', '/tmp', 'Foo', 'Bar']
verifylist = [
@ -132,14 +139,13 @@ class TestOvercloudRolesGenerateData(fakes.TestDeployOvercloud):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(NotFound, self.cmd.take_action, parsed_args)
capture_mock.assert_called_once_with(None)
get_roles_mock.assert_called_once_with('/tmp')
class TestOvercloudRoleInfo(fakes.TestDeployOvercloud):
class TestOvercloudRoleShow(fakes.TestDeployOvercloud):
def setUp(self):
super(TestOvercloudRoleInfo, self).setUp()
super(TestOvercloudRoleShow, self).setUp()
self.cmd = overcloud_roles.RoleShow(self.app, None)
@mock.patch('yaml.safe_load')
@ -159,11 +165,14 @@ class TestOvercloudRoleInfo(fakes.TestDeployOvercloud):
self.cmd.take_action(parsed_args)
open_mock.assert_called_once_with('/tmp/foo.yaml', 'r')
@mock.patch('tripleo_common.utils.roles.get_roles_list_from_directory')
@mock.patch('tripleoclient.v1.overcloud_roles.open')
@mock.patch('os.path.realpath')
def test_action_invalid_role(self, realpath_mock, open_mock):
def test_action_invalid_role(self, realpath_mock, open_mock,
get_roles_mock):
realpath_mock.return_value = '/tmp'
open_mock.side_effect = IOError('bar')
get_roles_mock.return_value = ['Controller', 'Compute']
arglist = ['--roles-path', '/tmp', 'foo']
verifylist = [

View File

@ -17,13 +17,12 @@ from __future__ import print_function
import collections
import os
import shutil
import sys
import yaml
from osc_lib.command import command
from tripleo_common.exception import NotFound
from tripleo_common.utils import roles as rolesutils
from tripleoclient.constants import TRIPLEO_HEAT_TEMPLATES
from tripleoclient.exceptions import NotFound
class RolesBaseCommand(command.Command):
@ -38,18 +37,6 @@ class RolesBaseCommand(command.Command):
'files. By default this is {}'.format(path))
return parser
def _get_roles(self, directory):
"""Return array of roles in roles path"""
if not os.path.exists(directory):
raise ValueError("Invalid roles path specified: {}".format(
directory))
roles = []
for f in os.listdir(directory):
if f.endswith(".yaml"):
roles.append(f[:-5])
roles.sort()
return roles
class RolesGenerate(RolesBaseCommand):
"""Generate roles_data.yaml file"""
@ -58,6 +45,9 @@ class RolesGenerate(RolesBaseCommand):
parser.add_argument('-o', '--output-file', metavar='<output file>',
help='File to capture all output to. For example, '
'roles_data.yaml')
parser.add_argument('--skip-validate', action='store_false',
help='Skip role metadata type validation when'
'generating the roles_data.yaml')
parser.add_argument('roles', nargs="+", metavar='<role>',
help='List of roles to use to generate the '
'roles_data.yaml file for the deployment. '
@ -73,13 +63,6 @@ class RolesGenerate(RolesBaseCommand):
if filename is not None:
sys.stdout = open(filename, 'w')
def _print_header(self):
"""Print file header"""
header = ["#" * 79,
"# File generated by tripleoclient",
"#" * 79]
print("\n".join(header))
def take_action(self, parsed_args):
"""Generate roles_data.yaml from imputed roles
@ -88,23 +71,17 @@ class RolesGenerate(RolesBaseCommand):
order they were provided.
"""
self.log.debug('take_action({})'.format(parsed_args))
self._capture_output(parsed_args.output_file)
roles_path = os.path.realpath(parsed_args.roles_path)
valid_roles = set(self._get_roles(roles_path))
# eliminate any dupes from the command line with an OrderedDict
requested_roles = collections.OrderedDict.fromkeys(parsed_args.roles)
role_check = set(requested_roles.keys()) - valid_roles
if len(role_check) > 0:
msg = "Invalid roles requested: {}\nValid Roles:\n{}".format(
role_check, '\n'.join(valid_roles)
)
raise NotFound(msg)
self._print_header()
for role in requested_roles:
file_path = os.path.join(roles_path, "{}.yaml".format(role))
with open(file_path, "r") as f:
shutil.copyfileobj(f, sys.stdout)
available_roles = rolesutils.get_roles_list_from_directory(roles_path)
rolesutils.check_role_exists(available_roles,
list(requested_roles.keys()))
self._capture_output(parsed_args.output_file)
roles_data = rolesutils.generate_roles_data_from_directory(
roles_path, list(requested_roles.keys()),
parsed_args.skip_validate)
sys.stdout.write(roles_data)
class RoleList(RolesBaseCommand):
@ -116,7 +93,7 @@ class RoleList(RolesBaseCommand):
def take_action(self, parsed_args):
self.log.debug('take_action({})'.format(parsed_args))
roles_path = os.path.realpath(parsed_args.roles_path)
roles = self._get_roles(roles_path)
roles = rolesutils.get_roles_list_from_directory(roles_path)
print('\n'.join(roles))
@ -131,11 +108,11 @@ class RoleShow(RolesBaseCommand):
def take_action(self, parsed_args):
self.log.debug('take_action({})'.format(parsed_args))
roles_path = os.path.realpath(parsed_args.roles_path)
file_path = os.path.join(roles_path,
'{}.yaml'.format(parsed_args.role))
role_name = parsed_args.role
file_path = os.path.join(roles_path, '{}.yaml'.format(role_name))
try:
with open(file_path, 'r') as f:
role = yaml.safe_load(f)[0]
role = rolesutils.validate_role_yaml(f)
except IOError:
raise NotFound("Role '{}' not found. Use 'openstack overcloud "
"roles list' to see the available roles.".