• Overview
    • Enforce Policy as Code
    • Infrastructure as Code
    • Inject Secrets into Terraform
    • Integrate with Existing Workflows
    • Manage Kubernetes
    • Manage Virtual Machine Images
    • Multi-Cloud Deployment
    • Network Infrastructure Automation
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
  • Registry
  • Tutorials
    • About the Docs
    • Intro to Terraform
    • Configuration Language
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
    • Provider Use
    • Plugin Development
    • Registry Publishing
    • Integration Program
    • Terraform Tools
    • CDK for Terraform
    • Glossary
  • Community
GitHub
Download
Try Terraform Cloud
    • v0.11.x (latest)
    • v0.10.x
    • v0.9.x
    • v0.8.x
    • v0.7.x

    Framework

  • Overview
  • Tutorial: Implement Create and Read
  • Provider Servers
  • Providers
    • Overview
    • Import
    • Plan Modification
    • State Upgrade
  • Data Sources
  • Schemas
  • Paths
  • Path Expressions
  • Attribute Types
  • Accessing State, Config, and Plan
  • Writing State
  • Returning Errors and Warnings
  • Validation
  • Acceptance Tests
  • Debugging
  • Other Plugin Docs

  • Plugin Development
  • SDKv2
  • Logging
  • Combining and Translating
Type '/' to Search

»Providers

Providers are Terraform plugins that define resources and data sources for practitioners to use. Providers are wrapped by a provider server for interacting with Terraform.

»Implement Provider Interface

Any type that fills the provider.Provider interface can be a provider. The provider interface has four required methods: GetSchema, Configure, GetResources, and GetDataSources. We recommend that you define a struct type to fill this interface.

An example provider implementation with a field storing an example API client:

// Ensure the implementation satisfies the provider.Provider interface.
var _ provider.Provider = &exampleProvider{}

// exampleProvider implements the provider.Provider interface. This implementation
// will be passed to data sources and resources as the provider.Provider parameter
// in each NewDataSource and NewResource method call respectively.
type exampleProvider struct{
    // Typically fields including API clients or configuration necessary for
    // resource and data source operations. For example:
    Client exampleApiClient

    // version is an example field that can be set with an actual provider
    // version on release, "dev" when the provider is built and ran locally,
    // and "test" when running acceptance testing.
    Version string
}

// GetSchema satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
    return tfsdk.Schema{
        Attributes: map[string]tfsdk.Attribute{
            // Provider specific implementation.
        },
    }, nil
}

// Configure satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
    // Provider specific implementation.
}

// GetDataSources satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) GetDataSources(ctx context.Context) (map[string]provider.DataSourceType, diag.Diagnostics) {
    return map[string]provider.DataSourceType{
        // Provider specific implementation
    }, nil
}

// GetResources satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) GetResources(ctx context.Context) (map[string]provider.ResourceType, diag.Diagnostics) {
    return map[string]provider.ResourceType{
        // Provider specific implementation
    }, nil
}
// Ensure the implementation satisfies the provider.Provider interface.
var _ provider.Provider = &exampleProvider{}

// exampleProvider implements the provider.Provider interface. This implementation
// will be passed to data sources and resources as the provider.Provider parameter
// in each NewDataSource and NewResource method call respectively.
type exampleProvider struct{
    // Typically fields including API clients or configuration necessary for
    // resource and data source operations. For example:
    Client exampleApiClient

    // version is an example field that can be set with an actual provider
    // version on release, "dev" when the provider is built and ran locally,
    // and "test" when running acceptance testing.
    Version string
}

// GetSchema satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
    return tfsdk.Schema{
        Attributes: map[string]tfsdk.Attribute{
            // Provider specific implementation.
        },
    }, nil
}

// Configure satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
    // Provider specific implementation.
}

// GetDataSources satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) GetDataSources(ctx context.Context) (map[string]provider.DataSourceType, diag.Diagnostics) {
    return map[string]provider.DataSourceType{
        // Provider specific implementation
    }, nil
}

// GetResources satisfies the provider.Provider interface for exampleProvider.
func (p *exampleProvider) GetResources(ctx context.Context) (map[string]provider.ResourceType, diag.Diagnostics) {
    return map[string]provider.ResourceType{
        // Provider specific implementation
    }, nil
}

Conventionally, many providers also create a helper function named New which can simplify provider server implementations.

func New(version string) func() provider.Provider {
    return func() provider.Provider {
        return &exampleProvider{
            Version: version,
        }
    }
}
func New(version string) func() provider.Provider {
    return func() provider.Provider {
        return &exampleProvider{
            Version: version,
        }
    }
}

»GetSchema

GetSchema returns a schema that describes the provider's configuration block. This configuration block is used to offer practitioners the opportunity to supply values to the provider and configure its behavior, rather than needing to include those values in every resource and data source. It is usually used to gather credentials, endpoints, and the other data used to authenticate with the API, but it is not limited to those uses.

provider "example" {
  endpoint = "https://example.test/"
  api_token = "v3rYs3cr3tt0k3n"
}
provider "example" {
  endpoint = "https://example.test/"
  api_token = "v3rYs3cr3tt0k3n"
}

Even if the provider does not want to accept practitioner configuration, it must return an empty schema.

The schema is meant to be immutable. It should not change at runtime, and should consistently return the same value.

»Configure

Configure handles and stores the values the practitioner entered in the provider's configuration block. This can mean creating the API client, storing the data on the type that implements the provider interface, or otherwise handling the values. This is the only time those values will be made available to the provider, so they need to be persisted if the provider will need to reference them from within a resource or data source. This is why we recommend using a struct to represent the provider, as it can hold multiple values in a strongly-typed way.

»Unknown Values

Not all values are guaranteed to be known when Configure is called. For example, if a practitioner interpolates a resource's unknown value into the block, that value may show up as unknown depending on how the graph executes:

resource "example_foo" "bar" {
  id = 123
}

provider "example" {
  endpoint = "https://example.test/"
  api_token = example_foo.bar.name
}
resource "example_foo" "bar" {
  id = 123
}

provider "example" {
  endpoint = "https://example.test/"
  api_token = example_foo.bar.name
}

In the example above, example_foo.bar.name is a read-only field on example_foo.bar that won't be set until after example_foo.bar has been applied. So the Configure method for the provider may report that the value is unknown. You can choose how your provider handles this. If some resources or data sources can be used without knowing that value, it may be worthwhile to emit a warning and check whether the value is set in resources and data sources before attempting to use it. If resources and data sources can't provide any functionality without knowing that value, it's often better to return an error, which will halt the apply.

»GetResources

GetResources returns a map of resource types. The keys of the map entries must be the name of the resource as it would appear in the configuration, including the provider prefix.

The list of resources is meant to be immutable. It should not change at runtime, and should consistently return the same values.

»GetDataSources

GetDataSources returns a map of data source types. The keys of the map entries must be the name of the data source as it would appear in the configuration, including the provider prefix.

The list of data sources is meant to be immutable. It should not change at runtime, and should consistently return the same values.

»Further Provider Capabilities

  • Validation helps practitioners understand the required syntax, types, and acceptable values for your provider.
github logoEdit this page
  • Overview
  • Docs
  • Extend
  • Privacy
  • Security
  • Press Kit
  • Consent Manager