Add profile validate operation to senlinclient
Add profile validate operation to senlinclient Change-Id: I7fd1e5e3fa9115ba270f2c0e5f645ac5183622e3
This commit is contained in:
parent
62bbf8491c
commit
e450261b02
@ -402,3 +402,49 @@ class TestProfileUpdate(TestProfile):
|
|||||||
self.cmd.take_action,
|
self.cmd.take_action,
|
||||||
parsed_args)
|
parsed_args)
|
||||||
self.assertIn('Profile not found: c6b8b252', str(error))
|
self.assertIn('Profile not found: c6b8b252', str(error))
|
||||||
|
|
||||||
|
|
||||||
|
class TestProfileValidate(TestProfile):
|
||||||
|
|
||||||
|
spec_path = 'senlinclient/tests/test_specs/nova_server.yaml'
|
||||||
|
response = {"profile": {
|
||||||
|
"created_at": None,
|
||||||
|
"domain": None,
|
||||||
|
"id": None,
|
||||||
|
"metadata": None,
|
||||||
|
"name": "validated_profile",
|
||||||
|
"project": "5f1cc92b578e4e25a3b284179cf20a9b",
|
||||||
|
"spec": {"properties": {
|
||||||
|
"flavor": 1,
|
||||||
|
"image": "cirros-0.3.4-x86_64-uec",
|
||||||
|
"name": "cirros_server"},
|
||||||
|
"type": "os.nova.server",
|
||||||
|
"version": 1.0},
|
||||||
|
"type": "os.nova.server-1.0",
|
||||||
|
"updated_at": None,
|
||||||
|
"user": "2d7aca950f3e465d8ef0c81720faf6ff"}}
|
||||||
|
|
||||||
|
defaults = {
|
||||||
|
"spec": {
|
||||||
|
"version": 1.0,
|
||||||
|
"type": "os.nova.server",
|
||||||
|
"properties": {
|
||||||
|
"flavor": 1,
|
||||||
|
"name": "cirros_server",
|
||||||
|
"image": "cirros-0.3.4-x86_64-uec"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestProfileValidate, self).setUp()
|
||||||
|
self.cmd = osc_profile.ValidateProfile(self.app, None)
|
||||||
|
self.mock_client.validate_profile = mock.Mock(
|
||||||
|
return_value=sdk_profile.Profile(**self.response['profile']))
|
||||||
|
utils.get_dict_properties = mock.Mock(return_value='')
|
||||||
|
|
||||||
|
def test_profile_validate(self):
|
||||||
|
arglist = ['--spec-file', self.spec_path]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, [])
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
self.mock_client.validate_profile.assert_called_with(**self.defaults)
|
||||||
|
@ -298,6 +298,48 @@ class ShellTest(testtools.TestCase):
|
|||||||
self.assertEqual(msg, six.text_type(ex))
|
self.assertEqual(msg, six.text_type(ex))
|
||||||
service.delete_profile.assert_called_with('profile2', False)
|
service.delete_profile.assert_called_with('profile2', False)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'process_stack_spec')
|
||||||
|
@mock.patch.object(utils, 'get_spec_content')
|
||||||
|
def test_do_profile_validate(self, mock_get, mock_proc):
|
||||||
|
args = self._make_args({'spec_file': mock.Mock()})
|
||||||
|
spec = copy.deepcopy(self.profile_spec)
|
||||||
|
mock_get.return_value = spec
|
||||||
|
params = {
|
||||||
|
'spec': spec,
|
||||||
|
}
|
||||||
|
service = mock.Mock()
|
||||||
|
profile = mock.Mock()
|
||||||
|
profile.to_dict.return_value = {}
|
||||||
|
service.validate_profile.return_value = profile
|
||||||
|
|
||||||
|
sh.do_profile_validate(service, args)
|
||||||
|
|
||||||
|
service.validate_profile.assert_called_once_with(**params)
|
||||||
|
|
||||||
|
# Miss 'type' key in spec file
|
||||||
|
del spec['type']
|
||||||
|
ex = self.assertRaises(exc.CommandError,
|
||||||
|
sh.do_profile_validate,
|
||||||
|
service, args)
|
||||||
|
self.assertEqual(_("Missing 'type' key in spec file."),
|
||||||
|
six.text_type(ex))
|
||||||
|
# Miss 'version' key in spec file
|
||||||
|
spec['type'] = 'os.heat.stack'
|
||||||
|
del spec['version']
|
||||||
|
ex = self.assertRaises(exc.CommandError,
|
||||||
|
sh.do_profile_validate,
|
||||||
|
service, args)
|
||||||
|
self.assertEqual(_("Missing 'version' key in spec file."),
|
||||||
|
six.text_type(ex))
|
||||||
|
# Miss 'properties' key in spec file
|
||||||
|
spec['version'] = 1.0
|
||||||
|
del spec['properties']
|
||||||
|
ex = self.assertRaises(exc.CommandError,
|
||||||
|
sh.do_profile_validate,
|
||||||
|
service, args)
|
||||||
|
self.assertEqual(_("Missing 'properties' key in spec file."),
|
||||||
|
six.text_type(ex))
|
||||||
|
|
||||||
@mock.patch.object(utils, 'print_list')
|
@mock.patch.object(utils, 'print_list')
|
||||||
def test_do_policy_type_list(self, mock_print):
|
def test_do_policy_type_list(self, mock_print):
|
||||||
service = mock.Mock()
|
service = mock.Mock()
|
||||||
|
@ -84,6 +84,14 @@ class Client(object):
|
|||||||
"""
|
"""
|
||||||
return self.service.delete_profile(profile, ignore_missing)
|
return self.service.delete_profile(profile, ignore_missing)
|
||||||
|
|
||||||
|
def validate_profile(self, **attrs):
|
||||||
|
"""Validate a profile spec
|
||||||
|
|
||||||
|
Doc link:
|
||||||
|
http://developer.openstack.org/api-ref-clustering-v1.html#validateProfile
|
||||||
|
"""
|
||||||
|
return self.service.validate_profile(**attrs)
|
||||||
|
|
||||||
def policy_types(self, **query):
|
def policy_types(self, **query):
|
||||||
"""List policy types
|
"""List policy types
|
||||||
|
|
||||||
|
@ -307,3 +307,65 @@ class UpdateProfile(command.ShowOne):
|
|||||||
parsed_args.profile)
|
parsed_args.profile)
|
||||||
senlin_client.update_profile(profile.id, **params)
|
senlin_client.update_profile(profile.id, **params)
|
||||||
return _show_profile(senlin_client, profile_id=profile.id)
|
return _show_profile(senlin_client, profile_id=profile.id)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateProfile(command.ShowOne):
|
||||||
|
"""Validate a profile."""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".ValidateProfile")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ValidateProfile, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'--spec-file',
|
||||||
|
metavar='<spec-file>',
|
||||||
|
required=True,
|
||||||
|
help=_('The spec file used to create the profile')
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
senlin_client = self.app.client_manager.clustering
|
||||||
|
|
||||||
|
spec = senlin_utils.get_spec_content(parsed_args.spec_file)
|
||||||
|
type_name = spec.get('type', None)
|
||||||
|
type_version = spec.get('version', None)
|
||||||
|
properties = spec.get('properties', None)
|
||||||
|
if type_name is None:
|
||||||
|
raise exc.CommandError(_("Missing 'type' key in spec file."))
|
||||||
|
if type_version is None:
|
||||||
|
raise exc.CommandError(_("Missing 'version' key in spec file."))
|
||||||
|
if properties is None:
|
||||||
|
raise exc.CommandError(_("Missing 'properties' key in spec file."))
|
||||||
|
|
||||||
|
if type_name == 'os.heat.stack':
|
||||||
|
stack_properties = senlin_utils.process_stack_spec(properties)
|
||||||
|
spec['properties'] = stack_properties
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'spec': spec,
|
||||||
|
}
|
||||||
|
|
||||||
|
profile = senlin_client.validate_profile(**params)
|
||||||
|
|
||||||
|
formatters = {}
|
||||||
|
formatters['metadata'] = senlin_utils.json_formatter
|
||||||
|
formatters['spec'] = senlin_utils.nested_dict_formatter(
|
||||||
|
['type', 'version', 'properties'],
|
||||||
|
['property', 'value'])
|
||||||
|
|
||||||
|
columns = [
|
||||||
|
'created_at',
|
||||||
|
'domain',
|
||||||
|
'id',
|
||||||
|
'metadata',
|
||||||
|
'name',
|
||||||
|
'project',
|
||||||
|
'spec',
|
||||||
|
'type',
|
||||||
|
'updated_at',
|
||||||
|
'user'
|
||||||
|
]
|
||||||
|
return columns, utils.get_dict_properties(profile.to_dict(), columns,
|
||||||
|
formatters=formatters)
|
||||||
|
@ -241,6 +241,44 @@ def do_profile_delete(service, args):
|
|||||||
print('Profile deleted: %s' % args.id)
|
print('Profile deleted: %s' % args.id)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('-s', '--spec-file', metavar='<SPEC FILE>', required=True,
|
||||||
|
help=_('The spec file used to create the profile.'))
|
||||||
|
def do_profile_validate(service, args):
|
||||||
|
"""Validate a profile."""
|
||||||
|
show_deprecated('senlin profile-validate',
|
||||||
|
'openstack cluster profile validate')
|
||||||
|
spec = utils.get_spec_content(args.spec_file)
|
||||||
|
type_name = spec.get('type', None)
|
||||||
|
type_version = spec.get('version', None)
|
||||||
|
properties = spec.get('properties', None)
|
||||||
|
if type_name is None:
|
||||||
|
raise exc.CommandError(_("Missing 'type' key in spec file."))
|
||||||
|
if type_version is None:
|
||||||
|
raise exc.CommandError(_("Missing 'version' key in spec file."))
|
||||||
|
if properties is None:
|
||||||
|
raise exc.CommandError(_("Missing 'properties' key in spec file."))
|
||||||
|
|
||||||
|
if type_name == 'os.heat.stack':
|
||||||
|
stack_properties = utils.process_stack_spec(properties)
|
||||||
|
spec['properties'] = stack_properties
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'spec': spec,
|
||||||
|
}
|
||||||
|
|
||||||
|
profile = service.validate_profile(**params)
|
||||||
|
|
||||||
|
formatters = {
|
||||||
|
'metadata': utils.json_formatter,
|
||||||
|
}
|
||||||
|
|
||||||
|
formatters['spec'] = utils.nested_dict_formatter(
|
||||||
|
['type', 'version', 'properties'],
|
||||||
|
['property', 'value'])
|
||||||
|
|
||||||
|
utils.print_dict(profile.to_dict(), formatters=formatters)
|
||||||
|
|
||||||
|
|
||||||
# POLICY TYPES
|
# POLICY TYPES
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ openstack.clustering.v1 =
|
|||||||
cluster_profile_type_list = senlinclient.v1.profile_type:ProfileTypeList
|
cluster_profile_type_list = senlinclient.v1.profile_type:ProfileTypeList
|
||||||
cluster_profile_type_show = senlinclient.v1.profile_type:ProfileTypeShow
|
cluster_profile_type_show = senlinclient.v1.profile_type:ProfileTypeShow
|
||||||
cluster_profile_update = senlinclient.v1.profile:UpdateProfile
|
cluster_profile_update = senlinclient.v1.profile:UpdateProfile
|
||||||
|
cluster_profile_validate = senlinclient.v1.profile:ValidateProfile
|
||||||
cluster_receiver_create = senlinclient.v1.receiver:CreateReceiver
|
cluster_receiver_create = senlinclient.v1.receiver:CreateReceiver
|
||||||
cluster_receiver_delete = senlinclient.v1.receiver:DeleteReceiver
|
cluster_receiver_delete = senlinclient.v1.receiver:DeleteReceiver
|
||||||
cluster_receiver_list = senlinclient.v1.receiver:ListReceiver
|
cluster_receiver_list = senlinclient.v1.receiver:ListReceiver
|
||||||
|
Loading…
x
Reference in New Issue
Block a user