【问题标题】:Regex pattern to match terraform module code正则表达式模式匹配 terraform 模块代码
【发布时间】:2020-08-06 01:55:22
【问题描述】:

我正在尝试使用正则表达式来匹配 terraform 模块并在行首添加注释。我不能仅对模块块使用正则表达式。请注意,某些行会在其他块(如资源)上重复。这个想法是扫描模块块并对其进行注释。任何帮助将不胜感激。花了很多时间蹦蹦跳跳的想法...

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 }
}

【问题讨论】:

    标签: python regex terraform multiline


    【解决方案1】:

    Terraform 语言不是 regular language,因此没有使用正则表达式处理它的完全通用方法。

    但是,该语言对其块语法有一些限制,这意味着您可以编写一个“足够好”的启发式算法来处理大多数情况(但仍然不是全部)。以下是有关 Terraform 语言的一些有用事实,可以帮助您稍微限制问题:

    • 块的开头必须始终出现在同一行,包括左大括号。在 module 关键字和 { 大括号之间包含额外的换行符是无效的。

    • 块有两种写法:

      • 正常布局是标题单独成一行,以引入块体的左大括号结尾:{。
      • 紧凑的单行布局将整个块放在一行上,内部有一个参数,如module "foo" { source = "./bar" }。
    • 正常布局中块的右大括号总是在自己的一行上。

    当然,也有一些不太方便的事实:

    • Terraform 也在其对象构造函数表达式中使用大括号,因此天真地寻找左大括号和右大括号会找到块边界和对象构造函数边界。

    • 字符串模板语法使用${ 或%{ 作为其开始分隔符,但它使用} 作为其结束分隔符,添加了右大括号的第三种含义。

    • “heredoc”语法脱离了正常的解析规则,意味着可以出现任意数量的大括号(不需要平衡)。但它们总是以<< 或<<- 开头,后跟一个标识符在一行的末尾,然后在其自己的一行上以相同的标识符结尾。

    综上所述,如果您可以控制输入并且可以确保它不会包含“边缘情况”,例如块头中间的 cmets、包含看起来像模块块的 heredoc 序列等,那么您可以能够通过逐行处理输入来获得“足够好”的结果:

    • 令 B = 0
    • 对于输入中的每一行:
      • 如果 B 为零:
      • 如果该行与 ^module ["\w- ]*{ 匹配,则对模块块执行您想要执行的任何操作。
      • 对于该行中的每个字符:
      • 如果字符是{,则递增B
      • 如果字符是},则减B

    这使用了一种简单的大括号计数方法来近似查找块的边界。如果输入包含带有不平衡大括号的文字字符串(带引号或heredoc),它将失败,因此您可以尝试通过计算打开/关闭引号和heredoc标记对来改进它。

    任何没有完整的语言解析器的东西总会有一些它无法处理的边缘情况,但是如果你可以限制你的输入不包括你的简单规则集无法理解的任何情况,那么像这样的方法以上可能对你有用。


    如果您愿意用 Go 编写程序,那么您可以使用 hclwrite 包,它是 Terraform 用于实现其语言语法的底层库的一部分。它有一个完整的解析器,并允许对其读取的内容进行“外科手术”编辑,尽管在我写这篇文章的时候,它似乎没有特别添加 cmets 到块的功能,所以它目前还没有准备好在这里解决你的具体目标.

    它可能对将来发现此问题并有其他与修改现有 Terraform 配置相关的目标的其他人有用,并且它可能会获得额外的功能来支持其他用例。

    【讨论】:

    • 马丁,非常感谢您的周到帖子。不幸的是,我处于边缘情况,在 terraform 文件中将有带有 here docs 的资源块以及带有 here docs 的模块块。当我将模块转换为资源时,我只需要注释模块块。这就是问题所在。我必须扫描文件,通过将模块块转换为资源块,将模块块替换为资源块,将它们写入 terraform 文件,然后返回查找模块块并对其进行注释。这就是我卡住的地方。谢谢!
    • 这组要求似乎无法使用正则表达式来实现。要稳健地执行这些步骤,将需要一个完整的 the underlying grammar 解析器。我认为最好寻找其他方法来满足您的基本目标,而不涉及对现有配置文件进行手术更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多