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):
|
class MalformedDHCPOptionsIdError(EC2ClientError):
|
||||||
def __init__(self, dhcp_options_id):
|
def __init__(self, dhcp_options_id):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
@ -677,6 +677,8 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
|
|||||||
self.id = random_instance_id()
|
self.id = random_instance_id()
|
||||||
self.lifecycle = kwargs.get("lifecycle")
|
self.lifecycle = kwargs.get("lifecycle")
|
||||||
|
|
||||||
|
nics = kwargs.get("nics", {})
|
||||||
|
|
||||||
launch_template_arg = kwargs.get("launch_template", {})
|
launch_template_arg = kwargs.get("launch_template", {})
|
||||||
if launch_template_arg and not image_id:
|
if launch_template_arg and not image_id:
|
||||||
# the image id from the template should be used
|
# 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")
|
self.region_name = kwargs.get("region_name", "us-east-1")
|
||||||
placement = kwargs.get("placement", None)
|
placement = kwargs.get("placement", None)
|
||||||
self.subnet_id = kwargs.get("subnet_id")
|
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)
|
in_ec2_classic = not bool(self.subnet_id)
|
||||||
self.key_name = kwargs.get("key_name")
|
self.key_name = kwargs.get("key_name")
|
||||||
self.ebs_optimized = kwargs.get("ebs_optimized", False)
|
self.ebs_optimized = kwargs.get("ebs_optimized", False)
|
||||||
@ -759,7 +765,7 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
|
|||||||
|
|
||||||
self._private_ips = set()
|
self._private_ips = set()
|
||||||
self.prep_nics(
|
self.prep_nics(
|
||||||
kwargs.get("nics", {}),
|
nics,
|
||||||
private_ip=kwargs.get("private_ip"),
|
private_ip=kwargs.get("private_ip"),
|
||||||
associate_public_ip=self.associate_public_ip,
|
associate_public_ip=self.associate_public_ip,
|
||||||
security_groups=self.security_groups,
|
security_groups=self.security_groups,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from moto.autoscaling import autoscaling_backends
|
from moto.autoscaling import autoscaling_backends
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from moto.core.utils import camelcase_to_underscores
|
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 (
|
from moto.ec2.utils import (
|
||||||
filters_from_querystring,
|
filters_from_querystring,
|
||||||
dict_from_querystring,
|
dict_from_querystring,
|
||||||
@ -70,6 +70,10 @@ class InstanceResponse(BaseResponse):
|
|||||||
),
|
),
|
||||||
"launch_template": self._get_multi_param_dict("LaunchTemplate"),
|
"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()
|
mappings = self._parse_block_device_mapping()
|
||||||
if mappings:
|
if mappings:
|
||||||
|
@ -2116,7 +2116,6 @@ def test_run_instance_with_nic_preexisting_boto3():
|
|||||||
MinCount=1,
|
MinCount=1,
|
||||||
MaxCount=1,
|
MaxCount=1,
|
||||||
NetworkInterfaces=[{"DeviceIndex": 0, "NetworkInterfaceId": eni.id,}],
|
NetworkInterfaces=[{"DeviceIndex": 0, "NetworkInterfaceId": eni.id,}],
|
||||||
SubnetId=subnet.id,
|
|
||||||
SecurityGroupIds=[security_group2.group_id],
|
SecurityGroupIds=[security_group2.group_id],
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
@ -3053,8 +3052,7 @@ def test_run_instance_and_associate_public_ip():
|
|||||||
ImageId=EXAMPLE_AMI_ID,
|
ImageId=EXAMPLE_AMI_ID,
|
||||||
MinCount=1,
|
MinCount=1,
|
||||||
MaxCount=1,
|
MaxCount=1,
|
||||||
NetworkInterfaces=[{"DeviceIndex": 0}],
|
NetworkInterfaces=[{"DeviceIndex": 0, "SubnetId": subnet.id}],
|
||||||
SubnetId=subnet.id,
|
|
||||||
)[0]
|
)[0]
|
||||||
interfaces = instance.network_interfaces_attribute
|
interfaces = instance.network_interfaces_attribute
|
||||||
addresses = interfaces[0]["PrivateIpAddresses"][0]
|
addresses = interfaces[0]["PrivateIpAddresses"][0]
|
||||||
@ -3067,8 +3065,9 @@ def test_run_instance_and_associate_public_ip():
|
|||||||
ImageId=EXAMPLE_AMI_ID,
|
ImageId=EXAMPLE_AMI_ID,
|
||||||
MinCount=1,
|
MinCount=1,
|
||||||
MaxCount=1,
|
MaxCount=1,
|
||||||
NetworkInterfaces=[{"DeviceIndex": 0, "AssociatePublicIpAddress": False}],
|
NetworkInterfaces=[
|
||||||
SubnetId=subnet.id,
|
{"DeviceIndex": 0, "SubnetId": subnet.id, "AssociatePublicIpAddress": False}
|
||||||
|
],
|
||||||
)[0]
|
)[0]
|
||||||
interfaces = instance.network_interfaces_attribute
|
interfaces = instance.network_interfaces_attribute
|
||||||
addresses = interfaces[0]["PrivateIpAddresses"][0]
|
addresses = interfaces[0]["PrivateIpAddresses"][0]
|
||||||
@ -3081,8 +3080,9 @@ def test_run_instance_and_associate_public_ip():
|
|||||||
ImageId=EXAMPLE_AMI_ID,
|
ImageId=EXAMPLE_AMI_ID,
|
||||||
MinCount=1,
|
MinCount=1,
|
||||||
MaxCount=1,
|
MaxCount=1,
|
||||||
NetworkInterfaces=[{"DeviceIndex": 0, "AssociatePublicIpAddress": True}],
|
NetworkInterfaces=[
|
||||||
SubnetId=subnet.id,
|
{"DeviceIndex": 0, "SubnetId": subnet.id, "AssociatePublicIpAddress": True}
|
||||||
|
],
|
||||||
)[0]
|
)[0]
|
||||||
interfaces = instance.network_interfaces_attribute
|
interfaces = instance.network_interfaces_attribute
|
||||||
addresses = interfaces[0]["PrivateIpAddresses"][0]
|
addresses = interfaces[0]["PrivateIpAddresses"][0]
|
||||||
@ -3094,6 +3094,27 @@ def test_run_instance_and_associate_public_ip():
|
|||||||
addresses["Association"].should.have.key("PublicIp")
|
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
|
@mock_ec2
|
||||||
def test_describe_instances_dryrun():
|
def test_describe_instances_dryrun():
|
||||||
client = boto3.client("ec2", region_name="us-east-1")
|
client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user