Summary
portkey_integration.secret_mappings[*].secret_reference_id is documented as accepting "the slug or UUID of the portkey_secret_reference" (docs/resources/integration.md:180), but passing a UUID makes every apply fail. Only the slug works.
Reproduction
resource "portkey_secret_reference" "test" {
name = "repro-sr"
manager_type = "hashicorp_vault"
secret_path = "kv/data/test/path"
vault_approle_auth = {
vault_addr = "https://vault.example.internal"
vault_role_id = "test-role-id"
vault_secret_id = "test-secret-id"
}
allow_all_workspaces = true
}
resource "portkey_integration" "test" {
name = "repro-int"
ai_provider_id = "openai"
secret_mappings = [
{
target_field = "key"
secret_reference_id = portkey_secret_reference.test.id # UUID -> fails
secret_key = "openai_key"
},
]
}
terraform apply:
Error: Provider produced inconsistent result after apply
When applying changes to portkey_integration.test, provider
"provider[\"registry.terraform.io/hashicorp/portkey\"]" produced an
unexpected new value: .secret_mappings: planned set element
cty.ObjectVal(map[string]cty.Value{"secret_key":cty.StringVal("openai_key"),
"secret_reference_id":cty.StringVal("2205a3a3-9c03-44a9-a3f1-70b79a3d62ff"),
"target_field":cty.StringVal("key")}) does not correlate with any element in
actual.
This is a bug in the provider, which should be reported in the provider's own
issue tracker.
Swapping .id for .slug makes the identical config apply cleanly.
Root cause
The API accepts a UUID on write but always echoes the slug back on read. Raw GET /integrations/{slug} for a mapping created with a UUID:
[
{
"secret_key": "openai_key",
"secret_reference_id": "tf-dbg-sr-vf-551840",
"target_field": "key"
}
]
secretMappingsFromClient (internal/provider/integration_resource.go:833-848) faithfully writes that slug into state. Because secret_mappings is a SetNestedAttribute, Terraform matches elements by whole-object value — a differing secret_reference_id means the planned element correlates with nothing in the result, and the framework raises the consistency error before the apply can complete.
Why it went unnoticed
There is currently no acceptance test anywhere in the repo that exercises secret_mappings. I confirmed the failure reproduces on main at eb86f73.
Possible fixes
- Normalize on read — if the prior state value for a mapping is a UUID and the API returns the slug for the same
target_field, keep the prior UUID in state. This preserves the documented "slug or UUID" contract at the cost of a prior-state lookup keyed on target_field (which ValidateConfig already guarantees is unique within the set).
- Resolve UUID → slug at request time so plan and state both hold the slug. Changes what the user sees in state versus what they wrote, so it would still need a plan modifier to avoid perpetual diffs.
- Document slug-only and add a validator rejecting UUID-shaped values with a clear message pointing at
.slug. Smallest change, but a functional regression against what the docs promise today.
Option 1 seems closest to correct. Whichever way it goes, it should land with an acceptance test covering both the .id and .slug forms.
Related
Found while reviewing #57 (value_format on secret_mappings). That PR is unaffected — its examples use .slug.
Summary
portkey_integration.secret_mappings[*].secret_reference_idis documented as accepting "theslugor UUID of theportkey_secret_reference" (docs/resources/integration.md:180), but passing a UUID makes every apply fail. Only the slug works.Reproduction
terraform apply:Swapping
.idfor.slugmakes the identical config apply cleanly.Root cause
The API accepts a UUID on write but always echoes the slug back on read. Raw
GET /integrations/{slug}for a mapping created with a UUID:[ { "secret_key": "openai_key", "secret_reference_id": "tf-dbg-sr-vf-551840", "target_field": "key" } ]secretMappingsFromClient(internal/provider/integration_resource.go:833-848) faithfully writes that slug into state. Becausesecret_mappingsis aSetNestedAttribute, Terraform matches elements by whole-object value — a differingsecret_reference_idmeans the planned element correlates with nothing in the result, and the framework raises the consistency error before the apply can complete.Why it went unnoticed
There is currently no acceptance test anywhere in the repo that exercises
secret_mappings. I confirmed the failure reproduces onmainat eb86f73.Possible fixes
target_field, keep the prior UUID in state. This preserves the documented "slug or UUID" contract at the cost of a prior-state lookup keyed ontarget_field(whichValidateConfigalready guarantees is unique within the set)..slug. Smallest change, but a functional regression against what the docs promise today.Option 1 seems closest to correct. Whichever way it goes, it should land with an acceptance test covering both the
.idand.slugforms.Related
Found while reviewing #57 (
value_formatonsecret_mappings). That PR is unaffected — its examples use.slug.