Merge "Allows to create x509 keypair"
This commit is contained in:
commit
ca3ba526a3
@ -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:
|
||||
|
@ -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',
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user