Keypair unit tests

Change-Id: I217a9c6abd52fd423e775459334e590a8e1549e7
This commit is contained in:
alevine 2014-12-22 11:57:33 +04:00
parent 8053ca77bb
commit 92e11cc9d8
6 changed files with 185 additions and 8 deletions

View File

@ -1242,7 +1242,7 @@ class CloudController(object):
return key_pair.delete_key_pair(context, key_name)
def import_key_pair(self, context, key_name, public_key_material):
return key_pair.create_key_pair(context, key_name,
return key_pair.import_key_pair(context, key_name,
public_key_material)
def describe_availability_zones(self, context, zone_name=None,

View File

@ -14,6 +14,7 @@
import base64
from novaclient import exceptions as nova_exception
from oslo.config import cfg
from ec2api.api import clients
@ -61,25 +62,38 @@ def describe_key_pairs(context, key_name=None, filter=None):
return {'keySet': formatted_key_pairs}
def _validate_name(name):
if len(name) > 255:
raise exception.InvalidParameterValue(
value=name,
parameter='KeyName',
reason='lenght is exceeds maximum of 255')
def create_key_pair(context, key_name):
_validate_name(key_name)
nova = clients.nova(context)
try:
key_pair = nova.keypairs.create(key_name)
except clients.novaclient.exceptions.Conflict as ex:
raise exception.KeyPairExists(key_name=key_name)
except nova_exception.OverLimit:
raise exception.ResourceLimitExceeded(resource='keypairs')
except nova_exception.Conflict:
raise exception.InvalidKeyPairDuplicate(key_name=key_name)
formatted_key_pair = _format_key_pair(key_pair)
formatted_key_pair['keyMaterial'] = key_pair.private_key
return formatted_key_pair
def import_key_pair(context, key_name, public_key_material):
_validate_name(key_name)
nova = clients.nova(context)
public_key = base64.b64decode(public_key_material)
try:
key_pair = nova.keypairs.create(key_name, public_key)
except clients.novaclient.exceptions.Conflict as ex:
raise exception.KeyPairExists(key_name=key_name)
except nova_exception.OverLimit:
raise exception.ResourceLimitExceeded(resource='keypairs')
except nova_exception.Conflict:
raise exception.InvalidKeyPairDuplicate(key_name=key_name)
return _format_key_pair(key_pair)
@ -87,7 +101,7 @@ def delete_key_pair(context, key_name):
nova = clients.nova(context)
try:
nova.keypairs.delete(key_name)
except exception.NotFound:
except nova_exception.NotFound:
# aws returns true even if the key doesn't exist
pass
return True

View File

@ -353,6 +353,10 @@ class ResourceLimitExceeded(Overlimit):
msg_fmt = _('You have reached the limit of %(resource)s')
class SecurityGroupLimitExceeded(Overlimit):
msg_fmt = _('You have reached the limit of security groups')
class ImageNotActive(Invalid):
ec2_code = 'InvalidAMIID.Unavailable'
# TODO(ft): Change the message with the real AWS message
@ -375,7 +379,7 @@ class InvalidAvailabilityZoneNotFound(NotFound):
msg_fmt = _("Availability zone %(id)s not found")
class KeyPairExists(Invalid):
class InvalidKeyPairDuplicate(Invalid):
ec2_code = 'InvalidKeyPair.Duplicate'
msg_fmt = _("Key pair '%(key_name)s' already exists.")

View File

@ -41,6 +41,7 @@ class ApiTestCase(test_base.BaseTestCase):
self.nova_servers = nova_mock.return_value.servers
self.nova_flavors = nova_mock.return_value.flavors
self.nova_floating_ips = nova_mock.return_value.floating_ips
self.nova_key_pairs = nova_mock.return_value.keypairs
self.nova_security_groups = nova_mock.return_value.security_groups
self.nova_security_group_rules = (
nova_mock.return_value.security_group_rules)

View File

@ -924,6 +924,63 @@ EC2_ROUTE_TABLE_2 = {
}
# keypair objects
class NovaKeyPair(object):
def __init__(self, nova_keypair_dict):
self.name = nova_keypair_dict['name']
self.fingerprint = nova_keypair_dict['fingerprint']
self.private_key = nova_keypair_dict['private_key']
self.public_key = nova_keypair_dict['public_key']
PRIVATE_KEY = (
'-----BEGIN RSA PRIVATE KEY-----\n'
'MIIEowIBAAKCAQEAgXvm1sZ9MDiAXvGraRFja0/WqyJ1gE6j/QPjreNryd34zBFcv2pQXLyvb'
'gQG\nFxN4rMGNScgKgLSgHjE/TNywkT8N7aYOiRmGkzQciP5t+zf8ZdCyl+hqgoQig1uY8sV/'
'fSxUWCB9\n8sF7Tpl0iGkWM6Wo0H/PvcwiS2+UPSzArj+b+Erb/JbBF4O8GgSmtLMeq60RuDM'
'dJi5JYCP66HUw\njtYb/f9y1Q9nEGVcxY2v0RI1n0yOaZDKPInLKHeR/ole2QVwPZB69mBj11'
'LErqb+jzCaSivnhy6g\nPzaSHdZaRmy1f+6ltFI1iKt+4y/iINOY0skYC1hc7IevE7j7dGQTD'
'wIDAQABAoIBAEbD2Vfd6MM2\nzemVuHFWoHggjRjAX2k9EWCRBJifJuSPXI7imka+qqbUNCgz'
'KMTpzlTT/wyouBy5Gp0Fmyu9nP30\ncP9FdsI04hiHLWUtcBwQ7+8RDNn6mmM0JcyWfdOIXnG'
'hjYMQVuUaGvLM6SQ4EnsteUJh57451zBV\nDbYVRES2Fbq+j8tPQj1KuD0HhZBboNPOxo6E5n'
'TxvMXnvuI+cb9D99lqATcb8c0zsLMl/5SKEBDc\nj72X4GPfE3Dc5/MO6L/89ms3TqF3lx8lh'
'wFSMfFfA3Nf5xrX3gnorGe81odXBXFveqMCemvfJYxg\nS9KPkM8CMnwn6yPS3ftW5xH3nMkC'
'gYEAvN4lQuOTy9RONCtfgZ6lhR00xfDiibOsE2jFXqXlXrZS\nunBx2WRwNuhAcYGbC4T71iC'
'BR+LJHECpFjEFX9cKjd8xZPdIzJmwMBylPnli8IxK9UMroxF/MDNy\nnJfdPIWagIrk9VRsQH'
'UOQW8Ab5dYJuP6c03L5xwmnFfeFnlz10MCgYEAr4Iu182bC2ppwr5AYD8T\n/QKVPZTmizbtG'
'H/7a2+WnfNCz2u0MOo2h1rF7/SOYR8nalTTsN1z4D8cRX7YQ0P4yBtNRNiN7WH3\n+smTWztI'
'VYvJA2RsOeP0zfGLJiFSMWLOjlqpJ7KbkEuPcxshGd+/w8upxgJeV8Dwz0ZWbY302kUC\ngYE'
'AhneTB+CHpaNuWm5W/S46ol9850DtySSG6vq5Kv3qJFii5eKQ7Do6Op145FdmT/lKY9WYtdmd'
'\nXeQbfpVAQlAUT5YM0NnOlv0FF/wNGkHKU4FPDPfZ5avbZjH688qb1S86JTK+eHy25d1xXNz'
'u7oRO\nWsIN2nIVLmI4iy90C4RFGYkCgYBXpKPtwk/VkItF46nUJku+Agcy3GOQS5p0rJyJ1w'
'yYzbykRf2S\nm7MlPpAvtqlPGLafI8MexEe0SO++SIyIcq4Oh4u7gITHcS/bfcPnQCBsD8UOu'
'5xMAGjkWuWI4gTg\ngp3xepaUK14B3anB6l9KQ3DIvrCGH/Kq0b+vUkmgpc4LHQKBgBtul9bN'
'KLF+LJf4JHYNFSurE8Y/\nn8FZ3dZo3T0Q3Sap9bP3ZHemoQ6QXbmpu3H4Mf+2kcNg6YKFW3p'
'hxW3cuAcZOMHPCrpr3mCdyhF0\nKM74ANEwg8MekBJTcWZUNFv9HZDvTuhp6HSrbMnNEQogkd'
'5PoubiusvAKpeb6NBGnLMq\n'
'-----END RSA PRIVATE KEY-----'
)
PUBLIC_KEY = ('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIkYwwXm8UeQXx1c2eFrDIB6b'
'6ApI0KTKs1wezDfFdSIs93vAt4Jx1MyaR/PwqwLk2CDyFoGJBWBI9YcodLAjoRg'
'Ovr6JigEv5V3yp+eEkeAJO0cPA21vN/KQ8Vxml68ZvvqbdqKZXc/rpFZ1OgCmHt'
'udo96uQiRB0FM3mdE8YOTswcfkJxTvCe3axX50pYXXfIb0dn9CzC1hyQWYPXvlv'
'qFNvr/Li7sSBycTBAh4Ar/uEigs/uOjhvzd7GpzY7qDqBVJFAmP7HiiOxoXPkKu'
'W62Ftd')
KEY_FINGERPRINT = '2a:72:dd:aa:0d:a6:45:4d:27:4f:75:28:73:0d:a6:10:35:88:e1:ce'
OS_KEY_PAIR = {'name': 'keyname',
'private_key': PRIVATE_KEY,
'public_key': PUBLIC_KEY,
'fingerprint': KEY_FINGERPRINT}
EC2_KEY_PAIR = {'keyName': 'keyname',
'keyFingerprint': KEY_FINGERPRINT,
'keyMaterial': PRIVATE_KEY}
# Object generator functions section
# internet gateway generator functions

View File

@ -0,0 +1,101 @@
# Copyright 2014
# The Cloudscaling Group, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import base64
from novaclient import exceptions as nova_exception
from ec2api.tests import base
from ec2api.tests import fakes
from ec2api.tests import matchers
from ec2api.tests import tools
class KeyPairCase(base.ApiTestCase):
def test_create_key_pair(self):
self.nova_key_pairs.create.return_value = (
fakes.NovaKeyPair(fakes.OS_KEY_PAIR))
resp = self.execute('CreateKeyPair', {'KeyName': 'keyname'})
self.assertEqual(200, resp['status'])
self.assertThat(fakes.EC2_KEY_PAIR, matchers.DictMatches(
tools.purge_dict(resp, {'status'})))
self.nova_key_pairs.create.assert_called_once_with('keyname')
def test_create_key_pair_invalid(self):
self.nova_key_pairs.create.side_effect = (
nova_exception.Conflict(409))
resp = self.execute('CreateKeyPair', {'KeyName': 'keyname'})
self.assertEqual(400, resp['status'])
self.assertEqual('InvalidKeyPair.Duplicate', resp['Error']['Code'])
resp = self.execute('CreateKeyPair', {'KeyName': 'k' * 256})
self.assertEqual(400, resp['status'])
self.assertEqual('InvalidParameterValue', resp['Error']['Code'])
self.nova_key_pairs.create.side_effect = (
nova_exception.OverLimit(413))
resp = self.execute('CreateKeyPair', {'KeyName': 'keyname'})
self.assertEqual(400, resp['status'])
self.assertEqual('ResourceLimitExceeded', resp['Error']['Code'])
def test_import_key_pair(self):
self.nova_key_pairs.create.return_value = (
fakes.NovaKeyPair(fakes.OS_KEY_PAIR))
resp = self.execute('ImportKeyPair',
{'KeyName': 'keyname',
'PublicKeyMaterial': base64.b64encode(
fakes.PUBLIC_KEY)})
self.assertEqual(200, resp['status'])
self.assertThat(tools.purge_dict(fakes.EC2_KEY_PAIR, {'keyMaterial'}),
matchers.DictMatches(tools.purge_dict(resp, {'status'})))
self.nova_key_pairs.create.assert_called_once_with('keyname',
fakes.PUBLIC_KEY)
def test_import_key_pair_invalid(self):
self.nova_key_pairs.create.side_effect = (
nova_exception.OverLimit(413))
resp = self.execute('ImportKeyPair',
{'KeyName': 'keyname',
'PublicKeyMaterial': base64.b64encode(
fakes.PUBLIC_KEY)})
self.assertEqual(400, resp['status'])
self.assertEqual('ResourceLimitExceeded', resp['Error']['Code'])
def test_delete_key_pair(self):
self.nova_key_pairs.delete.return_value = True
resp = self.execute('DeleteKeyPair', {'KeyName': 'keyname'})
self.assertEqual(200, resp['status'])
self.nova_key_pairs.delete.assert_called_once_with('keyname')
self.nova_key_pairs.delete.side_effect = nova_exception.NotFound(404)
resp = self.execute('DeleteKeyPair', {'KeyName': 'keyname1'})
self.assertEqual(200, resp['status'])
self.nova_key_pairs.delete.assert_any_call('keyname1')
def test_describe_key_pair(self):
self.nova_key_pairs.list.return_value = [fakes.NovaKeyPair(
fakes.OS_KEY_PAIR)]
resp = self.execute('DescribeKeyPairs', {})
self.assertEqual(200, resp['status'])
self.assertThat(resp['keySet'],
matchers.ListMatches([
tools.purge_dict(fakes.EC2_KEY_PAIR,
{'keyMaterial'})]))
self.nova_key_pairs.list.assert_called_once()
def test_describe_key_pair_invalid(self):
self.nova_key_pairs.list.return_value = [fakes.NovaKeyPair(
fakes.OS_KEY_PAIR)]
resp = self.execute('DescribeKeyPairs', {'KeyName': 'badname'})
self.assertEqual(404, resp['status'])
self.assertEqual('InvalidKeyPair.NotFound', resp['Error']['Code'])
self.nova_key_pairs.list.assert_called_once()