Skip to content

Instantly share code, notes, and snippets.

@ChristophShyper
Last active February 17, 2021 12:24
Show Gist options
  • Save ChristophShyper/02efe6e4d40443f1d04273b794b164e0 to your computer and use it in GitHub Desktop.
Save ChristophShyper/02efe6e4d40443f1d04273b794b164e0 to your computer and use it in GitHub Desktop.
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