Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider Go Pointer Value Constructors and Getters for Primitive Types #649

Closed
bflad opened this issue Feb 3, 2023 · 1 comment · Fixed by #689
Closed

Consider Go Pointer Value Constructors and Getters for Primitive Types #649

bflad opened this issue Feb 3, 2023 · 1 comment · Fixed by #689
Assignees
Labels
enhancement New feature or request types Issues and pull requests about our types abstraction and implementations.
Milestone

Comments

@bflad
Copy link
Contributor

bflad commented Feb 3, 2023

Module version

v1.1.1

Use-cases

Provider developers with terraform-plugin-framework are typically encouraged to work with types package types for a consistent data model across Terraform configuration, plan, and state data. Configuration and plan data may contain unknown values, which an important distinction from other type systems, including Go's built-in types.

However, API-based SDKs opposite of Terraform may prefer pointer-based Go types for data handling. For example:

Given the current types package design which has methodologies for working directly with non-pointer Go types, it can therefore require extra pointer-based logic to correctly work with data between Terraform and the API SDK.

Attempted Solutions

These examples assume *bool API client value handling and schema.BoolAttribute / types.Bool on the Terraform side.

if client.Value == nil {
  data.Value = types.BoolNull()
}

data.Value = types.BoolValue(*client.Value)
if data.Value.IsNull() {
  client.Value = nil
} else {
  value := data.Value.ValueBool()
  client.Value = &value
}

Proposal

This proposal covers the following types in the framework type system:

Framework Type (FT) Go Type (GT)
basetypes.Bool bool
basetypes.Float64 float64
basetypes.Int64 int64
basetypes.String string

In the types/basetypes package, create New{FT}PointerValue(*GT) value creator functions. For example:

// NewBoolPointerValue creates a Bool with a null value if nil or a known value.
func NewBoolPointerValue(value *bool) BoolValue {
	if value == nil {
		return NewBoolNull()
	}

	return NewBoolValue(*value)
}

In the types package, wrapper functions would be created to use to their basetypes equivalent similar to the other value creator function aliases. For example:

// BoolPointerValue creates a Bool with a null value if nil or a known value.
func BoolPointerValue(value *bool) basetypes.BoolValue {
	return basetypes.NewBoolPointerValue(value)
}

In the types/basetypes package, create func (t {FT}) Value{GT}Pointer() *{GT} getter methods. For example:

// ValueBoolPointer returns a pointer to the known bool value, nil for a null bool value,
// or a pointer to false for an unknown bool value.
func (b BoolValue) ValueBoolPointer() *bool {
	if b.IsNull() {
		return nil
	}

	return &b.value
}

Note that this method implementation is similar to the existing func (t {FT}) Value{GT}() {GT} getter methods, where the design is intentionally skewed to provide a potentially invalid answer in the name of simplicity rather than introduce a second diag.Diagnostics return which must always be handled (or worse and forbidden in our typical design decisions, a panic). The non-pointer getter methods return the Go type's zero-value in the case of null and unknown. Provider developers are expected to check against a value's unknown state prior to these methods and Terraform will typically raise its own error should there be a data consistency issue.

These new functions and methods should enable provider code such as:

data.Value = types.BoolPointerValue(client.Value)
// and conversely
client.Value = data.Value.ValueBoolPointer()

References

@bflad bflad added enhancement New feature or request types Issues and pull requests about our types abstraction and implementations. labels Feb 3, 2023
@bflad bflad self-assigned this Mar 14, 2023
@bflad bflad added this to the v1.2.0 milestone Mar 14, 2023
bflad added a commit that referenced this issue Mar 14, 2023
bflad added a commit that referenced this issue Mar 15, 2023
…nt64, and String (#689)

Reference: #649

Co-authored-by: Austin Valle <[email protected]>
@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request types Issues and pull requests about our types abstraction and implementations.
Projects
None yet
1 participant