diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 66f4effe0e9..eeb77c8aa49 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -100,6 +100,7 @@ /bigquery-connection/**/* @GoogleCloudPlatform/api-bigquery @GoogleCloudPlatform/python-samples-reviewers /bigquery-datatransfer/**/* @GoogleCloudPlatform/api-bigquery @GoogleCloudPlatform/python-samples-reviewers /bigquery-migration/**/* @GoogleCloudPlatform/api-bigquery @GoogleCloudPlatform/python-samples-reviewers +/bigquery-reservation/**/* @GoogleCloudPlatform/api-bigquery @GoogleCloudPlatform/python-samples-reviewers /dlp/**/* @GoogleCloudPlatform/googleapis-dlp @GoogleCloudPlatform/python-samples-reviewers /functions/spanner/* @GoogleCloudPlatform/api-spanner-python @GoogleCloudPlatform/functions-framework-google @GoogleCloudPlatform/python-samples-reviewers /healthcare/**/* @GoogleCloudPlatform/healthcare-life-sciences @GoogleCloudPlatform/python-samples-reviewers diff --git a/bigquery-reservation/snippets/__init__.py b/bigquery-reservation/snippets/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/bigquery-reservation/snippets/conftest.py b/bigquery-reservation/snippets/conftest.py new file mode 100644 index 00000000000..19b4fee6ea5 --- /dev/null +++ b/bigquery-reservation/snippets/conftest.py @@ -0,0 +1,42 @@ +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. + +import os + +from google.cloud.bigquery_reservation_v1.services import reservation_service +import pytest + + +@pytest.fixture(scope="session") +def project_id() -> str: + return os.environ["GOOGLE_CLOUD_PROJECT"] + + +@pytest.fixture(scope="session") +def reservation_client( + transport: str = "grpc", +) -> reservation_service.ReservationServiceClient: + return reservation_service.ReservationServiceClient(transport=transport) + + +@pytest.fixture(scope="session") +def location() -> str: + return "US" + + +@pytest.fixture(scope="session") +def location_path(project_id: str, location: str) -> str: + return reservation_service.ReservationServiceClient.common_location_path( + project_id, location + ) diff --git a/bigquery-reservation/snippets/noxfile_config.py b/bigquery-reservation/snippets/noxfile_config.py new file mode 100644 index 00000000000..e1c631ca86f --- /dev/null +++ b/bigquery-reservation/snippets/noxfile_config.py @@ -0,0 +1,38 @@ +# Copyright 2020 Google LLC +# +# 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. + +# Default TEST_CONFIG_OVERRIDE for python repos. + +# You can copy this file into your directory, then it will be inported from +# the noxfile.py. + +# The source of truth: +# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py + +TEST_CONFIG_OVERRIDE = { + # You can opt out from the test for specific Python versions. + "ignored_versions": ["2.7", "3.6"], + # Old samples are opted out of enforcing Python type hints + # All new samples should feature them + "enforce_type_hints": True, + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": {}, +} diff --git a/bigquery-reservation/snippets/quickstart.py b/bigquery-reservation/snippets/quickstart.py new file mode 100644 index 00000000000..cfcac248baf --- /dev/null +++ b/bigquery-reservation/snippets/quickstart.py @@ -0,0 +1,59 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# https://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. + +# [START bigqueryreservation_quickstart] +import argparse + +from google.cloud import bigquery_reservation_v1 + + +def main( + project_id: str = "your-project-id", location: str = "US", transport: str = "grpc" +) -> None: + # Constructs the client for interacting with the service. + client = bigquery_reservation_v1.ReservationServiceClient(transport=transport) + + report_reservations(client, project_id, location) + + +def report_reservations( + client: bigquery_reservation_v1.ReservationServiceClient, + project_id: str, + location: str, +) -> None: + """Prints details and summary information about reservations defined within + a given admin project and location. + """ + print("Reservations in project {} in location {}".format(project_id, location)) + req = bigquery_reservation_v1.ListReservationsRequest( + parent=client.common_location_path(project_id, location) + ) + total_reservations = 0 + for reservation in client.list_reservations(request=req): + print( + f"\tReservation {reservation.name} " + f"has {reservation.slot_capacity} slot capacity." + ) + total_reservations = total_reservations + 1 + print(f"\n{total_reservations} reservations processed.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--project_id", type=str) + parser.add_argument("--location", default="US", type=str) + args = parser.parse_args() + main(project_id=args.project_id, location=args.location) + +# [END bigqueryreservation_quickstart] diff --git a/bigquery-reservation/snippets/quickstart_test.py b/bigquery-reservation/snippets/quickstart_test.py new file mode 100644 index 00000000000..85a0a8727d6 --- /dev/null +++ b/bigquery-reservation/snippets/quickstart_test.py @@ -0,0 +1,26 @@ +# Copyright 2020 Google LLC +# +# 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 +# +# https://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. + +import pytest + +from . import quickstart + + +@pytest.mark.parametrize("transport", ["grpc", "rest"]) +def test_quickstart( + capsys: pytest.CaptureFixture, project_id: str, transport: str +) -> None: + quickstart.main(project_id=project_id, transport=transport) + out, _ = capsys.readouterr() + assert " reservations processed." in out diff --git a/bigquery-reservation/snippets/requirements-test.txt b/bigquery-reservation/snippets/requirements-test.txt new file mode 100644 index 00000000000..ca1f33bd3f4 --- /dev/null +++ b/bigquery-reservation/snippets/requirements-test.txt @@ -0,0 +1,2 @@ +pytest==7.3.1 +google-cloud-testutils==1.3.3 diff --git a/bigquery-reservation/snippets/requirements.txt b/bigquery-reservation/snippets/requirements.txt new file mode 100644 index 00000000000..e6881f116dd --- /dev/null +++ b/bigquery-reservation/snippets/requirements.txt @@ -0,0 +1 @@ +google-cloud-bigquery-reservation==1.11.1 diff --git a/bigquery-reservation/snippets/reservation_create.py b/bigquery-reservation/snippets/reservation_create.py new file mode 100644 index 00000000000..efaaefe3098 --- /dev/null +++ b/bigquery-reservation/snippets/reservation_create.py @@ -0,0 +1,79 @@ +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. + +from google.cloud.bigquery_reservation_v1.types import reservation as reservation_types + + +def create_reservation( + project_id: str, + location: str, + reservation_id: str, + slot_capacity: str, + transport: str, +) -> reservation_types.Reservation: + original_project_id = project_id + original_location = location + original_reservation_id = reservation_id + original_slot_capacity = slot_capacity + original_transport = transport + + # [START bigqueryreservation_reservation_create] + # TODO(developer): Set project_id to the project ID containing the + # reservation. + project_id = "your-project-id" + + # TODO(developer): Set location to the location of the reservation. + # See: https://cloud.google.com/bigquery/docs/locations for a list of + # available locations. + location = "US" + + # TODO(developer): Set reservation_id to a unique ID of the reservation. + reservation_id = "sample-reservation" + + # TODO(developer): Set slot_capicity to the number of slots in the + # reservation. + slot_capacity = 100 + + # TODO(developer): Choose a transport to use. Either 'grpc' or 'rest' + transport = "grpc" + + # [START_EXCLUDE] + project_id = original_project_id + location = original_location + reservation_id = original_reservation_id + slot_capacity = original_slot_capacity + transport = original_transport + # [END_EXCLUDE] + + from google.cloud.bigquery_reservation_v1.services import reservation_service + from google.cloud.bigquery_reservation_v1.types import ( + reservation as reservation_types, + ) + + reservation_client = reservation_service.ReservationServiceClient( + transport=transport + ) + + parent = reservation_client.common_location_path(project_id, location) + + reservation = reservation_types.Reservation(slot_capacity=slot_capacity) + reservation = reservation_client.create_reservation( + parent=parent, + reservation=reservation, + reservation_id=reservation_id, + ) + + print(f"Created reservation: {reservation.name}") + # [END bigqueryreservation_reservation_create] + return reservation diff --git a/bigquery-reservation/snippets/reservation_delete.py b/bigquery-reservation/snippets/reservation_delete.py new file mode 100644 index 00000000000..a0f25ce1cf2 --- /dev/null +++ b/bigquery-reservation/snippets/reservation_delete.py @@ -0,0 +1,58 @@ +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. + + +def delete_reservation( + project_id: str, location: str, reservation_id: str, transport: str +) -> None: + original_project_id = project_id + original_location = location + original_reservation_id = reservation_id + original_transport = transport + + # [START bigqueryreservation_reservation_delete] + # TODO(developer): Set project_id to the project ID containing the + # reservation. + project_id = "your-project-id" + + # TODO(developer): Set location to the location of the reservation. + # See: https://cloud.google.com/bigquery/docs/locations for a list of + # available locations. + location = "US" + + # TODO(developer): Set reservation_id to a unique ID of the reservation. + reservation_id = "sample-reservation" + + # TODO(developer): Choose a transport to use. Either 'grpc' or 'rest' + transport = "grpc" + + # [START_EXCLUDE] + project_id = original_project_id + location = original_location + reservation_id = original_reservation_id + transport = original_transport + # [END_EXCLUDE] + + from google.cloud.bigquery_reservation_v1.services import reservation_service + + reservation_client = reservation_service.ReservationServiceClient( + transport=transport + ) + reservation_name = reservation_client.reservation_path( + project_id, location, reservation_id + ) + reservation_client.delete_reservation(name=reservation_name) + + print(f"Deleted reservation: {reservation_name}") + # [END bigqueryreservation_reservation_delete] diff --git a/bigquery-reservation/snippets/reservation_test.py b/bigquery-reservation/snippets/reservation_test.py new file mode 100644 index 00000000000..5f4f8f6599b --- /dev/null +++ b/bigquery-reservation/snippets/reservation_test.py @@ -0,0 +1,88 @@ +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. + +import google.api_core.exceptions +from google.cloud.bigquery_reservation_v1.services import reservation_service +import pytest +import test_utils.prefixer + +from . import reservation_create, reservation_delete + +# Reservation IDs are limited to 64 characters. +reservation_prefixer = test_utils.prefixer.Prefixer( + "py-bq-r", "snippets", separator="-" +) + + +@pytest.fixture(scope="module", autouse=True) +def cleanup_reservations( + reservation_client: reservation_service.ReservationServiceClient, location_path: str +) -> None: + for reservation in reservation_client.list_reservations(parent=location_path): + reservation_id = reservation.name.split("/")[-1] + if reservation_prefixer.should_cleanup(reservation_id): + reservation_client.delete_reservation(name=reservation.name) + + +@pytest.fixture(scope="session") +def reservation_id( + reservation_client: reservation_service.ReservationServiceClient, + project_id: str, + location: str, +) -> str: + id_ = reservation_prefixer.create_prefix() + yield id_ + + reservation_name = reservation_client.reservation_path(project_id, location, id_) + try: + reservation_client.delete_reservation(name=reservation_name) + except google.api_core.exceptions.NotFound: + pass + + +@pytest.mark.parametrize("transport", ["grpc", "rest"]) +def test_reservation_samples( + capsys: pytest.CaptureFixture, + project_id: str, + location: str, + reservation_id: str, + transport: str, +) -> None: + slot_capacity = 100 + reservation = reservation_create.create_reservation( + project_id, location, reservation_id, slot_capacity, transport + ) + assert reservation.slot_capacity == 100 + assert reservation_id in reservation.name + out, _ = capsys.readouterr() + assert f"Created reservation: {reservation.name}" in out + + # The test for reservation_update is skipped for now, since without + # capacity commitment we cannot decrease the capacity within one hour. + + # slot_capacity = 50 + # reservation = reservation_update.update_reservation( + # project_id, location, reservation_id, slot_capacity, transport + # ) + # assert reservation.slot_capacity == 50 + # assert reservation_id in reservation.name + # out, _ = capsys.readouterr() + # assert f"Updated reservation: {reservation.name}" in out + + reservation_delete.delete_reservation( + project_id, location, reservation_id, transport + ) + out, _ = capsys.readouterr() + assert "Deleted reservation" in out + assert reservation_id in out diff --git a/bigquery-reservation/snippets/reservation_update.py b/bigquery-reservation/snippets/reservation_update.py new file mode 100644 index 00000000000..8afbd9d7d0f --- /dev/null +++ b/bigquery-reservation/snippets/reservation_update.py @@ -0,0 +1,84 @@ +# Copyright 2021 Google LLC +# +# 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 +# +# https://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. + +from google.cloud.bigquery_reservation_v1.types import reservation as reservation_types + + +def update_reservation( + project_id: str, + location: str, + reservation_id: str, + slot_capacity: str, + transport: str, +) -> reservation_types.Reservation: + original_project_id = project_id + original_location = location + original_reservation_id = reservation_id + original_slot_capacity = slot_capacity + original_transport = transport + + # [START bigqueryreservation_reservation_update] + # TODO(developer): Set project_id to the project ID containing the + # reservation. + project_id = "your-project-id" + + # TODO(developer): Set location to the location of the reservation. + # See: https://cloud.google.com/bigquery/docs/locations for a list of + # available locations. + location = "US" + + # TODO(developer): Set reservation_id to a unique ID of the reservation. + reservation_id = "sample-reservation" + + # TODO(developer): Set slot_capicity to the new number of slots in the + # reservation. + slot_capacity = 50 + + # TODO(developer): Choose a transport to use. Either 'grpc' or 'rest' + transport = "grpc" + + # [START_EXCLUDE] + project_id = original_project_id + location = original_location + reservation_id = original_reservation_id + slot_capacity = original_slot_capacity + transport = original_transport + # [END_EXCLUDE] + + from google.cloud.bigquery_reservation_v1.services import reservation_service + from google.cloud.bigquery_reservation_v1.types import ( + reservation as reservation_types, + ) + from google.protobuf import field_mask_pb2 + + reservation_client = reservation_service.ReservationServiceClient( + transport=transport + ) + + reservation_name = reservation_client.reservation_path( + project_id, location, reservation_id + ) + reservation = reservation_types.Reservation( + name=reservation_name, + slot_capacity=slot_capacity, + ) + field_mask = field_mask_pb2.FieldMask(paths=["slot_capacity"]) + reservation = reservation_client.update_reservation( + reservation=reservation, update_mask=field_mask + ) + + print(f"Updated reservation: {reservation.name}") + print(f"\tslot_capacity: {reservation.slot_capacity}") + # [END bigqueryreservation_reservation_update] + return reservation