AWS에서 Python을 사용하여 한 DynamoDB에서 다른 DynamoDB 테이블로 항목을 복사하는 방법


이 페이지에서

  1. 전제 조건
  2. 무엇을 할 것인가\n
  3. 전제 조건 확인\n
  4. 스크립트 만들기
  5. 스크립트를 실행합니다.\n
  6. 결론

Python을 사용하여 한 DynamoDB 테이블에서 다른 테이블로 항목을 복사할 수 있습니다. 동일한 스크립트를 사용하여 서로 다른 계정의 DynamoDB 테이블 간에 항목을 복사할 수 있습니다. 이 기사를 진행하기 전에 Python에 대한 기본적인 이해가 있다고 가정합니다. 직접 작성할 필요는 없으며 복사 작업을 완료하기 위해 스크립트를 실행하기만 하면 됩니다. 스크립트와 스크립트에 작성된 코드를 이해해야 하는 경우 Python에 대한 기본적인 이해가 필요합니다.

인터넷에 액세스할 수 있고 Python이 설치된 모든 컴퓨터에서 이 스크립트를 실행할 수 있습니다. 시스템에 Python 및 Boto3가 설치되어 있어야 합니다. 이 스크립트는 Python 2.7.16에서 테스트되었으며 Python 2.7에서 사용 가능한 다른 버전으로 시도할 수 있습니다.

AWS Data Pipeline 서비스를 사용하여 한 DynamoDB 테이블에서 다른 테이블로 항목을 복사할 수도 있지만 이는 약간 지루한 프로세스입니다. 그래서 작업을 단순화하기 위해 이 스크립트를 직접 작성했습니다.

이제 시작하겠습니다.

전제 조건

  1. Python에 대한 기본적인 이해.\n
  2. Linux 서버에 설치된 Python 2.7.16 및 Boto3.
  3. AWS 계정(계정이 없는 경우 생성).
  4. DynamoDB에 대한 충분한/전체 권한이 있는 AWS IAM 사용자의 access_key 및 secret_key. (AWS에서 access_key 및 secret_key를 사용하여 IAM 사용자를 생성하는 방법을 알아보려면 여기를 클릭하십시오.)\n

우리는 무엇을 할 것인가

  1. 전제 조건을 확인하십시오.\n
  2. 스크립트를 만듭니다.
  3. 스크립트를 실행합니다.\n

전제 조건 확인

파이썬 확인

핍 확인

보토3 확인

스크립트 만들기

로컬 시스템에서 다음 코드를 사용하여 새 파일을 만듭니다. 이 코드는 내 Github Repo에서도 사용할 수 있습니다. 다음은 Github의 코드 링크입니다.

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")

통사론:

스크립트를 실행합니다.

위 구문을 참조하여 인수를 스크립트에 전달할 수 있습니다.

명령:

여기,

  • -sa =소스 AWS 계정 액세스 키=AKIAQ6GAIA5XJXFLMTQR
  • -ss = 소스 AWS 계정 암호 키 = ihiHd8+NzLJK5DFfTz4i6EwcN6hbV2A5cMfurscg\n
  • -da=대상 AWS 계정 액세스 키=AKIAQ6GAIA5XJXFLMTQR
  • -ds = 대상 AWS 계정 암호 키 = ihiHd8+NzLJK5DFfTz4i6EwcN6hbV2A5cMfurscg\n
  • -st=소스 테이블=my-source-table
  • -dt=대상 테이블=my-destination-table

당신은 당신의 열쇠를 사용해야 합니다. 여기 있는 열쇠는 제 것입니다.

스크립트는 4가지 다른 사용 사례를 다룹니다.

  1. 사용 사례 1: 원본 및 대상 테이블이 모두 존재하지 않습니다.\n
  2. 사용 사례 2: 소스 테이블은 없지만 대상 테이블은 있습니다.
  3. 사용 사례 3: 소스 테이블은 있지만 대상 테이블은 없습니다.
  4. 사용 사례 4: 소스 및 대상 테이블이 모두 존재합니다.\n

이러한 사용 사례를 하나씩 살펴보겠습니다.

사용 사례 1: 원본 및 대상 테이블이 모두 존재하지 않습니다.

계정에 DynamoDB 테이블이 없는 상태에서 여전히 스크립트를 실행하려고 하면 "Both the tables do not exist" 메시지와 함께 스크립트가 종료됩니다.

사용 사례 2: 소스 테이블은 없지만 대상 테이블은 있습니다.

존재하지 않는 테이블을 소스 테이블로 전달하려고 하면 "소스 테이블이 없습니다" 메시지와 함께 스크립트가 종료됩니다.

사용 사례 3: 소스 테이블은 존재하지만 대상 테이블은 존재하지 않습니다.

위의 두 사용 사례 모두에서 작업이 수행되지 않습니다. 이제 존재하는 소스 테이블을 전달하지만 대상 테이블이 존재하지 않는 경우 스크립트는 대상 테이블로 지정한 이름으로 테이블을 생성하고 소스 테이블의 항목을 새로 생성된 대상 테이블로 복사합니다.

사용 사례 4: 소스 및 대상 테이블이 모두 존재합니다.

이 시나리오에서는 소스 테이블에서 항목을 복사하기 전에 대상 테이블의 백업을 수행한 다음 대상 테이블을 삭제합니다. 테이블이 삭제된 후 대상 매개변수에 지정한 이름으로 새 테이블이 생성된 다음 원본 테이블의 항목이 새로 생성된 대상 테이블에 복사됩니다.

결론

이 기사에서는 한 DynamoDB 테이블에서 다른 DynamoDB 테이블로 항목을 복사하는 Python 스크립트를 보았습니다. 이 스크립트는 한 테이블에서 다른 테이블로 항목을 복사하는 동안 발생할 수 있는 네 가지 사용 사례를 다룹니다. 이제 이 스크립트를 사용하여 하나의 DynamoDB 테이블에서 동일하거나 다른 AWS 계정의 다른 테이블로 항목을 복사할 수 있습니다.