Skip to content

Conversation

bbasata
Copy link
Contributor

@bbasata bbasata commented May 27, 2025

Description

This pull request adds a top-level list package. list.ListResource is the Framework concept that defines a list block type, just as ephemeral.EphemeralResource defines an ephemeral block type and resource.Resource defines a resource block type.

A list resource always returns instances of a single managed resource type. For example, a random_pet list resource can only return instances of a random_pet managed resource type.

A developer can choose to implement the list.ListResource interface with an existing resource.Resource. This is intended to allow for cohesion between list resource logic and with managed resource CRUD logic.

A developer can instead choose to implement the list.ListResource interface separately from an existing resource.Resource. This is intended to allow for decoupling list resource logic from managed resource CRUD logic.

To allow for response data that exceeds the client's or server's maximum gRPC message size, the Plugin Protocol specifies a stream response for the ListResource RPC. Accordingly, the handler's result type is named list.ListResourceStream and it includes an iterator function of type iter.Seq[ListResourceEvent].

Rollback Plan

  • If a change needs to be reverted, we will roll out an update to the code within 7 days.

Changes to Security Controls

None.

@bbasata bbasata force-pushed the add-list-package branch from 0601f75 to e96088a Compare May 27, 2025 22:22
@bbasata bbasata force-pushed the add-list-package branch from e96088a to d7f3133 Compare May 27, 2025 23:08

package schema

type Schema struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Clearly, this is a (very) partial implementation of a schema type 😃 In the interest of small pull requests, I'd like to save the details for the next PR.

// Metadata can satisfy both interfaces.
Metadata(context.Context, resource.MetadataRequest, *resource.MetadataResponse)

// ListResourceConfigSchema should return the schema for list blocks.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ConfigValidators, we have the precedent of a comment about method naming, such as:

	// This method name is separate from ConfigValidators in resource and other packages in
	// order to allow generic validators.

This method is not named Schema for a similar reason. To comment or not to comment?

ListResource

// ListResourceConfigValidators returns a list of functions which will all be performed during validation.
ListResourceConfigValidators(context.Context) []ConfigValidator
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ConfigValidators, we have the precedent of a comment about method naming, such as:

	// This method name is separate from ConfigValidators in resource and other packages in
	// order to allow generic validators.

This method is not named ConfigValidators for a similar reason. To comment or not to comment?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it might be worth being a little more specific in what these validators are used for at some point (i.e. list config validation when used with terraform query), then point to the other method name for resource config validation.

Same for the other methods

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 – will revisit the comments in a follow-up PR.

ListResource

// ValidateListResourceConfig performs the validation.
ValidateListResourceConfig(context.Context, ValidateConfigRequest, *ValidateConfigResponse)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ConfigValidators, we have the precedent of a comment about method naming, such as:

	// This method name is separate from ConfigValidators in resource and other packages in
	// order to allow generic validators.

This method is not named ValidateConfig for a similar reason. To comment or not to comment?

// The method signature is intended to be compatible with the Metadata
// method signature in the Resource interface. One implementation of
// Metadata can satisfy both interfaces.
Metadata(context.Context, resource.MetadataRequest, *resource.MetadataResponse)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A trade-off of compatibility: a bit of overloading of resource.MetadataRequest and resource.MetadataResponse. I think it's ok. I'm also open to improving on this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense, i briefly mentioned that you could share the interfaces internally if you wanted in our 1/1, but that would mean you couldn't write a descriptive package comment for the method, so not really a big deal to duplicate imo.

// signature is intended to be compatible with the Configure method
// signature in the Resource interface. One implementation of Configure can
// satisfy both interfaces.
Configure(context.Context, resource.ConfigureRequest, *resource.ConfigureResponse)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A trade-off of compatibility: a bit of overloading of resource.ConfigureRequest and resource.ConfigureResponse. I think it's ok. I'm also open to improving on this.

@bbasata bbasata marked this pull request as ready for review May 28, 2025 19:51
@bbasata bbasata requested a review from a team as a code owner May 28, 2025 19:51
@bbasata bbasata added this to the v1.16.0 milestone May 28, 2025
Copy link
Member

@austinvalle austinvalle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am halfway between ListResource and List 😆 , left some thoughts. I do like the interface design in general 👍🏻

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package list
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thought about the package location. Since list is coupled to managed resource (i.e. can't list without some managed resource existing in the provider), should we move all of these packages under resource?

resource/list
resource/list/schema

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😃 I started from resource and ended up in a top-level list package.

I took a cue from: an instance of a "list resource" corresponds to a "list block" in Terraform.

So from a config perspective, list feels okay at the level of resource and ephemeral. And the import paths feel simpler.

And we leave the door open for our understanding of list to evolve.

Schema: c.Schema,
TerraformValue: c.Raw,
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A note for later, eventually we'll need some form of Set* methods here. Typically providers are always supplementing data, i.e., we already created the object, populated some config data in, the provider "sets" the other attributes in the state, then we return it to Terraform.

Here, it might be a little different, we are creating the objects from scratch, so maybe different helpers can assist with that.

// The method signature is intended to be compatible with the Metadata
// method signature in the Resource interface. One implementation of
// Metadata can satisfy both interfaces.
Metadata(context.Context, resource.MetadataRequest, *resource.MetadataResponse)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense, i briefly mentioned that you could share the interfaces internally if you wanted in our 1/1, but that would mean you couldn't write a descriptive package comment for the method, so not really a big deal to duplicate imo.

@bbasata
Copy link
Contributor Author

bbasata commented May 29, 2025

Private is just data that can be passed around in memory and not referenced. If we don't have that in the protocol, then no need to add here. Provider meta shouldn't be applicable here and there are no client capabilities for this RPC yet. So none of them are applicable ATM 😃

✅ I've removed the TODO comment (012fb27).

@bbasata
Copy link
Contributor Author

bbasata commented May 29, 2025

Should we call this just tfsdk.Resource? 🤔

I'm 👍 on this. Shipping it.

Would it be too far to say that ResourceObject == State?

I think: [1] yes, they are two names for the same "underlying type," [2] I'd like to de-duplicate if possible, [3] maybe they are not aliases – one should not be assignable to the other (var state State = resourceObject // 💭 ), and [4] maybe they should be able to evolve independently.

💭 What if we extract an unexported type?

type valueWithSchema {
    Raw ...
    Schema ...
}

func (v *valueWithSchema) Get(...) { ... }

type Resource {
    valueWithSchema
}

type State {
    valueWithSchema
}

@bbasata
Copy link
Contributor Author

bbasata commented May 29, 2025

I feel like even omitting Resource would also be fine here. ListSchema, IdentitySchema, Schema

For consistency within the list package, I lean toward keeping ListResource in names of things that define the behavior of "a ListResource". With the exception of the List method itself.

@bbasata bbasata requested a review from austinvalle May 29, 2025 16:14
ListResource

// ListResourceConfigValidators returns a list of functions which will all be performed during validation.
ListResourceConfigValidators(context.Context) []ConfigValidator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it might be worth being a little more specific in what these validators are used for at some point (i.e. list config validation when used with terraform query), then point to the other method name for resource config validation.

Same for the other methods

@bbasata
Copy link
Contributor Author

bbasata commented May 30, 2025

No changelog entry for the moment. We'll write a feature-level changelog entry 🔜.

@bbasata bbasata merged commit 6997cf5 into main May 30, 2025
35 checks passed
@bbasata bbasata deleted the add-list-package branch May 30, 2025 20:21
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 30, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants