Skip to content

Commit 16c510e

Browse files
rahul2393gcf-owl-bot[bot]harshachinta
authored
docs: samples and tests for auto-generated createDatabase and createInstance 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]>
1 parent 1ed5a47 commit 16c510e

File tree

2 files changed

+248
-0
lines changed

2 files changed

+248
-0
lines changed

samples/samples/admin/samples.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2024 Google, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""This application demonstrates how to do basic operations using Cloud
18+
Spanner.
19+
For more information, see the README.rst under /spanner.
20+
"""
21+
22+
import time
23+
24+
from google.cloud import spanner
25+
from google.cloud.spanner_admin_instance_v1.types import spanner_instance_admin
26+
from google.cloud.spanner_admin_database_v1.types import spanner_database_admin
27+
28+
OPERATION_TIMEOUT_SECONDS = 240
29+
30+
31+
# [START spanner_create_instance]
32+
def create_instance(instance_id):
33+
"""Creates an instance."""
34+
spanner_client = spanner.Client()
35+
36+
config_name = "{}/instanceConfigs/regional-us-central1".format(
37+
spanner_client.project_name
38+
)
39+
40+
operation = spanner_client.instance_admin_api.create_instance(
41+
parent="projects/{}".format(spanner_client.project),
42+
instance_id=instance_id,
43+
instance=spanner_instance_admin.Instance(
44+
config=config_name,
45+
display_name="This is a display name.",
46+
node_count=1,
47+
labels={
48+
"cloud_spanner_samples": "true",
49+
"sample_name": "snippets-create_instance-explicit",
50+
"created": str(int(time.time())),
51+
},
52+
),
53+
)
54+
55+
print("Waiting for operation to complete...")
56+
operation.result(OPERATION_TIMEOUT_SECONDS)
57+
58+
print("Created instance {}".format(instance_id))
59+
60+
61+
# [END spanner_create_instance]
62+
63+
64+
# [START spanner_create_database_with_default_leader]
65+
def create_database_with_default_leader(instance_id, database_id, default_leader):
66+
"""Creates a database with tables with a default leader."""
67+
spanner_client = spanner.Client()
68+
operation = spanner_client.database_admin_api.create_database(
69+
request=spanner_database_admin.CreateDatabaseRequest(
70+
parent="projects/{}/instances/{}".format(
71+
spanner_client.project, instance_id
72+
),
73+
create_statement="CREATE DATABASE {}".format(database_id),
74+
extra_statements=[
75+
"""CREATE TABLE Singers (
76+
SingerId INT64 NOT NULL,
77+
FirstName STRING(1024),
78+
LastName STRING(1024),
79+
SingerInfo BYTES(MAX)
80+
) PRIMARY KEY (SingerId)""",
81+
"""CREATE TABLE Albums (
82+
SingerId INT64 NOT NULL,
83+
AlbumId INT64 NOT NULL,
84+
AlbumTitle STRING(MAX)
85+
) PRIMARY KEY (SingerId, AlbumId),
86+
INTERLEAVE IN PARENT Singers ON DELETE CASCADE""",
87+
"ALTER DATABASE {}"
88+
" SET OPTIONS (default_leader = '{}')".format(
89+
database_id, default_leader
90+
),
91+
],
92+
)
93+
)
94+
95+
print("Waiting for operation to complete...")
96+
database = operation.result(OPERATION_TIMEOUT_SECONDS)
97+
98+
print(
99+
"Database {} created with default leader {}".format(
100+
database.name, database.default_leader
101+
)
102+
)
103+
104+
105+
# [END spanner_create_database_with_default_leader]

samples/samples/admin/samples_test.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2024 Google, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""This application demonstrates how to do basic operations using Cloud
18+
Spanner.
19+
For more information, see the README.rst under /spanner.
20+
"""
21+
22+
import uuid
23+
24+
from google.api_core import exceptions
25+
from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect
26+
import pytest
27+
from test_utils.retry import RetryErrors
28+
29+
import samples
30+
31+
CREATE_TABLE_SINGERS = """\
32+
CREATE TABLE Singers (
33+
SingerId INT64 NOT NULL,
34+
FirstName STRING(1024),
35+
LastName STRING(1024),
36+
SingerInfo BYTES(MAX),
37+
FullName STRING(2048) AS (
38+
ARRAY_TO_STRING([FirstName, LastName], " ")
39+
) STORED
40+
) PRIMARY KEY (SingerId)
41+
"""
42+
43+
CREATE_TABLE_ALBUMS = """\
44+
CREATE TABLE Albums (
45+
SingerId INT64 NOT NULL,
46+
AlbumId INT64 NOT NULL,
47+
AlbumTitle STRING(MAX)
48+
) PRIMARY KEY (SingerId, AlbumId),
49+
INTERLEAVE IN PARENT Singers ON DELETE CASCADE
50+
"""
51+
52+
retry_429 = RetryErrors(exceptions.ResourceExhausted, delay=15)
53+
54+
55+
@pytest.fixture(scope="module")
56+
def sample_name():
57+
return "snippets"
58+
59+
60+
@pytest.fixture(scope="module")
61+
def database_dialect():
62+
"""Spanner dialect to be used for this sample.
63+
64+
The dialect is used to initialize the dialect for the database.
65+
It can either be GoogleStandardSql or PostgreSql.
66+
"""
67+
return DatabaseDialect.GOOGLE_STANDARD_SQL
68+
69+
70+
@pytest.fixture(scope="module")
71+
def create_instance_id():
72+
"""Id for the low-cost instance."""
73+
return f"create-instance-{uuid.uuid4().hex[:10]}"
74+
75+
76+
@pytest.fixture(scope="module")
77+
def lci_instance_id():
78+
"""Id for the low-cost instance."""
79+
return f"lci-instance-{uuid.uuid4().hex[:10]}"
80+
81+
82+
@pytest.fixture(scope="module")
83+
def database_id():
84+
return f"test-db-{uuid.uuid4().hex[:10]}"
85+
86+
87+
@pytest.fixture(scope="module")
88+
def create_database_id():
89+
return f"create-db-{uuid.uuid4().hex[:10]}"
90+
91+
92+
@pytest.fixture(scope="module")
93+
def cmek_database_id():
94+
return f"cmek-db-{uuid.uuid4().hex[:10]}"
95+
96+
97+
@pytest.fixture(scope="module")
98+
def default_leader_database_id():
99+
return f"leader_db_{uuid.uuid4().hex[:10]}"
100+
101+
102+
@pytest.fixture(scope="module")
103+
def database_ddl():
104+
"""Sequence of DDL statements used to set up the database.
105+
106+
Sample testcase modules can override as needed.
107+
"""
108+
return [CREATE_TABLE_SINGERS, CREATE_TABLE_ALBUMS]
109+
110+
111+
@pytest.fixture(scope="module")
112+
def default_leader():
113+
"""Default leader for multi-region instances."""
114+
return "us-east4"
115+
116+
117+
@pytest.fixture(scope="module")
118+
def base_instance_config_id(spanner_client):
119+
return "{}/instanceConfigs/{}".format(spanner_client.project_name, "nam7")
120+
121+
122+
def test_create_instance_explicit(spanner_client, create_instance_id):
123+
# Rather than re-use 'sample_isntance', we create a new instance, to
124+
# ensure that the 'create_instance' snippet is tested.
125+
retry_429(samples.create_instance)(create_instance_id)
126+
instance = spanner_client.instance(create_instance_id)
127+
retry_429(instance.delete)()
128+
129+
130+
def test_create_database_with_default_leader(
131+
capsys,
132+
multi_region_instance,
133+
multi_region_instance_id,
134+
default_leader_database_id,
135+
default_leader,
136+
):
137+
retry_429 = RetryErrors(exceptions.ResourceExhausted, delay=15)
138+
retry_429(samples.create_database_with_default_leader)(
139+
multi_region_instance_id, default_leader_database_id, default_leader
140+
)
141+
out, _ = capsys.readouterr()
142+
assert default_leader_database_id in out
143+
assert default_leader in out

0 commit comments

Comments
 (0)