terraformのjsonencode()には<, >, &を \u003c, \u003e, \u0026 に変換するよく知られた仕様がある。
When encoding strings, this function escapes some characters using Unicode escape sequences: replacing
<,>,&,U+2028, andU+2029with\u003c,\u003e,\u0026,\u2028, and\u2029. This is to preserve compatibility with Terraform 0.11 behavior.
replace()を使うのが今のところの回避策ではあるが、複数の文字列を置換するのがめんどいのでmultireplace() jsonunescape()というユーザー定義関数を作った。
output "london_bridge" { value = provider::multireplace::multireplace( "London Bridge Is Falling Down, Falling down, falling down", { Falling = "Winding", falling = "jumping" } ) #=> "London Bridge Is Winding Down, Winding down, jumping down" # value = provider::multireplace::multireplace( # "London Bridge Is Falling Down, Falling down, falling down", # { Falling = "Winding" }, # { falling = "jumping" } # ) }
locals { # see https://developer.hashicorp.com/terraform/language/functions/jsonencode jsonencode_html = jsonencode({ link = "<a href=\"https://example.com?foo=bar&zoo=baz\">Open</a>" }) jsonunescape_html = provider::multireplace::jsonunescape(local.jsonencode_html) } output "html" { value = <<-EOT ${local.jsonencode_html} --- ${local.jsonunescape_html} EOT #=> <<-EOT # {"link":"\u003ca href=\"https://example.com?foo=bar\u0026zoo=baz\"\u003eOpen\u003c/a\u003e"} # --- # {"link":"<a href=\"https://example.com?foo=bar&zoo=baz\">Open</a>"} # EOT }
その後、よく調べたらmultireplace()については既存の実装があった。
locals { # 実際の関数呼び出しは `provider::string-functions::multi_replace(...)` replaced = multi_replace("a,b,c,d,e", { "," = "|", "a" = "z", }) } output "replaced" { value = local.replaced } # replaced = "z|b|c|d|e"
こちらの方はmulti_replace()だけではなく、Case conversionやEscapingなど文字列まわりの便利関数が一通りそろっている。
jsonencode()に特化している訳ではないので、自作のterraform-provider-multireplaceプロバイダは使っていくと思うが、terraform-provider-string-functionsもなかなか便利そうなので今後使っていきたい。