diff --git a/moto/ec2/models.py b/moto/ec2/models.py index bdb1cb03a..586f49dcf 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -3307,6 +3307,7 @@ class Subnet(TaggedEC2Resource, CloudFormationModel): ] # Reserved by AWS self._unused_ips = set() # if instance is destroyed hold IP here for reuse self._subnet_ips = {} # has IP: instance + self.state = "available" @staticmethod def cloudformation_name_type(): @@ -3387,6 +3388,8 @@ class Subnet(TaggedEC2Resource, CloudFormationModel): return self.availability_zone elif filter_name in ("defaultForAz", "default-for-az"): return self.default_for_az + elif filter_name == "state": + return self.state else: return super(Subnet, self).get_filter_value(filter_name, "DescribeSubnets") diff --git a/moto/ec2/responses/subnets.py b/moto/ec2/responses/subnets.py index ef1b6249c..1cfd36993 100644 --- a/moto/ec2/responses/subnets.py +++ b/moto/ec2/responses/subnets.py @@ -99,7 +99,7 @@ DESCRIBE_SUBNETS_RESPONSE = """ {% for subnet in subnets %} {{ subnet.id }} - available + {{ subnet.state }} {{ subnet.vpc_id }} {{ subnet.cidr_block }} {{ subnet.available_ip_addresses }} diff --git a/tests/test_ec2/test_subnets.py b/tests/test_ec2/test_subnets.py index 246cacf6b..76e525990 100644 --- a/tests/test_ec2/test_subnets.py +++ b/tests/test_ec2/test_subnets.py @@ -677,3 +677,59 @@ def test_run_instances_should_attach_to_default_subnet(): subnets[0]["AvailableIpAddressCount"] == 4090 or subnets[1]["AvailableIpAddressCount"] == 4090 ) + + +@mock_ec2 +def test_describe_subnets_by_vpc_id(): + ec2 = boto3.resource("ec2", region_name="us-west-1") + client = boto3.client("ec2", region_name="us-west-1") + + vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16") + subnet1 = ec2.create_subnet( + VpcId=vpc1.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a" + ) + vpc2 = ec2.create_vpc(CidrBlock="172.31.0.0/16") + subnet2 = ec2.create_subnet( + VpcId=vpc2.id, CidrBlock="172.31.48.0/20", AvailabilityZone="us-west-1b" + ) + + subnets = client.describe_subnets( + Filters=[{"Name": "vpc-id", "Values": [vpc1.id]}] + ).get("Subnets", []) + subnets.should.have.length_of(1) + subnets[0]["SubnetId"].should.equal(subnet1.id) + + subnets = client.describe_subnets( + Filters=[{"Name": "vpc-id", "Values": [vpc2.id]}] + ).get("Subnets", []) + subnets.should.have.length_of(1) + subnets[0]["SubnetId"].should.equal(subnet2.id) + + # Specify multiple VPCs in Filter. + subnets = client.describe_subnets( + Filters=[{"Name": "vpc-id", "Values": [vpc1.id, vpc2.id]}] + ).get("Subnets", []) + subnets.should.have.length_of(2) + + # Specify mismatched SubnetIds/Filters. + subnets = client.describe_subnets( + SubnetIds=[subnet1.id], Filters=[{"Name": "vpc-id", "Values": [vpc2.id]}] + ).get("Subnets", []) + subnets.should.have.length_of(0) + + +@mock_ec2 +def test_describe_subnets_by_state(): + 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") + ec2.create_subnet( + VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-1a" + ) + + subnets = client.describe_subnets( + Filters=[{"Name": "state", "Values": ["available"]}] + ).get("Subnets", []) + for subnet in subnets: + subnet["State"].should.equal("available")