|
51 | 51 | _check_google_client_version as gbq_check_google_client_version, |
52 | 52 | _test_google_api_imports as gbq_test_google_api_imports, |
53 | 53 | ) |
| 54 | +from sqlalchemy import create_engine |
54 | 55 |
|
55 | 56 | from airflow.exceptions import AirflowException |
56 | 57 | from airflow.hooks.dbapi import DbApiHook |
@@ -114,6 +115,7 @@ def __init__( |
114 | 115 | self.running_job_id = None # type: Optional[str] |
115 | 116 | self.api_resource_configs = api_resource_configs if api_resource_configs else {} # type Dict |
116 | 117 | self.labels = labels |
| 118 | + self.credentials_path = "bigquery_hook_credentials.json" |
117 | 119 |
|
118 | 120 | def get_conn(self) -> "BigQueryConnection": |
119 | 121 | """Returns a BigQuery PEP 249 connection object.""" |
@@ -150,6 +152,41 @@ def get_client(self, project_id: Optional[str] = None, location: Optional[str] = |
150 | 152 | credentials=self._get_credentials(), |
151 | 153 | ) |
152 | 154 |
|
| 155 | + def get_uri(self) -> str: |
| 156 | + """Override DbApiHook get_uri method for get_sqlalchemy_engine()""" |
| 157 | + return f"bigquery://{self.project_id}" |
| 158 | + |
| 159 | + def get_sqlalchemy_engine(self, engine_kwargs=None): |
| 160 | + """ |
| 161 | + Get an sqlalchemy_engine object. |
| 162 | +
|
| 163 | + :param engine_kwargs: Kwargs used in :func:`~sqlalchemy.create_engine`. |
| 164 | + :return: the created engine. |
| 165 | + """ |
| 166 | + connection = self.get_connection(self.gcp_conn_id) |
| 167 | + if connection.extra_dejson.get("extra__google_cloud_platform__key_path"): |
| 168 | + credentials_path = connection.extra_dejson['extra__google_cloud_platform__key_path'] |
| 169 | + return create_engine(self.get_uri(), credentials_path=credentials_path, **engine_kwargs) |
| 170 | + elif connection.extra_dejson.get("extra__google_cloud_platform__keyfile_dict"): |
| 171 | + credential_file_content = json.loads( |
| 172 | + connection.extra_dejson["extra__google_cloud_platform__keyfile_dict"] |
| 173 | + ) |
| 174 | + return create_engine(self.get_uri(), credentials_info=credential_file_content, **engine_kwargs) |
| 175 | + try: |
| 176 | + # 1. If the environment variable GOOGLE_APPLICATION_CREDENTIALS is set |
| 177 | + # ADC uses the service account key or configuration file that the variable points to. |
| 178 | + # 2. If the environment variable GOOGLE_APPLICATION_CREDENTIALS isn't set |
| 179 | + # ADC uses the service account that is attached to the resource that is running your code. |
| 180 | + return create_engine(self.get_uri(), **engine_kwargs) |
| 181 | + except Exception as e: |
| 182 | + self.log.error(e) |
| 183 | + raise AirflowException( |
| 184 | + "For now, we only support instantiating SQLAlchemy engine by" |
| 185 | + " using ADC" |
| 186 | + ", extra__google_cloud_platform__key_path" |
| 187 | + "and extra__google_cloud_platform__keyfile_dict" |
| 188 | + ) |
| 189 | + |
153 | 190 | @staticmethod |
154 | 191 | def _resolve_table_reference( |
155 | 192 | table_resource: Dict[str, Any], |
|
0 commit comments