diff --git a/heat/engine/resources/openstack/nova/keypair.py b/heat/engine/resources/openstack/nova/keypair.py index b7994cc1d5..25df73acaa 100644 --- a/heat/engine/resources/openstack/nova/keypair.py +++ b/heat/engine/resources/openstack/nova/keypair.py @@ -22,7 +22,8 @@ from heat.engine import translation NOVA_MICROVERSIONS = (MICROVERSION_KEY_TYPE, - MICROVERSION_USER) = ('2.2', '2.10') + MICROVERSION_USER, + MICROVERSION_PUBLIC_KEY) = ('2.2', '2.10', '2.92') class KeyPair(resource.Resource): @@ -71,9 +72,10 @@ class KeyPair(resource.Resource): ), PUBLIC_KEY: properties.Schema( properties.Schema.STRING, - _('The optional public key. This allows users to supply the ' - 'public key from a pre-existing key pair. If not supplied, a ' - 'new key pair will be generated.') + _('The public key. This allows users to supply the public key ' + 'from a pre-existing key pair. In Nova api version < 2.92, ' + 'if not supplied, a new key pair will be generated. ' + 'This property is required since Nova api version 2.92.') ), KEY_TYPE: properties.Schema( properties.Schema.STRING, @@ -148,6 +150,7 @@ class KeyPair(resource.Resource): # Check if key_type is allowed to use key_type = self.properties[self.KEY_TYPE] user = self.properties[self.USER] + public_key = self.properties[self.PUBLIC_KEY] validate_props = [] c_plugin = self.client_plugin() @@ -161,6 +164,12 @@ class KeyPair(resource.Resource): 'support required api microversion.') % validate_props) raise exception.StackValidationFailed(message=msg) + if not public_key and c_plugin.is_version_supported( + MICROVERSION_PUBLIC_KEY): + msg = _('The public_key property is required by the nova API ' + 'version currently used.') + raise exception.StackValidationFailed(message=msg) + def handle_create(self): pub_key = self.properties[self.PUBLIC_KEY] or None user_id = self.properties[self.USER] diff --git a/heat/tests/openstack/nova/test_keypair.py b/heat/tests/openstack/nova/test_keypair.py index 29c92c0f03..83dd116d36 100644 --- a/heat/tests/openstack/nova/test_keypair.py +++ b/heat/tests/openstack/nova/test_keypair.py @@ -201,6 +201,29 @@ class NovaKeyPairTest(common.HeatTestCase): return_value='2.1') self._test_validate(user='user_A') + def test_validate_public_key(self): + self.patchobject(nova.NovaClientPlugin, 'get_max_microversion', + return_value='2.92') + template = copy.deepcopy(self.kp_template) + template['resources']['kp']['properties']['public_key'] = 'dummy' + stack = utils.parse_stack(template) + definition = stack.t.resource_definitions(stack)['kp'] + kp_res = keypair.KeyPair('kp', definition, stack) + kp_res.validate() + + def test_validate_public_key_fail(self): + self.patchobject(nova.NovaClientPlugin, 'get_max_microversion', + return_value='2.92') + template = copy.deepcopy(self.kp_template) + stack = utils.parse_stack(template) + definition = stack.t.resource_definitions(stack)['kp'] + kp_res = keypair.KeyPair('kp', definition, stack) + error = self.assertRaises(exception.StackValidationFailed, + kp_res.validate) + msg = ('The public_key property is required by the nova API version ' + 'currently used.') + self.assertIn(msg, str(error)) + def test_check_key(self): res = self._get_test_resource(self.kp_template) res.state_set(res.CREATE, res.COMPLETE, 'for test')