Does a TF provider support state shared between resources within a provider?

TLDR; does a TF provider support the sharing of data between resources, e.g. via state?

I am creating a provider for the Gravitee API gateway that uses its backend management API. Some of the configuration of the resources is extremely complicated, e.g. here is the call to create an API: API Reference. The schema for that POST request is going to be painful for developers to write as it’s so deeply nested.

Note how the OpenApi makes use of heterogeneous arrays, e.g. the listeners field is an array of objects, each of which is one of 3 types. I don’t believe I can represent this inside a TF schema. Am I wrong and if so, how should I handle this?

I’d like to simplify the resource schema to make it easier for developers by splitting it into several resources, e.g. an API resource and a number of listener resource types. I was thinking that a developer could define a listener resource that doesn’t actually do anything other than store itself in TF state and then an API resource could then pull in that config and then actually create/update the real resource via the Gravitee API.

For example:

resource gravitee_api_listener foo {
  ...
}

resource gravitee_api bar {
  ...
  listeners: [
    gravitee_api_listener.foo.id
  ]
}

Here the listener wouldn’t create anything, but its state/config would be made available to the api resource which would really create the resource. The developer has more, simpler, resources to define, instead of one mega-resource.

Is this feasible with TF, or is there another approach I should take here?

Hi @john_tipper :wave:

TLDR; does a TF provider support the sharing of data between resources, e.g. via state?

A provider resource does not have access to state for other resources managed by the same provider. There is discussion around some aspects of how to handle this situation in various posts relating to sharing state.

Note how the OpenApi makes use of heterogeneous arrays, e.g. the listeners field is an array of objects, each of which is one of 3 types. I don’t believe I can represent this inside a TF schema. Am I wrong and if so, how should I handle this?

One possible schema representation for the listeners field would be something along the following lines:

func (e *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
	resp.Schema = schema.Schema{
		Attributes: map[string]schema.Attribute{
			"listeners": schema.ListNestedAttribute{
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{
						"type": schema.StringAttribute{},
						"entry_points": schema.ListAttribute{
							ElementType: types.StringType, // assuming all strings ,
						},
						"servers": schema.ListAttribute{
							ElementType: types.StringType, // assuming all strings ,
						},
						"paths": schema.ListAttribute{
							ElementType: types.StringType, // assuming all strings ,
						},
						"path_mappings": schema.ListAttribute{
							ElementType: types.StringType, // assuming all strings ,
						},
						"cors": schema.SingleNestedAttribute{
							Attributes: map[string]schema.Attribute{
								"allow_credentials": schema.BoolAttribute{}, // assuming this is a bool,
								"allow_headers":     schema.BoolAttribute{}, // assuming this is a bool,
							},
						},
					},
				},
			},
		},
	}
}

I’d like to simplify the resource schema to make it easier for developers by splitting it into several resources, e.g. an API resource and a number of listener resource types. I was thinking that a developer could define a listener resource that doesn’t actually do anything other than store itself in TF state and then an API resource could then pull in that config and then actually create/update the real resource via the Gravitee API.

Can the listener resource be created independently from an API resource, and if so does it make sense to have the API resource depend upon previously created listener resource(s)? If this is the case, then perhaps you can separate out the managing of listener resource(s), from the API resource. However, if it is the case that there’s no concept of independent creation of these resources, and that the configuration for listener(s) (and endpointGroups, analytics) all need to be supplied when creating an API resource it likely makes more sense to have the schema and configuration of the API resource reflect this by having the schema and configuration that’s required to create an API resource include all of this information (e.g., listener, endpointGroups, analytics).