EC2 - SubnetId and NetworkInterfaces cannot both be specified when calling run_instances (#4719)

This commit is contained in:
Bert Blommers 2021-12-24 14:12:57 -01:00 committed by GitHub
parent b0a59fe05e
commit a1bfb6a48e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 9 deletions

View File

@ -49,6 +49,11 @@ class InvalidDHCPOptionsIdError(EC2ClientError):
)
class InvalidParameterCombination(EC2ClientError):
def __init__(self, msg):
super().__init__("InvalidParameterCombination", msg)
class MalformedDHCPOptionsIdError(EC2ClientError):
def __init__(self, dhcp_options_id):
super().__init__(

View File

@ -677,6 +677,8 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
self.id = random_instance_id()
self.lifecycle = kwargs.get("lifecycle")
nics = kwargs.get("nics", {})
launch_template_arg = kwargs.get("launch_template", {})
if launch_template_arg and not image_id:
# the image id from the template should be used
@ -703,6 +705,10 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
self.region_name = kwargs.get("region_name", "us-east-1")
placement = kwargs.get("placement", None)
self.subnet_id = kwargs.get("subnet_id")
if not self.subnet_id:
self.subnet_id = next(
(n["SubnetId"] for n in nics.values() if "SubnetId" in n), None
)
in_ec2_classic = not bool(self.subnet_id)
self.key_name = kwargs.get("key_name")
self.ebs_optimized = kwargs.get("ebs_optimized", False)
@ -759,7 +765,7 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
self._private_ips = set()
self.prep_nics(
kwargs.get("nics", {}),
nics,
private_ip=kwargs.get("private_ip"),
associate_public_ip=self.associate_public_ip,
security_groups=self.security_groups,

View File

@ -1,7 +1,7 @@
from moto.autoscaling import autoscaling_backends
from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores
from moto.ec2.exceptions import MissingParameterError
from moto.ec2.exceptions import MissingParameterError, InvalidParameterCombination
from moto.ec2.utils import (
filters_from_querystring,
dict_from_querystring,
@ -70,6 +70,10 @@ class InstanceResponse(BaseResponse):
),
"launch_template": self._get_multi_param_dict("LaunchTemplate"),
}
if len(kwargs["nics"]) and kwargs["subnet_id"]:
raise InvalidParameterCombination(
msg="Network interfaces and an instance-level subnet ID may not be specified on the same request"
)
mappings = self._parse_block_device_mapping()
if mappings:

View File

@ -2116,7 +2116,6 @@ def test_run_instance_with_nic_preexisting_boto3():
MinCount=1,
MaxCount=1,
NetworkInterfaces=[{"DeviceIndex": 0, "NetworkInterfaceId": eni.id,}],
SubnetId=subnet.id,
SecurityGroupIds=[security_group2.group_id],
)[0]
@ -3053,8 +3052,7 @@ def test_run_instance_and_associate_public_ip():
ImageId=EXAMPLE_AMI_ID,
MinCount=1,
MaxCount=1,
NetworkInterfaces=[{"DeviceIndex": 0}],
SubnetId=subnet.id,
NetworkInterfaces=[{"DeviceIndex": 0, "SubnetId": subnet.id}],
)[0]
interfaces = instance.network_interfaces_attribute
addresses = interfaces[0]["PrivateIpAddresses"][0]
@ -3067,8 +3065,9 @@ def test_run_instance_and_associate_public_ip():
ImageId=EXAMPLE_AMI_ID,
MinCount=1,
MaxCount=1,
NetworkInterfaces=[{"DeviceIndex": 0, "AssociatePublicIpAddress": False}],
SubnetId=subnet.id,
NetworkInterfaces=[
{"DeviceIndex": 0, "SubnetId": subnet.id, "AssociatePublicIpAddress": False}
],
)[0]
interfaces = instance.network_interfaces_attribute
addresses = interfaces[0]["PrivateIpAddresses"][0]
@ -3081,8 +3080,9 @@ def test_run_instance_and_associate_public_ip():
ImageId=EXAMPLE_AMI_ID,
MinCount=1,
MaxCount=1,
NetworkInterfaces=[{"DeviceIndex": 0, "AssociatePublicIpAddress": True}],
SubnetId=subnet.id,
NetworkInterfaces=[
{"DeviceIndex": 0, "SubnetId": subnet.id, "AssociatePublicIpAddress": True}
],
)[0]
interfaces = instance.network_interfaces_attribute
addresses = interfaces[0]["PrivateIpAddresses"][0]
@ -3094,6 +3094,27 @@ def test_run_instance_and_associate_public_ip():
addresses["Association"].should.have.key("PublicIp")
@mock_ec2
def test_run_instance_cannot_have_subnet_and_networkinterface_parameter():
ec2 = boto3.resource("ec2", "us-west-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 exc:
ec2.create_instances(
ImageId=EXAMPLE_AMI_ID,
MinCount=1,
MaxCount=1,
SubnetId=subnet.id,
NetworkInterfaces=[{"DeviceIndex": 0}],
)
err = exc.value.response["Error"]
err["Code"].should.equal("InvalidParameterCombination")
err["Message"].should.equal(
"Network interfaces and an instance-level subnet ID may not be specified on the same request"
)
@mock_ec2
def test_describe_instances_dryrun():
client = boto3.client("ec2", region_name="us-east-1")