Skip to content

Add Schema Mutation and Timeout Retrieval Functions #4

@bendbennett

Description

@bendbennett

Terraform CLI and Framework Versions

Terraform 1.2.9
Framework 0.12.0

Use Cases or Problem Statement

Provider developers should be able to call functions that will appropriately mutate the schema for use with timeouts that are declared using nested blocks or nested attributes.

Provider developers should be able to call functions that will retrieve the appropriate time.Duration for use in CRUD functions.

Nested Blocks

Currently, timeouts are defined within configuration when using SDKv2 as follows:

resource "provider_resource" "example" {
  /* ... */

  timeouts {
    create = "60m"
    read = "10m"
  }
}

When using the Framework, this would require that the tfsdk.Schema for the resource be manually altered by the provider developer to include the following:

func (t exampleResource) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
	return tfsdk.Schema{
		/* ... */
		Blocks: map[string]tfsdk.Block{
			"timeouts": {
				Attributes: map[string]tfsdk.Attribute{
					"create": {
						Type:     types.StringType,
						Optional: true,
					},
					/* ... */
				},
				NestingMode: tfsdk.BlockNestingModeSingle,
			},
		},

Nested Attributes

With the availability of nested attributes in protocol version 6, there is also the opportunity to define timeouts using the nested attribute syntax. For instance:

resource "provider_resource" "example" {
  /* ... */

  timeouts = {
    create = "60m"
    read = "10m"
  }
}

This would require that the tfsdk.Schema for the resource be manually altered by the provider developer to include the following:

diag.Diagnostics) {
	return tfsdk.Schema{
		/* ... */
		Attributes: map[string]tfsdk.Attribute{
			"timeouts": {
				Optional:    true,
				Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
					"create": {
						Optional: true,
						Type:     types.StringType,
					},
					/* ... */
				}),
			},
		},

Proposal

Inside a timeouts package, create the following exported types:

package timeouts

type Opts struct {
	Create bool
	Read   bool
	Update bool
	Delete bool
}

func Block(ctx context.Context, opts TimeoutsOpts) tfsdk.Block {
// Each field in opts is checked and a map entry is added
// for each field that is true. 

	return tfsdk.Block{
		Attributes: map[string]tfsdk.Attribute{
			"create": {
				Type:     types.StringType,
				Optional: true,
			},
			"read": {
				Type:     types.StringType,
				Optional: true,
			},
			/* ... */
		},
		NestingMode: tfsdk.BlockNestingModeSingle,
	}
}

func BlockAll(ctx context.Context) tfsdk.Block {
	return TimeoutsBlock(ctx, TimeoutsOpts{
		Create: true,
		Read:   true,
		Update: true,
		Delete: true,
	})
}

func Attributes(ctx context.Context, opts TimeoutsOpts) tfsdk.Attribute {
// Each field in opts is checked and a map entry is added
// for each field that is true.  

	return tfsdk.Attribute{
		Optional: true,
		Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
			"create": {
				Optional: true,
				Type:     types.StringType,
			},
			"read": {
				Optional: true,
				Type:     types.StringType,
			},
			/* ... */
		}),
	}
}

func AttributesAll(ctx context.Context) tfsdk.Attribute {
	return TimeoutsAttributes(ctx, TimeoutsOpts{
		Create: true,
		Read:   true,
		Update: true,
		Delete: true,
	})
}

This will then allow provider developers to call these functions to generate a nested block or nested attributes as follows:

func (t exampleResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
	return tfsdk.Schema{
		Blocks: map[string]tfsdk.Block{
			"timeouts": timeouts.Block(ctx, TimeoutsOpts{/* ... */}),
		},
                /* ... */
func (t exampleResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
	return tfsdk.Schema{
		Attributes: map[string]tfsdk.Attribute{
			"timeouts": timeouts.Attributes(ctx, TimeoutsOpts{/* ... */}),
		},
                /* ... */

Additionally, create the following exported types for retrieving time.Duration for use in timeouts within CRUD functions:

func Create(ctx context.Context, obj types.Object) (*time.Duration, diag.Diagnostics)
func CreateDefault(ctx context.Context, obj types.Object, def time.Duration) time.Duration
func Read(ctx context.Context, obj types.Object) (*time.Duration, diag.Diagnostics)
func ReadDefault(ctx context.Context, obj types.Object, def time.Duration) time.Duration
func Update(ctx context.Context, obj types.Object) (*time.Duration, diag.Diagnostics)
func UpdateDefault(ctx context.Context, obj types.Object, def time.Duration) time.Duration
func Delete(ctx context.Context, obj types.Object) (*time.Duration, diag.Diagnostics)
func DeleteDefault(ctx context.Context, obj types.Object, def time.Duration) time.Duration

Additional Information

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions