UpCloud Pulumi Provider ManagedObjectStoragePolicy Recreated When Description Is Omitted
Hey guys! Today, we're diving into a quirky issue with the UpCloud Pulumi provider that can cause some unexpected resource recreations. Specifically, we're talking about the ManagedObjectStoragePolicy
and how omitting the Description
field can lead to it being replaced on every Pulumi run. Let's break down what's happening and how to fix it.
The Problem: Recreated ManagedObjectStoragePolicy
So, here's the deal: if you're using the ManagedObjectStoragePolicy
resource in your Pulumi code and you happen to leave out the Description
field, you might notice that Pulumi wants to recreate this policy every time you run pulumi up
. This can be a bit of a head-scratcher, especially since the diff might not immediately scream out the reason for the replacement.
Digging into the Details
To give you a clearer picture, here’s what you might see in your Pulumi output when you run pulumi pre --diff
:
10:37:33 ❯ pulumi pre --diff
Previewing update (dev)
Compiling the program ...
Finished compiling
pulumi:pulumi:Stack: (same)
[urn=urn:pulumi:dev::bug-repro::pulumi:pulumi:Stack::bug-repro-dev]
+-upcloud:index/managedObjectStoragePolicy:ManagedObjectStoragePolicy: (replace)
[id=129f13d4-0b25-4ed7-a894-6139eb9b0884/example]
[urn=urn:pulumi:dev::bug-repro::upcloud:index/managedObjectStoragePolicy:ManagedObjectStoragePolicy::this]
[provider=urn:pulumi:dev::bug-repro::pulumi:providers:upcloud::default_0_5_3_github_/api.github.com/UpCloudLtd/pulumi-upcloud::fc11e34a-0fc1-4ad7-b8a2-4595f1f42286]
~ arn : "urn:ecs:iam::129f13d40b254ed7a8946139eb9b0884:policy/example" => [unknown]
~ attachmentCount : 0 => [unknown]
~ createdAt : "2025-09-30 07:37:31 +0000 UTC" => [unknown]
~ defaultVersionId: "v1" => [unknown]
- description : ""
document : "%7B%22Version%22%3A%20%222012-10-17%22%2C%20%20%22Statement%22%3A%20%5B%7B%22Action%22%3A%20%5B%22iam%3AGetUser%22%5D%2C%20%22Resource%22%3A%20%22%2A%..."
~ id : "129f13d4-0b25-4ed7-a894-6139eb9b0884/example" => [unknown]
name : "example"
serviceUuid : "129f13d4-0b25-4ed7-a894-6139eb9b0884"
~ system : false => [unknown]
~ updatedAt : "2025-09-30 07:37:31 +0000 UTC" => [unknown]
Resources:
+-1 to replace
2 unchanged
And when you run pulumi up
, you'll see something like this:
10:41:26 ❯ pulumi up
Previewing update (dev)
Type Name Plan
pulumi:pulumi:Stack bug-repro-dev
+- └─ upcloud:index:ManagedObjectStoragePolicy this replace
Resources:
+-1 to replace
2 unchanged
Notice that the ManagedObjectStoragePolicy
is marked for replacement. The key here is the missing description
. Pulumi detects a change because the Description
field, which the UpCloud API likely defaults to an empty string, is not explicitly set in your Pulumi code. This discrepancy triggers the replacement.
This ManagedObjectStoragePolicy recreation issue is a significant concern because it leads to unnecessary resource churn and can disrupt your infrastructure management workflows. Imagine you have numerous policies defined, and each one is being recreated on every run simply because of a missing description. This not only wastes resources but also increases the risk of unintended side effects.
Why This Happens
The root cause of this behavior likely lies within the UpCloud Pulumi provider's handling of the Description
field. When the field is omitted in your Pulumi code, the provider doesn't send any value for the description
during the resource creation or update. The UpCloud API, in turn, likely defaults this field to an empty string. However, on subsequent Pulumi runs, the provider detects a difference between the desired state (no description) and the actual state (empty string description), triggering a replacement.
This issue highlights the importance of explicitly managing all resource properties, even those that might seem optional. While it's tempting to omit fields that have default values, doing so can lead to unexpected behavior and resource drift. In the case of the ManagedObjectStoragePolicy
, explicitly setting the Description
field, even to an empty string, ensures that Pulumi correctly tracks the resource's state and avoids unnecessary recreations.
Sample Program: The Culprit
Here's a snippet of Go code that demonstrates the issue. This example is straight from the ManagedObjectStoragePolicy
documentation page, but with the Description
field unset:
package main
import (
"github.com/UpCloudLtd/pulumi-upcloud/sdk/go/upcloud"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
this, err := upcloud.NewManagedObjectStorage(ctx, "this", &upcloud.ManagedObjectStorageArgs{
Name: pulumi.String("example"),
Region: pulumi.String("europe-1"),
ConfiguredStatus: pulumi.String("started"),
})
if err != nil {
return err
}
_, err = upcloud.NewManagedObjectStoragePolicy(ctx, "this", &upcloud.ManagedObjectStoragePolicyArgs{
Name: pulumi.String("example"),
Document: pulumi.String("%7B%22Version%22%3A%20%222012-10-17%22%2C%20%20%22Statement%22%3A%20%5B%7B%22Action%22%3A%20%5B%22iam%3AGetUser%22%5D%2C%20%22Resource%22%3A%20%22%2A%22%2C%20%22Effect%22%3A%20%22Allow%22%2C%20%22Sid%22%3A%20%22editor%22%7D%5D%7D"),
ServiceUuid: this.ID(),
})
if err != nil {
return err
}
return nil
})
}
Reproducing the Issue
To see this in action, just run pulumi up
twice in a row with this code. You'll notice that the ManagedObjectStoragePolicy
gets recreated on the second run.
The Fix
The simplest fix is to add a Description
field to your ManagedObjectStoragePolicyArgs
. It doesn't even matter if the description is empty – just including the field is enough to prevent the recreation. Here's how you can modify the code:
_, err = upcloud.NewManagedObjectStoragePolicy(ctx, "this", &upcloud.ManagedObjectStoragePolicyArgs{
Name: pulumi.String("example"),
Document: pulumi.String("%7B%22Version%22%3A%20%222012-10-17%22%2C%20%20%22Statement%22%3A%20%5B%7B%22Action%22%3A%20%5B%22iam%3AGetUser%22%5D%2C%20%22Resource%22%3A%20%22%2A%22%2C%20%22Effect%22%3A%20%22Allow%22%2C%20%22Sid%22%3A%20%22editor%22%7D%5D%7D"),
ServiceUuid: this.ID(),
Description: pulumi.String(""), // Add this line
})
Run pulumi up
again, and you'll see that the policy no longer gets recreated unnecessarily.
Log Output and Affected Resources
If you're running into this, you might not see any specific errors in the logs, but the diff and update previews will clearly show the ManagedObjectStoragePolicy
being replaced. The affected resource is, of course, the ManagedObjectStoragePolicy
itself.
Pulumi About
Here's the output of pulumi about
from the environment where this issue was observed:
CLI
Version 3.198.0
Go Version go1.25.1
Go Compiler gc
Plugins
KIND NAME VERSION
language go 3.198.0
resource upcloud 0.5.3
Host
OS darwin
Version 15.6.1
Arch arm64
This project is written in go: executable='/Users/oula/.local/share/mise/installs/go/1.25.1/bin/go' version='go version go1.25.1 darwin/arm64'
Current Stack: bug-repro/dev
TYPE URN
pulumi:pulumi:Stack urn:pulumi:dev::bug-repro::pulumi:pulumi:Stack::bug-repro-dev
pulumi:providers:upcloud urn:pulumi:dev::bug-repro::pulumi:providers:upcloud::default_0_5_3_github_/api.github.com/UpCloudLtd/pulumi-upcloud
upcloud:index/managedObjectStorage:ManagedObjectStorage urn:pulumi:dev::bug-repro::upcloud:index/managedObjectStorage:ManagedObjectStorage::this
upcloud:index/managedObjectStoragePolicy:ManagedObjectStoragePolicy urn:pulumi:dev::bug-repro::upcloud:index/managedObjectStoragePolicy:ManagedObjectStoragePolicy::this
Found no pending operations associated with dev
Backend
Name pulumi.com
URL https://app.pulumi.com/oula-kuuva
User oula-kuuva
Organizations oula-kuuva
Token type personal
Dependencies:
NAME VERSION
github.com/pulumi/pulumi/sdk/v3 v3.198.0
github.com/UpCloudLtd/pulumi-upcloud/sdk v0.5.3
Pulumi locates its logs in /var/folders/1y/httmdjmd02qf57f9zd3py6kw0000gn/T/ by default
Additional Context
It's suspected that this issue might stem from the underlying Terraform provider, but further investigation would be needed to confirm. If you're curious, feel free to dig into the Terraform provider code and see if you can spot the culprit!
Contributing
If you've run into this issue, give it a 👍 reaction to show your support. If you're feeling adventurous and want to contribute a fix, leave a comment and link to your pull request. Let's make the UpCloud Pulumi provider even better together!
In Summary
The key takeaway here is that omitting the Description
field in your ManagedObjectStoragePolicy
can lead to unnecessary resource recreations. The simple fix is to explicitly set the Description
, even if it's just to an empty string. This ensures that Pulumi correctly manages the resource's state and avoids unwanted replacements. Keep this in mind, and you'll save yourself some headaches down the road! Happy Pulumi-ing, guys!