Skip to content

Commit d7f3133

Browse files
committed
list: add types for ListResource support
1 parent 80ed136 commit d7f3133

File tree

8 files changed

+377
-0
lines changed

8 files changed

+377
-0
lines changed

list/config_validator.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package list
5+
6+
import "context"
7+
8+
// ConfigValidator describes reusable ListResource configuration validation
9+
// functionality.
10+
type ConfigValidator interface {
11+
// Description describes the validation in plain text formatting.
12+
//
13+
// This information may be automatically added to list resource plain text
14+
// descriptions by external tooling.
15+
Description(context.Context) string
16+
17+
// MarkdownDescription describes the validation in Markdown formatting.
18+
//
19+
// This information may be automatically added to list resource Markdown
20+
// descriptions by external tooling.
21+
MarkdownDescription(context.Context) string
22+
23+
// ValidateResource performs the validation.
24+
//
25+
// This method name is separate from ConfigValidators in resource and other packages in
26+
// order to allow generic validators.
27+
ValidateListResourceConfig(context.Context, ValidateConfigRequest, *ValidateConfigResponse)
28+
}

list/list_resource.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package list
5+
6+
import (
7+
"context"
8+
"iter"
9+
10+
"github.com/hashicorp/terraform-plugin-framework/diag"
11+
"github.com/hashicorp/terraform-plugin-framework/resource"
12+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
13+
)
14+
15+
// ListResource represents an implementation of listing instances of a managed resource
16+
// This is the core interface for all list resource implementations.
17+
//
18+
// ListResource implementations can optionally implement these additional concepts:
19+
//
20+
// - Configure: Include provider-level data or clients.
21+
// - Validation: Schema-based or entire configuration via
22+
// ListResourceWithConfigValidators or ListResourceWithValidateConfig.
23+
type ListResource interface {
24+
// Metadata should return the full name of the list resource such as
25+
// examplecloud_thing. This name should match the full name of the managed
26+
// resource to be listed; otherwise, the GetMetadata RPC will return an
27+
// error diagnostic.
28+
//
29+
// The method signature is intended to be compatible with the Metadata
30+
// method signature in the Resource interface. One implementation of
31+
// Metadata can satisfy both interfaces.
32+
Metadata(context.Context, resource.MetadataRequest, *resource.MetadataResponse)
33+
34+
// ListResourceConfigSchema should return the schema for list blocks.
35+
ListResourceConfigSchema(context.Context, ListResourceSchemaRequest, *ListResourceSchemaResponse)
36+
37+
// ListResource is called when the provider must list instances of a
38+
// managed resource type that satisfy a user-provided request.
39+
ListResource(context.Context, ListResourceRequest, *ListResourceResponse)
40+
}
41+
42+
// ListResourceWithConfigure is an interface type that extends ListResource to include a method
43+
// which the framework will automatically call so provider developers have the
44+
// opportunity to setup any necessary provider-level data or clients.
45+
type ListResourceWithConfigure interface {
46+
ListResource
47+
48+
// Configure enables provider-level data or clients to be set. The method
49+
// signature is intended to be compatible with the Configure method
50+
// signature in the Resource interface. One implementation of Configure can
51+
// satisfy both interfaces.
52+
Configure(context.Context, resource.ConfigureRequest, *resource.ConfigureResponse)
53+
}
54+
55+
// ListResourceWithConfigValidators is an interface type that extends
56+
// ListResource to include declarative validations.
57+
//
58+
// Declaring validation using this methodology simplifies implementation of
59+
// reusable functionality. These also include descriptions, which can be used
60+
// for automating documentation.
61+
//
62+
// Validation will include ListResourceConfigValidators and
63+
// ValidateListResourceConfig, if both are implemented, in addition to any
64+
// Attribute or Type validation.
65+
type ListResourceWithConfigValidators interface {
66+
ListResource
67+
68+
// ListResourceConfigValidators returns a list of functions which will all be performed during validation.
69+
ListResourceConfigValidators(context.Context) []ConfigValidator
70+
}
71+
72+
// ListResourceWithValidateConfig is an interface type that extends ListResource to include
73+
// imperative validation.
74+
//
75+
// Declaring validation using this methodology simplifies one-off
76+
// functionality that typically applies to a single resource. Any documentation
77+
// of this functionality must be manually added into schema descriptions.
78+
//
79+
// Validation will include ListResourceConfigValidators and ValidateListResourceConfig, if both
80+
// are implemented, in addition to any Attribute or Type validation.
81+
type ListResourceWithValidateConfig interface {
82+
ListResource
83+
84+
// ValidateListResourceConfig performs the validation.
85+
ValidateListResourceConfig(context.Context, ValidateConfigRequest, *ValidateConfigResponse)
86+
}
87+
88+
// ListResourceRequest represents a request for the provider to list instances
89+
// of a managed resource type that satisfy a user-defined request. An instance
90+
// of this reqeuest struct is passed as an argument to the provider's
91+
// ListResource function implementation.
92+
type ListResourceRequest struct {
93+
// Config is the configuration the user supplied for listing resource
94+
// instances.
95+
Config tfsdk.Config
96+
97+
// IncludeResourceObject indicates whether the provider should populate
98+
// the ResourceObject field in the ListResourceEvent struct.
99+
IncludeResourceObject bool
100+
101+
// TODO: consider applicability of:
102+
//
103+
// Private *privatestate.ProviderData
104+
// ProviderMeta tfsdk.Config
105+
// ClientCapabilities ReadClientCapabilities
106+
}
107+
108+
// ListResourceResponse represents a response to a ListResourceRequest. An
109+
// instance of this response struct is supplied as an argument to the
110+
// provider's ListResource function implementation function. The provider
111+
// should set an iterator function on the response struct.
112+
type ListResourceResponse struct {
113+
// Results is a function that emits ListResourceEvent values via its yield
114+
// function argument.
115+
Results iter.Seq[ListResourceEvent]
116+
}
117+
118+
// ListResourceEvent represents a listed managed resource instance. A
119+
// provider's ListResource function implementation will emit zero or more
120+
// events for a user-provided request.
121+
type ListResourceEvent struct {
122+
// Identity is the identity of the managed resource instance.
123+
//
124+
// A nil value will raise will raise a diagnostic.
125+
Identity *tfsdk.ResourceIdentity
126+
127+
// ResourceObject is the provider's representation of the attributes of the
128+
// listed managed resource instance.
129+
//
130+
// If ListResourceRequest.IncludeResourceObject is true, a nil value will raise
131+
// a warning diagnostic.
132+
ResourceObject *tfsdk.ResourceObject
133+
134+
// DisplayName is a provider-defined human-readable description of the
135+
// listed managed resource instance, intended for CLI and browser UIs.
136+
DisplayName string
137+
138+
// Diagnostics report errors or warnings related to the listed managed
139+
// resource instance. An empty slice indicates a successful operation with
140+
// no warnings or errors generated.
141+
Diagnostics diag.Diagnostics
142+
}
143+
144+
// ValidateConfigRequest represents a request to validate the configuration of
145+
// a list resource. An instance of this request struct is supplied as an
146+
// argument to the ValidateListResourceConfig receiver method or automatically
147+
// passed through to each ListResourceConfigValidator.
148+
type ValidateConfigRequest struct {
149+
// Config is the configuration the user supplied for the resource.
150+
//
151+
// This configuration may contain unknown values if a user uses
152+
// interpolation or other functionality that would prevent Terraform
153+
// from knowing the value at request time.
154+
Config tfsdk.Config
155+
}
156+
157+
// ValidateConfigResponse represents a response to a ValidateConfigRequest. An
158+
// instance of this response struct is supplied as an argument to the
159+
// list.ValidateListResourceConfig receiver method or automatically passed
160+
// through to each ConfigValidator.
161+
type ValidateConfigResponse struct {
162+
// Diagnostics report errors or warnings related to validating the list
163+
// configuration. An empty slice indicates success, with no warnings
164+
// or errors generated.
165+
Diagnostics diag.Diagnostics
166+
}

list/list_resource_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package list_test
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/list"
10+
"github.com/hashicorp/terraform-plugin-framework/resource"
11+
)
12+
13+
type ComputeInstanceResource struct {
14+
NoOpListResource
15+
NoOpResource
16+
}
17+
18+
type ComputeInstanceWithValidateListResourceConfig struct {
19+
ComputeInstanceResource
20+
}
21+
22+
type ComputeInstanceWithListResourceConfigValidators struct {
23+
ComputeInstanceResource
24+
}
25+
26+
func (c *ComputeInstanceResource) Configure(_ context.Context, _ resource.ConfigureRequest, _ *resource.ConfigureResponse) {
27+
}
28+
29+
func (c *ComputeInstanceResource) Metadata(_ context.Context, _ resource.MetadataRequest, _ *resource.MetadataResponse) {
30+
}
31+
32+
func (c *ComputeInstanceWithValidateListResourceConfig) ValidateListResourceConfig(_ context.Context, _ list.ValidateConfigRequest, _ *list.ValidateConfigResponse) {
33+
}
34+
35+
func (c *ComputeInstanceWithListResourceConfigValidators) ListResourceConfigValidators(_ context.Context) []list.ConfigValidator {
36+
return nil
37+
}
38+
39+
// ExampleResource_listable demonstrates a resource.Resource that implements
40+
// list.ListResource interfaces.
41+
func ExampleResource_listable() {
42+
var _ list.ListResource = &ComputeInstanceResource{}
43+
var _ list.ListResourceWithConfigure = &ComputeInstanceResource{}
44+
var _ list.ListResourceWithValidateConfig = &ComputeInstanceWithValidateListResourceConfig{}
45+
var _ list.ListResourceWithConfigValidators = &ComputeInstanceWithListResourceConfigValidators{}
46+
47+
var _ resource.Resource = &ComputeInstanceResource{}
48+
var _ resource.ResourceWithConfigure = &ComputeInstanceResource{}
49+
50+
// Output:
51+
}

list/no_op_list_resource_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package list_test
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/list"
10+
)
11+
12+
type NoOpListResource struct{}
13+
14+
func (*NoOpListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceSchemaRequest, _ *list.ListResourceSchemaResponse) {
15+
}
16+
17+
func (*NoOpListResource) ListResource(_ context.Context, _ list.ListResourceRequest, _ *list.ListResourceResponse) {
18+
}

list/no_op_resource_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package list_test
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/resource"
10+
)
11+
12+
type NoOpResource struct{}
13+
14+
func (*NoOpResource) Schema(_ context.Context, _ resource.SchemaRequest, _ *resource.SchemaResponse) {
15+
}
16+
17+
func (*NoOpResource) Create(_ context.Context, _ resource.CreateRequest, _ *resource.CreateResponse) {
18+
}
19+
20+
func (*NoOpResource) Read(_ context.Context, _ resource.ReadRequest, _ *resource.ReadResponse) {
21+
}
22+
23+
func (*NoOpResource) Update(_ context.Context, _ resource.UpdateRequest, _ *resource.UpdateResponse) {
24+
}
25+
26+
func (*NoOpResource) Delete(_ context.Context, _ resource.DeleteRequest, _ *resource.DeleteResponse) {
27+
}

list/schema.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package list
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/diag"
8+
"github.com/hashicorp/terraform-plugin-framework/list/schema"
9+
)
10+
11+
// ListResourceSchemaRequest represents a request for the ListResource to
12+
// return its schema. An instance of this request struct is supplied as an
13+
// argument to the ListResource type ListResourceSchema method.
14+
type ListResourceSchemaRequest struct{}
15+
16+
// ListResourceSchemaResponse represents a response to a
17+
// ListResourceSchemaRequest. An instance of this response struct is supplied
18+
// as an argument to the ListResource type ListResourceResourceSchema method.
19+
type ListResourceSchemaResponse struct {
20+
// Schema is the schema of the list resource.
21+
Schema schema.Schema
22+
23+
// Diagnostics report errors or warnings related to retrieving the list
24+
// resource schema. An empty slice indicates success, with no warnings
25+
// or errors generated.
26+
Diagnostics diag.Diagnostics
27+
}

list/schema/schema.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package schema
5+
6+
type Schema struct {
7+
}

tfsdk/resource_object.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package tfsdk
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/diag"
10+
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
11+
"github.com/hashicorp/terraform-plugin-framework/internal/fwschemadata"
12+
"github.com/hashicorp/terraform-plugin-framework/path"
13+
"github.com/hashicorp/terraform-plugin-go/tftypes"
14+
)
15+
16+
// ResourceObject represents a Terraform resource.
17+
type ResourceObject struct {
18+
Raw tftypes.Value
19+
Schema fwschema.Schema
20+
}
21+
22+
// Get populates the struct passed as `target` with the resource.
23+
func (c ResourceObject) Get(ctx context.Context, target interface{}) diag.Diagnostics {
24+
return c.data().Get(ctx, target)
25+
}
26+
27+
// GetAttribute retrieves the attribute or block found at `path` and populates
28+
// the `target` with the value. This method is intended for top level schema
29+
// attributes or blocks. Use `types` package methods or custom types to step
30+
// into collections.
31+
//
32+
// Attributes or elements under null or unknown collections return null
33+
// values, however this behavior is not protected by compatibility promises.
34+
func (c ResourceObject) GetAttribute(ctx context.Context, path path.Path, target interface{}) diag.Diagnostics {
35+
return c.data().GetAtPath(ctx, path, target)
36+
}
37+
38+
// PathMatches returns all matching path.Paths from the given path.Expression.
39+
//
40+
// If a parent path is null or unknown, which would prevent a full expression
41+
// from matching, the parent path is returned rather than no match to prevent
42+
// false positives.
43+
func (c ResourceObject) PathMatches(ctx context.Context, pathExpr path.Expression) (path.Paths, diag.Diagnostics) {
44+
return c.data().PathMatches(ctx, pathExpr)
45+
}
46+
47+
func (c ResourceObject) data() fwschemadata.Data {
48+
return fwschemadata.Data{
49+
Description: fwschemadata.DataDescriptionConfiguration,
50+
Schema: c.Schema,
51+
TerraformValue: c.Raw,
52+
}
53+
}

0 commit comments

Comments
 (0)