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"
_______________________________________________ Mailing list: https://launchpad.net/~txaws-dev Post to : txaws-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~txaws-dev More help : https://help.launchpad.net/ListHelp