Hello,
In a SingleNestedAttribute, I think that computed attributes do not coexist well with optional-computed .
Here is my code, I have a SingleNestedAttribute that contains a configurable boolean and a read-only info.
{
...
"firewall": schema.SingleNestedAttribute{
Optional: true,
Computed: true,
Attributes: map[string]schema.Attribute{
"enabled": schema.BoolAttribute{
Optional: true,
Computed: true,
PlanModifiers: []planmodifier.Bool{
modifiers.BoolDefault(true), // true if not specified
},
},
"ports": schema.StringAttribute{
Computed: true,
},
},
...
}
Here is my main.tf (in both examples, firewall.enabled = true)
resource "elestio_postgres" "mypostgres1" {
name
}
resource "elestio_postgres" "mypostgres2" {
name
firewall = {
enabled = true
}
}
If I execute terraform apply
or terraform plan
, mypostgres2 will always detect a change, event if the firewall is already enabled.
I know that it comes from these attributes because postgres1 does not have the problem.
If I remove the ports attribute, the problem disappears.
Do you know a solution?
I don’t really want to create two singleNestedAttributes with configurable ones on one side, and read-only ones on the other.
Thanks for your time
Hey I think we have the same problem:
opened 05:13PM - 21 Dec 22 UTC
bug
waiting-response
### Module version
```
github.com/hashicorp/terraform-plugin-framework v1.0.1
…
```
### Relevant provider source code
This is adding the following diff to https://github.com/iwarapter/terraform-provider-pingfederate/commit/bb0e6075159d55a549b51ea7c884a255d9b3ccdf
The resource is defined: https://github.com/iwarapter/terraform-provider-pingfederate/blob/bb0e6075159d55a549b51ea7c884a255d9b3ccdf/internal/framework/schemes.go#L192-L643
```go
diff --git a/internal/framework/schemes.go b/internal/framework/schemes.go
index 53bd5bc..86293cc 100644
--- a/internal/framework/schemes.go
+++ b/internal/framework/schemes.go
@@ -377,22 +377,22 @@ func resourceClient() schema.Schema {
"oidc_policy": schema.SingleNestedAttribute{
Description: `Open ID Connect Policy settings. This is included in the message only when OIDC is enabled.`,
Optional: true,
- //Computed: true,
- Attributes: singleClientOIDCPolicy(),
- //PlanModifiers: []planmodifier.Object{
- // defaults.DefaultObject(map[string]attr.Value{
- // "grant_access_session_revocation_api": types.BoolValue(false),
- // "grant_access_session_session_management_api": types.BoolValue(false),
- // "id_token_content_encryption_algorithm": types.StringValue("RS256"),
- // "sector_identifier_uri": types.StringNull(),
- // "policy_group": types.StringNull(),
- // "pairwise_identifier_user_type": types.BoolNull(),
- // "ping_access_logout_capable": types.BoolNull(),
- // "id_token_encryption_algorithm": types.StringNull(),
- // "logout_uris": types.ListUnknown(types.StringType),
- // "id_token_signing_algorithm": types.StringNull(),
- // }),
- //},
+ Computed: true,
+ Attributes: singleClientOIDCPolicy(),
+ PlanModifiers: []planmodifier.Object{
+ defaults.DefaultObject(map[string]attr.Value{
+ "grant_access_session_revocation_api": types.BoolValue(false),
+ "grant_access_session_session_management_api": types.BoolValue(false),
+ "id_token_content_encryption_algorithm": types.StringValue("RS256"),
+ "sector_identifier_uri": types.StringNull(),
+ "policy_group": types.StringNull(),
+ "pairwise_identifier_user_type": types.BoolNull(),
+ "ping_access_logout_capable": types.BoolNull(),
+ "id_token_encryption_algorithm": types.StringNull(),
+ "logout_uris": types.ListUnknown(types.StringType),
+ "id_token_signing_algorithm": types.StringNull(),
+ }),
+ },
},
"pending_authorization_timeout_override": schema.NumberAttribute{
Description: `The 'device_code' and 'user_code' timeout, in seconds. This overrides the 'pendingAuthorizationTimeout' value present in Authorization Server Settings.`,
```
### Terraform Configuration Files
<!--
Paste the relevant parts of your Terraform configuration between the ``` marks below.
For large Terraform configs, please use a service like Dropbox and share a link to the ZIP file. For security, you can also encrypt the files using our GPG public key.
-->
```hcl
resource "pingfederate_oauth_client" "example" {
client_id = "acc_test_withoutoidc"
name = "acc_test_withoutoidc"
grant_types = ["ACCESS_TOKEN_VALIDATION"]
restrict_scopes = true
restricted_scopes = ["openid"]
}
```
### Debug Output
<!--
Full debug output can be obtained by running Terraform with the environment variable `TF_LOG=trace`. Please create a GitHub Gist containing the debug output. Please do _not_ paste the debug output in the issue, since debug output is long.
Debug output may contain sensitive information. Please review it before posting publicly, and if you are concerned feel free to encrypt the files using the HashiCorp security public key.
-->
### Expected Behavior
When the default plan modifier is added to the object, defaults are provided.
### Actual Behavior
When the `oidc_policy` default Plan Modifier is added in, it causes other attributes to show as changing:
```
=== CONT TestAccPingFederateOAuthClientResource
pingfederate_oauth_client_test.go:46: Step 1/3 error: After applying this test step, the plan was not empty.
stdout:
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# pingfederate_oauth_client.example1 will be updated in-place
~ resource "pingfederate_oauth_client" "example1" {
+ client_secret_changed_time = (known after apply)
id = "tf-acc-woot"
name = "my-client-name"
# (30 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
```
### Steps to Reproduce
With the plan modifier added tests fail: https://github.com/iwarapter/terraform-provider-pingfederate/pull/252
Here is a gist of the trace for the tests https://gist.github.com/iwarapter/8dc5a723e14e83e40e4280f928c7f236
### References
#582
bflad
January 9, 2023, 5:52pm
3
Hi @adamkrim Thank you for raising this topic.
Terraform requires knowing upfront during planning when an attribute value may change, otherwise it can cause a practitioner-facing error or, in the case of a Computed
only attribute, may require two applies to successfully update downstream value references. The framework opts to this unknown value behavior by default, rather than potentially letting provider developers unexpectedly cause practitioner-facing errors by default.
Is the ports
values expected to change ever? If not, adding the UseStateForUnknown()
plan modifier will prevent the framework from showing the known to unknown value plan difference by copying the existing prior state value into the planned value. If the value can change, then you will likely need to implement plan modification logic to match the API’s behavior (and Consider UnknownIf Attribute Plan Modifiers · Issue #605 · hashicorp/terraform-plugin-framework · GitHub might be of interest for something more baked into the framework).