How to determine supported terraform version(s) from module source?

(this is a follow-on to one part of this issue)

Given a module source tree - referenced using a local path, or downloaded from registry, or (most likely for my use case) git clone and then checked out to a specific reference - how can I determine what versions of terraform support that module?

My obvious preference is something inherent within the module itself, but it is a reasonable fallback to run some terraform CLI command, if that is necessary. Might even be able to fall back to “try with different versions”, but that is not pretty.

Thanks in advance.

Hi @deitch,

The terraform block has a required_version argument which defines the supported versions of Terraform for the module.

That’s the only way to definitively determine if a version is supported, however a lot of modules may not have that set. If there is no version information, there is no check, and Terraform makes a best effort to handle the given configuration.

Hi @jbardin ; thanks for jumping in.

Yeah, that works for those that have it. My bigger issue is:

What does “best effort” mean? Is there some algorithm I can replicate? Some library I can apply to the module source to say, “can this run with version X”? Or even a CLI I can execute to say, “can this run with version X”?

There are so many possible permutations of new features, changes, and bug fixes added over time it would be very difficult to determine the exact version supported heuristically. A module author could be using a combination of features supported in earlier version, but in an unusual manner that encounters a bug before a particular later version. If the module author did not document this restriction, the only thing you can do is try and run Terraform with that configuration.

A follow-on: if I have the required_version module, let’s say it is 1.3, is there a rule of thumb that will indicate if I can use 1.4.x or 1.5.x?

required_version is a version constraint, so it should specify what is supported. If the version says = 1.3.2 then only that version can be used. Otherwise there will be some sort of range to use.

Practically We do guarantee backwards compatibility throughout the v1 versions, so if ~> v1.3.0 is supported later versions should work as well, but Terraform won’t ignore that constraint and refuse to run until it is updated.

Ah, that practical part is important. In other words, if it says = 1.3.2, it doesn’t matter if I know that 1.4.0 will run fine with it, 1.4.0 will refuse to because of the constraint. Got it, thanks. Quite clarifies.

Ouch. And depending on some external shell-outs and how responses are parsed, I might not even know until I run an apply?

Is there a baseline validation I can do?

Technically that is possible, but that would be because of a bug rather than known incompatibility. If there are unsupported features in the configuration, Terraform will fail early when parsing the configuration, and any other issues should be raised during plan. Apply failing with a valid plan is very rare, and more often than not a problem with a provider than with Terraform.

The baseline validation is to check required_version, which should be specified. Any module which did not specify the version somehow (even through documentation) can only be validated by Terraform itself.

How would I do that? Is there a tf validate-module ./path/to/module kind of thing? Or maybe tf validate-module git::ssh::...? And then I guess it would depend on the version of terraform that tf points to?

Or is my only option to create a config that points to the module and then run tf validate on that config? Which means I need to know all of the vars to pass to the module. That is a lot of work, when all I really am after is, “which versions of terraform work for this module?”

I think the short answer here is that Terraform allows module authors to declare what their module is compatible with, but does not require module authors to specify that.

Therefore, just as with most programming languages, the presence of a version constraint is a helpful extra hint which often allows returning a better error message if there is a version mismatched, but the only way to know for sure whether a particular configuration is valid for a particular version of Terraform is to try evaluating it with that version. If the module uses language features not available in the given Terraform version then some sort of error would be returned saying that part of the configuration is invalid.

I’m not sure what could possibly be done that would be more exact than this. If you have any specific ideas, particularly if they are already implemented in some other language ecosystem that we could study for comparison, then I’d be interested to hear about them!

I wish I had something better to offer you. I do not.

What I am doing in the end is:

  1. Getting the list of tags from docker hub, and filtering for semver, and for a minimum version
  2. For each, running tf init --backend-false to see if it can process it.

Since a module is technically a config, that at least has a shot at working. It probably will fail for a lot of use cases, but I will not know until I try.

I would like it if there were a tf validate-module which just checked, “can I read this module?”

Hmm, a follow-on question. Is there such thing as a module that would work with 0.11.2 but not 0.11.1 (or 1.4.2 but not 1.4.1)?

I would think it is fair to assume (based on semver rules), that it wouldn’t be so, other than bugs fixed later. But I could safely work on just major and minor versions, and not worry about patch versions? Just take the highest 1.4 I can find, the highest 1.3, highest 0.11, etc.?

Would required_version break that? I guess it would?