Skip to content

secret_mappings: secret_reference_id given as UUID fails apply with "inconsistent result after apply" #69

Description

@roh26it

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

  1. 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).
  2. 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.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions