-
Notifications
You must be signed in to change notification settings - Fork 9.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to disable lockfiles #31533
Comments
Thanks for filing this request! |
Hi @wyardley! Can you say a little more about how you are using Renovate? I ask because my understanding of Renovate is that its purpose is to automatically propose upgrading to newer versions of a dependency, and for Terraform in particular I would've expected it to achieve that by proposing a change to the lock file which selects a newer version. It sounds like you're achieving that in a different way, in which case I'd like to hear more about it just so we can understand the problem underlying your request. I don't expect we will be able to do exactly what you are requesting -- Terraform relies on its own lock file to track which provider versions you've selected, so Terraform cannot operate at all without it -- but I'd like to think about other ways we could help Renovate to integrate with Terraform. |
So, there may be some rudimentary lockfile support at this point, though IIRC, it can only do it at a single top level lockfile maybe, and there have been some reported issues with certain providers... https://github.com/renovatebot/renovate/issues/10550e That said, I'm not sure it's fair for a tool like that to be able to support any specific arbitrary version of each tool's lockfile format -- to do so, it would either need to use Terraform, or manage exact compatibility with its lockfile format. For me, this is predictable enough - we update all instances of pinning terraform itself one version at a time, and the same for the various providers (GCP, AWS, Azure), across all states / substates / modules at a time, typically planning them, and validating in CI, to make sure things still are working as expected. I'm not sure if there could be a corner case where a module may pull in a transitive dependency that might change unexpectedly without using a lockfile, but I am totally Ok with that. For all intents and purposes, maintaining the exact versions we want, and no lockfile, provides essentially the same behavior as using a tool to update those same versions and a lockfile at the same time, but with (IMO) much less hassle, and less risk of the tool messing up the lockfile, having issues with certain providers, etc. It is typical (and for languages like Javascript or Ruby, which have a lot of dependencies and nested dependencies, we do follow this behavior) for Renovate to update the Lockfile as well. But with any of these languages, its default behavior is to pin all the dependencies it manages. With terraform, that basically means that, if you don't leave in any fuzzy version constraints, Renovate is already basically ensuring fairly predictable versions if you run
I will obviously defer to you on what Terraform "needs", but I guess I would say that it's more accurate to say that Terraform needs the dependencies specified in its configuration to know which provider versions you've selected. It can use the lockfile to ensure some predictability between runs once it's created a lockfile, if used (and you all suggest, but do not require, checking in the lockfile to vcs), but since Terraform can initialize and create a lockfile when one is not present, and knows what versions to install, I would say that, even if it's not possible now, it should theoretically be possible to create a situation where Terraform doesn't create, or read, a lockfile, and, of course, this is how Terraform worked for many years. In fact, as we're normally planning from a fresh environment with no lockfile or cache, we're already essentially behaving as if there were no lockfile, except in the occasional case we happen to plan something locally. I fully expect that the answer is that I shouldn't want what I'm asking for, and that's fine. |
We are in a similar situation - we build a master image with Terraform and install all of our providers into it at fixed versions (previously using It would be great if we could tell Terraform to just use the versions that are present in the directory it will already be searching for providers, not to download anything that is missing, and critically - not to complain about this very valid mode of operation. |
I guess my ideal model of how Renovate should behave with Terraform is to only update the lock file, and to propose selecting the highest-precedence provider version (per semver rules) which meets the constraints specified in the configuration. The constraints in the specification are intended to represent what versions a module is compatible with, whereas the lock file represents the single version of each provider a provider is currently using within the bounds of those constraints. I will admit that I'm not well versed in the details of how Renovate does its work, but it could achieve that by behaving as if it were performing the following steps:
Maintainers can then use the guidance in Understanding Lock File Changes to review the proposed change with consideration to their organization's typical policy for adopting new software. From what you've described it sounds like Renovate doesn't directly run the package manager whose lock files / manifests it is updating and instead attempts to manipulate those files directly itself. Is that true? If so, then indeed that does seem like a troublesome thing to maintain over time, but for any manifest or lock file that is supposed to be included in version control the package manager must presumably remain backward-compatible with its own historical formats so that it can handle upgrading, and for Terraform in particular I would not expect us to be changing the dependency lock file parser in a way that would not accept files generated by older versions. If the Renovate team is interested we'd love to learn about what's in the way of Renovate doing something which would achieve the same result as what I described above (even if it isn't implemented exactly how I described it). Also, I guess I should address the observation that Terraform used to work without a dependency lock file. It is true that before the "dependency lock file" was instead a hidden manifest file under the If you put |
Renovate (by default) partially works by pinning all the dependencies (it can use semver, but its default is to pin everything, and with terraform, I don't think it handles fuzzy version specs perfectly anyway). It does this even with systems like So therefore, you're getting a PR to update
It absolutely could do that, but I guess my point is that if one is already pinning all, or almost all, dependencies, the work needed to do this (the tool has to have the terraform binary baked into its container, potentially multiple versions of it) seems like a lot of work vs. just trusting that, since you asked for 1.1.1, you got 1.1.1. Presumably any concerns about checksum not matching or other security issues are already handled outside of the lockfile itself. So, I guess the question I have is, if you're already pinning all of your versions to exact equality, what additional benefit is the lockfile providing? Additionally, this is extra work to resolve conflicts in the lockfile if (as they frequently are) they're introduced; Renovate already handles this seamlessly, but just seems kind of unnecessary here.
Perhaps, but in the Good Olde Days (TM), terraform would also give you the version you asked for if you updated it, and IIRC, not checking in that lockfile was the recommended (vs. non-recommended now) behavior.
Yes, as mentioned, we already do that. So Terraform already is behaving this way (starting with no lockfile) not only when Renovate runs, but also in CI runs where validation happens, and so far, the sky hasn't fallen. And yet, it would be faster and simpler if terraform didn't need to create the lockfile (which will never be consumed) in this case. The ask here is to allow terraform a way to ignore the lockfile (or always behave as if And yes, I imagine I could add Of course we can argue about the "right" way, or the "Hashicorp approved" way to do things; I guess what's frustrating is that it doesn't seem like it would introduce too many issues to create an option to prevent |
I suppose where I'm getting caught up with this discussion is that we added the lock file specifically because people found it annoying that the version constraints in the configuration were simultaneously representing both "what dependencies are compatible with this module?" and "what exact version are we using right now?" such that people would get themselves into "dependency hell" situations where each of their modules was specifying a single exact version and they all had to always exactly agree in order for anything to work. The introduction of a user-visible lock file, rather than one that Terraform maintains only as an implementation detail in a hidden directory, separated those two concerns so that modules could focus only on describing what they are compatible with, and the lock file can take over the responsibility of tracking what's currently selected. From what you are saying it sounds like in your particular case you have no interest in tracking what modules are compatible with. I can imagine that being true if you are using exclusively first-party modules (so you don't need to deal with other people's version constraints) and you're motivated to stay on latest and just fix things when they break, rather than (as was true for the folks who advocated for lock files) treating upgrades as a project to be planned for and done explicitly at a convenient time. I can certainly understand that position, but I'd prefer to find an answer where you can get what you want without the need for a special "use the modules themselves to track selected versions" mode. Here's an question that might shed light on what I'm missing here: if Renovate hypothetically already had perfect support for updating the lock file as I described earlier, and if you just removed all of the version constraints from your modules entirely and used the lock file exclusively to track what versions you have selected (so Renovate would then always select the latest version of every provider to propose), what would you be missing? So far having exact version constraints in your modules feels functionally equivalent to having exact versions tracked in the lock file, but I assume there must be some detail I'm not seeing! 😀 Regarding As you've noticed yourself, |
Absolutely -- in a perfect world, I'd have no issue with this situation (though in my example, I'd prefer to have the version specs still pinned and updated in the . The problem is with "perfect" - I'm assuming Hashicorp doesn't have time to maintain / provide support for perfect dependency updates in Renovate (as well as comparable tools like Dependabot), nor to provide libraries in language other than golang to provide alternative interfaces besides the terraform binary for doing so, and it's also difficult to expect them to maintain perfect support for the various supported versions of terraform. Renovate does bake some binaries into its tools, but (even with things that are much more widely used than Terraform), the results are not always pefect. If someone is going to devote the time to maintain supporting updating the lockfiles in a way that will continue to work (even if the lockfile version format changes in the future), I will definitely be enthusiastic about embracing the approach you are suggesting.
That's exactly right. I absolutely understand the utility of the lockfile for most people's use cases. However, when mostly or exclusively using first-party modules, in a single project along with the rest of the terraform code, it's as easy, or maybe easier, to update / check everything in lockstep in one fell swoop.
I'll have to play around with some old versions. It's been a while. |
Maybe with the format in the tf lockfile it's not as bad as with some, but reading diffs of generated lockfiles tends to be a lot harder / messier, in my experience, as is resolving conflicts. For many types of generated files, GH doesn't even show the diff by default. |
ps - I will try this out (checked in lockfiles w/ Renovate) with a small personal project and see how the current state is in terms of how it's working. |
So, the good news is that Renovate does deal with multiple lockfiles Ok, and it basically works, though the hash format seems different from what I generated locally [side note: but, as suspected, the diff for the lockfile is both not displayed by default (ever) in the GH UI, and is somewhat harder to read (esp. in this case, where the hashes are turning over): Hopefully this helps explain why I don't like only the lockfile changing, especially, as well as some of my concerns about implementation varying depending on the logic of the program updating the lockfile and / or version of terraform used. |
ps - If I init based on the lockfile Renovate proposes locally, it also changes the lockfile back as shown (maybe related to #27811; also related: renovatebot/renovate#11821): diff --git a/gcp/.terraform.lock.hcl b/gcp/.terraform.lock.hcl
index 6f9ab2a..fe125f4 100644
--- a/gcp/.terraform.lock.hcl
+++ b/gcp/.terraform.lock.hcl
@@ -16,5 +16,17 @@ provider "registry.terraform.io/hashicorp/google" {
"h1:mCRW9OtukK3KDG1lRyFIun2LuJue56QgnCru8kmeyPA=",
"h1:n4dCdx9EhvoQO/SiLKZGkGKWxpCHodL5cjFtYDQhOQY=",
"h1:vyXvM/V6cv7Ux2JO1Zd6IinJYutBVTgBK+PXga4fkoE=",
+ "zh:03fa16d2811fc3ef523b8afad5ce4c1c72e686a425f48f9432f21b16c55c2872",
+ "zh:23ad507dad0b3478c46b050f9d4660251e20b2ae6f334f4904af9aeef7e6f5d2",
+ "zh:2a20c8c6bb1c8185c7c4b6e418cbdb36ab212c549ffa7ab4c027f929224798bc",
+ "zh:53b8cd6ecc73c6fc1570dfbf9a549af975741c25cf544d6fec13d96c7312bd93",
+ "zh:5856c11c35636c362e04ddaf3cce7ed94e0aea74f22b6d3fc2449f1c0ce4b159",
+ "zh:68cda07855d20984d4fce6959a760392b1ef4e09e4f8e74bf10765b020727f0c",
+ "zh:84b501635c135a692f378dec2e56beca088d25f5e6c98276dbab8de30d27ce5e",
+ "zh:972e990c88f1b4c9bfe501e3a829c02bd89a494b3b445900216906365397a672",
+ "zh:a47acfb0b07d83687fab00275381755817aacec6f9f949e8d52e0bcae45e870f",
+ "zh:dcb078b2be1d8527e7bf9283112ba1214bb76d2279d78d921bebd413fb0310e0",
+ "zh:e00a1b11f0782e389b02c8a4487b2f25c42647714adcb56770f87883440997e9",
+ "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
} |
ps: https://github.com/renovatebot/renovate/issues/13692 is also well worth reading, and has some explanation / discussion on why they implement the lockfile update in code vs. using the terraform binary. For one thing, it seems like as things stand now, Renovate can't trivially use the terraform binary directly for this, though I'm guessing |
Thanks for sharing these examples, @wyardley! One specific potential improvement I can see from what you've shared is in how As you've noticed, The newer Terraform currently has some logic to opportunistically "upgrade" from the It seems like that "upgrade" behavior also currently works in the opposite direction, effectively "downgrading" So with all of this said: I think we should consider making Terraform not generate additional Of course that doesn't address all of what you observed here, but it does at least seem like it would address this checksum-related oddity discussed in renovatebot/renovate#13692, without requiring Renovate to also generate the legacy checksum format. |
Separately, it also seems like Renovate is running into #27161 and with the new context here, I can see that it was opened directly in response to Renovate's challenges using In that other discussion I recommended to use Since there's already an issue open for that part I'll let that one continue to represent the question of how to get the lock file updated in a way that doesn't require backend initialization, which would be another part of the story of making Terraform support the "ideal" upgrade-detection flow I described earlier. |
Yes, it was a little odd that running
Without looking at the code, based on the discussion in the ticket, I think they're actually currently implementing it directly in code vs. shelling out to Terraform, but could be wrong there. |
Ok, had to look up the syntax for the old style config, but:
Maybe I'm missing something, but I don't see any files / directories being created that persist after |
Just for fun, also tried with latest 0.12.31; best I can tell, it's still not required to run
|
Hi @wyardley, Thanks for sharing those examples. I see what you are getting at now. In your most recent example I see that you found the However you are right that in these older versions before the lock file, because in those days the version constraints were overloaded to represent both "what are we compatible with" and "what exactly are we using", changing the version constraints in the module behaved like how editing the lock file would behave today, and so indeed However, we considered that a design error: Terraform should not just quietly upgrade something without announcing that it did so, because that may cause the configuration to behave in a subtly different way or -- in the worse case -- end up running a compromised version of the plugin that doesn't match the checksums that a team originally reviewed and approved. The However, what we can do (and I think we should do) is prioritize fixing the remaining friction that makes it hard to use the lock file for its intended purpose of capturing the currently-selected provider versions, so that there is no longer any reason to misuse version constraints as if they were a lock file. This discussing has identified a few different things to work on already, and I've copied those into an internal list of possible future projects for our team to consider. The goal of that project would be to make the lock file work as intended by addressing these and other rough edges, so that there will be fewer reasons to ignore the lock file. |
Hi, Renovate has an option to update the lockfile only if possible (`rangeStrategy: 'update-lockfile') Yes, we use custom code to create the hashes and update the lockfile. This has multiple reasons:
@apparentlymart I would be happy to discuss a way how to simplify this and improve the experience for users of Renovate and Terraform. |
Hi @secustor! Thanks for sharing that extra context. For the backend credentials issue at least, I'd suggest trying With that said, I also don't think there's any great harm in updating the lock file directly if Renovate has access to information that Terraform normally doesn't. The lock file format is a compatibility constraint and so future versions of Terraform should be able to consume the current lock file format for a long time, even if we were to introduce new versions of it in later releases. The lock file includes the aggregated version constraints from the configuration tree specifically to allow other consumers to decode just the lock file and not have to deeply analyze the whole module tree to collect dependencies. (Terraform itself doesn't actually need to use that information, because it already knows how to walk the module tree to produce the same information.) That would be primarily aimed at what Renovate calls the With the intention that the constraints in the configuration are describing what the modules are compatible with rather than what they are currently selecting, and with our existing recommendation that module authors constrain the upper bound only if they already know a specific later version of the provider broke compatibility, it seems less useful to automatically update a module to remove its upper version constraint bound, but of course there's no real harm in supporting that as an option for those who have a different workflow e.g. involving only internal modules that can reasonably be updated all together, without any need to coordinate between modules published by different authors. We would still like to make a new revision of the provider registry protocol which supports both the legacy hashing scheme and the current hashing scheme, but changing a documented protocol is of course a more significant effort than just changing implementation details inside the one CLI executable and also interacts with provider publishing workflows and therefore means rolling out a change across every separate provider repository. |
I tried to do what the helpful warning suggested and created the lockfile:
However, we already have these providers cached in our image and this causes Terraform to reach out again to the registry in order to download the providers, which is not ideal - we download and pin the versions of the providers intentionally to avoid having to reach out to the registry, and also to have a known good image to run Terraform from that isn't running un-vetted code. Regardless, this then causes the
I don't particularly feel like debugging this immediately, but I feel it's put us in a difficult position of having to work around some new behaviours or suffer endless noisy warnings. |
Hi @ohookins, If you intend to lock the checksums in your local mirror directory, instead of the ones in the origin registry for each provider, then you can use the This particular command defaults to using the origin registry because the common use for it is to lock the checksums signed by the provider author (which are only available from the origin registry) and then verify a local mirror against those checksums later to make sure that the mirror is correct. However, in your case it seems like you would prefer to treat the mirror itself as the root of trust, so you can use |
The works great, @apparentlymart , thanks a bunch! |
Seems like I spoke too soon, and only ran it on a workspace that didn't have any of our private local modules. There's a bit of a conflict when trying to do this:
But of course running |
I want to disable the lockfile because I don't use Terraform for provider resolution. I compile the provider, copy to the right location, and run Terraform. All this futzing around with lockfiles and their problems is entirely pointless. (At least in my case -- I'm sure it important if you're using third party providers and such.) |
Current Terraform Version
Use-cases
We use Renovate to pin versions of basically everything, and we
.gitignore
lockfiles.However, the Terraform feature to create / use a lockfile is still not configurable.
This means that when planning locally, one has to remember to use
terraform init -upgrade
when versions have changed -- even if you are already pinning versions to explicit known versions that you want. It also creates unnecessary lockfiles in cases where the lockfiles are gitignored and new environments are created.Please reconsider the previously dismissed feature request to allow users to choose not to use a lockfile.
Attempted Solutions
Proposal
Terraform should offer an option to not use the lockfile at all when initializing / planning.
References
terraform init
#29958The text was updated successfully, but these errors were encountered: