Поиск по сайту:

Как копировать элементы из одной таблицы DynamoDB в другую таблицу DynamoDB с помощью Python на AWS


Вы можете использовать Python для копирования элементов из одной таблицы DynamoDB в другую. Один и тот же сценарий можно использовать для копирования элементов между таблицами DynamoDB в разных учетных записях. Прежде чем мы приступим к этой статье, предполагается, что вы имеете базовое представление о Python. Вам не нужно ничего писать самостоятельно, вам просто нужно выполнить скрипт, чтобы завершить операцию копирования. Если вам нужно понять скрипт и написанный в нем код, то вам необходимо иметь базовые знания о Python.

Вы можете выполнить этот скрипт с любого компьютера, имеющего доступ к Интернету и установленного на нем Python. В вашей системе должны быть установлены Python и Boto3. Этот скрипт протестирован с Python 2.7.16, вы можете попробовать другие версии, доступные в Python 2.7.

Сервис AWS Data Pipeline также можно использовать для копирования элементов из одной таблицы DynamoDB в другую, но это немного утомительный процесс. Итак, я написал этот скрипт самостоятельно, чтобы упростить задачу.

Теперь давайте начнем.

Предпосылки

  1. Основное понимание Python.
  2. Python 2.7.16 и Boto3 установлены на сервере Linux.
  3. Аккаунт AWS (создайте, если у вас его нет).
  4. access_key и secret_key пользователя AWS IAM с достаточными/полными разрешениями на DynamoDB. (Нажмите здесь, чтобы узнать, как создать пользователя IAM с ключом доступа и секретным ключом в AWS, )

Что мы будем делать

  1. Проверьте предварительные условия.
  2. Создайте скрипт.
  3. Выполнить сценарий.

Проверить предварительные условия

Проверьте Python

python --version

Проверьте Пип

pip --version

Проверить Бото3

pip show boto3

Создать сценарий

Создайте новый файл со следующим кодом в вашей локальной системе. Код также доступен в моем репозитории Github. Ниже приведена ссылка на код на Github.

Ссылка на Github: https://github.com/shivalkarrahul/DevOps/blob/master/aws/python/aws-copy-dynamo-db-table/copy-dynamodb-table.py.

Файл: copy-dynamodb-table.py

import boto3
import os
import sys
import argparse
import datetime


global args
parser = argparse.ArgumentParser()

parser.add_argument('-sa', '--source_aws_access_key_id', required=True, action="store", dest="source_aws_access_key_id",
                    help="Source AWS Account aws_access_key_id", default=None)
parser.add_argument('-ss', '--source_aws_secret_access_key', required=True, action="store", dest="source_aws_secret_access_key",
                    help="Source AWS Account aws_secret_access_key", default=None)
parser.add_argument('-da', '--destination_aws_access_key_id', required=True, action="store", dest="destination_aws_access_key_id",
                    help="Destination AWS Account aws_access_key_id", default=None)
parser.add_argument('-ds', '--destination_aws_secret_access_key', required=True, action="store", dest="destination_aws_secret_access_key",
                    help="Destination AWS Account aws_secret_access_key", default=None)
parser.add_argument('-st', '--sourceTableName', required=True, action="store", dest="sourceTableName",
                    help="Source AWS Account DyanamoDB Table", default=None)
parser.add_argument('-dt', '--destinationTableName', required=True, action="store", dest="destinationTableName",
                    help="Destination AWS Account DyanamoDB Table", default=None) 
args = parser.parse_args()                                                                                                                       

source_aws_access_key_id = args.source_aws_access_key_id
source_aws_secret_access_key = args.source_aws_secret_access_key

destination_aws_access_key_id = args.destination_aws_access_key_id
destination_aws_secret_access_key = args.destination_aws_secret_access_key


sourceTableName=args.sourceTableName 
destinationTableName=args.destinationTableName 

sourceTableExists = "false" 
destinationTableExists = "false" 

print("Printing values")
print("source_aws_access_key_id", source_aws_access_key_id)
print("source_aws_secret_access_key", source_aws_secret_access_key)
print("destination_aws_access_key_id", destination_aws_access_key_id)
print("destination_aws_secret_access_key", destination_aws_secret_access_key)
print("sourceTableName", sourceTableName)
print("destinationTableName", destinationTableName)


timeStamp = datetime.datetime.now()
backupName = destinationTableName + str(timeStamp.strftime("-%Y_%m_%d_%H_%M_%S"))

item_count = 1000 #Specify total number of items to be copied here, this helps when a specified number of items need to be copied
counter = 1 # Don't not change this

source_session = boto3.Session(region_name='eu-west-3', aws_access_key_id=source_aws_access_key_id, aws_secret_access_key=source_aws_secret_access_key)
source_dynamo_client = source_session.client('dynamodb')

target_session = boto3.Session(region_name='eu-west-3', aws_access_key_id=destination_aws_access_key_id, aws_secret_access_key=destination_aws_secret_access_key)
target_dynamodb = target_session.resource('dynamodb')


dynamoclient = boto3.client('dynamodb', region_name='eu-west-3', #Specify the region here
    aws_access_key_id=source_aws_access_key_id,  #Add you source account's access key here
    aws_secret_access_key=source_aws_secret_access_key) #Add you source account's secret key here

dynamotargetclient = boto3.client('dynamodb', region_name='eu-west-3', #Specify the region here
    aws_access_key_id=destination_aws_access_key_id, #Add you destination account's access key here
    aws_secret_access_key=destination_aws_secret_access_key) #Add you destination account's secret key here
# response = dynamotargetclient.list_tables()
# print("List of tables", response)

dynamopaginator = dynamoclient.get_paginator('scan')

def validateTables(sourceTable, destinationTable):
    print("Inside validateTables")
    try:
        dynamoclient.describe_table(TableName=sourceTable)
        sourceTableExists = "true"
    except dynamotargetclient.exceptions.ResourceNotFoundException:
        sourceTableExists = "false"


    try:
        dynamotargetclient.describe_table(TableName=destinationTable)
        destinationTableExists = "true"
    except dynamotargetclient.exceptions.ResourceNotFoundException:
        destinationTableExists = "false"
    
    return {'sourceTableExists': sourceTableExists, 'destinationTableExists':destinationTableExists}        



def copyTable(sourceTable, destinationTable,item_count,counter):
    
    print("Inside copyTable")
    print("Coping", sourceTable, "to", destinationTable)

    print('Start Reading the Source Table')
    try:
            dynamoresponse = dynamopaginator.paginate(
            TableName=sourceTable,
            Select='ALL_ATTRIBUTES',
            ReturnConsumedCapacity='NONE',
            ConsistentRead=True
        )
    except dynamotargetclient.exceptions.ResourceNotFoundException:
        print("Table does not exist")
        print("Exiting")
        sys.exit()

    print('Finished Reading the Table')
    print('Proceed with writing to the Destination Table')
    print("Writing first", item_count , "items" )
    print(dynamoresponse)
    for page in dynamoresponse:
        for item in page['Items']:
            if (counter ==  item_count):
                print("exiting")
                sys.exit()
            else:      
                print('writing item no', counter)
                dynamotargetclient.put_item(
                    TableName=destinationTable,
                    Item=item
                    )   
            counter = counter + 1

def backupTable(destTableName, backupTimeStamp):
    print("Inside backupTable")
    print("Taking backup of = ", destTableName)
    print("Backup Name = ", backupTimeStamp)

    response = dynamotargetclient.create_backup(
        TableName=destTableName,
        BackupName=backupTimeStamp
    )
    print("Backup ARN =", response["BackupDetails"]["BackupArn"])

def deleteDestinationTable(destTableName):
    print("Inside deleteDestinationTable")
    try:
        dynamotargetclient.delete_table(TableName=destTableName)
        waiter = dynamotargetclient.get_waiter('table_not_exists')
        waiter.wait(TableName=destTableName)
        print("Table deleted")
    except dynamotargetclient.exceptions.ResourceNotFoundException:
        print("Table does not exist")


def doesNotExist():
    print("Inside doesNotExist")
    print("Destination table does not exist ")
    print("Exiting the execution")
    # sys.exit()

def createDestinationTable(sourceTable):
    print("Inside createDestinationTable")
    source_table = source_session.resource('dynamodb').Table(sourceTable)

    target_table = target_dynamodb.create_table(
    TableName=destinationTableName,
    KeySchema=source_table.key_schema,
    AttributeDefinitions=source_table.attribute_definitions,
    ProvisionedThroughput={
        'ReadCapacityUnits': 5,
        'WriteCapacityUnits': 5
    })

    target_table.wait_until_exists()
    target_table.reload()


result = validateTables(sourceTableName, destinationTableName)
print("value of sourceTableExists = ", result['sourceTableExists'])
print("value of destinationTableExists = ", result['destinationTableExists'])

if (result['sourceTableExists'] == "false" ) and (result['destinationTableExists'] == "false" ):
    print("Both the tables do not exist")

elif (result['sourceTableExists'] == "false" ) and (result['destinationTableExists'] == "true" ):
    print("Source Table does not exist")

elif (result['sourceTableExists'] == "true" ) and (result['destinationTableExists'] == "false" ):
    createDestinationTable(sourceTableName)
    copyTable(sourceTableName, destinationTableName, item_count, counter)

elif (result['sourceTableExists'] == "true" ) and (result['destinationTableExists'] == "true" ):
    backupTable(destinationTableName, backupName)
    deleteDestinationTable(destinationTableName)

    createDestinationTable(sourceTableName)
    copyTable(sourceTableName, destinationTableName, item_count, counter)

else:
    print("Something is wrong")

Синтаксис:

python copy-dynamodb-table.py -sa <source-account-access-key-here> -ss <source-account-secret-key-here> -da <destination-account-access-key-here> -ds <destination-account-secret-key-here> -st <source-table-name-here> -dt <destination-table-name-here>

Выполнить сценарий.

Вы можете обратиться к приведенному выше синтаксису и передать аргументы сценарию.

Команда:

python copy-dynamodb-table.py -sa AKI12345IA5XJXFLMTQR -ss ihiHd8+NzLJ567890z4i6EwcN6hbV2A5cMfurscg -da AKI12345IA5XJXFLMTQR -ds  ihiHd8+NzLJ567890z4i6EwcN6hbV2A5cMfurscg -st my-source-table -dt my-destination-table

Здесь,

  • -sa=Исходный ключ доступа к аккаунту AWS = AKIAQ6GAIA5XJXFLMTQR
  • -ss=Исходный секретный ключ аккаунта AWS=ihiHd8+NzLJK5DFfTz4i6EwcN6hbV2A5cMfurscg
  • -da=ключ доступа к целевому аккаунту AWS=AKIAQ6GAIA5XJXFLMTQR
  • -ds=Секретный ключ целевого аккаунта AWS=ihiHd8+NzLJK5DFfTz4i6EwcN6hbV2A5cMfurscg
  • -st = Исходная таблица = моя-исходная-таблица
  • -dt = Целевая таблица = моя-целевая-таблица

Вы должны использовать свои ключи, ключи здесь принадлежат мне.

Скрипт охватывает 4 различных варианта использования

  1. Сценарий использования 1. Обе таблицы, исходная и целевая, не существуют.
  2. Сценарий 2. Исходная таблица не существует, но существует целевая таблица.
  3. Сценарий 3. Исходная таблица существует, но не существует целевой таблицы.
  4. Сценарий 4. Обе таблицы – исходная и целевая – существуют.

Давайте рассмотрим эти варианты использования один за другим.

Вариант использования 1: обе таблицы, исходная и целевая, не существуют.

Если в вашей учетной записи нет таблиц DynamoDB, но вы все равно пытаетесь выполнить сценарий, сценарий завершится с сообщением «Обе таблицы не существуют».

Вариант использования 2. Исходная таблица не существует, но существует целевая таблица.

Если вы попытаетесь передать несуществующую таблицу в качестве исходной, сценарий завершится с сообщением «Исходная таблица не существует».

Вариант использования 3. Исходная таблица существует, но целевая таблица не существует.

В обоих вышеупомянутых двух случаях использования никакая операция не выполняется. Теперь, если вы передадите исходную таблицу, которая существует, но целевая таблица не существует, скрипт создаст таблицу с именем, которое вы укажете в качестве целевой таблицы, и скопирует элементы из исходной таблицы во вновь созданную целевую таблицу.

Вариант использования 4. Обе таблицы – исходная и целевая – существуют.

В этом сценарии перед копированием элементов из исходной таблицы создается резервная копия целевой таблицы, после чего целевая таблица удаляется. После удаления таблицы создается новая таблица с именем, указанным в параметре назначения, а затем элементы из исходной таблицы копируются во вновь созданную таблицу назначения.

Заключение

В этой статье мы видели сценарий Python для копирования элементов из одной таблицы DynamoDB в другую таблицу DynamoDB. Сценарий охватывает четыре различных варианта использования, которые могут возникнуть при копировании элементов из одной таблицы в другую. Теперь вы можете использовать этот скрипт для копирования элементов из одной таблицы DynamoDB в другую в том же или другом аккаунте AWS.