From 0413f3b99b2e450badcc6dad13d20891ca66cc9c Mon Sep 17 00:00:00 2001 From: kamran imaz <136354689+Kamran-imaz@users.noreply.github.com> Date: Sun, 28 Dec 2025 01:29:46 -0800 Subject: [PATCH 01/24] added deprecation of project_id parameter mentioned about deprication of project_id parameter --- providers/google/docs/operators/cloud/bigquery.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/providers/google/docs/operators/cloud/bigquery.rst b/providers/google/docs/operators/cloud/bigquery.rst index 41c49dd5e0311..61eed73de5963 100644 --- a/providers/google/docs/operators/cloud/bigquery.rst +++ b/providers/google/docs/operators/cloud/bigquery.rst @@ -208,6 +208,10 @@ nesting will a nested list where elements would represent the column values for that row. ``True`` - A Python list of dictionaries, where each dictionary represents a row. In each dictionary, the keys are the column names and the values are the corresponding values for those columns. +..note:: +The project_id parameter is deprecated and will be removed in a future release. +Please use table_project_id instead. + .. exampleinclude:: /../../google/tests/system/google/cloud/bigquery/example_bigquery_queries.py :language: python :dedent: 4 From 522e72eaf05c0908ad3561964246e7ded0d71f49 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 24 Jan 2026 20:07:47 +0530 Subject: [PATCH 02/24] updated all operators try/except in bigtable --- .../providers/google/cloud/hooks/bigtable.py | 13 ++- .../google/cloud/operators/bigtable.py | 79 ++++++------------- 2 files changed, 36 insertions(+), 56 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 83a631eafa687..8cf54af577782 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -203,7 +203,6 @@ def update_instance( instance_type=instance_type, labels=instance_labels, ) - operation = instance.update() operation.result(timeout) @@ -252,7 +251,10 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance is None: raise RuntimeError(f"Instance {instance_id} did not exist; unable to delete table {table_id}") - table = instance.table(table_id=table_id) + try: + table = instance.table(table_id=table_id) + except google.api_core.exceptions.NotFound: + self.log.info("The table '%s' no longer exists. Consider it as deleted", table_id) table.delete() @staticmethod @@ -268,7 +270,12 @@ def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: """ cluster = Cluster(cluster_id, instance) # "reload" is required to set location_id attribute on cluster. - cluster.reload() + try: + cluster.reload() + except google.api_core.exceptions.NotFound: + raise AirflowException( + f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance.id}'." + ) cluster.serve_nodes = nodes cluster.update() diff --git a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py index 6f583ca3c63fe..c672a8c47033a 100644 --- a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py @@ -164,24 +164,21 @@ def execute(self, context: Context) -> None: ) BigtableInstanceLink.persist(context=context) return - try: - hook.create_instance( - project_id=self.project_id, - instance_id=self.instance_id, - main_cluster_id=self.main_cluster_id, - main_cluster_zone=self.main_cluster_zone, - replica_clusters=self.replica_clusters, - instance_display_name=self.instance_display_name, - instance_type=self.instance_type, - instance_labels=self.instance_labels, - cluster_nodes=self.cluster_nodes, - cluster_storage_type=self.cluster_storage_type, - timeout=self.timeout, - ) - BigtableInstanceLink.persist(context=context) - except google.api_core.exceptions.GoogleAPICallError as e: - self.log.error("An error occurred. Exiting.") - raise e + + hook.create_instance( + project_id=self.project_id, + instance_id=self.instance_id, + main_cluster_id=self.main_cluster_id, + main_cluster_zone=self.main_cluster_zone, + replica_clusters=self.replica_clusters, + instance_display_name=self.instance_display_name, + instance_type=self.instance_type, + instance_labels=self.instance_labels, + cluster_nodes=self.cluster_nodes, + cluster_storage_type=self.cluster_storage_type, + timeout=self.timeout, + ) + BigtableInstanceLink.persist(context=context) class BigtableUpdateInstanceOperator(GoogleCloudBaseOperator, BigtableValidationMixin): @@ -260,10 +257,7 @@ def execute(self, context: Context) -> None: impersonation_chain=self.impersonation_chain, ) instance = hook.get_instance(project_id=self.project_id, instance_id=self.instance_id) - if not instance: - raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") - - try: + if instance: hook.update_instance( project_id=self.project_id, instance_id=self.instance_id, @@ -273,9 +267,8 @@ def execute(self, context: Context) -> None: timeout=self.timeout, ) BigtableInstanceLink.persist(context=context) - except google.api_core.exceptions.GoogleAPICallError as e: - self.log.error("An error occurred. Exiting.") - raise e + else: + raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") class BigtableDeleteInstanceOperator(GoogleCloudBaseOperator, BigtableValidationMixin): @@ -511,23 +504,11 @@ def execute(self, context: Context) -> None: gcp_conn_id=self.gcp_conn_id, impersonation_chain=self.impersonation_chain, ) - instance = hook.get_instance(project_id=self.project_id, instance_id=self.instance_id) - if not instance: - raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") - - try: - hook.delete_table( - project_id=self.project_id, - instance_id=self.instance_id, - table_id=self.table_id, - ) - except google.api_core.exceptions.NotFound: - # It's OK if table doesn't exists. - self.log.info("The table '%s' no longer exists. Consider it as deleted", self.table_id) - except google.api_core.exceptions.GoogleAPICallError as e: - self.log.error("An error occurred. Exiting.") - raise e - + hook.delete_table( + project_id=self.project_id, + instance_id=self.instance_id, + table_id=self.table_id, + ) class BigtableUpdateClusterOperator(GoogleCloudBaseOperator, BigtableValidationMixin): """ @@ -600,16 +581,8 @@ def execute(self, context: Context) -> None: impersonation_chain=self.impersonation_chain, ) instance = hook.get_instance(project_id=self.project_id, instance_id=self.instance_id) - if not instance: - raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") - - try: + if instance: hook.update_cluster(instance=instance, cluster_id=self.cluster_id, nodes=self.nodes) BigtableClusterLink.persist(context=context) - except google.api_core.exceptions.NotFound: - raise AirflowException( - f"Dependency: cluster '{self.cluster_id}' does not exist for instance '{self.instance_id}'." - ) - except google.api_core.exceptions.GoogleAPICallError as e: - self.log.error("An error occurred. Exiting.") - raise e + else: + raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") From 7e507592099d4c9f83f2040711836820d197d062 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 24 Jan 2026 20:13:17 +0530 Subject: [PATCH 03/24] removed bigquery deprecated project id comment --- providers/google/docs/operators/cloud/bigquery.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/providers/google/docs/operators/cloud/bigquery.rst b/providers/google/docs/operators/cloud/bigquery.rst index 61eed73de5963..41c49dd5e0311 100644 --- a/providers/google/docs/operators/cloud/bigquery.rst +++ b/providers/google/docs/operators/cloud/bigquery.rst @@ -208,10 +208,6 @@ nesting will a nested list where elements would represent the column values for that row. ``True`` - A Python list of dictionaries, where each dictionary represents a row. In each dictionary, the keys are the column names and the values are the corresponding values for those columns. -..note:: -The project_id parameter is deprecated and will be removed in a future release. -Please use table_project_id instead. - .. exampleinclude:: /../../google/tests/system/google/cloud/bigquery/example_bigquery_queries.py :language: python :dedent: 4 From 15a653e496b785961499acb0b9f9fb05e275e295 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 24 Jan 2026 20:32:10 +0530 Subject: [PATCH 04/24] added exception library in hook --- .../google/src/airflow/providers/google/cloud/hooks/bigtable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 8cf54af577782..61460783d98e3 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -27,6 +27,8 @@ from google.cloud.bigtable.instance import Instance from google.cloud.bigtable.table import ClusterState, Table +import google.api_core.exceptions + from airflow.providers.google.common.consts import CLIENT_INFO from airflow.providers.google.common.hooks.base_google import GoogleBaseHook From ccca98a08ce7a4623a9079d5acfbfb05dc052437 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 24 Jan 2026 22:12:28 +0530 Subject: [PATCH 05/24] re-corrected the try..except block for deletetable operator --- .../src/airflow/providers/google/cloud/hooks/bigtable.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 61460783d98e3..b67bb28824780 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -253,11 +253,12 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance is None: raise RuntimeError(f"Instance {instance_id} did not exist; unable to delete table {table_id}") + + table = instance.table(table_id=table_id) try: - table = instance.table(table_id=table_id) + table.delete() except google.api_core.exceptions.NotFound: self.log.info("The table '%s' no longer exists. Consider it as deleted", table_id) - table.delete() @staticmethod def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: From 58f4dee05e424c02d7d85dc1f05f9dc618ba5cf5 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 25 Jan 2026 12:24:29 +0530 Subject: [PATCH 06/24] reverted back previous if..else condition in the operators --- .../providers/google/cloud/hooks/bigtable.py | 5 ++-- .../google/cloud/operators/bigtable.py | 30 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index b67bb28824780..1f7a0f9fa647c 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -22,13 +22,12 @@ from collections.abc import Sequence from typing import TYPE_CHECKING +import google.api_core.exceptions from google.cloud.bigtable import Client, enums from google.cloud.bigtable.cluster import Cluster from google.cloud.bigtable.instance import Instance from google.cloud.bigtable.table import ClusterState, Table -import google.api_core.exceptions - from airflow.providers.google.common.consts import CLIENT_INFO from airflow.providers.google.common.hooks.base_google import GoogleBaseHook @@ -253,7 +252,7 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance is None: raise RuntimeError(f"Instance {instance_id} did not exist; unable to delete table {table_id}") - + table = instance.table(table_id=table_id) try: table.delete() diff --git a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py index c672a8c47033a..b0910e6049b5b 100644 --- a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py @@ -257,19 +257,19 @@ def execute(self, context: Context) -> None: impersonation_chain=self.impersonation_chain, ) instance = hook.get_instance(project_id=self.project_id, instance_id=self.instance_id) - if instance: - hook.update_instance( - project_id=self.project_id, - instance_id=self.instance_id, - instance_display_name=self.instance_display_name, - instance_type=self.instance_type, - instance_labels=self.instance_labels, - timeout=self.timeout, - ) - BigtableInstanceLink.persist(context=context) - else: + if not instance: raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") + hook.update_instance( + project_id=self.project_id, + instance_id=self.instance_id, + instance_display_name=self.instance_display_name, + instance_type=self.instance_type, + instance_labels=self.instance_labels, + timeout=self.timeout, + ) + BigtableInstanceLink.persist(context=context) + class BigtableDeleteInstanceOperator(GoogleCloudBaseOperator, BigtableValidationMixin): """ @@ -581,8 +581,8 @@ def execute(self, context: Context) -> None: impersonation_chain=self.impersonation_chain, ) instance = hook.get_instance(project_id=self.project_id, instance_id=self.instance_id) - if instance: - hook.update_cluster(instance=instance, cluster_id=self.cluster_id, nodes=self.nodes) - BigtableClusterLink.persist(context=context) - else: + if not instance: raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") + + hook.update_cluster(instance=instance, cluster_id=self.cluster_id, nodes=self.nodes) + BigtableClusterLink.persist(context=context) From 7b98f0f0e0058420caaff95b5f69f7fd5b362cc9 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 25 Jan 2026 19:49:24 +0530 Subject: [PATCH 07/24] handled test files --- .../providers/google/cloud/hooks/bigtable.py | 2 +- .../google/cloud/operators/test_bigtable.py | 24 +------------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 1f7a0f9fa647c..e43db993f4f9b 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -27,7 +27,7 @@ from google.cloud.bigtable.cluster import Cluster from google.cloud.bigtable.instance import Instance from google.cloud.bigtable.table import ClusterState, Table - +from airflow.providers.common.compat.sdk import AirflowException from airflow.providers.google.common.consts import CLIENT_INFO from airflow.providers.google.common.hooks.base_google import GoogleBaseHook diff --git a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py index b60e494a55640..91011821ba972 100644 --- a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py @@ -232,7 +232,7 @@ def test_create_instance_with_replicas_that_doesnt_exists(self, mock_hook): class TestBigtableInstanceUpdate: @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") - def test_delete_execute(self, mock_hook): + def test_update_execute(self, mock_hook): op = BigtableUpdateInstanceOperator( project_id=PROJECT_ID, instance_id=INSTANCE_ID, @@ -689,28 +689,6 @@ def test_deleting_table_that_doesnt_exists_empty_project_id(self, mock_hook): project_id=None, instance_id=INSTANCE_ID, table_id=TABLE_ID ) - @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") - def test_deleting_table_when_instance_doesnt_exists(self, mock_hook): - op = BigtableDeleteTableOperator( - project_id=PROJECT_ID, - instance_id=INSTANCE_ID, - table_id=TABLE_ID, - task_id="id", - gcp_conn_id=GCP_CONN_ID, - impersonation_chain=IMPERSONATION_CHAIN, - ) - - mock_hook.return_value.get_instance.return_value = None - with pytest.raises(AirflowException) as ctx: - op.execute(None) - err = ctx.value - assert str(err) == f"Dependency: instance '{INSTANCE_ID}' does not exist." - mock_hook.assert_called_once_with( - gcp_conn_id=GCP_CONN_ID, - impersonation_chain=IMPERSONATION_CHAIN, - ) - mock_hook.return_value.delete_table.assert_not_called() - @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") def test_different_error_reraised(self, mock_hook): op = BigtableDeleteTableOperator( From f137f47aff4e2b6b12f6971049a0f07a1d4b7584 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 25 Jan 2026 20:43:03 +0530 Subject: [PATCH 08/24] handled tests part 2 --- .../providers/google/cloud/hooks/bigtable.py | 2 +- .../unit/google/cloud/operators/test_bigtable.py | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index e43db993f4f9b..811a1ca814e09 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -276,7 +276,7 @@ def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: cluster.reload() except google.api_core.exceptions.NotFound: raise AirflowException( - f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance.id}'." + f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance.instance_id}'." ) cluster.serve_nodes = nodes cluster.update() diff --git a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py index 91011821ba972..c77337ee014bf 100644 --- a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py @@ -455,8 +455,8 @@ def test_updating_cluster_but_instance_does_not_exists_empty_project_id(self, mo @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") def test_updating_cluster_that_does_not_exists(self, mock_hook): instance = mock_hook.return_value.get_instance.return_value = mock.Mock(Instance) - mock_hook.return_value.update_cluster.side_effect = mock.Mock( - side_effect=google.api_core.exceptions.NotFound("Cluster not found.") + mock_hook.return_value.update_cluster.side_effect = AirflowException( + f"Dependency: cluster '{CLUSTER_ID}' does not exist for instance '{INSTANCE_ID}'." ) op = BigtableUpdateClusterOperator( project_id=PROJECT_ID, @@ -483,8 +483,8 @@ def test_updating_cluster_that_does_not_exists(self, mock_hook): @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") def test_updating_cluster_that_does_not_exists_empty_project_id(self, mock_hook): instance = mock_hook.return_value.get_instance.return_value = mock.Mock(Instance) - mock_hook.return_value.update_cluster.side_effect = mock.Mock( - side_effect=google.api_core.exceptions.NotFound("Cluster not found.") + mock_hook.return_value.update_cluster.side_effect = AirflowException( + f"Dependency: cluster '{CLUSTER_ID}' does not exist for instance '{INSTANCE_ID}'." ) op = BigtableUpdateClusterOperator( instance_id=INSTANCE_ID, @@ -655,9 +655,6 @@ def test_deleting_table_that_doesnt_exists(self, mock_hook): impersonation_chain=IMPERSONATION_CHAIN, ) - mock_hook.return_value.delete_table.side_effect = mock.Mock( - side_effect=google.api_core.exceptions.NotFound("Table not found.") - ) op.execute(None) mock_hook.assert_called_once_with( gcp_conn_id=GCP_CONN_ID, @@ -677,9 +674,6 @@ def test_deleting_table_that_doesnt_exists_empty_project_id(self, mock_hook): impersonation_chain=IMPERSONATION_CHAIN, ) - mock_hook.return_value.delete_table.side_effect = mock.Mock( - side_effect=google.api_core.exceptions.NotFound("Table not found.") - ) op.execute(None) mock_hook.assert_called_once_with( gcp_conn_id=GCP_CONN_ID, From d0c7da1fb66ef01115c6cc9983839bd0ec708fe4 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 25 Jan 2026 21:31:19 +0530 Subject: [PATCH 09/24] handled tests part 3 --- .../src/airflow/providers/google/cloud/hooks/bigtable.py | 5 +++-- .../airflow/providers/google/cloud/operators/bigtable.py | 2 +- .../tests/unit/google/cloud/operators/test_bigtable.py | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 811a1ca814e09..a60c615c2ff6a 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -27,6 +27,7 @@ from google.cloud.bigtable.cluster import Cluster from google.cloud.bigtable.instance import Instance from google.cloud.bigtable.table import ClusterState, Table + from airflow.providers.common.compat.sdk import AirflowException from airflow.providers.google.common.consts import CLIENT_INFO from airflow.providers.google.common.hooks.base_google import GoogleBaseHook @@ -260,7 +261,7 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None self.log.info("The table '%s' no longer exists. Consider it as deleted", table_id) @staticmethod - def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: + def update_cluster(instance: Instance, instance_id: str, cluster_id: str, nodes: int) -> None: """ Update number of nodes in the specified Cloud Bigtable cluster. @@ -276,7 +277,7 @@ def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: cluster.reload() except google.api_core.exceptions.NotFound: raise AirflowException( - f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance.instance_id}'." + f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance_id}'." ) cluster.serve_nodes = nodes cluster.update() diff --git a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py index b0910e6049b5b..91655c516081a 100644 --- a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py @@ -584,5 +584,5 @@ def execute(self, context: Context) -> None: if not instance: raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") - hook.update_cluster(instance=instance, cluster_id=self.cluster_id, nodes=self.nodes) + hook.update_cluster(instance=instance, instance_id=self.instance_id, cluster_id=self.cluster_id, nodes=self.nodes) BigtableClusterLink.persist(context=context) diff --git a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py index c77337ee014bf..54410c13025eb 100644 --- a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py @@ -456,7 +456,7 @@ def test_updating_cluster_but_instance_does_not_exists_empty_project_id(self, mo def test_updating_cluster_that_does_not_exists(self, mock_hook): instance = mock_hook.return_value.get_instance.return_value = mock.Mock(Instance) mock_hook.return_value.update_cluster.side_effect = AirflowException( - f"Dependency: cluster '{CLUSTER_ID}' does not exist for instance '{INSTANCE_ID}'." + f"Dependency: cluster '{CLUSTER_ID}' does not exist for instance '{INSTANCE_ID}'." ) op = BigtableUpdateClusterOperator( project_id=PROJECT_ID, @@ -477,7 +477,7 @@ def test_updating_cluster_that_does_not_exists(self, mock_hook): impersonation_chain=IMPERSONATION_CHAIN, ) mock_hook.return_value.update_cluster.assert_called_once_with( - instance=instance, cluster_id=CLUSTER_ID, nodes=NODES + instance=instance, instance_id=INSTANCE_ID, cluster_id=CLUSTER_ID, nodes=NODES ) @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") @@ -504,7 +504,7 @@ def test_updating_cluster_that_does_not_exists_empty_project_id(self, mock_hook) impersonation_chain=IMPERSONATION_CHAIN, ) mock_hook.return_value.update_cluster.assert_called_once_with( - instance=instance, cluster_id=CLUSTER_ID, nodes=NODES + instance=instance, instance_id=INSTANCE_ID, cluster_id=CLUSTER_ID, nodes=NODES ) @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") @@ -531,7 +531,7 @@ def test_different_error_reraised(self, mock_hook): impersonation_chain=IMPERSONATION_CHAIN, ) mock_hook.return_value.update_cluster.assert_called_once_with( - instance=instance, cluster_id=CLUSTER_ID, nodes=NODES + instance=instance, instance_id=INSTANCE_ID, cluster_id=CLUSTER_ID, nodes=NODES ) From 33052b4ebbc02c5449d955f7c6143a8dbb487c91 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 25 Jan 2026 22:53:58 +0530 Subject: [PATCH 10/24] handled tests part 4 --- .../src/airflow/providers/google/cloud/operators/bigtable.py | 5 ++++- .../google/tests/unit/google/cloud/hooks/test_bigtable.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py index 91655c516081a..08145a61d2704 100644 --- a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py @@ -510,6 +510,7 @@ def execute(self, context: Context) -> None: table_id=self.table_id, ) + class BigtableUpdateClusterOperator(GoogleCloudBaseOperator, BigtableValidationMixin): """ Updates a Cloud Bigtable cluster. @@ -584,5 +585,7 @@ def execute(self, context: Context) -> None: if not instance: raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") - hook.update_cluster(instance=instance, instance_id=self.instance_id, cluster_id=self.cluster_id, nodes=self.nodes) + hook.update_cluster( + instance=instance, instance_id=self.instance_id, cluster_id=self.cluster_id, nodes=self.nodes + ) BigtableClusterLink.persist(context=context) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index d68da85e6d08f..70c7ca9e645f2 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -508,7 +508,7 @@ def test_update_cluster(self, get_client, reload, update): client = mock.Mock(Client) instance = google.cloud.bigtable.instance.Instance(instance_id=CBT_INSTANCE, client=client) self.bigtable_hook_default_project_id.update_cluster( - instance=instance, cluster_id=CBT_CLUSTER, nodes=4 + instance=instance, instance_id=CBT_INSTANCE, cluster_id=CBT_CLUSTER, nodes=4 ) get_client.assert_not_called() reload.assert_called_once_with() From 7b5261046be4016806d50bc05639ef1036b94cae Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 01:21:14 +0530 Subject: [PATCH 11/24] removed instance_id from parameter in update cluster --- .../src/airflow/providers/google/cloud/hooks/bigtable.py | 4 ++-- .../airflow/providers/google/cloud/operators/bigtable.py | 4 +--- .../google/tests/unit/google/cloud/hooks/test_bigtable.py | 2 +- .../tests/unit/google/cloud/operators/test_bigtable.py | 6 +++--- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index a60c615c2ff6a..8575ea8bc42c2 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -261,7 +261,7 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None self.log.info("The table '%s' no longer exists. Consider it as deleted", table_id) @staticmethod - def update_cluster(instance: Instance, instance_id: str, cluster_id: str, nodes: int) -> None: + def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: """ Update number of nodes in the specified Cloud Bigtable cluster. @@ -277,7 +277,7 @@ def update_cluster(instance: Instance, instance_id: str, cluster_id: str, nodes: cluster.reload() except google.api_core.exceptions.NotFound: raise AirflowException( - f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance_id}'." + f"Dependency: cluster '{cluster_id}' does not exist for instance '{instance.instance_id}'." ) cluster.serve_nodes = nodes cluster.update() diff --git a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py index 08145a61d2704..11e3ea8e5b569 100644 --- a/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/operators/bigtable.py @@ -585,7 +585,5 @@ def execute(self, context: Context) -> None: if not instance: raise AirflowException(f"Dependency: instance '{self.instance_id}' does not exist.") - hook.update_cluster( - instance=instance, instance_id=self.instance_id, cluster_id=self.cluster_id, nodes=self.nodes - ) + hook.update_cluster(instance=instance, cluster_id=self.cluster_id, nodes=self.nodes) BigtableClusterLink.persist(context=context) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index 70c7ca9e645f2..d68da85e6d08f 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -508,7 +508,7 @@ def test_update_cluster(self, get_client, reload, update): client = mock.Mock(Client) instance = google.cloud.bigtable.instance.Instance(instance_id=CBT_INSTANCE, client=client) self.bigtable_hook_default_project_id.update_cluster( - instance=instance, instance_id=CBT_INSTANCE, cluster_id=CBT_CLUSTER, nodes=4 + instance=instance, cluster_id=CBT_CLUSTER, nodes=4 ) get_client.assert_not_called() reload.assert_called_once_with() diff --git a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py index 54410c13025eb..02fdf3ae3461b 100644 --- a/providers/google/tests/unit/google/cloud/operators/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/operators/test_bigtable.py @@ -477,7 +477,7 @@ def test_updating_cluster_that_does_not_exists(self, mock_hook): impersonation_chain=IMPERSONATION_CHAIN, ) mock_hook.return_value.update_cluster.assert_called_once_with( - instance=instance, instance_id=INSTANCE_ID, cluster_id=CLUSTER_ID, nodes=NODES + instance=instance, cluster_id=CLUSTER_ID, nodes=NODES ) @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") @@ -504,7 +504,7 @@ def test_updating_cluster_that_does_not_exists_empty_project_id(self, mock_hook) impersonation_chain=IMPERSONATION_CHAIN, ) mock_hook.return_value.update_cluster.assert_called_once_with( - instance=instance, instance_id=INSTANCE_ID, cluster_id=CLUSTER_ID, nodes=NODES + instance=instance, cluster_id=CLUSTER_ID, nodes=NODES ) @mock.patch("airflow.providers.google.cloud.operators.bigtable.BigtableHook") @@ -531,7 +531,7 @@ def test_different_error_reraised(self, mock_hook): impersonation_chain=IMPERSONATION_CHAIN, ) mock_hook.return_value.update_cluster.assert_called_once_with( - instance=instance, instance_id=INSTANCE_ID, cluster_id=CLUSTER_ID, nodes=NODES + instance=instance, cluster_id=CLUSTER_ID, nodes=NODES ) From 324e49232686f1b7860a92d8fdb91ed0f7db3282 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 01:44:47 +0530 Subject: [PATCH 12/24] added unit test for update cluster which does not exists in hooks bigtable --- .../unit/google/cloud/hooks/test_bigtable.py | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index d68da85e6d08f..7d63dc28791cb 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -26,7 +26,8 @@ from airflow.providers.google.cloud.hooks.bigtable import BigtableHook from airflow.providers.google.common.consts import CLIENT_INFO - +from airflow.exceptions import AirflowException +import pytest from unit.google.cloud.utils.base_gcp_mock import ( GCP_PROJECT_ID_HOOK_UNIT_TEST, mock_base_gcp_hook_default_project_id, @@ -514,6 +515,30 @@ def test_update_cluster(self, get_client, reload, update): reload.assert_called_once_with() update.assert_called_once_with() + @mock.patch("google.cloud.bigtable.cluster.Cluster.update") + @mock.patch("google.cloud.bigtable.cluster.Cluster.reload") + @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") + def test_update_cluster_does_not_exist(self, get_client, reload, update): + instance_method = get_client.return_value.instance + instance_method = instance_method.return_value + instance_exists_method = instance_method.exists + instance_exists_method.return_value = True + reload.side_effect = google.api_core.exceptions.NotFound("Cluster not found") + client = mock.Mock(Client) + instance = google.cloud.bigtable.instance.Instance(instance_id=CBT_INSTANCE, client=client) + with pytest.raises( + AirflowException, + match=f"Dependency: cluster '{CBT_CLUSTER}' does not exist for instance '{CBT_INSTANCE}'.", + ): + self.bigtable_hook_default_project_id.update_cluster( + instance=instance, + cluster_id=CBT_CLUSTER, + nodes=4, + ) + get_client.assert_not_called() + reload.assert_called_once_with() + update.assert_not_called() + @mock.patch("google.cloud.bigtable.table.Table.list_column_families") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") def test_list_column_families(self, get_client, list_column_families): From 127248196746a929d7b3ac3763a7d00e716418db Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 01:57:10 +0530 Subject: [PATCH 13/24] removed the parameter mock_project_id from test_delete_table as it is not used. in hooks test_bigtable.py --- providers/google/tests/unit/google/cloud/hooks/test_bigtable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index 7d63dc28791cb..11516573b12bf 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -460,7 +460,7 @@ def test_create_instance_overridden_project_id(self, get_client, instance_create return_value=GCP_PROJECT_ID_HOOK_UNIT_TEST, ) @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table(self, get_client, mock_project_id): + def test_delete_table(self, get_client): instance_method = get_client.return_value.instance instance_exists_method = instance_method.return_value.exists table_delete_method = instance_method.return_value.table.return_value.delete From 8083d056f575a0b7c1048851ef7d812c3ae015ef Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 02:05:28 +0530 Subject: [PATCH 14/24] added unit test for delete table when not exists in hooks test_bigtable.py --- .../unit/google/cloud/hooks/test_bigtable.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index 11516573b12bf..ad1f36a5ec95e 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -487,6 +487,23 @@ def test_delete_table_overridden_project_id(self, get_client): instance_exists_method.assert_called_once_with() table_delete_method.assert_called_once_with() + @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") + def test_delete_table_when_no_table_exists(self, get_client): + instance_method = get_client.return_value.instance + instance_exists_method = instance_method.return_value.exists + table_method = instance_method.return_value.table + table_delete_method = table_method.return_value.delete + instance_exists_method.return_value = True + table_delete_method.side_effect = google.api_core.exceptions.NotFound("Table not found") + self.bigtable_hook_default_project_id.delete_table( + instance_id=CBT_INSTANCE, + table_id=CBT_TABLE, + ) + get_client.assert_called_once_with(project_id=None) + instance_exists_method.assert_called_once_with() + table_method.assert_called_once_with(table_id=CBT_TABLE) + table_delete_method.assert_called_once_with() + @mock.patch("google.cloud.bigtable.table.Table.create") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") def test_create_table(self, get_client, create): From 53f1abb9499039b6b335b08f72f06573cffbd586 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 11:18:06 +0530 Subject: [PATCH 15/24] added mock validation in test_bigtable hook --- .../tests/unit/google/cloud/hooks/test_bigtable.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index ad1f36a5ec95e..f9c31a0d7b5ae 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -21,13 +21,14 @@ from unittest.mock import PropertyMock import google +import pytest from google.cloud.bigtable import Client, enums from google.cloud.bigtable.instance import Instance +from airflow.exceptions import AirflowException from airflow.providers.google.cloud.hooks.bigtable import BigtableHook from airflow.providers.google.common.consts import CLIENT_INFO -from airflow.exceptions import AirflowException -import pytest + from unit.google.cloud.utils.base_gcp_mock import ( GCP_PROJECT_ID_HOOK_UNIT_TEST, mock_base_gcp_hook_default_project_id, @@ -460,7 +461,7 @@ def test_create_instance_overridden_project_id(self, get_client, instance_create return_value=GCP_PROJECT_ID_HOOK_UNIT_TEST, ) @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table(self, get_client): + def test_delete_table(self, get_client, mock_project_id): instance_method = get_client.return_value.instance instance_exists_method = instance_method.return_value.exists table_delete_method = instance_method.return_value.table.return_value.delete @@ -474,8 +475,10 @@ def test_delete_table(self, get_client): instance_exists_method.assert_called_once_with() table_delete_method.assert_called_once_with() + @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook.get_credentials") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table_overridden_project_id(self, get_client): + def test_delete_table_overridden_project_id(self, get_client, mock_get_creds): + mock_get_creds.return_value = mock.Mock() instance_method = get_client.return_value.instance instance_exists_method = instance_method.return_value.exists table_delete_method = instance_method.return_value.table.return_value.delete From e30d0aa82fdf6a90f45f7c6c55064b68e3de9855 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 12:01:46 +0530 Subject: [PATCH 16/24] modified test_delete_table_when_no_table_exists for mock credentials --- .../google/tests/unit/google/cloud/hooks/test_bigtable.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index f9c31a0d7b5ae..e152a2e4c6b4f 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -475,10 +475,8 @@ def test_delete_table(self, get_client, mock_project_id): instance_exists_method.assert_called_once_with() table_delete_method.assert_called_once_with() - @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook.get_credentials") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table_overridden_project_id(self, get_client, mock_get_creds): - mock_get_creds.return_value = mock.Mock() + def test_delete_table_overridden_project_id(self, get_client): instance_method = get_client.return_value.instance instance_exists_method = instance_method.return_value.exists table_delete_method = instance_method.return_value.table.return_value.delete @@ -490,8 +488,10 @@ def test_delete_table_overridden_project_id(self, get_client, mock_get_creds): instance_exists_method.assert_called_once_with() table_delete_method.assert_called_once_with() + @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook.get_credentials") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table_when_no_table_exists(self, get_client): + def test_delete_table_when_no_table_exists(self, get_client, mock_get_creds): + mock_get_creds.return_value = mock.Mock() instance_method = get_client.return_value.instance instance_exists_method = instance_method.return_value.exists table_method = instance_method.return_value.table From 5b74d5b4f81a47676484150f0f7294c7b7274a82 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 12:33:23 +0530 Subject: [PATCH 17/24] test_delete_table_when_no_table_exists modified it --- .../unit/google/cloud/hooks/test_bigtable.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index e152a2e4c6b4f..8680b1f51ea77 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -490,22 +490,22 @@ def test_delete_table_overridden_project_id(self, get_client): @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook.get_credentials") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table_when_no_table_exists(self, get_client, mock_get_creds): + def test_delete_table_when_no_table_exists(self, mock_get_client, mock_get_creds): mock_get_creds.return_value = mock.Mock() - instance_method = get_client.return_value.instance - instance_exists_method = instance_method.return_value.exists - table_method = instance_method.return_value.table - table_delete_method = table_method.return_value.delete - instance_exists_method.return_value = True - table_delete_method.side_effect = google.api_core.exceptions.NotFound("Table not found") + mock_client = mock.Mock() + mock_get_client.return_value = mock_client + instance = mock_client.instance.return_value + instance.exists.return_value = True + table = instance.table.return_value + table.delete.side_effect = google.api_core.exceptions.NotFound("Table not found") self.bigtable_hook_default_project_id.delete_table( instance_id=CBT_INSTANCE, table_id=CBT_TABLE, ) - get_client.assert_called_once_with(project_id=None) - instance_exists_method.assert_called_once_with() - table_method.assert_called_once_with(table_id=CBT_TABLE) - table_delete_method.assert_called_once_with() + mock_get_client.assert_called_once_with(project_id=None) + instance.exists.assert_called_once_with() + instance.table.assert_called_once_with(table_id=CBT_TABLE) + table.delete.assert_called_once_with() @mock.patch("google.cloud.bigtable.table.Table.create") @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") From 331b627165d63893090270b837fc53a088806810 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 20:23:10 +0530 Subject: [PATCH 18/24] handled CI failures for table delete when no table exists hooks/test_bigtable.py --- .../google/tests/unit/google/cloud/hooks/test_bigtable.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index 8680b1f51ea77..9827cdd1c6214 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -488,10 +488,12 @@ def test_delete_table_overridden_project_id(self, get_client): instance_exists_method.assert_called_once_with() table_delete_method.assert_called_once_with() - @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook.get_credentials") + @mock.patch( + "airflow.providers.google.common.hooks.base_google.GoogleBaseHook.get_credentials_and_project_id" + ) @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") - def test_delete_table_when_no_table_exists(self, mock_get_client, mock_get_creds): - mock_get_creds.return_value = mock.Mock() + def test_delete_table_when_no_table_exists(self, mock_get_client, mock_get_creds_and_project): + mock_get_creds_and_project.return_value = (mock.Mock(), None) mock_client = mock.Mock() mock_get_client.return_value = mock_client instance = mock_client.instance.return_value From 79fb50b12d738f75f25f29717b92a16b75cb22dc Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Thu, 29 Jan 2026 21:40:15 +0530 Subject: [PATCH 19/24] added the mock project id for test_delete_table_when_no_table_exists in hooks/test_bigtable.py --- .../google/tests/unit/google/cloud/hooks/test_bigtable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py index 9827cdd1c6214..da013a23b6309 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigtable.py @@ -493,7 +493,7 @@ def test_delete_table_overridden_project_id(self, get_client): ) @mock.patch("airflow.providers.google.cloud.hooks.bigtable.BigtableHook._get_client") def test_delete_table_when_no_table_exists(self, mock_get_client, mock_get_creds_and_project): - mock_get_creds_and_project.return_value = (mock.Mock(), None) + mock_get_creds_and_project.return_value = (mock.Mock(), "test-project") mock_client = mock.Mock() mock_get_client.return_value = mock_client instance = mock_client.instance.return_value @@ -504,7 +504,7 @@ def test_delete_table_when_no_table_exists(self, mock_get_client, mock_get_creds instance_id=CBT_INSTANCE, table_id=CBT_TABLE, ) - mock_get_client.assert_called_once_with(project_id=None) + mock_get_client.assert_called_once_with(project_id="test-project") instance.exists.assert_called_once_with() instance.table.assert_called_once_with(table_id=CBT_TABLE) table.delete.assert_called_once_with() From e209a9798b27033a375b1107065ac18740ca59bf Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 31 Jan 2026 19:20:25 +0530 Subject: [PATCH 20/24] modified docstrings --- .../airflow/providers/google/cloud/hooks/bigtable.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 8575ea8bc42c2..48735dffa8c9a 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -88,9 +88,7 @@ def get_instance(self, instance_id: str, project_id: str) -> Instance | None: def delete_instance(self, instance_id: str, project_id: str) -> None: """ Delete the specified Cloud Bigtable instance. - - Raises google.api_core.exceptions.NotFound if the Cloud Bigtable instance does - not exist. + If the instance does not exist, logs a warning message and exits. :param project_id: Optional, Google Cloud project ID where the BigTable exists. If set to None or missing, @@ -241,8 +239,8 @@ def create_table( def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None: """ Delete the specified table in Cloud Bigtable. - - Raises google.api_core.exceptions.NotFound if the table does not exist. + If the instance does not exist, raises RuntimeError. + If the table does not exist, logs a warning message and exits. :param instance_id: The ID of the Cloud Bigtable instance. :param table_id: The ID of the table in Cloud Bigtable. @@ -265,7 +263,7 @@ def update_cluster(instance: Instance, cluster_id: str, nodes: int) -> None: """ Update number of nodes in the specified Cloud Bigtable cluster. - Raises google.api_core.exceptions.NotFound if the cluster does not exist. + If the cluster does not exist, raises AirflowException. :param instance: The Cloud Bigtable instance that owns the cluster. :param cluster_id: The ID of the cluster. From 90c7d449e03850b0b9f4711a7bea8ea91331b0d0 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 31 Jan 2026 20:36:58 +0530 Subject: [PATCH 21/24] prek run --- .../google/src/airflow/providers/google/cloud/hooks/bigtable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 48735dffa8c9a..8989d2aadf864 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -240,7 +240,7 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None """ Delete the specified table in Cloud Bigtable. If the instance does not exist, raises RuntimeError. - If the table does not exist, logs a warning message and exits. + If the table does not exist, logs a warning message and returns. :param instance_id: The ID of the Cloud Bigtable instance. :param table_id: The ID of the table in Cloud Bigtable. From 599fefea39fec00ecc43188ba2b84f882765fc4b Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sat, 31 Jan 2026 21:05:10 +0530 Subject: [PATCH 22/24] prek run part 2 --- .../google/src/airflow/providers/google/cloud/hooks/bigtable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 8989d2aadf864..5e45e18d1daae 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -95,6 +95,7 @@ def delete_instance(self, instance_id: str, project_id: str) -> None: the default project_id from the Google Cloud connection is used. :param instance_id: The ID of the Cloud Bigtable instance. """ + instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance: instance.delete() @@ -248,6 +249,7 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None BigTable exists. If set to None or missing, the default project_id from the Google Cloud connection is used. """ + instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance is None: raise RuntimeError(f"Instance {instance_id} did not exist; unable to delete table {table_id}") From 7701c29d08652b3937f1e682bb0166d6a35735b6 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 1 Feb 2026 00:23:47 +0530 Subject: [PATCH 23/24] fixed d205 docstring error --- .../google/src/airflow/providers/google/cloud/hooks/bigtable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 5e45e18d1daae..9c572dd22f7b0 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -88,6 +88,7 @@ def get_instance(self, instance_id: str, project_id: str) -> Instance | None: def delete_instance(self, instance_id: str, project_id: str) -> None: """ Delete the specified Cloud Bigtable instance. + If the instance does not exist, logs a warning message and exits. :param project_id: Optional, Google Cloud project ID where the @@ -240,6 +241,7 @@ def create_table( def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None: """ Delete the specified table in Cloud Bigtable. + If the instance does not exist, raises RuntimeError. If the table does not exist, logs a warning message and returns. From 33dee893a8f6629147de700a7d2fda9747cd3258 Mon Sep 17 00:00:00 2001 From: Kamran-imaz Date: Sun, 1 Feb 2026 00:25:46 +0530 Subject: [PATCH 24/24] final fix D205 docs string error --- .../src/airflow/providers/google/cloud/hooks/bigtable.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py index 9c572dd22f7b0..1a302eeb8252c 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/bigtable.py @@ -96,7 +96,6 @@ def delete_instance(self, instance_id: str, project_id: str) -> None: the default project_id from the Google Cloud connection is used. :param instance_id: The ID of the Cloud Bigtable instance. """ - instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance: instance.delete() @@ -241,7 +240,7 @@ def create_table( def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None: """ Delete the specified table in Cloud Bigtable. - + If the instance does not exist, raises RuntimeError. If the table does not exist, logs a warning message and returns. @@ -251,7 +250,6 @@ def delete_table(self, instance_id: str, table_id: str, project_id: str) -> None BigTable exists. If set to None or missing, the default project_id from the Google Cloud connection is used. """ - instance = self.get_instance(instance_id=instance_id, project_id=project_id) if instance is None: raise RuntimeError(f"Instance {instance_id} did not exist; unable to delete table {table_id}")