Skip to content

Commit e58776d

Browse files
committed
Merge branch 'csm_2_instrumentation' into csm_3_handlers
2 parents 1fdd7ad + 6bbac87 commit e58776d

File tree

5 files changed

+184
-239
lines changed

5 files changed

+184
-239
lines changed

tests/system/conftest.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@
2323
script_path = os.path.dirname(os.path.realpath(__file__))
2424
sys.path.append(script_path)
2525

26-
pytest_plugins = [
27-
"data.setup_fixtures",
28-
]
29-
3026

3127
@pytest.fixture(scope="session")
3228
def event_loop():

tests/system/data/__init__.py

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@
1414
# limitations under the License.
1515
#
1616
import pytest
17-
import uuid
1817
import os
18+
import uuid
1919
import datetime
2020

2121
TEST_FAMILY = "test-family"
2222
TEST_FAMILY_2 = "test-family-2"
2323
TEST_AGGREGATE_FAMILY = "test-aggregate-family"
2424

25+
# authorized view subset to allow all qualifiers
26+
ALLOW_ALL = ""
27+
ALL_QUALIFIERS = {"qualifier_prefixes": [ALLOW_ALL]}
28+
2529

2630
class SystemTestRunner:
2731
"""
@@ -80,3 +84,182 @@ def init_table_id(self, start_timestamp):
8084
start_timestamp: accessed when building table to ensure timestamp data is loaded before tests are run
8185
"""
8286
return f"test-table-{uuid.uuid4().hex}"
87+
88+
@pytest.fixture(scope="session")
89+
def admin_client(self):
90+
"""
91+
Client for interacting with Table and Instance admin APIs
92+
"""
93+
from google.cloud.bigtable.client import Client
94+
95+
client = Client(admin=True)
96+
yield client
97+
98+
@pytest.fixture(scope="session")
99+
def instance_id(self, admin_client, project_id, cluster_config):
100+
"""
101+
Returns BIGTABLE_TEST_INSTANCE if set, otherwise creates a new temporary instance for the test session
102+
"""
103+
from google.cloud.bigtable_admin_v2 import types
104+
from google.api_core import exceptions
105+
from google.cloud.environment_vars import BIGTABLE_EMULATOR
106+
107+
# use user-specified instance if available
108+
user_specified_instance = os.getenv("BIGTABLE_TEST_INSTANCE")
109+
if user_specified_instance:
110+
print("Using user-specified instance: {}".format(user_specified_instance))
111+
yield user_specified_instance
112+
return
113+
114+
# create a new temporary test instance
115+
instance_id = f"python-bigtable-tests-{uuid.uuid4().hex[:6]}"
116+
if os.getenv(BIGTABLE_EMULATOR):
117+
# don't create instance if in emulator mode
118+
yield instance_id
119+
else:
120+
try:
121+
operation = admin_client.instance_admin_client.create_instance(
122+
parent=f"projects/{project_id}",
123+
instance_id=instance_id,
124+
instance=types.Instance(
125+
display_name="Test Instance",
126+
# labels={"python-system-test": "true"},
127+
),
128+
clusters=cluster_config,
129+
)
130+
operation.result(timeout=240)
131+
except exceptions.AlreadyExists:
132+
pass
133+
yield instance_id
134+
admin_client.instance_admin_client.delete_instance(
135+
name=f"projects/{project_id}/instances/{instance_id}"
136+
)
137+
138+
@pytest.fixture(scope="session")
139+
def column_split_config(self):
140+
"""
141+
specify initial splits to create when creating a new test table
142+
"""
143+
return [(num * 1000).to_bytes(8, "big") for num in range(1, 10)]
144+
145+
@pytest.fixture(scope="session")
146+
def table_id(
147+
self,
148+
admin_client,
149+
project_id,
150+
instance_id,
151+
column_family_config,
152+
init_table_id,
153+
column_split_config,
154+
):
155+
"""
156+
Returns BIGTABLE_TEST_TABLE if set, otherwise creates a new temporary table for the test session
157+
158+
Args:
159+
- admin_client: Client for interacting with the Table Admin API. Supplied by the admin_client fixture.
160+
- project_id: The project ID of the GCP project to test against. Supplied by the project_id fixture.
161+
- instance_id: The ID of the Bigtable instance to test against. Supplied by the instance_id fixture.
162+
- init_column_families: A list of column families to initialize the table with, if pre-initialized table is not given with BIGTABLE_TEST_TABLE.
163+
Supplied by the init_column_families fixture.
164+
- init_table_id: The table ID to give to the test table, if pre-initialized table is not given with BIGTABLE_TEST_TABLE.
165+
Supplied by the init_table_id fixture.
166+
- column_split_config: A list of row keys to use as initial splits when creating the test table.
167+
"""
168+
from google.api_core import exceptions
169+
from google.api_core import retry
170+
171+
# use user-specified instance if available
172+
user_specified_table = os.getenv("BIGTABLE_TEST_TABLE")
173+
if user_specified_table:
174+
print("Using user-specified table: {}".format(user_specified_table))
175+
yield user_specified_table
176+
return
177+
178+
retry = retry.Retry(
179+
predicate=retry.if_exception_type(exceptions.FailedPrecondition)
180+
)
181+
try:
182+
parent_path = f"projects/{project_id}/instances/{instance_id}"
183+
print(f"Creating table: {parent_path}/tables/{init_table_id}")
184+
admin_client.table_admin_client.create_table(
185+
request={
186+
"parent": parent_path,
187+
"table_id": init_table_id,
188+
"table": {"column_families": column_family_config},
189+
"initial_splits": [{"key": key} for key in column_split_config],
190+
},
191+
retry=retry,
192+
)
193+
except exceptions.AlreadyExists:
194+
pass
195+
yield init_table_id
196+
print(f"Deleting table: {parent_path}/tables/{init_table_id}")
197+
try:
198+
admin_client.table_admin_client.delete_table(
199+
name=f"{parent_path}/tables/{init_table_id}"
200+
)
201+
except exceptions.NotFound:
202+
print(f"Table {init_table_id} not found, skipping deletion")
203+
204+
@pytest.fixture(scope="session")
205+
def authorized_view_id(
206+
self,
207+
admin_client,
208+
project_id,
209+
instance_id,
210+
table_id,
211+
):
212+
"""
213+
Creates and returns a new temporary authorized view for the test session
214+
215+
Args:
216+
- admin_client: Client for interacting with the Table Admin API. Supplied by the admin_client fixture.
217+
- project_id: The project ID of the GCP project to test against. Supplied by the project_id fixture.
218+
- instance_id: The ID of the Bigtable instance to test against. Supplied by the instance_id fixture.
219+
- table_id: The ID of the table to create the authorized view for. Supplied by the table_id fixture.
220+
"""
221+
from google.api_core import exceptions
222+
from google.api_core import retry
223+
224+
retry = retry.Retry(
225+
predicate=retry.if_exception_type(exceptions.FailedPrecondition)
226+
)
227+
new_view_id = uuid.uuid4().hex[:8]
228+
parent_path = f"projects/{project_id}/instances/{instance_id}/tables/{table_id}"
229+
new_path = f"{parent_path}/authorizedViews/{new_view_id}"
230+
try:
231+
print(f"Creating view: {new_path}")
232+
admin_client.table_admin_client.create_authorized_view(
233+
request={
234+
"parent": parent_path,
235+
"authorized_view_id": new_view_id,
236+
"authorized_view": {
237+
"subset_view": {
238+
"row_prefixes": [ALLOW_ALL],
239+
"family_subsets": {
240+
TEST_FAMILY: ALL_QUALIFIERS,
241+
TEST_FAMILY_2: ALL_QUALIFIERS,
242+
TEST_AGGREGATE_FAMILY: ALL_QUALIFIERS,
243+
},
244+
},
245+
},
246+
},
247+
retry=retry,
248+
)
249+
except exceptions.AlreadyExists:
250+
pass
251+
except exceptions.MethodNotImplemented:
252+
# will occur when run in emulator. Pass empty id
253+
new_view_id = None
254+
yield new_view_id
255+
if new_view_id:
256+
print(f"Deleting view: {new_path}")
257+
try:
258+
admin_client.table_admin_client.delete_authorized_view(name=new_path)
259+
except exceptions.NotFound:
260+
print(f"View {new_view_id} not found, skipping deletion")
261+
262+
@pytest.fixture(scope="session")
263+
def project_id(self, client):
264+
"""Returns the project ID from the client."""
265+
yield client.project

0 commit comments

Comments
 (0)