Subnet Connectivity

Introduction

I ran into SSH connectivity to the EC2 instance when using a key pair. To resolve this issue, I first created a VPC and then listed the public subnet associated to that VPC. The cause of the connectivity issue was that the subnet was a private subnet. It did not have an Internet Gateway attached to it.

Check Subnets in VPC

Constructor creates the boto3 client:

Slice Constructor
    def __init__(self):
        self.ec2 = boto3.client('ec2')
grid/slice.py
    def check_subnets_in_vpc(self, vpc_id):
        # Describe subnets that are associated with the specified VPC ID
        response = self.ec2.describe_subnets(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
        subnets = response.get('Subnets', [])

        if subnets:
            print(f"There are {len(subnets)} subnet(s) in VPC {vpc_id}.")
            for subnet in subnets:
                print(f"Subnet ID: {subnet['SubnetId']} - CIDR: {subnet['CidrBlock']}")
            return True
        else:
            print(f"No subnets found in VPC {vpc_id}.")
            return False
grid/slice.py
    def check_subnet_visibility(self, subnet_id):
        # Describe route tables associated with the subnet
        route_tables = self.ec2.describe_route_tables(Filters=[
            {'Name': 'association.subnet-id', 'Values': [subnet_id]}
        ])
        for route_table in route_tables['RouteTables']:
            for route in route_table['Routes']:
                # Check if the route table has a route to an Internet Gateway
                if 'GatewayId' in route and route['GatewayId'].startswith('igw-'):
                    return True
        return False

    def print_subnet_details(self, vpc_id):
        subnets = self.ec2.describe_subnets(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])['Subnets']

        if subnets:
            for subnet in subnets:
                # Determine if the subnet is public or private
                subnet_type = "Public" if self.check_subnet_visibility(subnet['SubnetId']) else "Private"

                # Attempt to find the subnet's Name tag
                subnet_name = None
                for tag in subnet.get('Tags', []):
                    if tag['Key'] == 'Name':
                        subnet_name = tag['Value']
                        break

                print(f"Subnet ID: {subnet['SubnetId']} - Type: {subnet_type} - Name: {subnet_name or 'N/A'}")
        else:
            print(f"No subnets found in VPC {vpc_id}.")

Run the Script

Test the method:

test_vpc.py
from grid.slice import Slice
from grid.network import Network

wafer = Slice()

name = "Boto3-VPC"
wafer.create_vpc(name)

vpc_id = 'vpc-0697b053ed59f29da'
wafer.check_subnets_in_vpc(vpc_id)
wafer.print_subnet_details(vpc_id)

network = Network()

if network.prevalidate_vpc(vpc_id):
    print("VPC validation successful. Proceeding with further steps.")
else:
    print("VPC validation failed. Aborting the process.")
Program Output
Checking for VPC by name: Boto3-VPC
Existing VPC found: vpc-0697b053ed59f29da
There are 1 subnet(s) in VPC vpc-0697b053ed59f29da.
Subnet ID: subnet-0cf60eb0cec863b0f - CIDR: 10.0.1.0/24
Subnet ID: subnet-0cf60eb0cec863b0f - Type: Public - Name: RailsPublicSubnet
VPC 'vpc-0697b053ed59f29da' is valid.
VPC validation successful. Proceeding with further steps.

I did not want to keep switching between AWS CLI and console to troubleshoot during development. I cleaned up the resources manually in AWS console before running these tests. The methods are now idempotent. It is capable of continuing the execution if the resource is already present and the exceptions are handled properly. No more crashes due to resource exceeds limit or already exists errors.