terraform-plugin-framework icon indicating copy to clipboard operation
terraform-plugin-framework copied to clipboard

Document upgrade path for blocks

Open abergmeier opened this issue 3 years ago • 6 comments

Module version

0.6.0

Use-cases

I have a provider (buildx), that I want to upgrade from SDKv2 to framework. Now I am stuck because I cannot seem to get the following to work:

resource "buildx_instance" "foo" {
  driver {
    name = "bar"
  }
}

Error is:

Blocks of type "driver" are not expected here. Did you mean to define argument "driver"? If so, use the equals sign to assign it a value.

Attempted Solutions

My naive approach was to define it as:

"driver": {
		Attributes: tfsdk.SetNestedAttributes(
			driverAttributes,
			tfsdk.SetNestedAttributesOptions{},
		),
		PlanModifiers: tfsdk.AttributePlanModifiers{
			tfsdk.RequiresReplace(),
		},
		Required: true,
		Validators: []tfsdk.AttributeValidator{
			validators.HasExactlyOneEntry("driver"),
		},
	},

Proposal

I am not sure whether there is some doc that I have not found yet or whether this needs to be documented.

References

abergmeier avatar Mar 29 '22 18:03 abergmeier

Hi @abergmeier 👋 Thank you for raising this and apologies for the lack of clarity around this. We are hoping that there will be a canonical terraform-plugin-sdk/v2 to terraform-plugin-framework migration guide created that explains some of the details of this process at a code level, we are just waiting for the framework code to solidify some more before doing so.

In the meantime though, it sounds like you might be looking for tfsdk.Schema.Blocks field for defining that part of the resource schema. In this framework, Attributes and Blocks are separately implemented so the abstraction is (hopefully) a little clearer than previously where helper/schema.Schema was overloaded with both types of practitioner configuration styles. Blocks can contain nested attributes and blocks while attributes can only contain nested attributes. The Go documentation for the Attributes and Blocks fields contains links on the practitioner configuration differences.

Something like the following might get you close in your ResourceType GetSchema method:

tfsdk.Schema{
	// ... potentially other Attributes, etc. fields ...
	Blocks: map[string]tfsdk.Block{
		"driver": {
			NestingMode: tfsdk.BlockNestingModeSet,
			Required:    true,
			Attributes: driverAttributes,
		},
	},
},

Does this help in your situation? Thanks again for creating this issue.

bflad avatar Mar 29 '22 19:03 bflad

@abergmeier gentle ping about the above.

bflad avatar Apr 21 '22 19:04 bflad

Does this help in your situation? Thanks again for creating this issue.

Thanks for clarifying this. It indeed let me make this work.

As a sidenote: I saw that Blocks is also deprecated. Is there a document which describes the why? From my experience, you mostly cannot implement the same functionality using attributes (blocks supports more "validation"). It does feel weird having to use something deprecated when implementing a new provider...

abergmeier avatar Apr 21 '22 19:04 abergmeier

https://github.com/hashicorp/terraform-plugin-framework/blob/main/docs/design/blocks.md describes it a little, but overall the Terraform CLI maintainers have determined that the practitioner experience is much better when working with attributes over blocks for a few reasons:

  • Generally, block usage in Terraform has been constrained by the older SDK (for a multitude of reasons) only supporting list and set block types, whereas the protocol actually supports other block types such as map blocks (e.g. my_block "some-label" {} syntax). Map nested attributes in the new protocol was vastly more trivial to implement in this newer SDK.
  • Repeating block syntax can be confusing for newcomers
  • Using dynamic to handle repeating blocks is generally confusing for practitioners whereas for expressions are much easier/ergonomic
  • Blocks themselves cannot support certain underlying type features, such as sensitivity, since they are structural. Only attributes and nested attributes can.

From my experience, you mostly cannot implement the same functionality using attributes (blocks supports more "validation")

I would love to hear more about your experience here. Attributes in this framework can implement validation for any attribute type. We are hoping to have common use case validators built as part of https://github.com/hashicorp/terraform-plugin-framework/issues/240.

bflad avatar Apr 21 '22 19:04 bflad

I would love to hear more about your experience here.

I would have to look into that again. IIRC it mostly failed since default support for attributes was not there/lacking.

abergmeier avatar Apr 21 '22 19:04 abergmeier

Personally I’d be sad to see blocks go. I get the above statements about repeatability being confusing for newcomers, but from my experience training colleagues, it’s not a big hurdle. For large configuration sets, lots of for loops tend to be broken into intermediate values using locals and then merged to create a final object/map/set which in contrast is a whole lot less cleaner than the block configuration style.

m13t avatar May 05 '22 07:05 m13t

An initial sdk/v2 to framework schema block migration guide has been published: https://www.terraform.io/plugin/framework/migrating/attributes-blocks/blocks 👍

Blocks were un-deprecated awhile ago and will have first-class support at least through version 1 of this framework.

bflad avatar Sep 13 '22 19:09 bflad

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

github-actions[bot] avatar Oct 14 '22 02:10 github-actions[bot]