txaws-dev team mailing list archive
-
txaws-dev team
-
Mailing list archive
-
Message #00019
[Merge] lp:~therve/txaws/import-keypair into lp:txaws
Thomas Herve has proposed merging lp:~therve/txaws/import-keypair into lp:txaws.
Requested reviews:
txAWS Developers (txaws-dev)
Related bugs:
Bug #738131 in txAWS: "Add support for ImportKeyPair"
https://bugs.launchpad.net/txaws/+bug/738131
For more details, see:
https://code.launchpad.net/~therve/txaws/import-keypair/+merge/54098
Rather simple branch, with some cleanups.
--
https://code.launchpad.net/~therve/txaws/import-keypair/+merge/54098
Your team txAWS Developers is requested to review the proposed merge of lp:~therve/txaws/import-keypair into lp:txaws.
=== modified file 'txaws/ec2/client.py'
--- txaws/ec2/client.py 2011-02-02 18:17:13 +0000
+++ txaws/ec2/client.py 2011-03-19 10:51:36 +0000
@@ -33,7 +33,7 @@
def describe_instances(self, *instance_ids):
"""Describe current instances."""
- instances= {}
+ instances = {}
for pos, instance_id in enumerate(instance_ids):
instances["InstanceId.%d" % (pos + 1)] = instance_id
query = self.query_factory(
@@ -167,7 +167,7 @@
"""
instances = {}
for pos, instance_id in enumerate(instance_ids):
- instances["InstanceId.%d" % (pos+1)] = instance_id
+ instances["InstanceId.%d" % (pos + 1)] = instance_id
query = self.query_factory(
action="TerminateInstances", creds=self.creds,
endpoint=self.endpoint, other_params=instances)
@@ -197,7 +197,7 @@
"""
group_names = {}
if names:
- group_names = dict([("GroupName.%d" % (i+1), name)
+ group_names = dict([("GroupName.%d" % (i + 1), name)
for i, name in enumerate(names)])
query = self.query_factory(
action="DescribeSecurityGroups", creds=self.creds,
@@ -648,6 +648,27 @@
d = query.submit()
return d.addCallback(self._parse_truth_return)
+ def import_keypair(self, keypair_name, key_material):
+ """
+ Import an existing SSH key into EC2. It supports:
+ * OpenSSH public key format (e.g., the format in
+ ~/.ssh/authorized_keys)
+ * Base64 encoded DER format
+ * SSH public key file format as specified in RFC4716
+ """
+ query = self.query_factory(
+ action="ImportKeyPair", creds=self.creds, endpoint=self.endpoint,
+ other_params={"KeyName": keypair_name,
+ "PublicKeyMaterial": b64encode(key_material)})
+ d = query.submit()
+ return d.addCallback(self._parse_import_keypair, key_material)
+
+ def _parse_import_keypair(self, xml_bytes, key_material):
+ keypair_data = XML(xml_bytes)
+ key_name = keypair_data.findtext("keyName")
+ key_fingerprint = keypair_data.findtext("keyFingerprint")
+ return model.Keypair(key_name, key_fingerprint, key_material)
+
def allocate_address(self):
"""
Acquire an elastic IP address to be attached subsequently to EC2
@@ -734,7 +755,7 @@
def describe_availability_zones(self, names=None):
zone_names = None
if names:
- zone_names = dict([("ZoneName.%d" % (i+1), name)
+ zone_names = dict([("ZoneName.%d" % (i + 1), name)
for i, name in enumerate(names)])
query = self.query_factory(
action="DescribeAvailabilityZones", creds=self.creds,
=== modified file 'txaws/ec2/tests/test_client.py'
--- txaws/ec2/tests/test_client.py 2011-02-02 18:17:13 +0000
+++ txaws/ec2/tests/test_client.py 2011-03-19 10:51:36 +0000
@@ -120,7 +120,6 @@
self.assertEquals(zone.name, "us-east-1a")
self.assertEquals(zone.state, "available")
-
creds = AWSCredentials("foo", "bar")
ec2 = client.EC2Client(creds, query_factory=StubQuery)
d = ec2.describe_availability_zones(["us-east-1a"])
@@ -1360,6 +1359,42 @@
d.addCallback(self.assertFalse)
return d
+ def test_import_keypair(self):
+
+ def check_parsed_import_keypair(keypair):
+ self.assertEquals(keypair.name, "example-key-name")
+ self.assertEquals(
+ keypair.fingerprint,
+ "1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f")
+ self.assertEquals(keypair.material, material)
+
+ class StubQuery(object):
+
+ def __init__(stub, action="", creds=None, endpoint=None,
+ other_params={}):
+ self.assertEqual(action, "ImportKeyPair")
+ self.assertEqual("foo", creds)
+ self.assertEquals(
+ other_params,
+ {"KeyName": "example-key-name",
+ "PublicKeyMaterial":
+ "c3NoLWRzcyBBQUFBQjNOemFDMWtjM01BQUFDQkFQNmFjakFQeitUR"
+ "jJkREtmZGlhcnp2cXBBcjhlbUl6UElBWUp6QXNoTFgvUTJCZ2tWc0"
+ "42eGI2QUlIUGE1MUFtWXVieU5PYjMxeVhWS2FRQTF6L213SHZtRld"
+ "LQ1ZFQ0wwPSkgdXNlckBob3N0"})
+
+ def submit(self):
+ return succeed(payload.sample_import_keypair_result)
+
+ ec2 = client.EC2Client(creds="foo", query_factory=StubQuery)
+ material = (
+ "ssh-dss AAAAB3NzaC1kc3MAAACBAP6acjAPz+TF2dDKfdiarzvqpAr8emIzPIAY"
+ "JzAshLX/Q2BgkVsN6xb6AIHPa51AmYubyNOb31yXVKaQA1z/mwHvmFWKCVECL0=)"
+ " user@host")
+ d = ec2.import_keypair("example-key-name", material)
+ d.addCallback(check_parsed_import_keypair)
+ return d
+
class EC2ErrorWrapperTestCase(TXAWSTestCase):
@@ -1486,7 +1521,7 @@
query = client.Query(
action="DescribeInstances", creds=self.creds,
endpoint=self.endpoint, other_params={"InstanceId.0": "12345"},
- time_tuple=(2007,11,12,13,14,15,0,0,0))
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0))
self.assertEqual(
query.params,
{"AWSAccessKeyId": "foo",
@@ -1518,7 +1553,7 @@
query = client.Query(
action="DescribeInstances", creds=self.creds,
endpoint=self.endpoint, other_params={"fun": "games"},
- time_tuple=(2007,11,12,13,14,15,0,0,0))
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0))
self.assertEqual([
("AWSAccessKeyId", "foo"),
("Action", "DescribeInstances"),
@@ -1547,9 +1582,9 @@
query = client.Query(
action="DescribeInstances", creds=self.creds,
endpoint=self.endpoint,
- other_params={"fu n": "g/ames", "argwithnovalue":"",
+ other_params={"fu n": "g/ames", "argwithnovalue": "",
"InstanceId.1": "i-1234"},
- time_tuple=(2007,11,12,13,14,15,0,0,0))
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0))
expected_query = ("AWSAccessKeyId=foo&Action=DescribeInstances"
"&InstanceId.1=i-1234"
"&SignatureVersion=2&"
@@ -1560,7 +1595,8 @@
def test_signing_text(self):
query = client.Query(
action="DescribeInstances", creds=self.creds,
- endpoint=self.endpoint, time_tuple=(2007,11,12,13,14,15,0,0,0))
+ endpoint=self.endpoint,
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0))
signing_text = ("GET\n%s\n/\n" % self.endpoint.host +
"AWSAccessKeyId=foo&Action=DescribeInstances&"
"SignatureVersion=2&"
@@ -1570,7 +1606,8 @@
def test_old_signing_text(self):
query = client.Query(
action="DescribeInstances", creds=self.creds,
- endpoint=self.endpoint, time_tuple=(2007,11,12,13,14,15,0,0,0),
+ endpoint=self.endpoint,
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0),
other_params={"SignatureVersion": "1"})
signing_text = (
"ActionDescribeInstancesAWSAccessKeyIdfooSignatureVersion1"
@@ -1589,7 +1626,8 @@
def test_old_sign(self):
query = client.Query(
action="DescribeInstances", creds=self.creds,
- endpoint=self.endpoint, time_tuple=(2007,11,12,13,14,15,0,0,0),
+ endpoint=self.endpoint,
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0),
other_params={"SignatureVersion": "1"})
query.sign()
self.assertEqual(
@@ -1598,7 +1636,8 @@
def test_unsupported_sign(self):
query = client.Query(
action="DescribeInstances", creds=self.creds,
- endpoint=self.endpoint, time_tuple=(2007,11,12,13,14,15,0,0,0),
+ endpoint=self.endpoint,
+ time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0),
other_params={"SignatureVersion": "0"})
self.assertRaises(RuntimeError, query.sign)
@@ -1622,7 +1661,7 @@
query = client.Query(
action='BadQuery', creds=self.creds, endpoint=self.endpoint,
- time_tuple=(2009,8,15,13,14,15,0,0,0))
+ time_tuple=(2009, 8, 15, 13, 14, 15, 0, 0, 0))
failure = query.submit()
d = self.assertFailure(failure, TwistedWebError)
@@ -1647,7 +1686,7 @@
query = client.Query(
action='BadQuery', creds=self.creds, endpoint=self.endpoint,
- time_tuple=(2009,8,15,13,14,15,0,0,0))
+ time_tuple=(2009, 8, 15, 13, 14, 15, 0, 0, 0))
failure = query.submit()
d = self.assertFailure(failure, TwistedWebError)
@@ -1676,7 +1715,7 @@
query = client.Query(
action='BadQuery', creds=self.creds, endpoint=self.endpoint,
- time_tuple=(2009,8,15,13,14,15,0,0,0))
+ time_tuple=(2009, 8, 15, 13, 14, 15, 0, 0, 0))
failure = query.submit()
d = self.assertFailure(failure, TwistedWebError)
@@ -1731,7 +1770,7 @@
"""Copied from twisted.web.test.test_webclient."""
query = client.Query(
action="DummyQuery", creds=self.creds, endpoint=self.endpoint,
- time_tuple=(2009,8,17,13,14,15,0,0,0))
+ time_tuple=(2009, 8, 15, 13, 14, 15, 0, 0, 0))
deferred = query.get_page(self.get_url("file"))
deferred.addCallback(self.assertEquals, "0123456789")
return deferred
=== modified file 'txaws/testing/payload.py'
--- txaws/testing/payload.py 2010-07-20 10:15:48 +0000
+++ txaws/testing/payload.py 2011-03-19 10:51:36 +0000
@@ -706,6 +706,15 @@
"""
+sample_import_keypair_result = """\
+<?xml version="1.0"?>
+<ImportKeyPairResponse xmlns="http://ec2.amazonaws.com/doc/%s/">
+ <keyName>example-key-name</keyName>
+ <keyFingerprint>1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f</keyFingerprint>
+</ImportKeyPairResponse>
+""" % (version.ec2_api,)
+
+
sample_allocate_address_result = """\
<?xml version="1.0"?>
<AllocateAddressResponse xmlns="http://ec2.amazonaws.com/doc/%s/">