One option might be to define functions that return map[string]tfsdk.Attribute{}
.
example.tf
Following contains configuration for a provider and a resource that share the same attribute structure for “list_nested_attribute”.
provider "attributes" {
list_nested_attribute = [
{
int64_attribute = 9223372036854775807
list_attribute = ["list-element", "list-element"]
list_nested_nested_attribute = [
{
int64_attribute_nested = 9223372036854775807
}
]
},
{
int64_attribute = 9223372036854775807
list_attribute = ["list-element", "list-element"]
list_nested_nested_attribute = [
{
int64_attribute_nested = 9223372036854775807
}
]
}
]
}
resource "attributes_example" "example" {
configurable_attribute = "some-value"
list_nested_attribute = [
{
int64_attribute = 9223372036854775807
list_attribute = ["list-element", "list-element"]
list_nested_nested_attribute = [
{
int64_attribute_nested = 9223372036854775807
}
]
},
{
int64_attribute = 9223372036854775807
list_attribute = ["list-element", "list-element"]
list_nested_nested_attribute = [
{
int64_attribute_nested = 9223372036854775807
}
]
}
]
}
provider.GetSchema
GetSchema
uses 3 functions to compose the schema structure.
func (p *scaffoldingProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
Attributes: getAttributes(),
}, nil
}
func getAttributes() map[string]tfsdk.Attribute {
return map[string]tfsdk.Attribute{
"list_nested_attribute": {
Optional: true,
Attributes: tfsdk.ListNestedAttributes(getNestedAttributes()),
},
}
}
func getNestedAttributes() map[string]tfsdk.Attribute {
return map[string]tfsdk.Attribute{
"int64_attribute": {
Optional: true,
Type: types.Int64Type,
},
"list_attribute": {
Optional: true,
Type: types.ListType{ElemType: types.StringType},
},
"list_nested_nested_attribute": {
Optional: true,
Attributes: tfsdk.ListNestedAttributes(getNestedNestedAttributes()),
},
}
}
func getNestedNestedAttributes() map[string]tfsdk.Attribute {
return map[string]tfsdk.Attribute{
"int64_attribute_nested": {
Optional: true,
Type: types.Int64Type,
},
}
}
provider data model
The providerData
model provides the necessary structure to unmarshall the provider configuration onto.
type providerData struct {
ListNestedAttribute []ListNestedAttribute `tfsdk:"list_nested_attribute"`
}
type ListNestedAttribute struct {
Int64Attribute types.Int64 `tfsdk:"int64_attribute"`
ListAttribute types.List `tfsdk:"list_attribute"`
ListNestedNestedAttribute []ListNestedNestedAttribute `tfsdk:"list_nested_nested_attribute"`
}
type ListNestedNestedAttribute struct {
Int64Attribute types.Int64 `tfsdk:"int64_attribute_nested"`
}
provider.Configure
Configure
unmarshalls onto providerData
.
func (p *scaffoldingProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
var data providerData
diags := req.Config.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
/* .... */
resource.GetSchema
resource.GetSchema
uses the same getAttributes
func that provider.GetSchema
uses and then adds the additional attributes that are required for the resource.
func (t *exampleResource) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
attrs := getAttributes()
attrs["configurable_attribute"] = tfsdk.Attribute{
MarkdownDescription: "Example configurable attribute",
Optional: true,
Type: types.StringType,
}
attrs["id"] = tfsdk.Attribute{
Computed: true,
MarkdownDescription: "Example identifier",
PlanModifiers: tfsdk.AttributePlanModifiers{
resource.UseStateForUnknown(),
},
Type: types.StringType,
}
return tfsdk.Schema{
Attributes: attrs,
}, nil
}
resource data model
The exampleResourceData
model provides the necessary structure to unmarshall the resource configuration onto.
type exampleResourceData struct {
ConfigurableAttribute types.String `tfsdk:"configurable_attribute"`
Id types.String `tfsdk:"id"`
ListNestedAttribute []ListNestedAttribute `tfsdk:"list_nested_attribute"`
}
resource.Create
Create
unmarshalls onto exampleResourceData
.
func (t exampleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data exampleResourceData
diags := req.Config.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
data.Id = types.String{Value: "example-id"}
tflog.Trace(ctx, "created a resource")
diags = resp.State.Set(ctx, &data)
resp.Diagnostics.Append(diags...)
}