Although moving to a Cloud Operating model and self-service means a far greater degree of ownership of infrastructure by internal customers, these still need to rely on teams of specialists to maintain the platforms, libraries, modules, etc. that those consumers of internal services, well, consume.
One of the best ways for these specialists to communicate ideas to the wider org, beyond the usual meetings, workshops, and presentations, is code, specifically, versioning of code.
In Terraform Enterprise, this communication can take the form of versioning re-usable modules in an internal module registry.
External re-usable modules, like the Vault module, should have strict version pinning, and internal modules, to facilitate faster feedback loops and better communication with SRE, should have looser version pinning.
Here's an example policy that you can set:
Hi everyone at Rupture AgCorp IT,
We would like you all to make sure that you're pinning external Terraform Modules to their Minor version numbers, in accordance with Semantic Versioning (https://semver.org)
But for internal modules, because changes to these are much more directly relevant to compliance and business changes, we now require you to have looser version pinning, to major versions only.
This may cause issues, but they're issues we want to find out about, and handle, sooner rather than later.
It's part of the way that we can make sure that our efforts to improve our internal services are meeting your needs, and an even better feedback mechanism than the conversations you are all so gracious to have with us on a regular basis.
If you have any questions about this policy, or you think it's bunk, we're happy to discuss it as part of our portion of the Rupture AgCorp IT all-hands on Friday, or in person if you happen to drop by our desks.
But make sure everyone in the SRE group knows how to properly do Semantic Versioning, to avoid unwanted changes!
You need to do this because if someone in your core services team marks a change as a bug fix or a security patch that they should have marked as a minor or major version change, this will betray the expectations you've set with the consumers of your service. And people will give up, and all but the adventurous will just avoid adopting new versions at all.
For modules maintained within your organization, a version range strategy may be appropriate if a semantic versioning methodology is used consistently or if there is a well-defined release process that avoids unwanted updates.
Here are two example use cases:
If you want to support Legacy Terraform versions, you can make a major version change reflect the new version of Terraform, e.g. Terraform 0.13.x would be supported by version 3.x.x of your module, and Terraform 0.12.x would be supported by version 2.x.x.
For instance, if you have a Module that adds some company specific context or standard resources to another module, like the AKS module, and you keep making updates each month, you do not want your internal projects and Terraform code for your SaaS or IaaS footprint to have versions pinned to the patch version. If the Terraform modules for your internal systems have their dependencies from the HashiCorp registry, like HashiCorp's Vault module, pinned to the security patch version, or minor version, well, OK. Maybe it's needed.
But if they're pinning your internally developed modules in your internal module registry to the patch version, it means you're missing out on a great chance to have productive conversations with the people who would consume your code about what they need and what they don't want.
It means that if you make an important change or necessary improvement in something they're not an expert in, they'll never know!
By the way, I haven't written this out of some kind of academic consideration for potential future issues.
This is a real solution to a real problem that organizations even more sophisticated than my own have run into. And I recommend that if you use Terraform and have shared services, you give it serious consideration.