Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add samples from spanner/cloud-client #117

Merged
merged 76 commits into from Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
4e8f7c5
Add spanner samples [(#804)](https://github.com/GoogleCloudPlatform/p…
Feb 14, 2017
7b81a23
Update snippets.py [(#815)](https://github.com/GoogleCloudPlatform/py…
jasonmorton Feb 22, 2017
e3e62a6
Changed read_write minimum amount to 300,000 as per bug [(#818)](http…
ryanmats Feb 22, 2017
9df9890
Remove cloud config fixture [(#887)](https://github.com/GoogleCloudPl…
Apr 4, 2017
1ded769
Fix reference to our testing tools
Apr 12, 2017
5346f6b
Auto-update dependencies. [(#914)](https://github.com/GoogleCloudPlat…
dpebot Apr 24, 2017
dc391f9
Re-generate all readmes
Apr 27, 2017
7391845
Auto-update dependencies. [(#922)](https://github.com/GoogleCloudPlat…
dpebot May 1, 2017
3337ecb
Update spanner sample to use bind parameters [(#928)](https://github.…
May 3, 2017
fb68a54
Fix default arguments
May 5, 2017
2b46e90
Fix README rst links [(#962)](https://github.com/GoogleCloudPlatform/…
waprin May 24, 2017
7db79ec
Auto-update dependencies. [(#992)](https://github.com/GoogleCloudPlat…
dpebot Jun 17, 2017
8a35c27
Auto-update dependencies. [(#1004)](https://github.com/GoogleCloudPla…
dpebot Jun 27, 2017
278b6ce
Swap the album titles to be consistent with other samples [(#1035)](h…
Jul 27, 2017
ba6d34f
Auto-update dependencies. [(#1055)](https://github.com/GoogleCloudPla…
dpebot Aug 7, 2017
59a4e04
Pass multi_use=True to spanner read-only transaction [(#1063)](https:…
Aug 8, 2017
4e22fb1
fix typo
Aug 8, 2017
a8ce453
Auto-update dependencies. [(#1093)](https://github.com/GoogleCloudPla…
dpebot Aug 29, 2017
211387d
Add spanner stale data sample [(#1107)](https://github.com/GoogleClou…
Sep 12, 2017
8147700
Update all generated readme auth instructions [(#1121)](https://githu…
Sep 18, 2017
80ca3db
Added Link to Python Setup Guide [(#1158)](https://github.com/GoogleC…
Oct 12, 2017
dc8a99c
Auto-update dependencies. [(#1138)](https://github.com/GoogleCloudPla…
dpebot Oct 23, 2017
52e04c6
Auto-update dependencies. [(#1186)](https://github.com/GoogleCloudPla…
dpebot Nov 1, 2017
dae800f
Fixed failed tests on Kokoro (Spanner + Translate) [(#1192)](https://…
Nov 3, 2017
0af87b2
Bump spanner stale read from 10 to 15 seconds. [(#1207)](https://gith…
SurferJeffAtGoogle Nov 9, 2017
52d825c
Added "Open in Cloud Shell" buttons to README files [(#1254)](https:/…
Dec 7, 2017
16a87a6
Auto-update dependencies. [(#1316)](https://github.com/GoogleCloudPla…
dpebot Jan 12, 2018
2e1ee6c
Auto-update dependencies. [(#1354)](https://github.com/GoogleCloudPla…
dpebot Feb 8, 2018
9640e96
Add Spanner region tags. [(#1376)](https://github.com/GoogleCloudPlat…
jmdobry Mar 1, 2018
9381802
Auto-update dependencies. [(#1377)](https://github.com/GoogleCloudPla…
dpebot Mar 5, 2018
9c217e3
Spanner Batch Query Sample [(#1402)](https://github.com/GoogleCloudPl…
kurtisvg Mar 15, 2018
7aba51c
Auto-update dependencies. [(#1406)](https://github.com/GoogleCloudPla…
dpebot Mar 16, 2018
a662787
Spanner Commit Timestamp Sample [(#1425)](https://github.com/GoogleCl…
kurtisvg Mar 27, 2018
cea767f
Regenerate the README files and fix the Open in Cloud Shell link for …
Apr 7, 2018
57d526e
Update READMEs to fix numbering and add git clone [(#1464)](https://g…
frankyn Apr 26, 2018
813f0a8
Adding Spanner STRUCT param samples [(#1519)](https://github.com/Goog…
jabubake Jun 13, 2018
07777ce
Fix python Cloud Spanner tests. [(#1548)](https://github.com/GoogleCl…
jsimonweb Jun 29, 2018
9924d57
Cleanup spanner tests. [(#1633)](https://github.com/GoogleCloudPlatfo…
kurtisvg Aug 21, 2018
0850798
Added Spanner DML/PDML samples. [(#1742)](https://github.com/GoogleC…
kurtisvg Oct 10, 2018
8b239e8
Update method name to match action. [(#1836)](https://github.com/Goo…
jsimonweb Nov 13, 2018
f083646
Auto-update dependencies. [(#1846)](https://github.com/GoogleCloudPla…
dpebot Nov 20, 2018
4224746
Add sample to delete data. [(#1872)](https://github.com/GoogleCloudPl…
RobinRH Dec 7, 2018
9d6fd8d
Auto-update dependencies. [(#1980)](https://github.com/GoogleCloudPla…
dpebot Feb 6, 2019
61136e4
Add Cloud Spanner Batch DML sample [(#2068)](https://github.com/Googl…
jsimonweb Mar 25, 2019
99bf094
Add queryWithParameter to Cloud Spanner sample. [(#2153)](https://git…
jsimonweb May 15, 2019
f8a828b
Deflake bigtable and spanner tests. [(#2224)](https://github.com/Goog…
theacodes Jun 14, 2019
7519b11
Improve and fix Cloud Spanner samples that transfer marketing budget …
hegemonic Jun 19, 2019
cd34847
Add Datatypes examples to Spanner sample. [(#2251)](https://github.co…
jsimonweb Jul 10, 2019
02fc4e6
Add bulk loading Python Sample [(#2295)](https://github.com/GoogleClo…
tonioshikanlu Aug 6, 2019
a2f1898
Fix Spanner `BOOL` example after upstream typo fix [(#2356)](https://…
wchargin Sep 5, 2019
3f0639c
Updates to spanner version with BOOL correctly spelled. [(#2392)](htt…
gguuss Sep 13, 2019
3560942
Adds updates for samples profiler ... vision [(#2439)](https://github…
gguuss Oct 7, 2019
9feca9a
update filenames to match the CSV files [(#2535)](https://github.com/…
mmmarklu Nov 16, 2019
83cdcda
Auto-update dependencies. [(#2005)](https://github.com/GoogleCloudPla…
dpebot Dec 21, 2019
2027631
Delete spanner/cloud-client/bulk_load_csv. [(#2721)](https://github.c…
lgruen Jan 17, 2020
15cff78
spanner: add query options versioning samples [(#3093)](https://githu…
larkee Mar 17, 2020
ef4c0e2
spanner: Add Cloud Spanner Backup samples [(#3101)](https://github.co…
larkee Mar 30, 2020
1d7fa0c
Simplify noxfile setup. [(#2806)](https://github.com/GoogleCloudPlatf…
kurtisvg Apr 2, 2020
44e81e8
Update dependency google-cloud-spanner to v1.15.1 [(#3377)](https://g…
renovate-bot Apr 13, 2020
ee0dca1
[spanner] fix: bump the timeout for instance creation [(#3468)](https…
Apr 23, 2020
2ecd360
[spanner] fix: set timeout for polling on operations [(#3488)](https:…
Apr 25, 2020
9dd04cf
fix: use DELETE FROM for consistency [(#3498)](https://github.com/Goo…
skuruppu Apr 28, 2020
bf24403
chore: pin new release [(#3688)](https://github.com/GoogleCloudPlatfo…
larkee May 5, 2020
006401d
chore: some lint fixes [(#3749)](https://github.com/GoogleCloudPlatfo…
May 13, 2020
2bec1d2
chore(deps): update dependency google-cloud-spanner to v1.17.0 [(#388…
renovate-bot May 27, 2020
a62c454
Improve Spanner delete_data sample coverage [(#3922)](https://github.…
larkee Jun 3, 2020
8cb43c0
chore(deps): update dependency google-cloud-spanner to v1.17.1 [(#416…
renovate-bot Jun 25, 2020
a54e210
fix(spanner): use uuid for unique id [(#4198)](https://github.com/Goo…
Jun 29, 2020
1e6670e
feat(spanner): add sample for create instance [(#4230)](https://githu…
larkee Jul 6, 2020
32ac0b0
chore(deps): update dependency pytest to v5.4.3 [(#4279)](https://git…
renovate-bot Jul 12, 2020
aebfbad
chore(deps): update dependency mock to v4 [(#4287)](https://github.co…
renovate-bot Jul 13, 2020
a29be24
test(spanner): add sleep to fix flaky test [(#4289)](https://github.c…
larkee Jul 13, 2020
3e54af6
Merge branch 'samples-samples' into add-samples-samples
zx-zx Jul 23, 2020
10d06cc
chore: update templates
larkee Jul 24, 2020
3585a1f
fix lint
larkee Jul 27, 2020
2d092e0
Merge branch 'master' into add-samples-samples
larkee Jul 29, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
@@ -0,0 +1,11 @@
# Code owners file.
# This file controls who is tagged for review for any given pull request.
#
# For syntax help see:
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax


# The api-spanner-python team is the default owner for anything not
# explicitly taken by someone else.
* @googleapis/api-spanner-python
/samples/ @googleapis/api-spanner-python @googleapis/python-samples-owners
4 changes: 2 additions & 2 deletions docs/_templates/layout.html
Expand Up @@ -21,8 +21,8 @@

<div class="body" role="main">
<div class="admonition" id="python2-eol">
On January 1, 2020 this library will no longer support Python 2 on the latest released version.
Previously released library versions will continue to be available. For more information please
As of January 1, 2020 this library no longer supports Python 2 on the latest released version.
Library versions released prior to that date will continue to be available. For more information please
visit <a href="https://cloud.google.com/python/docs/python2-sunset/">Python 2 support on Google Cloud</a>.
</div>
{% block body %} {% endblock %}
Expand Down
1 change: 1 addition & 0 deletions samples/AUTHORING_GUIDE.md
@@ -0,0 +1 @@
See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/AUTHORING_GUIDE.md
1 change: 1 addition & 0 deletions samples/CONTRIBUTING.md
@@ -0,0 +1 @@
See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md
290 changes: 290 additions & 0 deletions samples/samples/README.rst

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions samples/samples/README.rst.in
@@ -0,0 +1,24 @@
# This file is used to generate README.rst

product:
name: Google Cloud Spanner
short_name: Cloud Spanner
url: https://cloud.google.com/spanner/docs
description: >
`Google Cloud Spanner`_ is a highly scalable, transactional, managed,
NewSQL database service. Cloud Spanner solves the need for a
horizontally-scaling database with consistent global transactions and
SQL semantics.

setup:
- auth
- install_deps

samples:
- name: Snippets
file: snippets.py
show_help: true

cloud_client_library: true

folder: spanner/cloud-client
314 changes: 314 additions & 0 deletions samples/samples/backup_sample.py
@@ -0,0 +1,314 @@
# Copyright 2020 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This application demonstrates how to create and restore from backups
using Cloud Spanner.

For more information, see the README.rst under /spanner.
"""

import argparse
from datetime import datetime, timedelta
import time

from google.cloud import spanner


# [START spanner_create_backup]
def create_backup(instance_id, database_id, backup_id):
"""Creates a backup for a database."""
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

# Create a backup
expire_time = datetime.utcnow() + timedelta(days=14)
backup = instance.backup(backup_id, database=database, expire_time=expire_time)
operation = backup.create()

# Wait for backup operation to complete.
operation.result(1200)

# Verify that the backup is ready.
backup.reload()
assert backup.is_ready() is True

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


# [END spanner_create_backup]


# [START spanner_restore_database]
def restore_database(instance_id, new_database_id, backup_id):
"""Restores a database from a backup."""
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
# Create a backup on database_id.

# Start restoring backup to a new database.
backup = instance.backup(backup_id)
new_database = instance.database(new_database_id)
operation = new_database.restore(backup)

# Wait for restore operation to complete.
operation.result(1200)

# Newly created database has restore information.
new_database.reload()
restore_info = new_database.restore_info
print(
"Database {} restored to {} from backup {}.".format(
restore_info.backup_info.source_database,
new_database_id,
restore_info.backup_info.backup,
)
)


# [END spanner_restore_database]


# [START spanner_cancel_backup]
def cancel_backup(instance_id, database_id, backup_id):
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

expire_time = datetime.utcnow() + timedelta(days=30)

# Create a backup.
backup = instance.backup(backup_id, database=database, expire_time=expire_time)
operation = backup.create()

# Cancel backup creation.
operation.cancel()

# Cancel operations are best effort so either it will complete or
# be cancelled.
while not operation.done():
time.sleep(300) # 5 mins

# Deal with resource if the operation succeeded.
if backup.exists():
print("Backup was created before the cancel completed.")
backup.delete()
print("Backup deleted.")
else:
print("Backup creation was successfully cancelled.")


# [END spanner_cancel_backup]


# [START spanner_list_backup_operations]
def list_backup_operations(instance_id, database_id):
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)

# List the CreateBackup operations.
filter_ = (
"(metadata.database:{}) AND "
"(metadata.@type:type.googleapis.com/"
"google.spanner.admin.database.v1.CreateBackupMetadata)"
).format(database_id)
operations = instance.list_backup_operations(filter_=filter_)
for op in operations:
metadata = op.metadata
print(
"Backup {} on database {}: {}% complete.".format(
metadata.name, metadata.database, metadata.progress.progress_percent
)
)


# [END spanner_list_backup_operations]


# [START spanner_list_database_operations]
def list_database_operations(instance_id):
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)

# List the progress of restore.
filter_ = (
"(metadata.@type:type.googleapis.com/"
"google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)"
)
operations = instance.list_database_operations(filter_=filter_)
for op in operations:
print(
"Database {} restored from backup is {}% optimized.".format(
op.metadata.name, op.metadata.progress.progress_percent
)
)


# [END spanner_list_database_operations]


# [START spanner_list_backups]
def list_backups(instance_id, database_id, backup_id):
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)

# List all backups.
print("All backups:")
for backup in instance.list_backups():
print(backup.name)

# List all backups that contain a name.
print('All backups with backup name containing "{}":'.format(backup_id))
for backup in instance.list_backups(filter_="name:{}".format(backup_id)):
print(backup.name)

# List all backups for a database that contains a name.
print('All backups with database name containing "{}":'.format(database_id))
for backup in instance.list_backups(filter_="database:{}".format(database_id)):
print(backup.name)

# List all backups that expire before a timestamp.
expire_time = datetime.utcnow().replace(microsecond=0) + timedelta(days=30)
print(
'All backups with expire_time before "{}-{}-{}T{}:{}:{}Z":'.format(
*expire_time.timetuple()
)
)
for backup in instance.list_backups(
filter_='expire_time < "{}-{}-{}T{}:{}:{}Z"'.format(*expire_time.timetuple())
):
print(backup.name)

# List all backups with a size greater than some bytes.
print("All backups with backup size more than 100 bytes:")
for backup in instance.list_backups(filter_="size_bytes > 100"):
print(backup.name)

# List backups that were created after a timestamp that are also ready.
create_time = datetime.utcnow().replace(microsecond=0) - timedelta(days=1)
print(
'All backups created after "{}-{}-{}T{}:{}:{}Z" and are READY:'.format(
*create_time.timetuple()
)
)
for backup in instance.list_backups(
filter_='create_time >= "{}-{}-{}T{}:{}:{}Z" AND state:READY'.format(
*create_time.timetuple()
)
):
print(backup.name)

print("All backups with pagination")
for page in instance.list_backups(page_size=2).pages:
for backup in page:
print(backup.name)


# [END spanner_list_backups]


# [START spanner_delete_backup]
def delete_backup(instance_id, backup_id):
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
backup = instance.backup(backup_id)
backup.reload()

# Wait for databases that reference this backup to finish optimizing.
while backup.referencing_databases:
time.sleep(30)
backup.reload()

# Delete the backup.
backup.delete()

# Verify that the backup is deleted.
assert backup.exists() is False
print("Backup {} has been deleted.".format(backup.name))


# [END spanner_delete_backup]


# [START spanner_update_backup]
def update_backup(instance_id, backup_id):
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
backup = instance.backup(backup_id)
backup.reload()

# Expire time must be within 366 days of the create time of the backup.
old_expire_time = backup.expire_time
new_expire_time = old_expire_time + timedelta(days=30)
backup.update_expire_time(new_expire_time)
print(
"Backup {} expire time was updated from {} to {}.".format(
backup.name, old_expire_time, new_expire_time
)
)


# [END spanner_update_backup]


if __name__ == "__main__": # noqa: C901
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("instance_id", help="Your Cloud Spanner instance ID.")
parser.add_argument(
"--database-id", help="Your Cloud Spanner database ID.", default="example_db"
)
parser.add_argument(
"--backup-id", help="Your Cloud Spanner backup ID.", default="example_backup"
)

subparsers = parser.add_subparsers(dest="command")
subparsers.add_parser("create_backup", help=create_backup.__doc__)
subparsers.add_parser("cancel_backup", help=cancel_backup.__doc__)
subparsers.add_parser("update_backup", help=update_backup.__doc__)
subparsers.add_parser("restore_database", help=restore_database.__doc__)
subparsers.add_parser("list_backups", help=list_backups.__doc__)
subparsers.add_parser("list_backup_operations", help=list_backup_operations.__doc__)
subparsers.add_parser(
"list_database_operations", help=list_database_operations.__doc__
)
subparsers.add_parser("delete_backup", help=delete_backup.__doc__)

args = parser.parse_args()

if args.command == "create_backup":
create_backup(args.instance_id, args.database_id, args.backup_id)
elif args.command == "cancel_backup":
cancel_backup(args.instance_id, args.database_id, args.backup_id)
elif args.command == "update_backup":
update_backup(args.instance_id, args.backup_id)
elif args.command == "restore_database":
restore_database(args.instance_id, args.database_id, args.backup_id)
elif args.command == "list_backups":
list_backups(args.instance_id, args.database_id, args.backup_id)
elif args.command == "list_backup_operations":
list_backup_operations(args.instance_id, args.database_id)
elif args.command == "list_database_operations":
list_database_operations(args.instance_id)
elif args.command == "delete_backup":
delete_backup(args.instance_id, args.backup_id)
else:
print("Command {} did not match expected commands.".format(args.command))