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:
parent
5a63435c37
commit
38153d1cd4
|
@ -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 = [
|
||||
|
|
|
@ -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.".
|
||||
|
|
Loading…
Reference in New Issue