txaws-dev team mailing list archive
-
txaws-dev team
-
Mailing list archive
-
Message #00146
[Merge] lp:~franciscosouza/txaws/txaws-bundled-vpc into lp:txaws
Francisco Souza has proposed merging lp:~franciscosouza/txaws/txaws-bundled-vpc into lp:txaws.
Requested reviews:
txAWS Committers (txaws-dev)
For more details, see:
https://code.launchpad.net/~franciscosouza/txaws/txaws-bundled-vpc/+merge/135397
client, ec2: bundling changes needed for VPC
I use this CL for patching only, original CL's are:
https://codereview.appspot.com/6852064/
https://codereview.appspot.com/6826065/
https://codereview.appspot.com/6814123/
https://codereview.appspot.com/6822097/
This one also includes a change in parsing of instance sets.
https://codereview.appspot.com/6851093/
--
https://code.launchpad.net/~franciscosouza/txaws/txaws-bundled-vpc/+merge/135397
Your team txAWS Committers is requested to review the proposed merge of lp:~franciscosouza/txaws/txaws-bundled-vpc into lp:txaws.
=== modified file 'txaws/client/base.py'
--- txaws/client/base.py 2012-05-16 02:35:26 +0000
+++ txaws/client/base.py 2012-11-21 12:35:25 +0000
@@ -1,3 +1,6 @@
+import os
+import urlparse
+
try:
from xml.etree.ElementTree import ParseError
except ImportError:
@@ -6,16 +9,16 @@
import warnings
from StringIO import StringIO
+from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet.ssl import ClientContextFactory
from twisted.internet.protocol import Protocol
from twisted.internet.defer import Deferred, succeed, fail
from twisted.python import failure
from twisted.web import http
from twisted.web.iweb import UNKNOWN_LENGTH
-from twisted.web.client import HTTPClientFactory
-from twisted.web.client import Agent
+from twisted.web.client import Agent, ProxyAgent
from twisted.web.client import ResponseDone
-from twisted.web.http import NO_CONTENT
+from twisted.web.http import NO_CONTENT, PotentialDataLoss
from twisted.web.http_headers import Headers
from twisted.web.error import Error as TwistedWebError
try:
@@ -130,7 +133,7 @@
self._received += len(bytes)
def connectionLost(self, reason):
- reason.trap(ResponseDone)
+ reason.trap(ResponseDone, PotentialDataLoss)
d = self.finished
self.finished = None
streaming = self.content_length is UNKNOWN_LENGTH
@@ -220,16 +223,28 @@
if (self.body_producer is None) and (data is not None):
self.body_producer = FileBodyProducer(StringIO(data))
if scheme == "https":
- if self.endpoint.ssl_hostname_verification:
- contextFactory = WebVerifyingContextFactory(host)
+ proxy_endpoint = os.environ.get("https_proxy")
+ if proxy_endpoint:
+ proxy_url = urlparse.urlparse(proxy_endpoint)
+ endpoint = TCP4ClientEndpoint(self.reactor, proxy_url.hostname, proxy_url.port)
+ agent = ProxyAgent(endpoint)
else:
- contextFactory = WebClientContextFactory()
- agent = Agent(self.reactor, contextFactory)
+ if self.endpoint.ssl_hostname_verification:
+ contextFactory = WebVerifyingContextFactory(host)
+ else:
+ contextFactory = WebClientContextFactory()
+ agent = Agent(self.reactor, contextFactory)
self.client.url = url
d = agent.request(method, url, self.request_headers,
self.body_producer)
else:
- agent = Agent(self.reactor)
+ proxy_endpoint = os.environ.get("http_proxy")
+ if proxy_endpoint:
+ proxy_url = urlparse.urlparse(proxy_endpoint)
+ endpoint = TCP4ClientEndpoint(self.reactor, proxy_url.hostname, proxy_url.port)
+ agent = ProxyAgent(endpoint)
+ else:
+ agent = Agent(self.reactor)
d = agent.request(method, url, self.request_headers,
self.body_producer)
d.addCallback(self._handle_response)
=== modified file 'txaws/client/discover/tests/test_command.py'
--- txaws/client/discover/tests/test_command.py 2012-01-27 02:10:24 +0000
+++ txaws/client/discover/tests/test_command.py 2012-11-21 12:35:25 +0000
@@ -74,9 +74,9 @@
url = (
"http://endpoint?AWSAccessKeyId=key&"
"Action=DescribeRegions&"
- "Signature=3%2BHSkQQosF1Sr9AL3kdY31tEfTWQ2whjJOUSc3kvc2c%3D&"
+ "Signature=7fyxNidMkL%2B85udGOxqm%2BgM2o1gLyeLG2a0UOmfBOXQ%3D&"
"SignatureMethod=HmacSHA256&SignatureVersion=2&"
- "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2009-11-30")
+ "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2012-08-15")
self.assertEqual("GET", self.method)
self.assertEqual(url, self.url)
self.assertEqual("URL: %s\n"
@@ -99,9 +99,9 @@
url = (
"http://endpoint?AWSAccessKeyId=key&"
"Action=DescribeRegions&RegionName.0=us-west-1&"
- "Signature=6D8aCgSPQOYixowRHy26aRFzK2Vwgixl9uwegYX9nLA%3D&"
+ "Signature=FL4JjDKbWdg531q1KKUPild%2BvyqspA5wxSmOeWXWsJI%3D&"
"SignatureMethod=HmacSHA256&SignatureVersion=2&"
- "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2009-11-30")
+ "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2012-08-15")
self.assertEqual("GET", self.method)
self.assertEqual(url, self.url)
self.assertEqual("URL: %s\n"
@@ -128,9 +128,9 @@
url = (
"http://endpoint?AWSAccessKeyId=key&"
"Action=DescribeRegions&RegionName.0=us-west-1&"
- "Signature=6D8aCgSPQOYixowRHy26aRFzK2Vwgixl9uwegYX9nLA%3D&"
+ "Signature=FL4JjDKbWdg531q1KKUPild%2BvyqspA5wxSmOeWXWsJI%3D&"
"SignatureMethod=HmacSHA256&SignatureVersion=2&"
- "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2009-11-30")
+ "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2012-08-15")
self.assertEqual("GET", self.method)
self.assertEqual(url, self.url)
self.assertEqual("URL: %s\n"
@@ -185,9 +185,9 @@
url = (
"http://endpoint?AWSAccessKeyId=key&"
"Action=DescribeRegions&RegionName.0=us-west-1&"
- "Signature=6D8aCgSPQOYixowRHy26aRFzK2Vwgixl9uwegYX9nLA%3D&"
+ "Signature=FL4JjDKbWdg531q1KKUPild%2BvyqspA5wxSmOeWXWsJI%3D&"
"SignatureMethod=HmacSHA256&SignatureVersion=2&"
- "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2009-11-30")
+ "Timestamp=2010-06-04T23%3A40%3A00Z&Version=2012-08-15")
self.assertEqual("GET", self.method)
self.assertEqual(url, self.url)
self.assertEqual("URL: %s\n"
=== modified file 'txaws/ec2/client.py'
--- txaws/ec2/client.py 2012-05-05 00:17:02 +0000
+++ txaws/ec2/client.py 2012-11-21 12:35:25 +0000
@@ -48,7 +48,7 @@
def run_instances(self, image_id, min_count, max_count,
security_groups=None, key_name=None, instance_type=None,
user_data=None, availability_zone=None, kernel_id=None,
- ramdisk_id=None):
+ ramdisk_id=None, subnet_id=None, security_group_ids=None):
"""Run new instances.
TODO: blockDeviceMapping, monitoring, subnetId
@@ -57,9 +57,21 @@
"MaxCount": str(max_count)}
if key_name is not None:
params["KeyName"] = key_name
- if security_groups is not None:
+ if subnet_id is not None:
+ params["SubnetId"] = subnet_id
+ if security_group_ids is not None:
+ for i, id in enumerate(security_group_ids):
+ params["SecurityGroupId.%d" % (i + 1)] = id
+ else:
+ msg = "You must specify the security_group_ids with the subnet_id"
+ raise ValueError(msg)
+ elif security_groups is not None:
for i, name in enumerate(security_groups):
params["SecurityGroup.%d" % (i + 1)] = name
+ else:
+ msg = ("You must specify either the subnet_id and "
+ "security_group_ids or security_groups")
+ raise ValueError(msg)
if user_data is not None:
params["UserData"] = b64encode(user_data)
if instance_type is not None:
@@ -110,28 +122,37 @@
d = query.submit()
return d.addCallback(self.parser.describe_security_groups)
- def create_security_group(self, name, description):
+ def create_security_group(self, name, description, vpc_id=None):
"""Create security group.
@param name: Name of the new security group.
@param description: Description of the new security group.
+ @param vpc_id: ID of the VPC to which the security group will belong.
@return: A C{Deferred} that will fire with a truth value for the
success of the operation.
"""
parameters = {"GroupName": name, "GroupDescription": description}
+ if vpc_id:
+ parameters["VpcId"] = vpc_id
query = self.query_factory(
action="CreateSecurityGroup", creds=self.creds,
endpoint=self.endpoint, other_params=parameters)
d = query.submit()
- return d.addCallback(self.parser.truth_return)
+ return d.addCallback(self.parser.create_security_group)
- def delete_security_group(self, name):
+ def delete_security_group(self, name=None, id=None):
"""
- @param name: Name of the new security group.
+ @param name: Name of the security group.
+ @param id: Id of the security group.
@return: A C{Deferred} that will fire with a truth value for the
success of the operation.
"""
- parameter = {"GroupName": name}
+ if name:
+ parameter = {"GroupName": name}
+ elif id:
+ parameter = {"GroupId": id}
+ else:
+ raise ValueError("You must provide either the security group name or id")
query = self.query_factory(
action="DeleteSecurityGroup", creds=self.creds,
endpoint=self.endpoint, other_params=parameter)
@@ -139,7 +160,7 @@
return d.addCallback(self.parser.truth_return)
def authorize_security_group(
- self, group_name, source_group_name="", source_group_owner_id="",
+ self, group_name=None, group_id=None, source_group_name="", source_group_owner_id="",
ip_protocol="", from_port="", to_port="", cidr_ip=""):
"""
There are two ways to use C{authorize_security_group}:
@@ -150,6 +171,8 @@
@param group_name: The group you will be modifying with a new
authorization.
+ @param group_id: The id of the group you will be modifying with
+ a new authorization.
Optionally, the following parameters:
@param source_group_name: Name of security group to authorize access to
@@ -188,7 +211,12 @@
msg = ("You must specify either both group parameters or "
"all the ip parameters.")
raise ValueError(msg)
- parameters["GroupName"] = group_name
+ if group_id:
+ parameters["GroupId"] = group_id
+ elif group_name:
+ parameters["GroupName"] = group_name
+ else:
+ raise ValueError("You must specify either the group name of the group id.")
query = self.query_factory(
action="AuthorizeSecurityGroupIngress", creds=self.creds,
endpoint=self.endpoint, other_params=parameters)
@@ -224,7 +252,7 @@
return d
def revoke_security_group(
- self, group_name, source_group_name="", source_group_owner_id="",
+ self, group_name=None, group_id=None, source_group_name="", source_group_owner_id="",
ip_protocol="", from_port="", to_port="", cidr_ip=""):
"""
There are two ways to use C{revoke_security_group}:
@@ -273,7 +301,12 @@
msg = ("You must specify either both group parameters or "
"all the ip parameters.")
raise ValueError(msg)
- parameters["GroupName"] = group_name
+ if group_id:
+ parameters["GroupId"] = group_id
+ elif group_name:
+ parameters["GroupName"] = group_name
+ else:
+ raise ValueError("You must specify either the group name of the group id.")
query = self.query_factory(
action="RevokeSecurityGroupIngress", creds=self.creds,
endpoint=self.endpoint, other_params=parameters)
@@ -547,6 +580,10 @@
ipAddress, stateReason, architecture, rootDeviceName,
blockDeviceMapping, instanceLifecycle, spotInstanceRequestId.
"""
+ for group_data in instance_data.find("groupSet"):
+ group_id = group_data.findtext("groupId")
+ group_name = group_data.findtext("groupName")
+ reservation.groups.append((group_id, group_name))
instance_id = instance_data.findtext("instanceId")
instance_state = instance_data.find(
"instanceState").findtext("name")
@@ -599,16 +636,10 @@
results = []
# May be a more elegant way to do this:
for reservation_data in root.find("reservationSet"):
- # Get the security group information.
- groups = []
- for group_data in reservation_data.find("groupSet"):
- group_id = group_data.findtext("groupId")
- groups.append(group_id)
# Create a reservation object with the parsed data.
reservation = model.Reservation(
reservation_id=reservation_data.findtext("reservationId"),
- owner_id=reservation_data.findtext("ownerId"),
- groups=groups)
+ owner_id=reservation_data.findtext("ownerId"))
# Get the list of instances.
instances = self.instances_set(
reservation_data, reservation)
@@ -670,6 +701,7 @@
root = XML(xml_bytes)
result = []
for group_info in root.findall("securityGroupInfo/item"):
+ id = group_info.findtext("groupId")
name = group_info.findtext("groupName")
description = group_info.findtext("groupDescription")
owner_id = group_info.findtext("ownerId")
@@ -709,11 +741,15 @@
for user_id, group_name in allowed_groups]
security_group = model.SecurityGroup(
- name, description, owner_id=owner_id,
+ id, name, description, owner_id=owner_id,
groups=allowed_groups, ips=allowed_ips)
result.append(security_group)
return result
+ def create_security_group(self, xml_bytes):
+ root = XML(xml_bytes)
+ return root.findtext("groupId")
+
def truth_return(self, xml_bytes):
"""Parse the XML for a truth value.
=== modified file 'txaws/ec2/model.py'
--- txaws/ec2/model.py 2012-03-02 22:00:10 +0000
+++ txaws/ec2/model.py 2012-11-21 12:35:25 +0000
@@ -80,7 +80,8 @@
@ivar allowed_ips: The sequence of L{IPPermission} instances for this
security group.
"""
- def __init__(self, name, description, owner_id="", groups=None, ips=None):
+ def __init__(self, id, name, description, owner_id="", groups=None, ips=None):
+ self.id = id
self.name = name
self.description = description
self.owner_id = owner_id
=== modified file 'txaws/ec2/tests/test_client.py'
--- txaws/ec2/tests/test_client.py 2012-03-02 22:00:10 +0000
+++ txaws/ec2/tests/test_client.py 2012-11-21 12:35:25 +0000
@@ -171,7 +171,8 @@
self.assertEquals(reservation.owner_id, "123456789012")
# check groups
group = reservation.groups[0]
- self.assertEquals(group, "default")
+ self.assertEquals(group[0], "sg-64f9eb08")
+ self.assertEquals(group[1], "default")
# check instance
self.assertEquals(instance.instance_id, "i-abcdef01")
self.assertEquals(instance.instance_state, "running")
@@ -201,7 +202,8 @@
self.assertEquals(reservation.owner_id, "123456789012")
# check groups
group = reservation.groups[0]
- self.assertEquals(group, "default")
+ self.assertEquals(group[0], "sg-64f9eb08")
+ self.assertEquals(group[1], "default")
# check instance
self.assertEquals(instance.instance_id, "i-abcdef01")
self.assertEquals(instance.instance_state, "running")
@@ -331,7 +333,8 @@
self.assertEquals(reservation.owner_id, "495219933132")
# check groups
group = reservation.groups[0]
- self.assertEquals(group, "default")
+ self.assertEquals(group[0], "sg-64f9eb08")
+ self.assertEquals(group[1], "default")
# check instance
self.assertEquals(instance.instance_id, "i-2ba64342")
self.assertEquals(instance.instance_state, "pending")
@@ -377,6 +380,59 @@
ramdisk_id=u"r-1234")
d.addCallback(self.check_parsed_run_instances)
+ def test_run_instances_with_subnet(self):
+ class StubQuery(object):
+ def __init__(stub, action="", creds=None, endpoint=None,
+ other_params={}):
+ self.assertEqual(action, "RunInstances")
+ self.assertEqual(creds.access_key, "foo")
+ self.assertEqual(creds.secret_key, "bar")
+ self.assertEquals(
+ other_params,
+ {"ImageId": "ami-1234", "MaxCount": "2", "MinCount": "1",
+ "SecurityGroupId.1": u"sg-a72d9f92e", "KeyName": u"default",
+ "UserData": "Zm9v", "InstanceType": u"m1.small",
+ "Placement.AvailabilityZone": u"us-east-1b",
+ "KernelId": u"k-1234", "RamdiskId": u"r-1234",
+ "SubnetId": "subnet-a72d829f"})
+
+ def submit(self):
+ return succeed(
+ payload.sample_run_instances_result)
+
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds, query_factory=StubQuery)
+ d = ec2.run_instances("ami-1234", 1, 2, security_group_ids=[u"sg-a72d9f92e"],
+ key_name=u"default", user_data=u"foo", instance_type=u"m1.small",
+ availability_zone=u"us-east-1b", kernel_id=u"k-1234",
+ ramdisk_id=u"r-1234", subnet_id="subnet-a72d829f")
+ d.addCallback(self.check_parsed_run_instances)
+
+ def test_run_instances_with_subnet_but_without_secgroup_id(self):
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds)
+ error = self.assertRaises(ValueError, ec2.run_instances, "ami-1234", 1, 2,
+ key_name=u"default", user_data=u"foo", instance_type=u"m1.small",
+ availability_zone=u"us-east-1b", kernel_id=u"k-1234",
+ ramdisk_id=u"r-1234", subnet_id="subnet-a72d829f")
+ self.assertEqual(
+ str(error),
+ "You must specify the security_group_ids with the subnet_id"
+ )
+
+ def test_run_instances_without_subnet_and_secgroups(self):
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds)
+ error = self.assertRaises(ValueError, ec2.run_instances, "ami-1234", 1, 2,
+ key_name=u"default", user_data=u"foo", instance_type=u"m1.small",
+ availability_zone=u"us-east-1b", kernel_id=u"k-1234",
+ ramdisk_id=u"r-1234")
+ self.assertEqual(
+ str(error),
+ ("You must specify either the subnet_id and "
+ "security_group_ids or security_groups")
+ )
+
class EC2ClientSecurityGroupsTestCase(TXAWSTestCase):
@@ -400,6 +456,7 @@
def check_results(security_groups):
[security_group] = security_groups
+ self.assertEquals(security_group.id, "sg-a1a1a1")
self.assertEquals(security_group.owner_id,
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM")
self.assertEquals(security_group.name, "WebServers")
@@ -440,6 +497,7 @@
security_group = security_groups[0]
self.assertEquals(security_group.owner_id,
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM")
+ self.assertEquals(security_group.id, "sg-a1a1a1")
self.assertEquals(security_group.name, "MessageServers")
self.assertEquals(security_group.description, "Message Servers")
self.assertEquals(security_group.allowed_groups, [])
@@ -451,6 +509,7 @@
security_group = security_groups[1]
self.assertEquals(security_group.owner_id,
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM")
+ self.assertEquals(security_group.id, "sg-c3c3c3")
self.assertEquals(security_group.name, "WebServers")
self.assertEquals(security_group.description, "Web Servers")
self.assertEquals([(pair.user_id, pair.group_name)
@@ -583,14 +642,45 @@
def submit(self):
return succeed(payload.sample_create_security_group)
+ def check_result(id):
+ self.assertEquals(id, "sg-1a2b3c4d")
+
creds = AWSCredentials("foo", "bar")
ec2 = client.EC2Client(creds, query_factory=StubQuery)
d = ec2.create_security_group(
"WebServers",
"The group for the web server farm.")
- return self.assertTrue(d)
-
- def test_delete_security_group(self):
+ return d.addCallback(check_result)
+
+ def test_create_security_group_with_VPC(self):
+ class StubQuery(object):
+
+ def __init__(stub, action="", creds=None, endpoint=None,
+ other_params={}):
+ self.assertEqual(action, "CreateSecurityGroup")
+ self.assertEqual(creds.access_key, "foo")
+ self.assertEqual(creds.secret_key, "bar")
+ self.assertEqual(other_params, {
+ "GroupName": "WebServers",
+ "GroupDescription": "The group for the web server farm.",
+ "VpcId": "vpc-a4f2",
+ })
+
+ def submit(self):
+ return succeed(payload.sample_create_security_group)
+
+ def check_result(id):
+ self.assertEquals(id, "sg-1a2b3c4d")
+
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds, query_factory=StubQuery)
+ d = ec2.create_security_group(
+ "WebServers",
+ "The group for the web server farm.",
+ "vpc-a4f2")
+ return d.addCallback(check_result)
+
+ def test_delete_security_group_using_name(self):
"""
L{EC2Client.delete_security_group} returns a C{Deferred} that
eventually fires with a true value, indicating the success of the
@@ -615,6 +705,40 @@
d = ec2.delete_security_group("WebServers")
return self.assertTrue(d)
+ def test_delete_security_group_using_id(self):
+ """
+ L{EC2Client.delete_security_group} returns a C{Deferred} that
+ eventually fires with a true value, indicating the success of the
+ operation.
+ """
+ class StubQuery(object):
+
+ def __init__(stub, action="", creds=None, endpoint=None,
+ other_params={}):
+ self.assertEqual(action, "DeleteSecurityGroup")
+ self.assertEqual(creds.access_key, "foo")
+ self.assertEqual(creds.secret_key, "bar")
+ self.assertEqual(other_params, {
+ "GroupId": "sg-a1a1a1",
+ })
+
+ def submit(self):
+ return succeed(payload.sample_delete_security_group)
+
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds, query_factory=StubQuery)
+ d = ec2.delete_security_group(id="sg-a1a1a1")
+ return self.assertTrue(d)
+
+ def test_delete_security_group_without_id_and_name(self):
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds)
+ error = self.assertRaises(ValueError, ec2.delete_security_group)
+ self.assertEquals(
+ str(error),
+ "You must provide either the security group name or id",
+ )
+
def test_delete_security_group_failure(self):
"""
L{EC2Client.delete_security_group} returns a C{Deferred} that
@@ -676,9 +800,42 @@
creds = AWSCredentials("foo", "bar")
ec2 = client.EC2Client(creds, query_factory=StubQuery)
d = ec2.authorize_security_group(
- "WebServers", source_group_name="AppServers",
- source_group_owner_id="123456789123")
- return self.assertTrue(d)
+ group_name="WebServers", source_group_name="AppServers",
+ source_group_owner_id="123456789123")
+ return self.assertTrue(d)
+
+ def test_authorize_security_group_using_group_id(self):
+ class StubQuery(object):
+
+ def __init__(stub, action="", creds=None, endpoint=None,
+ other_params={}):
+ self.assertEqual(action, "AuthorizeSecurityGroupIngress")
+ self.assertEqual(creds.access_key, "foo")
+ self.assertEqual(creds.secret_key, "bar")
+ self.assertEqual(other_params, {
+ "GroupId": "sg-a1b2c3d4e5f6",
+ "SourceSecurityGroupName": "AppServers",
+ "SourceSecurityGroupOwnerId": "123456789123",
+ })
+
+ def submit(self):
+ return succeed(payload.sample_authorize_security_group)
+
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds, query_factory=StubQuery)
+ d = ec2.authorize_security_group(
+ group_id="sg-a1b2c3d4e5f6", source_group_name="AppServers",
+ source_group_owner_id="123456789123")
+ return self.assertTrue(d)
+
+ def test_authorize_security_group_without_group_id_and_group_name(self):
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds)
+ error = self.assertRaises(ValueError, ec2.authorize_security_group,
+ source_group_name="AppServers", source_group_owner_id="123456789123")
+ self.assertEquals(
+ str(error),
+ "You must specify either the group name of the group id.")
def test_authorize_security_group_with_ip_permissions(self):
"""
@@ -707,7 +864,7 @@
creds = AWSCredentials("foo", "bar")
ec2 = client.EC2Client(creds, query_factory=StubQuery)
d = ec2.authorize_security_group(
- "WebServers", ip_protocol="tcp", from_port="22", to_port="80",
+ group_name="WebServers", ip_protocol="tcp", from_port="22", to_port="80",
cidr_ip="0.0.0.0/0")
return self.assertTrue(d)
@@ -722,16 +879,12 @@
"""
creds = AWSCredentials("foo", "bar")
ec2 = client.EC2Client(creds)
- self.assertRaises(ValueError, ec2.authorize_security_group,
- "WebServers", ip_protocol="tcp", from_port="22")
- try:
- ec2.authorize_security_group(
- "WebServers", ip_protocol="tcp", from_port="22")
- except Exception, error:
- self.assertEquals(
- str(error),
- ("You must specify either both group parameters or all the "
- "ip parameters."))
+ error = self.assertRaises(ValueError, ec2.authorize_security_group,
+ group_name="WebServers", ip_protocol="tcp", from_port="22")
+ self.assertEquals(
+ str(error),
+ ("You must specify either both group parameters or all the "
+ "ip parameters."))
def test_authorize_group_permission(self):
"""
@@ -822,6 +975,30 @@
source_group_owner_id="123456789123")
return self.assertTrue(d)
+ def test_revoke_security_group_using_group_id(self):
+ class StubQuery(object):
+
+ def __init__(stub, action="", creds=None, endpoint=None,
+ other_params={}):
+ self.assertEqual(action, "RevokeSecurityGroupIngress")
+ self.assertEqual(creds.access_key, "foo")
+ self.assertEqual(creds.secret_key, "bar")
+ self.assertEqual(other_params, {
+ "GroupId": "sg-a1a1a1",
+ "SourceSecurityGroupName": "AppServers",
+ "SourceSecurityGroupOwnerId": "123456789123",
+ })
+
+ def submit(self):
+ return succeed(payload.sample_revoke_security_group)
+
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds, query_factory=StubQuery)
+ d = ec2.revoke_security_group(
+ group_id="sg-a1a1a1", source_group_name="AppServers",
+ source_group_owner_id="123456789123")
+ return self.assertTrue(d)
+
def test_revoke_security_group_with_ip_permissions(self):
"""
L{EC2Client.revoke_security_group} returns a C{Deferred} that
@@ -853,6 +1030,15 @@
cidr_ip="0.0.0.0/0")
return self.assertTrue(d)
+ def test_revoke_security_group_without_group_id_and_group_name(self):
+ creds = AWSCredentials("foo", "bar")
+ ec2 = client.EC2Client(creds)
+ error = self.assertRaises(ValueError, ec2.revoke_security_group,
+ source_group_name="AppServers", source_group_owner_id="123456789123")
+ self.assertEquals(
+ str(error),
+ "You must specify either the group name of the group id.")
+
def test_revoke_security_group_with_missing_parameters(self):
"""
L{EC2Client.revoke_security_group} returns a C{Deferred} that
@@ -864,16 +1050,12 @@
"""
creds = AWSCredentials("foo", "bar")
ec2 = client.EC2Client(creds)
- self.assertRaises(ValueError, ec2.authorize_security_group,
- "WebServers", ip_protocol="tcp", from_port="22")
- try:
- ec2.authorize_security_group(
- "WebServers", ip_protocol="tcp", from_port="22")
- except Exception, error:
- self.assertEquals(
- str(error),
- ("You must specify either both group parameters or all the "
- "ip parameters."))
+ error = self.assertRaises(ValueError, ec2.revoke_security_group,
+ group_name="WebServers", ip_protocol="tcp", from_port="22")
+ self.assertEquals(
+ str(error),
+ ("You must specify either both group parameters or all the "
+ "ip parameters."))
def test_revoke_group_permission(self):
"""
@@ -1561,7 +1743,7 @@
{"AWSAccessKeyId": "foo",
"Action": "DescribeInstances",
"SignatureVersion": "2",
- "Version": "2009-11-30"})
+ "Version": "2012-08-15"})
def test_init_other_args_are_params(self):
query = client.Query(
@@ -1575,7 +1757,7 @@
"InstanceId.0": "12345",
"SignatureVersion": "2",
"Timestamp": "2007-11-12T13:14:15Z",
- "Version": "2009-11-30"})
+ "Version": "2012-08-15"})
def test_no_timestamp_if_expires_in_other_params(self):
"""
@@ -1593,7 +1775,7 @@
"Action": "DescribeInstances",
"SignatureVersion": "2",
"Expires": "2007-11-12T13:14:15Z",
- "Version": "2009-11-30"})
+ "Version": "2012-08-15"})
def test_sign(self):
query = client.Query(
@@ -1601,7 +1783,7 @@
endpoint=self.endpoint,
time_tuple=(2007, 11, 12, 13, 14, 15, 0, 0, 0))
query.sign()
- self.assertEqual("G4c2NtQaFNhWWT8EWPVIIOpHVr0mGUYwJVYss9krsMU=",
+ self.assertEqual("c0gbkemrGEJdqxWOl2UZYaygYiBLVjrpWBs7bTN7Ndo=",
query.params["Signature"])
def test_old_sign(self):
@@ -1612,7 +1794,7 @@
other_params={"SignatureVersion": "1"})
query.sign()
self.assertEqual(
- "9xP+PIs/3QXW+4mWX6WGR4nGqfE=", query.params["Signature"])
+ "7tWrIC5VYvXOjVE+roVoyDUt2Yw=", query.params["Signature"])
def test_unsupported_sign(self):
query = client.Query(
=== modified file 'txaws/ec2/tests/test_model.py'
--- txaws/ec2/tests/test_model.py 2012-01-23 01:04:25 +0000
+++ txaws/ec2/tests/test_model.py 2012-11-21 12:35:25 +0000
@@ -8,7 +8,8 @@
class SecurityGroupTestCase(TXAWSTestCase):
def test_creation_defaults(self):
- group = model.SecurityGroup("name", "desc")
+ group = model.SecurityGroup("sg-a3f2", "name", "desc")
+ self.assertEquals(group.id, "sg-a3f2")
self.assertEquals(group.name, "name")
self.assertEquals(group.description, "desc")
self.assertEquals(group.owner_id, "")
@@ -18,14 +19,15 @@
def test_creation_all_parameters(self):
user = "somegal24"
other_groups = [
- model.SecurityGroup("other1", "another group 1"),
- model.SecurityGroup("other2", "another group 2")]
+ model.SecurityGroup("sg-other1", "other1", "another group 1"),
+ model.SecurityGroup("sg-other2", "other2", "another group 2")]
user_group_pairs = [
model.UserIDGroupPair(user, other_groups[0].name),
model.UserIDGroupPair(user, other_groups[1].name)]
ips = [model.IPPermission("tcp", "80", "80", "10.0.1.0/24")]
group = model.SecurityGroup(
- "name", "desc", owner_id="me", groups=user_group_pairs, ips=ips)
+ "id", "name", "desc", owner_id="me", groups=user_group_pairs, ips=ips)
+ self.assertEquals(group.id, "id")
self.assertEquals(group.name, "name")
self.assertEquals(group.description, "desc")
self.assertEquals(group.owner_id, "me")
=== modified file 'txaws/server/tests/test_call.py'
--- txaws/server/tests/test_call.py 2012-01-27 02:10:24 +0000
+++ txaws/server/tests/test_call.py 2012-11-21 12:35:25 +0000
@@ -11,4 +11,4 @@
2009-11-30, which is the earliest version we support.
"""
call = Call()
- self.assertEqual(call.version, "2009-11-30")
+ self.assertEqual(call.version, "2012-08-15")
=== modified file 'txaws/testing/payload.py'
--- txaws/testing/payload.py 2012-05-16 02:47:12 +0000
+++ txaws/testing/payload.py 2012-11-21 12:35:25 +0000
@@ -9,11 +9,7 @@
<item>
<reservationId>r-cf24b1a6</reservationId>
<ownerId>123456789012</ownerId>
- <groupSet>
- <item>
- <groupId>default</groupId>
- </item>
- </groupSet>
+ <groupSet/>
<instancesSet>
<item>
<instanceId>i-abcdef01</instanceId>
@@ -22,6 +18,12 @@
<code>16</code>
<name>running</name>
</instanceState>
+ <groupSet>
+ <item>
+ <groupId>sg-64f9eb08</groupId>
+ <groupName>default</groupName>
+ </item>
+ </groupSet>
<privateDnsName>domU-12-31-39-03-15-11.compute-1.internal\
</privateDnsName>
<dnsName>ec2-75-101-245-65.compute-1.amazonaws.com</dnsName>
@@ -48,11 +50,7 @@
<item>
<reservationId>r-cf24b1a6</reservationId>
<ownerId>123456789012</ownerId>
- <groupSet>
- <item>
- <groupId>default</groupId>
- </item>
- </groupSet>
+ <groupSet/>
<instancesSet>
<item>
<instanceId>i-abcdef01</instanceId>
@@ -67,6 +65,12 @@
<privateIpAddress>10.0.0.1</privateIpAddress>
<ipAddress>75.101.245.65</ipAddress>
<reason/>
+ <groupSet>
+ <item>
+ <groupId>sg-64f9eb08</groupId>
+ <groupName>default</groupName>
+ </item>
+ </groupSet>
<keyName>keyname</keyName>
<amiLaunchIndex>0</amiLaunchIndex>
<productCodes>
@@ -92,18 +96,14 @@
<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/%s/">
<reservationId>r-47a5402e</reservationId>
<ownerId>495219933132</ownerId>
- <groupSet>
- <item>
- <groupId>default</groupId>
- </item>
- </groupSet>
+ <groupSet/>
<instancesSet>
<item>
<instanceId>i-2ba64342</instanceId>
<imageId>ami-60a54009</imageId>
<instanceState>
<code>0</code>
- <name>pending</name>
+ <name>pending</name>
</instanceState>
<privateDnsName></privateDnsName>
<dnsName></dnsName>
@@ -111,6 +111,12 @@
<amiLaunchIndex>0</amiLaunchIndex>
<instanceType>m1.small</instanceType>
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
+ <groupSet>
+ <item>
+ <groupId>sg-64f9eb08</groupId>
+ <groupName>default</groupName>
+ </item>
+ </groupSet>
<placement>
<availabilityZone>us-east-1b</availabilityZone>
</placement>
@@ -120,7 +126,7 @@
<imageId>ami-60a54009</imageId>
<instanceState>
<code>0</code>
- <name>pending</name>
+ <name>pending</name>
</instanceState>
<privateDnsName></privateDnsName>
<dnsName></dnsName>
@@ -128,6 +134,12 @@
<amiLaunchIndex>1</amiLaunchIndex>
<instanceType>m1.small</instanceType>
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
+ <groupSet>
+ <item>
+ <groupId>sg-64f9eb08</groupId>
+ <groupName>default</groupName>
+ </item>
+ </groupSet>
<placement>
<availabilityZone>us-east-1b</availabilityZone>
</placement>
@@ -145,6 +157,12 @@
<amiLaunchIndex>2</amiLaunchIndex>
<instanceType>m1.small</instanceType>
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
+ <groupSet>
+ <item>
+ <groupId>sg-64f9eb08</groupId>
+ <groupName>default</groupName>
+ </item>
+ </groupSet>
<placement>
<availabilityZone>us-east-1b</availabilityZone>
</placement>
@@ -213,6 +231,7 @@
<fromPort/>
</item>
</ipPermissions>
+ <groupId>sg-a1a1a1</groupId>
<groupName>WebServers</groupName>
<groupDescription>Web servers</groupDescription>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
@@ -228,6 +247,7 @@
<securityGroupInfo>
<item>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
+ <groupId>sg-a1a1a1</groupId>
<groupName>WebServers</groupName>
<groupDescription>Web Servers</groupDescription>
<ipPermissions>
@@ -256,6 +276,7 @@
<securityGroupInfo>
<item>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
+ <groupId>sg-a1a1a1</groupId>
<groupName>MessageServers</groupName>
<groupDescription>Message Servers</groupDescription>
<ipPermissions>
@@ -274,6 +295,7 @@
</item>
<item>
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
+ <groupId>sg-c3c3c3</groupId>
<groupName>WebServers</groupName>
<groupDescription>Web Servers</groupDescription>
<ipPermissions>
@@ -457,6 +479,7 @@
sample_create_security_group = """\
<CreateSecurityGroupResponse xmlns="http://ec2.amazonaws.com/doc/%s/">
<return>true</return>
+ <groupId>sg-1a2b3c4d</groupId>
</CreateSecurityGroupResponse>
""" % (version.ec2_api,)
=== modified file 'txaws/version.py'
--- txaws/version.py 2012-01-24 23:18:36 +0000
+++ txaws/version.py 2012-11-21 12:35:25 +0000
@@ -1,3 +1,3 @@
txaws = "0.2.3"
-ec2_api = "2009-11-30"
+ec2_api = "2012-08-15"
s3_api = "2006-03-01"
Follow ups