diff --git a/ci/README.md b/ci/README.md index d1b5d836..420053d6 100644 --- a/ci/README.md +++ b/ci/README.md @@ -316,4 +316,49 @@ BIGTABLE_SERVICE_URL=$(gcloud run services describe \ --format="value(status.url)" \ gcf-tutorial-cloud-bigtable) curl -H "projectID: ${GOOGLE_CLOUD_PROJECT}" -H "instanceID: test-instance-0" -H "tableID: test-table" "${BIGTABLE_SERVICE_URL}" -``` \ No newline at end of file +``` + +### Spanner + +Create the instance: + +```shell +gcloud --project="${GOOGLE_CLOUD_PROJECT}" spanner instances create test-instance-0 \ + --config="regional-us-central1" \ + --description="Test instance for CI builds" \ + --nodes=1 +``` + +To populate the database, use the spanner examples from the C++ client library: + +```shell +( + cd $HOME/google-cloud-cpp + bazel run //google/cloud/spanner/samples:samples -- \ + create-database "${GOOGLE_CLOUD_PROJECT}" test-instance-0 test-db + bazel run //google/cloud/spanner/samples:samples -- \ + insert-data "${GOOGLE_CLOUD_PROJECT}" test-instance-0 test-db +) +``` + +```shell +pack build -v \ + --env TARGET_FUNCTION=tutorial_cloud_spanner \ + --path examples/site/tutorial_cloud_spanner \ + "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-spanner" +docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-spanner" +gcloud run deploy gcf-tutorial-cloud-spanner \ + --project="${GOOGLE_CLOUD_PROJECT}" \ + --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-spanner:latest" \ + --region="us-central1" \ + --platform="managed" \ + --set-env-vars=GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT}",SPANNER_INSTANCE=test-instance-0,SPANNER_DATABASE=test-db \ + --allow-unauthenticated +SPANNER_SERVICE_URL=$(gcloud run services describe \ + --project="${GOOGLE_CLOUD_PROJECT}" \ + --platform="managed" \ + --region="us-central1" \ + --format="value(status.url)" \ + gcf-tutorial-cloud-spanner) +curl "${SPANNER_SERVICE_URL}" +``` diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2a6cf645..7d0a8c44 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -18,6 +18,7 @@ find_package(Boost REQUIRED COMPONENTS log) find_package(fmt REQUIRED) find_package(google_cloud_cpp_bigtable REQUIRED) find_package(google_cloud_cpp_pubsub REQUIRED) +find_package(google_cloud_cpp_spanner REQUIRED) find_package(google_cloud_cpp_storage REQUIRED) add_library( @@ -51,7 +52,8 @@ add_library( site/tips_lazy_globals/tips_lazy_globals.cc site/tips_retry/tips_retry.cc site/tips_scopes/tips_scopes.cc - site/tutorial_cloud_bigtable/tutorial_cloud_bigtable.cc) + site/tutorial_cloud_bigtable/tutorial_cloud_bigtable.cc + site/tutorial_cloud_spanner/tutorial_cloud_spanner.cc) functions_framework_cpp_add_common_options(functions_framework_examples) if (MSVC) set_property( diff --git a/examples/site/tutorial_cloud_spanner/CMakeLists.txt b/examples/site/tutorial_cloud_spanner/CMakeLists.txt new file mode 100644 index 00000000..0512b91b --- /dev/null +++ b/examples/site/tutorial_cloud_spanner/CMakeLists.txt @@ -0,0 +1,23 @@ +# ~~~ +# 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 +# +# 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. +# ~~~ + +find_package(google_cloud_cpp_spanner REQUIRED) +find_package(functions_framework_cpp REQUIRED) + +add_library(functions_framework_cpp_function tutorial_cloud_spanner.cc) +target_link_libraries( + functions_framework_cpp_function functions-framework-cpp::framework + google-cloud-cpp::spanner) diff --git a/examples/site/tutorial_cloud_spanner/tutorial_cloud_spanner.cc b/examples/site/tutorial_cloud_spanner/tutorial_cloud_spanner.cc new file mode 100644 index 00000000..1c9ea11b --- /dev/null +++ b/examples/site/tutorial_cloud_spanner/tutorial_cloud_spanner.cc @@ -0,0 +1,66 @@ +// 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 +// +// 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. + +// [START spanner_functions_quickstart] +#include +#include +#include +#include +#include +#include +#include + +namespace gcf = ::google::cloud::functions; +namespace spanner = ::google::cloud::spanner; + +namespace { +auto get_spanner_database() { + auto getenv = [](char const* var) { + auto const* value = std::getenv(var); + if (value == nullptr) { + throw std::runtime_error("Environment variable " + std::string(var) + + " is not set"); + } + return std::string(value); + }; + return spanner::Database(getenv("GOOGLE_CLOUD_PROJECT"), + getenv("SPANNER_INSTANCE"), + getenv("SPANNER_DATABASE")); +} +} // namespace + +gcf::HttpResponse tutorial_cloud_spanner( + gcf::HttpRequest /*request*/) { // NOLINT + static auto const kClient = + spanner::Client(spanner::MakeConnection(get_spanner_database())); + + auto client = kClient; + + std::ostringstream os; + os << "Albums:\n"; + auto rows = client.ExecuteQuery(spanner::SqlStatement( + "SELECT SingerId, AlbumId, AlbumTitle FROM Albums")); + using RowType = std::tuple; + for (auto const& row : spanner::StreamOf(rows)) { + if (!row) throw std::runtime_error(row.status().message()); + os << std::get<0>(*row) << " " << std::get<1>(*row) << " " + << std::get<2>(*row) << "\n"; + } + + gcf::HttpResponse response; + response.set_payload(std::move(os).str()); + response.set_header("content-type", "text/plain"); + return response; +} +// [END spanner_functions_quickstart] diff --git a/examples/site/tutorial_cloud_spanner/vcpkg.json b/examples/site/tutorial_cloud_spanner/vcpkg.json new file mode 100644 index 00000000..b3a7a731 --- /dev/null +++ b/examples/site/tutorial_cloud_spanner/vcpkg.json @@ -0,0 +1,8 @@ +{ + "name": "tutorial-cloud-spanner", + "version-string": "unversioned", + "dependencies": [ + "functions-framework-cpp", + "google-cloud-cpp" + ] +}