Cómo copiar elementos de un DynamoDB a otra tabla de DynamoDB usando Python en AWS

Versión de Python

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 una comprensión básica de Python.

Puede ejecutar este script desde cualquier máquina con acceso a Internet y Python instalado en ella. 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

  1. Comprensión básica de Python.
  2. Python 2.7.16 y Boto3 instalados en el servidor Linux.
  3. Cuenta AWS (Crear si no tienes uno).
  4. ‘access_key’ y ‘secret_key’ de un usuario de AWS IAM con permisos suficientes o completos en DynamoDB. (Haga clic aquí para obtener información sobre cómo crear un usuario de IAM con ‘access_key’ y ‘secret_key’ en AWS)

Que haremos

  1. Consulte los requisitos previos.
  2. Crear un guión.
  3. Ejecutar el Script.

Verifique los requisitos previos

Compruebe Python

python –versión

Versión de Python

Compruebe Pip

pip –versión

Versión pipa

Ver Boto3

pepita mostrar boto3

Versión Boto3

Crear un guión

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 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 -ss <clave-secreta-de-la-cuenta-de-origen-aquí> -da <clave-de-acceso-a-la-cuenta-de-destino-aquí> -ds < clave-secreta-de-la-cuenta-de-destino-aquí> -st <nombre-de-la-tabla-de-origen-aquí> -dt <nombre-de-la-tabla-de-destino-aquí>

Ejecutar el Script.

Puede consultar la sintaxis anterior y pasar los argumentos al script.

Dominio:

python copy-dynamodb-table.py -sa AKI12345IA5XJXFLMTQR -ss ihiHd8+NzLJ567890z4i6EwcN6hbV2A5cMfurscg -da AKI12345IA5XJXFLMTQR -ds ihiHd8+NzLJ567890z4i6EwcN6hbV2A5cMfurscg -da AKI12345IA5XJXFLMTQR -ds ihiHd8+NzLJ567890z4i6EwcN6hbV2A5cMfurscg -ds ihiHd8+NzLJ567890z4i6EwcN6hbV2A5cMfurscg-mydestination-fur-table-source-dm-table-source

Aquí,

  • -sa = Clave de acceso a la cuenta de AWS de origen = AKIAQ6GAIA5XJXFLMTQR
  • -ss = Clave secreta de la cuenta AWS de origen = ihiHd8+NzLJK5DFfTz4i6EwcN6hbV2A5cMfurscg
  • -da = Clave de acceso a la cuenta de AWS de destino = AKIAQ6GAIA5XJXFLMTQR
  • -ds = Clave secreta de la cuenta de AWS de destino = ihiHd8+NzLJK5DFfTz4i6EwcN6hbV2A5cMfurscg
  • -st = Tabla de origen = mi-tabla-de-origen
  • -dt = Tabla de destino = mi-tabla-de-destino

Debes usar tus llaves, las llaves aquí me pertenecen.

El script cubre 4 casos de uso diferentes.

  1. Caso de uso 1: ambas tablas, origen y destino, no existen.
  2. Caso de uso 2: la tabla de origen no existe pero la tabla de destino existe.
  3. Caso de uso 3: la tabla de origen existe pero la tabla de destino no existe.
  4. Caso de uso 4: Ambas tablas, Origen y Destino, existen.

Veamos estos casos de uso uno por uno.

Caso de uso 1: ambas tablas, origen y destino, no existen.

Si no tiene tablas de DynamoDB en su cuenta y sigue intentando ejecutar la secuencia de comandos, la secuencia de comandos saldrá con el mensaje «Ambas tablas no existen».

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 tabla de origen, la secuencia de comandos saldrá con el mensaje «La tabla de origen no existe».

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, el script 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.

La tabla de destino no existe

Caso de uso 4: Ambas tablas, Origen y Destino, existen.

En este escenario, se realiza una copia de seguridad de la tabla de destino antes de copiar 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.

Tanto las mesas

Ambas tablas existen

Copia de seguridad de la tabla de destino antes de hacer frente a nuevos elementos

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 este script para copiar elementos de una tabla de DynamoDB a otra en la misma cuenta de AWS o en una diferente.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *