Merge pull request #658 from kierandoonan/master

Add encrypted attribute to Volumes/Snapshots
This commit is contained in:
Steve Pulec 2016-07-09 21:11:52 -04:00 committed by GitHub
commit 3e797d9c50
3 changed files with 81 additions and 12 deletions

View File

@ -1536,7 +1536,7 @@ class VolumeAttachment(object):
class Volume(TaggedEC2Resource):
def __init__(self, ec2_backend, volume_id, size, zone, snapshot_id=None):
def __init__(self, ec2_backend, volume_id, size, zone, snapshot_id=None, encrypted=False):
self.id = volume_id
self.size = size
self.zone = zone
@ -1544,6 +1544,7 @@ class Volume(TaggedEC2Resource):
self.attachment = None
self.snapshot_id = snapshot_id
self.ec2_backend = ec2_backend
self.encrypted = encrypted
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
@ -1593,6 +1594,9 @@ class Volume(TaggedEC2Resource):
if filter_name == 'volume-id':
return self.id
if filter_name == 'encrypted':
return str(self.encrypted).lower()
filter_value = super(Volume, self).get_filter_value(filter_name)
if filter_value is None:
@ -1602,7 +1606,7 @@ class Volume(TaggedEC2Resource):
class Snapshot(TaggedEC2Resource):
def __init__(self, ec2_backend, snapshot_id, volume, description):
def __init__(self, ec2_backend, snapshot_id, volume, description, encrypted=False):
self.id = snapshot_id
self.volume = volume
self.description = description
@ -1610,6 +1614,7 @@ class Snapshot(TaggedEC2Resource):
self.create_volume_permission_groups = set()
self.ec2_backend = ec2_backend
self.status = 'completed'
self.encrypted = encrypted
def get_filter_value(self, filter_name):
@ -1628,6 +1633,9 @@ class Snapshot(TaggedEC2Resource):
if filter_name == 'volume-size':
return self.volume.size
if filter_name == 'encrypted':
return str(self.encrypted).lower()
filter_value = super(Snapshot, self).get_filter_value(filter_name)
if filter_value is None:
@ -1643,14 +1651,16 @@ class EBSBackend(object):
self.snapshots = {}
super(EBSBackend, self).__init__()
def create_volume(self, size, zone_name, snapshot_id=None):
def create_volume(self, size, zone_name, snapshot_id=None, encrypted=False):
volume_id = random_volume_id()
zone = self.get_zone_by_name(zone_name)
if snapshot_id:
snapshot = self.get_snapshot(snapshot_id)
if size is None:
size = snapshot.volume.size
volume = Volume(self, volume_id, size, zone, snapshot_id)
if snapshot.encrypted:
encrypted = snapshot.encrypted
volume = Volume(self, volume_id, size, zone, snapshot_id, encrypted)
self.volumes[volume_id] = volume
return volume
@ -1699,7 +1709,7 @@ class EBSBackend(object):
def create_snapshot(self, volume_id, description):
snapshot_id = random_snapshot_id()
volume = self.get_volume(volume_id)
snapshot = Snapshot(self, snapshot_id, volume, description)
snapshot = Snapshot(self, snapshot_id, volume, description, volume.encrypted)
self.snapshots[snapshot_id] = snapshot
return snapshot

View File

@ -29,7 +29,8 @@ class ElasticBlockStore(BaseResponse):
size = self._get_param('Size')
zone = self._get_param('AvailabilityZone')
snapshot_id = self._get_param('SnapshotId')
volume = self.ec2_backend.create_volume(size, zone, snapshot_id)
encrypted = self._get_param('Encrypted') or 'false'
volume = self.ec2_backend.create_volume(size, zone, snapshot_id, encrypted)
template = self.response_template(CREATE_VOLUME_RESPONSE)
return template.render(volume=volume)
@ -117,6 +118,7 @@ CREATE_VOLUME_RESPONSE = """<CreateVolumeResponse xmlns="http://ec2.amazonaws.co
{% else %}
<snapshotId/>
{% endif %}
<encrypted>{{ volume.encrypted }}</encrypted>
<availabilityZone>{{ volume.zone.name }}</availabilityZone>
<status>creating</status>
<createTime>{{ volume.create_time}}</createTime>
@ -135,6 +137,7 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
{% else %}
<snapshotId/>
{% endif %}
<encrypted>{{ volume.encrypted }}</encrypted>
<availabilityZone>{{ volume.zone.name }}</availabilityZone>
<status>{{ volume.status }}</status>
<createTime>{{ volume.create_time}}</createTime>
@ -199,6 +202,7 @@ CREATE_SNAPSHOT_RESPONSE = """<CreateSnapshotResponse xmlns="http://ec2.amazonaw
<ownerId>111122223333</ownerId>
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
<description>{{ snapshot.description }}</description>
<encrypted>{{ snapshot.encrypted }}</encrypted>
</CreateSnapshotResponse>"""
DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
@ -214,6 +218,7 @@ DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.am
<ownerId>111122223333</ownerId>
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
<description>{{ snapshot.description }}</description>
<encrypted>{{ snapshot.encrypted }}</encrypted>
<tagSet>
{% for tag in snapshot.get_tags() %}
<item>

View File

@ -20,6 +20,7 @@ def test_create_and_delete_volume():
all_volumes.should.have.length_of(1)
all_volumes[0].size.should.equal(80)
all_volumes[0].zone.should.equal("us-east-1a")
all_volumes[0].encrypted.should.be(False)
volume = all_volumes[0]
volume.delete()
@ -34,6 +35,15 @@ def test_create_and_delete_volume():
cm.exception.request_id.should_not.be.none
@mock_ec2
def test_create_encrypted_volume():
conn = boto.connect_ec2('the_key', 'the_secret')
conn.create_volume(80, "us-east-1a", encrypted=True)
all_volumes = conn.get_all_volumes()
all_volumes[0].encrypted.should.be(True)
@mock_ec2
def test_filter_volume_by_id():
conn = boto.connect_ec2('the_key', 'the_secret')
@ -57,9 +67,9 @@ def test_volume_filters():
instance.update()
volume1 = conn.create_volume(80, "us-east-1a")
volume2 = conn.create_volume(36, "us-east-1b")
volume3 = conn.create_volume(20, "us-east-1c")
volume1 = conn.create_volume(80, "us-east-1a", encrypted=True)
volume2 = conn.create_volume(36, "us-east-1b", encrypted=False)
volume3 = conn.create_volume(20, "us-east-1c", encrypted=True)
snapshot = volume3.create_snapshot(description='testsnap')
volume4 = conn.create_volume(25, "us-east-1a", snapshot=snapshot)
@ -107,6 +117,16 @@ def test_volume_filters():
volumes_by_tag = conn.get_all_volumes(filters={'tag:testkey1': 'testvalue1'})
set([vol.id for vol in volumes_by_tag]).should.equal(set([volume1.id]))
volumes_by_unencrypted = conn.get_all_volumes(filters={'encrypted': 'false'})
set([vol.id for vol in volumes_by_unencrypted]).should.equal(
set([block_mapping.volume_id, volume2.id])
)
volumes_by_encrypted = conn.get_all_volumes(filters={'encrypted': 'true'})
set([vol.id for vol in volumes_by_encrypted]).should.equal(
set([volume1.id, volume3.id, volume4.id])
)
@mock_ec2
def test_volume_attach_and_detach():
@ -162,6 +182,7 @@ def test_create_snapshot():
snapshots.should.have.length_of(1)
snapshots[0].description.should.equal('a test snapshot')
snapshots[0].start_time.should_not.be.none
snapshots[0].encrypted.should.be(False)
# Create snapshot without description
snapshot = volume.create_snapshot()
@ -178,6 +199,21 @@ def test_create_snapshot():
cm.exception.request_id.should_not.be.none
@mock_ec2
def test_create_encrypted_snapshot():
conn = boto.connect_ec2('the_key', 'the_secret')
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
snapshot = volume.create_snapshot('a test snapshot')
snapshot.update()
snapshot.status.should.equal('completed')
snapshots = conn.get_all_snapshots()
snapshots.should.have.length_of(1)
snapshots[0].description.should.equal('a test snapshot')
snapshots[0].start_time.should_not.be.none
snapshots[0].encrypted.should.be(True)
@mock_ec2
def test_filter_snapshot_by_id():
conn = boto.connect_ec2('the_key', 'the_secret')
@ -202,13 +238,13 @@ def test_filter_snapshot_by_id():
@mock_ec2
def test_snapshot_filters():
conn = boto.connect_ec2('the_key', 'the_secret')
volume1 = conn.create_volume(20, "us-east-1a")
volume2 = conn.create_volume(25, "us-east-1a")
volume1 = conn.create_volume(20, "us-east-1a", encrypted=False)
volume2 = conn.create_volume(25, "us-east-1a", encrypted=True)
snapshot1 = volume1.create_snapshot(description='testsnapshot1')
snapshot2 = volume1.create_snapshot(description='testsnapshot2')
snapshot3 = volume2.create_snapshot(description='testsnapshot3')
conn.create_tags([snapshot1.id], {'testkey1': 'testvalue1'})
conn.create_tags([snapshot2.id], {'testkey2': 'testvalue2'})
@ -236,6 +272,9 @@ def test_snapshot_filters():
snapshots_by_tag = conn.get_all_snapshots(filters={'tag:testkey1': 'testvalue1'})
set([snap.id for snap in snapshots_by_tag]).should.equal(set([snapshot1.id]))
snapshots_by_encrypted = conn.get_all_snapshots(filters={'encrypted': 'true'})
set([snap.id for snap in snapshots_by_encrypted]).should.equal(set([snapshot3.id]))
@mock_ec2
def test_snapshot_attribute():
@ -332,6 +371,21 @@ def test_create_volume_from_snapshot():
new_volume.snapshot_id.should.equal(snapshot.id)
@mock_ec2
def test_create_volume_from_encrypted_snapshot():
conn = boto.connect_ec2('the_key', 'the_secret')
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
snapshot = volume.create_snapshot('a test snapshot')
snapshot.update()
snapshot.status.should.equal('completed')
new_volume = snapshot.create_volume('us-east-1a')
new_volume.size.should.equal(80)
new_volume.snapshot_id.should.equal(snapshot.id)
new_volume.encrypted.should.be(True)
@mock_ec2
def test_modify_attribute_blockDeviceMapping():
"""