Puede usar Python para copiar elementos de una tabla de DynamoDB a otra. El mismo script se puede usar para copiar elementos entre tablas de DynamoDB en diferentes cuentas. Antes de continuar con este artículo, se supone que tiene una comprensión básica de Python. No necesita escribir nada por su cuenta, solo necesitaría ejecutar el script para terminar con la operación de copia. Si necesita comprender el script y el código escrito en él, debe tener un conocimiento básico de Python.
Puedes ejecutar este script desde cualquier máquina con acceso a Internet y Python instalado. Debe tener Python y Boto3 instalados en su sistema. Este script está probado con Python 2.7.16, puede probar con diferentes versiones disponibles en Python 2.7.
El servicio AWS Data Pipeline también se puede usar para copiar elementos de una tabla de DynamoDB a otra, pero ese es un proceso un poco tedioso. Entonces, escribí este script por mi cuenta para simplificar la tarea.
Ahora, comencemos.
Requisitos previos
- Comprensión básica de Python.
- Python 2.7.16 y Boto3 instalados en el servidor Linux.
- Cuenta de AWS (cree si no tiene una).
- 'access_key' y 'secret_key' de un usuario de IAM de AWS con permisos suficientes o completos en DynamoDB. (Haga clic aquí para aprender a crear un usuario de IAM con 'access_key' y 'secret_key' en AWS)
Qué haremos
- Consulte los requisitos previos.
- Cree una secuencia de comandos.
- Ejecute la secuencia de comandos.
Verificar requisitos previos
Comprobar Python
python --versión
Comprobar Pip
pip --versión
Comprobar Boto3
pip muestra boto3
Crear un Script
Cree un nuevo archivo con el siguiente código en su sistema local. El código también está disponible en mi Github Repo. El siguiente es el enlace al código en Github.
Enlace de Github: https://github.com/shivalkarrahul/DevOps/blob/master/aws/python/aws-copy-dynamo-db-table/copy-dynamodb-table.py
Archivo: 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")
Sintaxis:
python copy-dynamodb-table.py -sa
Ejecutar la secuencia de comandos.
Puede consultar la sintaxis anterior y pasar los argumentos al script.
Comando:
pitón copy-dynamodb-table.py -sa AKI12345IA5XJXFLMTQR -SS ihiHd8 + NzLJ567890z4i6EwcN6hbV2A5cMfurscg -da AKI12345IA5XJXFLMTQR -ds ihiHd8 + NzLJ567890z4i6EwcN6hbV2A5cMfurscg -st mi-source-mesa -dt mi-destino-tabla
Aquí,
- -sa =Clave de acceso a la cuenta de AWS de origen = AKIAQ6GAIA5XJXFLMTQR
- -ss = Clave secreta de la cuenta AWS de origen = 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
- -da = Destino Clave de acceso a la cuenta de AWS = AKIAQ6GAIA5XJXFLMTQR
- -ds = Clave secreta de la cuenta de AWS de destino = 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
- -st = Tabla de origen = mi-tabla-de-origen
- -dt = Tabla de destino = mi-tabla-de-destino
Debes usar tus claves, las claves aquí me pertenecen.
El script cubre 4 casos de uso diferentes
- Caso de uso 1:ambas tablas, Origen y Destino, no existen.
- Caso de uso 2: la tabla de origen no existe pero existe la tabla de destino.
- Caso de uso 3: la tabla de origen existe pero la tabla de destino no existe.
- Caso de uso 4:ambas tablas, fuente y destino, existen.
Veamos estos casos de uso uno por uno.
Caso de uso 1:ambas tablas, Fuente y Destino, no existen.
Si no tiene tablas de DynamoDB en su cuenta y aun así intenta ejecutar la secuencia de comandos, la secuencia de comandos saldrá con el mensaje "Ambas tablas no existen".
Caso de uso 2: la tabla de origen no existe pero la tabla de destino existe.
Si intenta pasar la tabla que no existe como la tabla de origen, la secuencia de comandos saldrá con el mensaje "La tabla de origen no existe".
Caso de uso 3: la tabla de origen existe pero la tabla de destino no existe.
En los dos casos de uso anteriores, no se realiza ninguna operación. Ahora, si pasa la tabla de origen que existe pero la tabla de destino no existe, la secuencia de comandos creará una tabla con el nombre que especifique como tabla de destino y copiará los elementos de la tabla de origen a la tabla de destino recién creada.
Caso de uso 4:ambas tablas, fuente y destino, existen.
En este escenario, se realiza una copia de seguridad de la tabla de destino antes de copiar los elementos de la tabla de origen y luego se elimina la tabla de destino. Después de eliminar la tabla, se crea una nueva tabla con el nombre que especifique en el parámetro de destino y luego los elementos de la tabla de origen se copian en la tabla de destino recién creada.
Conclusión
En este artículo, vimos la secuencia de comandos de Python para copiar elementos de una tabla de DynamoDB a otra tabla de DynamoDB. El script cubre cuatro casos de uso diferentes que pueden surgir al copiar elementos de una tabla a otra. Ahora puede usar esta secuencia de comandos para copiar elementos de una tabla de DynamoDB a otra en la misma cuenta de AWS o en otra diferente.