-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: samples and tests for auto-generated createDatabase and createI…
…nstance APIs. (#1065) * docs: samples and tests for auto-generated createDatabase and createInstance APIs. * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix lint * incorporate suggestions * rename tests * fix lint * fix failures * chore(spanner): fix formatting * incorporate suggesitons --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com> Co-authored-by: Sri Harsha CH <[email protected]> Co-authored-by: Sri Harsha CH <[email protected]>
- Loading branch information
1 parent
1ed5a47
commit 16c510e
Showing
2 changed files
with
248 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#!/usr/bin/env python | ||
|
||
# Copyright 2024 Google, Inc. | ||
# | ||
# 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 do basic operations using Cloud | ||
Spanner. | ||
For more information, see the README.rst under /spanner. | ||
""" | ||
|
||
import time | ||
|
||
from google.cloud import spanner | ||
from google.cloud.spanner_admin_instance_v1.types import spanner_instance_admin | ||
from google.cloud.spanner_admin_database_v1.types import spanner_database_admin | ||
|
||
OPERATION_TIMEOUT_SECONDS = 240 | ||
|
||
|
||
# [START spanner_create_instance] | ||
def create_instance(instance_id): | ||
"""Creates an instance.""" | ||
spanner_client = spanner.Client() | ||
|
||
config_name = "{}/instanceConfigs/regional-us-central1".format( | ||
spanner_client.project_name | ||
) | ||
|
||
operation = spanner_client.instance_admin_api.create_instance( | ||
parent="projects/{}".format(spanner_client.project), | ||
instance_id=instance_id, | ||
instance=spanner_instance_admin.Instance( | ||
config=config_name, | ||
display_name="This is a display name.", | ||
node_count=1, | ||
labels={ | ||
"cloud_spanner_samples": "true", | ||
"sample_name": "snippets-create_instance-explicit", | ||
"created": str(int(time.time())), | ||
}, | ||
), | ||
) | ||
|
||
print("Waiting for operation to complete...") | ||
operation.result(OPERATION_TIMEOUT_SECONDS) | ||
|
||
print("Created instance {}".format(instance_id)) | ||
|
||
|
||
# [END spanner_create_instance] | ||
|
||
|
||
# [START spanner_create_database_with_default_leader] | ||
def create_database_with_default_leader(instance_id, database_id, default_leader): | ||
"""Creates a database with tables with a default leader.""" | ||
spanner_client = spanner.Client() | ||
operation = spanner_client.database_admin_api.create_database( | ||
request=spanner_database_admin.CreateDatabaseRequest( | ||
parent="projects/{}/instances/{}".format( | ||
spanner_client.project, instance_id | ||
), | ||
create_statement="CREATE DATABASE {}".format(database_id), | ||
extra_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 (default_leader = '{}')".format( | ||
database_id, default_leader | ||
), | ||
], | ||
) | ||
) | ||
|
||
print("Waiting for operation to complete...") | ||
database = operation.result(OPERATION_TIMEOUT_SECONDS) | ||
|
||
print( | ||
"Database {} created with default leader {}".format( | ||
database.name, database.default_leader | ||
) | ||
) | ||
|
||
|
||
# [END spanner_create_database_with_default_leader] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
#!/usr/bin/env python | ||
|
||
# Copyright 2024 Google, Inc. | ||
# | ||
# 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 do basic operations using Cloud | ||
Spanner. | ||
For more information, see the README.rst under /spanner. | ||
""" | ||
|
||
import uuid | ||
|
||
from google.api_core import exceptions | ||
from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect | ||
import pytest | ||
from test_utils.retry import RetryErrors | ||
|
||
import samples | ||
|
||
CREATE_TABLE_SINGERS = """\ | ||
CREATE TABLE Singers ( | ||
SingerId INT64 NOT NULL, | ||
FirstName STRING(1024), | ||
LastName STRING(1024), | ||
SingerInfo BYTES(MAX), | ||
FullName STRING(2048) AS ( | ||
ARRAY_TO_STRING([FirstName, LastName], " ") | ||
) STORED | ||
) PRIMARY KEY (SingerId) | ||
""" | ||
|
||
CREATE_TABLE_ALBUMS = """\ | ||
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 | ||
""" | ||
|
||
retry_429 = RetryErrors(exceptions.ResourceExhausted, delay=15) | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def sample_name(): | ||
return "snippets" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def database_dialect(): | ||
"""Spanner dialect to be used for this sample. | ||
The dialect is used to initialize the dialect for the database. | ||
It can either be GoogleStandardSql or PostgreSql. | ||
""" | ||
return DatabaseDialect.GOOGLE_STANDARD_SQL | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def create_instance_id(): | ||
"""Id for the low-cost instance.""" | ||
return f"create-instance-{uuid.uuid4().hex[:10]}" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def lci_instance_id(): | ||
"""Id for the low-cost instance.""" | ||
return f"lci-instance-{uuid.uuid4().hex[:10]}" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def database_id(): | ||
return f"test-db-{uuid.uuid4().hex[:10]}" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def create_database_id(): | ||
return f"create-db-{uuid.uuid4().hex[:10]}" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def cmek_database_id(): | ||
return f"cmek-db-{uuid.uuid4().hex[:10]}" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def default_leader_database_id(): | ||
return f"leader_db_{uuid.uuid4().hex[:10]}" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def database_ddl(): | ||
"""Sequence of DDL statements used to set up the database. | ||
Sample testcase modules can override as needed. | ||
""" | ||
return [CREATE_TABLE_SINGERS, CREATE_TABLE_ALBUMS] | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def default_leader(): | ||
"""Default leader for multi-region instances.""" | ||
return "us-east4" | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def base_instance_config_id(spanner_client): | ||
return "{}/instanceConfigs/{}".format(spanner_client.project_name, "nam7") | ||
|
||
|
||
def test_create_instance_explicit(spanner_client, create_instance_id): | ||
# Rather than re-use 'sample_isntance', we create a new instance, to | ||
# ensure that the 'create_instance' snippet is tested. | ||
retry_429(samples.create_instance)(create_instance_id) | ||
instance = spanner_client.instance(create_instance_id) | ||
retry_429(instance.delete)() | ||
|
||
|
||
def test_create_database_with_default_leader( | ||
capsys, | ||
multi_region_instance, | ||
multi_region_instance_id, | ||
default_leader_database_id, | ||
default_leader, | ||
): | ||
retry_429 = RetryErrors(exceptions.ResourceExhausted, delay=15) | ||
retry_429(samples.create_database_with_default_leader)( | ||
multi_region_instance_id, default_leader_database_id, default_leader | ||
) | ||
out, _ = capsys.readouterr() | ||
assert default_leader_database_id in out | ||
assert default_leader in out |