admin管理员组

文章数量:1122846

I am using Terraform to manage some cloudwatch alarms, and when Terraform destroys the alarms I want it to also delete the anomaly detection on the underlying metrics. As far as I can tell, I cannot manage the metrics themselves directly in Terraform (see ).

I am using a local-exec provisioner block and I think my problem is the command I'm trying to run involves some JSON. I was also trying to leave some newlines in the command itself for readability sake. I am really struggling with the way Terraform handles string literals. I've tried EOT, EOF, using a variable but I just can't get it to work.

Here's the command I'm trying to get Terraform to execute (this command works from my terminal)

    aws cloudwatch delete-anomaly-detector \
        --single-metric-anomaly-detector 
        '{
        "Namespace": "AWS/ApplicationELB",
        "AccountId": "redacted",
        "MetricName": "RequestCountPerTarget",
        "Dimensions": [
            {
                "Name": "TargetGroup",
                "Value": "redacted"
            }
        ],
        "Stat": "Average"
        }'

Here's my Terraform configuration (truncated for brevity)

resource "aws_cloudwatch_metric_alarm" "example" {
  alarm_name            = "example"
  #....
  #redacted for brevity
  #....
  provisioner "local-exec" {
    when = destroy
    command = format("aws cloudwatch delete-anomaly-detector --single-metric-anomoly-detector '%s'", jsonencode({
        Namespace   = "AWS\\ApplicationELB"
        AccountId   = "redacted"
        MetricName  = "RequestCountPerTarget"
        Dimensions  = [{
          Name  = "TargetGroup"
          Value = "redacted"
         }]
         Stat        = "Average"
       }
    ))
  }
}

When I run terraform apply it does execute, but the command isn't executed properly by the interpreter.

module.example.aws_cloudwatch_metric_alarm.example[0] (local-exec): Executing: ["/bin/sh" "-c" "aws cloudwatch delete-anomaly-detector --single-metric-anomoly-detector '{"AccountId":"redacted","Dimensions":[{"Name":"TargetGroup","Value":"redacted"}],"MetricName":"RequestCountPerTarget","Namespace":"AWS\\ApplicationELB","Stat":"Average"}'"]

module.example.aws_cloudwatch_metric_alarm.example[0] (local-exec): usage: aws [options] [ ...] [parameters] (local-exec): usage: aws [options] [ ...] [parameters]

I also created some gists if that's easier to read.

AWS command I'm trying to get Terraform to run

Terraform config (truncated)

I am using Terraform to manage some cloudwatch alarms, and when Terraform destroys the alarms I want it to also delete the anomaly detection on the underlying metrics. As far as I can tell, I cannot manage the metrics themselves directly in Terraform (see https://github.com/hashicorp/terraform-provider-aws/issues/18344).

I am using a local-exec provisioner block and I think my problem is the command I'm trying to run involves some JSON. I was also trying to leave some newlines in the command itself for readability sake. I am really struggling with the way Terraform handles string literals. I've tried EOT, EOF, using a variable but I just can't get it to work.

Here's the command I'm trying to get Terraform to execute (this command works from my terminal)

    aws cloudwatch delete-anomaly-detector \
        --single-metric-anomaly-detector 
        '{
        "Namespace": "AWS/ApplicationELB",
        "AccountId": "redacted",
        "MetricName": "RequestCountPerTarget",
        "Dimensions": [
            {
                "Name": "TargetGroup",
                "Value": "redacted"
            }
        ],
        "Stat": "Average"
        }'

Here's my Terraform configuration (truncated for brevity)

resource "aws_cloudwatch_metric_alarm" "example" {
  alarm_name            = "example"
  #....
  #redacted for brevity
  #....
  provisioner "local-exec" {
    when = destroy
    command = format("aws cloudwatch delete-anomaly-detector --single-metric-anomoly-detector '%s'", jsonencode({
        Namespace   = "AWS\\ApplicationELB"
        AccountId   = "redacted"
        MetricName  = "RequestCountPerTarget"
        Dimensions  = [{
          Name  = "TargetGroup"
          Value = "redacted"
         }]
         Stat        = "Average"
       }
    ))
  }
}

When I run terraform apply it does execute, but the command isn't executed properly by the interpreter.

module.example.aws_cloudwatch_metric_alarm.example[0] (local-exec): Executing: ["/bin/sh" "-c" "aws cloudwatch delete-anomaly-detector --single-metric-anomoly-detector '{"AccountId":"redacted","Dimensions":[{"Name":"TargetGroup","Value":"redacted"}],"MetricName":"RequestCountPerTarget","Namespace":"AWS\\ApplicationELB","Stat":"Average"}'"]

module.example.aws_cloudwatch_metric_alarm.example[0] (local-exec): usage: aws [options] [ ...] [parameters] (local-exec): usage: aws [options] [ ...] [parameters]

I also created some gists if that's easier to read.

AWS command I'm trying to get Terraform to run

Terraform config (truncated)

Share Improve this question edited Nov 22, 2024 at 19:08 TylerH 21.2k76 gold badges79 silver badges110 bronze badges asked Nov 22, 2024 at 16:47 pandaPowderpandaPowder 2,1152 gold badges13 silver badges7 bronze badges 5
  • 1 Maybe try creating a json file and using file or templatefile functions? Or, as an alternative, use the local_file data source to read a file? – Rui Jarimba Commented Nov 22, 2024 at 16:57
  • 1 I'm not super familiar with Terraform but it looks like jsonencode could help – lines Commented Nov 22, 2024 at 16:57
  • 1 Are you asking what the best way to do something is or how to make something work that's currently broken? Your question is a little unclear. – TylerH Commented Nov 22, 2024 at 17:34
  • 1 Thank you for the feedback @TylerH. I will clarify! Yes, this code is not currently working and I'm wondering how to get change the way I'm handling the strings to get it to work. In its current state, this is the output of the command when I run terraform apply: (local-exec): usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters] – pandaPowder Commented Nov 22, 2024 at 18:08
  • It seems like you have a typo in the Namespace value relative to your command: "AWS\\ApplicationELB" instead of "AWS/ApplicationELB". Unfortunately questions where the root cause is a typo are considered invalid for SO, so if this solves your problem please let us know. – Matthew Schuchard Commented Nov 22, 2024 at 18:23
Add a comment  | 

1 Answer 1

Reset to default 0

<<EOT Block: The <<EOT (a Here Document) is used to manage multi-line strings without worrying about escaping newlines or quotes. This makes the JSON string more readable.

resource "aws_cloudwatch_metric_alarm" "example" {
      alarm_name            = "example"
      #....
      #redacted for brevity
      #....
      provisioner "local-exec" {
        when    = destroy
        command = <<EOT
    aws cloudwatch delete-anomaly-detector --single-metric-anomaly-detector '{
      "Namespace": "AWS/ApplicationELB",
      "AccountId": "redacted",
      "MetricName": "RequestCountPerTarget",
      "Dimensions": [
        {
          "Name": "TargetGroup",
          "Value": "redacted"
        }
      ],
      "Stat": "Average"
    }'
    EOT
      }
    }

I also updated Namespace to use AWS/ApplicationELB directly without double backslashes (\), as the double backslashes were likely misinterpreted.

本文标签: