Persisting Data Between Bundle Actions
When you create a bundle, you often need to preserve data generated during one action (like install)
for use in subsequent actions (like upgrade or uninstall). For example, you might create a virtual
machine during installation and need its ID to delete it during uninstallation.
Porter provides two mechanisms to persist data between bundle actions:
- Parameter Sources - Reference outputs from previous actions as parameter values
- State Files - Automatically persist and restore files between bundle runs
This guide helps you understand when to use each approach and how to implement them.
Quick Comparison
| Feature | Parameter Sources | State Files |
|---|---|---|
| Access in templates | ✅ Yes (bundle.parameters.X) |
❌ No (file-only access) |
| User can override | ✅ Yes | ❌ No |
| Transparency | ✅ Visible in parameter sets | ⚠️ Hidden from users |
| Best for | IDs, connection strings, config values | Tool state files (terraform.tfstate, kubeconfig) |
| Data types | string, number, boolean, file, object | file only |
Approach 1: Parameter Sources
Parameter sources allow you to capture an output from one action and automatically inject it as a parameter in subsequent actions. This is ideal when you need to use the value in templates or allow users to override the value if needed.
How It Works
- During
install, a step captures an output using jsonPath or regex from the command output - You declare a bundle-level output to make this value available
- You define a parameter with a
sourcefield that references the output - During
upgradeoruninstall, Porter automatically provides the output’s last value - You reference the value using
${bundle.parameters.PARAM_NAME}in your steps - If the output doesn’t exist yet (first install), users can provide it via the parameter
Example: Virtual Machine ID
Here’s a complete example showing how to remember a VM instance ID:
schemaVersion: 1.0.1
name: my-vm-bundle
version: 0.1.0
mixins:
- exec
# Declare the bundle-level output
outputs:
- name: instance-id
type: string
description: The ID of the created virtual machine
applyTo:
- install
# Define a parameter that sources its value from the output
parameters:
- name: instance-id
type: string
description: The virtual machine instance ID
# This parameter only applies to upgrade and uninstall
# During install, we generate it; we don't need it as input
applyTo:
- upgrade
- uninstall
source:
output: instance-id
install:
- exec:
description: "Create virtual machine"
command: create-vm
arguments:
- --name
- myvm
- --format
- json
# Capture the output from the command
outputs:
- name: instance-id
jsonPath: "$.id"
upgrade:
- exec:
description: "Upgrade virtual machine"
command: echo
arguments:
- "Upgrading VM: ${bundle.parameters.instance-id}"
uninstall:
- exec:
description: "Delete virtual machine"
command: delete-vm
arguments:
- --id
- "${bundle.parameters.instance-id}"Using Parameter Values in Templates
One major advantage of parameter sources is that you can access them in templates:
upgrade:
- exec:
description: "Upgrade VM ${bundle.parameters.instance-id}"
command: upgrade-vm
arguments:
- --id
- "${bundle.parameters.instance-id}"Sourcing From Dependencies
You can also source parameters from outputs generated by bundle dependencies:
parameters:
- name: connection-string
type: string
source:
dependency: mysql
output: connstrUser Overrides
Users can override parameter source values if needed:
porter upgrade myvm --param instance-id=vm-12345
This is useful for recovery scenarios or when manually managing resources.
Approach 2: State Files
The state feature allows Porter to automatically persist files between bundle runs. This is ideal for
tool-specific state files (like terraform.tfstate) or configuration files that don’t need to be
exposed as parameters.
How It Works
- You declare which file paths should be persisted in the
statesection - When a bundle completes, Porter saves any files at those paths
- On the next bundle run, Porter automatically restores those files
- Your bundle can read/write these files directly from the filesystem
Important Limitation
State files cannot be accessed via templates or environment variables. You cannot use
bundle.parameters.X or $PARAMETER_NAME to access state data. The files are simply
restored to the filesystem for your tools to read directly.
Example: Terraform State
Here’s a complete example using Terraform state files:
schemaVersion: 1.0.1
name: terraform-bundle
version: 0.1.0
mixins:
- terraform
# Declare which files should be persisted
state:
- name: tfstate
path: terraform/terraform.tfstate
description: Terraform state file
- name: tfvars
path: terraform/terraform.tfvars.json
description: Terraform variables
install:
- terraform:
description: "Create infrastructure"
input: false
vars:
location: eastus
upgrade:
- terraform:
description: "Update infrastructure"
input: false
# The terraform.tfstate file is automatically restored here
# Terraform reads it directly from the filesystem
uninstall:
- terraform:
description: "Destroy infrastructure"
input: false
# The terraform.tfstate file is automatically restored here
# Terraform needs it to know what to destroyState File Paths
Relative paths in the state section are relative to the bundle directory (/cnab/app):
state:
- name: kubeconfig
path: .kube/config # Resolves to /cnab/app/.kube/config
- name: ssh-key
path: /root/.ssh/id_rsa # Absolute pathWhen State Files Are Saved
Porter saves state files when:
- The bundle action completes successfully
- The file exists at the specified path
Porter restores state files:
- Before each bundle action runs (except the first install)
Choosing the Right Approach
Use this decision guide to choose the appropriate mechanism:
Use Parameter Sources When:
- ✅ You need to use the value in templates (
${bundle.parameters.X}) - ✅ The data is a string, number, boolean, or small object/file
- ✅ You want users to be able to see or override the value
- ✅ The data represents an identifier, connection string, or configuration value
Examples: VM instance IDs, database connection strings, resource names, API endpoints, account IDs
Use State Files When:
- ✅ A tool generates its own state file format (Terraform, Helm, etc.)
- ✅ The file is large or binary
- ✅ You don’t need to access the data in templates or as variables
- ✅ You want to hide implementation details from users
- ✅ The tool reads the file directly from a specific path
Examples: terraform.tfstate, kubeconfig, .terraform.lock.hcl, SSH keys, certificate files
Combining Both Approaches
You can use both mechanisms together in the same bundle. For example, you might:
- Use state for Terraform’s
.tfstatefile - Use parameter sources to capture Terraform outputs (like resource IDs) for use in other commands
state:
- name: tfstate
path: terraform/terraform.tfstate
outputs:
- name: cluster-id
type: string
parameters:
- name: cluster-id
type: string
source:
output: cluster-id
applyTo:
- upgrade
- uninstall
install:
- terraform:
description: "Create cluster"
- exec:
description: "Capture cluster ID"
command: bash
flags:
c: |
# Extract output from Terraform and save as Porter output
CLUSTER_ID=$(terraform output -raw cluster_id)
mkdir -p /cnab/app/porter/outputs
echo -n "$CLUSTER_ID" > /cnab/app/porter/outputs/cluster-id
upgrade:
- exec:
description: "Configure cluster ${bundle.parameters.cluster-id}"
command: configure-cluster
arguments:
- "${bundle.parameters.cluster-id}"
- terraform:
description: "Update infrastructure"Working with File Parameters
When using parameter sources with type: file, the file content is persisted and restored:
outputs:
- name: ssh-key
type: file
path: /cnab/app/ssh-key.pem
parameters:
- name: ssh-key
type: file
path: /cnab/app/ssh-key.pem
source:
output: ssh-key
applyTo:
- upgrade
- uninstallThis gives you template/variable access plus file persistence. However, for purely file-based
workflows where you don’t need template access, state is simpler.
Troubleshooting
Parameter source value is empty
If your parameter source isn’t working:
- Verify the output was actually created during the previous action
- Check that the output file path is correct:
/cnab/app/porter/outputs/<output-name> - Ensure the output definition exists in your manifest
- Review the bundle logs:
porter installation logs show <installation-name>
State file not restored
If your state file isn’t being restored:
- Verify the file was created during the previous action at the exact path specified
- Check that the path in the
statesection matches exactly (including absolute vs. relative) - Ensure the previous action completed successfully
- State files are only restored on subsequent runs, not during the first install
Cannot access state data in templates
This is expected behavior. State files cannot be accessed via bundle.parameters.X or environment
variables. If you need template/variable access, use parameter sources instead.
See Also
- Bundle Manifest Reference - Complete manifest syntax
- Parameters - Parameter configuration
- Outputs - Output configuration
- State - State configuration
- Using Templates - Template syntax and functions
- Working with Dependencies - Sourcing outputs from dependencies