[
https://issues.apache.org/jira/browse/AIRFLOW-3433?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16712048#comment-16712048
]
ASF GitHub Bot commented on AIRFLOW-3433:
-
ryanyuan closed pull request #4284: [AIRFLOW-3433] Create Google Cloud Spanner
Hook
URL: https://github.com/apache/incubator-airflow/pull/4284
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/airflow/contrib/hooks/gcp_spanner_hook.py
b/airflow/contrib/hooks/gcp_spanner_hook.py
new file mode 100644
index 00..5f98cced9a
--- /dev/null
+++ b/airflow/contrib/hooks/gcp_spanner_hook.py
@@ -0,0 +1,500 @@
+# -*- coding: utf-8 -*-
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+from airflow import AirflowException
+from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
+from apiclient.discovery import HttpError, build
+
+
+class SpannerHook(GoogleCloudBaseHook):
+"""
+Interact with Google Cloud Spanner. This hook uses the Google Cloud
Platform
+connection.
+
+This object is not threads safe. If you want to make multiple requests
+simultaneously, you will need to create a hook per thread.
+"""
+
+def __init__(
+self, gcp_conn_id="google_cloud_default", delegate_to=None,
version="v1"
+):
+super(SpannerHook, self).__init__(gcp_conn_id, delegate_to)
+self.version = version
+
+def get_conn(self):
+"""
+Returns a Google Cloud Spanner service object.
+"""
+http_authorized = self._authorize()
+return build(
+"spanner", self.version, http=http_authorized,
cache_discovery=False
+)
+
+def list_instance_configs(self, project_id):
+"""
+Lists the supported instance configurations for a given project.
+
+.. seealso::
+For more information, see:
+
https://cloud.google.com/spanner/docs/reference/rest/v1/projects.instanceConfigs/list
+
+:param project_id: The name of the project for which a list of
supported instance
+configurations is requested
+:type project_id: str
+"""
+
+project_id = project_id if project_id is not None else self.project_id
+
+self.log.info("Retrieving Spanner instance configs")
+
+try:
+resp = (
+self.get_conn()
+.projects()
+.instanceConfigs()
+.list(parent="projects/{}".format(project_id))
+.execute()
+)
+
+self.log.info("Spanner instance configs retrieved successfully")
+
+return resp
+except HttpError as err:
+raise AirflowException(
+"BigQuery job failed. Error was: {}".format(err.content)
+)
+
+def create_instance(self, project_id, body):
+"""
+Method to create a Cloud Spanner instance and begins preparing it to
begin serving.
+If the named instance already exists, it will return 409 Instance
Already Exists.
+
+.. seealso::
+For more information, see:
+
https://cloud.google.com/spanner/docs/reference/rest/v1/projects.instances/create
+
+:param project_id: The name of the project in which to create the
instance
+:type project_id: str
+:param body: the request body containing instance creation data
+:type rows: dict
+
+**Example or body**:
+body = {
+"instanceId": "spanner-instance-1",
+"instance": {
+"nodeCount": 1,
+"config": "projects/spanner-project/instanceConfigs/eur3",
+"displayName": "Spanner Instance 1",
+},
+}
+"""
+
+project_id = project_id if project_id is not None else self.project_id
+
+if "instanceId" not in body:
+raise ValueError("instanceId is undefined in the body")