Class PlanValidator

java.lang.Object
com.eqixiac.equinix.design.optimizer.wizard.PlanValidator

public final class PlanValidator extends Object
Layered, plan-time validation for the Deployment Wizard. Separates "validate the plan/data" from "live dry-run a connection" so a brand-new customer - who owns no resources and may target a metro with zero footprint - still gets a fully validated plan without provisioning anything first.
  • Layer 1 - structural / catalog (no provisioning, no live connection dry-run): names (length/charset, asserted locally - never learned from a 400), duplicate names, IP /30 overlaps, ASN sanity, package/metro validity; and, against the public catalog the optimizer already fetched, that every Z-side service-profile uuid resolves, is offered in the connection's metro with a valid seller region, and that the bandwidth fits the profile's allowed tiers and the router package ceiling. A required cloud that is NOT offered at a targeted metro is flagged as a new-market gap rather than silently dropped.
  • Layer 2 - live router dry-run (self-contained, real): each planned Cloud Router is posted to POST /fabric/v4/routers?dryRun=true. FCRs have no dependency, so this fully validates package/metro/notifications at plan time with nothing provisioned.
  • Layer 3 - connection endpoint dry-run: a connection whose A-side Cloud Router does not exist yet is not sent a doomed endpoint-less dry-run; it is recorded as DEFERRED (validated structurally now; the live endpoint dry-run runs at provisioning, and needs the customer's authorization key). A connection whose A-side endpoint already exists (a caller-supplied port/FCR, lens 3b) IS dry-run for real, with a complete body.

Every catalog / dry-run step is best-effort: a gateway that cannot serve a surface at all (a bare stub, an offline run) skips that step rather than failing the plan, exactly as the optimizer's catalog scan degrades. Hard errors are only raised from working catalog data or a genuine API rejection.

Three outcome buckets

A live-layer step reaches one of three distinct verdicts, never conflated:

  • ERROR - the plan is wrong: a hard structural/catalog failure, or a genuine API rejection of a well-formed request (a 4xx validation rejection, e.g. HTTP 400/409). Errors invalidate the plan.
  • DEFERRED - will legitimately validate at provisioning: the connection endpoint dry-run postponed because the A-side Cloud Router does not exist yet (lens 3a). Not an error.
  • SKIPPED - could not validate now, and here is why: an infeasibility - the live surface was unavailable (offline / bare stub / not connected), or the API answered with a non-rejection failure (401/403 not entitled, 429 throttled, 5xx server-side, or a transport/timeout error). A skip never invalidates the plan; it is surfaced with a human/LLM-readable reason so the gap is called out rather than hidden.

The rejection-vs-infeasibility split is centralized in classifyLiveFailure(Throwable) so every live-layer catch classifies identically, and so the execution-time pre-flight can reuse it.

A PlannedMulticloudInterconnect has no Fabric request body and this SDK calls no cloud-provider API, so no layer can validate it live and none will at provisioning. Each link is therefore recorded as SKIPPED with a reason naming the link, never as DEFERRED (nothing validates it later) and never as an ERROR, with two exceptions that are Layer-1 errors: a structurally malformed entry (blank or duplicate name, the same cloud on both sides, a non-positive bandwidth), and an entry produced under CloudToCloudStrategy.NATIVE_ONLY for which the catalog holds no usable environment (none for the region pair, a status other than GA, or no size covering the requested bandwidth).

  • Method Details

    • validate

      public static PlanValidator.Result validate(List<MetroRecommendation> metros, OptimizationRequest request, DeploymentTopology topology, List<PlannedCloudRouter> routers, List<PlannedConnection> providerConnections, List<PlannedBackboneLink> backboneLinks, List<PlannedRoutingProtocol> protocols, Long customerAsn, FabricGateway fabric)
      Validates a plan that has no native multicloud links. Equivalent to the ten-argument overload with multicloudLinks == null.
      Parameters:
      metros - the source metro recommendations (for the new-market check); may be null
      request - the optimization request (for workload provider dependencies); may be null
      topology - the placement topology (which workloads sit where); may be null
      routers - the planned Cloud Routers
      providerConnections - the planned provider connections
      backboneLinks - the planned backbone links
      protocols - the planned routing protocols (for IP overlap checks)
      customerAsn - the customer BGP ASN, or null to skip the ASN sanity check
      fabric - the gateway for catalog + dry-run access; null skips every live step
      Returns:
      the validation result
    • validate

      public static PlanValidator.Result validate(List<MetroRecommendation> metros, OptimizationRequest request, DeploymentTopology topology, List<PlannedCloudRouter> routers, List<PlannedConnection> providerConnections, List<PlannedBackboneLink> backboneLinks, List<PlannedRoutingProtocol> protocols, List<PlannedMulticloudInterconnect> multicloudLinks, Long customerAsn, FabricGateway fabric)
      Validates a plan across all layers.
      Parameters:
      metros - the source metro recommendations (for the new-market check); may be null
      request - the optimization request (for workload provider dependencies); may be null
      topology - the placement topology (which workloads sit where); may be null
      routers - the planned Cloud Routers
      providerConnections - the planned provider connections
      backboneLinks - the planned backbone links
      protocols - the planned routing protocols (for IP overlap checks)
      multicloudLinks - the planned native multicloud links (Beta); may be null. Each is recorded as skipped, or as an error in the cases listed in the class documentation
      customerAsn - the customer BGP ASN, or null to skip the ASN sanity check
      fabric - the gateway for catalog + dry-run access; null skips every live step
      Returns:
      the validation result
    • classifyLiveFailure

      public static PlanValidator.LiveFailure classifyLiveFailure(Throwable e)
      Classifies a failure thrown from a live validation step (a router or connection dry-run) as either a genuine rejection of a well-formed request - a real plan defect that must become an ERROR - or an infeasibility that must become a SKIPPED(reason) and never invalidate an otherwise-sound plan.
      Parameters:
      e - the failure thrown from the live step; null tolerated (treated as infeasible)
      Returns:
      the classification, with an infeasibility reason when applicable