Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provider: Deprecate DataSourceType, ResourceType, Provider type GetDataSources, and Provider type GetResources #472

Merged
merged 12 commits into from Sep 12, 2022

Commits on Sep 8, 2022

  1. provider: Deprecate DataSourceType, ResourceType, Provider type…

    … `GetDataSources`, and `Provider` type `GetResources`
    
    Reference: #441
    Reference: #442
    
    The goal of this change is twofold:
    
    - Deprecate the separate `DataSourceType` and `ResourceType` types.
    - Enable `DataSource` and `Resource` to be self-documenting with respects to their type name.
    
    Removing `DataSourceType` and `ResourceType` simplifies provider implementations and gives developers the choice of whether or not to configure extra data in their `DataSource` and `Resource` implementations by adding the optional `Configure` method. This data is no longer required to be the `provider.Provider` itself, but rather can be any type such as a provider-defined structure or vendor-supplied client type.
    
    Enabling `DataSource` and `Resource` type name handling within the implementation allows provider developers to further split out their data source and resource code across package boundaries without repeated map addition logic.
    
    Given this framework version 0.11.1 code (which generally is split across Go files/packages, but shown altogether here for brevity):
    
    ```go
    var _ provider.Provider = &ExampleProvider{}
    
    type ExampleProvider struct{
      configured bool
      // ... additional remote client fields, etc.
    }
    
    func (p ExampleProvider) GetDataSources(ctx context.Context) (map[string]provider.DataSourceType, diag.Diagnostics) {
    	return map[string]provider.DataSourceType{
    		"example_thing": ThingDataSourceType{},
    	}, nil
    }
    
    func (p ExampleProvider) GetResources(ctx context.Context) (map[string]provider.ResourceType, diag.Diagnostics) {
    	return map[string]provider.ResourceType{
    		"example_thing": ThingResourceType{},
    	}, nil
    }
    
    func (p ExampleProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { /* ... */ }
    
    func (p *ExampleProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
      // ... remote client setup, etc.
      p.configured = true
    }
    
    var _ provider.DataSourceType = ThingDataSourceType{}
    var _ datasource.DataSource = ThingDataSource{}
    
    type ThingDataSourceType struct{}
    
    type ThingDataSource struct{
      provider ExampleProvider
    }
    
    func (t ThingDataSourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { /* ... */ }
    
    func (t ThingDataSourceType) NewDataSource(ctx context.Context, p provider.Provider) (datasource.DataSource, diag.Diagnostics) {
      return ThingDataSource{
        provider: p.(ExampleProvider), // unchecked type assertion shown for brevity
      }
    }
    
    func (d ThingDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
      // e.g. d.provider.Client.ReadThing()
    }
    
    var _ provider.ResourceType = ThingResourceType{}
    var _ resource.Resource = ThingResource{}
    
    type ThingResourceType struct{}
    
    type ThingResource struct{
      provider ExampleProvider
    }
    
    func (t ThingResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { /* ... */ }
    
    func (t ThingResourceType) NewResource(ctx context.Context, p provider.Provider) (resource.Resource, diag.Diagnostics) {
      return ThingResource{
        provider: p.(ExampleProvider), // unchecked type assertion shown for brevity
      }
    }
    
    func (r ThingResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
      // e.g. r.provider.Client.CreateThing()
    }
    
    func (r ThingResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
      // e.g. r.provider.Client.DeleteThing()
    }
    
    func (r ThingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
      // e.g. r.provider.Client.ReadThing()
    }
    
    func (r ThingResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
      // e.g. r.provider.Client.UpdateThing()
    }
    ```
    
    Could be migrated as:
    
    ```go
    type ExampleClient struct {
      // client/data fields OR just use the vendor client type directly instead of this new type
    }
    
    var _ provider.Provider = &ExampleProvider{}
    
    type ExampleProvider struct{
      // setting client, etc. fields here is now completely optional,
      // if you want to configure data sources and resource with _this_ type
    }
    
    func (p ExampleProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
      // make available in DataSource and Resource type TypeName methods
      resp.TypeName = "example"
    }
    
    func (p ExampleProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
      return []func() datasource.DataSource{
    		NewThingDataSource,
    	}
    }
    
    func (p ExampleProvider) Resources(ctx context.Context) []func() resource.Resource {
      return []func() resource.Resource{
    		NewThingResource,
    	}
    }
    
    func (p ExampleProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { /* ... */ }
    
    func (p *ExampleProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
      client := &ExampleClient{} // OR existing vendor type OR p itself
      resp.DataSourceData = client
      resp.ResourceData = client
    }
    
    var _ datasource.DataSource = ThingDataSource{}
    
    func NewThingDataSource() datasource.DataSource {
      return ThingDataSource{}
    }
    
    type ThingDataSource struct{
      client *ExampleClient
    }
    
    func (d ThingDataSource) TypeName(ctx context.Context, req datasource.TypeNameRequest, resp *datasource.TypeNameResponse) {
      resp.TypeName = req.ProviderTypeName + "_thing"
    }
    
    func (d ThingDataSource) GetSchema(ctx context.Context) (fwschema.Schema, diag.Diagnostics) { /* ... */ }
    
    func (d ThingDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse)  {
      d.client = req.ProviderData.(*ExampleClient) // unchecked type assertion shown for brevity
    }
    
    func (d ThingDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
      // e.g. d.client.ReadThing()
    }
    
    var _ resource.Resource = ThingResource{}
    
    func NewThingResource() resource.Resource {
      return ThingResource{}
    }
    
    type ThingResource struct{
      client *ExampleClient
    }
    
    func (d ThingResource) TypeName(ctx context.Context, req resource.TypeNameRequest, resp *resource.TypeNameResponse) {
      resp.TypeName = req.ProviderTypeName + "_thing"
    }
    
    func (r ThingResource) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { /* ... */ }
    
    func (r ThingResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
      r.client = req.ProviderConfigureData.(*ExampleClient) // unchecked type assertion shown for brevity
    }
    
    func (r ThingResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
      // e.g. r.client.CreateThing()
    }
    
    func (r ThingResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
      // e.g. r.client.DeleteThing()
    }
    
    func (r ThingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
      // e.g. r.client.ReadThing()
    }
    
    func (r ThingResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
      // e.g. r.client.UpdateThing()
    }
    ```
    
    Some additional implementation notes:
    
    - The new `Provider` type `Metadata` method is called at the beginning of the `GetProviderSchema` RPC and populates the provider type name for data source and resource type name requests.
    - The framework server will automatically validate against duplicate type names, missing type names, and missing schemas when using the new `Provider` type `DataSources` and `Resources` methods.
    - The new `DataSource` and `Resource` type `Configure` methods are automatically called where the framework server previously called the `DataSourceType` type `NewDataSource` method and `ResourceType` type `NewDataSource` method.
    - The new `DataSource` and `Resource` type `TypeName` methods could potentially be renamed `Metadata` to match the `Provider` implementation and potentially help futureproof it, however it could be unclear to provider developers where to set the type name at first and there are no apparent use cases which would extend that type of metadata yet.
    bflad committed Sep 8, 2022
    Copy the full SHA
    7eecd4c View commit details
    Browse the repository at this point in the history
  2. Update CHANGELOG for #472

    bflad committed Sep 8, 2022
    Copy the full SHA
    6e3fc1a View commit details
    Browse the repository at this point in the history
  3. internal/fwserver: Check deprecated ResourceType's when searching for…

    … Resource implementations
    bflad committed Sep 8, 2022
    Copy the full SHA
    301117a View commit details
    Browse the repository at this point in the history

Commits on Sep 9, 2022

  1. Copy the full SHA
    93a75d1 View commit details
    Browse the repository at this point in the history
  2. Copy the full SHA
    aff5e2f View commit details
    Browse the repository at this point in the history
  3. Copy the full SHA
    675c046 View commit details
    Browse the repository at this point in the history
  4. provider: Ensure DataSourceType and ResourceType includes Go document…

    …ation Deprecated comment
    bflad committed Sep 9, 2022
    Copy the full SHA
    99f9980 View commit details
    Browse the repository at this point in the history
  5. Copy the full SHA
    77b993e View commit details
    Browse the repository at this point in the history
  6. Copy the full SHA
    6ab1983 View commit details
    Browse the repository at this point in the history

Commits on Sep 12, 2022

  1. Copy the full SHA
    73411bb View commit details
    Browse the repository at this point in the history
  2. Update .changelog/472.txt

    bflad committed Sep 12, 2022
    Copy the full SHA
    0d8f4ef View commit details
    Browse the repository at this point in the history
  3. Copy the full SHA
    573f8d4 View commit details
    Browse the repository at this point in the history