Skip to content

Commit f42f31c

Browse files
nickchoatebchew
authored andcommitted
Allow dynamodump to be imported as a module (#30)
* Refactored main code into a main method to allow importing of dynamo dump script into other python scripts. * Fixed spacing error as reported by flake. * Removed extra whitespace.
1 parent d95d48b commit f42f31c

File tree

2 files changed

+167
-159
lines changed

2 files changed

+167
-159
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ nosetests.xml
3636
.pydevproject
3737

3838
dump
39+
dynamodump.iml

dynamodump.py

Lines changed: 166 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -442,165 +442,172 @@ def do_restore(conn, sleep_interval, source_table, destination_table, write_capa
442442
logging.info("Empty schema of " + source_table + " table created. Time taken: " + str(datetime.datetime.now().replace(microsecond=0) - start_time))
443443

444444

445-
# parse args
446-
parser = argparse.ArgumentParser(description="Simple DynamoDB backup/restore/empty.")
447-
parser.add_argument("-m", "--mode", help="'backup' or 'restore' or 'empty'")
448-
parser.add_argument("-r", "--region",
449-
help="AWS region to use, e.g. 'us-west-1'. Use '" + LOCAL_REGION + "' for local DynamoDB testing")
450-
parser.add_argument("--host", help="Host of local DynamoDB [required only for local]")
451-
parser.add_argument("--port", help="Port of local DynamoDB [required only for local]")
452-
parser.add_argument("--accessKey", help="Access key of local DynamoDB [required only for local]")
453-
parser.add_argument("--secretKey", help="Secret key of local DynamoDB [required only for local]")
454-
parser.add_argument("-p", "--profile",
455-
help="AWS credentials file profile to use. Allows you to use a profile instead of accessKey, secretKey authentication")
456-
parser.add_argument("-s", "--srcTable",
457-
help="Source DynamoDB table name to backup or restore from, use 'tablename*' for wildcard prefix selection or '*' for all tables")
458-
parser.add_argument("-d", "--destTable",
459-
help="Destination DynamoDB table name to backup or restore to, use 'tablename*' for wildcard prefix selection (defaults to use '-' separator) [optional, defaults to source]")
460-
parser.add_argument("--prefixSeparator", help="Specify a different prefix separator, e.g. '.' [optional]")
461-
parser.add_argument("--noSeparator", action='store_true',
462-
help="Overrides the use of a prefix separator for backup wildcard searches [optional]")
463-
parser.add_argument("--readCapacity",
464-
help="Change the temp read capacity of the DynamoDB table to backup from [optional]")
465-
parser.add_argument("--writeCapacity",
466-
help="Change the temp write capacity of the DynamoDB table to restore to [defaults to " + str(
467-
RESTORE_WRITE_CAPACITY) + ", optional]")
468-
parser.add_argument("--schemaOnly", action="store_true", default=False,
469-
help="Backup or restore the schema only. Do not backup/restore data. Can be used with both backup and restore modes. Cannot be used with the --dataOnly [optional]")
470-
parser.add_argument("--dataOnly", action="store_true", default=False,
471-
help="Restore data only. Do not delete/recreate schema [optional for restore]")
472-
parser.add_argument("--skipThroughputUpdate", action="store_true", default=False,
473-
help="Skip updating throughput values across tables [optional]")
474-
parser.add_argument("--dumpPath", help="Directory to place and search for DynamoDB table backups (defaults to use '" + str(DATA_DUMP) + "') [optional]", default=str(DATA_DUMP))
475-
parser.add_argument("--log", help="Logging level - DEBUG|INFO|WARNING|ERROR|CRITICAL [optional]")
476-
args = parser.parse_args()
477-
478-
# set log level
479-
log_level = LOG_LEVEL
480-
if args.log is not None:
481-
log_level = args.log.upper()
482-
logging.basicConfig(level=getattr(logging, log_level))
483-
484-
485-
# Check to make sure that --dataOnly and --schemaOnly weren't simultaneously specified
486-
if args.schemaOnly and args.dataOnly:
487-
logging.info("Options --schemaOnly and --dataOnly are mutually exclusive.")
488-
sys.exit(1)
489-
490-
491-
# instantiate connection
492-
if args.region == LOCAL_REGION:
493-
conn = DynamoDBConnection(aws_access_key_id=args.accessKey, aws_secret_access_key=args.secretKey, host=args.host,
494-
port=int(args.port), is_secure=False)
495-
sleep_interval = LOCAL_SLEEP_INTERVAL
496-
else:
497-
if not args.profile:
498-
conn = boto.dynamodb2.connect_to_region(args.region, aws_access_key_id=args.accessKey,
499-
aws_secret_access_key=args.secretKey)
500-
sleep_interval = AWS_SLEEP_INTERVAL
445+
def main():
446+
global args, sleep_interval, start_time
447+
# parse args
448+
parser = argparse.ArgumentParser(description="Simple DynamoDB backup/restore/empty.")
449+
parser.add_argument("-m", "--mode", help="'backup' or 'restore' or 'empty'")
450+
parser.add_argument("-r", "--region",
451+
help="AWS region to use, e.g. 'us-west-1'. Use '" + LOCAL_REGION + "' for local DynamoDB testing")
452+
parser.add_argument("--host", help="Host of local DynamoDB [required only for local]")
453+
parser.add_argument("--port", help="Port of local DynamoDB [required only for local]")
454+
parser.add_argument("--accessKey", help="Access key of local DynamoDB [required only for local]")
455+
parser.add_argument("--secretKey", help="Secret key of local DynamoDB [required only for local]")
456+
parser.add_argument("-p", "--profile",
457+
help="AWS credentials file profile to use. Allows you to use a profile instead of accessKey, secretKey authentication")
458+
parser.add_argument("-s", "--srcTable",
459+
help="Source DynamoDB table name to backup or restore from, use 'tablename*' for wildcard prefix selection or '*' for all tables")
460+
parser.add_argument("-d", "--destTable",
461+
help="Destination DynamoDB table name to backup or restore to, use 'tablename*' for wildcard prefix selection (defaults to use '-' separator) [optional, defaults to source]")
462+
parser.add_argument("--prefixSeparator", help="Specify a different prefix separator, e.g. '.' [optional]")
463+
parser.add_argument("--noSeparator", action='store_true',
464+
help="Overrides the use of a prefix separator for backup wildcard searches [optional]")
465+
parser.add_argument("--readCapacity",
466+
help="Change the temp read capacity of the DynamoDB table to backup from [optional]")
467+
parser.add_argument("--writeCapacity",
468+
help="Change the temp write capacity of the DynamoDB table to restore to [defaults to " + str(
469+
RESTORE_WRITE_CAPACITY) + ", optional]")
470+
parser.add_argument("--schemaOnly", action="store_true", default=False,
471+
help="Backup or restore the schema only. Do not backup/restore data. Can be used with both backup and restore modes. Cannot be used with the --dataOnly [optional]")
472+
parser.add_argument("--dataOnly", action="store_true", default=False,
473+
help="Restore data only. Do not delete/recreate schema [optional for restore]")
474+
parser.add_argument("--skipThroughputUpdate", action="store_true", default=False,
475+
help="Skip updating throughput values across tables [optional]")
476+
parser.add_argument("--dumpPath",
477+
help="Directory to place and search for DynamoDB table backups (defaults to use '" + str(
478+
DATA_DUMP) + "') [optional]", default=str(DATA_DUMP))
479+
parser.add_argument("--log", help="Logging level - DEBUG|INFO|WARNING|ERROR|CRITICAL [optional]")
480+
args = parser.parse_args()
481+
# set log level
482+
log_level = LOG_LEVEL
483+
if args.log is not None:
484+
log_level = args.log.upper()
485+
logging.basicConfig(level=getattr(logging, log_level))
486+
# Check to make sure that --dataOnly and --schemaOnly weren't simultaneously specified
487+
if args.schemaOnly and args.dataOnly:
488+
logging.info("Options --schemaOnly and --dataOnly are mutually exclusive.")
489+
sys.exit(1)
490+
491+
# instantiate connection
492+
if args.region == LOCAL_REGION:
493+
conn = DynamoDBConnection(aws_access_key_id=args.accessKey, aws_secret_access_key=args.secretKey,
494+
host=args.host,
495+
port=int(args.port), is_secure=False)
496+
sleep_interval = LOCAL_SLEEP_INTERVAL
501497
else:
502-
conn = boto.dynamodb2.connect_to_region(args.region, profile_name=args.profile)
503-
sleep_interval = AWS_SLEEP_INTERVAL
504-
505-
506-
# don't proceed if connection is not established
507-
if not conn:
508-
logging.info('Unable to establish connection with dynamodb')
509-
sys.exit(1)
510-
511-
512-
# set prefix separator
513-
prefix_separator = DEFAULT_PREFIX_SEPARATOR
514-
if args.prefixSeparator is not None:
515-
prefix_separator = args.prefixSeparator
516-
if args.noSeparator is True:
517-
prefix_separator = None
518-
519-
# do backup/restore
520-
start_time = datetime.datetime.now().replace(microsecond=0)
521-
if args.mode == "backup":
522-
if args.srcTable.find("*") != -1:
523-
matching_backup_tables = get_table_name_matches(conn, args.srcTable, prefix_separator)
524-
logging.info("Found " + str(len(matching_backup_tables)) + " table(s) in DynamoDB host to backup: " + ", ".join(
525-
matching_backup_tables))
526-
527-
threads = []
528-
for table_name in matching_backup_tables:
529-
t = threading.Thread(target=do_backup, args=(conn, table_name, args.readCapacity,))
530-
threads.append(t)
531-
t.start()
532-
time.sleep(THREAD_START_DELAY)
533-
534-
for thread in threads:
535-
thread.join()
536-
537-
logging.info("Backup of table(s) " + args.srcTable + " completed!")
538-
else:
539-
do_backup(conn, args.srcTable, args.readCapacity)
540-
elif args.mode == "restore":
541-
if args.destTable is not None:
542-
dest_table = args.destTable
543-
else:
544-
dest_table = args.srcTable
545-
546-
if dest_table.find("*") != -1:
547-
matching_destination_tables = get_table_name_matches(conn, dest_table, prefix_separator)
548-
delete_str = ": " if args.dataOnly else " to be deleted: "
549-
logging.info(
550-
"Found " + str(len(matching_destination_tables)) + " table(s) in DynamoDB host" + delete_str + ", ".join(
551-
matching_destination_tables))
552-
553-
threads = []
554-
for table_name in matching_destination_tables:
555-
t = threading.Thread(target=delete_table, args=(conn, sleep_interval, table_name,))
556-
threads.append(t)
557-
t.start()
558-
time.sleep(THREAD_START_DELAY)
559-
560-
for thread in threads:
561-
thread.join()
562-
563-
matching_restore_tables = get_restore_table_matches(args.srcTable, prefix_separator)
564-
logging.info(
565-
"Found " + str(len(matching_restore_tables)) + " table(s) in " + args.dumpPath + " to restore: " + ", ".join(
566-
matching_restore_tables))
567-
568-
threads = []
569-
for source_table in matching_restore_tables:
570-
if args.srcTable == "*":
571-
t = threading.Thread(target=do_restore,
572-
args=(conn, sleep_interval, source_table, source_table, args.writeCapacity))
573-
else:
574-
t = threading.Thread(target=do_restore, args=(conn, sleep_interval, source_table,
575-
change_prefix(source_table, args.srcTable, dest_table,
576-
prefix_separator), args.writeCapacity,))
577-
threads.append(t)
578-
t.start()
579-
time.sleep(THREAD_START_DELAY)
498+
if not args.profile:
499+
conn = boto.dynamodb2.connect_to_region(args.region, aws_access_key_id=args.accessKey,
500+
aws_secret_access_key=args.secretKey)
501+
sleep_interval = AWS_SLEEP_INTERVAL
502+
else:
503+
conn = boto.dynamodb2.connect_to_region(args.region, profile_name=args.profile)
504+
sleep_interval = AWS_SLEEP_INTERVAL
505+
506+
# don't proceed if connection is not established
507+
if not conn:
508+
logging.info('Unable to establish connection with dynamodb')
509+
sys.exit(1)
510+
511+
# set prefix separator
512+
prefix_separator = DEFAULT_PREFIX_SEPARATOR
513+
if args.prefixSeparator is not None:
514+
prefix_separator = args.prefixSeparator
515+
if args.noSeparator is True:
516+
prefix_separator = None
517+
518+
# do backup/restore
519+
start_time = datetime.datetime.now().replace(microsecond=0)
520+
if args.mode == "backup":
521+
if args.srcTable.find("*") != -1:
522+
matching_backup_tables = get_table_name_matches(conn, args.srcTable, prefix_separator)
523+
logging.info(
524+
"Found " + str(len(matching_backup_tables)) + " table(s) in DynamoDB host to backup: " + ", ".join(
525+
matching_backup_tables))
526+
527+
threads = []
528+
for table_name in matching_backup_tables:
529+
t = threading.Thread(target=do_backup, args=(conn, table_name, args.readCapacity,))
530+
threads.append(t)
531+
t.start()
532+
time.sleep(THREAD_START_DELAY)
533+
534+
for thread in threads:
535+
thread.join()
536+
537+
logging.info("Backup of table(s) " + args.srcTable + " completed!")
538+
else:
539+
do_backup(conn, args.srcTable, args.readCapacity)
540+
elif args.mode == "restore":
541+
if args.destTable is not None:
542+
dest_table = args.destTable
543+
else:
544+
dest_table = args.srcTable
545+
546+
if dest_table.find("*") != -1:
547+
matching_destination_tables = get_table_name_matches(conn, dest_table, prefix_separator)
548+
delete_str = ": " if args.dataOnly else " to be deleted: "
549+
logging.info(
550+
"Found " + str(
551+
len(matching_destination_tables)) + " table(s) in DynamoDB host" + delete_str + ", ".join(
552+
matching_destination_tables))
553+
554+
threads = []
555+
for table_name in matching_destination_tables:
556+
t = threading.Thread(target=delete_table, args=(conn, sleep_interval, table_name,))
557+
threads.append(t)
558+
t.start()
559+
time.sleep(THREAD_START_DELAY)
560+
561+
for thread in threads:
562+
thread.join()
563+
564+
matching_restore_tables = get_restore_table_matches(args.srcTable, prefix_separator)
565+
logging.info(
566+
"Found " + str(
567+
len(matching_restore_tables)) + " table(s) in " + args.dumpPath + " to restore: " + ", ".join(
568+
matching_restore_tables))
569+
570+
threads = []
571+
for source_table in matching_restore_tables:
572+
if args.srcTable == "*":
573+
t = threading.Thread(target=do_restore,
574+
args=(conn, sleep_interval, source_table, source_table, args.writeCapacity))
575+
else:
576+
t = threading.Thread(target=do_restore, args=(conn, sleep_interval, source_table,
577+
change_prefix(source_table, args.srcTable, dest_table,
578+
prefix_separator), args.writeCapacity,))
579+
threads.append(t)
580+
t.start()
581+
time.sleep(THREAD_START_DELAY)
580582

581-
for thread in threads:
582-
thread.join()
583+
for thread in threads:
584+
thread.join()
583585

584-
logging.info("Restore of table(s) " + args.srcTable + " to " + dest_table + " completed!")
585-
else:
586-
delete_table(conn, sleep_interval, dest_table)
587-
do_restore(conn, sleep_interval, args.srcTable, dest_table, args.writeCapacity)
588-
elif args.mode == "empty":
589-
if args.srcTable.find("*") != -1:
590-
matching_backup_tables = get_table_name_matches(conn, args.srcTable, prefix_separator)
591-
logging.info("Found " + str(len(matching_backup_tables)) + " table(s) in DynamoDB host to empty: " + ", ".join(
592-
matching_backup_tables))
593-
594-
threads = []
595-
for table_name in matching_backup_tables:
596-
t = threading.Thread(target=do_empty, args=(conn, table_name))
597-
threads.append(t)
598-
t.start()
599-
time.sleep(THREAD_START_DELAY)
600-
601-
for thread in threads:
602-
thread.join()
603-
604-
logging.info("Empty of table(s) " + args.srcTable + " completed!")
605-
else:
606-
do_empty(conn, args.srcTable)
586+
logging.info("Restore of table(s) " + args.srcTable + " to " + dest_table + " completed!")
587+
else:
588+
delete_table(conn, sleep_interval, dest_table)
589+
do_restore(conn, sleep_interval, args.srcTable, dest_table, args.writeCapacity)
590+
elif args.mode == "empty":
591+
if args.srcTable.find("*") != -1:
592+
matching_backup_tables = get_table_name_matches(conn, args.srcTable, prefix_separator)
593+
logging.info(
594+
"Found " + str(len(matching_backup_tables)) + " table(s) in DynamoDB host to empty: " + ", ".join(
595+
matching_backup_tables))
596+
597+
threads = []
598+
for table_name in matching_backup_tables:
599+
t = threading.Thread(target=do_empty, args=(conn, table_name))
600+
threads.append(t)
601+
t.start()
602+
time.sleep(THREAD_START_DELAY)
603+
604+
for thread in threads:
605+
thread.join()
606+
607+
logging.info("Empty of table(s) " + args.srcTable + " completed!")
608+
else:
609+
do_empty(conn, args.srcTable)
610+
611+
612+
if __name__ == "__main__":
613+
main()

0 commit comments

Comments
 (0)