Terraform 在不应该的情况下解释本地表达式

Con*_*ery 6 regex amazon-web-services amazon-ecs terraform

我有一个在 AWS ECS 上运行的 Kafka 客户端容器,它应该从容器环境变量中接收要订阅哪些主题的正则表达式。在我的 terraform 中,我定义环境变量,如下所示:

..
      {
        "name": "KAFKA_TOPIC_REGEX",
        "value": "${local.kafka_topic_regex[local.environment]}"
      }
..
Run Code Online (Sandbox Code Playgroud)

在 locals.tf 文件中使用相应的值,如下所示:

..
  kafka_topic_regex = {
    development = "^(ab\..*\..*)$|^(foo\.bar)$"
  }
..
Run Code Online (Sandbox Code Playgroud)

但是我很难让它按预期工作。当我进行地形规划时,显示以下错误:

The symbol "." is not a valid escape sequence selector.
Run Code Online (Sandbox Code Playgroud)

不幸的是,我需要反斜杠,以便正则表达式使用文字点作为主题名称中的字符。我无法逃避反斜杠,因为我实际上需要它存在于正则表达式中。

我同样尝试过正则表达式,如下所示:

^(ab[.].*[.].*)$|^(foo[.]bar)$
Run Code Online (Sandbox Code Playgroud)

同样,Terraform 对此做了一些奇怪的解释,在计划中该值显示为:

^ab.(.*)
Run Code Online (Sandbox Code Playgroud)

这意味着我需要的文字点不在正则表达式中,因为它需要在正则表达式中转义。

看起来 Terraform 正在解释我的字符串并导致计划/应用失败,而它不应该解释它。

任何帮助将不胜感激,谢谢

Mar*_*ins 8

不幸的是,这是一种典型的情况,当一种语言的源代码用另一种语言编写为字符串时会导致这种情况:您需要处理多个级别的转义。尽管将正则表达式称为“另一种语言”似乎很慷慨,但从 Terraform 的角度来看,这正是它们的本质,尽管它是一种非常简洁的语言,具有非常具体的功能集。

这里的要求是编写一个 Terraform 可以计算的表达式,以生成一个包含正则表达式的字符串,然后正则表达式引擎可以解释该正则表达式。正如您所指出的,生成的正则表达式字符串必须包含文字反斜杠,因为反斜杠是正则表达式语言的一部分。

我们可以通过使用额外的反斜杠转义反斜杠来生成 Terraform 语言中包含文字反斜杠的字符串:

"\\"
Run Code Online (Sandbox Code Playgroud)

从 Terraform 的角度来看,上面的代码将生成一个仅包含一个反斜杠的字符串。

我们可以通过转义正则表达式中的所有反斜杠来将这个想法扩展到您的正则表达式问题:

  kafka_topic_regex = {
    development = "^(ab\\..*\\..*)$|^(foo\\.bar)$"
  }
Run Code Online (Sandbox Code Playgroud)

当 Terraform 计算该带引号的字符串时,它将通过生成单个文字反斜杠来响应转义的反斜杠,因此生成的字符串将如^(ab\..*\..*)$|^(foo\.bar)$正则表达式引擎所期望的那样。然后,您可以将该结果传递给正则表达式引擎进行处理,此时它应该看到序列\.并(如您所愿)将其视为文字.而不是“任何单个字符”通配符。

需要注意的一个“陷阱”是,Terraform 在 UI 中呈现字符串值(例如描述计划的更改)时使用其自己的带引号字符串语法的变体。这样做时,它将重新引入反斜杠转义,以便在屏幕上明确呈现结果,将其显示为^(ab\\..*\\..*)$|^(foo\\.bar)$。一般来说,当读取 Terraform 在屏幕上显示的输出值时,我们应该将它们理解为Terraform 自己的语言中常量值的表示,而不是将使用的文字值。这类似于 Terraform 将数字显示为十进制数字序列(例如 )的方式1234,而不是显示真正代表 Terraform 内存中该值的原始二进制值。


Con*_*ery 0

似乎实际应用的计划/应用细分是错误的。使用方括号转义点的正则表达式将应用正确的值,但在计划和应用中显示不正确。工作版本: ^(ab[.].*[.].*)$|^(foo[.]bar)$