From da146b7a5d1d2ab6795c53301656d39e5594962f Mon Sep 17 00:00:00 2001 From: Zoe Date: Thu, 25 Feb 2021 12:42:06 +1100 Subject: [PATCH] feat: add samples for PITR (#222) This PR modifies existing samples and adds a sample to show how to use the PITR feature. --- samples/samples/backup_sample.py | 51 ++++++++++++++++++++++++--- samples/samples/backup_sample_test.py | 18 ++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/samples/samples/backup_sample.py b/samples/samples/backup_sample.py index 5e2f51679b..ace4b16829 100644 --- a/samples/samples/backup_sample.py +++ b/samples/samples/backup_sample.py @@ -34,7 +34,8 @@ def create_backup(instance_id, database_id, backup_id): # Create a backup expire_time = datetime.utcnow() + timedelta(days=14) - backup = instance.backup(backup_id, database=database, expire_time=expire_time) + version_time = database.earliest_version_time + backup = instance.backup(backup_id, database=database, expire_time=expire_time, version_time=version_time) operation = backup.create() # Wait for backup operation to complete. @@ -47,8 +48,8 @@ def create_backup(instance_id, database_id, backup_id): # Get the name, create time and backup size. backup.reload() print( - "Backup {} of size {} bytes was created at {}".format( - backup.name, backup.size_bytes, backup.create_time + "Backup {} of size {} bytes was created at {} for version of database at {}".format( + backup.name, backup.size_bytes, backup.create_time, backup.version_time ) ) @@ -63,7 +64,7 @@ def restore_database(instance_id, new_database_id, backup_id): instance = spanner_client.instance(instance_id) # Create a backup on database_id. - # Start restoring backup to a new database. + # Start restoring an existing backup to a new database. backup = instance.backup(backup_id) new_database = instance.database(new_database_id) operation = new_database.restore(backup) @@ -75,10 +76,11 @@ def restore_database(instance_id, new_database_id, backup_id): new_database.reload() restore_info = new_database.restore_info print( - "Database {} restored to {} from backup {}.".format( + "Database {} restored to {} from backup {} with version time {}.".format( restore_info.backup_info.source_database, new_database_id, restore_info.backup_info.backup, + restore_info.backup_info.version_time ) ) @@ -269,6 +271,45 @@ def update_backup(instance_id, backup_id): # [END spanner_update_backup] +# [START spanner_create_database_with_version_retention_period] +def create_database_with_version_retention_period(instance_id, database_id, retention_period): + """Creates a database with a version retention period.""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + ddl_statements = [ + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "CREATE TABLE Albums (" + + " SingerId INT64 NOT NULL," + + " AlbumId INT64 NOT NULL," + + " AlbumTitle STRING(MAX)" + + ") PRIMARY KEY (SingerId, AlbumId)," + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE", + "ALTER DATABASE `{}`" + " SET OPTIONS (version_retention_period = '{}')".format( + database_id, retention_period + ) + ] + db = instance.database(database_id, ddl_statements) + operation = db.create() + + operation.result(30) + + db.reload() + + print("Database {} created with version retention period {} and earliest version time {}".format( + db.database_id, db.version_retention_period, db.earliest_version_time + )) + + db.drop() + +# [END spanner_create_database_with_version_retention_period] + + if __name__ == "__main__": # noqa: C901 parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter diff --git a/samples/samples/backup_sample_test.py b/samples/samples/backup_sample_test.py index 8d73c8acf1..3a911b320c 100644 --- a/samples/samples/backup_sample_test.py +++ b/samples/samples/backup_sample_test.py @@ -38,8 +38,10 @@ def unique_backup_id(): INSTANCE_ID = unique_instance_id() DATABASE_ID = unique_database_id() +RETENTION_DATABASE_ID = unique_database_id() RESTORE_DB_ID = unique_database_id() BACKUP_ID = unique_backup_id() +RETENTION_PERIOD = "7d" @pytest.fixture(scope="module") @@ -70,6 +72,7 @@ def test_create_backup(capsys, database): assert BACKUP_ID in out +# Depends on test_create_backup having run first @RetryErrors(exception=DeadlineExceeded, max_tries=2) def test_restore_database(capsys): backup_sample.restore_database(INSTANCE_ID, RESTORE_DB_ID, BACKUP_ID) @@ -79,6 +82,7 @@ def test_restore_database(capsys): assert BACKUP_ID in out +# Depends on test_create_backup having run first def test_list_backup_operations(capsys, spanner_instance): backup_sample.list_backup_operations(INSTANCE_ID, DATABASE_ID) out, _ = capsys.readouterr() @@ -86,6 +90,7 @@ def test_list_backup_operations(capsys, spanner_instance): assert DATABASE_ID in out +# Depends on test_create_backup having run first def test_list_backups(capsys, spanner_instance): backup_sample.list_backups(INSTANCE_ID, DATABASE_ID, BACKUP_ID) out, _ = capsys.readouterr() @@ -93,18 +98,21 @@ def test_list_backups(capsys, spanner_instance): assert id_count == 7 +# Depends on test_create_backup having run first def test_update_backup(capsys): backup_sample.update_backup(INSTANCE_ID, BACKUP_ID) out, _ = capsys.readouterr() assert BACKUP_ID in out +# Depends on test_create_backup having run first def test_delete_backup(capsys, spanner_instance): backup_sample.delete_backup(INSTANCE_ID, BACKUP_ID) out, _ = capsys.readouterr() assert BACKUP_ID in out +# Depends on test_create_backup having run first def test_cancel_backup(capsys): backup_sample.cancel_backup(INSTANCE_ID, DATABASE_ID, BACKUP_ID) out, _ = capsys.readouterr() @@ -113,3 +121,13 @@ def test_cancel_backup(capsys): "Backup deleted." in out ) assert cancel_success or cancel_failure + + +@RetryErrors(exception=DeadlineExceeded, max_tries=2) +def test_create_database_with_retention_period(capsys, spanner_instance): + backup_sample.create_database_with_version_retention_period(INSTANCE_ID, RETENTION_DATABASE_ID, RETENTION_PERIOD) + out, _ = capsys.readouterr() + assert (RETENTION_DATABASE_ID + " created with ") in out + assert ("retention period " + RETENTION_PERIOD) in out + database = spanner_instance.database(RETENTION_DATABASE_ID) + database.drop()