Terraform
Schemas
Schemas specify the constraints of Terraform configuration blocks. They define what fields a top-level block has and give Terraform metadata about those fields, such as provider, resource, or data source configuration. You can think of the schema as the "type information" or the "shape" of top-level block data.
Each concept that sends/receives data from Terraform has its own schema package and Schema type, which defines functionality available to that concept. For example (non-exhaustive):
- Provider Schema: provider/schema.Schema
- Resource Schemas: resource/schema.Schema
- Data Source Schemas: datasource/schema.Schema
During execution of the terraform validate, terraform plan and terraform apply commands, Terraform calls the provider GetProviderSchema RPC, in which the framework calls all Schema methods on each registered type in the provider, for example:
- provider.Providerinterface- Schemamethod
- resource.Resourceinterface- Schemamethod
- datasource.DataSourceinterface- Schemamethod
Version
Version is only valid for resources.
Every schema has a version, which is an integer that allows you to track changes to your schemas. It is generally only used when upgrading resource state, to help massage resources created with earlier schemas into the shape defined by the current schema. It will never be used for provider or data source schemas and can be omitted.
DeprecationMessage
Not every resource, data source, or provider will be supported forever.
Sometimes designs change or APIs are deprecated. Schemas that have their
DeprecationMessage property set will display that message as a warning when
that provider, data source, or resource is used. A good message will tell
practitioners that the provider, resource, or data source is deprecated, and
will indicate a migration strategy.
Description
Various tooling like
terraform-plugin-docs and
the language server can use
metadata in the schema to generate documentation or offer a better editor
experience for practitioners. Use the Description property to add a description of a resource, data source, or provider that these tools can leverage.
MarkdownDescription
Similar to the Description property, the MarkdownDescription is used to
provide a markdown-formatted version of the description to tooling like
terraform-plugin-docs. It
is a best practice to only alter the formatting, not the content, between the
Description and MarkdownDescription.
At the moment, if the MarkdownDescription property is set it will always be
used instead of the Description property. It is possible that a different strategy may be employed in the future to surface descriptions to other tooling in a different format, so we recommend specifying both fields.
Unit Testing
Schemas can be unit tested via each of the schema.Schema type ValidateImplementation() methods. This unit testing raises schema implementation issues more quickly in comparison to acceptance tests, but does not replace the purpose of acceptance testing.
In this example, a thing_resource_test.go file is created alongside the thing_resource.go implementation file:
import (
  "context"
  "testing"
  // The fwresource import alias is so there is no collision
  // with the more typical acceptance testing import:
  // "github.com/hashicorp/terraform-plugin-testing/helper/resource"
  fwresource "github.com/hashicorp/terraform-plugin-framework/resource"
)
func TestThingResourceSchema(t *testing.T) {
  t.Parallel()
  ctx := context.Background()
  schemaRequest := fwresource.SchemaRequest{}
  schemaResponse := &fwresource.SchemaResponse{}
  // Instantiate the resource.Resource and call its Schema method
  NewThingResource().Schema(ctx, schemaRequest, schemaResponse)
  if schemaResponse.Diagnostics.HasError() {
    t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics)
  }
  // Validate the schema
  diagnostics := schemaResponse.Schema.ValidateImplementation(ctx)
  if diagnostics.HasError() {
    t.Fatalf("Schema validation diagnostics: %+v", diagnostics)
  }
}