Skip to content

Instantly share code, notes, and snippets.

@ChristophShyper
Last active February 17, 2021 12:24
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
Pass metadata between Terraform modules using DynamoDB. Only scalar values are possible. Maps or sets will cause issues. Much faster than remote state.

Save metadata in DynamoDB

resource "aws_dynamodb_table_item" "organization" {
  table_name = "my-dyn-db-table"
  hash_key = "KeyName"
  item = jsonencode({
    KeyName = {
      S = "organization"
    }
    Outputs = {
      M = {
        organization_arn = {
          S = aws_organizations_organization.default.arn
        }
        organization_id = {
          S = aws_organizations_organization.default.id
        }
      }
    }
  })
}

Use Python

Create the script for reading data

import boto3
import json
import sys


def handler(arg):
    table_name = arg['table_name']
    key_name = arg['key_name']
    item_name = arg['item_name']
    attr_name = arg['attr_name']
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table(table_name)
    ret = table.get_item(
        Key={
            key_name: item_name
        }
    )['Item'][attr_name]
    print("{}".format(json.dumps(ret)))


if __name__ == '__main__':
    data = json.load(sys.stdin)
    handler(data)
    exit(0)

Read the data via data source

data "external" "example" {
  program = ["python3", "${path.module}/read-dynamodb.py"]

  query = {
    table_name = "my-dyn-db-table"
    key_name = "ModulePath"
    item_name = "organization"
    attr_name = "Outputs"
  }
}

Use the data

output "organization_id" {
  value = data.external.example.result.organization_id
}

Use Bash

Create the script for reading data

#!/usr/bin/env bash
set -e
eval "$(jq -r '@sh "TABLE_NAME=\(.table_name) KEY_NAME=\(.key_name) ITEM_NAME=\(.item_name)"')"
RESP=$(aws dynamodb get-item --table-name "${TABLE_NAME}" --key "{ \"${KEY_NAME}\": { \"S\": \"${ITEM_NAME}\" }}" --region eu-west-1 | jq '.Item.Outputs.M')
jq -n --arg resp "${RESP}" '{"Outputs":$resp}'

Read the data via data source

data "external" "example" {
  program = ["sh", "${path.module}/read-dynamodb.sh"]

  query = {
    table_name = "my-dyn-db-table"
    key_name = "KeyName"
    item_name = "organization"
  }
}

Use the data

output "organization" {
  value = data.external.example.result["Outputs"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment