Update plans
--help
if the environment variable PULUMI_EXPERIMENTAL
is set to true
.The result of previews can be saved to an update plan, this can then be used during a later update to constrain the update only to the operations that were planned.
Constraining updates to plans may be useful in organizations with strict approval processes.
Generate an update plan
To generate an update plan run pulumi preview --save-plan=plan.json
. The plan will be written to the plan.json
file.
Use an update plan
To use an update plan run pulumi up --plan=plan.json
, this will constrain the update to only the operations that were saved to the plan.
An update plan constrains the pulumi up operation to allow only the changes described in the plan. No other changes will be applied.
It’s important to note that the plan is not evaluated in an all-or-nothing fashion before changes are applied. Instead, update operations run in batches as the program execution progresses and resources resolve their input values. At any point, if any discrepancy between the plan and the actual execution is detected, the pulumi up
operation will immediately fail, preventing any unexpected updates.
This approach ensures that only planned changes are applied while allowing for the natural resolution of resource dependencies during execution.
Limitations
Update plans can only record information that is available at preview time. This means there are some program constructs that while possible to run correctly at update time, can’t be recorded at preview time.
The most common one is inputs set by the output of other resources that are being created. While the plan will
record that the program wants to set the input field, it can’t record the value which it will be set with and
simply records unknown
.
The next most common issue is creating resources inside an apply
function. If the value for the apply is
unknown at preview time, then the apply function will not run. This results in the plan not recording
anything for the resources created inside the apply and reporting an error at update time when they try to
create. This mostly comes up in the context of needing to create a resource for every item in an array, we
have an issue on GitHub tracking support for this.
The final issue is configuring explicit providers with unknown inputs. Providers configured with unknowns currently do not do full checks and diffs of resources at preview time, this can result in the plan not including information about default, or normalized values which then get set during the actual update.
The first limitation should not prevent the use of plans, it simply makes them a little harder to review and not as strong a guarantee as to what the program will do. We will be looking at improving the precision here.
The other two are best worked around today by splitting your stacks up and using stack references to pass the values forward. Stack reference values are never unknown (because the other stack must have run by the time they’re used).
Format
The format of update plans is currently experimental and subject to change. The most up to date description of the format is the code.
Update plans as a feature will not be deprecated, but the format of the JSON file could change.
Example
Below is an example update plan file from previewing the creation of the aws-typescript template.
{
"manifest": {
"time": "2022-11-15T11:38:20.7291898Z",
"magic": "03503ad839446037795e489261c69ed98257c899e8d4e52abb8134db63afcdd3",
"version": "3.46.2"
},
"config": {
"aws:region": "us-east-1"
},
"resourcePlans": {
"urn:pulumi:dev::examplets::aws:s3/bucket:Bucket::my-bucket": {
"goal": {
"type": "aws:s3/bucket:Bucket",
"name": "my-bucket",
"custom": true,
"inputDiff": {
"adds": {
"__defaults": [
"acl",
"bucket",
"forceDestroy"
],
"acl": "private",
"bucket": "my-bucket-6209a55",
"forceDestroy": false
}
},
"outputDiff": {},
"parent": "urn:pulumi:dev::examplets::pulumi:pulumi:Stack::examplets-dev",
"protect": false,
"provider": "urn:pulumi:dev::examplets::pulumi:providers:aws::default_5_20_0::04da6b54-80e4-46f7-96ec-b56ff0331ba9",
"customTimeouts": {}
},
"steps": [
"create"
],
"state": {
"acl": "private",
"bucket": "my-bucket-6209a55",
"forceDestroy": false,
"id": ""
},
"seed": "6PPrWjTx+PuWSaBVfirvdxH8JvVxKmUPPlvLirSDaFc="
},
"urn:pulumi:dev::examplets::pulumi:providers:aws::default_5_20_0": {
"goal": {
"type": "pulumi:providers:aws",
"name": "default_5_20_0",
"custom": true,
"inputDiff": {
"adds": {
"region": "us-east-1",
"version": "5.20.0"
}
},
"outputDiff": {},
"protect": false,
"customTimeouts": {}
},
"steps": [
"create"
],
"state": {
"region": "us-east-1",
"version": "5.20.0"
},
"seed": "tunRRve9v1XHWU8kz/K22BpSx25+PZIUWSEvGdMlrB4="
},
"urn:pulumi:dev::examplets::pulumi:pulumi:Stack::examplets-dev": {
"goal": {
"type": "pulumi:pulumi:Stack",
"name": "examplets-dev",
"custom": false,
"inputDiff": {},
"outputDiff": {
"adds": {
"bucketName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9"
}
},
"protect": false,
"customTimeouts": {}
},
"steps": [
"create"
],
"state": {
"bucketName": "04da6b54-80e4-46f7-96ec-b56ff0331ba9"
},
"seed": "H+gYmoW6MtpQibswnx9E8p4c3gMoGk2wJKtl9RDVKb0="
}
}
}
This is a textual representation of the goals, and operation steps that the program planned to take.
For the most part this should be readable without much internal knowledge of Pulumi, for example you can see
this plans on creating an s3:Bucket
object called “my-bucket-6209a55”. A lot of the other options correspond
directly to things you should be familiar with from Pulumi programs (such as parents, providers, custom or
component resources).
Some of the less obvious aspects of the above are the string "04da6b54-80e4-46f7-96ec-b56ff0331ba9"
and the
"seed"
property. "04da6b54-80e4-46f7-96ec-b56ff0331ba9"
is used to represent an unknown value, for
example in the above the bucketName
output didn’t resolve to a concrete value at preview time, and so the
plan recorded it as unknown. The "seed"
property is used to ensure that when re-running with a plan set any
“random” defaults (such as the “-6209a55” suffixed to the bucket name) are deterministic, when running an
update with a plan the seeds from the plan will be used rather than new seeds being randomly generated.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.