Conditionally add a block in dynamodb item

Hi Folks,
I need to add a block in dynamodb_table_item only if a condition is true.
(Last comment in example)

resource "aws_dynamodb_table_item" "new_account" {
  table_name = "OrgAccountRequest"
  hash_key   = "id"
  item       = jsonencode(merge({
      "id"= {
        "S"= "${var.account_email_address}"
      },
 
      "accountType"= {
        "S"= "${var.account_type}"
      },
      "appName"= {
        "S"= "${var.domain_name}"
      },
      "costCenter"= {
        "S"= "${var.cost_center}"
      },
     
      # var.account_type == "sandbox" ? {"datadog_enabled" = { "BOOL" = var.datadog_enabled }}  : null      
      }
  ))
}

Can anyone help me with this?
Thank you

Hi @shubhampatel-eb

You are very close, you just have your ternary statement in the wrong place for the merge.

Merge expects an arbitrary number of maps

Example 1

> merge({a="b", c="d"}, {e={f="g"}})
{
  "a" = "b"
  "c" = "d"
  "e" = {
    "f" = "g"
  }
}

But where you have your ternary expression it is inside the first map as another item, rather than a separate map to merge with it.

Example 2

> merge({a="b", c="d",{ e = { f="g" }}})
╷
│ Error: Missing key/value separator
│
│   on <console-input> line 1:
│   (source code not available)
│
│ Expected an equals sign ("=") to mark the beginning of the attribute value.

When the ternary expression is moved outside of the first map you get the desired behaviour (As per Example 1):

Example 3

> merge({a="b", c="d"}, "abc" == "abc" ? {e={f="g"}}:{})
{
  "a" = "b"
  "c" = "d"
  "e" = {
    "f" = "g"
  }
}

To introduce this into your code (Note I have removed the jsonencode for clarity:

  item = merge({
    id = {
      S = "${var.account_email_address}"
    }
    accountType = {
      S = "${var.account_type}"
    }
    appName = {
      S = "${var.domain_name}"
    }
    costCenter = {
      S = "${var.cost_center}"
    }
    },
    var.account_type == "sandbox" ? {
      datadogEnabled = {
        BOOL = var.datadog_enabled
      }
    } : {}
  )

Which shows as the following format, as desired:

Outputs:

item = {
  "accountType" = {
    "S" = "sandbox"
  }
  "appName" = {
    "S" = "domain.com"
  }
  "costCenter" = {
    "S" = "12345"
  }
  "datadogEnabled" = {
    "BOOL" = true
  }
  "id" = {
    "S" = "account@domain.com"
  }
}

Hope that helps!

Happy Terraforming

@ExtelligenceIT Thank you for the solution. It is working. Can we do it without jsonencode function?

Hi @shubhampatel-eb,

aws_dynamodb_table_item item argument does require a JSON representation so you will still need the jsonencode as follows:

 item = jsonencode(merge({
    id = {
      S = "${var.account_email_address}"
    }
    accountType = {
      S = "${var.account_type}"
    }
    appName = {
      S = "${var.domain_name}"
    }
    costCenter = {
      S = "${var.cost_center}"
    }
    },
    var.account_type == "sandbox" ? {
      datadogEnabled = {
        BOOL = var.datadog_enabled
      }
    } : {}
  ))

Apologies, I missed this from my example.

If my answers worked for you, can you please mark the relevant reply as the solution, to help others that may have the same issue fid the solution more easily.

Thanks