diff options
author | Daniel Lindsley <daniel@toastdriven.com> | 2013-09-13 15:37:29 -0700 |
---|---|---|
committer | Daniel Lindsley <daniel@toastdriven.com> | 2013-09-13 15:37:29 -0700 |
commit | d7edafccda9fb1c1169e4b0a22a0afbaf853dcc3 (patch) | |
tree | 1557b3976a470f58a0e86f91f463d6d4601f75d1 | |
parent | 9049f05190134296d2aa11206a5900c358c3dd7f (diff) | |
download | boto-d7edafccda9fb1c1169e4b0a22a0afbaf853dcc3.tar.gz |
Fixes #1723 - A prior commit broke ``run_instances`` with block device mappings on EC2. This makes both EC2 & Autoscaling work with block device mappings.
-rw-r--r-- | boto/ec2/autoscale/__init__.py | 2 | ||||
-rw-r--r-- | boto/ec2/blockdevicemapping.py | 12 | ||||
-rw-r--r-- | boto/ec2/connection.py | 6 | ||||
-rw-r--r-- | tests/unit/ec2/test_blockdevicemapping.py | 54 |
4 files changed, 68 insertions, 6 deletions
diff --git a/boto/ec2/autoscale/__init__.py b/boto/ec2/autoscale/__init__.py index f82ce9ec..9a8270db 100644 --- a/boto/ec2/autoscale/__init__.py +++ b/boto/ec2/autoscale/__init__.py @@ -225,7 +225,7 @@ class AutoScaleConnection(AWSQueryConnection): if launch_config.ramdisk_id: params['RamdiskId'] = launch_config.ramdisk_id if launch_config.block_device_mappings: - [x.build_list_params(params) for x in launch_config.block_device_mappings] + [x.autoscale_build_list_params(params) for x in launch_config.block_device_mappings] if launch_config.security_groups: self.build_list_params(params, launch_config.security_groups, 'SecurityGroups') diff --git a/boto/ec2/blockdevicemapping.py b/boto/ec2/blockdevicemapping.py index df774ae9..78f7e61d 100644 --- a/boto/ec2/blockdevicemapping.py +++ b/boto/ec2/blockdevicemapping.py @@ -115,10 +115,18 @@ class BlockDeviceMapping(dict): elif name == 'item': self[self.current_name] = self.current_value - def build_list_params(self, params, prefix=''): + def ec2_build_list_params(self, params, prefix=''): + pre = '%sBlockDeviceMapping' % prefix + return self._build_list_params(params, prefix=pre) + + def autoscale_build_list_params(self, params, prefix=''): + pre = '%sBlockDeviceMappings.member' % prefix + return self._build_list_params(params, prefix=pre) + + def _build_list_params(self, params, prefix=''): i = 1 for dev_name in self: - pre = '%sBlockDeviceMapping.%d' % (prefix, i) + pre = '%s.%d' % (prefix, i) params['%s.DeviceName' % pre] = dev_name block_dev = self[dev_name] if block_dev.ephemeral_name: diff --git a/boto/ec2/connection.py b/boto/ec2/connection.py index be0286df..71da5f0b 100644 --- a/boto/ec2/connection.py +++ b/boto/ec2/connection.py @@ -312,7 +312,7 @@ class EC2Connection(AWSQueryConnection): if root_device_name: params['RootDeviceName'] = root_device_name if block_device_map: - block_device_map.build_list_params(params) + block_device_map.ec2_build_list_params(params) if dry_run: params['DryRun'] = 'true' rs = self.get_object('RegisterImage', params, ResultSet, verb='POST') @@ -843,7 +843,7 @@ class EC2Connection(AWSQueryConnection): if private_ip_address: params['PrivateIpAddress'] = private_ip_address if block_device_map: - block_device_map.build_list_params(params) + block_device_map.ec2_build_list_params(params) if disable_api_termination: params['DisableApiTermination'] = 'true' if instance_initiated_shutdown_behavior: @@ -1466,7 +1466,7 @@ class EC2Connection(AWSQueryConnection): if placement_group: params['%s.Placement.GroupName' % ls] = placement_group if block_device_map: - block_device_map.build_list_params(params, '%s.' % ls) + block_device_map.ec2_build_list_params(params, '%s.' % ls) if instance_profile_name: params['%s.IamInstanceProfile.Name' % ls] = instance_profile_name if instance_profile_arn: diff --git a/tests/unit/ec2/test_blockdevicemapping.py b/tests/unit/ec2/test_blockdevicemapping.py index 02ecf582..78539744 100644 --- a/tests/unit/ec2/test_blockdevicemapping.py +++ b/tests/unit/ec2/test_blockdevicemapping.py @@ -1,8 +1,12 @@ import mock import unittest +from boto.ec2.connection import EC2Connection from boto.ec2.blockdevicemapping import BlockDeviceType, BlockDeviceMapping +from tests.unit import AWSMockServiceTestCase + + class BlockDeviceTypeTests(unittest.TestCase): def setUp(self): self.block_device_type = BlockDeviceType() @@ -75,5 +79,55 @@ class BlockDeviceMappingTests(unittest.TestCase): self.block_device_mapping.endElement("item", "some item", None) self.assertEqual(self.block_device_mapping["some name"], "some value") + +class TestLaunchConfiguration(AWSMockServiceTestCase): + connection_class = EC2Connection + + def default_body(self): + # This is a dummy response + return """ + <DescribeLaunchConfigurationsResponse> + </DescribeLaunchConfigurationsResponse> + """ + + def test_run_instances_block_device_mapping(self): + # Same as the test in ``unit/ec2/autoscale/test_group.py:TestLaunchConfiguration``, + # but with modified request parameters (due to a mismatch between EC2 & + # Autoscaling). + self.set_http_response(status_code=200) + dev_sdf = BlockDeviceType(snapshot_id='snap-12345') + dev_sdg = BlockDeviceType(snapshot_id='snap-12346') + + bdm = BlockDeviceMapping() + bdm['/dev/sdf'] = dev_sdf + bdm['/dev/sdg'] = dev_sdg + + response = self.service_connection.run_instances( + image_id='123456', + instance_type='m1.large', + security_groups=['group1', 'group2'], + block_device_map=bdm + ) + + self.assert_request_parameters({ + 'Action': 'RunInstances', + 'BlockDeviceMapping.1.DeviceName': '/dev/sdf', + 'BlockDeviceMapping.1.Ebs.DeleteOnTermination': 'false', + 'BlockDeviceMapping.1.Ebs.SnapshotId': 'snap-12345', + 'BlockDeviceMapping.2.DeviceName': '/dev/sdg', + 'BlockDeviceMapping.2.Ebs.DeleteOnTermination': 'false', + 'BlockDeviceMapping.2.Ebs.SnapshotId': 'snap-12346', + 'ImageId': '123456', + 'InstanceType': 'm1.large', + 'MaxCount': 1, + 'MinCount': 1, + 'SecurityGroup.1': 'group1', + 'SecurityGroup.2': 'group2', + }, ignore_params_values=[ + 'Version', 'AWSAccessKeyId', 'SignatureMethod', 'SignatureVersion', + 'Timestamp' + ]) + + if __name__ == "__main__": unittest.main() |