{#- Self-contained report (report.py): inline CSS and SVG only. No scripts, links or external assets, so the file can be saved, shared and printed to PDF as is. -#} IPLens report · {{ r.account }}{{ ' · ' ~ r.env_label if r.env }}

IP address report

{{ r.account }} · region {{ r.region }} · snapshot taken {{ r.taken_at }} · generated {{ r.generated_at }} {% if r.env %} · environment {{ r.env_label }}{% endif %} {% if r.redacted %} · identifiers redacted{% endif %}
{% for n in r.notes %}
{{ n }}
{% endfor %}

Summary

{% set s = r.summary %}
VPCs
{{ s.vpcs }}
Subnets
{{ s.subnets }}
Usable IPs
{{ s.usable }}
Used (incl. idle)
{{ s.used_pct | pct }}
{{ s.consumed }} IPs · {{ s.idle }} idle
Free
{{ s.free_pct | pct }}
{{ s.free }} IPs
At-risk subnets
{{ r.at_risk | length }}

At-risk subnets

Forecast full within {{ soon_days }} days (Trends, {{ r.trend_window }}-day window) or less than {{ at_risk_pct | int }}% free.

{% for a in r.at_risk %} {% else %} {% endfor %}
SubnetNameCIDRAZUsed FreeFree %Forecast
{{ a.subnet.subnet_id }} {{ a.subnet.name }} {{ a.subnet.cidr }} {{ a.subnet.az }} {{ a.subnet.consumed }} {{ a.subnet.free }} {{ bar(100 - a.subnet.free_pct, width=80, cls='err') }} {{ a.subnet.free_pct | pct }} {% if a.forecast %}{{ a.forecast.text }}{% if a.forecast.confidence_note %}
{{ a.forecast.confidence_note }}
{% endif %}{% else %}no history{% endif %}
No subnet is at risk.

Top IP consumers

{% for title, rows in (("By owner", r.by_owner), ("By environment", r.by_env), ("By resource type", r.by_type)) %}

{{ title }}

{% for c in rows %} {% else %} {% endfor %}
{{ title[3:] | capitalize }}IPsShare
{{ c.label }}{{ c.ips }}{{ bar(c.pct, width=90) }} {{ c.pct | pct }}
No IPs.
{% endfor %}

Used-IP trend

{{ r.trend_snapshots }} snapshot(s) in the last {{ r.trend_window }} days · {% set fc = r.trend_total.forecast %}forecast: {{ fc.text if fc else 'not enough data' }} {% if fc and fc.confidence_note %} · {{ fc.confidence_note }}{% endif %}

{{ chart(r.trend_total, width=900, height=240) }} {% if r.trend_vpcs | length > 1 %} {% for v in r.trend_vpcs %} {% endfor %}
VPCNameUsedLimitTrendForecast
{{ v.key }}{{ v.name }}{{ v.latest }} {{ v.capacity }}{{ chart(v, width=160, height=36, compact=True) }} {{ v.forecast.text if v.forecast else '' }}
{% endif %}

Suggestions

Allowed: IPs to free
{{ r.totals.allowed }}
{{ r.allowed | length }} suggestion(s)
Blocked by rules
{{ r.totals.blocked }}
{{ r.blocked | length }} suggestion(s)

Estimates; alternative suggestions for the same resources can overlap. IPLens never changes AWS.

{% for title, items, blocked in (("Allowed", r.allowed, False), ("Blocked by rule", r.blocked, True)) %}

{{ title }}

{% if blocked %}{% endif %} {% for s in items %} {% if blocked %}{% endif %} {% else %} {% endfor %}
TypeSuggestionIPs savedBlocked by
{{ s.kind_label }} {{ s.title }}
{{ s.detail }}
{% if s.ips_saved %}{{ s.ips_saved }}{% else %}{{ s.impact or '–' }}{% endif %}
    {% for name, reason in s.blocked_by %}
  • {{ name }}: {{ reason }}
  • {% endfor %}
None.
{% endfor %}

CIDR headroom

Free space of each VPC CIDR (every subnet counts). Less than {{ low_pct | int }}% free is flagged. The recommendation is the first /{{ r.secondary_prefix }} secondary CIDR that passes the AWS association restrictions and does not overlap any network IPLens knows (all accounts' VPCs, Transit Gateway and peering routes). Read-only: nothing is created in AWS.

{% for h in r.headroom %}

{{ h.vpc.vpc_id }} {{ h.vpc.name }} · {{ h.free_pct | pct }} free {% if h.low %}low headroom{% else %}ok{% endif %}

{% for m in h.maps %} {% endfor %}
CIDRAddressesIn subnetsFree Largest freeFree /24sFragmentation
{{ m.cidr }}{% if m.primary %} primary{% endif %} {{ m.size }}{{ m.allocated }}{{ m.free_total }} {{ m.largest_free or '–' }}{{ m.per_size[24][0] }} {{ bar(m.fragmentation * 100, width=70) }} {{ '%.2f' | format(m.fragmentation) }}
{% if h.recommendation %}
Secondary CIDR recommendation: {{ h.recommendation.cidr }} (pool {{ h.recommendation.pool }}) {{ h.recommendation.status }}
{% if h.recommendation.warnings %}{% endif %}
{{ h.terraform }}
{% else %}
No secondary /{{ r.secondary_prefix }} candidate passes the checks.
{% endif %}
{% else %}
No VPCs.
{% endfor %}

Ownership coverage

{% set o = r.ownership %} {% if o %}
Resources
{{ o.total }}
Managed
{{ r.managed }}
{{ r.managed_pct | pct }}
Unmanaged
{{ o.unmanaged | length }}
{% for c in o.counts %} {% endfor %}
SourceResourcesShare
{{ c.label }}{{ c.count }} {% set p = 100.0 * c.count / o.total if o.total else 0 %}{{ bar(p, width=90, cls='err' if not c.source else '') }} {{ p | pct }}
{% if o.unmanaged %}

Unmanaged resources{% if o.unmanaged | length > max_unmanaged %} (first {{ max_unmanaged }} of {{ o.unmanaged | length }}){% endif %}

{% for u in o.unmanaged[:max_unmanaged] %}{% endfor %}
TypeResource
{{ u.label }}{{ u.resource_id }}
{% endif %} {% else %}
No ownership data.
{% endif %}