Rewrite deprecated EC2 tests (#3881)

This commit is contained in:
Bert Blommers 2021-09-25 11:13:07 +00:00 committed by GitHub
parent 8e93bfc60b
commit 939b800e96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 7076 additions and 286 deletions

View File

@ -268,7 +268,7 @@ CREATE_SNAPSHOT_RESPONSE = """<CreateSnapshotResponse xmlns="http://ec2.amazonaw
<ownerId>{{ snapshot.owner_id }}</ownerId> <ownerId>{{ snapshot.owner_id }}</ownerId>
<volumeSize>{{ snapshot.volume.size }}</volumeSize> <volumeSize>{{ snapshot.volume.size }}</volumeSize>
<description>{{ snapshot.description }}</description> <description>{{ snapshot.description }}</description>
<encrypted>{{ snapshot.encrypted }}</encrypted> <encrypted>{{ 'true' if snapshot.encrypted else 'false' }}</encrypted>
<tagSet> <tagSet>
{% for tag in snapshot.get_tags() %} {% for tag in snapshot.get_tags() %}
<item> <item>
@ -309,7 +309,7 @@ DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.am
<ownerId>{{ snapshot.owner_id }}</ownerId> <ownerId>{{ snapshot.owner_id }}</ownerId>
<volumeSize>{{ snapshot.volume.size }}</volumeSize> <volumeSize>{{ snapshot.volume.size }}</volumeSize>
<description>{{ snapshot.description }}</description> <description>{{ snapshot.description }}</description>
<encrypted>{{ snapshot.encrypted }}</encrypted> <encrypted>{{ 'true' if snapshot.encrypted else 'false' }}</encrypted>
<tagSet> <tagSet>
{% for tag in snapshot.get_tags() %} {% for tag in snapshot.get_tags() %}
<item> <item>

View File

@ -11,3 +11,5 @@ logging.getLogger("botocore").setLevel(logging.CRITICAL)
# (Source: moto/ec2/resources/amis.json) # (Source: moto/ec2/resources/amis.json)
EXAMPLE_AMI_ID = "ami-12c6146b" EXAMPLE_AMI_ID = "ami-12c6146b"
EXAMPLE_AMI_ID2 = "ami-03cf127a" EXAMPLE_AMI_ID2 = "ami-03cf127a"
EXAMPLE_AMI_PARAVIRTUAL = "ami-fa7cdd89"
EXAMPLE_AMI_WINDOWS = "ami-f4cf1d8d"

View File

@ -12,10 +12,11 @@ import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
from moto.ec2.models import AMIS, OWNER_ID from moto.ec2.models import AMIS, OWNER_ID
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_PARAVIRTUAL, EXAMPLE_AMI_WINDOWS
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_create_and_delete(): def test_ami_create_and_delete():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -94,6 +95,97 @@ def test_ami_create_and_delete():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_ami_create_and_delete_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
initial_ami_count = len(AMIS)
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
ec2.describe_snapshots()["Snapshots"].should.have.length_of(initial_ami_count)
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
with pytest.raises(ClientError) as ex:
ec2.create_image(
InstanceId=instance["InstanceId"], Name="test-ami", DryRun=True
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
err = ex.value.response["Error"]
err["Code"].should.equal("DryRunOperation")
err["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set"
)
image_id = ec2.create_image(
InstanceId=instance["InstanceId"],
Name="test-ami",
Description="this is a test ami",
)["ImageId"]
all_images = ec2.describe_images()["Images"]
set([i["ImageId"] for i in all_images]).should.contain(image_id)
retrieved_image = [i for i in all_images if i["ImageId"] == image_id][0]
retrieved_image.should.have.key("ImageId").equal(image_id)
retrieved_image.should.have.key("VirtualizationType").equal(
instance["VirtualizationType"]
)
retrieved_image.should.have.key("Architecture").equal(instance["Architecture"])
retrieved_image.should.have.key("KernelId").equal(instance["KernelId"])
retrieved_image.should.have.key("Platform").equal(instance["Platform"])
retrieved_image.should.have.key("CreationDate")
ec2.terminate_instances(InstanceIds=[instance["InstanceId"]])
# Ensure we're no longer creating a volume
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
# Validate auto-created snapshot
snapshots = ec2.describe_snapshots()["Snapshots"]
snapshots.should.have.length_of(initial_ami_count + 1)
retrieved_image_snapshot_id = retrieved_image["BlockDeviceMappings"][0]["Ebs"][
"SnapshotId"
]
[s["SnapshotId"] for s in snapshots].should.contain(retrieved_image_snapshot_id)
snapshot = [s for s in snapshots if s["SnapshotId"] == retrieved_image_snapshot_id][
0
]
snapshot["Description"].should.equal(
"Auto-created snapshot for AMI {0}".format(retrieved_image["ImageId"])
)
# root device should be in AMI's block device mappings
root_mapping = [
m
for m in retrieved_image["BlockDeviceMappings"]
if m["DeviceName"] == retrieved_image["RootDeviceName"]
]
root_mapping.should_not.equal([])
# Deregister
with pytest.raises(ClientError) as ex:
ec2.deregister_image(ImageId=image_id, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
err = ex.value.response["Error"]
err["Code"].should.equal("DryRunOperation")
err["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set"
)
success = ec2.deregister_image(ImageId=image_id)
success["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
with pytest.raises(ClientError) as ex:
ec2.deregister_image(ImageId=image_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidAMIID.NotFound")
ex.value.response["ResponseMetadata"]["RequestId"].should_not.be.none
# Has boto3 equivalent
@requires_boto_gte("2.14.0") @requires_boto_gte("2.14.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_copy(): def test_ami_copy():
@ -176,6 +268,92 @@ def test_ami_copy():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_ami_copy_boto3():
ec2 = boto3.client("ec2", region_name="us-west-1")
initial_ami_count = len(AMIS)
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
ec2.describe_snapshots()["Snapshots"].should.have.length_of(initial_ami_count)
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
source_image_id = ec2.create_image(
InstanceId=instance["InstanceId"],
Name="test-ami",
Description="this is a test ami",
)["ImageId"]
ec2.terminate_instances(InstanceIds=[instance["InstanceId"]])
source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0]
with pytest.raises(ClientError) as ex:
ec2.copy_image(
SourceRegion="us-west-1",
SourceImageId=source_image["ImageId"],
Name="test-copy-ami",
Description="this is a test copy ami",
DryRun=True,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
err = ex.value.response["Error"]
err["Code"].should.equal("DryRunOperation")
err["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set"
)
copy_image_ref = ec2.copy_image(
SourceRegion="us-west-1",
SourceImageId=source_image["ImageId"],
Name="test-copy-ami",
Description="this is a test copy ami",
)
copy_image_id = copy_image_ref["ImageId"]
copy_image = ec2.describe_images(ImageIds=[copy_image_id])["Images"][0]
copy_image["Name"].should.equal("test-copy-ami")
copy_image["Description"].should.equal("this is a test copy ami")
copy_image["ImageId"].should.equal(copy_image_id)
copy_image["VirtualizationType"].should.equal(source_image["VirtualizationType"])
copy_image["Architecture"].should.equal(source_image["Architecture"])
copy_image["KernelId"].should.equal(source_image["KernelId"])
copy_image["Platform"].should.equal(source_image["Platform"])
# Ensure we're no longer creating a volume
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
# Validate auto-created snapshot
ec2.describe_snapshots()["Snapshots"].should.have.length_of(initial_ami_count + 2)
copy_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"].shouldnt.equal(
source_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"]
)
# Copy from non-existent source ID.
with pytest.raises(ClientError) as ex:
ec2.copy_image(
SourceRegion="us-west-1",
SourceImageId="ami-abcd1234",
Name="test-copy-ami",
Description="this is a test copy ami",
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound")
# Copy from non-existent source region.
with pytest.raises(ClientError) as ex:
ec2.copy_image(
SourceRegion="us-east-1",
SourceImageId=source_image["ImageId"],
Name="test-copy-ami",
Description="this is a test copy ami",
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound")
@mock_ec2 @mock_ec2
def test_copy_image_changes_owner_id(): def test_copy_image_changes_owner_id():
conn = boto3.client("ec2", region_name="us-east-1") conn = boto3.client("ec2", region_name="us-east-1")
@ -200,6 +378,7 @@ def test_copy_image_changes_owner_id():
describe_resp["Images"][0]["ImageId"].should.equal(copy_resp["ImageId"]) describe_resp["Images"][0]["ImageId"].should.equal(copy_resp["ImageId"])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_tagging(): def test_ami_tagging():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -228,6 +407,36 @@ def test_ami_tagging():
image.tags["a key"].should.equal("some value") image.tags["a key"].should.equal("some value")
@mock_ec2
def test_ami_tagging_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
res = boto3.resource("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
image_id = ec2.create_image(
InstanceId=instance["InstanceId"],
Name="test-ami",
Description="this is a test ami",
)["ImageId"]
image = res.Image(image_id)
with pytest.raises(ClientError) as ex:
image.create_tags(Tags=[{"Key": "a key", "Value": "some value"}], DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
err = ex.value.response["Error"]
err["Code"].should.equal("DryRunOperation")
err["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set"
)
image.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
image.tags.should.equal([{"Value": "some value", "Key": "a key"}])
image = ec2.describe_images(ImageIds=[image_id])["Images"][0]
image["Tags"].should.equal([{"Value": "some value", "Key": "a key"}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_create_from_missing_instance(): def test_ami_create_from_missing_instance():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -240,6 +449,20 @@ def test_ami_create_from_missing_instance():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_ami_create_from_missing_instance_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
ec2.create_image(
InstanceId="i-abcdefg", Name="test-ami", Description="this is a test ami"
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidInstanceID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_pulls_attributes_from_instance(): def test_ami_pulls_attributes_from_instance():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -252,6 +475,23 @@ def test_ami_pulls_attributes_from_instance():
image.kernel_id.should.equal("test-kernel") image.kernel_id.should.equal("test-kernel")
@mock_ec2
def test_ami_pulls_attributes_from_instance_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
ec2.modify_instance_attribute(
InstanceId=instance["InstanceId"], Kernel={"Value": "test-kernel"}
)
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami")[
"ImageId"
]
image = boto3.resource("ec2", region_name="us-east-1").Image(image_id)
image.kernel_id.should.equal("test-kernel")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_uses_account_id_if_valid_access_key_is_supplied(): def test_ami_uses_account_id_if_valid_access_key_is_supplied():
access_key = "AKIAXXXXXXXXXXXXXXXX" access_key = "AKIAXXXXXXXXXXXXXXXX"
@ -265,6 +505,29 @@ def test_ami_uses_account_id_if_valid_access_key_is_supplied():
[(ami.id, ami.owner_id) for ami in images].should.equal([(image_id, ACCOUNT_ID)]) [(ami.id, ami.owner_id) for ami in images].should.equal([(image_id, ACCOUNT_ID)])
@mock_ec2
def test_ami_uses_account_id_if_valid_access_key_is_supplied_boto3():
# The boto-equivalent required an access_key to be passed in, but Moto will always mock this in boto3
# So the only thing we're testing here, really.. is whether OwnerId is equal to ACCOUNT_ID?
# TODO: Maybe patch account_id with multiple values, and verify it always matches with OwnerId
# TODO: And probably remove the modify_instance_attribute, as it looks like it was a unnecessary copy-paste
ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
ec2.modify_instance_attribute(
InstanceId=instance["InstanceId"], Kernel={"Value": "test-kernel"}
)
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami")[
"ImageId"
]
images = ec2.describe_images(Owners=["self"])["Images"]
[(ami["ImageId"], ami["OwnerId"]) for ami in images].should.equal(
[(image_id, ACCOUNT_ID)]
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_filters(): def test_ami_filters():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -326,6 +589,87 @@ def test_ami_filters():
len(amis_by_nonpublic).should.equal(1) len(amis_by_nonpublic).should.equal(1)
@mock_ec2
def test_ami_filters_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instanceA = reservationA["Instances"][0]
ec2.modify_instance_attribute(
InstanceId=instanceA["InstanceId"], Kernel={"Value": "k-1234abcd"}
)
imageA_id = ec2.create_image(InstanceId=instanceA["InstanceId"], Name="test-ami-A")[
"ImageId"
]
imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id)
reservationB = ec2.run_instances(
ImageId=EXAMPLE_AMI_PARAVIRTUAL, MinCount=1, MaxCount=1
)
instanceB = reservationB["Instances"][0]
ec2.modify_instance_attribute(
InstanceId=instanceB["InstanceId"], Kernel={"Value": "k-abcd1234"}
)
imageB_id = ec2.create_image(InstanceId=instanceB["InstanceId"], Name="test-ami-B")[
"ImageId"
]
imageB = boto3.resource("ec2", region_name="us-east-1").Image(imageB_id)
imageB.modify_attribute(LaunchPermission={"Add": [{"Group": "all"}]})
amis_by_architecture = ec2.describe_images(
Filters=[{"Name": "architecture", "Values": ["x86_64"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_architecture].should.contain(imageB_id)
amis_by_architecture.should.have.length_of(40)
amis_by_kernel = ec2.describe_images(
Filters=[{"Name": "kernel-id", "Values": ["k-abcd1234"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_kernel].should.equal([imageB.id])
amis_by_virtualization = ec2.describe_images(
Filters=[{"Name": "virtualization-type", "Values": ["paravirtual"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_virtualization].should.contain(imageB.id)
amis_by_virtualization.should.have.length_of(3)
amis_by_platform = ec2.describe_images(
Filters=[{"Name": "platform", "Values": ["windows"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_platform].should.contain(imageA_id)
amis_by_platform.should.have.length_of(25)
amis_by_id = ec2.describe_images(
Filters=[{"Name": "image-id", "Values": [imageA_id]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_id].should.equal([imageA_id])
amis_by_state = ec2.describe_images(
Filters=[{"Name": "state", "Values": ["available"]}]
)["Images"]
ami_ids_by_state = [ami["ImageId"] for ami in amis_by_state]
ami_ids_by_state.should.contain(imageA_id)
ami_ids_by_state.should.contain(imageB.id)
amis_by_state.should.have.length_of(40)
amis_by_name = ec2.describe_images(
Filters=[{"Name": "name", "Values": [imageA.name]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_name].should.equal([imageA.id])
amis_by_public = ec2.describe_images(
Filters=[{"Name": "is-public", "Values": ["true"]}]
)["Images"]
amis_by_public.should.have.length_of(38)
amis_by_nonpublic = ec2.describe_images(
Filters=[{"Name": "is-public", "Values": ["false"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_nonpublic].should.contain(imageA.id)
amis_by_nonpublic.should.have.length_of(2)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_filtering_via_tag(): def test_ami_filtering_via_tag():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -349,6 +693,38 @@ def test_ami_filtering_via_tag():
set([ami.id for ami in amis_by_tagB]).should.equal(set([imageB.id])) set([ami.id for ami in amis_by_tagB]).should.equal(set([imageB.id]))
@mock_ec2
def test_ami_filtering_via_tag_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instanceA = reservationA["Instances"][0]
imageA_id = ec2.create_image(InstanceId=instanceA["InstanceId"], Name="test-ami-A")[
"ImageId"
]
imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id)
imageA.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
reservationB = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instanceB = reservationB["Instances"][0]
imageB_id = ec2.create_image(InstanceId=instanceB["InstanceId"], Name="test-ami-B")[
"ImageId"
]
imageB = boto3.resource("ec2", region_name="us-east-1").Image(imageB_id)
imageB.create_tags(Tags=[{"Key": "another key", "Value": "some other value"}])
amis_by_tagA = ec2.describe_images(
Filters=[{"Name": "tag:a key", "Values": ["some value"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_tagA].should.equal([imageA_id])
amis_by_tagB = ec2.describe_images(
Filters=[{"Name": "tag:another key", "Values": ["some other value"]}]
)["Images"]
[ami["ImageId"] for ami in amis_by_tagB].should.equal([imageB_id])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_getting_missing_ami(): def test_getting_missing_ami():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -360,6 +736,18 @@ def test_getting_missing_ami():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_getting_missing_ami_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
ec2.Image("ami-missing").load()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_getting_malformed_ami(): def test_getting_malformed_ami():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -371,6 +759,18 @@ def test_getting_malformed_ami():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_getting_malformed_ami_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
ec2.Image("foo-missing").load()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.Malformed")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_attribute_group_permissions(): def test_ami_attribute_group_permissions():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -434,6 +834,73 @@ def test_ami_attribute_group_permissions():
) )
@mock_ec2
def test_ami_attribute_group_permissions_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[
"ImageId"
]
image = boto3.resource("ec2", region_name="us-east-1").Image(image_id)
# Baseline
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
ADD_GROUP_ARGS = {
"ImageId": image_id,
"Attribute": "launchPermission",
"OperationType": "add",
"UserGroups": ["all"],
}
REMOVE_GROUP_ARGS = {
"ImageId": image_id,
"Attribute": "launchPermission",
"OperationType": "remove",
"UserGroups": ["all"],
}
# Add 'all' group and confirm
with pytest.raises(ClientError) as ex:
image.modify_attribute(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set"
)
image.modify_attribute(**ADD_GROUP_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([{"Group": "all"}])
image.reload()
image.public.should.equal(True)
# Add is idempotent
image.modify_attribute(**ADD_GROUP_ARGS)
# Remove 'all' group and confirm
image.modify_attribute(**REMOVE_GROUP_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
image.reload()
image.public.should.equal(False)
# Remove is idempotent
image.modify_attribute(**REMOVE_GROUP_ARGS)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_attribute_user_permissions(): def test_ami_attribute_user_permissions():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -509,6 +976,86 @@ def test_ami_attribute_user_permissions():
) )
@mock_ec2
def test_ami_attribute_user_permissions_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[
"ImageId"
]
image = boto3.resource("ec2", region_name="us-east-1").Image(image_id)
# Baseline
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
USER1 = "123456789011"
USER2 = "123456789022"
ADD_USERS_ARGS = {
"ImageId": image.id,
"Attribute": "launchPermission",
"OperationType": "add",
"UserIds": [USER1, USER2],
}
REMOVE_USERS_ARGS = {
"ImageId": image.id,
"Attribute": "launchPermission",
"OperationType": "remove",
"UserIds": [USER1, USER2],
}
REMOVE_SINGLE_USER_ARGS = {
"ImageId": image.id,
"Attribute": "launchPermission",
"OperationType": "remove",
"UserIds": [USER1],
}
# Add multiple users and confirm
image.modify_attribute(**ADD_USERS_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.have.length_of(2)
permissions.should.contain({"UserId": USER1})
permissions.should.contain({"UserId": USER2})
image.reload()
image.public.should.equal(False)
# Add is idempotent
image.modify_attribute(**ADD_USERS_ARGS)
# Remove single user and confirm
image.modify_attribute(**REMOVE_SINGLE_USER_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([{"UserId": USER2}])
image.reload()
image.public.should.equal(False)
# Remove multiple users and confirm
image.modify_attribute(**REMOVE_USERS_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
image.reload()
image.public.should.equal(False)
# Remove is idempotent
image.modify_attribute(**REMOVE_USERS_ARGS)
@mock_ec2 @mock_ec2
def test_ami_describe_executable_users(): def test_ami_describe_executable_users():
conn = boto3.client("ec2", region_name="us-east-1") conn = boto3.client("ec2", region_name="us-east-1")
@ -613,6 +1160,7 @@ def test_ami_describe_executable_users_and_filter():
images[0]["ImageId"].should.equal(image_id) images[0]["ImageId"].should.equal(image_id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_attribute_user_and_group_permissions(): def test_ami_attribute_user_and_group_permissions():
""" """
@ -669,6 +1217,72 @@ def test_ami_attribute_user_and_group_permissions():
image.is_public.should.equal(False) image.is_public.should.equal(False)
@mock_ec2
def test_ami_attribute_user_and_group_permissions_boto3():
"""
Boto supports adding/removing both users and groups at the same time.
Just spot-check this -- input variations, idempotency, etc are validated
via user-specific and group-specific tests above.
"""
ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[
"ImageId"
]
image = boto3.resource("ec2", region_name="us-east-1").Image(image_id)
# Baseline
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
USER1 = "123456789011"
USER2 = "123456789022"
ADD_ARGS = {
"ImageId": image.id,
"Attribute": "launchPermission",
"OperationType": "add",
"UserGroups": ["all"],
"UserIds": [USER1, USER2],
}
REMOVE_ARGS = {
"ImageId": image.id,
"Attribute": "launchPermission",
"OperationType": "remove",
"UserGroups": ["all"],
"UserIds": [USER1, USER2],
}
# Add and confirm
image.modify_attribute(**ADD_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.have.length_of(3)
permissions.should.contain({"Group": "all"})
permissions.should.contain({"UserId": "123456789022"})
permissions.should.contain({"UserId": "123456789011"})
image.reload()
image.public.should.equal(True)
# Remove and confirm
image.modify_attribute(**REMOVE_ARGS)
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
image.reload()
image.public.should.equal(False)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_attribute_error_cases(): def test_ami_attribute_error_cases():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -760,6 +1374,108 @@ def test_ami_attribute_error_cases():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_ami_attribute_error_cases_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[
"ImageId"
]
image = boto3.resource("ec2", region_name="us-east-1").Image(image_id)
# Error: Add with group != 'all'
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId=image_id,
Attribute="launchPermission",
OperationType="add",
UserGroups=["everyone"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue")
# Error: Add with user ID that isn't an integer.
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId=image_id,
Attribute="launchPermission",
OperationType="add",
UserIds=["12345678901A"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue")
# Error: Add with user ID that is > length 12.
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId=image_id,
Attribute="launchPermission",
OperationType="add",
UserIds=["1234567890123"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue")
# Error: Add with user ID that is < length 12.
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId=image_id,
Attribute="launchPermission",
OperationType="add",
UserIds=["12345678901"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue")
# Error: Add with one invalid user ID among other valid IDs, ensure no
# partial changes.
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId=image_id,
Attribute="launchPermission",
OperationType="add",
UserIds=["123456789011", "foo", "123456789022"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue")
permissions = image.describe_attribute(Attribute="launchPermission")[
"LaunchPermissions"
]
permissions.should.equal([])
# Error: Add with invalid image ID
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId="ami-abcd1234",
Attribute="launchPermission",
OperationType="add",
UserGroups=["all"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound")
# Error: Remove with invalid image ID
with pytest.raises(ClientError) as ex:
image.modify_attribute(
ImageId="ami-abcd1234",
Attribute="launchPermission",
OperationType="remove",
UserGroups=["all"],
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound")
@mock_ec2 @mock_ec2
def test_ami_describe_non_existent(): def test_ami_describe_non_existent():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")

View File

@ -7,6 +7,7 @@ import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_describe_regions(): def test_describe_regions():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -16,6 +17,7 @@ def test_describe_regions():
region.endpoint.should.contain(region.name) region.endpoint.should.contain(region.name)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_availability_zones(): def test_availability_zones():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")

View File

@ -1,12 +1,15 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto import boto
import boto3
import sure # noqa import sure # noqa
import pytest import pytest
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError
from moto import mock_ec2_deprecated from moto import mock_ec2_deprecated, mock_ec2
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_customer_gateways(): def test_create_customer_gateways():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -19,6 +22,18 @@ def test_create_customer_gateways():
customer_gateway.ip_address.should.equal("205.251.242.54") customer_gateway.ip_address.should.equal("205.251.242.54")
@mock_ec2
def test_create_customer_gateways_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
customer_gateway = create_customer_gateway(ec2)
customer_gateway.should.have.key("CustomerGatewayId").match(r"cgw-\w+")
customer_gateway.should.have.key("Type").equal("ipsec.1")
customer_gateway.should.have.key("BgpAsn").equal("65534")
customer_gateway.should.have.key("IpAddress").equal("205.251.242.54")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_describe_customer_gateways(): def test_describe_customer_gateways():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -28,6 +43,17 @@ def test_describe_customer_gateways():
cgws[0].id.should.match(customer_gateway.id) cgws[0].id.should.match(customer_gateway.id)
@mock_ec2
def test_describe_customer_gateways_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
customer_gateway = create_customer_gateway(ec2)
cgws = ec2.describe_customer_gateways()["CustomerGateways"]
cgws.should.have.length_of(1)
cgws[0]["CustomerGatewayId"].should.match(customer_gateway["CustomerGatewayId"])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_customer_gateways(): def test_delete_customer_gateways():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -42,8 +68,40 @@ def test_delete_customer_gateways():
cgws.should.have.length_of(1) cgws.should.have.length_of(1)
@mock_ec2
def test_delete_customer_gateways_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
customer_gateway = create_customer_gateway(ec2)
cgws = ec2.describe_customer_gateways()["CustomerGateways"]
cgws.should.have.length_of(1)
ec2.delete_customer_gateway(CustomerGatewayId=customer_gateway["CustomerGatewayId"])
cgws = ec2.describe_customer_gateways()["CustomerGateways"]
cgws.should.have.length_of(1)
cgws[0].should.have.key("State").equal("deleted")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_customer_gateways_bad_id(): def test_delete_customer_gateways_bad_id():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
with pytest.raises(EC2ResponseError) as cm: with pytest.raises(EC2ResponseError) as cm:
conn.delete_customer_gateway("cgw-0123abcd") conn.delete_customer_gateway("cgw-0123abcd")
@mock_ec2
def test_delete_customer_gateways_bad_id_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
ec2.delete_customer_gateway(CustomerGatewayId="cgw-0123abcd")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidCustomerGatewayID.NotFound")
def create_customer_gateway(ec2):
return ec2.create_customer_gateway(
Type="ipsec.1", PublicIp="205.251.242.54", BgpAsn=65534
)["CustomerGateway"]

View File

@ -5,15 +5,18 @@ import pytest
import boto3 import boto3
import boto import boto
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated, settings
from unittest import SkipTest
SAMPLE_DOMAIN_NAME = "example.com" SAMPLE_DOMAIN_NAME = "example.com"
SAMPLE_NAME_SERVERS = ["10.0.0.6", "10.0.0.7"] SAMPLE_NAME_SERVERS = ["10.0.0.6", "10.0.0.7"]
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_associate(): def test_dhcp_options_associate():
"""associate dhcp option""" """associate dhcp option"""
@ -25,6 +28,27 @@ def test_dhcp_options_associate():
rval.should.be.equal(True) rval.should.be.equal(True)
@mock_ec2
def test_dhcp_options_associate_boto3():
""" associate dhcp option """
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
client.associate_dhcp_options(DhcpOptionsId=dhcp_options.id, VpcId=vpc.id)
#
vpc.reload()
vpc.dhcp_options_id.should.equal(dhcp_options.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_associate_invalid_dhcp_id(): def test_dhcp_options_associate_invalid_dhcp_id():
"""associate dhcp option bad dhcp options id""" """associate dhcp option bad dhcp options id"""
@ -38,6 +62,21 @@ def test_dhcp_options_associate_invalid_dhcp_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_dhcp_options_associate_invalid_dhcp_id_boto3():
""" associate dhcp option bad dhcp options id """
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
with pytest.raises(ClientError) as ex:
client.associate_dhcp_options(DhcpOptionsId="foo", VpcId=vpc.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidDhcpOptionID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_associate_invalid_vpc_id(): def test_dhcp_options_associate_invalid_vpc_id():
"""associate dhcp option invalid vpc id""" """associate dhcp option invalid vpc id"""
@ -51,6 +90,26 @@ def test_dhcp_options_associate_invalid_vpc_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_dhcp_options_associate_invalid_vpc_id_boto3():
""" associate dhcp option invalid vpc id """
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
with pytest.raises(ClientError) as ex:
client.associate_dhcp_options(DhcpOptionsId=dhcp_options.id, VpcId="foo")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_delete_with_vpc(): def test_dhcp_options_delete_with_vpc():
"""Test deletion of dhcp options with vpc""" """Test deletion of dhcp options with vpc"""
@ -77,6 +136,37 @@ def test_dhcp_options_delete_with_vpc():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_dhcp_options_delete_with_vpc_boto3():
"""Test deletion of dhcp options with vpc"""
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
client.associate_dhcp_options(DhcpOptionsId=dhcp_options.id, VpcId=vpc.id)
with pytest.raises(ClientError) as ex:
client.delete_dhcp_options(DhcpOptionsId=dhcp_options.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("DependencyViolation")
vpc.delete()
with pytest.raises(ClientError) as ex:
client.describe_dhcp_options(DhcpOptionsIds=[dhcp_options.id])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidDhcpOptionID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_dhcp_options(): def test_create_dhcp_options():
"""Create most basic dhcp option""" """Create most basic dhcp option"""
@ -92,6 +182,31 @@ def test_create_dhcp_options():
) )
@mock_ec2
def test_create_dhcp_options_boto3():
"""Create most basic dhcp option"""
ec2 = boto3.resource("ec2", region_name="us-west-1")
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
config = dhcp_options.dhcp_configurations
config.should.have.length_of(2)
config.should.contain(
{
"Key": "domain-name-servers",
"Values": [{"Value": ip} for ip in SAMPLE_NAME_SERVERS],
}
)
config.should.contain(
{"Key": "domain-name", "Values": [{"Value": SAMPLE_DOMAIN_NAME}]}
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_dhcp_options_invalid_options(): def test_create_dhcp_options_invalid_options():
"""Create invalid dhcp options""" """Create invalid dhcp options"""
@ -111,6 +226,30 @@ def test_create_dhcp_options_invalid_options():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_create_dhcp_options_invalid_options_boto3():
"""Create invalid dhcp options"""
ec2 = boto3.resource("ec2", region_name="us-west-1")
servers = ["f", "f", "f", "f", "f"]
with pytest.raises(ClientError) as ex:
ec2.create_dhcp_options(
DhcpConfigurations=[{"Key": "ntp-servers", "Values": servers}]
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidParameterValue")
with pytest.raises(ClientError) as ex:
ec2.create_dhcp_options(
DhcpConfigurations=[{"Key": "netbios-node-type", "Values": ["0"]}]
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidParameterValue")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_describe_dhcp_options(): def test_describe_dhcp_options():
"""Test dhcp options lookup by id""" """Test dhcp options lookup by id"""
@ -124,6 +263,43 @@ def test_describe_dhcp_options():
dhcp_options.should.be.length_of(1) dhcp_options.should.be.length_of(1)
@mock_ec2
def test_describe_dhcp_options_boto3():
"""Test dhcp options lookup by id"""
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
all_options = client.describe_dhcp_options()["DhcpOptions"]
all_options.should.have.length_of(0)
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
all_options = client.describe_dhcp_options(DhcpOptionsIds=[dhcp_options.id])[
"DhcpOptions"
]
all_options.should.have.length_of(1)
all_options = client.describe_dhcp_options()["DhcpOptions"]
all_options.should.have.length_of(1)
all_options[0]["DhcpOptionsId"].should.equal(dhcp_options.id)
config = all_options[0]["DhcpConfigurations"]
config.should.have.length_of(2)
config.should.contain(
{
"Key": "domain-name-servers",
"Values": [{"Value": ip} for ip in SAMPLE_NAME_SERVERS],
}
)
config.should.contain(
{"Key": "domain-name", "Values": [{"Value": SAMPLE_DOMAIN_NAME}]}
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_describe_dhcp_options_invalid_id(): def test_describe_dhcp_options_invalid_id():
"""get error on invalid dhcp_option_id lookup""" """get error on invalid dhcp_option_id lookup"""
@ -136,6 +312,19 @@ def test_describe_dhcp_options_invalid_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_describe_dhcp_options_invalid_id_boto3():
"""get error on invalid dhcp_option_id lookup"""
client = boto3.client("ec2", region_name="us-west-1")
with pytest.raises(ClientError) as ex:
client.describe_dhcp_options(DhcpOptionsIds=["1"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidDhcpOptionID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_dhcp_options(): def test_delete_dhcp_options():
"""delete dhcp option""" """delete dhcp option"""
@ -154,6 +343,29 @@ def test_delete_dhcp_options():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_delete_dhcp_options_boto3():
"""delete dhcp option"""
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp_option = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
client.delete_dhcp_options(DhcpOptionsId=dhcp_option.id)
with pytest.raises(ClientError) as ex:
client.describe_dhcp_options(DhcpOptionsIds=[dhcp_option.id])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidDhcpOptionID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_dhcp_options_invalid_id(): def test_delete_dhcp_options_invalid_id():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -167,6 +379,18 @@ def test_delete_dhcp_options_invalid_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_delete_dhcp_options_invalid_id_boto3():
client = boto3.client("ec2", region_name="us-west-1")
with pytest.raises(ClientError) as ex:
client.delete_dhcp_options(DhcpOptionsId="dopt-abcd1234")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidDhcpOptionID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_dhcp_options_malformed_id(): def test_delete_dhcp_options_malformed_id():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -180,6 +404,18 @@ def test_delete_dhcp_options_malformed_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_delete_dhcp_options_malformed_id_boto3():
client = boto3.client("ec2", region_name="us-west-1")
with pytest.raises(ClientError) as ex:
client.delete_dhcp_options(DhcpOptionsId="foo-abcd1234")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidDhcpOptionsId.Malformed")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_tagging(): def test_dhcp_tagging():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -197,6 +433,32 @@ def test_dhcp_tagging():
dhcp_option.tags["a key"].should.equal("some value") dhcp_option.tags["a key"].should.equal("some value")
@mock_ec2
def test_dhcp_tagging_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp_option = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
dhcp_option.create_tags(Tags=[{"Key": "a tag", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("ResourceId").equal(dhcp_option.id)
tag.should.have.key("ResourceType").equal("dhcp-options")
tag.should.have.key("Key").equal("a tag")
tag.should.have.key("Value").equal("some value")
# Refresh the DHCP options
dhcp_option = client.describe_dhcp_options()["DhcpOptions"][0]
dhcp_option["Tags"].should.equal([{"Key": "a tag", "Value": "some value"}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_get_by_tag(): def test_dhcp_options_get_by_tag():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -233,6 +495,83 @@ def test_dhcp_options_get_by_tag():
dhcp_options_sets.should.have.length_of(2) dhcp_options_sets.should.have.length_of(2)
@mock_ec2
def test_dhcp_options_get_by_tag_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp1 = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.10.2"]},
]
)
dhcp1.create_tags(
Tags=[
{"Key": "Name", "Value": "TestDhcpOptions1"},
{"Key": "test-tag", "Value": "test-value"},
]
)
dhcp2 = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.20.2"]},
]
)
dhcp2.create_tags(
Tags=[
{"Key": "Name", "Value": "TestDhcpOptions2"},
{"Key": "test-tag", "Value": "test-value"},
]
)
dhcp_options_sets = client.describe_dhcp_options(
Filters=[
{"Name": "tag:Name", "Values": ["TestDhcpOptions1"]},
{"Name": "tag:test-tag", "Values": ["test-value"]},
]
)["DhcpOptions"]
dhcp_options_sets.should.have.length_of(1)
config = dhcp_options_sets[0]["DhcpConfigurations"]
config.should.have.length_of(2)
config.should.contain({"Key": "domain-name", "Values": [{"Value": "example.com"}]})
config.should.contain(
{"Key": "domain-name-servers", "Values": [{"Value": "10.0.10.2"}]}
)
tags = dhcp_options_sets[0]["Tags"]
tags.should.have.length_of(2)
tags.should.contain({"Key": "Name", "Value": "TestDhcpOptions1"})
tags.should.contain({"Key": "test-tag", "Value": "test-value"})
dhcp_options_sets = client.describe_dhcp_options(
Filters=[
{"Name": "tag:Name", "Values": ["TestDhcpOptions2"]},
{"Name": "tag:test-tag", "Values": ["test-value"]},
]
)["DhcpOptions"]
dhcp_options_sets.should.have.length_of(1)
config = dhcp_options_sets[0]["DhcpConfigurations"]
config.should.have.length_of(2)
config.should.contain({"Key": "domain-name", "Values": [{"Value": "example.com"}]})
config.should.contain(
{"Key": "domain-name-servers", "Values": [{"Value": "10.0.20.2"}]}
)
tags = dhcp_options_sets[0]["Tags"]
tags.should.have.length_of(2)
tags.should.contain({"Key": "Name", "Value": "TestDhcpOptions2"})
tags.should.contain({"Key": "test-tag", "Value": "test-value"})
dhcp_options_sets = client.describe_dhcp_options(
Filters=[{"Name": "tag:test-tag", "Values": ["test-value"]}]
)["DhcpOptions"]
dhcp_options_sets.should.have.length_of(2)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_get_by_id(): def test_dhcp_options_get_by_id():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -263,6 +602,47 @@ def test_dhcp_options_get_by_id():
dhcp_options_sets[0].options["domain-name-servers"][0].should.be.equal("10.0.20.2") dhcp_options_sets[0].options["domain-name-servers"][0].should.be.equal("10.0.20.2")
@mock_ec2
def test_dhcp_options_get_by_id_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp1 = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": ["test1.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.10.2"]},
]
)
dhcp1.create_tags(Tags=[{"Key": "Name", "Value": "TestDhcpOptions1"}])
dhcp1.create_tags(Tags=[{"Key": "test-tag", "Value": "test-value"}])
dhcp2 = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": ["test2.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.20.2"]},
]
)
dhcp1.create_tags(Tags=[{"Key": "Name", "Value": "TestDhcpOptions2"}])
dhcp1.create_tags(Tags=[{"Key": "test-tag", "Value": "test-value"}])
d = client.describe_dhcp_options()["DhcpOptions"]
d.should.have.length_of(2)
d = client.describe_dhcp_options(
Filters=[{"Name": "dhcp-options-id", "Values": [dhcp1.id]}]
)["DhcpOptions"]
d.should.have.length_of(1)
d[0].should.have.key("DhcpOptionsId").equal(dhcp1.id)
d = client.describe_dhcp_options(
Filters=[{"Name": "dhcp-options-id", "Values": [dhcp2.id]}]
)["DhcpOptions"]
d.should.have.length_of(1)
d[0].should.have.key("DhcpOptionsId").equal(dhcp2.id)
@mock_ec2 @mock_ec2
def test_dhcp_options_get_by_value_filter(): def test_dhcp_options_get_by_value_filter():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
@ -323,6 +703,7 @@ def test_dhcp_options_get_by_key_filter():
dhcp_options_sets.should.have.length_of(3) dhcp_options_sets.should.have.length_of(3)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_dhcp_options_get_by_invalid_filter(): def test_dhcp_options_get_by_invalid_filter():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -333,3 +714,24 @@ def test_dhcp_options_get_by_invalid_filter():
conn.get_all_dhcp_options.when.called_with(filters=filters).should.throw( conn.get_all_dhcp_options.when.called_with(filters=filters).should.throw(
NotImplementedError NotImplementedError
) )
@mock_ec2
def test_dhcp_options_get_by_invalid_filter_boto3():
if settings.TEST_SERVER_MODE:
raise SkipTest("Will throw a generic 500 in ServerMode")
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
filters = [{"Name": "invalid-filter", "Values": ["n/a"]}]
client.describe_dhcp_options.when.called_with(Filters=filters).should.throw(
NotImplementedError
)

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto import boto
import boto.ec2
import boto3 import boto3
import pytest import pytest
@ -14,6 +15,7 @@ from moto.kms import mock_kms
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_and_delete_volume(): def test_create_and_delete_volume():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -51,6 +53,43 @@ def test_create_and_delete_volume():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_create_and_delete_volume_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a")
all_volumes = client.describe_volumes()["Volumes"]
current_volume = [item for item in all_volumes if item["VolumeId"] == volume.id]
current_volume.should.have.length_of(1)
current_volume[0]["Size"].should.equal(80)
current_volume[0]["AvailabilityZone"].should.equal("us-east-1a")
current_volume[0]["Encrypted"].should.be(False)
with pytest.raises(ClientError) as ex:
volume.delete(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteVolume operation: Request would have succeeded, but DryRun flag is set"
)
volume.delete()
all_volumes = client.describe_volumes()["Volumes"]
my_volume = [item for item in all_volumes if item["VolumeId"] == volume.id]
my_volume.should.have.length_of(0)
# Deleting something that was already deleted should throw an error
with pytest.raises(ClientError) as ex:
volume.delete()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVolume.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_attached_volume(): def test_delete_attached_volume():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -90,6 +129,47 @@ def test_delete_attached_volume():
my_volume.should.have.length_of(0) my_volume.should.have.length_of(0)
@mock_ec2
def test_delete_attached_volume_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
# create an instance
instance = reservation["Instances"][0]
# create a volume
volume = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a")
# attach volume to instance
volume.attach_to_instance(InstanceId=instance["InstanceId"], Device="/dev/sdh")
volume.state.should.equal("in-use")
volume.attachments.should.have.length_of(1)
volume.attachments[0]["InstanceId"].should.equal(instance["InstanceId"])
volume.attachments[0]["State"].should.equal("attached")
# attempt to delete volume
# assert raises VolumeInUseError
with pytest.raises(ClientError) as ex:
volume.delete()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("VolumeInUse")
ex.value.response["Error"]["Message"].should.equal(
"Volume {0} is currently attached to {1}".format(
volume.id, instance["InstanceId"]
)
)
volume.detach_from_instance(InstanceId=instance["InstanceId"])
volume.state.should.equal("available")
volume.delete()
all_volumes = client.describe_volumes()["Volumes"]
[v["VolumeId"] for v in all_volumes].shouldnt.contain(volume.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_encrypted_volume_dryrun(): def test_create_encrypted_volume_dryrun():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -102,6 +182,19 @@ def test_create_encrypted_volume_dryrun():
) )
@mock_ec2
def test_create_encrypted_volume_dryrun_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
ec2.create_volume(Size=80, AvailabilityZone="us-east-1a", DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set"
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_encrypted_volume(): def test_create_encrypted_volume():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -119,6 +212,17 @@ def test_create_encrypted_volume():
all_volumes[0].encrypted.should.be(True) all_volumes[0].encrypted.should.be(True)
@mock_ec2
def test_create_encrypted_volume_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a", Encrypted=True)
all_volumes = client.describe_volumes(VolumeIds=[volume.id])["Volumes"]
all_volumes[0]["Encrypted"].should.be(True)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_filter_volume_by_id(): def test_filter_volume_by_id():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -139,6 +243,29 @@ def test_filter_volume_by_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_filter_volume_by_id_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume1 = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a")
volume2 = ec2.create_volume(Size=36, AvailabilityZone="us-east-1b")
volume3 = ec2.create_volume(Size=20, AvailabilityZone="us-east-1c")
vol3 = client.describe_volumes(VolumeIds=[volume3.id])["Volumes"]
vol3.should.have.length_of(1)
vol3[0]["Size"].should.equal(20)
vol3[0]["AvailabilityZone"].should.equal("us-east-1c")
vol12 = client.describe_volumes(VolumeIds=[volume1.id, volume2.id])["Volumes"]
vol12.should.have.length_of(2)
with pytest.raises(ClientError) as ex:
client.describe_volumes(VolumeIds=["vol-does_not_exist"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("InvalidVolume.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_volume_filters(): def test_volume_filters():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -247,6 +374,76 @@ def test_volume_filters():
).should.equal({volume2.id}) ).should.equal({volume2.id})
@mock_ec2
def test_volume_filters_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
volume1 = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a", Encrypted=True)
volume2 = ec2.create_volume(Size=36, AvailabilityZone="us-east-1b", Encrypted=False)
volume3 = ec2.create_volume(Size=20, AvailabilityZone="us-east-1c", Encrypted=True)
snapshot = volume3.create_snapshot(Description="testsnap")
volume4 = ec2.create_volume(
Size=25, AvailabilityZone="us-east-1a", SnapshotId=snapshot.id
)
ec2.create_tags(
Resources=[volume1.id], Tags=[{"Key": "testkey1", "Value": "testvalue1"}]
)
ec2.create_tags(
Resources=[volume2.id], Tags=[{"Key": "testkey2", "Value": "testvalue2"}]
)
volume1.reload()
volume2.reload()
volume3.reload()
volume4.reload()
instance = ec2.Instance(instance["InstanceId"])
instance.reload()
block_mapping = [
m for m in instance.block_device_mappings if m["DeviceName"] == "/dev/sda1"
][0]
block_volume = block_mapping["Ebs"]["VolumeId"]
def verify_filter(name, value, expected=None):
expected = expected or block_volume
expected = expected if type(expected) == list else [expected]
volumes = client.describe_volumes(Filters=[{"Name": name, "Values": [value]}])[
"Volumes"
]
set([vol["VolumeId"] for vol in volumes]).should.equal(set(expected))
# We should probably make this less strict, i.e. figure out which formats AWS expects/approves of
attach_time = block_mapping["Ebs"]["AttachTime"].strftime("%Y-%m-%dT%H:%M:%S.000Z")
verify_filter("attachment.attach-time", attach_time)
verify_filter("attachment.device", "/dev/sda1")
verify_filter("attachment.instance-id", instance.id)
verify_filter("attachment.status", "attached")
verify_filter("size", str(volume2.size), expected=volume2.id)
verify_filter("snapshot-id", snapshot.id, expected=volume4.id)
verify_filter("status", "in-use")
verify_filter("volume-id", volume1.id, expected=volume1.id)
verify_filter("tag-key", "testkey1", expected=volume1.id)
verify_filter("tag-value", "testvalue1", expected=volume1.id)
verify_filter("tag:testkey1", "testvalue1", expected=volume1.id)
verify_filter("encrypted", "false", expected=[block_volume, volume2.id])
verify_filter("encrypted", "true", expected=[volume1.id, volume3.id, volume4.id])
verify_filter("availability-zone", "us-east-1b", expected=volume2.id)
#
create_time = volume4.create_time.strftime("%Y-%m-%dT%H:%M:%S.000Z")
volumes_by_attach_device = client.describe_volumes(
Filters=[{"Name": "create-time", "Values": [create_time]}]
)["Volumes"]
[vol["VolumeId"] for vol in volumes_by_attach_device].should.contain(volume4.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_volume_attach_and_detach(): def test_volume_attach_and_detach():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -305,6 +502,66 @@ def test_volume_attach_and_detach():
cm3.value.request_id.should_not.be.none cm3.value.request_id.should_not.be.none
@mock_ec2
def test_volume_attach_and_detach_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
volume = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a")
volume.reload()
volume.state.should.equal("available")
with pytest.raises(ClientError) as ex:
volume.attach_to_instance(
InstanceId=instance["InstanceId"], Device="/dev/sdh", DryRun=True
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the AttachVolume operation: Request would have succeeded, but DryRun flag is set"
)
volume.attach_to_instance(InstanceId=instance["InstanceId"], Device="/dev/sdh")
volume.state.should.equal("in-use")
volume.attachments[0]["State"].should.equal("attached")
volume.attachments[0]["InstanceId"].should.equal(instance["InstanceId"])
with pytest.raises(ClientError) as ex:
volume.detach_from_instance(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DetachVolume operation: Request would have succeeded, but DryRun flag is set"
)
volume.detach_from_instance(InstanceId=instance["InstanceId"])
volume.state.should.equal("available")
with pytest.raises(ClientError) as ex1:
volume.attach_to_instance(InstanceId="i-1234abcd", Device="/dev/sdh")
ex1.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex1.value.response["Error"]["Code"].should.equal("InvalidInstanceID.NotFound")
with pytest.raises(ClientError) as ex2:
client.detach_volume(
VolumeId=volume.id, InstanceId=instance["InstanceId"], Device="/dev/sdh"
)
ex2.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex2.value.response["Error"]["Code"].should.equal("InvalidAttachment.NotFound")
with pytest.raises(ClientError) as ex3:
client.detach_volume(
VolumeId=volume.id, InstanceId="i-1234abcd", Device="/dev/sdh"
)
ex3.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex3.value.response["Error"]["Code"].should.equal("InvalidInstanceID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_snapshot(): def test_create_snapshot():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -345,6 +602,51 @@ def test_create_snapshot():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_create_snapshot_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a")
with pytest.raises(ClientError) as ex:
volume.create_snapshot(Description="a dryrun snapshot", DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set"
)
snapshot = volume.create_snapshot(Description="a test snapshot")
snapshot.reload()
snapshot.state.should.equal("completed")
snapshots = [
snap
for snap in client.describe_snapshots()["Snapshots"]
if snap["SnapshotId"] == snapshot.id
]
snapshots.should.have.length_of(1)
snapshots[0]["Description"].should.equal("a test snapshot")
snapshots[0]["StartTime"].should_not.be.none
snapshots[0]["Encrypted"].should.be(False)
# Create snapshot without description
num_snapshots = len(client.describe_snapshots()["Snapshots"])
snapshot = volume.create_snapshot()
client.describe_snapshots()["Snapshots"].should.have.length_of(num_snapshots + 1)
snapshot.delete()
client.describe_snapshots()["Snapshots"].should.have.length_of(num_snapshots)
# Deleting something that was already deleted should throw an error
with pytest.raises(ClientError) as ex:
snapshot.delete()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_encrypted_snapshot(): def test_create_encrypted_snapshot():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -360,6 +662,31 @@ def test_create_encrypted_snapshot():
snapshots[0].encrypted.should.be(True) snapshots[0].encrypted.should.be(True)
@mock_ec2
@pytest.mark.parametrize("encrypted", [True, False])
def test_create_encrypted_snapshot_boto3(encrypted):
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume = ec2.create_volume(
Size=80, AvailabilityZone="us-east-1a", Encrypted=encrypted
)
snapshot = volume.create_snapshot(Description="a test snapshot")
snapshot.encrypted.should.be(encrypted)
snapshot.reload()
snapshot.state.should.equal("completed")
snapshots = [
snap
for snap in client.describe_snapshots()["Snapshots"]
if snap["SnapshotId"] == snapshot.id
]
snapshots.should.have.length_of(1)
snapshots[0]["Description"].should.equal("a test snapshot")
snapshots[0]["StartTime"].should_not.be.none
snapshots[0]["Encrypted"].should.be(encrypted)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_filter_snapshot_by_id(): def test_filter_snapshot_by_id():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -387,6 +714,35 @@ def test_filter_snapshot_by_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_filter_snapshot_by_id_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume1 = ec2.create_volume(Size=36, AvailabilityZone="us-east-1a")
snap1 = volume1.create_snapshot(Description="a test snapshot 1")
volume2 = ec2.create_volume(Size=42, AvailabilityZone="us-east-1a")
snap2 = volume2.create_snapshot(Description="a test snapshot 2")
volume3 = ec2.create_volume(Size=84, AvailabilityZone="us-east-1a")
snap3 = volume3.create_snapshot(Description="a test snapshot 3")
snapshots1 = client.describe_snapshots(SnapshotIds=[snap1.id])["Snapshots"]
snapshots1.should.have.length_of(1)
snapshots1[0]["VolumeId"].should.equal(volume1.id)
snapshots2 = client.describe_snapshots(SnapshotIds=[snap2.id, snap3.id])[
"Snapshots"
]
snapshots2.should.have.length_of(2)
for s in snapshots2:
s["StartTime"].should_not.be.none
s["VolumeId"].should.be.within([volume2.id, volume3.id])
with pytest.raises(ClientError) as ex:
client.describe_snapshots(SnapshotIds=["snap-does_not_exist"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_snapshot_filters(): def test_snapshot_filters():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -451,6 +807,60 @@ def test_snapshot_filters():
) )
@mock_ec2
def test_snapshot_filters_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume1 = ec2.create_volume(Size=20, AvailabilityZone="us-east-1a", Encrypted=False)
volume2 = ec2.create_volume(Size=25, AvailabilityZone="us-east-1a", Encrypted=True)
snapshot1 = volume1.create_snapshot(Description="testsnapshot1")
snapshot2 = volume1.create_snapshot(Description="testsnapshot2")
snapshot3 = volume2.create_snapshot(Description="testsnapshot3")
ec2.create_tags(
Resources=[snapshot1.id], Tags=[{"Key": "testkey1", "Value": "testvalue1"}]
)
ec2.create_tags(
Resources=[snapshot2.id], Tags=[{"Key": "testkey2", "Value": "testvalue2"}]
)
def verify_filter(name, value, expected):
expected = expected if type(expected) == list else [expected]
snapshots = client.describe_snapshots(
Filters=[{"Name": name, "Values": [value]}]
)["Snapshots"]
set([s["SnapshotId"] for s in snapshots]).should.equal(set(expected))
verify_filter("description", "testsnapshot1", expected=snapshot1.id)
verify_filter("snapshot-id", snapshot1.id, expected=snapshot1.id)
verify_filter("volume-id", volume1.id, expected=[snapshot1.id, snapshot2.id])
verify_filter(
"volume-size", str(volume1.size), expected=[snapshot1.id, snapshot2.id]
)
verify_filter("tag-key", "testkey1", expected=snapshot1.id)
verify_filter("tag-value", "testvalue1", expected=snapshot1.id)
verify_filter("tag:testkey2", "testvalue2", expected=snapshot2.id)
verify_filter("encrypted", "true", expected=snapshot3.id)
verify_filter(
"owner-id", OWNER_ID, expected=[snapshot1.id, snapshot2.id, snapshot3.id]
)
#
# We should probably make this less strict, i.e. figure out which formats AWS expects/approves of
start_time = snapshot1.start_time.strftime("%Y-%m-%dT%H:%M:%S.000Z")
snapshots = client.describe_snapshots(
Filters=[{"Name": "start-time", "Values": [start_time]}]
)["Snapshots"]
[s["SnapshotId"] for s in snapshots].should.contain(snapshot1.id)
snapshots = client.describe_snapshots(
Filters=[{"Name": "status", "Values": ["completed"]}]
)["Snapshots"]
[s["SnapshotId"] for s in snapshots].should.contain(snapshot1.id)
[s["SnapshotId"] for s in snapshots].should.contain(snapshot2.id)
[s["SnapshotId"] for s in snapshots].should.contain(snapshot3.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_snapshot_attribute(): def test_snapshot_attribute():
import copy import copy
@ -732,6 +1142,7 @@ def test_modify_snapshot_attribute():
assert len(attributes["CreateVolumePermissions"]) == 0 assert len(attributes["CreateVolumePermissions"]) == 0
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_volume_from_snapshot(): def test_create_volume_from_snapshot():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -755,6 +1166,7 @@ def test_create_volume_from_snapshot():
new_volume.snapshot_id.should.equal(snapshot.id) new_volume.snapshot_id.should.equal(snapshot.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_volume_from_encrypted_snapshot(): def test_create_volume_from_encrypted_snapshot():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -770,6 +1182,27 @@ def test_create_volume_from_encrypted_snapshot():
new_volume.encrypted.should.be(True) new_volume.encrypted.should.be(True)
@mock_ec2
@pytest.mark.parametrize("encrypted", [True, False])
def test_create_volume_from_snapshot_boto3(encrypted):
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume = ec2.create_volume(
Size=80, AvailabilityZone="us-east-1a", Encrypted=encrypted
)
snapshot = volume.create_snapshot(Description="a test snapshot")
snapshot.reload()
snapshot.state.should.equal("completed")
new_volume = client.create_volume(
SnapshotId=snapshot.id, AvailabilityZone="us-east-1a"
)
new_volume["Size"].should.equal(80)
new_volume["SnapshotId"].should.equal(snapshot.id)
new_volume["Encrypted"].should.equal(encrypted)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_modify_attribute_blockDeviceMapping(): def test_modify_attribute_blockDeviceMapping():
""" """
@ -801,6 +1234,46 @@ def test_modify_attribute_blockDeviceMapping():
instance.block_device_mapping["/dev/sda1"].delete_on_termination.should.be(True) instance.block_device_mapping["/dev/sda1"].delete_on_termination.should.be(True)
@mock_ec2
def test_modify_attribute_blockDeviceMapping_boto3():
"""
Reproduces the missing feature explained at [0], where we want to mock a
call to modify an instance attribute of type: blockDeviceMapping.
[0] https://github.com/spulec/moto/issues/160
"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = ec2.Instance(reservation["Instances"][0]["InstanceId"])
with pytest.raises(ClientError) as ex:
instance.modify_attribute(
BlockDeviceMappings=[
{"DeviceName": "/dev/sda1", "Ebs": {"DeleteOnTermination": True}}
],
DryRun=True,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the ModifyInstanceAttribute operation: Request would have succeeded, but DryRun flag is set"
)
instance.modify_attribute(
BlockDeviceMappings=[
{"DeviceName": "/dev/sda1", "Ebs": {"DeleteOnTermination": True}}
]
)
instance.reload()
mapping = instance.block_device_mappings[0]
mapping.should.have.key("DeviceName").equal("/dev/sda1")
mapping["Ebs"]["DeleteOnTermination"].should.be(True)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_volume_tag_escaping(): def test_volume_tag_escaping():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -823,6 +1296,29 @@ def test_volume_tag_escaping():
dict(snaps[0].tags).should.equal({"key": "</closed>"}) dict(snaps[0].tags).should.equal({"key": "</closed>"})
@mock_ec2
def test_volume_tag_escaping_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
volume = ec2.create_volume(Size=10, AvailabilityZone="us-east-1a")
snapshot = client.create_snapshot(VolumeId=volume.id, Description="Desc")
snapshot = ec2.Snapshot(snapshot["SnapshotId"])
with pytest.raises(ClientError) as ex:
snapshot.create_tags(Tags=[{"Key": "key", "Value": "</closed>"}], DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set"
)
snapshot.tags.should.have.length_of(0)
snapshot.create_tags(Tags=[{"Key": "key", "Value": "</closed>"}])
snapshot.tags.should.equal([{"Key": "key", "Value": "</closed>"}])
@mock_ec2 @mock_ec2
def test_volume_property_hidden_when_no_tags_exist(): def test_volume_property_hidden_when_no_tags_exist():
ec2_client = boto3.client("ec2", region_name="us-east-1") ec2_client = boto3.client("ec2", region_name="us-east-1")

View File

@ -5,6 +5,7 @@ import pytest
import boto import boto
import boto3 import boto3
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
@ -14,6 +15,7 @@ from tests import EXAMPLE_AMI_ID
import logging import logging
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_allocate_classic(): def test_eip_allocate_classic():
"""Allocate/release Classic EIP""" """Allocate/release Classic EIP"""
@ -45,6 +47,40 @@ def test_eip_allocate_classic():
standard.should_not.be.within(conn.get_all_addresses()) standard.should_not.be.within(conn.get_all_addresses())
@mock_ec2
def test_eip_allocate_classic_boto3():
"""Allocate/release Classic EIP"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.allocate_address(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set"
)
standard = client.allocate_address()
standard.should.have.key("PublicIp")
standard.should.have.key("Domain").equal("standard")
standard = ec2.ClassicAddress(standard["PublicIp"])
standard.load()
with pytest.raises(ClientError) as ex:
standard.release(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set"
)
standard.release()
client.describe_addresses()["Addresses"].should.be.empty
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_allocate_vpc(): def test_eip_allocate_vpc():
"""Allocate/release VPC EIP""" """Allocate/release VPC EIP"""
@ -65,6 +101,32 @@ def test_eip_allocate_vpc():
vpc.release() vpc.release()
@mock_ec2
def test_eip_allocate_vpc_boto3():
"""Allocate/release VPC EIP"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.allocate_address(Domain="vpc", DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set"
)
vpc = client.allocate_address(Domain="vpc")
vpc.should.have.key("AllocationId")
vpc.should.have.key("Domain").equal("vpc")
client.describe_addresses()["Addresses"].should.have.length_of(1)
vpc = ec2.VpcAddress(vpc["AllocationId"])
vpc.release()
client.describe_addresses()["Addresses"].should.be.empty
@mock_ec2 @mock_ec2
def test_specific_eip_allocate_vpc(): def test_specific_eip_allocate_vpc():
"""Allocate VPC EIP with specific address""" """Allocate VPC EIP with specific address"""
@ -77,6 +139,7 @@ def test_specific_eip_allocate_vpc():
logging.debug("vpc alloc_id:".format(vpc["AllocationId"])) logging.debug("vpc alloc_id:".format(vpc["AllocationId"]))
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_allocate_invalid_domain(): def test_eip_allocate_invalid_domain():
"""Allocate EIP invalid domain""" """Allocate EIP invalid domain"""
@ -89,6 +152,19 @@ def test_eip_allocate_invalid_domain():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_eip_allocate_invalid_domain_boto3():
"""Allocate EIP invalid domain"""
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.allocate_address(Domain="bogus")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("InvalidParameterValue")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_associate_classic(): def test_eip_associate_classic():
"""Associate/Disassociate EIP to classic instance""" """Associate/Disassociate EIP to classic instance"""
@ -140,6 +216,60 @@ def test_eip_associate_classic():
instance.terminate() instance.terminate()
@mock_ec2
def test_eip_associate_classic_boto3():
"""Associate/Disassociate EIP to classic instance"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = ec2.Instance(reservation["Instances"][0]["InstanceId"])
eip = client.allocate_address()
eip = ec2.ClassicAddress(eip["PublicIp"])
eip.instance_id.should.be.empty
with pytest.raises(ClientError) as ex:
client.associate_address(PublicIp=eip.public_ip)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
ex.value.response["Error"]["Message"].should.equal(
"Invalid request, expect InstanceId/NetworkId parameter."
)
with pytest.raises(ClientError) as ex:
client.associate_address(
InstanceId=instance.id, PublicIp=eip.public_ip, DryRun=True
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the AssociateAddress operation: Request would have succeeded, but DryRun flag is set"
)
client.associate_address(InstanceId=instance.id, PublicIp=eip.public_ip)
eip.reload()
eip.instance_id.should.be.equal(instance.id)
with pytest.raises(ClientError) as ex:
client.disassociate_address(PublicIp=eip.public_ip, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DisAssociateAddress operation: Request would have succeeded, but DryRun flag is set"
)
client.disassociate_address(PublicIp=eip.public_ip)
eip.reload()
eip.instance_id.should.be.equal("")
eip.release()
client.describe_addresses()["Addresses"].should.be.empty
instance.terminate()
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_associate_vpc(): def test_eip_associate_vpc():
"""Associate/Disassociate EIP to VPC instance""" """Associate/Disassociate EIP to VPC instance"""
@ -181,6 +311,50 @@ def test_eip_associate_vpc():
instance.terminate() instance.terminate()
@mock_ec2
def test_eip_associate_vpc_boto3():
"""Associate/Disassociate EIP to VPC instance"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = ec2.Instance(reservation["Instances"][0]["InstanceId"])
eip = client.allocate_address(Domain="vpc")
eip.shouldnt.have.key("InstanceId")
eip = ec2.VpcAddress(eip["AllocationId"])
with pytest.raises(ClientError) as ex:
client.associate_address(AllocationId=eip.allocation_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
ex.value.response["Error"]["Message"].should.equal(
"Invalid request, expect InstanceId/NetworkId parameter."
)
client.associate_address(InstanceId=instance.id, AllocationId=eip.allocation_id)
eip.reload()
eip.instance_id.should.be.equal(instance.id)
client.disassociate_address(AssociationId=eip.association_id)
eip.reload()
eip.instance_id.should.be.equal("")
eip.association_id.should.be.none
with pytest.raises(ClientError) as ex:
eip.release(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set"
)
eip.release()
instance.terminate()
@mock_ec2 @mock_ec2
def test_eip_boto3_vpc_association(): def test_eip_boto3_vpc_association():
"""Associate EIP to VPC instance in a new subnet with boto3""" """Associate EIP to VPC instance in a new subnet with boto3"""
@ -228,6 +402,7 @@ def test_eip_boto3_vpc_association():
address.instance_id.should.be.empty address.instance_id.should.be.empty
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_associate_network_interface(): def test_eip_associate_network_interface():
"""Associate/Disassociate EIP to NIC""" """Associate/Disassociate EIP to NIC"""
@ -259,6 +434,42 @@ def test_eip_associate_network_interface():
eip = None eip = None
@mock_ec2
def test_eip_associate_network_interface_boto3():
"""Associate/Disassociate EIP to NIC"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
eni = ec2.create_network_interface(SubnetId=subnet.id)
eip = client.allocate_address(Domain="vpc")
eip = ec2.ClassicAddress(eip["PublicIp"])
eip.network_interface_id.should.be.empty
with pytest.raises(ClientError) as ex:
client.associate_address(NetworkInterfaceId=eni.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
ex.value.response["Error"]["Message"].should.equal(
"Invalid request, expect PublicIp/AllocationId parameter."
)
client.associate_address(NetworkInterfaceId=eni.id, AllocationId=eip.allocation_id)
eip.reload()
eip.network_interface_id.should.be.equal(eni.id)
client.disassociate_address(AssociationId=eip.association_id)
eip.reload()
eip.network_interface_id.should.be.empty
eip.association_id.should.be.none
eip.release()
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_reassociate(): def test_eip_reassociate():
"""reassociate EIP""" """reassociate EIP"""
@ -292,6 +503,48 @@ def test_eip_reassociate():
instance2.terminate() instance2.terminate()
@mock_ec2
def test_eip_reassociate_boto3():
"""reassociate EIP"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=2, MaxCount=2)
instance1 = ec2.Instance(reservation["Instances"][0]["InstanceId"])
instance2 = ec2.Instance(reservation["Instances"][1]["InstanceId"])
eip = client.allocate_address()
eip = ec2.ClassicAddress(eip["PublicIp"])
client.associate_address(InstanceId=instance1.id, PublicIp=eip.public_ip)
# Same ID is idempotent
client.associate_address(InstanceId=instance1.id, PublicIp=eip.public_ip)
eip.reload()
eip.instance_id.should.equal(instance1.id)
# Different ID detects resource association
with pytest.raises(ClientError) as ex:
client.associate_address(
InstanceId=instance2.id, PublicIp=eip.public_ip, AllowReassociation=False
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("Resource.AlreadyAssociated")
client.associate_address(
InstanceId=instance2.id, PublicIp=eip.public_ip, AllowReassociation=True
)
eip.reload()
eip.instance_id.should.equal(instance2.id)
eip.release()
instance1.terminate()
instance2.terminate()
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_reassociate_nic(): def test_eip_reassociate_nic():
"""reassociate EIP""" """reassociate EIP"""
@ -323,6 +576,44 @@ def test_eip_reassociate_nic():
eip = None eip = None
@mock_ec2
def test_eip_reassociate_nic_boto3():
"""reassociate EIP"""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
subnet = client.create_subnet(VpcId=vpc["VpcId"], CidrBlock="10.0.0.0/18")["Subnet"]
eni1 = ec2.create_network_interface(SubnetId=subnet["SubnetId"])
eni2 = ec2.create_network_interface(SubnetId=subnet["SubnetId"])
eip = ec2.ClassicAddress(client.allocate_address()["PublicIp"])
client.associate_address(NetworkInterfaceId=eni1.id, PublicIp=eip.public_ip)
# Same ID is idempotent
client.associate_address(NetworkInterfaceId=eni1.id, PublicIp=eip.public_ip)
eip.reload()
eip.network_interface_id.should.equal(eni1.id)
# Different ID detects resource association
with pytest.raises(ClientError) as ex:
client.associate_address(NetworkInterfaceId=eni2.id, PublicIp=eip.public_ip)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("Resource.AlreadyAssociated")
client.associate_address(
NetworkInterfaceId=eni2.id, PublicIp=eip.public_ip, AllowReassociation=True
)
eip.reload()
eip.network_interface_id.should.equal(eni2.id)
eip.release()
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_associate_invalid_args(): def test_eip_associate_invalid_args():
"""Associate EIP, invalid args""" """Associate EIP, invalid args"""
@ -342,6 +633,27 @@ def test_eip_associate_invalid_args():
instance.terminate() instance.terminate()
@mock_ec2
def test_eip_associate_invalid_args_boto3():
"""Associate EIP, invalid args """
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = ec2.Instance(reservation["Instances"][0]["InstanceId"])
client.allocate_address()
with pytest.raises(ClientError) as ex:
client.associate_address(InstanceId=instance.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
instance.terminate()
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_disassociate_bogus_association(): def test_eip_disassociate_bogus_association():
"""Disassociate bogus EIP""" """Disassociate bogus EIP"""
@ -354,6 +666,19 @@ def test_eip_disassociate_bogus_association():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_eip_disassociate_bogus_association_boto3():
"""Disassociate bogus EIP"""
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.disassociate_address(AssociationId="bogus")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("InvalidAssociationID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_release_bogus_eip(): def test_eip_release_bogus_eip():
"""Release bogus EIP""" """Release bogus EIP"""
@ -366,6 +691,19 @@ def test_eip_release_bogus_eip():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_eip_release_bogus_eip_boto3():
"""Release bogus EIP"""
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.release_address(AllocationId="bogus")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("InvalidAllocationID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_disassociate_arg_error(): def test_eip_disassociate_arg_error():
"""Invalid arguments disassociate address""" """Invalid arguments disassociate address"""
@ -378,6 +716,19 @@ def test_eip_disassociate_arg_error():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_eip_disassociate_arg_error_boto3():
"""Invalid arguments disassociate address"""
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.disassociate_address()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_release_arg_error(): def test_eip_release_arg_error():
"""Invalid arguments release address""" """Invalid arguments release address"""
@ -390,6 +741,19 @@ def test_eip_release_arg_error():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_eip_release_arg_error_boto3():
"""Invalid arguments release address"""
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.release_address()
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_describe(): def test_eip_describe():
"""Listing of allocated Elastic IP Addresses.""" """Listing of allocated Elastic IP Addresses."""
@ -430,6 +794,51 @@ def test_eip_describe():
len(conn.get_all_addresses()).should.be.equal(0) len(conn.get_all_addresses()).should.be.equal(0)
@mock_ec2
def test_eip_describe_boto3():
"""Listing of allocated Elastic IP Addresses."""
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
eips = []
number_of_classic_ips = 2
number_of_vpc_ips = 2
# allocate some IPs
for _ in range(number_of_classic_ips):
eips.append(ec2.ClassicAddress(client.allocate_address()["PublicIp"]))
for _ in range(number_of_vpc_ips):
eip_id = client.allocate_address(Domain="vpc")["AllocationId"]
eips.append(ec2.VpcAddress(eip_id))
eips.should.have.length_of(number_of_classic_ips + number_of_vpc_ips)
# Can we find each one individually?
for eip in eips:
if eip.allocation_id:
lookup_addresses = client.describe_addresses(
AllocationIds=[eip.allocation_id]
)["Addresses"]
else:
lookup_addresses = client.describe_addresses(PublicIps=[eip.public_ip])[
"Addresses"
]
len(lookup_addresses).should.be.equal(1)
lookup_addresses[0]["PublicIp"].should.be.equal(eip.public_ip)
# Can we find first two when we search for them?
lookup_addresses = client.describe_addresses(
PublicIps=[eips[0].public_ip, eips[1].public_ip]
)["Addresses"]
lookup_addresses.should.have.length_of(2)
lookup_addresses[0]["PublicIp"].should.be.equal(eips[0].public_ip)
lookup_addresses[1]["PublicIp"].should.be.equal(eips[1].public_ip)
# Release all IPs
for eip in eips:
eip.release()
client.describe_addresses()["Addresses"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_eip_describe_none(): def test_eip_describe_none():
"""Error when search for bogus IP""" """Error when search for bogus IP"""
@ -442,6 +851,18 @@ def test_eip_describe_none():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_eip_describe_none_boto3():
"""Error when search for bogus IP"""
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.describe_addresses(PublicIps=["256.256.256.256"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("InvalidAddress.NotFound")
@mock_ec2 @mock_ec2
def test_eip_filters(): def test_eip_filters():
service = boto3.resource("ec2", region_name="us-west-1") service = boto3.resource("ec2", region_name="us-west-1")

View File

@ -9,10 +9,11 @@ import boto.ec2
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated, settings
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_elastic_network_interfaces(): def test_elastic_network_interfaces():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -56,6 +57,54 @@ def test_elastic_network_interfaces():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_elastic_network_interfaces_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
with pytest.raises(ClientError) as ex:
ec2.create_network_interface(SubnetId=subnet.id, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set"
)
eni_id = ec2.create_network_interface(SubnetId=subnet.id).id
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni["Groups"].should.have.length_of(0)
eni["PrivateIpAddresses"].should.have.length_of(1)
eni["PrivateIpAddresses"][0]["PrivateIpAddress"].startswith("10.").should.be.true
with pytest.raises(ClientError) as ex:
client.delete_network_interface(NetworkInterfaceId=eni_id, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set"
)
client.delete_network_interface(NetworkInterfaceId=eni_id)
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(0)
with pytest.raises(ClientError) as ex:
client.delete_network_interface(NetworkInterfaceId=eni_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal(
"InvalidNetworkInterfaceID.NotFound"
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_elastic_network_interfaces_subnet_validation(): def test_elastic_network_interfaces_subnet_validation():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -67,6 +116,18 @@ def test_elastic_network_interfaces_subnet_validation():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_elastic_network_interfaces_subnet_validation_boto3():
client = boto3.client("ec2", "us-east-1")
with pytest.raises(ClientError) as ex:
client.create_network_interface(SubnetId="subnet-abcd1234")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidSubnetID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_elastic_network_interfaces_with_private_ip(): def test_elastic_network_interfaces_with_private_ip():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -85,6 +146,28 @@ def test_elastic_network_interfaces_with_private_ip():
eni.private_ip_addresses[0].private_ip_address.should.equal(private_ip) eni.private_ip_addresses[0].private_ip_address.should.equal(private_ip)
@mock_ec2
def test_elastic_network_interfaces_with_private_ip_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
private_ip = "54.0.0.1"
ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress=private_ip)
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni["Groups"].should.have.length_of(0)
eni["PrivateIpAddresses"].should.have.length_of(1)
eni["PrivateIpAddresses"][0]["PrivateIpAddress"].should.equal(private_ip)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_elastic_network_interfaces_with_groups(): def test_elastic_network_interfaces_with_groups():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -110,6 +193,29 @@ def test_elastic_network_interfaces_with_groups():
) )
@mock_ec2
def test_elastic_network_interfaces_with_groups_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
sec_group1 = ec2.create_security_group(GroupName="group #1", Description="n/a")
sec_group2 = ec2.create_security_group(GroupName="group #2", Description="n/a")
subnet.create_network_interface(Groups=[sec_group1.id, sec_group2.id])
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni["Groups"].should.have.length_of(2)
set([group["GroupId"] for group in eni["Groups"]]).should.equal(
set([sec_group1.id, sec_group2.id])
)
# Has boto3 equivalent
@requires_boto_gte("2.12.0") @requires_boto_gte("2.12.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_elastic_network_interfaces_modify_attribute(): def test_elastic_network_interfaces_modify_attribute():
@ -154,6 +260,47 @@ def test_elastic_network_interfaces_modify_attribute():
eni.groups[1].id.should.equal(security_group2.id) eni.groups[1].id.should.equal(security_group2.id)
@mock_ec2
def test_elastic_network_interfaces_modify_attribute_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
sec_group1 = ec2.create_security_group(GroupName="group #1", Description="n/a")
sec_group2 = ec2.create_security_group(GroupName="group #2", Description="n/a")
eni_id = subnet.create_network_interface(Groups=[sec_group1.id]).id
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni["Groups"].should.have.length_of(1)
eni["Groups"][0]["GroupId"].should.equal(sec_group1.id)
with pytest.raises(ClientError) as ex:
client.modify_network_interface_attribute(
NetworkInterfaceId=eni_id, Groups=[sec_group2.id], DryRun=True
)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set"
)
client.modify_network_interface_attribute(
NetworkInterfaceId=eni_id, Groups=[sec_group2.id]
)
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni["Groups"].should.have.length_of(1)
eni["Groups"][0]["GroupId"].should.equal(sec_group2.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_elastic_network_interfaces_filtering(): def test_elastic_network_interfaces_filtering():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -215,6 +362,75 @@ def test_elastic_network_interfaces_filtering():
).should.throw(NotImplementedError) ).should.throw(NotImplementedError)
@mock_ec2
def test_elastic_network_interfaces_filtering_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
sec_group1 = ec2.create_security_group(GroupName="group #1", Description="n/a")
sec_group2 = ec2.create_security_group(GroupName="group #2", Description="n/a")
eni1 = subnet.create_network_interface(Groups=[sec_group1.id, sec_group2.id])
eni2 = subnet.create_network_interface(Groups=[sec_group1.id])
eni3 = subnet.create_network_interface(Description="test description")
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(3)
# Filter by NetworkInterfaceId
enis_by_id = client.describe_network_interfaces(NetworkInterfaceIds=[eni1.id])[
"NetworkInterfaces"
]
enis_by_id.should.have.length_of(1)
set([eni["NetworkInterfaceId"] for eni in enis_by_id]).should.equal(set([eni1.id]))
# Filter by ENI ID
enis_by_id = client.describe_network_interfaces(
Filters=[{"Name": "network-interface-id", "Values": [eni1.id]}]
)["NetworkInterfaces"]
enis_by_id.should.have.length_of(1)
set([eni["NetworkInterfaceId"] for eni in enis_by_id]).should.equal(set([eni1.id]))
# Filter by Security Group
enis_by_group = client.describe_network_interfaces(
Filters=[{"Name": "group-id", "Values": [sec_group1.id]}]
)["NetworkInterfaces"]
enis_by_group.should.have.length_of(2)
set([eni["NetworkInterfaceId"] for eni in enis_by_group]).should.equal(
set([eni1.id, eni2.id])
)
# Filter by ENI ID and Security Group
enis_by_group = client.describe_network_interfaces(
Filters=[
{"Name": "network-interface-id", "Values": [eni1.id]},
{"Name": "group-id", "Values": [sec_group1.id]},
]
)["NetworkInterfaces"]
enis_by_group.should.have.length_of(1)
set([eni["NetworkInterfaceId"] for eni in enis_by_group]).should.equal(
set([eni1.id])
)
# Filter by Description
enis_by_description = client.describe_network_interfaces(
Filters=[{"Name": "description", "Values": [eni3.description]}]
)["NetworkInterfaces"]
enis_by_description.should.have.length_of(1)
enis_by_description[0]["Description"].should.equal(eni3.description)
# Unsupported filter
if not settings.TEST_SERVER_MODE:
# ServerMode will just throw a generic 500
filters = [{"Name": "not-implemented-filter", "Values": ["foobar"]}]
client.describe_network_interfaces.when.called_with(
Filters=filters
).should.throw(NotImplementedError)
@mock_ec2 @mock_ec2
def test_elastic_network_interfaces_get_by_tag_name(): def test_elastic_network_interfaces_get_by_tag_name():
ec2 = boto3.resource("ec2", region_name="us-west-2") ec2 = boto3.resource("ec2", region_name="us-west-2")

View File

@ -5,6 +5,7 @@ import pytest
import boto import boto
import boto3 import boto3
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
@ -12,6 +13,7 @@ from moto import mock_ec2_deprecated, mock_ec2
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_console_output(): def test_console_output():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -21,6 +23,7 @@ def test_console_output():
output.output.should_not.equal(None) output.output.should_not.equal(None)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_console_output_without_instance(): def test_console_output_without_instance():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -39,3 +42,14 @@ def test_console_output_boto3():
output = instances[0].console_output() output = instances[0].console_output()
output.get("Output").should_not.equal(None) output.get("Output").should_not.equal(None)
@mock_ec2
def test_console_output_without_instance_boto3():
client = boto3.client("ec2", "us-east-1")
with pytest.raises(ClientError) as ex:
client.get_console_output(InstanceId="i-1234abcd")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"]["RequestId"].shouldnt.be.none
ex.value.response["Error"]["Code"].should.equal("InvalidInstanceID.NotFound")

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ import boto
import boto3 import boto3
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
@ -19,6 +20,7 @@ BAD_VPC = "vpc-deadbeef"
BAD_IGW = "igw-deadbeef" BAD_IGW = "igw-deadbeef"
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_create(): def test_igw_create():
"""internet gateway create""" """internet gateway create"""
@ -42,6 +44,31 @@ def test_igw_create():
igw.attachments.should.have.length_of(0) igw.attachments.should.have.length_of(0)
@mock_ec2
def test_igw_create_boto3():
""" internet gateway create """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(0)
with pytest.raises(ClientError) as ex:
client.create_internet_gateway(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateInternetGateway operation: Request would have succeeded, but DryRun flag is set"
)
igw = ec2.create_internet_gateway()
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(1)
igw.id.should.match(r"igw-[0-9a-f]+")
igw = client.describe_internet_gateways()["InternetGateways"][0]
igw["Attachments"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_attach(): def test_igw_attach():
"""internet gateway attach""" """internet gateway attach"""
@ -63,6 +90,30 @@ def test_igw_attach():
igw.attachments[0].vpc_id.should.be.equal(vpc.id) igw.attachments[0].vpc_id.should.be.equal(vpc.id)
@mock_ec2
def test_igw_attach_boto3():
""" internet gateway attach """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw = ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
with pytest.raises(ClientError) as ex:
vpc.attach_internet_gateway(InternetGatewayId=igw.id, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the AttachInternetGateway operation: Request would have succeeded, but DryRun flag is set"
)
vpc.attach_internet_gateway(InternetGatewayId=igw.id)
igw = client.describe_internet_gateways()["InternetGateways"][0]
igw["Attachments"].should.equal([{"State": "available", "VpcId": vpc.id}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_attach_bad_vpc(): def test_igw_attach_bad_vpc():
"""internet gateway fail to attach w/ bad vpc""" """internet gateway fail to attach w/ bad vpc"""
@ -76,6 +127,20 @@ def test_igw_attach_bad_vpc():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_attach_bad_vpc_boto3():
""" internet gateway fail to attach w/ bad vpc """
ec2 = boto3.resource("ec2", "us-west-1")
igw = ec2.create_internet_gateway()
with pytest.raises(ClientError) as ex:
igw.attach_to_vpc(VpcId=BAD_VPC)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_attach_twice(): def test_igw_attach_twice():
"""internet gateway fail to attach twice""" """internet gateway fail to attach twice"""
@ -92,6 +157,24 @@ def test_igw_attach_twice():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_attach_twice_boto3():
""" internet gateway fail to attach twice """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
igw = ec2.create_internet_gateway()
vpc1 = ec2.create_vpc(CidrBlock=VPC_CIDR)
vpc2 = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc1.id)
with pytest.raises(ClientError) as ex:
client.attach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc2.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("Resource.AlreadyAssociated")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_detach(): def test_igw_detach():
"""internet gateway detach""" """internet gateway detach"""
@ -113,6 +196,31 @@ def test_igw_detach():
igw.attachments.should.have.length_of(0) igw.attachments.should.have.length_of(0)
@mock_ec2
def test_igw_detach_boto3():
""" internet gateway detach"""
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
igw = ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id)
with pytest.raises(ClientError) as ex:
client.detach_internet_gateway(
InternetGatewayId=igw.id, VpcId=vpc.id, DryRun=True
)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DetachInternetGateway operation: Request would have succeeded, but DryRun flag is set"
)
client.detach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id)
igw = client.describe_internet_gateways()["InternetGateways"][0]
igw["Attachments"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_detach_wrong_vpc(): def test_igw_detach_wrong_vpc():
"""internet gateway fail to detach w/ wrong vpc""" """internet gateway fail to detach w/ wrong vpc"""
@ -129,6 +237,24 @@ def test_igw_detach_wrong_vpc():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_detach_wrong_vpc_boto3():
""" internet gateway fail to detach w/ wrong vpc """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
igw = ec2.create_internet_gateway()
vpc1 = ec2.create_vpc(CidrBlock=VPC_CIDR)
vpc2 = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc1.id)
with pytest.raises(ClientError) as ex:
client.detach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc2.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("Gateway.NotAttached")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_detach_invalid_vpc(): def test_igw_detach_invalid_vpc():
"""internet gateway fail to detach w/ invalid vpc""" """internet gateway fail to detach w/ invalid vpc"""
@ -144,6 +270,23 @@ def test_igw_detach_invalid_vpc():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_detach_invalid_vpc_boto3():
""" internet gateway fail to detach w/ invalid vpc """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
igw = ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id)
with pytest.raises(ClientError) as ex:
client.detach_internet_gateway(InternetGatewayId=igw.id, VpcId=BAD_VPC)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("Gateway.NotAttached")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_detach_unattached(): def test_igw_detach_unattached():
"""internet gateway fail to detach unattached""" """internet gateway fail to detach unattached"""
@ -158,6 +301,22 @@ def test_igw_detach_unattached():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_detach_unattached_boto3():
""" internet gateway fail to detach unattached """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
igw = ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
with pytest.raises(ClientError) as ex:
client.detach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("Gateway.NotAttached")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_delete(): def test_igw_delete():
"""internet gateway delete""" """internet gateway delete"""
@ -179,6 +338,30 @@ def test_igw_delete():
conn.get_all_internet_gateways().should.have.length_of(0) conn.get_all_internet_gateways().should.have.length_of(0)
@mock_ec2
def test_igw_delete_boto3():
""" internet gateway delete"""
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
ec2.create_vpc(CidrBlock=VPC_CIDR)
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(0)
igw = ec2.create_internet_gateway()
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(1)
with pytest.raises(ClientError) as ex:
client.delete_internet_gateway(InternetGatewayId=igw.id, DryRun=True)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteInternetGateway operation: Request would have succeeded, but DryRun flag is set"
)
client.delete_internet_gateway(InternetGatewayId=igw.id)
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_delete_attached(): def test_igw_delete_attached():
"""internet gateway fail to delete attached""" """internet gateway fail to delete attached"""
@ -194,6 +377,23 @@ def test_igw_delete_attached():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_delete_attached_boto3():
""" internet gateway fail to delete attached """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw = ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id)
with pytest.raises(ClientError) as ex:
client.delete_internet_gateway(InternetGatewayId=igw.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("DependencyViolation")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_desribe(): def test_igw_desribe():
"""internet gateway fetch by id""" """internet gateway fetch by id"""
@ -203,6 +403,19 @@ def test_igw_desribe():
igw.id.should.equal(igw_by_search.id) igw.id.should.equal(igw_by_search.id)
@mock_ec2
def test_igw_describe_boto3():
""" internet gateway fetch by id """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw = ec2.create_internet_gateway()
igw_by_search = client.describe_internet_gateways(InternetGatewayIds=[igw.id])[
"InternetGateways"
][0]
igw.id.should.equal(igw_by_search["InternetGatewayId"])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_describe_bad_id(): def test_igw_describe_bad_id():
"""internet gateway fail to fetch by bad id""" """internet gateway fail to fetch by bad id"""
@ -214,6 +427,18 @@ def test_igw_describe_bad_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_igw_describe_bad_id_boto3():
""" internet gateway fail to fetch by bad id """
client = boto3.client("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
client.describe_internet_gateways(InternetGatewayIds=[BAD_IGW])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidInternetGatewayID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_filter_by_vpc_id(): def test_igw_filter_by_vpc_id():
"""internet gateway filter by vpc id""" """internet gateway filter by vpc id"""
@ -229,6 +454,25 @@ def test_igw_filter_by_vpc_id():
result[0].id.should.equal(igw1.id) result[0].id.should.equal(igw1.id)
@mock_ec2
def test_igw_filter_by_vpc_id_boto3():
""" internet gateway filter by vpc id """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw1 = ec2.create_internet_gateway()
ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw1.id, VpcId=vpc.id)
result = client.describe_internet_gateways(
Filters=[{"Name": "attachment.vpc-id", "Values": [vpc.id]}]
)
result["InternetGateways"].should.have.length_of(1)
result["InternetGateways"][0]["InternetGatewayId"].should.equal(igw1.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_filter_by_tags(): def test_igw_filter_by_tags():
"""internet gateway filter by vpc id""" """internet gateway filter by vpc id"""
@ -243,6 +487,24 @@ def test_igw_filter_by_tags():
result[0].id.should.equal(igw1.id) result[0].id.should.equal(igw1.id)
@mock_ec2
def test_igw_filter_by_tags_boto3():
""" internet gateway filter by vpc id """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw1 = ec2.create_internet_gateway()
igw2 = ec2.create_internet_gateway()
igw1.create_tags(Tags=[{"Key": "tests", "Value": "yes"}])
result = client.describe_internet_gateways(
Filters=[{"Name": "tag:tests", "Values": ["yes"]}]
)
result["InternetGateways"].should.have.length_of(1)
result["InternetGateways"][0]["InternetGatewayId"].should.equal(igw1.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_filter_by_internet_gateway_id(): def test_igw_filter_by_internet_gateway_id():
"""internet gateway filter by internet gateway id""" """internet gateway filter by internet gateway id"""
@ -256,6 +518,23 @@ def test_igw_filter_by_internet_gateway_id():
result[0].id.should.equal(igw1.id) result[0].id.should.equal(igw1.id)
@mock_ec2
def test_igw_filter_by_internet_gateway_id_boto3():
""" internet gateway filter by internet gateway id """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw1 = ec2.create_internet_gateway()
igw2 = ec2.create_internet_gateway()
result = client.describe_internet_gateways(
Filters=[{"Name": "internet-gateway-id", "Values": [igw1.id]}]
)
result["InternetGateways"].should.have.length_of(1)
result["InternetGateways"][0]["InternetGatewayId"].should.equal(igw1.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_igw_filter_by_attachment_state(): def test_igw_filter_by_attachment_state():
"""internet gateway filter by attachment state""" """internet gateway filter by attachment state"""
@ -271,6 +550,24 @@ def test_igw_filter_by_attachment_state():
result[0].id.should.equal(igw1.id) result[0].id.should.equal(igw1.id)
@mock_ec2
def test_igw_filter_by_attachment_state_boto3():
""" internet gateway filter by attachment state """
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
igw1 = ec2.create_internet_gateway()
igw2 = ec2.create_internet_gateway()
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw1.id, VpcId=vpc.id)
result = client.describe_internet_gateways(
Filters=[{"Name": "attachment.state", "Values": ["available"]}]
)
result["InternetGateways"].should.have.length_of(1)
result["InternetGateways"][0]["InternetGatewayId"].should.equal(igw1.id)
@mock_ec2 @mock_ec2
def test_create_internet_gateway_with_tags(): def test_create_internet_gateway_with_tags():
ec2 = boto3.resource("ec2", region_name="eu-central-1") ec2 = boto3.resource("ec2", region_name="eu-central-1")

View File

@ -3,10 +3,12 @@ from __future__ import unicode_literals
import pytest import pytest
import boto import boto
import boto3
import sure # noqa import sure # noqa
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from moto import mock_ec2_deprecated from botocore.exceptions import ClientError
from moto import mock_ec2, mock_ec2_deprecated
from .helpers import rsa_check_private_key from .helpers import rsa_check_private_key
@ -44,12 +46,21 @@ ffsm7UIHtCBYERr9Nx0u20ldfhkgB1lhaJb5o0ZJ3pmJ38KChfyHe5EUcqRdEFo89Mp72VI2Z6UHyL17
moto@github.com""" moto@github.com"""
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_empty(): def test_key_pairs_empty():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
assert len(conn.get_all_key_pairs()) == 0 assert len(conn.get_all_key_pairs()) == 0
@mock_ec2
def test_key_pairs_empty_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
client.describe_key_pairs()["KeyPairs"].should.be.empty
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_invalid_id(): def test_key_pairs_invalid_id():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -61,6 +72,19 @@ def test_key_pairs_invalid_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_key_pairs_invalid_id_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
client.describe_key_pairs(KeyNames=["foo"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_create(): def test_key_pairs_create():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -81,6 +105,7 @@ def test_key_pairs_create():
assert kps[0].name == "foo" assert kps[0].name == "foo"
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_create_two(): def test_key_pairs_create_two():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -102,6 +127,43 @@ def test_key_pairs_create_two():
kps[0].name.should.equal("foo") kps[0].name.should.equal("foo")
@mock_ec2
def test_key_pairs_create_dryrun_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
ec2.create_key_pair(KeyName="foo", DryRun=True)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateKeyPair operation: Request would have succeeded, but DryRun flag is set"
)
@mock_ec2
def test_key_pairs_create_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
kp = ec2.create_key_pair(KeyName="foo")
rsa_check_private_key(kp.key_material)
# Verify the client can create a key_pair as well - should behave the same
kp2 = client.create_key_pair(KeyName="foo2")
rsa_check_private_key(kp2["KeyMaterial"])
kp.key_material.shouldnt.equal(kp2["KeyMaterial"])
kps = client.describe_key_pairs()["KeyPairs"]
kps.should.have.length_of(2)
set([k["KeyName"] for k in kps]).should.equal(set(["foo", "foo2"]))
kps = client.describe_key_pairs(KeyNames=["foo"])["KeyPairs"]
kps.should.have.length_of(1)
kps[0].should.have.key("KeyName").equal("foo")
kps[0].should.have.key("KeyFingerprint")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_create_exist(): def test_key_pairs_create_exist():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -115,6 +177,19 @@ def test_key_pairs_create_exist():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_key_pairs_create_exist_boto3():
client = boto3.client("ec2", "us-west-1")
client.create_key_pair(KeyName="foo")
with pytest.raises(ClientError) as ex:
client.create_key_pair(KeyName="foo")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.Duplicate")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_delete_no_exist(): def test_key_pairs_delete_no_exist():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -123,6 +198,14 @@ def test_key_pairs_delete_no_exist():
r.should.be.ok r.should.be.ok
@mock_ec2
def test_key_pairs_delete_no_exist_boto3():
client = boto3.client("ec2", "us-west-1")
client.describe_key_pairs()["KeyPairs"].should.have.length_of(0)
client.delete_key_pair(KeyName="non-existing")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_delete_exist(): def test_key_pairs_delete_exist():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -141,6 +224,25 @@ def test_key_pairs_delete_exist():
assert len(conn.get_all_key_pairs()) == 0 assert len(conn.get_all_key_pairs()) == 0
@mock_ec2
def test_key_pairs_delete_exist_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
client.create_key_pair(KeyName="foo")
with pytest.raises(ClientError) as ex:
client.delete_key_pair(KeyName="foo", DryRun=True)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set"
)
client.delete_key_pair(KeyName="foo")
client.describe_key_pairs()["KeyPairs"].should.equal([])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_import(): def test_key_pairs_import():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -167,6 +269,41 @@ def test_key_pairs_import():
assert kps[1].name == kp2.name assert kps[1].name == kp2.name
@mock_ec2
def test_key_pairs_import_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
client.import_key_pair(
KeyName="foo", PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH, DryRun=True
)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the ImportKeyPair operation: Request would have succeeded, but DryRun flag is set"
)
kp1 = client.import_key_pair(
KeyName="foo", PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH
)
print(kp1)
kp1.should.have.key("KeyName").equal("foo")
kp1.should.have.key("KeyFingerprint").equal(RSA_PUBLIC_KEY_FINGERPRINT)
kp2 = client.import_key_pair(
KeyName="foo2", PublicKeyMaterial=RSA_PUBLIC_KEY_RFC4716
)
kp2.should.have.key("KeyName").equal("foo2")
kp2.should.have.key("KeyFingerprint").equal(RSA_PUBLIC_KEY_FINGERPRINT)
kps = client.describe_key_pairs()["KeyPairs"]
kps.should.have.length_of(2)
kps[0]["KeyName"].should.equal(kp1["KeyName"])
kps[1]["KeyName"].should.equal(kp2["KeyName"])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_import_exist(): def test_key_pairs_import_exist():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -181,6 +318,23 @@ def test_key_pairs_import_exist():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_key_pairs_import_exist_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
kp = client.import_key_pair(KeyName="foo", PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH)
kp["KeyName"].should.equal("foo")
client.describe_key_pairs()["KeyPairs"].should.have.length_of(1)
with pytest.raises(ClientError) as ex:
client.create_key_pair(KeyName="foo")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.Duplicate")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pairs_invalid(): def test_key_pairs_invalid():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -204,6 +358,34 @@ def test_key_pairs_invalid():
ex.value.message.should.equal("Key is not in valid OpenSSH public key format") ex.value.message.should.equal("Key is not in valid OpenSSH public key format")
@mock_ec2
def test_key_pairs_invalid_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
client.import_key_pair(KeyName="foo", PublicKeyMaterial=b"")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidKeyPair.Format")
err["Message"].should.equal("Key is not in valid OpenSSH public key format")
with pytest.raises(ClientError) as ex:
client.import_key_pair(KeyName="foo", PublicKeyMaterial=b"garbage")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidKeyPair.Format")
err["Message"].should.equal("Key is not in valid OpenSSH public key format")
with pytest.raises(ClientError) as ex:
client.import_key_pair(KeyName="foo", PublicKeyMaterial=DSA_PUBLIC_KEY_OPENSSH)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidKeyPair.Format")
err["Message"].should.equal("Key is not in valid OpenSSH public key format")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_key_pair_filters(): def test_key_pair_filters():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -217,3 +399,23 @@ def test_key_pair_filters():
kp_by_name = conn.get_all_key_pairs(filters={"fingerprint": kp3.fingerprint}) kp_by_name = conn.get_all_key_pairs(filters={"fingerprint": kp3.fingerprint})
set([kp.name for kp in kp_by_name]).should.equal(set([kp3.name])) set([kp.name for kp in kp_by_name]).should.equal(set([kp3.name]))
@mock_ec2
def test_key_pair_filters_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
_ = ec2.create_key_pair(KeyName="kpfltr1")
kp2 = ec2.create_key_pair(KeyName="kpfltr2")
kp3 = ec2.create_key_pair(KeyName="kpfltr3")
kp_by_name = client.describe_key_pairs(
Filters=[{"Name": "key-name", "Values": ["kpfltr2"]}]
)["KeyPairs"]
set([kp["KeyName"] for kp in kp_by_name]).should.equal(set([kp2.name]))
kp_by_name = client.describe_key_pairs(
Filters=[{"Name": "fingerprint", "Values": [kp3.key_fingerprint]}]
)["KeyPairs"]
set([kp["KeyName"] for kp in kp_by_name]).should.equal(set([kp3.name]))

View File

@ -9,6 +9,7 @@ from moto import mock_ec2_deprecated, mock_ec2
from moto.ec2.models import OWNER_ID from moto.ec2.models import OWNER_ID
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_default_network_acl_created_with_vpc(): def test_default_network_acl_created_with_vpc():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -17,6 +18,17 @@ def test_default_network_acl_created_with_vpc():
all_network_acls.should.have.length_of(2) all_network_acls.should.have.length_of(2)
@mock_ec2
def test_default_network_acl_created_with_vpc_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
ec2.create_vpc(CidrBlock="10.0.0.0/16")
all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(2)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_network_acls(): def test_network_acls():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -26,6 +38,25 @@ def test_network_acls():
all_network_acls.should.have.length_of(3) all_network_acls.should.have.length_of(3)
@mock_ec2
def test_network_create_and_list_acls_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
created_acl = ec2.create_network_acl(VpcId=vpc.id)
all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(3)
acl_found = [
a for a in all_network_acls if a["NetworkAclId"] == created_acl.network_acl_id
][0]
acl_found["VpcId"].should.equal(vpc.id)
acl_found["Tags"].should.equal([])
acl_found["IsDefault"].should.equal(False)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_new_subnet_associates_with_default_network_acl(): def test_new_subnet_associates_with_default_network_acl():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -40,6 +71,22 @@ def test_new_subnet_associates_with_default_network_acl():
[a.subnet_id for a in acl.associations].should.contain(subnet.id) [a.subnet_id for a in acl.associations].should.contain(subnet.id)
@mock_ec2
def test_new_subnet_associates_with_default_network_acl_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
default_vpc = client.describe_vpcs()["Vpcs"][0]
subnet = ec2.create_subnet(VpcId=default_vpc["VpcId"], CidrBlock="172.31.112.0/20")
all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(1)
acl = all_network_acls[0]
acl["Associations"].should.have.length_of(7)
[a["SubnetId"] for a in acl["Associations"]].should.contain(subnet.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_network_acl_entries(): def test_network_acl_entries():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -69,6 +116,43 @@ def test_network_acl_entries():
entries[0].rule_action.should.equal("ALLOW") entries[0].rule_action.should.equal("ALLOW")
@mock_ec2
def test_network_acl_entries_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
network_acl = ec2.create_network_acl(VpcId=vpc.id)
client.create_network_acl_entry(
NetworkAclId=network_acl.id,
RuleNumber=110,
Protocol="6", # TCP
RuleAction="ALLOW",
CidrBlock="0.0.0.0/0",
Egress=False,
PortRange={"From": 443, "To": 443},
)
all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(3)
test_network_acl = next(
na for na in all_network_acls if na["NetworkAclId"] == network_acl.id
)
test_network_acl.should.have.key("IsDefault").should.equal(False)
entries = test_network_acl["Entries"]
entries.should.have.length_of(1)
entries[0]["RuleNumber"].should.equal(110)
entries[0]["Protocol"].should.equal("6")
entries[0]["RuleAction"].should.equal("ALLOW")
entries[0]["Egress"].should.equal(False)
entries[0]["PortRange"].should.equal({"To": 443, "From": 443})
entries[0]["CidrBlock"].should.equal("0.0.0.0/0")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_network_acl_entry(): def test_delete_network_acl_entry():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -95,6 +179,36 @@ def test_delete_network_acl_entry():
entries.should.have.length_of(0) entries.should.have.length_of(0)
@mock_ec2
def test_delete_network_acl_entry_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
network_acl = ec2.create_network_acl(VpcId=vpc.id)
client.create_network_acl_entry(
NetworkAclId=network_acl.id,
RuleNumber=110,
Protocol="6", # TCP
RuleAction="ALLOW",
CidrBlock="0.0.0.0/0",
Egress=False,
PortRange={"From": 443, "To": 443},
)
client.delete_network_acl_entry(
NetworkAclId=network_acl.id, RuleNumber=110, Egress=False
)
all_network_acls = client.describe_network_acls()["NetworkAcls"]
test_network_acl = next(
na for na in all_network_acls if na["NetworkAclId"] == network_acl.id
)
test_network_acl["Entries"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_replace_network_acl_entry(): def test_replace_network_acl_entry():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -133,6 +247,47 @@ def test_replace_network_acl_entry():
entries[0].rule_action.should.equal("DENY") entries[0].rule_action.should.equal("DENY")
@mock_ec2
def test_replace_network_acl_entry_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
network_acl = ec2.create_network_acl(VpcId=vpc.id)
client.create_network_acl_entry(
NetworkAclId=network_acl.id,
RuleNumber=110,
Protocol="6", # TCP
RuleAction="ALLOW",
CidrBlock="0.0.0.0/0",
Egress=False,
PortRange={"From": 443, "To": 443},
)
client.replace_network_acl_entry(
NetworkAclId=network_acl.id,
RuleNumber=110,
Protocol="-1",
RuleAction="DENY",
CidrBlock="0.0.0.0/0",
Egress=False,
PortRange={"From": 22, "To": 22},
)
all_network_acls = client.describe_network_acls()["NetworkAcls"]
test_network_acl = next(
na for na in all_network_acls if na["NetworkAclId"] == network_acl.id
)
entries = test_network_acl["Entries"]
entries.should.have.length_of(1)
entries[0]["RuleNumber"].should.equal(110)
entries[0]["Protocol"].should.equal("-1")
entries[0]["RuleAction"].should.equal("DENY")
entries[0]["PortRange"].should.equal({"To": 22, "From": 22})
# TODO: How to convert 'associate_network_acl' to boto3?
@mock_ec2_deprecated @mock_ec2_deprecated
def test_associate_new_network_acl_with_subnet(): def test_associate_new_network_acl_with_subnet():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -151,6 +306,7 @@ def test_associate_new_network_acl_with_subnet():
test_network_acl.associations[0].subnet_id.should.equal(subnet.id) test_network_acl.associations[0].subnet_id.should.equal(subnet.id)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_network_acl(): def test_delete_network_acl():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -171,6 +327,29 @@ def test_delete_network_acl():
any(acl.id == network_acl.id for acl in updated_network_acls).shouldnt.be.ok any(acl.id == network_acl.id for acl in updated_network_acls).shouldnt.be.ok
@mock_ec2
def test_delete_network_acl_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
network_acl = ec2.create_network_acl(VpcId=vpc.id)
all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(3)
any(acl["NetworkAclId"] == network_acl.id for acl in all_network_acls).should.be.ok
client.delete_network_acl(NetworkAclId=network_acl.id)
updated_network_acls = client.describe_network_acls()["NetworkAcls"]
updated_network_acls.should.have.length_of(2)
any(
acl["NetworkAclId"] == network_acl.id for acl in updated_network_acls
).shouldnt.be.ok
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_network_acl_tagging(): def test_network_acl_tagging():
conn = boto.connect_vpc("the_key", "the secret") conn = boto.connect_vpc("the_key", "the secret")
@ -189,6 +368,27 @@ def test_network_acl_tagging():
test_network_acl.tags["a key"].should.equal("some value") test_network_acl.tags["a key"].should.equal("some value")
@mock_ec2
def test_network_acl_tagging_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
network_acl = ec2.create_network_acl(VpcId=vpc.id)
network_acl.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("ResourceId").equal(network_acl.id)
tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value")
all_network_acls = client.describe_network_acls()["NetworkAcls"]
test_network_acl = next(
na for na in all_network_acls if na["NetworkAclId"] == network_acl.id
)
test_network_acl["Tags"].should.equal([{"Value": "some value", "Key": "a key"}])
@mock_ec2 @mock_ec2
def test_new_subnet_in_new_vpc_associates_with_default_network_acl(): def test_new_subnet_in_new_vpc_associates_with_default_network_acl():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")

View File

@ -2,10 +2,12 @@ from __future__ import unicode_literals
import boto.ec2 import boto.ec2
import boto.ec2.autoscale import boto.ec2.autoscale
import boto.ec2.elb import boto.ec2.elb
import boto3
import sure import sure
from boto3 import Session from boto3 import Session
from moto import mock_ec2_deprecated, mock_autoscaling_deprecated, mock_elb_deprecated from moto import mock_ec2_deprecated, mock_autoscaling_deprecated, mock_elb_deprecated
from moto import mock_autoscaling, mock_ec2, mock_elb
from moto.ec2 import ec2_backends from moto.ec2 import ec2_backends
from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2 from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2
@ -30,6 +32,12 @@ def add_servers_to_region(ami_id, count, region):
conn.run_instances(ami_id) conn.run_instances(ami_id)
def add_servers_to_region_boto3(ami_id, count, region):
ec2 = boto3.resource("ec2", region_name=region)
ec2.create_instances(ImageId=ami_id, MinCount=count, MaxCount=count)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_add_servers_to_a_single_region(): def test_add_servers_to_a_single_region():
region = "ap-northeast-1" region = "ap-northeast-1"
@ -44,6 +52,21 @@ def test_add_servers_to_a_single_region():
image_ids.should.equal([EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2]) image_ids.should.equal([EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2])
@mock_ec2
def test_add_servers_to_a_single_region_boto3():
region = "ap-northeast-1"
add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region)
add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region)
client = boto3.client("ec2", region_name=region)
reservations = client.describe_instances()["Reservations"]
reservations.should.have.length_of(2)
image_ids = [r["Instances"][0]["ImageId"] for r in reservations]
image_ids.should.equal([EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_add_servers_to_multiple_regions(): def test_add_servers_to_multiple_regions():
region1 = "us-east-1" region1 = "us-east-1"
@ -63,6 +86,26 @@ def test_add_servers_to_multiple_regions():
ap_reservations[0].instances[0].image_id.should.equal(EXAMPLE_AMI_ID2) ap_reservations[0].instances[0].image_id.should.equal(EXAMPLE_AMI_ID2)
@mock_ec2
def test_add_servers_to_multiple_regions_boto3():
region1 = "us-east-1"
region2 = "ap-northeast-1"
add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region1)
add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region2)
us_client = boto3.client("ec2", region_name=region1)
ap_client = boto3.client("ec2", region_name=region2)
us_reservations = us_client.describe_instances()["Reservations"]
ap_reservations = ap_client.describe_instances()["Reservations"]
us_reservations.should.have.length_of(1)
ap_reservations.should.have.length_of(1)
us_reservations[0]["Instances"][0]["ImageId"].should.equal(EXAMPLE_AMI_ID)
ap_reservations[0]["Instances"][0]["ImageId"].should.equal(EXAMPLE_AMI_ID2)
# Has boto3 equivalent
@mock_autoscaling_deprecated @mock_autoscaling_deprecated
@mock_elb_deprecated @mock_elb_deprecated
def test_create_autoscaling_group(): def test_create_autoscaling_group():
@ -161,3 +204,69 @@ def test_create_autoscaling_group():
list(ap_group.termination_policies).should.equal( list(ap_group.termination_policies).should.equal(
["OldestInstance", "NewestInstance"] ["OldestInstance", "NewestInstance"]
) )
@mock_autoscaling
@mock_elb
@mock_ec2
def test_create_autoscaling_group_boto3():
regions = [("us-east-1", "c"), ("ap-northeast-1", "a")]
for region, zone in regions:
a_zone = "{}{}".format(region, zone)
asg_name = "{}_tester_group".format(region)
lb_name = "{}_lb".format(region)
config_name = "{}_tester".format(region)
elb_client = boto3.client("elb", region_name=region)
elb_client.create_load_balancer(
LoadBalancerName=lb_name,
Listeners=[
{"Protocol": "http", "LoadBalancerPort": 80, "InstancePort": 8080}
],
AvailabilityZones=[],
)
as_client = boto3.client("autoscaling", region_name=region)
as_client.create_launch_configuration(
LaunchConfigurationName=config_name,
ImageId=EXAMPLE_AMI_ID,
InstanceType="m1.small",
)
ec2_client = boto3.client("ec2", region_name=region)
subnet_id = ec2_client.describe_subnets(
Filters=[{"Name": "availability-zone", "Values": [a_zone]}]
)["Subnets"][0]["SubnetId"]
as_client.create_auto_scaling_group(
AutoScalingGroupName=asg_name,
AvailabilityZones=[a_zone],
DefaultCooldown=60,
DesiredCapacity=2,
HealthCheckGracePeriod=100,
HealthCheckType="EC2",
LaunchConfigurationName=config_name,
LoadBalancerNames=[lb_name],
MinSize=2,
MaxSize=2,
PlacementGroup="us_test_placement",
VPCZoneIdentifier=subnet_id,
TerminationPolicies=["OldestInstance", "NewestInstance"],
)
groups = as_client.describe_auto_scaling_groups()["AutoScalingGroups"]
groups.should.have.length_of(1)
group = groups[0]
group["AutoScalingGroupName"].should.equal(asg_name)
group["DesiredCapacity"].should.equal(2)
group["MaxSize"].should.equal(2)
group["MinSize"].should.equal(2)
group["VPCZoneIdentifier"].should.equal(subnet_id)
group["LaunchConfigurationName"].should.equal(config_name)
group["DefaultCooldown"].should.equal(60)
group["HealthCheckGracePeriod"].should.equal(100)
group["HealthCheckType"].should.equal("EC2")
group["LoadBalancerNames"].should.equal([lb_name])
group["PlacementGroup"].should.equal("us_test_placement")
group["TerminationPolicies"].should.equal(["OldestInstance", "NewestInstance"])

View File

@ -8,11 +8,12 @@ from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated, settings
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_tables_defaults(): def test_route_tables_defaults():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -38,6 +39,37 @@ def test_route_tables_defaults():
all_route_tables.should.have.length_of(0) all_route_tables.should.have.length_of(0)
@mock_ec2
def test_route_tables_defaults_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
all_route_tables.should.have.length_of(1)
main_route_table = all_route_tables[0]
main_route_table["VpcId"].should.equal(vpc.id)
routes = main_route_table["Routes"]
routes.should.have.length_of(1)
local_route = routes[0]
local_route["GatewayId"].should.equal("local")
local_route["State"].should.equal("active")
local_route["DestinationCidrBlock"].should.equal(vpc.cidr_block)
vpc.delete()
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
all_route_tables.should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_tables_additional(): def test_route_tables_additional():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -78,6 +110,52 @@ def test_route_tables_additional():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_route_tables_additional_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = vpc.create_route_table()
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
all_route_tables.should.have.length_of(2)
all_route_tables[0]["VpcId"].should.equal(vpc.id)
all_route_tables[1]["VpcId"].should.equal(vpc.id)
all_route_table_ids = [r["RouteTableId"] for r in all_route_tables]
all_route_table_ids.should.contain(route_table.route_table_id)
routes = route_table.routes
routes.should.have.length_of(1)
local_route = routes[0]
local_route.gateway_id.should.equal("local")
local_route.state.should.equal("active")
local_route.destination_cidr_block.should.equal(vpc.cidr_block)
with pytest.raises(ClientError) as ex:
client.delete_vpc(VpcId=vpc.id)
ex.value.response["Error"]["Code"].should.equal("DependencyViolation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
client.delete_route_table(RouteTableId=route_table.route_table_id)
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
all_route_tables.should.have.length_of(1)
with pytest.raises(ClientError) as ex:
client.delete_route_table(RouteTableId="rtb-1234abcd")
ex.value.response["Error"]["Code"].should.equal("InvalidRouteTableID.NotFound")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_tables_filters_standard(): def test_route_tables_filters_standard():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -122,6 +200,66 @@ def test_route_tables_filters_standard():
).should.throw(NotImplementedError) ).should.throw(NotImplementedError)
@mock_ec2
def test_route_tables_filters_standard_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table1 = ec2.create_route_table(VpcId=vpc1.id)
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table2 = ec2.create_route_table(VpcId=vpc2.id)
all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(5)
# Filter by main route table
main_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.main", "Values": ["true"]}]
)["RouteTables"]
main_route_tables.should.have.length_of(3)
main_route_table_ids = [
route_table["RouteTableId"] for route_table in main_route_tables
]
main_route_table_ids.should_not.contain(route_table1.id)
main_route_table_ids.should_not.contain(route_table2.id)
# Filter by VPC
vpc1_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc1.id]}]
)["RouteTables"]
vpc1_route_tables.should.have.length_of(2)
vpc1_route_table_ids = [
route_table["RouteTableId"] for route_table in vpc1_route_tables
]
vpc1_route_table_ids.should.contain(route_table1.id)
vpc1_route_table_ids.should_not.contain(route_table2.id)
# Filter by VPC and main route table
vpc2_main_route_tables = client.describe_route_tables(
Filters=[
{"Name": "association.main", "Values": ["true"]},
{"Name": "vpc-id", "Values": [vpc2.id]},
]
)["RouteTables"]
vpc2_main_route_tables.should.have.length_of(1)
vpc2_main_route_table_ids = [
route_table["RouteTableId"] for route_table in vpc2_main_route_tables
]
vpc2_main_route_table_ids.should_not.contain(route_table1.id)
vpc2_main_route_table_ids.should_not.contain(route_table2.id)
# Unsupported filter
if not settings.TEST_SERVER_MODE:
# ServerMode will just throw a generic 500
filters = [{"Name": "not-implemented-filter", "Values": ["foobar"]}]
client.describe_route_tables.when.called_with(Filters=filters).should.throw(
NotImplementedError
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_tables_filters_associations(): def test_route_tables_filters_associations():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -165,6 +303,58 @@ def test_route_tables_filters_associations():
association1_route_tables[0].associations.should.have.length_of(2) association1_route_tables[0].associations.should.have.length_of(2)
@mock_ec2
def test_route_tables_filters_associations_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet1 = vpc.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/24")
subnet2 = vpc.create_subnet(VpcId=vpc.id, CidrBlock="10.0.1.0/24")
subnet3 = vpc.create_subnet(VpcId=vpc.id, CidrBlock="10.0.2.0/24")
route_table1 = ec2.create_route_table(VpcId=vpc.id)
route_table2 = ec2.create_route_table(VpcId=vpc.id)
association_id1 = client.associate_route_table(
RouteTableId=route_table1.id, SubnetId=subnet1.id
)["AssociationId"]
client.associate_route_table(RouteTableId=route_table1.id, SubnetId=subnet2.id)
client.associate_route_table(RouteTableId=route_table2.id, SubnetId=subnet3.id)
all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(4)
# Filter by association ID
association1_route_tables = client.describe_route_tables(
Filters=[
{
"Name": "association.route-table-association-id",
"Values": [association_id1],
}
]
)["RouteTables"]
association1_route_tables.should.have.length_of(1)
association1_route_tables[0]["RouteTableId"].should.equal(route_table1.id)
association1_route_tables[0]["Associations"].should.have.length_of(2)
# Filter by route table ID
route_table2_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.route-table-id", "Values": [route_table2.id]}]
)["RouteTables"]
route_table2_route_tables.should.have.length_of(1)
route_table2_route_tables[0]["RouteTableId"].should.equal(route_table2.id)
route_table2_route_tables[0]["Associations"].should.have.length_of(1)
# Filter by subnet ID
subnet_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.subnet-id", "Values": [subnet1.id]}]
)["RouteTables"]
subnet_route_tables.should.have.length_of(1)
subnet_route_tables[0]["RouteTableId"].should.equal(route_table1.id)
subnet_route_tables[0]["Associations"].should.have.length_of(2)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_table_associations(): def test_route_table_associations():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -231,6 +421,81 @@ def test_route_table_associations():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_route_table_associations_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
route_table = ec2.create_route_table(VpcId=vpc.id)
all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(3)
# Refresh
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
r["Associations"].should.have.length_of(0)
# Associate
association_id = client.associate_route_table(
RouteTableId=route_table.id, SubnetId=subnet.id
)["AssociationId"]
# Refresh
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
r["Associations"].should.have.length_of(1)
r["Associations"][0]["RouteTableAssociationId"].should.equal(association_id)
r["Associations"][0]["Main"].should.equal(True)
r["Associations"][0]["RouteTableId"].should.equal(route_table.id)
r["Associations"][0]["SubnetId"].should.equal(subnet.id)
# Associate is idempotent
association_id_idempotent = client.associate_route_table(
RouteTableId=route_table.id, SubnetId=subnet.id
)["AssociationId"]
association_id_idempotent.should.equal(association_id)
# Error: Attempt delete associated route table.
with pytest.raises(ClientError) as ex:
client.delete_route_table(RouteTableId=route_table.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("DependencyViolation")
# Disassociate
client.disassociate_route_table(AssociationId=association_id)
# Refresh
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
r["Associations"].should.have.length_of(0)
# Error: Disassociate with invalid association ID
with pytest.raises(ClientError) as ex:
client.disassociate_route_table(AssociationId=association_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAssociationID.NotFound")
# Error: Associate with invalid subnet ID
with pytest.raises(ClientError) as ex:
client.associate_route_table(
RouteTableId=route_table.id, SubnetId="subnet-1234abcd"
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidSubnetID.NotFound")
# Error: Associate with invalid route table ID
with pytest.raises(ClientError) as ex:
client.associate_route_table(RouteTableId="rtb-1234abcd", SubnetId=subnet.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidRouteTableID.NotFound")
# Has boto3 equivalent
@requires_boto_gte("2.16.0") @requires_boto_gte("2.16.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_table_replace_route_table_association(): def test_route_table_replace_route_table_association():
@ -308,6 +573,99 @@ def test_route_table_replace_route_table_association():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_route_table_replace_route_table_association_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
route_table1_id = ec2.create_route_table(VpcId=vpc.id).id
route_table2_id = ec2.create_route_table(VpcId=vpc.id).id
all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(4)
# Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
"RouteTables"
][0]
route_table1["Associations"].should.have.length_of(0)
# Associate
association_id1 = client.associate_route_table(
RouteTableId=route_table1_id, SubnetId=subnet.id
)["AssociationId"]
# Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
"RouteTables"
][0]
route_table2 = client.describe_route_tables(RouteTableIds=[route_table2_id])[
"RouteTables"
][0]
# Validate
route_table1["Associations"].should.have.length_of(1)
route_table2["Associations"].should.have.length_of(0)
route_table1["Associations"][0]["RouteTableAssociationId"].should.equal(
association_id1
)
route_table1["Associations"][0]["Main"].should.equal(True)
route_table1["Associations"][0]["RouteTableId"].should.equal(route_table1_id)
route_table1["Associations"][0]["SubnetId"].should.equal(subnet.id)
# Replace Association
association_id2 = client.replace_route_table_association(
AssociationId=association_id1, RouteTableId=route_table2_id
)["NewAssociationId"]
# Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
"RouteTables"
][0]
route_table2 = client.describe_route_tables(RouteTableIds=[route_table2_id])[
"RouteTables"
][0]
# Validate
route_table1["Associations"].should.have.length_of(0)
route_table2["Associations"].should.have.length_of(1)
route_table2["Associations"][0]["RouteTableAssociationId"].should.equal(
association_id2
)
route_table2["Associations"][0]["Main"].should.equal(True)
route_table2["Associations"][0]["RouteTableId"].should.equal(route_table2_id)
route_table2["Associations"][0]["SubnetId"].should.equal(subnet.id)
# Replace Association is idempotent
association_id_idempotent = client.replace_route_table_association(
AssociationId=association_id2, RouteTableId=route_table2_id
)["NewAssociationId"]
association_id_idempotent.should.equal(association_id2)
# Error: Replace association with invalid association ID
with pytest.raises(ClientError) as ex:
client.replace_route_table_association(
AssociationId="rtbassoc-1234abcd", RouteTableId=route_table1_id
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAssociationID.NotFound")
# Error: Replace association with invalid route table ID
with pytest.raises(ClientError) as ex:
client.replace_route_table_association(
AssociationId=association_id2, RouteTableId="rtb-1234abcd"
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidRouteTableID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_route_table_get_by_tag(): def test_route_table_get_by_tag():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -345,6 +703,7 @@ def test_route_table_get_by_tag_boto3():
route_tables[0].tags[0].should.equal({"Key": "Name", "Value": "TestRouteTable"}) route_tables[0].tags[0].should.equal({"Key": "Name", "Value": "TestRouteTable"})
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_routes_additional(): def test_routes_additional():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -395,6 +754,60 @@ def test_routes_additional():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_routes_additional_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
main_route_table.routes.should.have.length_of(1)
igw = ec2.create_internet_gateway()
ROUTE_CIDR = "10.0.0.4/24"
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=igw.id)
main_route_table.routes.should.have.length_of(2)
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
new_routes.should.have.length_of(1)
new_route = new_routes[0]
new_route.gateway_id.should.equal(igw.id)
new_route.instance_id.should.be.none
new_route.state.should.equal("active")
new_route.destination_cidr_block.should.equal(ROUTE_CIDR)
client.delete_route(
RouteTableId=main_route_table.id, DestinationCidrBlock=ROUTE_CIDR
)
main_route_table.reload()
main_route_table.routes.should.have.length_of(1)
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
new_routes.should.have.length_of(0)
with pytest.raises(ClientError) as ex:
client.delete_route(
RouteTableId=main_route_table.id, DestinationCidrBlock=ROUTE_CIDR
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidRoute.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_routes_replace(): def test_routes_replace():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -448,6 +861,78 @@ def test_routes_replace():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_routes_replace_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
# Various route targets
igw = ec2.create_internet_gateway()
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
# Create initial route
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=igw.id)
# Replace...
def get_target_route():
route_table = client.describe_route_tables(RouteTableIds=[main_route_table.id])[
"RouteTables"
][0]
routes = [
route
for route in route_table["Routes"]
if route["DestinationCidrBlock"] != vpc.cidr_block
]
routes.should.have.length_of(1)
return routes[0]
client.replace_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_CIDR,
InstanceId=instance.id,
)
target_route = get_target_route()
target_route.shouldnt.have.key("GatewayId")
target_route["InstanceId"].should.equal(instance.id)
target_route["State"].should.equal("active")
target_route["DestinationCidrBlock"].should.equal(ROUTE_CIDR)
client.replace_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_CIDR,
GatewayId=igw.id,
)
target_route = get_target_route()
target_route["GatewayId"].should.equal(igw.id)
target_route.shouldnt.have.key("InstanceId")
target_route["State"].should.equal("active")
target_route["DestinationCidrBlock"].should.equal(ROUTE_CIDR)
with pytest.raises(ClientError) as ex:
client.replace_route(
RouteTableId="rtb-1234abcd",
DestinationCidrBlock=ROUTE_CIDR,
GatewayId=igw.id,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidRouteTableID.NotFound")
# Has boto3 equivalent
@requires_boto_gte("2.19.0") @requires_boto_gte("2.19.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_routes_not_supported(): def test_routes_not_supported():
@ -471,6 +956,48 @@ def test_routes_not_supported():
).should.throw(NotImplementedError) ).should.throw(NotImplementedError)
@mock_ec2
def test_routes_not_supported_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
main_route_table_id = client.describe_route_tables()["RouteTables"][0][
"RouteTableId"
]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
# Create
with pytest.raises(ClientError) as ex:
client.create_route(
RouteTableId=main_route_table_id,
DestinationCidrBlock=ROUTE_CIDR,
NetworkInterfaceId="eni-1234abcd",
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal(
"InvalidNetworkInterfaceID.NotFound"
)
igw = ec2.create_internet_gateway()
client.create_route(
RouteTableId=main_route_table_id,
DestinationCidrBlock=ROUTE_CIDR,
GatewayId=igw.id,
)
# Replace
if not settings.TEST_SERVER_MODE:
args = {
"RouteTableId": main_route_table.id,
"DestinationCidrBlock": ROUTE_CIDR,
"NetworkInterfaceId": "eni-1234abcd",
}
client.replace_route.when.called_with(**args).should.throw(NotImplementedError)
# Has boto3 equivalent
@requires_boto_gte("2.34.0") @requires_boto_gte("2.34.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_routes_vpc_peering_connection(): def test_routes_vpc_peering_connection():
@ -506,6 +1033,45 @@ def test_routes_vpc_peering_connection():
new_route.destination_cidr_block.should.equal(ROUTE_CIDR) new_route.destination_cidr_block.should.equal(ROUTE_CIDR)
@mock_ec2
def test_routes_vpc_peering_connection_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
peer_vpc = ec2.create_vpc(CidrBlock="11.0.0.0/16")
vpc_pcx = ec2.create_vpc_peering_connection(VpcId=vpc.id, PeerVpcId=peer_vpc.id)
main_route_table.create_route(
DestinationCidrBlock=ROUTE_CIDR, VpcPeeringConnectionId=vpc_pcx.id
)
# Refresh route table
main_route_table.reload()
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
new_routes.should.have.length_of(1)
new_route = new_routes[0]
new_route.gateway_id.should.be.none
new_route.instance_id.should.be.none
new_route.vpc_peering_connection_id.should.equal(vpc_pcx.id)
new_route.state.should.equal("active")
new_route.destination_cidr_block.should.equal(ROUTE_CIDR)
# Has boto3 equivalent
@requires_boto_gte("2.34.0") @requires_boto_gte("2.34.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_routes_vpn_gateway(): def test_routes_vpn_gateway():
@ -535,6 +1101,40 @@ def test_routes_vpn_gateway():
new_route.vpc_peering_connection_id.should.be.none new_route.vpc_peering_connection_id.should.be.none
@mock_ec2
def test_routes_vpn_gateway_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
vpn_gw_id = client.create_vpn_gateway(Type="ipsec.1")["VpnGateway"]["VpnGatewayId"]
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=vpn_gw_id)
main_route_table.reload()
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
new_routes.should.have.length_of(1)
new_route = new_routes[0]
new_route.gateway_id.should.equal(vpn_gw_id)
new_route.instance_id.should.be.none
new_route.vpc_peering_connection_id.should.be.none
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_network_acl_tagging(): def test_network_acl_tagging():
@ -554,6 +1154,27 @@ def test_network_acl_tagging():
test_route_table.tags["a key"].should.equal("some value") test_route_table.tags["a key"].should.equal("some value")
@mock_ec2
def test_network_acl_tagging_boto3():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = ec2.create_route_table(VpcId=vpc.id)
route_table.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("ResourceType").equal("route-table")
tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value")
all_route_tables = client.describe_route_tables()["RouteTables"]
test_route_table = next(
na for na in all_route_tables if na["RouteTableId"] == route_table.id
)
test_route_table["Tags"].should.equal([{"Value": "some value", "Key": "a key"}])
@mock_ec2 @mock_ec2
def test_create_route_with_invalid_destination_cidr_block_parameter(): def test_create_route_with_invalid_destination_cidr_block_parameter():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")

View File

@ -16,6 +16,7 @@ from moto import mock_ec2, mock_ec2_deprecated, settings
from moto.ec2 import ec2_backend from moto.ec2 import ec2_backend
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_and_describe_security_group(): def test_create_and_describe_security_group():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -53,6 +54,41 @@ def test_create_and_describe_security_group():
set(group_names).should.equal(set(["default", "test security group"])) set(group_names).should.equal(set(["default", "test security group"]))
@mock_ec2
def test_create_and_describe_security_group_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
client.create_security_group(GroupName="test", Description="test", DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set"
)
security_group = ec2.create_security_group(
GroupName="test security group", Description="test"
)
security_group.group_name.should.equal("test security group")
security_group.description.should.equal("test")
# Trying to create another group with the same name should throw an error
with pytest.raises(ClientError) as ex:
client.create_security_group(GroupName="test security group", Description="n/a")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.Duplicate")
all_groups = client.describe_security_groups()["SecurityGroups"]
# The default group gets created automatically
all_groups.should.have.length_of(2)
group_names = [group["GroupName"] for group in all_groups]
set(group_names).should.equal(set(["default", "test security group"]))
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_security_group_without_description_raises_error(): def test_create_security_group_without_description_raises_error():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -64,6 +100,18 @@ def test_create_security_group_without_description_raises_error():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_create_security_group_without_description_raises_error_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
with pytest.raises(ClientError) as ex:
ec2.create_security_group(GroupName="test security group", Description="")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("MissingParameter")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_default_security_group(): def test_default_security_group():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -72,6 +120,15 @@ def test_default_security_group():
groups[0].name.should.equal("default") groups[0].name.should.equal("default")
@mock_ec2
def test_default_security_group_boto3():
client = boto3.client("ec2", "us-west-1")
groups = client.describe_security_groups()["SecurityGroups"]
groups.should.have.length_of(1)
groups[0]["GroupName"].should.equal("default")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_and_describe_vpc_security_group(): def test_create_and_describe_vpc_security_group():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -103,6 +160,46 @@ def test_create_and_describe_vpc_security_group():
all_groups[0].name.should.equal("test security group") all_groups[0].name.should.equal("test security group")
@mock_ec2
def test_create_and_describe_vpc_security_group_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
name = "test secgr"
vpc_id = "vpc-5300000c"
security_group = ec2.create_security_group(
GroupName=name, Description="test", VpcId=vpc_id
)
security_group.vpc_id.should.equal(vpc_id)
security_group.group_name.should.equal(name)
security_group.description.should.equal("test")
# Trying to create another group with the same name in the same VPC should
# throw an error
with pytest.raises(ClientError) as ex:
ec2.create_security_group(GroupName=name, Description="n/a", VpcId=vpc_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.Duplicate")
# Trying to create another group in the same name without VPC should pass
ec2.create_security_group(GroupName=name, Description="non-vpc-group")
all_groups = client.describe_security_groups()["SecurityGroups"]
all_groups.should.have.length_of(3) # 1 default, 1 vpc, 1 no-vpc
all_groups = client.describe_security_groups(
Filters=[{"Name": "vpc_id", "Values": [vpc_id]}]
)["SecurityGroups"]
all_groups.should.have.length_of(1)
all_groups[0]["VpcId"].should.equal(vpc_id)
all_groups[0]["GroupName"].should.equal(name)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_two_security_groups_with_same_name_in_different_vpc(): def test_create_two_security_groups_with_same_name_in_different_vpc():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -124,6 +221,26 @@ def test_create_two_security_groups_with_same_name_in_different_vpc():
set(group_names).should.equal(set(["default", "test security group"])) set(group_names).should.equal(set(["default", "test security group"]))
@mock_ec2
def test_create_two_security_groups_with_same_name_in_different_vpc_boto3():
ec2 = boto3.resource("ec2", "us-east-1")
client = boto3.client("ec2", "us-east-1")
name = "test security group"
vpc_id = "vpc-5300000c"
vpc_id2 = "vpc-5300000d"
ec2.create_security_group(GroupName=name, Description="n/a 1", VpcId=vpc_id)
ec2.create_security_group(GroupName=name, Description="n/a 2", VpcId=vpc_id2)
all_groups = client.describe_security_groups()["SecurityGroups"]
all_groups.should.have.length_of(3)
group_names = [group["GroupName"] for group in all_groups]
# The default group is created automatically
set(group_names).should.equal(set(["default", name]))
@mock_ec2 @mock_ec2
def test_create_two_security_groups_in_vpc_with_ipv6_enabled(): def test_create_two_security_groups_in_vpc_with_ipv6_enabled():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
@ -137,6 +254,7 @@ def test_create_two_security_groups_in_vpc_with_ipv6_enabled():
security_group.ip_permissions_egress.should.have.length_of(2) security_group.ip_permissions_egress.should.have.length_of(2)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_deleting_security_groups(): def test_deleting_security_groups():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -169,6 +287,40 @@ def test_deleting_security_groups():
conn.get_all_security_groups().should.have.length_of(1) conn.get_all_security_groups().should.have.length_of(1)
@mock_ec2
def test_deleting_security_groups_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
security_group1 = ec2.create_security_group(GroupName="test1", Description="test1")
ec2.create_security_group(GroupName="test2", Description="test2")
client.describe_security_groups()["SecurityGroups"].should.have.length_of(3)
# Deleting a group that doesn't exist should throw an error
with pytest.raises(ClientError) as ex:
client.delete_security_group(GroupName="foobar")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.NotFound")
# Delete by name
with pytest.raises(ClientError) as ex:
client.delete_security_group(GroupName="test2", DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set"
)
client.delete_security_group(GroupName="test2")
client.describe_security_groups()["SecurityGroups"].should.have.length_of(2)
# Delete by group id
client.delete_security_group(GroupId=security_group1.id)
client.describe_security_groups()["SecurityGroups"].should.have.length_of(1)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_security_group_in_vpc(): def test_delete_security_group_in_vpc():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -179,6 +331,26 @@ def test_delete_security_group_in_vpc():
conn.delete_security_group(group_id=security_group1.id) conn.delete_security_group(group_id=security_group1.id)
@mock_ec2
def test_delete_security_group_in_vpc_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
client.describe_security_groups()["SecurityGroups"].should.have.length_of(1)
group = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId="vpc-12345"
)
client.describe_security_groups()["SecurityGroups"].should.have.length_of(2)
# this should not throw an exception
client.delete_security_group(GroupId=group.id)
client.describe_security_groups()["SecurityGroups"].should.have.length_of(1)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_authorize_ip_range_and_revoke(): def test_authorize_ip_range_and_revoke():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -316,6 +488,126 @@ def test_authorize_ip_range_and_revoke():
egress_security_group.rules_egress.should.have.length_of(1) egress_security_group.rules_egress.should.have.length_of(1)
@mock_ec2
def test_authorize_ip_range_and_revoke_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
security_group = ec2.create_security_group(GroupName="test", Description="test")
with pytest.raises(ClientError) as ex:
security_group.authorize_ingress(
IpProtocol="tcp",
FromPort=22,
ToPort=2222,
CidrIp="123.123.123.123/32",
DryRun=True,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the GrantSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set"
)
ingress_permissions = [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 2222,
"IpRanges": [{"CidrIp": "123.123.123.123/32"}],
}
]
security_group.authorize_ingress(IpPermissions=ingress_permissions)
security_group.ip_permissions.should.have.length_of(1)
security_group.ip_permissions[0]["ToPort"].should.equal(2222)
security_group.ip_permissions[0]["IpProtocol"].should.equal("tcp")
security_group.ip_permissions[0]["IpRanges"].should.equal(
[{"CidrIp": "123.123.123.123/32"}]
)
# Wrong Cidr should throw error
with pytest.raises(ClientError) as ex:
wrong_permissions = copy.deepcopy(ingress_permissions)
wrong_permissions[0]["IpRanges"][0]["CidrIp"] = "123.123.123.122/32"
security_group.revoke_ingress(IpPermissions=wrong_permissions)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidPermission.NotFound")
# Actually revoke
with pytest.raises(ClientError) as ex:
security_group.revoke_ingress(IpPermissions=ingress_permissions, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the RevokeSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set"
)
security_group.revoke_ingress(IpPermissions=ingress_permissions)
security_group.ip_permissions.should.have.length_of(0)
# Test for egress as well
egress_security_group = ec2.create_security_group(
GroupName="testegress", Description="testegress", VpcId="vpc-3432589"
)
egress_permissions = [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 2222,
"IpRanges": [{"CidrIp": "123.123.123.123/32"}],
}
]
with pytest.raises(ClientError) as ex:
egress_security_group.authorize_egress(
IpPermissions=egress_permissions, DryRun=True
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the GrantSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set"
)
egress_security_group.authorize_egress(IpPermissions=egress_permissions)
egress_security_group.ip_permissions_egress[0]["FromPort"].should.equal(22)
egress_security_group.ip_permissions_egress[0]["IpProtocol"].should.equal("tcp")
egress_security_group.ip_permissions_egress[0]["ToPort"].should.equal(2222)
egress_security_group.ip_permissions_egress[0]["IpRanges"].should.equal(
[{"CidrIp": "123.123.123.123/32"}]
)
# Wrong Cidr should throw error
with pytest.raises(ClientError) as ex:
wrong_permissions = copy.deepcopy(egress_permissions)
wrong_permissions[0]["IpRanges"][0]["CidrIp"] = "123.123.123.122/32"
security_group.revoke_egress(IpPermissions=wrong_permissions)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidPermission.NotFound")
# Actually revoke
with pytest.raises(ClientError) as ex:
egress_security_group.revoke_egress(
IpPermissions=egress_permissions, DryRun=True,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the RevokeSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set"
)
egress_security_group.revoke_egress(IpPermissions=egress_permissions)
egress_security_group = client.describe_security_groups()["SecurityGroups"][0]
# There is still the default outbound rule
egress_security_group["IpPermissionsEgress"].should.have.length_of(1)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_authorize_other_group_and_revoke(): def test_authorize_other_group_and_revoke():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -360,6 +652,59 @@ def test_authorize_other_group_and_revoke():
security_group.rules.should.have.length_of(0) security_group.rules.should.have.length_of(0)
@mock_ec2
def test_authorize_other_group_and_revoke_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
security_group = ec2.create_security_group(GroupName="test", Description="test")
other_security_group = ec2.create_security_group(
GroupName="other", Description="other"
)
ec2.create_security_group(GroupName="wrong", Description="wrong")
# Note: Should be easier to use the SourceSecurityGroupNames-parameter, but that's not supported atm
permissions = [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 2222,
"UserIdGroupPairs": [
{
"GroupId": other_security_group.id,
"GroupName": other_security_group.group_name,
"UserId": other_security_group.owner_id,
}
],
}
]
security_group.authorize_ingress(IpPermissions=permissions)
found_sec_group = client.describe_security_groups(GroupNames=["test"])[
"SecurityGroups"
][0]
found_sec_group["IpPermissions"][0]["ToPort"].should.equal(2222)
found_sec_group["IpPermissions"][0]["UserIdGroupPairs"][0]["GroupId"].should.equal(
other_security_group.id
)
# Wrong source group should throw error
with pytest.raises(ClientError) as ex:
wrong_permissions = copy.deepcopy(permissions)
wrong_permissions[0]["UserIdGroupPairs"][0]["GroupId"] = "unknown"
security_group.revoke_ingress(IpPermissions=wrong_permissions)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.NotFound")
# Actually revoke
security_group.revoke_ingress(IpPermissions=permissions)
found_sec_group = client.describe_security_groups(GroupNames=["test"])[
"SecurityGroups"
][0]
found_sec_group["IpPermissions"].should.have.length_of(0)
@mock_ec2 @mock_ec2
def test_authorize_other_group_egress_and_revoke(): def test_authorize_other_group_egress_and_revoke():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
@ -395,6 +740,7 @@ def test_authorize_other_group_egress_and_revoke():
sg01.ip_permissions_egress.should.have.length_of(1) sg01.ip_permissions_egress.should.have.length_of(1)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_authorize_group_in_vpc(): def test_authorize_group_in_vpc():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -435,6 +781,56 @@ def test_authorize_group_in_vpc():
security_group.rules.should.have.length_of(0) security_group.rules.should.have.length_of(0)
@mock_ec2
def test_authorize_group_in_vpc_boto3():
ec2 = boto3.resource("ec2", "ap-south-1")
client = boto3.client("ec2", region_name="ap-south-1")
vpc_id = "vpc-12345"
# create 2 groups in a vpc
security_group = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId=vpc_id
)
other_security_group = ec2.create_security_group(
GroupName="test2", Description="test2", VpcId=vpc_id
)
permissions = [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 2222,
"UserIdGroupPairs": [
{
"GroupId": other_security_group.id,
"GroupName": other_security_group.group_name,
"UserId": other_security_group.owner_id,
}
],
}
]
security_group.authorize_ingress(IpPermissions=permissions)
# Check that the rule is accurate
found_sec_group = client.describe_security_groups(GroupNames=["test1"])[
"SecurityGroups"
][0]
found_sec_group["IpPermissions"][0]["ToPort"].should.equal(2222)
found_sec_group["IpPermissions"][0]["UserIdGroupPairs"][0]["GroupId"].should.equal(
other_security_group.id
)
# Now remove the rule
security_group.revoke_ingress(IpPermissions=permissions)
# And check that it gets revoked
found_sec_group = client.describe_security_groups(GroupNames=["test1"])[
"SecurityGroups"
][0]
found_sec_group["IpPermissions"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_security_groups(): def test_get_all_security_groups():
conn = boto.connect_ec2() conn = boto.connect_ec2()
@ -472,6 +868,43 @@ def test_get_all_security_groups():
resp.should.have.length_of(3) resp.should.have.length_of(3)
@mock_ec2
def test_describe_security_groups():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
vpc_id = "vpc-mjm05d27"
sg1 = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId=vpc_id
)
ec2.create_security_group(GroupName="test2", Description="test2")
resp = client.describe_security_groups(GroupNames=["test1"])["SecurityGroups"]
resp.should.have.length_of(1)
resp[0].should.have.key("GroupId").equal(sg1.id)
with pytest.raises(ClientError) as ex:
client.describe_security_groups(GroupNames=["does_not_exist"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.NotFound")
resp = client.describe_security_groups(
Filters=[{"Name": "vpc-id", "Values": [vpc_id]}]
)["SecurityGroups"]
resp.should.have.length_of(1)
resp[0].should.have.key("GroupId").equal(sg1.id)
resp = client.describe_security_groups(
Filters=[{"Name": "description", "Values": ["test1"]}]
)["SecurityGroups"]
resp.should.have.length_of(1)
resp[0].should.have.key("GroupId").equal(sg1.id)
resp = client.describe_security_groups()["SecurityGroups"]
resp.should.have.length_of(3)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_authorize_bad_cidr_throws_invalid_parameter_value(): def test_authorize_bad_cidr_throws_invalid_parameter_value():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -485,6 +918,26 @@ def test_authorize_bad_cidr_throws_invalid_parameter_value():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_authorize_bad_cidr_throws_invalid_parameter_value_boto3():
ec2 = boto3.resource("ec2", "us-west-1")
sec_group = ec2.create_security_group(GroupName="test", Description="test")
with pytest.raises(ClientError) as ex:
permissions = [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 2222,
"IpRanges": [{"CidrIp": "123.123.123.123"}],
}
]
sec_group.authorize_ingress(IpPermissions=permissions)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidParameterValue")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_security_group_tagging(): def test_security_group_tagging():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -511,6 +964,7 @@ def test_security_group_tagging():
group.tags["Test"].should.equal("Tag") group.tags["Test"].should.equal("Tag")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_security_group_tag_filtering(): def test_security_group_tag_filtering():
conn = boto.connect_ec2() conn = boto.connect_ec2()
@ -521,6 +975,25 @@ def test_security_group_tag_filtering():
groups.should.have.length_of(1) groups.should.have.length_of(1)
@mock_ec2
def test_security_group_tag_filtering_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
sg = ec2.create_security_group(GroupName="test-sg", Description="Test SG")
sg.create_tags(Tags=[{"Key": "test-tag", "Value": "test-value"}])
groups = client.describe_security_groups(
Filters=[{"Name": "tag:test-tag", "Values": ["test-value"]}]
)["SecurityGroups"]
groups.should.have.length_of(1)
groups = client.describe_security_groups(
Filters=[{"Name": "tag:test-tag", "Values": ["unknown"]}]
)["SecurityGroups"]
groups.should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_authorize_all_protocols_with_no_port_specification(): def test_authorize_all_protocols_with_no_port_specification():
conn = boto.connect_ec2() conn = boto.connect_ec2()
@ -534,6 +1007,24 @@ def test_authorize_all_protocols_with_no_port_specification():
sg.rules[0].to_port.should.equal(None) sg.rules[0].to_port.should.equal(None)
@mock_ec2
def test_authorize_all_protocols_with_no_port_specification_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
sg = ec2.create_security_group(GroupName="test", Description="test")
permissions = [{"IpProtocol": "-1", "IpRanges": [{"CidrIp": "0.0.0.0/0"}]}]
sg.authorize_ingress(IpPermissions=permissions)
sg = client.describe_security_groups(GroupNames=["test"])["SecurityGroups"][0]
permission = sg["IpPermissions"][0]
permission.should.have.key("IpProtocol").equal("-1")
permission.should.have.key("IpRanges").equal([{"CidrIp": "0.0.0.0/0"}])
permission.shouldnt.have.key("FromPort")
permission.shouldnt.have.key("ToPort")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_sec_group_rule_limit(): def test_sec_group_rule_limit():
ec2_conn = boto.connect_ec2() ec2_conn = boto.connect_ec2()
@ -599,6 +1090,123 @@ def test_sec_group_rule_limit():
cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded") cm.value.error_code.should.equal("RulesPerSecurityGroupLimitExceeded")
@mock_ec2
@pytest.mark.parametrize(
"use_vpc", [True, False], ids=["Use VPC", "Without VPC"],
)
def test_sec_group_rule_limit_boto3(use_vpc):
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
limit = 60
if use_vpc:
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg = ec2.create_security_group(
GroupName="test", Description="test", VpcId=vpc.id
)
other_sg = ec2.create_security_group(
GroupName="test_2", Description="test_other", VpcId=vpc.id
)
else:
sg = ec2.create_security_group(GroupName="test", Description="test")
other_sg = ec2.create_security_group(
GroupName="test_2", Description="test_other"
)
# INGRESS
with pytest.raises(ClientError) as ex:
ip_permissions = [
{
"IpProtocol": "-1",
"IpRanges": [{"CidrIp": "{}.0.0.0/0".format(i)} for i in range(110)],
}
]
client.authorize_security_group_ingress(
GroupId=sg.id, IpPermissions=ip_permissions
)
ex.value.response["Error"]["Code"].should.equal(
"RulesPerSecurityGroupLimitExceeded"
)
sg.reload()
sg.ip_permissions.should.be.empty
# authorize a rule targeting a different sec group (because this count too)
other_permissions = [
{
"IpProtocol": "-1",
"UserIdGroupPairs": [
{
"GroupId": other_sg.id,
"GroupName": other_sg.group_name,
"UserId": other_sg.owner_id,
}
],
}
]
client.authorize_security_group_ingress(
GroupId=sg.id, IpPermissions=other_permissions
)
# fill the rules up the limit
permissions = [
{
"IpProtocol": "-1",
"IpRanges": [{"CidrIp": "{}.0.0.0/0".format(i)} for i in range(limit - 1)],
}
]
client.authorize_security_group_ingress(GroupId=sg.id, IpPermissions=permissions)
# verify that we cannot authorize past the limit for a CIDR IP
with pytest.raises(ClientError) as ex:
permissions = [{"IpProtocol": "-1", "IpRanges": [{"CidrIp": "100.0.0.0/0"}],}]
client.authorize_security_group_ingress(
GroupId=sg.id, IpPermissions=permissions
)
ex.value.response["Error"]["Code"].should.equal(
"RulesPerSecurityGroupLimitExceeded"
)
# verify that we cannot authorize past the limit for a different sec group
with pytest.raises(ClientError) as ex:
client.authorize_security_group_ingress(
GroupId=sg.id, IpPermissions=other_permissions
)
ex.value.response["Error"]["Code"].should.equal(
"RulesPerSecurityGroupLimitExceeded"
)
# EGRESS
# authorize a rule targeting a different sec group (because this count too)
client.authorize_security_group_egress(
GroupId=sg.id, IpPermissions=other_permissions
)
# fill the rules up the limit
# remember that by default, when created a sec group contains 1 egress rule
# so our other_sg rule + 98 CIDR IP rules + 1 by default == 100 the limit
permissions = [
{
"IpProtocol": "-1",
"IpRanges": [
{"CidrIp": "{}.0.0.0/0".format(i)} for i in range(1, limit - 1)
],
}
]
client.authorize_security_group_egress(GroupId=sg.id, IpPermissions=permissions)
# verify that we cannot authorize past the limit for a CIDR IP
with pytest.raises(ClientError) as ex:
permissions = [{"IpProtocol": "-1", "IpRanges": [{"CidrIp": "101.0.0.0/0"}],}]
client.authorize_security_group_egress(GroupId=sg.id, IpPermissions=permissions)
ex.value.response["Error"]["Code"].should.equal(
"RulesPerSecurityGroupLimitExceeded"
)
# verify that we cannot authorize past the limit for a different sec group
with pytest.raises(ClientError) as ex:
client.authorize_security_group_egress(
GroupId=sg.id, IpPermissions=other_permissions
)
ex.value.response["Error"]["Code"].should.equal(
"RulesPerSecurityGroupLimitExceeded"
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_sec_group_rule_limit_vpc(): def test_sec_group_rule_limit_vpc():
ec2_conn = boto.connect_ec2() ec2_conn = boto.connect_ec2()
@ -1013,6 +1621,7 @@ def test_security_group_ingress_without_multirule_after_reload():
assert len(sg_after.ip_permissions) == 1 assert len(sg_after.ip_permissions) == 1
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_security_groups_filter_with_same_vpc_id(): def test_get_all_security_groups_filter_with_same_vpc_id():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -1035,6 +1644,33 @@ def test_get_all_security_groups_filter_with_same_vpc_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_get_all_security_groups_filter_with_same_vpc_id_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc_id = "vpc-5300000c"
security_group = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId=vpc_id
)
security_group2 = ec2.create_security_group(
GroupName="test2", Description="test2", VpcId=vpc_id
)
security_group.vpc_id.should.equal(vpc_id)
security_group2.vpc_id.should.equal(vpc_id)
security_groups = client.describe_security_groups(
GroupIds=[security_group.id], Filters=[{"Name": "vpc-id", "Values": [vpc_id]}]
)["SecurityGroups"]
security_groups.should.have.length_of(1)
with pytest.raises(ClientError) as ex:
client.describe_security_groups(GroupIds=["does_not_exist"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.NotFound")
@mock_ec2 @mock_ec2
def test_revoke_security_group_egress(): def test_revoke_security_group_egress():
ec2 = boto3.resource("ec2", "us-east-1") ec2 = boto3.resource("ec2", "us-east-1")

View File

@ -147,6 +147,7 @@ def test_request_spot_instances_default_arguments():
request.shouldnt.contain("SubnetId") request.shouldnt.contain("SubnetId")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_cancel_spot_instance_request(): def test_cancel_spot_instance_request():
conn = boto.connect_ec2() conn = boto.connect_ec2()
@ -170,6 +171,42 @@ def test_cancel_spot_instance_request():
requests.should.have.length_of(0) requests.should.have.length_of(0)
@mock_ec2
def test_cancel_spot_instance_request_boto3():
client = boto3.client("ec2", region_name="us-west-1")
client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"]
requests.should.have.length_of(1)
request = requests[0]
request.should.have.key("CreateTime")
request.should.have.key("Type").equal("one-time")
request.should.have.key("SpotInstanceRequestId")
request.should.have.key("SpotPrice").equal("0.5")
request["LaunchSpecification"]["ImageId"].should.equal(EXAMPLE_AMI_ID)
with pytest.raises(ClientError) as ex:
client.cancel_spot_instance_requests(
SpotInstanceRequestIds=[request["SpotInstanceRequestId"]], DryRun=True
)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CancelSpotInstance operation: Request would have succeeded, but DryRun flag is set"
)
client.cancel_spot_instance_requests(
SpotInstanceRequestIds=[request["SpotInstanceRequestId"]]
)
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"]
requests.should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_request_spot_instances_fulfilled(): def test_request_spot_instances_fulfilled():
""" """
@ -195,6 +232,36 @@ def test_request_spot_instances_fulfilled():
request.state.should.equal("active") request.state.should.equal("active")
@mock_ec2
def test_request_spot_instances_fulfilled_boto3():
"""
Test that moto correctly fullfills a spot instance request
"""
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
request = client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"]
requests.should.have.length_of(1)
request = requests[0]
request["State"].should.equal("open")
if not settings.TEST_SERVER_MODE:
ec2_backends["us-east-1"].spot_instance_requests[request_id].state = "active"
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"]
requests.should.have.length_of(1)
request = requests[0]
request["State"].should.equal("active")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_tag_spot_instance_request(): def test_tag_spot_instance_request():
""" """
@ -214,6 +281,32 @@ def test_tag_spot_instance_request():
tag_dict.should.equal({"tag1": "value1", "tag2": "value2"}) tag_dict.should.equal({"tag1": "value1", "tag2": "value2"})
@mock_ec2
def test_tag_spot_instance_request_boto3():
"""
Test that moto correctly tags a spot instance request
"""
client = boto3.client("ec2", region_name="us-west-1")
request = client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
client.create_tags(
Resources=[request_id],
Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}],
)
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"]
requests.should.have.length_of(1)
request = requests[0]
request["Tags"].should.have.length_of(2)
request["Tags"].should.contain({"Key": "tag1", "Value": "value1"})
request["Tags"].should.contain({"Key": "tag2", "Value": "value2"})
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_spot_instance_requests_filtering(): def test_get_all_spot_instance_requests_filtering():
""" """
@ -244,6 +337,58 @@ def test_get_all_spot_instance_requests_filtering():
requests.should.have.length_of(1) requests.should.have.length_of(1)
@mock_ec2
def test_get_all_spot_instance_requests_filtering_boto3():
"""
Test that moto correctly filters spot instance requests
"""
client = boto3.client("ec2", region_name="us-west-1")
request1 = client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
request1_id = request1["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
request2 = client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
request2_id = request2["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
client.create_tags(
Resources=[request1_id],
Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}],
)
client.create_tags(
Resources=[request2_id],
Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "wrong"}],
)
requests = client.describe_spot_instance_requests(
Filters=[{"Name": "state", "Values": ["active"]}]
)["SpotInstanceRequests"]
requests.should.have.length_of(0)
requests = client.describe_spot_instance_requests(
Filters=[{"Name": "state", "Values": ["open"]}]
)["SpotInstanceRequests"]
requests.should.have.length_of(3)
requests = client.describe_spot_instance_requests(
Filters=[{"Name": "tag:tag1", "Values": ["value1"]}]
)["SpotInstanceRequests"]
requests.should.have.length_of(2)
requests = client.describe_spot_instance_requests(
Filters=[
{"Name": "tag:tag1", "Values": ["value1"]},
{"Name": "tag:tag2", "Values": ["value2"]},
]
)["SpotInstanceRequests"]
requests.should.have.length_of(1)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_request_spot_instances_setting_instance_id(): def test_request_spot_instances_setting_instance_id():
conn = boto.ec2.connect_to_region("us-east-1") conn = boto.ec2.connect_to_region("us-east-1")
@ -334,3 +479,21 @@ def test_spot_price_history():
response = client.describe_spot_price_history(InstanceTypes=i_types) response = client.describe_spot_price_history(InstanceTypes=i_types)
price = response["SpotPriceHistory"][0] price = response["SpotPriceHistory"][0]
assert price["InstanceType"] in i_types assert price["InstanceType"] in i_types
@mock_ec2
def test_request_spot_instances_setting_instance_id_boto3():
client = boto3.client("ec2", region_name="us-east-1")
request = client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
)
request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
if not settings.TEST_SERVER_MODE:
req = ec2_backends["us-east-1"].spot_instance_requests[request_id]
req.state = "active"
req.instance_id = "i-12345678"
request = client.describe_spot_instance_requests()["SpotInstanceRequests"][0]
assert request["State"] == "active"
assert request["InstanceId"] == "i-12345678"

View File

@ -10,10 +10,11 @@ import pytest
import sure # noqa import sure # noqa
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated, settings
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_subnets(): def test_subnets():
ec2 = boto.connect_ec2("the_key", "the_secret") ec2 = boto.connect_ec2("the_key", "the_secret")
@ -36,6 +37,30 @@ def test_subnets():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_subnets_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
all_subnets = client.describe_subnets()["Subnets"]
nr_of_a_zones = len(client.describe_availability_zones()["AvailabilityZones"])
all_subnets.should.have.length_of(1 + nr_of_a_zones)
client.delete_subnet(SubnetId=subnet.id)
all_subnets = client.describe_subnets()["Subnets"]
all_subnets.should.have.length_of(nr_of_a_zones)
with pytest.raises(ClientError) as ex:
client.delete_subnet(SubnetId=subnet.id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidSubnetID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_subnet_create_vpc_validation(): def test_subnet_create_vpc_validation():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -47,6 +72,18 @@ def test_subnet_create_vpc_validation():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_subnet_create_vpc_validation_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
ec2.create_subnet(VpcId="vpc-abcd1234", CidrBlock="10.0.0.0/18")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_subnet_tagging(): def test_subnet_tagging():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -65,6 +102,25 @@ def test_subnet_tagging():
subnet.tags["a key"].should.equal("some value") subnet.tags["a key"].should.equal("some value")
@mock_ec2
def test_subnet_tagging_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
subnet.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0]
tag["Key"].should.equal("a key")
tag["Value"].should.equal("some value")
# Refresh the subnet
subnet = client.describe_subnets(SubnetIds=[subnet.id])["Subnets"][0]
subnet["Tags"].should.equal([{"Key": "a key", "Value": "some value"}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_subnet_should_have_proper_availability_zone_set(): def test_subnet_should_have_proper_availability_zone_set():
conn = boto.vpc.connect_to_region("us-west-1") conn = boto.vpc.connect_to_region("us-west-1")
@ -73,6 +129,16 @@ def test_subnet_should_have_proper_availability_zone_set():
subnetA.availability_zone.should.equal("us-west-1b") subnetA.availability_zone.should.equal("us-west-1b")
@mock_ec2
def test_subnet_should_have_proper_availability_zone_set_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
vpcA = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnetA = ec2.create_subnet(
VpcId=vpcA.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1b"
)
subnetA.availability_zone.should.equal("us-west-1b")
@mock_ec2 @mock_ec2
def test_availability_zone_in_create_subnet(): def test_availability_zone_in_create_subnet():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
@ -101,6 +167,7 @@ def test_default_subnet():
subnet.map_public_ip_on_launch.shouldnt.be.ok subnet.map_public_ip_on_launch.shouldnt.be.ok
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_non_default_subnet(): def test_non_default_subnet():
vpc_cli = boto.vpc.connect_to_region("us-west-1") vpc_cli = boto.vpc.connect_to_region("us-west-1")
@ -203,6 +270,7 @@ def test_modify_subnet_attribute_validation():
) )
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_subnet_get_by_id(): def test_subnet_get_by_id():
ec2 = boto.ec2.connect_to_region("us-west-1") ec2 = boto.ec2.connect_to_region("us-west-1")
@ -230,6 +298,38 @@ def test_subnet_get_by_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_subnet_get_by_id_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpcA = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnetA = ec2.create_subnet(
VpcId=vpcA.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a"
)
vpcB = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnetB1 = ec2.create_subnet(
VpcId=vpcB.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a"
)
subnetB2 = ec2.create_subnet(
VpcId=vpcB.id, CidrBlock="10.0.1.0/24", AvailabilityZone="us-west-1b"
)
subnets_by_id = client.describe_subnets(SubnetIds=[subnetA.id, subnetB1.id])[
"Subnets"
]
subnets_by_id.should.have.length_of(2)
subnets_by_id = tuple(map(lambda s: s["SubnetId"], subnets_by_id))
subnetA.id.should.be.within(subnets_by_id)
subnetB1.id.should.be.within(subnets_by_id)
with pytest.raises(ClientError) as ex:
client.describe_subnets(SubnetIds=["subnet-does_not_exist"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidSubnetID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_subnets_filtering(): def test_get_subnets_filtering():
ec2 = boto.ec2.connect_to_region("us-west-1") ec2 = boto.ec2.connect_to_region("us-west-1")
@ -305,6 +405,101 @@ def test_get_subnets_filtering():
).should.throw(NotImplementedError) ).should.throw(NotImplementedError)
@mock_ec2
def test_get_subnets_filtering_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpcA = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnetA = ec2.create_subnet(
VpcId=vpcA.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a"
)
vpcB = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnetB1 = ec2.create_subnet(
VpcId=vpcB.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a"
)
subnetB2 = ec2.create_subnet(
VpcId=vpcB.id, CidrBlock="10.0.1.0/24", AvailabilityZone="us-west-1b"
)
nr_of_a_zones = len(client.describe_availability_zones()["AvailabilityZones"])
all_subnets = client.describe_subnets()["Subnets"]
all_subnets.should.have.length_of(3 + nr_of_a_zones)
# Filter by VPC ID
subnets_by_vpc = client.describe_subnets(
Filters=[{"Name": "vpc-id", "Values": [vpcB.id]}]
)["Subnets"]
subnets_by_vpc.should.have.length_of(2)
set([subnet["SubnetId"] for subnet in subnets_by_vpc]).should.equal(
set([subnetB1.id, subnetB2.id])
)
# Filter by CIDR variations
subnets_by_cidr1 = client.describe_subnets(
Filters=[{"Name": "cidr", "Values": ["10.0.0.0/24"]}]
)["Subnets"]
subnets_by_cidr1.should.have.length_of(2)
set([subnet["SubnetId"] for subnet in subnets_by_cidr1]).should.equal(
set([subnetA.id, subnetB1.id])
)
subnets_by_cidr2 = client.describe_subnets(
Filters=[{"Name": "cidr-block", "Values": ["10.0.0.0/24"]}]
)["Subnets"]
subnets_by_cidr2.should.have.length_of(2)
set([subnet["SubnetId"] for subnet in subnets_by_cidr2]).should.equal(
set([subnetA.id, subnetB1.id])
)
subnets_by_cidr3 = client.describe_subnets(
Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/24"]}]
)["Subnets"]
subnets_by_cidr3.should.have.length_of(2)
set([subnet["SubnetId"] for subnet in subnets_by_cidr3]).should.equal(
set([subnetA.id, subnetB1.id])
)
# Filter by VPC ID and CIDR
subnets_by_vpc_and_cidr = client.describe_subnets(
Filters=[
{"Name": "vpc-id", "Values": [vpcB.id]},
{"Name": "cidr", "Values": ["10.0.0.0/24"]},
]
)["Subnets"]
subnets_by_vpc_and_cidr.should.have.length_of(1)
subnets_by_vpc_and_cidr[0]["SubnetId"].should.equal(subnetB1.id)
# Filter by subnet ID
subnets_by_id = client.describe_subnets(
Filters=[{"Name": "subnet-id", "Values": [subnetA.id]}]
)["Subnets"]
subnets_by_id.should.have.length_of(1)
subnets_by_id[0]["SubnetId"].should.equal(subnetA.id)
# Filter by availabilityZone
subnets_by_az = client.describe_subnets(
Filters=[
{"Name": "availabilityZone", "Values": ["us-west-1a"]},
{"Name": "vpc-id", "Values": [vpcB.id]},
]
)["Subnets"]
subnets_by_az.should.have.length_of(1)
subnets_by_az[0]["SubnetId"].should.equal(subnetB1.id)
# Filter by defaultForAz
subnets_by_az = client.describe_subnets(
Filters=[{"Name": "defaultForAz", "Values": ["true"]}]
)["Subnets"]
subnets_by_az.should.have.length_of(nr_of_a_zones)
# Unsupported filter
if not settings.TEST_SERVER_MODE:
filters = [{"Name": "not-implemented-filter", "Values": ["foobar"]}]
client.describe_subnets.when.called_with(Filters=filters).should.throw(
NotImplementedError
)
@mock_ec2 @mock_ec2
def test_create_subnet_response_fields(): def test_create_subnet_response_fields():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")

View File

@ -15,6 +15,7 @@ import pytest
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_add_tag(): def test_add_tag():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -39,6 +40,33 @@ def test_add_tag():
existing_instance.tags["a key"].should.equal("some value") existing_instance.tags["a key"].should.equal("some value")
@mock_ec2
def test_instance_create_tags():
ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
with pytest.raises(ClientError) as ex:
instance.create_tags(
Tags=[{"Key": "a key", "Value": "some value"}], DryRun=True
)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set"
)
instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
chain = itertools.chain.from_iterable
existing_instances = list(
chain([res["Instances"] for res in client.describe_instances()["Reservations"]])
)
existing_instances.should.have.length_of(1)
existing_instance = existing_instances[0]
existing_instance["Tags"].should.equal([{"Key": "a key", "Value": "some value"}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_remove_tag(): def test_remove_tag():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -68,6 +96,40 @@ def test_remove_tag():
instance.remove_tag("a key", "some value") instance.remove_tag("a key", "some value")
@mock_ec2
def test_instance_delete_tags():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tags = client.describe_tags()["Tags"]
tag = tags[0]
tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value")
with pytest.raises(ClientError) as ex:
instance.delete_tags(DryRun=True)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set"
)
# Specifying key only
instance.delete_tags(Tags=[{"Key": "a key"}])
client.describe_tags()["Tags"].should.have.length_of(0)
instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
client.describe_tags()["Tags"].should.have.length_of(1)
# Specifying key and value
instance.delete_tags(Tags=[{"Key": "a key", "Value": "some value"}])
client.describe_tags()["Tags"].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_tags(): def test_get_all_tags():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -82,6 +144,7 @@ def test_get_all_tags():
tag.value.should.equal("some value") tag.value.should.equal("some value")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_tags_with_special_characters(): def test_get_all_tags_with_special_characters():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -96,6 +159,20 @@ def test_get_all_tags_with_special_characters():
tag.value.should.equal("some<> value") tag.value.should.equal("some<> value")
@mock_ec2
def test_get_all_tags_with_special_characters_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
instance.create_tags(Tags=[{"Key": "a key", "Value": "some<> value"}])
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some<> value")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_tags(): def test_create_tags():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -123,6 +200,40 @@ def test_create_tags():
) )
@mock_ec2
def test_create_tags_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
tag_list = [
{"Key": "a key", "Value": "some value"},
{"Key": "another key", "Value": "some other value"},
{"Key": "blank key", "Value": ""},
]
with pytest.raises(ClientError) as ex:
client.create_tags(Resources=[instance.id], Tags=tag_list, DryRun=True)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set"
)
client.create_tags(Resources=[instance.id], Tags=tag_list)
tags = client.describe_tags()["Tags"]
tags.should.have.length_of(3)
for expected_tag in tag_list:
tags.should.contain(
{
"Key": expected_tag["Key"],
"ResourceId": instance.id,
"ResourceType": "instance",
"Value": expected_tag["Value"],
}
)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_tag_limit_exceeded(): def test_tag_limit_exceeded():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -152,6 +263,35 @@ def test_tag_limit_exceeded():
tag.value.should.equal("a value") tag.value.should.equal("a value")
@mock_ec2
def test_tag_limit_exceeded_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
tag_list = []
for i in range(51):
tag_list.append({"Key": "{0:02d}".format(i + 1), "Value": ""})
with pytest.raises(ClientError) as ex:
client.create_tags(Resources=[instance.id], Tags=tag_list)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("TagLimitExceeded")
instance.create_tags(Tags=[{"Key": "a key", "Value": "a value"}])
with pytest.raises(ClientError) as ex:
client.create_tags(Resources=[instance.id], Tags=tag_list)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("TagLimitExceeded")
tags = client.describe_tags()["Tags"]
tags.should.have.length_of(1)
tags[0].should.have.key("Key").equal("a key")
tags[0].should.have.key("Value").equal("a value")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_invalid_parameter_tag_null(): def test_invalid_parameter_tag_null():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -165,6 +305,7 @@ def test_invalid_parameter_tag_null():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_invalid_id(): def test_invalid_id():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -181,6 +322,27 @@ def test_invalid_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_invalid_id_boto3():
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.create_tags(
Resources=["ami-blah"], Tags=[{"Key": "key", "Value": "tag"}]
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidID")
with pytest.raises(ClientError) as ex:
client.create_tags(
Resources=["blah-blah"], Tags=[{"Key": "key", "Value": "tag"}]
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidID")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_tags_resource_id_filter(): def test_get_all_tags_resource_id_filter():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -208,6 +370,59 @@ def test_get_all_tags_resource_id_filter():
tag.value.should.equal("some value") tag.value.should.equal("some value")
@mock_ec2
def test_get_all_tags_resource_filter_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
client.create_tags(
Resources=[instance.id],
Tags=[{"Key": "an instance key", "Value": "some value"}],
)
image = instance.create_image(Name="test-ami", Description="this is a test ami")
image.create_tags(Tags=[{"Key": "an image key", "Value": "some value"}])
expected = {
"Key": "an instance key",
"ResourceId": instance.id,
"ResourceType": "instance",
"Value": "some value",
}
tags = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [instance.id]}]
)["Tags"]
tags.should.equal([expected])
tags = client.describe_tags(
Filters=[{"Name": "resource-type", "Values": ["instance"]}]
)["Tags"]
tags.should.equal([expected])
tags = client.describe_tags(
Filters=[{"Name": "key", "Values": ["an instance key"]}]
)["Tags"]
tags.should.equal([expected])
expected = {
"Key": "an image key",
"ResourceId": image.id,
"ResourceType": "image",
"Value": "some value",
}
tags = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [image.id]}]
)["Tags"]
tags.should.equal([expected])
tags = client.describe_tags(
Filters=[{"Name": "resource-type", "Values": ["image"]}]
)["Tags"]
tags.should.equal([expected])
tags = client.describe_tags(
Filters=[{"Name": "resource-type", "Values": ["unknown"]}]
)["Tags"]
tags.should.equal([])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_tags_resource_type_filter(): def test_get_all_tags_resource_type_filter():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -235,6 +450,7 @@ def test_get_all_tags_resource_type_filter():
tag.value.should.equal("some value") tag.value.should.equal("some value")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_tags_key_filter(): def test_get_all_tags_key_filter():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -254,6 +470,7 @@ def test_get_all_tags_key_filter():
tag.value.should.equal("some value") tag.value.should.equal("some value")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_get_all_tags_value_filter(): def test_get_all_tags_value_filter():
conn = boto.connect_ec2("the_key", "the_secret") conn = boto.connect_ec2("the_key", "the_secret")
@ -298,6 +515,43 @@ def test_get_all_tags_value_filter():
tags.should.have.length_of(1) tags.should.have.length_of(1)
@mock_ec2
def test_get_all_tags_value_filter_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
def create_instance_with_tag(value):
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[
0
]
tag = {"Key": "an instance key", "Value": value}
client.create_tags(Resources=[instance.id], Tags=[tag])
return instance
instance_a = create_instance_with_tag("some value")
instance_b = create_instance_with_tag("some other value")
instance_c = create_instance_with_tag("other value*")
instance_d = create_instance_with_tag("other value**")
instance_e = create_instance_with_tag("other value*?")
image = instance_a.create_image(Name="test-ami", Description="this is a test ami")
image.create_tags(Tags=[{"Key": "an image key", "Value": "some value"}])
def filter_by_value(query, expected):
filter = {"Name": "value", "Values": [query]}
tags = client.describe_tags(Filters=[filter])["Tags"]
set([t["ResourceId"] for t in tags]).should.equal(set(expected))
filter_by_value("some value", [instance_a.id, image.id])
filter_by_value("some*value", [instance_a.id, instance_b.id, image.id])
filter_by_value("*some*value", [instance_a.id, instance_b.id, image.id])
filter_by_value("*some*value*", [instance_a.id, instance_b.id, image.id])
filter_by_value("*value\*", [instance_c.id])
filter_by_value("*value\*\*", [instance_d.id])
filter_by_value("*value\*\?", [instance_e.id])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_retrieved_instances_must_contain_their_tags(): def test_retrieved_instances_must_contain_their_tags():
tag_key = "Tag name" tag_key = "Tag name"
@ -329,6 +583,33 @@ def test_retrieved_instances_must_contain_their_tags():
retrieved_tags[tag_key].should.equal(tag_value) retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2
def test_retrieved_instances_must_contain_their_tags_boto3():
tag_key = "Tag name"
tag_value = "Tag value"
tags_to_be_set = {"Key": tag_key, "Value": tag_value}
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
reservations = client.describe_instances()["Reservations"]
reservations.should.have.length_of(1)
instances = reservations[0]["Instances"]
instances.should.have.length_of(1)
instances[0]["InstanceId"].should.equal(instance.id)
instances[0].shouldnt.have.key("Tags")
client.create_tags(Resources=[instance.id], Tags=[tags_to_be_set])
reservations = client.describe_instances()["Reservations"]
instance = reservations[0]["Instances"][0]
retrieved_tags = instance["Tags"]
# Check whether tag is present with correct value
retrieved_tags.should.equal([{"Key": tag_key, "Value": tag_value}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_retrieved_volumes_must_contain_their_tags(): def test_retrieved_volumes_must_contain_their_tags():
tag_key = "Tag name" tag_key = "Tag name"
@ -352,6 +633,24 @@ def test_retrieved_volumes_must_contain_their_tags():
retrieved_tags[tag_key].should.equal(tag_value) retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2
def test_retrieved_volumes_must_contain_their_tags_boto3():
tag_key = "Tag name"
tag_value = "Tag value"
tags_to_be_set = {"Key": tag_key, "Value": tag_value}
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
volume = ec2.create_volume(Size=80, AvailabilityZone="us-east-1a")
volume.tags.should.be.none
client.create_tags(Resources=[volume.id], Tags=[tags_to_be_set])
volume.reload()
volume.tags.should.equal([{"Key": tag_key, "Value": tag_value}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_retrieved_snapshots_must_contain_their_tags(): def test_retrieved_snapshots_must_contain_their_tags():
tag_key = "Tag name" tag_key = "Tag name"
@ -376,6 +675,24 @@ def test_retrieved_snapshots_must_contain_their_tags():
retrieved_tags[tag_key].should.equal(tag_value) retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2
def test_retrieved_snapshots_must_contain_their_tags_boto3():
tag_key = "Tag name"
tag_value = "Tag value"
tags_to_be_set = {"Key": tag_key, "Value": tag_value}
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
volume = ec2.create_volume(Size=80, AvailabilityZone="eu-west-1a")
snapshot = ec2.create_snapshot(VolumeId=volume.id)
client.create_tags(Resources=[snapshot.id], Tags=[tags_to_be_set])
snapshot = client.describe_snapshots(SnapshotIds=[snapshot.id])["Snapshots"][0]
snapshot["Tags"].should.equal([{"Key": tag_key, "Value": tag_value}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_filter_instances_by_wildcard_tags(): def test_filter_instances_by_wildcard_tags():
conn = boto.connect_ec2( conn = boto.connect_ec2(
@ -398,6 +715,36 @@ def test_filter_instances_by_wildcard_tags():
reservations.should.have.length_of(2) reservations.should.have.length_of(2)
@mock_ec2
def test_filter_instances_by_wildcard_tags_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
reservations = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=2, MaxCount=2)
instance_a, instance_b = reservations
instance_a.create_tags(Tags=[{"Key": "Key1", "Value": "Value1"}])
instance_b.create_tags(Tags=[{"Key": "Key1", "Value": "Value2"}])
res = client.describe_instances(
Filters=[{"Name": "tag:Key1", "Values": ["Value*"]}]
)
res["Reservations"][0]["Instances"].should.have.length_of(2)
res = client.describe_instances(Filters=[{"Name": "tag-key", "Values": ["Key*"]}])
res["Reservations"][0]["Instances"].should.have.length_of(2)
res = client.describe_instances(
Filters=[{"Name": "tag-value", "Values": ["Value*"]}]
)
res["Reservations"][0]["Instances"].should.have.length_of(2)
res = client.describe_instances(
Filters=[{"Name": "tag-value", "Values": ["Value2*"]}]
)
res["Reservations"][0]["Instances"].should.have.length_of(1)
@mock_ec2 @mock_ec2
def test_create_volume_with_tags(): def test_create_volume_with_tags():
client = boto3.client("ec2", "us-west-2") client = boto3.client("ec2", "us-west-2")

View File

@ -1,276 +1,390 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto import boto
import boto3 import boto3
import pytest import pytest
import sure # noqa import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
@mock_ec2_deprecated @mock_ec2
def test_virtual_private_gateways(): def test_attach_unknown_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret") """describe_vpn_gateways attachment.vpc-id filter"""
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a") ec2 = boto3.client("ec2", region_name="us-east-1")
vpn_gateway.should_not.be.none
vpn_gateway.id.should.match(r"vgw-\w+") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
vpn_gateway.type.should.equal("ipsec.1")
vpn_gateway.state.should.equal("available") with pytest.raises(ClientError) as ex:
vpn_gateway.availability_zone.should.equal("us-east-1a") ec2.attach_vpn_gateway(VpcId=vpc["VpcId"], VpnGatewayId="?")
err = ex.value.response["Error"]
err["Message"].should.equal("The virtual private gateway ID '?' does not exist")
@mock_ec2_deprecated err["Code"].should.equal("InvalidVpnGatewayID.NotFound")
def test_describe_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a") @mock_ec2
def test_delete_unknown_vpn_gateway():
vgws = conn.get_all_vpn_gateways() """describe_vpn_gateways attachment.vpc-id filter"""
vgws.should.have.length_of(1)
ec2 = boto3.client("ec2", region_name="us-east-1")
gateway = vgws[0]
gateway.id.should.match(r"vgw-\w+") with pytest.raises(ClientError) as ex:
gateway.id.should.equal(vpn_gateway.id) ec2.delete_vpn_gateway(VpnGatewayId="?")
vpn_gateway.type.should.equal("ipsec.1") err = ex.value.response["Error"]
vpn_gateway.state.should.equal("available") err["Message"].should.equal("The virtual private gateway ID '?' does not exist")
vpn_gateway.availability_zone.should.equal("us-east-1a") err["Code"].should.equal("InvalidVpnGatewayID.NotFound")
@mock_ec2 @mock_ec2
def test_attach_unknown_vpn_gateway(): def test_detach_unknown_vpn_gateway():
"""describe_vpn_gateways attachment.vpc-id filter""" """describe_vpn_gateways attachment.vpc-id filter"""
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
ec2.attach_vpn_gateway(VpcId=vpc["VpcId"], VpnGatewayId="?") ec2.detach_vpn_gateway(VpcId=vpc["VpcId"], VpnGatewayId="?")
err = ex.value.response["Error"] err = ex.value.response["Error"]
err["Message"].should.equal("The virtual private gateway ID '?' does not exist") err["Message"].should.equal("The virtual private gateway ID '?' does not exist")
err["Code"].should.equal("InvalidVpnGatewayID.NotFound") err["Code"].should.equal("InvalidVpnGatewayID.NotFound")
@mock_ec2 @mock_ec2
def test_delete_unknown_vpn_gateway(): def test_describe_vpn_connections_attachment_vpc_id_filter():
"""describe_vpn_gateways attachment.vpc-id filter""" """describe_vpn_gateways attachment.vpc-id filter"""
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex: vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.delete_vpn_gateway(VpnGatewayId="?") vpc_id = vpc["Vpc"]["VpcId"]
err = ex.value.response["Error"] gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
err["Message"].should.equal("The virtual private gateway ID '?' does not exist") gateway_id = gateway["VpnGateway"]["VpnGatewayId"]
err["Code"].should.equal("InvalidVpnGatewayID.NotFound")
ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id)
@mock_ec2 gateways = ec2.describe_vpn_gateways(
def test_detach_unknown_vpn_gateway(): Filters=[{"Name": "attachment.vpc-id", "Values": [vpc_id]}]
"""describe_vpn_gateways attachment.vpc-id filter""" )
ec2 = boto3.client("ec2", region_name="us-east-1") gateways["VpnGateways"].should.have.length_of(1)
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] gateways["VpnGateways"][0]["VpcAttachments"].should.contain(
{"State": "attached", "VpcId": vpc_id}
with pytest.raises(ClientError) as ex: )
ec2.detach_vpn_gateway(VpcId=vpc["VpcId"], VpnGatewayId="?")
err = ex.value.response["Error"]
err["Message"].should.equal("The virtual private gateway ID '?' does not exist") @mock_ec2
err["Code"].should.equal("InvalidVpnGatewayID.NotFound") def test_describe_vpn_connections_state_filter_deatched():
"""describe_vpn_gateways attachment.state filter - don't match detatched"""
@mock_ec2 ec2 = boto3.client("ec2", region_name="us-east-1")
def test_describe_vpn_connections_attachment_vpc_id_filter():
"""describe_vpn_gateways attachment.vpc-id filter""" vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc_id = vpc["Vpc"]["VpcId"]
ec2 = boto3.client("ec2", region_name="us-east-1") gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"]
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc_id = vpc["Vpc"]["VpcId"] ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id)
gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"] gateways = ec2.describe_vpn_gateways(
Filters=[{"Name": "attachment.state", "Values": ["detached"]}]
ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id) )
gateways = ec2.describe_vpn_gateways( gateways["VpnGateways"].should.have.length_of(0)
Filters=[{"Name": "attachment.vpc-id", "Values": [vpc_id]}]
)
# Has boto3 equivalent
gateways["VpnGateways"].should.have.length_of(1) @mock_ec2_deprecated
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id) def test_virtual_private_gateways():
gateways["VpnGateways"][0]["VpcAttachments"].should.contain( conn = boto.connect_vpc("the_key", "the_secret")
{"State": "attached", "VpcId": vpc_id}
) vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vpn_gateway.should_not.be.none
vpn_gateway.id.should.match(r"vgw-\w+")
@mock_ec2 vpn_gateway.type.should.equal("ipsec.1")
def test_describe_vpn_connections_state_filter_attached(): vpn_gateway.state.should.equal("available")
"""describe_vpn_gateways attachment.state filter - match attached""" vpn_gateway.availability_zone.should.equal("us-east-1a")
ec2 = boto3.client("ec2", region_name="us-east-1")
@mock_ec2
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") def test_virtual_private_gateways_boto3():
vpc_id = vpc["Vpc"]["VpcId"] client = boto3.client("ec2", region_name="us-west-1")
gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"] vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a"
ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id) )["VpnGateway"]
gateways = ec2.describe_vpn_gateways( vpn_gateway["VpnGatewayId"].should.match(r"vgw-\w+")
Filters=[{"Name": "attachment.state", "Values": ["attached"]}] vpn_gateway["Type"].should.equal("ipsec.1")
) vpn_gateway["State"].should.equal("available")
vpn_gateway["AvailabilityZone"].should.equal("us-east-1a")
gateways["VpnGateways"].should.have.length_of(1)
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
gateways["VpnGateways"][0]["VpcAttachments"].should.contain( # Has boto3 equivalent
{"State": "attached", "VpcId": vpc_id} @mock_ec2_deprecated
) def test_describe_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
@mock_ec2
def test_describe_vpn_connections_state_filter_deatched(): vgws = conn.get_all_vpn_gateways()
"""describe_vpn_gateways attachment.state filter - don't match detatched""" vgws.should.have.length_of(1)
ec2 = boto3.client("ec2", region_name="us-east-1") gateway = vgws[0]
gateway.id.should.match(r"vgw-\w+")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") gateway.id.should.equal(vpn_gateway.id)
vpc_id = vpc["Vpc"]["VpcId"] vpn_gateway.type.should.equal("ipsec.1")
gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1") vpn_gateway.state.should.equal("available")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"] vpn_gateway.availability_zone.should.equal("us-east-1a")
ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id)
@mock_ec2
gateways = ec2.describe_vpn_gateways( def test_describe_vpn_gateway_boto3():
Filters=[{"Name": "attachment.state", "Values": ["detached"]}] client = boto3.client("ec2", region_name="us-west-1")
) vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a"
gateways["VpnGateways"].should.have.length_of(0) )["VpnGateway"]
vgws = client.describe_vpn_gateways()["VpnGateways"]
@mock_ec2 vgws.should.have.length_of(1)
def test_describe_vpn_connections_id_filter_match():
"""describe_vpn_gateways vpn-gateway-id filter - match correct id""" gateway = vgws[0]
gateway["VpnGatewayId"].should.match(r"vgw-\w+")
ec2 = boto3.client("ec2", region_name="us-east-1") gateway["VpnGatewayId"].should.equal(vpn_gateway["VpnGatewayId"])
# TODO: fixme. This currently returns the ID
gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1") # gateway["Type"].should.equal("ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"] gateway["State"].should.equal("available")
gateway["AvailabilityZone"].should.equal("us-east-1a")
gateways = ec2.describe_vpn_gateways(
Filters=[{"Name": "vpn-gateway-id", "Values": [gateway_id]}]
) @mock_ec2
def test_describe_vpn_connections_state_filter_attached():
gateways["VpnGateways"].should.have.length_of(1) """ describe_vpn_gateways attachment.state filter - match attached """
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
ec2 = boto3.client("ec2", region_name="us-east-1")
@mock_ec2 vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
def test_describe_vpn_connections_id_filter_miss(): vpc_id = vpc["Vpc"]["VpcId"]
"""describe_vpn_gateways vpn-gateway-id filter - don't match""" gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"]
ec2 = boto3.client("ec2", region_name="us-east-1")
ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id)
ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateways = ec2.describe_vpn_gateways(
gateways = ec2.describe_vpn_gateways( Filters=[{"Name": "attachment.state", "Values": ["attached"]}]
Filters=[{"Name": "vpn-gateway-id", "Values": ["unknown_gateway_id"]}] )
)
gateways["VpnGateways"].should.have.length_of(1)
gateways["VpnGateways"].should.have.length_of(0) gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
gateways["VpnGateways"][0]["VpcAttachments"].should.contain(
{"State": "attached", "VpcId": vpc_id}
@mock_ec2 )
def test_describe_vpn_connections_type_filter_match():
"""describe_vpn_gateways type filter - match"""
@mock_ec2
ec2 = boto3.client("ec2", region_name="us-east-1") def test_describe_vpn_connections_id_filter_match():
""" describe_vpn_gateways vpn-gateway-id filter - match correct id """
gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"] ec2 = boto3.client("ec2", region_name="us-east-1")
gateways = ec2.describe_vpn_gateways( gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
Filters=[{"Name": "type", "Values": ["ipsec.1"]}] gateway_id = gateway["VpnGateway"]["VpnGatewayId"]
)
gateways = ec2.describe_vpn_gateways(
gateways["VpnGateways"].should.have.length_of(1) Filters=[{"Name": "vpn-gateway-id", "Values": [gateway_id]}]
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id) )
gateways["VpnGateways"].should.have.length_of(1)
@mock_ec2 gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
def test_describe_vpn_connections_type_filter_miss():
"""describe_vpn_gateways type filter - don't match"""
@mock_ec2
ec2 = boto3.client("ec2", region_name="us-east-1") def test_describe_vpn_connections_id_filter_miss():
""" describe_vpn_gateways vpn-gateway-id filter - don't match """
ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
ec2 = boto3.client("ec2", region_name="us-east-1")
gateways = ec2.describe_vpn_gateways(
Filters=[{"Name": "type", "Values": ["unknown_type"]}] ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
)
gateways = ec2.describe_vpn_gateways(
gateways["VpnGateways"].should.have.length_of(0) Filters=[{"Name": "vpn-gateway-id", "Values": ["unknown_gateway_id"]}]
)
@mock_ec2_deprecated gateways["VpnGateways"].should.have.length_of(0)
def test_vpn_gateway_vpc_attachment():
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16") @mock_ec2
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a") def test_describe_vpn_connections_type_filter_match():
""" describe_vpn_gateways type filter - match """
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
ec2 = boto3.client("ec2", region_name="us-east-1")
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
attachments.should.have.length_of(1) gateway_id = gateway["VpnGateway"]["VpnGatewayId"]
attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached") gateways = ec2.describe_vpn_gateways(
Filters=[{"Name": "type", "Values": ["ipsec.1"]}]
)
@mock_ec2_deprecated
def test_delete_vpn_gateway(): gateways["VpnGateways"].should.have.length_of(1)
conn = boto.connect_vpc("the_key", "the_secret") gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.delete_vpn_gateway(vpn_gateway.id) @mock_ec2
vgws = conn.get_all_vpn_gateways() def test_describe_vpn_connections_type_filter_miss():
vgws.should.have.length_of(1) """ describe_vpn_gateways type filter - don't match """
vgws[0].state.should.equal("deleted")
ec2 = boto3.client("ec2", region_name="us-east-1")
@mock_ec2_deprecated ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
def test_vpn_gateway_tagging():
conn = boto.connect_vpc("the_key", "the_secret") gateways = ec2.describe_vpn_gateways(
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a") Filters=[{"Name": "type", "Values": ["unknown_type"]}]
vpn_gateway.add_tag("a key", "some value") )
tag = conn.get_all_tags()[0] gateways["VpnGateways"].should.have.length_of(0)
tag.name.should.equal("a key")
tag.value.should.equal("some value")
# Has boto3 equivalent
# Refresh the subnet @mock_ec2_deprecated
vpn_gateway = conn.get_all_vpn_gateways()[0] def test_vpn_gateway_vpc_attachment():
vpn_gateway.tags.should.have.length_of(1) conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway.tags["a key"].should.equal("some value") vpc = conn.create_vpc("10.0.0.0/16")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
@mock_ec2_deprecated conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
def test_detach_vpn_gateway():
gateway = conn.get_all_vpn_gateways()[0]
conn = boto.connect_vpc("the_key", "the_secret") attachments = gateway.attachments
vpc = conn.create_vpc("10.0.0.0/16") attachments.should.have.length_of(1)
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a") attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached")
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0] @mock_ec2
attachments = gateway.attachments def test_vpn_gateway_vpc_attachment_boto3():
attachments.should.have.length_of(1) ec2 = boto3.resource("ec2", region_name="us-west-1")
attachments[0].vpc_id.should.equal(vpc.id) client = boto3.client("ec2", region_name="us-west-1")
attachments[0].state.should.equal("attached") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpn_gateway = client.create_vpn_gateway(
conn.detach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id) Type="ipsec.1", AvailabilityZone="us-east-1a"
)["VpnGateway"]
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments client.attach_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"], VpcId=vpc.id)
attachments.should.have.length_of(1)
attachments[0].state.should.equal("detached") gateway = client.describe_vpn_gateways()["VpnGateways"][0]
attachments = gateway["VpcAttachments"]
attachments.should.equal([{"State": "attached", "VpcId": vpc.id}])
# Has boto3 equivalent
@mock_ec2_deprecated
def test_delete_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.delete_vpn_gateway(vpn_gateway.id)
vgws = conn.get_all_vpn_gateways()
vgws.should.have.length_of(1)
vgws[0].state.should.equal("deleted")
@mock_ec2
def test_delete_vpn_gateway_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a"
)["VpnGateway"]
client.delete_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"])
gateways = client.describe_vpn_gateways()["VpnGateways"]
gateways.should.have.length_of(1)
gateways[0].should.have.key("State").equal("deleted")
# Has boto3 equivalent
@mock_ec2_deprecated
def test_vpn_gateway_tagging():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vpn_gateway.add_tag("a key", "some value")
tag = conn.get_all_tags()[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
# Refresh the subnet
vpn_gateway = conn.get_all_vpn_gateways()[0]
vpn_gateway.tags.should.have.length_of(1)
vpn_gateway.tags["a key"].should.equal("some value")
@mock_ec2
def test_vpn_gateway_tagging_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a"
)["VpnGateway"]
client.create_tags(
Resources=[vpn_gateway["VpnGatewayId"]],
Tags=[{"Key": "a key", "Value": "some value"}],
)
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value")
vpn_gateway = client.describe_vpn_gateways()["VpnGateways"][0]
# TODO: Fixme: Tags is currently empty
# vpn_gateway["Tags"].should.equal([{'Key': 'a key', 'Value': 'some value'}])
# Has boto3 equivalent
@mock_ec2_deprecated
def test_detach_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(1)
attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached")
conn.detach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(1)
attachments[0].state.should.equal("detached")
@mock_ec2
def test_detach_vpn_gateway_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a"
)
vpn_gateway = vpn_gateway["VpnGateway"]
client.attach_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"], VpcId=vpc.id)
gateway = client.describe_vpn_gateways()["VpnGateways"][0]
attachments = gateway["VpcAttachments"]
attachments.should.equal([{"State": "attached", "VpcId": vpc.id}])
client.detach_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"], VpcId=vpc.id)
gateway = client.describe_vpn_gateways()["VpnGateways"][0]
attachments = gateway["VpcAttachments"]
attachments.should.equal([{"State": "detached", "VpcId": vpc.id}])

View File

@ -13,6 +13,7 @@ from moto import mock_ec2, mock_ec2_deprecated
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
# Has boto3 equivalent
@requires_boto_gte("2.32.0") @requires_boto_gte("2.32.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_peering_connections(): def test_vpc_peering_connections():
@ -26,6 +27,26 @@ def test_vpc_peering_connections():
return vpc_pcx return vpc_pcx
def create_vpx_pcx(ec2, client):
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
peer_vpc = ec2.create_vpc(CidrBlock="11.0.0.0/16")
vpc_pcx = client.create_vpc_peering_connection(VpcId=vpc.id, PeerVpcId=peer_vpc.id)
vpc_pcx = vpc_pcx["VpcPeeringConnection"]
return vpc_pcx
@mock_ec2
def test_vpc_peering_connections_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc_pcx = create_vpx_pcx(ec2, client)
vpc_pcx.should.have.key("VpcPeeringConnectionId")
vpc_pcx["Status"]["Code"].should.equal("initiating-request")
# Has boto3 equivalent
@requires_boto_gte("2.32.0") @requires_boto_gte("2.32.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_peering_connections_get_all(): def test_vpc_peering_connections_get_all():
@ -38,6 +59,18 @@ def test_vpc_peering_connections_get_all():
all_vpc_pcxs[0]._status.code.should.equal("pending-acceptance") all_vpc_pcxs[0]._status.code.should.equal("pending-acceptance")
@mock_ec2
def test_vpc_peering_connections_get_all_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc_pcx = create_vpx_pcx(ec2, client)
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"]
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]["Status"]["Code"].should.equal("pending-acceptance")
# Has boto3 equivalent
@requires_boto_gte("2.32.0") @requires_boto_gte("2.32.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_peering_connections_accept(): def test_vpc_peering_connections_accept():
@ -58,6 +91,29 @@ def test_vpc_peering_connections_accept():
all_vpc_pcxs[0]._status.code.should.equal("active") all_vpc_pcxs[0]._status.code.should.equal("active")
@mock_ec2
def test_vpc_peering_connections_accept_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc_pcx = create_vpx_pcx(ec2, client)
vpc_pcx_id = vpc_pcx["VpcPeeringConnectionId"]
vpc_pcx = client.accept_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id)
vpc_pcx = vpc_pcx["VpcPeeringConnection"]
vpc_pcx["Status"]["Code"].should.equal("active")
with pytest.raises(ClientError) as ex:
client.reject_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidStateTransition")
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"]
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]["Status"]["Code"].should.equal("active")
# Has boto3 equivalent
@requires_boto_gte("2.32.0") @requires_boto_gte("2.32.0")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_peering_connections_reject(): def test_vpc_peering_connections_reject():
@ -78,6 +134,27 @@ def test_vpc_peering_connections_reject():
all_vpc_pcxs[0]._status.code.should.equal("rejected") all_vpc_pcxs[0]._status.code.should.equal("rejected")
@mock_ec2
def test_vpc_peering_connections_reject_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc_pcx = create_vpx_pcx(ec2, client)
vpc_pcx_id = vpc_pcx["VpcPeeringConnectionId"]
client.reject_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id)
with pytest.raises(ClientError) as ex:
client.accept_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidStateTransition")
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"]
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]["Status"]["Code"].should.equal("rejected")
# Has boto3 equivalent
@requires_boto_gte("2.32.1") @requires_boto_gte("2.32.1")
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_peering_connections_delete(): def test_vpc_peering_connections_delete():
@ -98,6 +175,28 @@ def test_vpc_peering_connections_delete():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_vpc_peering_connections_delete_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc_pcx = create_vpx_pcx(ec2, client)
vpc_pcx_id = vpc_pcx["VpcPeeringConnectionId"]
client.delete_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id)
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"]
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]["Status"]["Code"].should.equal("deleted")
with pytest.raises(ClientError) as ex:
client.delete_vpc_peering_connection(VpcPeeringConnectionId="pcx-1234abcd")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal(
"InvalidVpcPeeringConnectionId.NotFound"
)
@mock_ec2 @mock_ec2
def test_vpc_peering_connections_cross_region(): def test_vpc_peering_connections_cross_region():
# create vpc in us-west-1 and ap-northeast-1 # create vpc in us-west-1 and ap-northeast-1

View File

@ -16,6 +16,7 @@ SAMPLE_DOMAIN_NAME = "example.com"
SAMPLE_NAME_SERVERS = ["10.0.0.6", "10.0.0.7"] SAMPLE_NAME_SERVERS = ["10.0.0.6", "10.0.0.7"]
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpcs(): def test_vpcs():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -37,6 +38,29 @@ def test_vpcs():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_create_and_delete_vpc():
ec2 = boto3.resource("ec2", region_name="eu-north-1")
client = boto3.client("ec2", region_name="eu-north-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc.cidr_block.should.equal("10.0.0.0/16")
all_vpcs = client.describe_vpcs()["Vpcs"]
all_vpcs.should.have.length_of(2)
vpc.delete()
all_vpcs = client.describe_vpcs()["Vpcs"]
all_vpcs.should.have.length_of(1)
with pytest.raises(ClientError) as ex:
client.delete_vpc(VpcId="vpc-1234abcd")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_defaults(): def test_vpc_defaults():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -53,6 +77,28 @@ def test_vpc_defaults():
conn.get_all_security_groups(filters={"vpc-id": [vpc.id]}).should.have.length_of(0) conn.get_all_security_groups(filters={"vpc-id": [vpc.id]}).should.have.length_of(0)
@mock_ec2
def test_vpc_defaults_boto3():
ec2 = boto3.resource("ec2", region_name="eu-north-1")
client = boto3.client("ec2", region_name="eu-north-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
client.describe_vpcs()["Vpcs"].should.have.length_of(2)
client.describe_route_tables()["RouteTables"].should.have.length_of(2)
client.describe_security_groups(Filters=[{"Name": "vpc-id", "Values": [vpc.id]}])[
"SecurityGroups"
].should.have.length_of(1)
vpc.delete()
client.describe_vpcs()["Vpcs"].should.have.length_of(1)
client.describe_route_tables()["RouteTables"].should.have.length_of(1)
client.describe_security_groups(Filters=[{"Name": "vpc-id", "Values": [vpc.id]}])[
"SecurityGroups"
].should.have.length_of(0)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_isdefault_filter(): def test_vpc_isdefault_filter():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -62,6 +108,23 @@ def test_vpc_isdefault_filter():
conn.get_all_vpcs(filters={"isDefault": "true"}).should.have.length_of(1) conn.get_all_vpcs(filters={"isDefault": "true"}).should.have.length_of(1)
@mock_ec2
def test_vpc_isdefault_filter_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
client.describe_vpcs(Filters=[{"Name": "isDefault", "Values": ["true"]}])[
"Vpcs"
].should.have.length_of(1)
vpc.delete()
client.describe_vpcs(Filters=[{"Name": "isDefault", "Values": ["true"]}])[
"Vpcs"
].should.have.length_of(1)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_multiple_vpcs_default_filter(): def test_multiple_vpcs_default_filter():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -74,6 +137,22 @@ def test_multiple_vpcs_default_filter():
vpc[0].cidr_block.should.equal("172.31.0.0/16") vpc[0].cidr_block.should.equal("172.31.0.0/16")
@mock_ec2
def test_multiple_vpcs_default_filter_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
ec2.create_vpc(CidrBlock="10.8.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="192.168.0.0/16")
client.describe_vpcs()["Vpcs"].should.have.length_of(4)
vpc = client.describe_vpcs(Filters=[{"Name": "isDefault", "Values": ["true"]}])[
"Vpcs"
]
vpc.should.have.length_of(1)
vpc[0]["CidrBlock"].should.equal("172.31.0.0/16")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_state_available_filter(): def test_vpc_state_available_filter():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -84,6 +163,22 @@ def test_vpc_state_available_filter():
conn.get_all_vpcs(filters={"state": "available"}).should.have.length_of(2) conn.get_all_vpcs(filters={"state": "available"}).should.have.length_of(2)
@mock_ec2
def test_vpc_state_available_filter_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.1.0.0/16")
client.describe_vpcs(Filters=[{"Name": "state", "Values": ["available"]}])[
"Vpcs"
].should.have.length_of(3)
vpc.delete()
client.describe_vpcs(Filters=[{"Name": "state", "Values": ["available"]}])[
"Vpcs"
].should.have.length_of(2)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_tagging(): def test_vpc_tagging():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -100,6 +195,23 @@ def test_vpc_tagging():
vpc.tags["a key"].should.equal("some value") vpc.tags["a key"].should.equal("some value")
@mock_ec2
def test_vpc_tagging_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value")
# Refresh the vpc
vpc = client.describe_vpcs(VpcIds=[vpc.id])["Vpcs"][0]
vpc["Tags"].should.equal([{"Key": "a key", "Value": "some value"}])
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_id(): def test_vpc_get_by_id():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -120,6 +232,28 @@ def test_vpc_get_by_id():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_vpc_get_by_id_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpcs = client.describe_vpcs(VpcIds=[vpc1.id, vpc2.id])["Vpcs"]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
with pytest.raises(ClientError) as ex:
client.describe_vpcs(VpcIds=["vpc-does_not_exist"])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVpcID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_cidr_block(): def test_vpc_get_by_cidr_block():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -134,6 +268,24 @@ def test_vpc_get_by_cidr_block():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_cidr_block_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpcs = client.describe_vpcs(Filters=[{"Name": "cidr", "Values": ["10.0.0.0/16"]}])[
"Vpcs"
]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_dhcp_options_id(): def test_vpc_get_by_dhcp_options_id():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -152,6 +304,33 @@ def test_vpc_get_by_dhcp_options_id():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_dhcp_options_id_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/24")
client.associate_dhcp_options(DhcpOptionsId=dhcp_options.id, VpcId=vpc1.id)
client.associate_dhcp_options(DhcpOptionsId=dhcp_options.id, VpcId=vpc2.id)
vpcs = client.describe_vpcs(
Filters=[{"Name": "dhcp-options-id", "Values": [dhcp_options.id]}]
)["Vpcs"]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_tag(): def test_vpc_get_by_tag():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -170,6 +349,28 @@ def test_vpc_get_by_tag():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc3.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(Filters=[{"Name": "tag:Name", "Values": ["TestVPC"]}])[
"Vpcs"
]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_tag_key_superset(): def test_vpc_get_by_tag_key_superset():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -190,6 +391,30 @@ def test_vpc_get_by_tag_key_superset():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_key_superset_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc3.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(Filters=[{"Name": "tag-key", "Values": ["Name"]}])[
"Vpcs"
]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_tag_key_subset(): def test_vpc_get_by_tag_key_subset():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -210,6 +435,30 @@ def test_vpc_get_by_tag_key_subset():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_key_subset_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc3.create_tags(Tags=[{"Key": "Test", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(
Filters=[{"Name": "tag-key", "Values": ["Name", "Key"]}]
)["Vpcs"]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_tag_value_superset(): def test_vpc_get_by_tag_value_superset():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -230,6 +479,30 @@ def test_vpc_get_by_tag_value_superset():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_value_superset_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc3.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(Filters=[{"Name": "tag-value", "Values": ["TestVPC"]}])[
"Vpcs"
]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_get_by_tag_value_subset(): def test_vpc_get_by_tag_value_subset():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -249,6 +522,28 @@ def test_vpc_get_by_tag_value_subset():
vpc2.id.should.be.within(vpc_ids) vpc2.id.should.be.within(vpc_ids)
@mock_ec2
def test_vpc_get_by_tag_value_subset_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(
Filters=[{"Name": "tag-value", "Values": ["TestVPC", "TestVPC2"]}]
)["Vpcs"]
vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
@mock_ec2 @mock_ec2
def test_default_vpc(): def test_default_vpc():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
@ -382,6 +677,7 @@ def test_vpc_modify_enable_dns_hostnames():
attr.get("Value").should.be.ok attr.get("Value").should.be.ok
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_vpc_associate_dhcp_options(): def test_vpc_associate_dhcp_options():
conn = boto.connect_vpc() conn = boto.connect_vpc()
@ -394,6 +690,24 @@ def test_vpc_associate_dhcp_options():
dhcp_options.id.should.equal(vpc.dhcp_options_id) dhcp_options.id.should.equal(vpc.dhcp_options_id)
@mock_ec2
def test_vpc_associate_dhcp_options_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
{"Key": "domain-name-servers", "Values": SAMPLE_NAME_SERVERS},
]
)
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
client.associate_dhcp_options(DhcpOptionsId=dhcp_options.id, VpcId=vpc.id)
vpc.reload()
dhcp_options.id.should.equal(vpc.dhcp_options_id)
@mock_ec2 @mock_ec2
def test_associate_vpc_ipv4_cidr_block(): def test_associate_vpc_ipv4_cidr_block():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")

View File

@ -5,10 +5,11 @@ import boto3
import pytest import pytest
import sure # noqa import sure # noqa
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.client import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_vpn_connections(): def test_create_vpn_connections():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -20,6 +21,17 @@ def test_create_vpn_connections():
vpn_connection.type.should.equal("ipsec.1") vpn_connection.type.should.equal("ipsec.1")
@mock_ec2
def test_create_vpn_connections_boto3():
client = boto3.client("ec2", region_name="us-east-1")
vpn_connection = client.create_vpn_connection(
Type="ipsec.1", VpnGatewayId="vgw-0123abcd", CustomerGatewayId="cgw-0123abcd"
)["VpnConnection"]
vpn_connection["VpnConnectionId"].should.match(r"vpn-\w+")
vpn_connection["Type"].should.equal("ipsec.1")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_vpn_connections(): def test_delete_vpn_connections():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -33,6 +45,24 @@ def test_delete_vpn_connections():
list_of_vpn_connections[0].state.should.equal("deleted") list_of_vpn_connections[0].state.should.equal("deleted")
@mock_ec2
def test_delete_vpn_connections_boto3():
client = boto3.client("ec2", region_name="us-east-1")
vpn_connection = client.create_vpn_connection(
Type="ipsec.1", VpnGatewayId="vgw-0123abcd", CustomerGatewayId="cgw-0123abcd"
)["VpnConnection"]
cnx = client.describe_vpn_connections()["VpnConnections"]
cnx.should.have.length_of(1)
client.delete_vpn_connection(VpnConnectionId=vpn_connection["VpnConnectionId"])
cnx = client.describe_vpn_connections()["VpnConnections"]
cnx.should.have.length_of(1)
cnx[0].should.have.key("State").equal("deleted")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_delete_vpn_connections_bad_id(): def test_delete_vpn_connections_bad_id():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")
@ -40,6 +70,17 @@ def test_delete_vpn_connections_bad_id():
conn.delete_vpn_connection("vpn-0123abcd") conn.delete_vpn_connection("vpn-0123abcd")
@mock_ec2
def test_delete_vpn_connections_bad_id_boto3():
client = boto3.client("ec2", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.delete_vpn_connection(VpnConnectionId="vpn-0123abcd")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidVpnConnectionID.NotFound")
# Has boto3 equivalent
@mock_ec2_deprecated @mock_ec2_deprecated
def test_describe_vpn_connections(): def test_describe_vpn_connections():
conn = boto.connect_vpc("the_key", "the_secret") conn = boto.connect_vpc("the_key", "the_secret")