Terraform:“ INVALID_JSON_DESCRIPTION:非法的无引号字符

时间:2019-08-21 08:36:56

标签: amazon-web-services terraform terraform-provider-aws terraform-template-file

我有一个Terraform step_function脚本,该脚本调用Lambda函数来发送电子邮件。我想将电子邮件正文作为这样的变量发送:

  data "template_file" "start_es_email" {
    template = "${file("email_template/start_es.html")}"
  }

  data "template_file" "start_template" {
    template = "${file("step_function/start_stepfunction.json")}"

    vars = {
      aws_region            = "${var.aws_region}",
      ses_sender            = "${var.ses_sender}"
      ses_destination_email = "${var.ses_destination_emails}"
      ses_body_html         = "${data.template_file.start_es_email.rendered}"
    }
  }

这是start_es.html文件的内容,它只是一个简单的HTML内容:

<html>
<body>
<h1>ElasticSearch cluster started and ready</h1>
<p>
The ElasticSearch cluster has started and ready to use
</p>
</body>
</html>

这是状态函数资源:

resource "aws_sfn_state_machine" "start_cluster" {
  name     = "start-es-sfn-${var.environment}"
  role_arn = "${aws_iam_role.step_function_iam_role.arn}"

  definition = "${data.template_file.start_template.rendered}"
}

这就是我在状态函数json文件中所拥有的:

"SendSuccessEmail": {
      "Type": "Task",
      "Resource": "${lambda_notification}",
      "Parameters": {
        "SES_SENDER": "${ses_sender}",
        "SES_DESTINATION_EMAIL": "${ses_destination_email}",
        "SUBJECT": "${ses_subject}",
        "BODY_HTML": "${ses_body_html}"
      },
      "End": true
    },

现在,当调用terraform apply时,我收到此错误:

  

错误:InvalidDefinition:无效的状态机定义:   'INVALID_JSON_DESCRIPTION:非法的不带引号的字符(((CTRL-CHAR,   代码10)):必须使用反斜杠进行转义以包含在字符串中   值

我试图使html内容像这样一行:

<html><body><h1>ElasticSearch cluster started and ready</h1><p>The ElasticSearch cluster has started and ready to use</p></body></html>

它可以正常工作,但是那样读取和维护文件并不是很好。

有办法解决吗?

谢谢。

2 个答案:

答案 0 :(得分:0)

根据您提供的信息,看来渲染的模板具有非法字符,需要转义。控制字符10是换行符。因此,每个新行都需要使用反斜杠进行转义。您是否在Windows应用程序(如notepad ++或类似文件)中创建了该html文件?我会尝试在VSCode或Linux编辑器(如vim或nano)中创建它。

作为另一种选择,您可以尝试在每行文本的末尾使用'\\ n'或'\ n'而不使用对号来转义换行符。我以前没有遇到过这个问题,因此我不确定要与Terraform合作的正确方法。 JSON的地形整理有时可能很困难。

我能告诉您的是为什么您得到CC10,并且将所有信息都放在一行上就可以工作。

答案 1 :(得分:0)

如果您正在使用Terraform v0.12或能够对其进行升级,则可以使用功能jsonencode来避免此问题:

resource "aws_sfn_state_machine" "start_cluster" {
  name     = "start-es-sfn-${var.environment}"
  role_arn = aws_iam_role.step_function_iam_role.arn

  definition = jsonencode({
    "SendSuccessEmail": {
      "Type": "Task",
      "Resource": lambda_notification,
      "Parameters": {
        "SES_SENDER": var.ses_sender,
        "SES_DESTINATION_EMAIL": var.ses_destination_emails,
        "SUBJECT": var.ses_subject,
        "BODY_HTML": data.template_file.start_es_email.rendered,
      },
      "End": true,
    },
  })
}

通过使用jsonencode,您可以让Terraform担心JSON编码。它将看到data.template_file.start_es_email.rendered值中包含换行符,并将自动以\n对其进行转义。除非出于特殊原因需要精确控制数据的格式,否则我建议始终使用jsonencode在Terraform中生成JSON,而不要使用字符串模板。

尽管Terraform 0.11 确实具有jsonencode函数,但是它是一种更为简单的实现,对于这种特殊情况不会产生正确的结果。