Unifying Terraform, OpenTofu, and Pulumi: How InfraOrcinus Normalizes Multi-Engine Delivery
By Chirag Panchal · Founder & Lead Architect · · 6 min read
How InfraOrcinus abstracts diverse IaC dialects into a canonical PlanSummary model. Enabling enterprise platform teams to enforce unified security policies, pre-flight cost estimation, and human approvals regardless of the underlying engine.
Development Status & Architectural Evolution: InfraOrcinus is in active development. Architecture specifications, internal interfaces, and operational protocols described herein reflect our current engineering design and are continuously refined to make InfraOrcinus robust, resilient, and enterprise-grade.
Enterprise platform engineering teams rarely have the luxury of greenfield standardization. In reality, large organizations accumulate multiple Infrastructure as Code tools:
- Legacy production backbones running HashiCorp Terraform.
- Modern open-source modules migrating to OpenTofu under the MPL-2.0 license.
- Application engineering teams utilizing Pulumi to define infrastructure using TypeScript or Python.
When each tool operates as an isolated silo, governance becomes fragmented. Security engineers must write separate policy definitions for each syntax, finance teams struggle to aggregate multi-cloud spend, and platform leaders lack a single pane of glass for deployment approvals.
InfraOrcinus solves this through Universal Plan Normalization.
1. The Babel of Infrastructure Plan Formats
Every IaC engine produces its own dialect when previewing changes:
- Terraform generates HCL plan files and raw JSON state diffs with complex nested change actions (
["create"],["update"],["delete", "create"]). - OpenTofu introduces custom client-side encryption metadata and community provider registries.
- Pulumi emits structured preview event streams representing resource graph DAG diffs.
Feeding these distinct schemas directly to downstream policy engines (such as Open Policy Agent) forces platform teams to maintain duplicate Rego rule sets for every engine.
2. The Canonical PlanSummary Data Structure
Instead of coupling governance gates to engine syntaxes, InfraOrcinus ingests execution diffs into a single, engine-agnostic Go data structure:
type PlanSummary struct {
Engine EngineType // Terraform, OpenTofu, Pulumi
ResourceActions []ResourceAction // Normalized: Create, Read, Update, Delete
AddCount int // Resources to add
ChangeCount int // Resources to modify
DestroyCount int // Resources to destroy
ProposedCost *CostEstimate // Monthly expenditure delta
PolicyViolations []PolicyViolation // Evaluated compliance status
Checksum string // SHA-256 of the normalized plan
}
By standardizing on PlanSummary:
- One Policy Engine: Security teams author rules once against a uniform, plan-shaped resource model (a list of
resource_changes, each with a type, address, and before/after values), whether the change originates from Terraform, OpenTofu, or Pulumi. Rules are either built-in (resource type, attribute, operator) or Rego evaluated in-process by an embedded Open Policy Agent engine, so there is no separate OPA server to run. - Unified Blast-Radius Review: Human approvers see an identical, readable diff interface regardless of whether the developer wrote HCL or TypeScript.
- Consistent Pre-Flight Cost Estimates: Infracost queries execute against normalized resource addresses, calculating cost deltas accurately across all providers.
3. Pluggable Runner Engine Adapters
InfraOrcinus executes engines through an internal interface:
type EngineAdapter interface {
Validate(ctx context.Context, workingDir string) error
Plan(ctx context.Context, workingDir string, vars map[string]any) (*PlanSummary, error)
Apply(ctx context.Context, workingDir string, planRef string) (*ExecutionResult, error)
}
When a run is triggered:
- The InfraOrcinus control plane resolves the stack configuration and selects the designated engine adapter.
- The runner spins up an ephemeral container with the corresponding binary (
tofu,terraform, orpulumi). - The engine output is parsed and mapped into
PlanSummary. - Downstream gates evaluate policies, query pricing deltas, and halt at the human approval gate.
4. Policy Across Engines
Policy evaluation happens on the normalized plan, before the approval gate:
- Two rule styles. Built-in rules need no Rego: they match a resource type and attribute with an operator such as
eq,contains,regex, orexists. Rego handles cross-resource constraints and complex conditionals. - Enforcement levels.
advisoryviolations are recorded as warnings and the run can proceed.mandatoryviolations block the apply until the plan changes or the policy is adjusted. - Fail closed. If a Rego policy stops compiling, errors, or exceeds its time limit, that is recorded as a blocking violation rather than "no violations found". When no policy is enabled, the run page says that nothing was checked, rather than reporting a clean pass.
- Sandboxed. Policies are user-authored code in the control plane, so network and host-information functions are disabled and each evaluation is time-limited.
- Other scanners. Third-party scanners such as Checkov or tfsec are not built into the evaluation path. Teams that rely on them can run them in CI alongside InfraOrcinus, or express the same rules as Rego or built-in rules so the result is enforced at the gate.
The same rules also check AI-drafted blueprints before they are saved, using only statically known values, with unknown values judged at the real plan.
5. Where Engines Genuinely Differ
Normalization is a strength, but honesty about its limits matters:
| Area | Terraform / OpenTofu | Pulumi |
|---|---|---|
| Plan source | Structured plan JSON | Preview event stream |
| Values unknown until apply | Marked as computed in the plan | Often unknown in the preview, especially with programmatic logic and dynamic providers |
| Secrets | Sensitive values marked in the plan and masked on the server before display | Secrets are treated as sensitive in the preview and should be masked the same way |
| Dependency graph | Dependency edges shown in the resource graph | Resources shown, but dependency edges are not yet drawn |
| Cost estimation | Priced from the normalized resources | Not priced yet. Pricing recognizes Terraform and OpenTofu resource types, so Pulumi resources show "pricing not available for this resource type" and cost-threshold policies only see the priced part of a plan |
Treat the approval of a Pulumi plan with the same care but a longer eye on values flagged as unknown, because a program can compute a different result at apply time than the preview showed.
6. Versions, State, and Mixed-Engine Estates
- Version pinning. The engine and its version are selected per environment, and the container image tag can be pinned (for example
1.8.2) so every run uses the same binary. We recommend OpenTofu 1.7+ and Pulumi 3.110+ as baselines. The platform does not enforce a minimum version yet, so pin what you test. - State is per engine. Terraform and OpenTofu use the native HTTP backend or a configured remote backend; Pulumi keeps its own state model. There is no cross-engine shared state file.
- Mixed estates. A platform team can run a Terraform network stack and a Pulumi application stack side by side, with unified policy, cost, and approvals. Coupling between them should go through explicit, published outputs and parameters rather than reading one engine's state from another.
- Migrating between engines. Moving Terraform stacks to OpenTofu is a drop-in change of engine and image because modules and the backend protocol are compatible. Moving to or from Pulumi is a rewrite of the definition, not a switch.
[!NOTE] Since this article was written, Azure Bicep and AWS CloudFormation have joined the same plan model. See Azure Bicep and AWS CloudFormation in InfraOrcinus for how what-if and change sets are normalized, and how tightly each engine binds the approval to the apply.
Summary
Multi-engine reality should not mean fractured governance. By translating Terraform, OpenTofu, and Pulumi plans into a single canonical format, InfraOrcinus enables enterprises to adopt open-source tooling like OpenTofu while preserving uniform security, cost controls, and human approvals across the fleet.