Merge pull request #2825 from bblommers/feature/2699
EC2 - Add option to add volumes using CloudFormation
This commit is contained in:
commit
9c3f6c7592
@ -557,6 +557,10 @@ class Instance(TaggedEC2Resource, BotoInstance):
|
|||||||
# worst case we'll get IP address exaustion... rarely
|
# worst case we'll get IP address exaustion... rarely
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_block_device(self, size, device_path):
|
||||||
|
volume = self.ec2_backend.create_volume(size, self.region_name)
|
||||||
|
self.ec2_backend.attach_volume(volume.id, self.id, device_path)
|
||||||
|
|
||||||
def setup_defaults(self):
|
def setup_defaults(self):
|
||||||
# Default have an instance with root volume should you not wish to
|
# Default have an instance with root volume should you not wish to
|
||||||
# override with attach volume cmd.
|
# override with attach volume cmd.
|
||||||
@ -564,6 +568,7 @@ class Instance(TaggedEC2Resource, BotoInstance):
|
|||||||
self.ec2_backend.attach_volume(volume.id, self.id, "/dev/sda1")
|
self.ec2_backend.attach_volume(volume.id, self.id, "/dev/sda1")
|
||||||
|
|
||||||
def teardown_defaults(self):
|
def teardown_defaults(self):
|
||||||
|
if "/dev/sda1" in self.block_device_mapping:
|
||||||
volume_id = self.block_device_mapping["/dev/sda1"].volume_id
|
volume_id = self.block_device_mapping["/dev/sda1"].volume_id
|
||||||
self.ec2_backend.detach_volume(volume_id, self.id, "/dev/sda1")
|
self.ec2_backend.detach_volume(volume_id, self.id, "/dev/sda1")
|
||||||
self.ec2_backend.delete_volume(volume_id)
|
self.ec2_backend.delete_volume(volume_id)
|
||||||
@ -621,6 +626,7 @@ class Instance(TaggedEC2Resource, BotoInstance):
|
|||||||
subnet_id=properties.get("SubnetId"),
|
subnet_id=properties.get("SubnetId"),
|
||||||
key_name=properties.get("KeyName"),
|
key_name=properties.get("KeyName"),
|
||||||
private_ip=properties.get("PrivateIpAddress"),
|
private_ip=properties.get("PrivateIpAddress"),
|
||||||
|
block_device_mappings=properties.get("BlockDeviceMappings", {}),
|
||||||
)
|
)
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
for tag in properties.get("Tags", []):
|
for tag in properties.get("Tags", []):
|
||||||
@ -880,7 +886,14 @@ class InstanceBackend(object):
|
|||||||
)
|
)
|
||||||
new_reservation.instances.append(new_instance)
|
new_reservation.instances.append(new_instance)
|
||||||
new_instance.add_tags(instance_tags)
|
new_instance.add_tags(instance_tags)
|
||||||
|
if "block_device_mappings" in kwargs:
|
||||||
|
for block_device in kwargs["block_device_mappings"]:
|
||||||
|
new_instance.add_block_device(
|
||||||
|
block_device["Ebs"]["VolumeSize"], block_device["DeviceName"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
new_instance.setup_defaults()
|
new_instance.setup_defaults()
|
||||||
|
|
||||||
return new_reservation
|
return new_reservation
|
||||||
|
|
||||||
def start_instances(self, instance_ids):
|
def start_instances(self, instance_ids):
|
||||||
|
@ -9,6 +9,7 @@ from nose.tools import assert_raises
|
|||||||
import base64
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
import json
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import boto
|
import boto
|
||||||
@ -18,7 +19,7 @@ from boto.exception import EC2ResponseError, EC2ResponseError
|
|||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from moto import mock_ec2_deprecated, mock_ec2
|
from moto import mock_ec2_deprecated, mock_ec2, mock_cloudformation
|
||||||
from tests.helpers import requires_boto_gte
|
from tests.helpers import requires_boto_gte
|
||||||
|
|
||||||
|
|
||||||
@ -1414,3 +1415,40 @@ def test_describe_instance_attribute():
|
|||||||
invalid_instance_attribute=invalid_instance_attribute
|
invalid_instance_attribute=invalid_instance_attribute
|
||||||
)
|
)
|
||||||
ex.exception.response["Error"]["Message"].should.equal(message)
|
ex.exception.response["Error"]["Message"].should.equal(message)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
@mock_cloudformation
|
||||||
|
def test_volume_size_through_cloudformation():
|
||||||
|
ec2 = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
cf = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
|
||||||
|
volume_template = {
|
||||||
|
"AWSTemplateFormatVersion": "2010-09-09",
|
||||||
|
"Resources": {
|
||||||
|
"testInstance": {
|
||||||
|
"Type": "AWS::EC2::Instance",
|
||||||
|
"Properties": {
|
||||||
|
"ImageId": "ami-d3adb33f",
|
||||||
|
"KeyName": "dummy",
|
||||||
|
"InstanceType": "t2.micro",
|
||||||
|
"BlockDeviceMappings": [
|
||||||
|
{"DeviceName": "/dev/sda2", "Ebs": {"VolumeSize": "50"}}
|
||||||
|
],
|
||||||
|
"Tags": [
|
||||||
|
{"Key": "foo", "Value": "bar"},
|
||||||
|
{"Key": "blah", "Value": "baz"},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
template_json = json.dumps(volume_template)
|
||||||
|
cf.create_stack(StackName="test_stack", TemplateBody=template_json)
|
||||||
|
instances = ec2.describe_instances()
|
||||||
|
volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][
|
||||||
|
"Ebs"
|
||||||
|
]
|
||||||
|
|
||||||
|
volumes = ec2.describe_volumes(VolumeIds=[volume["VolumeId"]])
|
||||||
|
volumes["Volumes"][0]["Size"].should.equal(50)
|
||||||
|
Loading…
Reference in New Issue
Block a user