dbt-labs / dbt-labs/terraform-provider-dbtcloud
dbtcloud_postgres_credential: id always shows (known after apply) when using password_wo
- Dominant language
- Go
- Stars
- 117
- Forks
- 37
- Avg merge
- 9h 1m
- Merged PRs (30d)
- 6
Description
## Description
Any `dbtcloud_postgres_credential` resource that uses `password_wo` (the write-only password argument) shows an in-place update on **every** `terraform plan`, even when nothing has actually changed. The only visible attribute in the diff is `id`:
```
# dbtcloud_postgres_credential.example will be updated in-place
!~ resource "dbtcloud_postgres_credential" "example" {
!~ id = "*************" -> (known after apply)
# (11 unchanged attributes hidden)
}
```
This happens on a clean, unmodified config with no other drift — confirmed by comparing against the live dbt Cloud API, where all 11 hidden attributes genuinely match.
## Root cause (from reading the provider source)
1. `password_wo` has no companion `ModifyPlan` logic in [`resource.go`](https://github.com/dbt-labs/terraform-provider-dbtcloud/blob/765cc5634133d1d6c58a9b7cebe673493392b23f/pkg/framework/objects/postgres_credential/resource.go). The docstring for `password_wo_version` says it's required "to trigger updates," but nothing in the resource actually reads/compares it to decide whether an update is needed — so the resource is unconditionally considered for update whenever `password_wo` is set, regardless of `password_wo_version`.
2. In [`schema.go`](https://github.com/dbt-labs/terraform-provider-dbtcloud/blob/765cc5634133d1d6c58a9b7cebe673493392b23f/pkg/framework/objects/postgres_credential/schema.go#L57-L60), the `id` attribute is `Computed` with no `PlanModifiers`:
```go
"id": resource_schema.StringAttribute{
Computed: true,
Description: "The ID of this resource. Contains the project ID and the credential ID.",
},
```
Compare to `credential_id` a few lines below, which correctly has `UseStateForUnknown()`:
```go
"credential_id": resource_schema.Int64Attribute{
Computed: true,
...
PlanModifiers: []planmodifier.Int64{
int64planmodifier.UseStateForUnknown(),
},
},
```
Since `id` is just `fmt.Sprintf("%d:%d", project_id, credential_id)` — both of which are already stable and known — it should never need to be recomputed as unknown. The missing plan modifier means it gets marked unknown any time the resource is touched for update, which surfaces as the only visible line in the diff.
## Impact
- Every `terraform apply` re-sends the plaintext password to the dbt Cloud API even when it hasn't changed.
- Noisy plans make it harder to spot genuine drift for these resources, since they always show as needing an update.
- This likely affects the other `_wo\" resources in the provider using the same write-only pattern (e.g. `dbtcloud_snowflake_credential`'s `private_key_wo`) if they share the same gap — I haven't audited those, but the underlying pattern is presumably shared.
## Expected behavior
- `terraform plan` should show no changes for a `dbtcloud_postgres_credential` resource using `password_wo` when `password_wo_version` is unchanged and no other attribute differs.
- At minimum, `id` should carry `UseStateForUnknown()` so it doesn't spuriously appear in the diff.
## Terraform / provider versions
- `dbtcloud` provider: `1.11.1`
- Terraform: `>= 1.11` (required for write-only argument support)
## Reproduction
```hcl
resource "dbtcloud_postgres_credential" "example" {
default_schema = "target"
is_active = true
num_threads = 4
password_wo = var.pg_password
password_wo_version = 1
project_id = dbtcloud_project.example.id
target_name = "default"
username = var.pg_username
}
```
Run `terraform plan` twice in a row with no config changes in between — the second plan still shows `id` as `(known after apply)` and the resource as "will be updated in-place."
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.