33

I'd like to replicate some dynamodb tables, schema only, into my local environment for testing purposes. First I've tried:

aws dynamodb describe-table --table-name Foo > FooTable.json

But it's obvious that the output schema is not compliant to the input schema from the create-table command:

aws dynamodb create-table --cli-input-json file://FooTable.json --endpoint=http://localhost:8000

What I'm trying to avoid is to generate dozens of skeletons with aws dynamodb create-table --generate-cli-skeleton and fill them manually :/

Is there a way to get the table schema in a format that is "useful" for recreation? I find it unbelievable that there are no straightforward way of doing it through the web graphic interface or the standard aws command line - after hearing how "good" was their service.

Alexander Patrikalakis
  • 5,054
  • 1
  • 30
  • 48
marcio
  • 10,002
  • 11
  • 54
  • 83
  • Does this answer your question? [Create a DynamoDB table from json](https://stackoverflow.com/questions/25334621/create-a-dynamodb-table-from-json) – Curtis Yallop May 27 '21 at 16:41

3 Answers3

17

I just managed to do a complete dump and "restore" using bchew/dynamodump:

git clone git@github.com:bchew/dynamodump.git

Notice the --schemaOnly option in the documentation https://github.com/bchew/dynamodump. Command was:

./dynamodump.py -m backup --schemaOnly --region foo-region --host localhost --srcTable '*' --port 8000 --accessKey fooKey --secretKey barKey

Then you can use the -m restore mode to put the data or schema back into a local dynamodb or wherever desired :)

With that said, I still find it unbelievable how bad is the amazon dynamodb tool-chain. Come on guys.

marcio
  • 10,002
  • 11
  • 54
  • 83
  • `dynamodump.py -h` results me in `Requested Python version (2) is not installed` what to do with that? How switch script to python `3.6.1`? – Cherry Jun 29 '17 at 13:44
  • I don't think it's compatible with python 3. You will need to install python 2 on your machine. – marcio Jun 29 '17 at 16:40
  • As of January this year it supports python3 (github.com/bchew/dynamodump/pull/42) – guzman Aug 31 '18 at 11:24
  • hi @marcio, when I am running `python3 dynamodump.py -m restore -r local -s * --host localhost --port 4569 --log DEBUG` I get the error below: `usage: dynamodump.py [-h] [-a {zip,tar}] [-b BUCKET] . [--dumpPath DUMPPATH] [--log LOG] . dynamodump.py: error: unrecognized arguments: LICENSE README.md dump dynamodump.py requirements.txt test` . – Parik Tiwari Nov 19 '18 at 23:38
3

This takes aws dynamodb describe-table output, and transforms it into the input-format of aws dynamodb create-table --cli-input-json:

AWS_PROFILE=xyz aws dynamodb describe-table --table-name MyTable > mytable_full.json

# Pull out just what is minimally needed for table-creation:
#
#  TableName
#  KeySchema
#  AttributeDefinitions (must only contain attributes used in keys)
#  Global/Local Secondary Indexes
#  Defaults BillingMode to PAY_PER_REQUEST
#   (any provisioning can be set up manually based on load)

jq <mytable_full.json '.Table | {TableName, KeySchema, AttributeDefinitions} + (try {LocalSecondaryIndexes: [ .LocalSecondaryIndexes[] | {IndexName, KeySchema, Projection} ]} // {}) + (try {GlobalSecondaryIndexes: [ .GlobalSecondaryIndexes[] | {IndexName, KeySchema, Projection} ]} // {}) + {BillingMode: "PAY_PER_REQUEST"}' ​>mytable.json

AWS_PROFILE=xyz aws dynamodb create-table --cli-input-json file://mytable.json

You can also paste the json into python (the python dict syntax closely matches json) eg

import boto3

dynamodb = boto3.resource("dynamodb")

tabledef = {
    "TableName": "MyTable",
    "KeySchema": [
...
}

table = dynamodb.create_table(**tabledef)
print("Table status: ", table.table_status)

References:

https://docs.aws.amazon.com/cli/latest/reference/dynamodb/describe-table.html https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html#creating-a-new-table

Curtis Yallop
  • 6,696
  • 3
  • 46
  • 36
  • Thanks for posting this. It is super helpful. I am trying to create a table with PROVISIONED capacity mode. How can pull the Read and WriteCapacityUnits into mytable.json from the table? – Pavan_k_k Sep 23 '22 at 18:56
2

Here is a version using C#, AWS CLI and Newtonsoft JSON on Windows. Start by running this command: -

aws dynamodb describe-table --table-name TheTable --profile SourceAWSCredsProfile > TheTable.json

Pick up the file, deserialize and serialize to the --cli-input-json friendly class: -

TableContainer tableContainer;

string sourceFile = "TheTable.json";
string destFile = "TheTable.cli-input.json";

using (StreamReader file = File.OpenText(sourceFile))
{
    JsonSerializer serializer = new JsonSerializer();
    tableContainer = (TableContainer)serializer.Deserialize(file, typeof(TableContainer));
}

File.WriteAllText(destFile, JsonConvert.SerializeObject(tableContainer.Table, Formatting.Indented, new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore
    }
));

Now run this command to import the table definition: -

aws dynamodb create-table --cli-input-json file://TheTable.cli-input.json --profile DestinationAWSCredsProfile

The TableContainer class definition is below. The absence of certain properties cleans out everything that the --cli-input-json parameter doesn't need. You can recreate this class anytime by running: -

aws dynamodb create-table --generate-cli-skeleton

Then copy and paste the output into a new class file, using the very handy Paste Special... Paste JSON as Classes feature in Visual Studio.

public class TableContainer
{
    public DynamoTableCLIJSON Table { get; set; }
}

public class DynamoTableCLIJSON
{
    public Attributedefinition[] AttributeDefinitions { get; set; }
    public string TableName { get; set; }
    public Keyschema[] KeySchema { get; set; }
    public Localsecondaryindex[] LocalSecondaryIndexes { get; set; }
    public Globalsecondaryindex[] GlobalSecondaryIndexes { get; set; }
    public string BillingMode { get; set; }
    public Provisionedthroughput ProvisionedThroughput { get; set; }
    public Streamspecification StreamSpecification { get; set; }
    public Ssespecification SSESpecification { get; set; }
    public Tag[] Tags { get; set; }
}

public class Provisionedthroughput
{
    public int ReadCapacityUnits { get; set; }
    public int WriteCapacityUnits { get; set; }
}

public class Streamspecification
{
    public bool StreamEnabled { get; set; }
    public string StreamViewType { get; set; }
}

public class Ssespecification
{
    public bool Enabled { get; set; }
    public string SSEType { get; set; }
    public string KMSMasterKeyId { get; set; }
}

public class Attributedefinition
{
    public string AttributeName { get; set; }
    public string AttributeType { get; set; }
}

public class Keyschema
{
    public string AttributeName { get; set; }
    public string KeyType { get; set; }
}

public class Localsecondaryindex
{
    public string IndexName { get; set; }
    public Keyschema1[] KeySchema { get; set; }
    public Projection Projection { get; set; }
}

public class Projection
{
    public string ProjectionType { get; set; }
    public string[] NonKeyAttributes { get; set; }
}

public class Keyschema1
{
    public string AttributeName { get; set; }
    public string KeyType { get; set; }
}

public class Globalsecondaryindex
{
    public string IndexName { get; set; }
    public Keyschema2[] KeySchema { get; set; }
    public Projection1 Projection { get; set; }
    public Provisionedthroughput1 ProvisionedThroughput { get; set; }
}

public class Projection1
{
    public string ProjectionType { get; set; }
    public string[] NonKeyAttributes { get; set; }
}

public class Provisionedthroughput1
{
    public int ReadCapacityUnits { get; set; }
    public int WriteCapacityUnits { get; set; }
}

public class Keyschema2
{
    public string AttributeName { get; set; }
    public string KeyType { get; set; }
}

public class Tag
{
    public string Key { get; set; }
    public string Value { get; set; }
}
Meeple
  • 156
  • 4