Skip to content

Investigate Consolidation of Schema Required/Optional/Computed #31

Open
@bflad

Description

@bflad

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.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    breaking-changeThis PR introduces a breaking change or the resolution of this issue may require a breaking change.enhancementNew feature or requestschemaIssues and pull requests about the abstraction for specifying schemas.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions