Skip to content

Commit e3b212d

Browse files
committed
datasource/schema: Initial package
Reference: #132 Reference: #326 Reference: #437 Reference: #491 Reference: #508 Reference: #532 This change introduces a new `datasource/schema` package, which contains schema interfaces and types relevant to data sources, such as omitting plan modifiers and schema versioning. This new schema implementation also provides strongly typed attributes, nested attributes, and blocks with customizable types. Nested attributes and blocks are exposed with a separate nested object for customization and validation. The implementation leans heavily on the design choice of the framework being responsible for preventing provider developer runtime errors. The tailored fields no longer expose functionality that is not available for data sources. The framework design will also raise compiler-time errors for errant typing of validators.
1 parent 488e688 commit e3b212d

File tree

97 files changed

+13330
-363
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+13330
-363
lines changed

.changelog/pending.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:note
2+
datasource: The `DataSource` type `GetSchema` method has been deprecated. Use the `Schema` method instead.
3+
```
4+
5+
```release-note:feature
6+
datasource/schema: New package which contains schema interfaces and types relevant to data sources
7+
```

datasource/data_source.go

+23-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
)
99

1010
// DataSource represents an instance of a data source type. This is the core
11-
// interface that all data sources must implement.
11+
// interface that all data sources must implement. Data sources must also
12+
// implement the Schema method or the deprecated GetSchema method. The Schema
13+
// method will be required in a future version.
1214
//
1315
// Data sources can optionally implement these additional concepts:
1416
//
@@ -20,9 +22,6 @@ type DataSource interface {
2022
// examplecloud_thing.
2123
Metadata(context.Context, MetadataRequest, *MetadataResponse)
2224

23-
// GetSchema returns the schema for this data source.
24-
GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics)
25-
2625
// Read is called when the provider must read data source values in
2726
// order to update state. Config values should be read from the
2827
// ReadRequest and new state values set on the ReadResponse.
@@ -60,6 +59,26 @@ type DataSourceWithConfigValidators interface {
6059
ConfigValidators(context.Context) []ConfigValidator
6160
}
6261

62+
// DataSourceWithGetSchema is a temporary interface type that extends
63+
// DataSource to include the deprecated GetSchema method.
64+
type DataSourceWithGetSchema interface {
65+
DataSource
66+
67+
// GetSchema returns the schema for this data source.
68+
//
69+
// Deprecated: Use Schema method instead.
70+
GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics)
71+
}
72+
73+
// DataSourceWithSchema is a temporary interface type that extends
74+
// DataSource to include the new Schema method.
75+
type DataSourceWithSchema interface {
76+
DataSource
77+
78+
// Schema should return the schema for this data source.
79+
Schema(context.Context, SchemaRequest, *SchemaResponse)
80+
}
81+
6382
// DataSourceWithValidateConfig is an interface type that extends DataSource to include imperative validation.
6483
//
6584
// Declaring validation using this methodology simplifies one-off

datasource/schema.go

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package datasource
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
5+
"github.com/hashicorp/terraform-plugin-framework/diag"
6+
)
7+
8+
// SchemaRequest represents a request for the DataSource to return its schema.
9+
// An instance of this request struct is supplied as an argument to the
10+
// DataSource type Schema method.
11+
type SchemaRequest struct{}
12+
13+
// SchemaResponse represents a response to a SchemaRequest. An instance of this
14+
// response struct is supplied as an argument to the DataSource type Schema
15+
// method.
16+
type SchemaResponse struct {
17+
// Schema is the schema of the data source.
18+
Schema schema.Schema
19+
20+
// Diagnostics report errors or warnings related to validating the data
21+
// source configuration. An empty slice indicates success, with no warnings
22+
// or errors generated.
23+
Diagnostics diag.Diagnostics
24+
}

datasource/schema/attribute.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package schema
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
5+
)
6+
7+
// Attribute define a value field inside the Schema. Implementations in this
8+
// package include:
9+
// - BoolAttribute
10+
// - Float64Attribute
11+
// - Int64Attribute
12+
// - ListAttribute
13+
// - MapAttribute
14+
// - NumberAttribute
15+
// - ObjectAttribute
16+
// - SetAttribute
17+
// - StringAttribute
18+
//
19+
// Additionally, the NestedAttribute interface extends Attribute with nested
20+
// attributes. Only supported in protocol version 6. Implementations in this
21+
// package include:
22+
// - ListNestedAttribute
23+
// - MapNestedAttribute
24+
// - SetNestedAttribute
25+
// - SingleNestedAttribute
26+
//
27+
// In practitioner configurations, an equals sign (=) is required to set
28+
// the value. [Configuration Reference]
29+
//
30+
// [Configuration Reference]: https://developer.hashicorp.com/terraform/language/syntax/configuration
31+
type Attribute interface {
32+
fwschema.Attribute
33+
}

datasource/schema/block.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package schema
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
5+
)
6+
7+
// Block defines a structural field inside a Schema. Implementations in this
8+
// package include:
9+
// - ListNestedBlock
10+
// - SetNestedBlock
11+
// - SingleNestedBlock
12+
//
13+
// In practitioner configurations, an equals sign (=) cannot be used to set the
14+
// value. Blocks are instead repeated as necessary, or require the use of
15+
// [Dynamic Block Expressions].
16+
//
17+
// Prefer NestedAttribute over Block. Blocks should typically be used for
18+
// configuration compatibility with previously existing schemas from an older
19+
// Terraform Plugin SDK. Efforts should be made to convert from Block to
20+
// NestedAttribute as a breaking change for practitioners.
21+
//
22+
// [Dynamic Block Expressions]: https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks
23+
//
24+
// [Configuration Reference]: https://developer.hashicorp.com/terraform/language/syntax/configuration
25+
type Block interface {
26+
fwschema.Block
27+
}

datasource/schema/bool_attribute.go

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

0 commit comments

Comments
 (0)