Merge "Allows to create x509 keypair"

This commit is contained in:
Jenkins 2016-12-21 08:14:45 +00:00 committed by Gerrit Code Review
commit ca3ba526a3
3 changed files with 74 additions and 8 deletions

View File

@ -59,9 +59,9 @@ class NovaClientPlugin(client_plugin.ClientPlugin):
exceptions_module = exceptions
supported_versions = [
NOVA_API_VERSION, V2_26
NOVA_API_VERSION, V2_2, V2_26
] = [
'2.1', '2.26'
'2.1', '2.2', '2.26'
]
service_types = [COMPUTE] = ['compute']
@ -89,7 +89,7 @@ class NovaClientPlugin(client_plugin.ClientPlugin):
client = nc.Client(version, **args)
# NOTE: check for microversion availability
if version == self.V2_26:
if version in [self.V2_2, self.V2_26]:
try:
client.versions.get_current()
except exceptions.NotAcceptable:

View File

@ -12,6 +12,7 @@
# under the License.
import six
from heat.common import exception
from heat.common.i18n import _
from heat.engine import attributes
from heat.engine import constraints
@ -40,9 +41,9 @@ class KeyPair(resource.Resource):
required_service_extension = 'os-keypairs'
PROPERTIES = (
NAME, SAVE_PRIVATE_KEY, PUBLIC_KEY,
NAME, SAVE_PRIVATE_KEY, PUBLIC_KEY, KEY_TYPE,
) = (
'name', 'save_private_key', 'public_key',
'name', 'save_private_key', 'public_key', 'type',
)
ATTRIBUTES = (
@ -72,6 +73,13 @@ class KeyPair(resource.Resource):
'public key from a pre-existing key pair. If not supplied, a '
'new key pair will be generated.')
),
KEY_TYPE: properties.Schema(
properties.Schema.STRING,
_('Keypair type. Supported since Nova api version 2.2.'),
constraints=[
constraints.AllowedValues(['ssh', 'x509'])],
support_status=support.SupportStatus(version='8.0.0')
),
}
attributes_schema = {
@ -113,10 +121,35 @@ class KeyPair(resource.Resource):
self._public_key = nova_key.public_key
return self._public_key
def validate(self):
super(KeyPair, self).validate()
# Check if key_type is allowed to use
if self.properties[self.KEY_TYPE]:
try:
self.client(
version=self.client_plugin().V2_2)
except exception.InvalidServiceVersion as ex:
msg = (_('Cannot use "%(type)s" property - nova does not '
'support it: %(error)s') %
{'error': six.text_type(ex), 'type': self.KEY_TYPE})
raise exception.StackValidationFailed(message=msg)
def handle_create(self):
pub_key = self.properties[self.PUBLIC_KEY] or None
new_keypair = self.client().keypairs.create(self.properties[self.NAME],
public_key=pub_key)
key_type = self.properties[self.KEY_TYPE]
nc = self.client(
version=self.client_plugin().V2_2) if key_type else self.client()
create_kwargs = {
'name': self.properties[self.NAME],
'public_key': pub_key
}
if key_type:
create_kwargs[self.KEY_TYPE] = key_type
new_keypair = nc.keypairs.create(**create_kwargs)
if (self.properties[self.SAVE_PRIVATE_KEY] and
hasattr(new_keypair, 'private_key')):
self.data_set('private_key',

View File

@ -67,7 +67,7 @@ class NovaKeyPairTest(common.HeatTestCase):
return kp_res
def _get_mock_kp_for_create(self, key_name, public_key=None,
priv_saved=False):
priv_saved=False, key_type=None):
template = copy.deepcopy(self.kp_template)
template['resources']['kp']['properties']['name'] = key_name
props = template['resources']['kp']['properties']
@ -78,6 +78,8 @@ class NovaKeyPairTest(common.HeatTestCase):
if priv_saved:
nova_key.private_key = "private key for %s" % key_name
props['save_private_key'] = True
if key_type:
props['type'] = key_type
kp_res = self._get_test_resource(template)
self.patchobject(self.fake_keypairs, 'create',
return_value=nova_key)
@ -92,6 +94,8 @@ class NovaKeyPairTest(common.HeatTestCase):
self.patchobject(created_key, 'to_dict',
return_value=key_info)
scheduler.TaskRunner(tp_test.create)()
self.fake_keypairs.create.assert_called_once_with(
name=key_name, public_key=None)
self.assertEqual("", tp_test.FnGetAtt('private_key'))
self.assertEqual("generated test public key",
tp_test.FnGetAtt('public_key'))
@ -99,6 +103,17 @@ class NovaKeyPairTest(common.HeatTestCase):
self.assertEqual((tp_test.CREATE, tp_test.COMPLETE), tp_test.state)
self.assertEqual(tp_test.resource_id, created_key.name)
def test_create_key_with_type(self):
"""Test basic create."""
key_name = "with_type"
tp_test, created_key = self._get_mock_kp_for_create(key_name,
key_type='ssh')
scheduler.TaskRunner(tp_test.create)()
self.assertEqual((tp_test.CREATE, tp_test.COMPLETE), tp_test.state)
self.assertEqual(tp_test.resource_id, created_key.name)
self.fake_keypairs.create.assert_called_once_with(
name=key_name, public_key=None, type='ssh')
def test_create_key_empty_name(self):
"""Test creation of a keypair whose name is of length zero."""
key_name = ""
@ -127,6 +142,24 @@ class NovaKeyPairTest(common.HeatTestCase):
self.assertIn("kp.properties.name: length (256) is out of "
"range (min: 1, max: 255)", six.text_type(error))
def test_validate(self):
template = copy.deepcopy(self.kp_template)
template['resources']['kp']['properties']['type'] = 'x509'
stack = utils.parse_stack(template)
definition = stack.t.resource_definitions(stack)['kp']
kp_res = keypair.KeyPair('kp', definition, stack)
self.patchobject(nova.NovaClientPlugin, '_create',
side_effect=exception.InvalidServiceVersion(
service='compute',
version='2.2'
))
error = self.assertRaises(exception.StackValidationFailed,
kp_res.validate)
self.assertIn('Cannot use "type" property - nova does not support it: '
'Invalid service compute version 2.2',
six.text_type(error))
def test_check_key(self):
res = self._get_test_resource(self.kp_template)
res.client = mock.Mock()