Providers are Terraform plugins that define resources and data sources for practitioners to use. You serve your providers with a provider server so they can interact with Terraform. The provider schema defines the allowed attributes and other configuration data about your provider.
This page explains how to migrate a provider server, definition, and schema from SDKv2 to the plugin framework. Refer to the Migrating schema page in this migration guide to learn how to migrate your provider's schema to the framework.
Terraform connects to your provider over RPC. The provider server connects to Terraform and handles RPC calls between Terraform and your provider code. When you migrate your provider from SDKv2 to Terraform, you must update your provider server, provider definition, and provider schema. When you migrate using the terraform-plugin-mux
module, your provider server will serve both the SDKv2 and framework versions of your provider. Once migration is complete, remove the SDKv2 versions of your provider server, definition, and schema.
You must update your provider's main.go
file to serve your framework provider. Refer to Provider Servers in the framework documentation for details about framework provider servers.
You can use the terraform-plugin-mux
module to help you iteratively migrate individual resources and data sources to the framework across multiple release cycles. The module multiplexes, or muxes, data using SDKv2 and the framework concurrently. Refer to Migration using a mux server for more information.
If you are migrating your provider in a single release cycle, update your provider's main()
function to serve the framework provider instead of the SDKv2 version.
In SDKv2, the provider package's main
function serves the provider by calling plugin.Serve
.
The following code shows a basic implementation for serving an SDKv2 provider.
SDKv2
func main() {
plugin.Serve(
&plugin.ServeOpts{
ProviderFunc: provider.New,
ProviderAddr: "registry.terraform.io/<namespace>/<provider_name>",
},
)
}
In the framework, serve your provider by calling providerserver.Serve
in your provider package's main
function. Refer to Provider Servers in the framework documentation for details about provider servers.
The following code shows an equivalent implementation for serving a provider in the framework.
Framework
func main() {
err := providerserver.Serve(
context.Background(),
provider.New,
providerserver.ServeOpts{
Address: "registry.terraform.io/<namespace>/<provider_name>",
},
)
if err != nil {
log.Fatal(err)
}
}
Providers built with SDKv2 use a schema.Provider
struct to define their behavior, while framework providers use a type that you define that implements the provider.Provider
interface. Refer to Providers in the framework documentation for details about framework provider definitions.
When migrating using a mux provider server, you will implement both the SDKv2 and framework versions of your provider definition during the migration. Once you have completed the migration, remove the SDKv2 provider definition and related mux server code from your provider server.
The ProviderFunc
field on plugin.ServeOpts
requires a pointer to schema.Provider
to access your provider's schema. This is typically satisfied by calling a function that returns a pointer to schema.Provider
.
The ResourcesMap
and DataSourcesMap
fields each contain a map of strings to functions that each return a pointer to a schema.Resource
struct for the given resource or data source.
The following example shows a basic implementation of an SDKv2 provider.
SDKv2
func New() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{},
ConfigureContextFunc: configureContextFunc(),
ResourcesMap: map[string]*schema.Resource{
"resource_example": resourceExample(),
},
DataSourcesMap: map[string]*schema.Resource{
"dataSource_example": dataSourceExample(),
},
/* ... */
}
}
In the framework, the second argument to your provider.Serve
function requires a function that returns a type satisfying the provider.Provider
interface.
The following code shows a typical implementation. In this implementation, the Resources
method returns a slice of functions that return types that implement the resource.Resource
interface. The DataSources
method returns a slice of functions that return types that implement the datasource.DataSource
interface. Refer to the Resources and Data Sources pages in this guide to implement these functions for your provider.
Framework
type exampleCloudProvider struct {
}
func New() provider.Provider {
return &exampleCloudProvider{}
}
func (p *exampleCloudProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "examplecloud"
}
func (p *exampleCloudProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{}
}
func (p *exampleCloudProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
}
func (p *exampleCloudProvider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource {
func() resource.Resource {
return resourceExample{}
},
}
}
func (p *exampleCloudProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource {
func() datasource.DataSource {
return dataSourceExample{}
},
}
}
Migration notes
Remember the following differences between SDKv2 and the framework when you migrate your provider definition.
New
function returns a pointer to a schema.Provider
struct. In the framework, New
returns a type that you define which satisfies the provider.Provider
interface.Schema
is a field on schema.Provider
that contains map[string]*schema.Schema
, which maps attribute names to schema.Schema
structs. In the framework, Schema
is a method you define on your provider that returns your provider's schema.Schema
struct.ConfigureContextFunc
is a field on schema.Provider
containing a function that configures the provider. In the framework, Configure
is a function you define on your provider that configures your provider.ResourcesMap
is a field on schema.Provider
containing map[string]*schema.Resource
, which maps resource names to schema.Resource
structs. In the framework, Resources
is a method you define on your provider that returns []func() resource.Resource
, a slice of resource types that you define which satisfy the resource.Resource
interface.DataSourcesMap
is a field on schema.Provider
containing map[string]*schema.Resource
, which maps data source names to schema.Resource
structs. SDKv2 data sources and resources both use schema.Resource
. In the framework, DataSources
is a method you define on your provider that returns []func() datasource.DataSource
, a slice of data source types that you define which satisfy the datasource.DataSource
interface.The following example shows how to set up a provider schema, configuration, resources, and data sources using SDKv2.
SDKv2
func New() (*schema.Provider, error) {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"attribute": {
/* ... */
},
},
ConfigureContextFunc: configureProvider,
ResourcesMap: map[string]*schema.Resource{
"exampleResource": exampleResource(),
/* ... */
},
DataSourcesMap: map[string]*schema.Resource{
"exampleDataSource": exampleDataSource(),
/* ... */
},
}, nil
}
The following shows the same section of provider code after the migration.
Framework
var _ provider.Provider = (*exampleProvider)(nil)
func New() provider.Provider {
return &exampleProvider{}
}
func (p *exampleProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
func() resource.Resource {
return &exampleResource{}
},
/* ... */
}
}
func (p *exampleProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
func() datasource.DataSource {
return &exampleDataSource{}
},
/* ... */
}
}
func (p *exampleProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"attribute": schema.SingleNestedBlock{
/* ... */
},
},
}
}
func (p *exampleProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "example"
}
func (p *exampleProvider) Configure(_ context.Context, _ provider.ConfigureRequest, resp *provider.ConfigureResponse) {
/* ... */
}
A provider schema defines the attributes and behaviors of the provider. For example, a provider that connects to a third-party API may define attributes for the base URL or a required authentication token.
When you use a muxed provider server to migrate from SDKv2 to the framework, the SDKv2 version of your provider definition uses an SDKv2 provider schema, and your framework provider definition uses a framework provider schema. Once you have completed the migration, remove the SDKv2 provider schema along with the provider definition and related mux code from your provider server.
In SDKv2, you implement a provider schema by populating the Schema
field on the schema.Provider
struct. The Schema
field contains a map[string]*schema.Schema
. Each map entry represents the name of the attribute and pointer to a schema.Schema
struct that defines that attribute's behavior.
In the framework, the Schema
method returns the provider schema. The Schema
method is part of the provider.Provider
interface that your provider must implement. Schema
returns a struct containing fields for Attributes
and Blocks
. These Attributes
and Blocks
contain map[string]schema.Attribute
and map[string]schema.Block
, respectively. Refer to Providers - Schema in the framework documentation for details about framework provider schema.
The following example defines the provider schema in the Schema
field within the schema.Provider
struct.
SDKv2
func New() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
/* ... */
},
The following code shows the Schema
method, which returns the provider schema.
SDKv2
func (p *ExampleCloudProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
/* ... */
}
}
Refer to the Migrating schema page in this migration guide to learn how to migrate schema to the framework.
Migration notesschema.Schema
is a struct that defines attributes and behaviors, such as Type
or Optional
. In the framework schema.Schema
is a struct that includes attributes and blocks.Refer to the following examples when you migrate your provider.
Nested blocks and attributesThis example shows how to use a nested block and a nested attribute for the SDKv2 and framework examples, respectively. Refer to the Blocks with Computed Fields page in this guide for more details.
The following example shows the configuration of the example_attribute
attribute for the provider's example_block
configuration block in SDKv2.
SDKv2
Schema: map[string]*schema.Schema{
"example_block": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"example_attribute": {
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: validation.ToDiagFunc(validation.IsURLWithScheme(SupportedProxySchemesStr())),
ConflictsWith: []string{"example_block.0.another_attribute"},
},
/* ... */
The following shows the same section of provider code after the migration.
This code implements the example_attribute
attribute for the example_Block
block with the framework.
Framework
func (p *exampleProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
/*...*/
Blocks: map[string]schema.Block{
"example_block": schema.ListNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"example_attribute": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
attribute_validator.UrlWithScheme(supportedProxySchemesStr()...),
stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("another_attribute")),
},
},
},
Validators: []validator.List{
listvalidator.SizeAtMost(1),
},
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4