-
Notifications
You must be signed in to change notification settings - Fork 9.5k
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
Terraform provider version constraint resolution for NOT prerelease #33452
Comments
Thanks for reporting this @jskirde. There is logic in Terraform's version resolution to ignore prerelease versions unless they are named exactly, so writing just I wonder then if the logic for that special rule isn't taking into account the negation. It works by searching the version constraints for any exact version references that are prereleases, and so perhaps it's incorrectly classifying these negated terms as "exact", since they do specify an exact version even though it's negated. This version handle belongs to an upstream library rather than to Terraform itself, but I happen to be the maintainer of that library so I'll be able to arrange for a fix to be released so far Terraform can use it, if the problem does turn out to be there. |
I tried quickly adding a test case to the upstream apparentlymart/go-versions that resembles this situation, with both a lower bound and a negation: {
MustMakeSet(MeetingConstraintsStringRuby(">= 2.0.0, != 2.0.0-beta1, != 2.0.0-beta2")),
MustParseVersion("2.0.0-beta2"),
false,
}, This table-based test asks whether the version given in the second field is matched by the constraints given in the first field. In this case I would expect the answer to be This test passed, so unfortunately I think that disproves my theory that this might just be a flaw in the logic for deciding whether a particular prerelease version is "explicitly selected". Something else seems to be going on here. |
Looking back again at what you reported, I see this in the
In particular, notice that this final merged constraint contains both As you noted at the end, Terraform should've treated this as a contradiction and either matched nothing at all (because a version can't be both 2.0.1-alpha2 and not 2.0.1-alpha2 at the same time) or returned an error during version constraint parsing saying that there's a contradiction. It seems like the bug is that the positive |
Okay! I was able to reproduce this variant in the upstream test suite: {
MustMakeSet(MeetingConstraintsStringRuby(">= 2.0.0, != 2.0.0-beta1, != 2.0.0-beta2, 2.0.0-beta2")),
MustParseVersion("2.0.0-beta2"),
false,
}, This test fails because the version set membership test returns |
It seems like the minimum reproduction case here is:
If either of the above don't hold then the test passes. Here's the revised test case: {
MustMakeSet(MeetingConstraintsStringRuby("!= 2.0.0-beta1, 2.0.0-beta1")),
MustParseVersion("2.0.0-beta1"),
false, // the constraint is contradictory, so includes nothing
},
For readability, here's a more concise view of how the library is interpreting this version constraint:
That interpretation seems flawed: the outer With that said, I am also kinda curious as to why it chose "union" here since I would have intuitively expected these version sets to be combined with "intersection", since the comma operator in this syntax means "AND", not "OR". Perhaps the root cause is there. |
Further poking confirms that it does seem to be the special case for prerelease versions that's somehow causing the problem, because there's already a test in the parsing code for this trivial contradiction case:
This behaves as I would've expected, producing an empty set by applying intersection to both "1.0.0" and "not 1.0.0", which have no versions in common. The equivalent of this with prereleases makes a similar odd result as in the previous comment: `1.0.0-beta1, != 1.0.0-beta1`
versions.Union(
versions.Only(versions.MustParseVersion("1.0.0-beta1")),
versions.Intersection(
versions.Released,
versions.Only(versions.MustParseVersion("1.0.0-beta1")),
(versions.All).Subtract(versions.Only(versions.MustParseVersion("1.0.0-beta1"))),
)
) So it seems like the logic that tries to carve out the exception for allowing prereleases while lowering the constraint into its constituent operators is where the problem lies here. Since this bug is with what is arguably an edge case (it's rare for version constraints to contain negations at all, let alone ones that are prereleases and are contradicted) and the correct behavior here would've been a failure anyway (so this isn't blocking any valid configuration from working) I'm going to leave this context here for now in the hope of addressing this in future, but I unfortunately have to divert to other planned work for today. Thanks for reporting this, and sorry for the incorrect behavior. |
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. |
Terraform Version
Terraform Configuration Files
Terraform is able to select a pre-release provider for a module even if it's explicitly denied using a version constraint.
This means that if any one module enforces a pre-release version and other modules use pessimistic or greater than version constraints, after all the constraints are AND'ed together, a pre-release version will be selected.
output
$ terraform init -upgrade
Initializing the backend...
Upgrading modules...
Initializing provider plugins...
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
version = "2.0.1-alpha1, !=2.0.1-alpha1"
The text was updated successfully, but these errors were encountered: