12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

既存のDynamoDBのテーブルを複製するシェルスクリプト (元テーブルと同じテーブルを作成&元テーブルに入ってたアイテムも登録する)

Posted at

やりたいこと

既存のAWSのDynamoDBに存在するテーブル群を、そのまま複製したい
(TABLE_A というテーブルがあるとき、TABLE_A_COPY というテーブルを作りたい)

  • TABLE_A_COPY は、 TABLE_A と同じテーブル定義であってほしい
  • TABLE_A_COPY には、 TABLE_A に登録されているアイテムがすべて登録されていてほしい
  • 上記を複数テーブルに対して行いたい

ちなみに、その理由は「テストで使いたいから」ですが、やってること自体はテストと関係ないので他の用途でも使えると思います。

大雑把な流れ

以下の処理を、複製したいテーブルの数だけ繰り返す

  1. 既存のテーブルのテーブル定義を取得して、ファイルに出力する
  2. 1 で作成したファイルを、aws dynamodb create-table で使用できる形に整形する (そのままだと、不要なデータがいっぱいあってエラーになるので)
  3. 2 で整形したファイルを使って、新しいテーブルを作成する
  4. 既存のテーブルに登録されているアイテム情報を取得して、ファイルに出力する
  5. 4 で作成したファイルからアイテム情報を読み込み、新しいテーブルに登録する

使用するツール

実際のスクリプト (データ作成先はローカル)

copy_table_for_test.sh
# !/bin/bash

# 元テーブルのテーブル定義から、create-table用のテーブル定義ファイルを作成する
get_table_data() {
  # AWSから元テーブルのテーブル定義を取得してファイルに出力
  aws dynamodb describe-table --table-name ${original_table_name} > ${original_table_file}

  # AWSから出力したテーブル定義を、create-tableに使用できる形に成形してファイルに出力
  cat ${original_table_file} |
  jq '.Table' |
  jq '.TableName = "'${new_table_name}'"' |
  jq 'del(.TableStatus)' |
  jq 'del(.CreationDateTime)' |
  jq 'del(.ProvisionedThroughput.LastIncreaseDateTime)' |
  jq 'del(.ProvisionedThroughput.NumberOfDecreasesToday)' |
  jq 'del(.TableSizeBytes)' |
  jq 'del(.ItemCount)' |
  jq 'del(.TableArn)' |
  jq 'del(.TableId)' |
  jq 'del(.LatestStreamLabel)' |
  jq 'del(.LatestStreamArn)' |
  jq 'del(.GlobalSecondaryIndexes[]?.IndexStatus)' |
  jq 'del(.GlobalSecondaryIndexes[]?.IndexSizeBytes)' |
  jq 'del(.GlobalSecondaryIndexes[]?.ItemCount)' |
  jq 'del(.GlobalSecondaryIndexes[]?.IndexArn)' |
  jq 'del(.GlobalSecondaryIndexes[]?.ProvisionedThroughput.NumberOfDecreasesToday)' > ${new_table_file}
}

# 元テーブルのテーブル定義ファイルを元に、テスト用のテーブルを新規作成する
create_table() {
  aws dynamodb create-table --cli-input-json file://${new_table_file} --endpoint-url http://localhost:8000
}

# 元テーブルに登録されているアイテム情報を、ファイルに出力する
get_items_data() {
  aws dynamodb scan --table-name ${table_name} > ${original_items_file}
}

# 元テーブルのアイテム情報ファイルを元に、テスト用のテーブルにアイテムを登録する
put_items() {
  # 登録対象のアイテム数
  item_length=$(cat ${original_items_file} | jq ".Items | length")

  # アイテム数 > 0 の場合のみ、テスト用テーブルにアイテムを登録する
  # (アイテムが無いのに put-itemコマンド実行しようとするとエラーになるので)
  if [ ${item_length} -gt 0 ]; then
    for i in $( seq 0 $((${item_length} - 1)) ); do
      item=$(cat ${original_items_file} | jq ".Items[${i}]")
      aws dynamodb put-item --table-name ${new_table_name} --item "${item}" --endpoint-url http://localhost:8000
    done
  fi
}

# テスト用に複製するテーブル群のテーブル名を指定
target_tables=("TABLE_A" "TABLE_B" "TABLE_C")

for table_name in ${target_tables[@]}; do
  # テーブル名
  original_table_name=${table_name}
  new_table_name=${original_table_name}_copy

  # テーブル定義ファイル名
  original_table_file=original_table_${original_table_name}.json
  new_table_file=new_table_${new_table_name}.json

  # アイテム情報ファイル名
  original_items_file=original_items_${original_table_name}.json

  get_table_data
  create_table
  get_items_data
  put_items
done

注意点

  • 手元のテーブル群に対してはこれで成功したけど、コピー元のテーブルの設定によっては get_table_data() 内でやってるJSONファイル整形処理をもっと増やさないといけない可能性があります。
  • 上記のスクリプトでは、新しいテーブルの作成先はローカルの DynamoDB にしています。
    --endpoint-url http://localhost:8000 を削除すると、ローカルじゃなくてクラウド上にテーブル作成します。

参考

12
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?