问题
I am trying to use regex to match terraform module and add a comment to the beginning of the line. I am not able to use regex for the module block only. Note that some lines do repeat on other blocks like resource. The idea is to scan for module block and comment it. Any help will be greatly appreciated. Spent a lot of time bouncing ideas...
module my module {
name = myaws
version = 1.0
source = terraform.mycompany.com
tag = { cost = poc }
}
data "my file" "file-name-creation-data" {
template = file("path/file.json")
}
resource aws_iam_role_policy "my-role" {
name = "first-policy"
role = new role.rolename
tag = { cost = pic }
}
回答1:
The Terraform language is not a regular language and so there is no fully-general way to process it with regular expressions.
However, the language has some constraints on its block syntax that mean you can potentially write a "good enough" heuristic that will deal with most cases (but still not all). Here are some useful facts about the Terraform language that can help constrain the problem a little:
The opening of a block must always appear all on the same line, including the opening brace. It's not valid to include additional newlines between the
module
keyword and the{
brace.There are two ways to write a block:
- Normal layout is for the header to be on a line of its own, ending with the opening brace that introduces the block body:
{
. - The compact single-line layout has the entire block on one line, with a single argument inside like
module "foo" { source = "./bar" }
.
- Normal layout is for the header to be on a line of its own, ending with the opening brace that introduces the block body:
The closing brace for a block in normal layout is always on a line of its own.
There are some not-so-convenient facts too, of course:
Terraform also uses braces for its object constructor expressions, so naively hunting for opening and closing braces will find both block boundaries and object constructor boundaries.
The string template syntax uses
${
or%{
as its opening delimiters, but it uses}
as its closing delimiters, adding a third meaning of a closing brace.The "heredoc" syntax escapes from the normal parsing rules and means that arbitrary numbers of braces (that do not need to be balanced) can appear. But they always start with a
<<
or<<-
followed by an identifier at the end of a line and then end with that same identifier on a line of its own.
With all of that said, if you have control over the input and can ensure it will not include "edge cases" like comments in the middle of block headers, heredoc sequences containing what looks like a module block, etc then you may be able to get a "good enough" result by processing the input on a line-by-line basis:
- Let B = 0
- For each line in the input:
- If B is zero:
- If the line matches
^module ["\w- ]*{
then take whatever action you want to take for a module block. - For each character in the line:
- If character is
{
then increment B - If character is
}
then decrement B
This uses a naive brace-counting approach to approximate finding the boundaries of blocks. It will fail if the input contains literal string (either quoted or heredoc) with unbalanced braces inside it, so you might try to improve on that by counting open/close quote and heredoc marker pairs too.
Anything short of a full parser for the language will always have some edge-case it can't handle, but if you can constrain your input to not include any situation that your simpler ruleset can't understand then an approach like the above might work for you.
If you were willing to write your program in Go then you'd be able to use the hclwrite package which is a part of the underlying library Terraform uses to implement its language syntax. It has a full parser and allows making "surgical" edits to what it reads, though at the time I write this it doesn't seem to have functions for adding comments to blocks in particular so it's not currently ready to solve your specific goal here.
It might be useful to others who find this question in future that have other goals related to modifying existing Terraform configurations, and it may get additional functionality to support other use-cases in the future.
来源:https://stackoverflow.com/questions/61375395/regex-pattern-to-match-terraform-module-code