Dynamic block generation from unknown set of keys

I am creating a module that wraps aws_s3_bucket and some more modules to make the creation of bucket with required configuration easy.

My issue is that there are nested blocks used in aws_s3_bucket resource and I want my module users to pass that information from outside. For instance “lifecycle_rule” nested block which is complex and consists of another level of nested blocks inside it like “expiration” - I want module users to completely define their own set of lifecycle rules.

I could have used dynamic blocks with for_each if the nested block was not containing further nested blocks but in this case, I can’t do that really. Or else I have to replicate the whole structural schema of “lifecycle_rule” (recursively) into my module’s variable type and also will have to expand each level in schema manually - which doesn’t only mean a lot of code but also means that I will have to keep on updating as soon as provider add news fields in the resource definition.

What would be the best way to solve this issue?

Please let me know if I am not making sense or if you’d like more information.

Any response on this? Please do let me know if I am not making sense in the question.

I believe that this should be considered as a gap with 0.12 as compared to 0.11 where we were able to pass things like lifecycle_rules from outside the module as variable/argument. And although 0.12 is typesafe but it took away this feature.

And this feature was making code/custom-modules more modular in nature but now we have to copy/paste from resource/data definitions from github to copy exact same type etc.

Hi @samkit,

Sorry I didn’t see this message earlier because I was out sick when you originally posted it.

As you’ve noted, the only way to do this with Terraform today is to write an object type that corresponds with the structure of lifecycle_rule and explicitly write out how that object maps to lifecycle_rule blocks.

It’s intentionally not possible to just pass through the schema of a resource type, because that would mean that the interface of your module would depend on what version of the provider the user happens to have selected. The interface of a module is supposed to be fully defined by its own variable and output declarations, and so (per Terraform language design) you should release a new version of the module if you want to allow new capabilities, so that you have an opportunity to make sure those new features fit into whatever abstraction your module is intended to create.

Understood and thanks for getting back on this!

Though I would agree that a new version of the module should be required to offer new functionality, the problem with the current approach is that I have to copy/paste lifecycle_rule definition as-is from aws provider’s github.

And although it does what it is supposed to do, it doesn’t seem modular because there is lot of copy/paste and secondly it is harder to maintain going forward.

Is there another better way to do this?

Hi @apparentlymart - any thing that you think I can do to improve the case as mentioned in above response?

Hi @samkit,

The main thing that comes to my mind is that rather than copying the content of that module you could instead call the module: it seems like it already does what you want here, so you could benefit from that existing implementation rather than duplicating it.

@apparentlymart - I would have done that, but behind the firewall its not possible to contact github.

Alright, I guess this is what I have currently.

Thanks though for answering!