[Bug]: aws_bedrockagent_data_source: connector_parameters plans a whitespace-only update when the service stores the JSON in another key order
Description
aws_bedrockagent_data_source with data_source_configuration.managed_knowledge_base_connector_configuration.connector_parameters (added in v6.64.0) plans an in-place update marked # whitespace changes whenever the JSON document the service returns is serialised differently from the one jsonencode produces, even though the two are the same JSON. The attribute is a plain string, so the provider compares serialisations, not documents.
Two ways to get there, both seen on one data source (Confluence connector, managed knowledge base, eu-west-1):
- Create the data source with a document that omits keys the service fills in (
crawlIdentities,filterConfiguration.maxFileSizeInMegaBytes). Every following plan wants to updateconnector_parameters: the service now returns those keys, so the strings differ. Expected: a diff that shows the added keys, which it does, but writing them into the config only turns it into case 2. - With the document complete (every key the service returns is in the config), the next plan still shows
# whitespace changes:jsonencodesorts keys, the service returns them in the order it stored them. Oneapplythat re-sends the document clears it, because the service then stores and echoes the document in the order it received. Until that apply the plan is not clean, and a later edit in the console (or any change on the service side to the stored order) brings the diff back.
Case 2 is the part worth fixing: the plan proposes an update for a document that is semantically identical. Silencing it with ignore_changes would also hide a real change to the space list or the crawl scope.
The sibling attribute deletion_protection_threshold had a perpetual diff on the same resource (#49959) and was fixed by making the provider read the value back properly; connector_parameters needs the equivalent for JSON: a normalised JSON type (jsontypes.Normalized or a DiffSuppressFunc that compares parsed documents), the way aws_iam_policy.policy and other JSON attributes already behave.
Affected Resource(s) or Data Source(s)
aws_bedrockagent_data_source
Potential Terraform Configuration
resource "aws_bedrockagent_data_source" "guide" {
knowledge_base_id = aws_bedrockagent_knowledge_base.guide.id
name = "confluence-example-guide"
data_deletion_policy = "DELETE"
data_source_configuration {
type = "MANAGED_KNOWLEDGE_BASE_CONNECTOR"
managed_knowledge_base_connector_configuration {
connector_parameters = jsonencode({
type = "CONFLUENCE"
version = "1"
aclEnabled = false
crawlIdentities = false
connectionConfiguration = {
secretArn = data.aws_secretsmanager_secret.confluence.arn
type = "SAAS"
authType = "BASIC"
hostUrl = "https://example.atlassian.net"
}
dataEntityConfiguration = {
crawlPage = true
crawlBlog = false
crawlPageAttachment = false
crawlBlogAttachment = false
crawlArchivedSpace = false
crawlArchivedPage = false
crawlPersonalSpace = false
}
filterConfiguration = {
inclusionSpaceKeys = ["EXAMPLE"]
maxFileSizeInMegaBytes = "500"
}
})
media_extraction_configuration {
image_extraction_configuration {
image_extraction_status = "ENABLED"
}
}
deletion_protection_configuration {
deletion_protection_status = "ENABLED"
deletion_protection_threshold = 50
}
}
}
}Expected Behavior
A plan after a successful apply, with the config carrying every key the service returns, shows no change on connector_parameters, regardless of the key order the service stores.
Actual Behavior
# aws_bedrockagent_data_source.guide will be updated in-place
~ resource "aws_bedrockagent_data_source" "guide" {
id = "DSXXXXXXXX,KBXXXXXXXX"
name = "confluence-example-guide"
# (5 unchanged attributes hidden)
~ data_source_configuration {
# (1 unchanged attribute hidden)
~ managed_knowledge_base_connector_configuration {
~ connector_parameters = jsonencode( # whitespace changes
{
aclEnabled = false
connectionConfiguration = {
authType = "BASIC"
hostUrl = "https://example.atlassian.net"
secretArn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:example"
type = "SAAS"
}
crawlIdentities = false
dataEntityConfiguration = {
crawlArchivedPage = false
crawlArchivedSpace = false
crawlBlog = false
crawlBlogAttachment = false
crawlPage = true
crawlPageAttachment = false
crawlPersonalSpace = false
}
filterConfiguration = {
inclusionSpaceKeys = [
"EXAMPLE",
]
maxFileSizeInMegaBytes = "500"
}
type = "CONFLUENCE"
version = "1"
}
)
# (2 unchanged blocks hidden)
}
}
}The apply of exactly this plan succeeds and the next plan is clean.
Steps to Reproduce
- Create a managed knowledge base and the data source above with
connector_parametersmissingcrawlIdentitiesandmaxFileSizeInMegaBytes; apply. terraform plan: an update onconnector_parameters(the service added the two keys).- Add the two keys to the config with the values the service returned;
terraform plan:# whitespace changesonconnector_parameters. terraform apply;terraform plan: clean.
Terraform and AWS Provider Version
Terraform v1.16.1, provider hashicorp/aws v6.64.0.
Debug Output / Panic Output
None (no error; a plan that should be empty).
Important Factoids
- The knowledge base is
type = "MANAGED"with the managed embedding model; the connector isMANAGED_KNOWLEDGE_BASE_CONNECTOR/CONFLUENCE. crawlIdentitiesis not in the CreateDataSource connector reference; it is a key GetDataSource returns. That is what makes step 1 the usual starting point.
References
- #49959 (the sibling perpetual diff on
deletion_protection_threshold, same resource, same provider version) - https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-confluence-connect.html (the connector document)
Source: hashicorp/terraform-provider-aws