frostmoln_vpc_routes (Data Source)
Lists the tenant's routes on one VPC — every row the routes panel and fm network vpc route list would show, rendered exactly as frostmoln_vpc_route writes it.
This is the drift detector the per-route resource cannot be. frostmoln_vpc_route is one resource per route, deliberately non-authoritative — no resource owns the table — so a route added out of band (in the portal, with fm, through the API, or by a colleague) is invisible to every plan. A more-specific added route can even silently shadow a managed one: longest prefix wins, the plan stays clean, and traffic goes where the configuration does not say. This data source READS the set, so out-of-band routes appear in it, and a check block or lifecycle postcondition over it turns that difference into a failed plan (see the example and the surface-contract guide).
TENANT VIEW ONLY: platform-owned routes — the system routes DNS and managed services ride — are NEVER listed, by design. What this returns is exactly what frostmoln_vpc_route sees, which is what lets a check treat the list as the WHOLE visible table rather than a partial one.
IT REFUSES RATHER THAN LIE: a 404 from the route collection has two causes that cannot be told apart on the wire — this deployment does not serve route management at all, or this VPC has no router and therefore no route table. The data source asks the VPC itself to separate what it can, and errors either way. An empty table that is really a refusal would read as "no drift", which is the one wrong answer this data source exists to prevent.
Example Usage
# The drift-detection recipe for VPC routes.
#
# `frostmoln_vpc_route` is one resource per route and deliberately
# non-authoritative — no resource owns the table — so a route added out of band
# (portal, `fm`, API, a colleague) is invisible to every plan. THE SHADOW CASE
# this exists for: Terraform owns 0.0.0.0/0 -> appliance, and someone adds
# 10.20.0.0/16 -> other-box. Longest prefix wins, the plan stays clean, and
# traffic goes where the configuration does not say. This data source reads the
# whole tenant-visible table; the check block below pins it and turns the
# difference into a failed plan.
data "frostmoln_vpc_routes" "table" {
vpc_id = frostmoln_vpc.main.id
}
# Destinations this configuration manages. One route here; with several, give
# the resource a for_each and use destinations = toset(values(...)[*].destination).
locals {
managed_destinations = [
frostmoln_vpc_route.appliance_default.destination,
]
}
# Every tenant-visible row must be a route this configuration declares.
# (Platform-owned routes never appear in the listing, by design, so nothing
# needs filtering for the pin to be total over what the tenant controls.)
check "vpc_routes_pinned" {
data = data.frostmoln_vpc_routes.table
assert {
condition = length([
for row in data.frostmoln_vpc_routes.table.routes : row.destination
if !contains(local.managed_destinations, row.destination)
]) == 0
error_message = (
"This VPC has routes Terraform does not manage. They were added outside Terraform — " +
"in the portal, with `fm`, or by someone else — and one of them may be shadowing a " +
"managed route (a more-specific destination wins the traffic). Import the route with " +
"`terraform import frostmoln_vpc_route.<name> \"${frostmoln_vpc.main.id}/<destination>\"` " +
"or remove it, then re-run the plan."
)
}
}
resource "frostmoln_vpc_route" "appliance_default" {
vpc_id = frostmoln_vpc.main.id
destination = "0.0.0.0/0"
next_hop = frostmoln_instance.appliance.private_ip
}Schema
Required
vpc_id(String) The ID of the VPC whose tenant-visible route table to list.
Read-Only
id(String) The identifier of this listing — the same VPC id asvpc_id, deliberately mirrored rather than distinct: one VPC's visible table is the whole identity of this listing, and there is no server-side id beyond it.routes(Attributes List) Every tenant-visible route on the VPC, in the canonical rendering the platform reports back: exactly the rowsfrostmoln_vpc_routecan see. A VPC with no tenant routes renders as an empty list, never null. (see below for nested schema)
Nested Schema for routes
Read-Only:
destination(String) Destination CIDR, in the canonical (masked) form the platform stores —203.0.113.0/24. A platform default route is reported back as the single0.0.0.0/0it was written as.next_hop(String) Next hop, exactly as the platform renders it back: an address on a subnet attached to the VPC, or the reserved tokeninternet— which reads back as the token, never as the address it resolved to, so a check over these rows never sees a gateway rebuild as drift.