Skip to main content
The ubx-plugin-pulumi plugin is the primary execution engine for ubx. It takes IR JSON, generates a complete Pulumi program in your chosen runtime language, and runs it via the Pulumi Automation API.

Install

ubx plugin install pulumi
Installs to ~/.ubx/plugins/pulumi/ubx-plugin-pulumi.

Configure

In workspace.xcl:
workspace {
  engine  = "pulumi"
  runtime = "python"   // python | typescript | go
}

What the plugin generates

Python runtime (runtime = "python")

.ubx/
├── __main__.py        # Pulumi Python program
├── requirements.txt   # Dependencies
└── Pulumi.yaml        # Project metadata
requirements.txt always starts with:
pulumi>=3.0.0,<4.0.0
Then adds per-provider packages:
pulumi-aws>=1.0.0
pulumi-kubernetes>=1.0.0

TypeScript runtime (runtime = "typescript")

.ubx/
├── index.ts
├── package.json
└── Pulumi.yaml

Go runtime (runtime = "go")

.ubx/
├── main.go
├── go.mod
└── Pulumi.yaml

Stack name

The Pulumi project/stack name is derived from the stack directory name:
stackName = filepath.Base(dir)

Cross-stack references

@stack.output references become Pulumi StackReference objects in generated code:
# Generated for @networking.vpc_id
networking_ref = pulumi.StackReference(
    f"{pulumi.get_organization()}/{pulumi.get_project()}/networking"
)
vpc_id = networking_ref.get_output("vpc_id")

Outputs

XCL output blocks become pulumi.export() calls:
# XCL: output vpc_id { value = vpc.id }
pulumi.export("vpc_id", vpc.id)
The export key matches the bare identifier in the output block label.

Plugin RPCs

RPCDescription
CompileGenerates code, returns artifact_uri (path to .ubx/)
PlanRuns pulumi preview, returns summary
ApplyRuns pulumi up, streams ProgressEvent
DestroyRuns pulumi destroy, streams ProgressEvent

Backend

The plugin receives the backend URL from the IR. Backend URL construction:
Backend typeURL format
localfile://<stack-dir>/.ubx/state/
s3s3://bucket/key
gcsgs://bucket
azblobazblob://container
pulumihttps://api.pulumi.com

For-loop resources

For for-iterated resources, the plugin generates list comprehensions in Python:
# XCL: subnets = aws.ec2.Subnet { for az in input.azs ... }
subnets = [aws.ec2.Subnet(f"subnet-{i}", ...) for i, az in enumerate(azs)]
Outputs are collected as:
pulumi.export("subnet_ids", [s.id for s in subnets])