EC2 - SubnetId and NetworkInterfaces cannot both be specified when calling run_instances (#4719)
This commit is contained in:
parent
b0a59fe05e
commit
a1bfb6a48e
@ -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__(
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user