Skip to content

Commit d514911

Browse files
committed
Update logic to check null/unknowness in both the container and underlying value
1 parent 624dbc4 commit d514911

File tree

1 file changed

+53
-106
lines changed

1 file changed

+53
-106
lines changed

internal/fwserver/attribute_validation.go

Lines changed: 53 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -101,96 +101,63 @@ func AttributeValidate(ctx context.Context, a fwschema.Attribute, req ValidateAt
101101
return
102102
}
103103

104-
// Dynamic values need to perform more logic to check the config value for null/unknown-ness
105-
dynamicValuable, ok := attributeConfig.(basetypes.DynamicValuable)
106-
if ok {
104+
configHasNullValue := attributeConfig.IsNull()
105+
configHasUnknownValue := attributeConfig.IsUnknown()
106+
// If the value is dynamic, we still need to check if the underlying value is null or unknown
107+
if dynamicValuable, isDynamic := attributeConfig.(basetypes.DynamicValuable); !configHasNullValue && !configHasUnknownValue && isDynamic {
107108
dynamicConfigVal, diags := dynamicValuable.ToDynamicValue(ctx)
108109
resp.Diagnostics.Append(diags...)
109110
if diags.HasError() {
110111
return
111112
}
112-
113-
// Terraform CLI does not automatically perform certain configuration
114-
// checks yet. If it eventually does, this logic should remain at least
115-
// until Terraform CLI versions 0.12 through the release containing the
116-
// checks are considered end-of-life.
117-
// Reference: https://github.com/hashicorp/terraform/issues/30669
118-
if a.IsComputed() && !a.IsOptional() && !dynamicConfigVal.IsUnderlyingValueNull() {
119-
resp.Diagnostics.AddAttributeError(
120-
req.AttributePath,
121-
"Invalid Configuration for Read-Only Attribute",
122-
"Cannot set value for this attribute as the provider has marked it as read-only. Remove the configuration line setting the value.\n\n"+
123-
"Refer to the provider documentation or contact the provider developers for additional information about configurable and read-only attributes that are supported.",
124-
)
113+
if dynamicConfigVal.IsUnderlyingValueNull() {
114+
configHasNullValue = true
125115
}
126116

127-
// Terraform CLI does not automatically perform certain configuration
128-
// checks yet. If it eventually does, this logic should remain at least
129-
// until Terraform CLI versions 0.12 through the release containing the
130-
// checks are considered end-of-life.
131-
// Reference: https://github.com/hashicorp/terraform/issues/30669
132-
if a.IsRequired() && dynamicConfigVal.IsUnderlyingValueNull() {
133-
resp.Diagnostics.AddAttributeError(
134-
req.AttributePath,
135-
"Missing Configuration for Required Attribute",
136-
fmt.Sprintf("Must set a configuration value for the %s attribute as the provider has marked it as required.\n\n", req.AttributePath.String())+
137-
"Refer to the provider documentation or contact the provider developers for additional information about configurable attributes that are required.",
138-
)
117+
if dynamicConfigVal.IsUnderlyingValueUnknown() {
118+
configHasUnknownValue = true
139119
}
120+
}
140121

141-
// If the client doesn't support write-only attributes (first supported in Terraform v1.11.0), then we raise an early validation error
142-
// to avoid a confusing data consistency error when the provider attempts to return "null" for a write-only attribute in the planned/final state.
143-
//
144-
// Write-only attributes can only be successfully used with a supporting client, so the only option for a practitoner to utilize a write-only attribute
145-
// is to upgrade their Terraform CLI version to v1.11.0 or later.
146-
if !req.ClientCapabilities.WriteOnlyAttributesAllowed && a.IsWriteOnly() && !dynamicConfigVal.IsUnderlyingValueNull() {
147-
resp.Diagnostics.AddAttributeError(
148-
req.AttributePath,
149-
"WriteOnly Attribute Not Allowed",
150-
fmt.Sprintf("The resource contains a non-null value for WriteOnly attribute %s. Write-only attributes are only supported in Terraform 1.11 and later.", req.AttributePath.String()),
151-
)
152-
}
153-
} else {
154-
// Terraform CLI does not automatically perform certain configuration
155-
// checks yet. If it eventually does, this logic should remain at least
156-
// until Terraform CLI versions 0.12 through the release containing the
157-
// checks are considered end-of-life.
158-
// Reference: https://github.com/hashicorp/terraform/issues/30669
159-
if a.IsComputed() && !a.IsOptional() && !attributeConfig.IsNull() {
160-
resp.Diagnostics.AddAttributeError(
161-
req.AttributePath,
162-
"Invalid Configuration for Read-Only Attribute",
163-
"Cannot set value for this attribute as the provider has marked it as read-only. Remove the configuration line setting the value.\n\n"+
164-
"Refer to the provider documentation or contact the provider developers for additional information about configurable and read-only attributes that are supported.",
165-
)
166-
}
122+
// Terraform CLI does not automatically perform certain configuration
123+
// checks yet. If it eventually does, this logic should remain at least
124+
// until Terraform CLI versions 0.12 through the release containing the
125+
// checks are considered end-of-life.
126+
// Reference: https://github.com/hashicorp/terraform/issues/30669
127+
if a.IsComputed() && !a.IsOptional() && !configHasNullValue {
128+
resp.Diagnostics.AddAttributeError(
129+
req.AttributePath,
130+
"Invalid Configuration for Read-Only Attribute",
131+
"Cannot set value for this attribute as the provider has marked it as read-only. Remove the configuration line setting the value.\n\n"+
132+
"Refer to the provider documentation or contact the provider developers for additional information about configurable and read-only attributes that are supported.",
133+
)
134+
}
167135

168-
// Terraform CLI does not automatically perform certain configuration
169-
// checks yet. If it eventually does, this logic should remain at least
170-
// until Terraform CLI versions 0.12 through the release containing the
171-
// checks are considered end-of-life.
172-
// Reference: https://github.com/hashicorp/terraform/issues/30669
173-
if a.IsRequired() && attributeConfig.IsNull() {
174-
resp.Diagnostics.AddAttributeError(
175-
req.AttributePath,
176-
"Missing Configuration for Required Attribute",
177-
fmt.Sprintf("Must set a configuration value for the %s attribute as the provider has marked it as required.\n\n", req.AttributePath.String())+
178-
"Refer to the provider documentation or contact the provider developers for additional information about configurable attributes that are required.",
179-
)
180-
}
136+
// Terraform CLI does not automatically perform certain configuration
137+
// checks yet. If it eventually does, this logic should remain at least
138+
// until Terraform CLI versions 0.12 through the release containing the
139+
// checks are considered end-of-life.
140+
// Reference: https://github.com/hashicorp/terraform/issues/30669
141+
if a.IsRequired() && configHasNullValue {
142+
resp.Diagnostics.AddAttributeError(
143+
req.AttributePath,
144+
"Missing Configuration for Required Attribute",
145+
fmt.Sprintf("Must set a configuration value for the %s attribute as the provider has marked it as required.\n\n", req.AttributePath.String())+
146+
"Refer to the provider documentation or contact the provider developers for additional information about configurable attributes that are required.",
147+
)
148+
}
181149

182-
// If the client doesn't support write-only attributes (first supported in Terraform v1.11.0), then we raise an early validation error
183-
// to avoid a confusing data consistency error when the provider attempts to return "null" for a write-only attribute in the planned/final state.
184-
//
185-
// Write-only attributes can only be successfully used with a supporting client, so the only option for a practitoner to utilize a write-only attribute
186-
// is to upgrade their Terraform CLI version to v1.11.0 or later.
187-
if !req.ClientCapabilities.WriteOnlyAttributesAllowed && a.IsWriteOnly() && !attributeConfig.IsNull() {
188-
resp.Diagnostics.AddAttributeError(
189-
req.AttributePath,
190-
"WriteOnly Attribute Not Allowed",
191-
fmt.Sprintf("The resource contains a non-null value for WriteOnly attribute %s. Write-only attributes are only supported in Terraform 1.11 and later.", req.AttributePath.String()),
192-
)
193-
}
150+
// If the client doesn't support write-only attributes (first supported in Terraform v1.11.0), then we raise an early validation error
151+
// to avoid a confusing data consistency error when the provider attempts to return "null" for a write-only attribute in the planned/final state.
152+
//
153+
// Write-only attributes can only be successfully used with a supporting client, so the only option for a practitoner to utilize a write-only attribute
154+
// is to upgrade their Terraform CLI version to v1.11.0 or later.
155+
if !req.ClientCapabilities.WriteOnlyAttributesAllowed && a.IsWriteOnly() && !configHasNullValue {
156+
resp.Diagnostics.AddAttributeError(
157+
req.AttributePath,
158+
"WriteOnly Attribute Not Allowed",
159+
fmt.Sprintf("The resource contains a non-null value for WriteOnly attribute %s. Write-only attributes are only supported in Terraform 1.11 and later.", req.AttributePath.String()),
160+
)
194161
}
195162
req.AttributeConfig = attributeConfig
196163

@@ -224,33 +191,13 @@ func AttributeValidate(ctx context.Context, a fwschema.Attribute, req ValidateAt
224191
AttributeValidateNestedAttributes(ctx, a, req, resp)
225192

226193
// Show deprecation warnings only for known values.
227-
if a.GetDeprecationMessage() != "" && !attributeConfig.IsNull() && !attributeConfig.IsUnknown() {
228-
// Dynamic values need to perform more logic to check the config value for null/unknown-ness
229-
dynamicValuable, ok := attributeConfig.(basetypes.DynamicValuable)
230-
if !ok {
231-
resp.Diagnostics.AddAttributeWarning(
232-
req.AttributePath,
233-
"Attribute Deprecated",
234-
a.GetDeprecationMessage(),
235-
)
236-
return
237-
}
238-
239-
dynamicConfigVal, diags := dynamicValuable.ToDynamicValue(ctx)
240-
resp.Diagnostics.Append(diags...)
241-
if diags.HasError() {
242-
return
243-
}
244-
245-
// For dynamic values, it's possible to be known when only the type is known.
246-
// The underlying value can still be null or unknown, so check for that here
247-
if !dynamicConfigVal.IsUnderlyingValueNull() && !dynamicConfigVal.IsUnderlyingValueUnknown() {
248-
resp.Diagnostics.AddAttributeWarning(
249-
req.AttributePath,
250-
"Attribute Deprecated",
251-
a.GetDeprecationMessage(),
252-
)
253-
}
194+
if a.GetDeprecationMessage() != "" && !configHasNullValue && !configHasUnknownValue {
195+
resp.Diagnostics.AddAttributeWarning(
196+
req.AttributePath,
197+
"Attribute Deprecated",
198+
a.GetDeprecationMessage(),
199+
)
200+
return
254201
}
255202
}
256203

0 commit comments

Comments
 (0)