Description
Module version
v0.1.0
Use-cases
In Terraform Plugin SDK and v0.1.0 of this project, there are currently only a few meaningful valid configurations of Required
, Optional
, and Computed
for schema attributes. Switching these to a single field that captures the meaningful valid configurations means there is no way to misconfigure them and it is not losing any configurability. Setting these as false
is a perfectly valid implementation, just conventionally shied away from in most current schemas due to its unnecessary verbosity.
Mapping out the three possible boolean field declarations:
Required: true
: ✅Required: false
: ❌Required: true
+Optional: true
: ❌Required: true
+Optional: false
: 👍 (just verbose)Required: false
+Optional: true
: 👍 (just verbose)Required: false
+Optional: false
: ❌Required: true
+Computed: true
: ❌Required: true
+Computed: false
: 👍 (just verbose)Required: false
+Computed: true
: 👍 (just verbose)Required: false
+Computed: false
: ❌Optional: true
: ✅Optional: false
: ❌Optional: true
+Computed: true
: ✅Optional: false
+Computed: true
: 👍 (just verbose)Optional: true
+Computed: false
: 👍 (just verbose)Optional: false
+Computed: false
: ❌Computed: true
: ✅Computed: false
: ❌
In terms of static analysis, it is much easier to deal with one required field than three optional and conflicting ones. For example, it is relatively easy to write go/analysis
and semgrep
tooling that checks for the existence of a field declaration with a struct. Tooling and ensuring consistency around that is harder if you need to check values, let alone multiple of them, to ensure validity and any stylistic conventions. Not the biggest deal, but preferring no false
values for the current booleans requires additional static analysis, for example: https://github.com/bflad/tfproviderlint/tree/main/passes/S019.
Proposal
Quick sketch being:
const (
// Requires configuration.
AttributeConfigurationRequired AttributeConfiguration = 0
// Configuration is not required, but value can be optionally set.
// Shows difference if plugin returns value and there is no configuration.
AttributeConfigurationOptional AttributeConfiguration = 1
// Configuration is not required, but value can be optionally set.
// Does not show difference if plugin returns value and there is no configuration.
AttributeConfigurationOptionalComputed AttributeConfiguration = 2
// Cannot be configured, however the plugin can set the value.
AttributeConfigurationComputed AttributeConfiguration = 3
)
type AttributeConfiguration uint8
type Attribute struct {
// ... other fields ...
// The below would replace Required, Optional, and Computed
Configuration AttributeConfiguration
}
Which the naming can be adjusted as necessary, e.g. can be further reduced with any of dropping Attribute, Attribute to Attr, Configuration to Config, moving to a separate package, etc.