Skip to content

Commit 6ed8df7

Browse files
list: add dynamic attribute type (#1180)
* remove irrelevant comment on lists and maps of objects * add dynamic attribute to list schemas * update comment for dynamic attribute Co-authored-by: Austin Valle <[email protected]> --------- Co-authored-by: Austin Valle <[email protected]>
1 parent 283721d commit 6ed8df7

File tree

4 files changed

+656
-6
lines changed

4 files changed

+656
-6
lines changed

list/schema/dynamic_attribute.go

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package schema
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-go/tftypes"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/attr"
10+
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
11+
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema/fwxschema"
12+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
13+
"github.com/hashicorp/terraform-plugin-framework/types"
14+
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
15+
)
16+
17+
// Ensure the implementation satisifies the desired interfaces.
18+
var (
19+
_ Attribute = DynamicAttribute{}
20+
_ fwxschema.AttributeWithDynamicValidators = DynamicAttribute{}
21+
)
22+
23+
// DynamicAttribute represents a schema attribute that is a dynamic, rather
24+
// than a single static type. Static types are always preferable over dynamic
25+
// types in Terraform as practitioners will receive less helpful configuration
26+
// assistance from validation error diagnostics and editor integrations. When
27+
// retrieving the value for this attribute, use types.Dynamic as the value type
28+
// unless the CustomType field is set.
29+
//
30+
// The concrete value type for a dynamic is determined at runtime by Terraform, if defined in the configuration.
31+
type DynamicAttribute struct {
32+
// CustomType enables the use of a custom attribute type in place of the
33+
// default basetypes.DynamicType. When retrieving data, the basetypes.DynamicValuable
34+
// associated with this custom type must be used in place of types.Dynamic.
35+
CustomType basetypes.DynamicTypable
36+
37+
// Required indicates whether the practitioner must enter a value for
38+
// this attribute or not. Required and Optional cannot both be true.
39+
Required bool
40+
41+
// Optional indicates whether the practitioner can choose to enter a value
42+
// for this attribute or not. Optional and Required cannot both be true.
43+
Optional bool
44+
45+
// Description is used in various tooling, like the language server, to
46+
// give practitioners more information about what this attribute is,
47+
// what it's for, and how it should be used. It should be written as
48+
// plain text, with no special formatting.
49+
Description string
50+
51+
// MarkdownDescription is used in various tooling, like the
52+
// documentation generator, to give practitioners more information
53+
// about what this attribute is, what it's for, and how it should be
54+
// used. It should be formatted using Markdown.
55+
MarkdownDescription string
56+
57+
// DeprecationMessage defines warning diagnostic details to display when
58+
// practitioner configurations use this Attribute. The warning diagnostic
59+
// summary is automatically set to "Attribute Deprecated" along with
60+
// configuration source file and line information.
61+
//
62+
// Set this field to a practitioner actionable message such as:
63+
//
64+
// - "Configure other_attribute instead. This attribute will be removed
65+
// in the next major version of the provider."
66+
// - "Remove this attribute's configuration as it no longer is used and
67+
// the attribute will be removed in the next major version of the
68+
// provider."
69+
//
70+
// In Terraform 1.2.7 and later, this warning diagnostic is displayed any
71+
// time a practitioner attempts to configure a value for this attribute and
72+
// certain scenarios where this attribute is referenced.
73+
//
74+
// In Terraform 1.2.6 and earlier, this warning diagnostic is only
75+
// displayed when the Attribute is Required or Optional, and if the
76+
// practitioner configuration sets the value to a known or unknown value
77+
// (which may eventually be null). It has no effect when the Attribute is
78+
// Computed-only (read-only; not Required or Optional).
79+
//
80+
// Across any Terraform version, there are no warnings raised for
81+
// practitioner configuration values set directly to null, as there is no
82+
// way for the framework to differentiate between an unset and null
83+
// configuration due to how Terraform sends configuration information
84+
// across the protocol.
85+
//
86+
// Additional information about deprecation enhancements for read-only
87+
// attributes can be found in:
88+
//
89+
// - https://github.com/hashicorp/terraform/issues/7569
90+
//
91+
DeprecationMessage string
92+
93+
// Validators define value validation functionality for the attribute. All
94+
// elements of the slice of AttributeValidator are run, regardless of any
95+
// previous error diagnostics.
96+
//
97+
// Many common use case validators can be found in the
98+
// github.com/hashicorp/terraform-plugin-framework-validators Go module.
99+
//
100+
// If the Type field points to a custom type that implements the
101+
// xattr.TypeWithValidate interface, the validators defined in this field
102+
// are run in addition to the validation defined by the type.
103+
Validators []validator.Dynamic
104+
}
105+
106+
// ApplyTerraform5AttributePathStep always returns an error as it is not
107+
// possible to step further into a DynamicAttribute.
108+
func (a DynamicAttribute) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
109+
return a.GetType().ApplyTerraform5AttributePathStep(step)
110+
}
111+
112+
// Equal returns true if the given Attribute is a DynamicAttribute
113+
// and all fields are equal.
114+
func (a DynamicAttribute) Equal(o fwschema.Attribute) bool {
115+
if _, ok := o.(DynamicAttribute); !ok {
116+
return false
117+
}
118+
119+
return fwschema.AttributesEqual(a, o)
120+
}
121+
122+
// GetDeprecationMessage returns the DeprecationMessage field value.
123+
func (a DynamicAttribute) GetDeprecationMessage() string {
124+
return a.DeprecationMessage
125+
}
126+
127+
// GetDescription returns the Description field value.
128+
func (a DynamicAttribute) GetDescription() string {
129+
return a.Description
130+
}
131+
132+
// GetMarkdownDescription returns the MarkdownDescription field value.
133+
func (a DynamicAttribute) GetMarkdownDescription() string {
134+
return a.MarkdownDescription
135+
}
136+
137+
// GetType returns types.DynamicType or the CustomType field value if defined.
138+
func (a DynamicAttribute) GetType() attr.Type {
139+
if a.CustomType != nil {
140+
return a.CustomType
141+
}
142+
143+
return types.DynamicType
144+
}
145+
146+
// IsComputed returns false because it does not apply to ListResource schemas.
147+
func (a DynamicAttribute) IsComputed() bool {
148+
return false
149+
}
150+
151+
// IsOptional returns the Optional field value.
152+
func (a DynamicAttribute) IsOptional() bool {
153+
return a.Optional
154+
}
155+
156+
// IsRequired returns the Required field value.
157+
func (a DynamicAttribute) IsRequired() bool {
158+
return a.Required
159+
}
160+
161+
// IsSensitive returns false because it does not apply to ListResource schemas.
162+
func (a DynamicAttribute) IsSensitive() bool {
163+
return false
164+
}
165+
166+
// IsWriteOnly returns false as write-only attributes are not relevant to ephemeral resource schemas,
167+
// as these schemas describe data that is explicitly not saved to any artifact.
168+
func (a DynamicAttribute) IsWriteOnly() bool {
169+
return false
170+
}
171+
172+
// DynamicValidators returns the Validators field value.
173+
func (a DynamicAttribute) DynamicValidators() []validator.Dynamic {
174+
return a.Validators
175+
}
176+
177+
// IsRequiredForImport returns false as this behavior is only relevant
178+
// for managed resource identity schema attributes.
179+
func (a DynamicAttribute) IsRequiredForImport() bool {
180+
return false
181+
}
182+
183+
// IsOptionalForImport returns false as this behavior is only relevant
184+
// for managed resource identity schema attributes.
185+
func (a DynamicAttribute) IsOptionalForImport() bool {
186+
return false
187+
}

0 commit comments

Comments
 (0)