-
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
Support for lookaheads in the regex parser #30433
Comments
I wanted to see if I could work around this with a positive lookahead, but that also fails. |
Hi @tspearconquest, Terraform is using the "RE2" regular expression engine, which does indeed omit several of the more "expensive" features from other regex engines like Perl's. I don't expect we will aim to grow the regex support here because regular expressions are not Terraform's focus and we don't wish to risk changing behavior of existing modules using the current engine. However, focusing on your underlying use-case rather than the regex solution to it (thanks for including that context!), perhaps another way to get there would be to use can(cidrnetmask(var.vnet_address_space)) This function parses its argument as CIDR notation in order to do its job, and so it already has a definition of the expected syntax built in to it. |
Hi, thanks for pointing that out. I hadn't thought of it. This should fill the gap for the example, certainly. Now unfortunately I must say the We would like to be able to take either form in some variables where both forms are supported. The use of I could open an issue with the provider to ask for this support, but want to make the case that it could be a useful feature to add a function for this purpose to Terraform. Something which can validate both forms, as well as possibly take an argument in the form of a list of IP ranges considered valid, so that you can (for example) prevent ranges outside of your subnets from being allowed via the variable validation rule. Would you be open to accepting a feature request for this? |
Hi @tspearconquest, The functions built in to the Terraform language are typically ones that have broad applicability, and the existing Our typical answer for the possibility of user-defined behavior like this today is to encourage writing a custom provider which offers a data source that provides whatever information is needed, but that approach won't help in this particular case because it isn't valid to refer to a data resource from a validation rule, and even if it were it would cause a dependency cycle to have the data resource refer to the variable and the variable also refer to the data resource. Given all of that, I think what you've raised here would be a good additional example use-case for #2771, where we're considering how to allow provider plugins to contribute extension functions to the Terraform language. We're not currently actively working on that, but I'm going to create a link between these two issues so that we can see this additional use-case when considering that other issue in future, and take it into account when prioritizing what to work on next. In the meantime, it is true that
While I do see that this is getting considerably more fiddly than my original suggestion, you could potentially support both by trying both forms, like this: can(cidrnetmask(var.vnet_address_space)) || can(cidrnetmask("${var.vnet_address_space}/32")) Thanks! |
Thank you as well. This looks like a suitable workaround for now. Thanks also for considering the idea and the additional insight. Do you want me to keep this open or close it out? |
I just destroyed my brain trying to get standard lookaheads working with Terraform regex before I realized the function is incorrectly named (perhaps change it to regexlite?). For anyone looking for more complex validation reqs, have a look at this example that satisfies RDS Postgres; and the following CIDR examples I slapped in just to help out anyone here for that particular nugget. |
Current Terraform Version
Use-cases
Many times it is required to input an IP or subnet somewhere in order to build a resource. Often, these inputs are unsanitized but it is desirable to perform input sanitization for variables containing IPs by using a regex.
I found the following post which provides a number of examples of regex patterns to return only correct matches for IPs and so I thought I'd try using
length(regexall())
with a slight variation on the second shortest example:https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp
My attempt to use it in a validation block:
But I got an error:
In the error above, the part:
^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])([.](?!
is underlined, meaning the error is being caused by the capture group([.](?!$)|$)
which leads me to believe that the negation operator for a lookahead is failingAttempted Solutions
I googled to see if the other way to negate a match would work. That is...
[^]
with the thing you don't want to match inside (the end of line character$
for me.) It doesn't match because the$
is literal instead of an end of line character when it is used inside a character class.Proposal
References
The text was updated successfully, but these errors were encountered: