2.4. Outputs and References
This lab covers pulumi.Output — how to inspect, transform with apply(), and combine outputs with Output.all().
Step 1 — Inspect stack outputs
The container from the previous lab already exports container_name. List all exported values for the current stack:
Read a single output by name:
Explanation
pulumi.export("key", value) declares a stack output — a named value that is written to state after every
successful deploy. Stack outputs are the public interface of a stack:
| Where they appear | How |
|---|---|
| CLI | pulumi stack output [name] |
| Other stacks | Consumed via pulumi.StackReference |
| CI/CD scripts | Read with pulumi stack output --json for machine parsing |
Outputs can also expose generated secrets to the console after a deploy — though in production, credentials belong in a dedicated store such as Azure Key Vault or HashiCorp Vault rather than as plain stack outputs.
Step 2 — Transform an output with apply()
Add a message export that embeds the container name into a string. Extend the main() function in __main__.py:
Apply and read the result:
Explanation
container.name is not a plain str — it is a pulumi.Output[str]. Pulumi outputs are resolved asynchronously
during deployment. At the time your Python module is evaluated, the container does not exist yet, so its name is
not yet known. This shows up clearly in pulumi preview, where unresolved values appear as <computed>.
apply() schedules a function to run after the value is resolved at deploy time:
The return value of apply() is itself an Output, so it can be exported, passed into another resource argument,
or chained with another apply().
Don’t use Output values directly as strings
This will raise a TypeError at runtime:
Always use apply() to work with the value inside an output.
Step 3 — Combine outputs with Output.all()
Export a single string that combines values from two different resources. Add to main():
Apply and inspect:
Explanation
Output.all() accepts any number of outputs and returns a single Output[list] that resolves when every input is
resolved. It takes a function — expressed here as a lambda — that receives the resolved values as a list in the same
order they were passed to Output.all().
Use Output.all() whenever your transformation needs values from more than one resource. A typical real-world example
is assembling a database connection string:
The PostgreSQL server hostname and the database name come from two separate resources — Output.all() waits for
both before building the string.
Output.all() preserves dependencies
The resulting output carries the combined dependencies of all its inputs. Pulumi will ensure all referenced resources are fully deployed before any resource that consumes the combined output.