apache-airflow-providers-google 10.17.0rc1__py3-none-any.whl → 10.18.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. airflow/providers/google/__init__.py +5 -8
  2. airflow/providers/google/cloud/hooks/automl.py +35 -1
  3. airflow/providers/google/cloud/hooks/bigquery.py +126 -41
  4. airflow/providers/google/cloud/hooks/cloud_composer.py +250 -2
  5. airflow/providers/google/cloud/hooks/cloud_sql.py +154 -7
  6. airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +7 -2
  7. airflow/providers/google/cloud/hooks/compute_ssh.py +2 -1
  8. airflow/providers/google/cloud/hooks/dataflow.py +246 -32
  9. airflow/providers/google/cloud/hooks/dataplex.py +6 -2
  10. airflow/providers/google/cloud/hooks/dlp.py +14 -14
  11. airflow/providers/google/cloud/hooks/gcs.py +6 -2
  12. airflow/providers/google/cloud/hooks/gdm.py +2 -2
  13. airflow/providers/google/cloud/hooks/kubernetes_engine.py +2 -2
  14. airflow/providers/google/cloud/hooks/mlengine.py +8 -4
  15. airflow/providers/google/cloud/hooks/pubsub.py +1 -1
  16. airflow/providers/google/cloud/hooks/secret_manager.py +252 -4
  17. airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +1431 -74
  18. airflow/providers/google/cloud/hooks/vertex_ai/prediction_service.py +91 -0
  19. airflow/providers/google/cloud/links/vertex_ai.py +2 -1
  20. airflow/providers/google/cloud/log/gcs_task_handler.py +2 -1
  21. airflow/providers/google/cloud/operators/automl.py +243 -37
  22. airflow/providers/google/cloud/operators/bigquery.py +164 -62
  23. airflow/providers/google/cloud/operators/bigquery_dts.py +4 -3
  24. airflow/providers/google/cloud/operators/bigtable.py +7 -6
  25. airflow/providers/google/cloud/operators/cloud_build.py +12 -11
  26. airflow/providers/google/cloud/operators/cloud_composer.py +147 -2
  27. airflow/providers/google/cloud/operators/cloud_memorystore.py +17 -16
  28. airflow/providers/google/cloud/operators/cloud_sql.py +60 -17
  29. airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +35 -16
  30. airflow/providers/google/cloud/operators/compute.py +12 -11
  31. airflow/providers/google/cloud/operators/datacatalog.py +21 -20
  32. airflow/providers/google/cloud/operators/dataflow.py +59 -42
  33. airflow/providers/google/cloud/operators/datafusion.py +11 -10
  34. airflow/providers/google/cloud/operators/datapipeline.py +3 -2
  35. airflow/providers/google/cloud/operators/dataprep.py +5 -4
  36. airflow/providers/google/cloud/operators/dataproc.py +20 -17
  37. airflow/providers/google/cloud/operators/datastore.py +8 -7
  38. airflow/providers/google/cloud/operators/dlp.py +31 -30
  39. airflow/providers/google/cloud/operators/functions.py +4 -3
  40. airflow/providers/google/cloud/operators/gcs.py +66 -41
  41. airflow/providers/google/cloud/operators/kubernetes_engine.py +256 -49
  42. airflow/providers/google/cloud/operators/life_sciences.py +2 -1
  43. airflow/providers/google/cloud/operators/mlengine.py +11 -10
  44. airflow/providers/google/cloud/operators/pubsub.py +6 -5
  45. airflow/providers/google/cloud/operators/spanner.py +7 -6
  46. airflow/providers/google/cloud/operators/speech_to_text.py +2 -1
  47. airflow/providers/google/cloud/operators/stackdriver.py +11 -10
  48. airflow/providers/google/cloud/operators/tasks.py +14 -13
  49. airflow/providers/google/cloud/operators/text_to_speech.py +2 -1
  50. airflow/providers/google/cloud/operators/translate_speech.py +2 -1
  51. airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +333 -26
  52. airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +20 -12
  53. airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +0 -1
  54. airflow/providers/google/cloud/operators/vision.py +13 -12
  55. airflow/providers/google/cloud/operators/workflows.py +12 -14
  56. airflow/providers/google/cloud/secrets/secret_manager.py +2 -1
  57. airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -1
  58. airflow/providers/google/cloud/sensors/bigtable.py +2 -1
  59. airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -1
  60. airflow/providers/google/cloud/sensors/dataflow.py +239 -52
  61. airflow/providers/google/cloud/sensors/datafusion.py +2 -1
  62. airflow/providers/google/cloud/sensors/dataproc.py +3 -2
  63. airflow/providers/google/cloud/sensors/gcs.py +14 -12
  64. airflow/providers/google/cloud/sensors/tasks.py +2 -1
  65. airflow/providers/google/cloud/sensors/workflows.py +2 -1
  66. airflow/providers/google/cloud/transfers/adls_to_gcs.py +8 -2
  67. airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +7 -1
  68. airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +7 -1
  69. airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +2 -1
  70. airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +1 -1
  71. airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -0
  72. airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +5 -6
  73. airflow/providers/google/cloud/transfers/gcs_to_gcs.py +22 -12
  74. airflow/providers/google/cloud/triggers/bigquery.py +75 -6
  75. airflow/providers/google/cloud/triggers/cloud_composer.py +68 -0
  76. airflow/providers/google/cloud/triggers/cloud_sql.py +2 -1
  77. airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +2 -1
  78. airflow/providers/google/cloud/triggers/dataflow.py +504 -4
  79. airflow/providers/google/cloud/triggers/dataproc.py +190 -27
  80. airflow/providers/google/cloud/triggers/kubernetes_engine.py +2 -3
  81. airflow/providers/google/cloud/triggers/mlengine.py +2 -1
  82. airflow/providers/google/cloud/triggers/vertex_ai.py +94 -0
  83. airflow/providers/google/common/hooks/base_google.py +45 -7
  84. airflow/providers/google/firebase/hooks/firestore.py +2 -2
  85. airflow/providers/google/firebase/operators/firestore.py +2 -1
  86. airflow/providers/google/get_provider_info.py +5 -3
  87. {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0.dist-info}/METADATA +18 -18
  88. {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0.dist-info}/RECORD +90 -90
  89. airflow/providers/google/cloud/example_dags/example_cloud_sql_query.py +0 -289
  90. {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0.dist-info}/WHEEL +0 -0
  91. {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0.dist-info}/entry_points.txt +0 -0
@@ -19,7 +19,6 @@
19
19
 
20
20
  from __future__ import annotations
21
21
 
22
- import re
23
22
  import warnings
24
23
  from functools import cached_property
25
24
  from typing import TYPE_CHECKING, Any, Sequence
@@ -29,13 +28,13 @@ import yaml
29
28
  from deprecated import deprecated
30
29
  from google.api_core.exceptions import AlreadyExists
31
30
  from google.cloud.container_v1.types import Cluster
32
- from kubernetes.client import V1JobList
31
+ from kubernetes.client import V1JobList, models as k8s
33
32
  from kubernetes.utils.create_from_yaml import FailToCreateError
34
33
  from packaging.version import parse as parse_version
35
34
 
36
35
  from airflow.configuration import conf
37
36
  from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
38
- from airflow.providers.cncf.kubernetes.operators.job import KubernetesDeleteJobOperator, KubernetesJobOperator
37
+ from airflow.providers.cncf.kubernetes.operators.job import KubernetesJobOperator
39
38
  from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
40
39
  from airflow.providers.cncf.kubernetes.operators.resource import (
41
40
  KubernetesCreateResourceOperator,
@@ -43,11 +42,8 @@ from airflow.providers.cncf.kubernetes.operators.resource import (
43
42
  )
44
43
  from airflow.providers.cncf.kubernetes.utils.pod_manager import OnFinishAction
45
44
  from airflow.providers.google.cloud.hooks.kubernetes_engine import (
46
- GKECustomResourceHook,
47
- GKEDeploymentHook,
48
45
  GKEHook,
49
- GKEJobHook,
50
- GKEPodHook,
46
+ GKEKubernetesHook,
51
47
  )
52
48
  from airflow.providers.google.cloud.links.kubernetes_engine import (
53
49
  KubernetesEngineClusterLink,
@@ -61,9 +57,20 @@ from airflow.providers.google.cloud.triggers.kubernetes_engine import (
61
57
  GKEOperationTrigger,
62
58
  GKEStartPodTrigger,
63
59
  )
60
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
64
61
  from airflow.providers_manager import ProvidersManager
65
62
  from airflow.utils.timezone import utcnow
66
63
 
64
+ try:
65
+ from airflow.providers.cncf.kubernetes.operators.job import KubernetesDeleteJobOperator
66
+ except ImportError:
67
+ from airflow.exceptions import AirflowOptionalProviderFeatureException
68
+
69
+ raise AirflowOptionalProviderFeatureException(
70
+ "Failed to import KubernetesDeleteJobOperator. This operator is only available in cncf-kubernetes "
71
+ "provider version >=8.1.0"
72
+ )
73
+
67
74
  if TYPE_CHECKING:
68
75
  from kubernetes.client.models import V1Job, V1Pod
69
76
 
@@ -166,7 +173,7 @@ class GKEDeleteClusterOperator(GoogleCloudBaseOperator):
166
173
  *,
167
174
  name: str,
168
175
  location: str,
169
- project_id: str | None = None,
176
+ project_id: str = PROVIDE_PROJECT_ID,
170
177
  gcp_conn_id: str = "google_cloud_default",
171
178
  api_version: str = "v2",
172
179
  impersonation_chain: str | Sequence[str] | None = None,
@@ -310,7 +317,7 @@ class GKECreateClusterOperator(GoogleCloudBaseOperator):
310
317
  *,
311
318
  location: str,
312
319
  body: dict | Cluster,
313
- project_id: str | None = None,
320
+ project_id: str = PROVIDE_PROJECT_ID,
314
321
  gcp_conn_id: str = "google_cloud_default",
315
322
  api_version: str = "v2",
316
323
  impersonation_chain: str | Sequence[str] | None = None,
@@ -496,7 +503,7 @@ class GKEStartKueueInsideClusterOperator(GoogleCloudBaseOperator):
496
503
  cluster_name: str,
497
504
  kueue_version: str,
498
505
  use_internal_ip: bool = False,
499
- project_id: str | None = None,
506
+ project_id: str = PROVIDE_PROJECT_ID,
500
507
  gcp_conn_id: str = "google_cloud_default",
501
508
  impersonation_chain: str | Sequence[str] | None = None,
502
509
  **kwargs,
@@ -522,13 +529,13 @@ class GKEStartKueueInsideClusterOperator(GoogleCloudBaseOperator):
522
529
  )
523
530
 
524
531
  @cached_property
525
- def deployment_hook(self) -> GKEDeploymentHook:
532
+ def deployment_hook(self) -> GKEKubernetesHook:
526
533
  if self._cluster_url is None or self._ssl_ca_cert is None:
527
534
  raise AttributeError(
528
- "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
535
+ "Cluster url and ssl_ca_cert should be defined before using self.deployment_hook method. "
529
536
  "Try to use self.get_kube_creds method",
530
537
  )
531
- return GKEDeploymentHook(
538
+ return GKEKubernetesHook(
532
539
  gcp_conn_id=self.gcp_conn_id,
533
540
  impersonation_chain=self.impersonation_chain,
534
541
  cluster_url=self._cluster_url,
@@ -536,13 +543,14 @@ class GKEStartKueueInsideClusterOperator(GoogleCloudBaseOperator):
536
543
  )
537
544
 
538
545
  @cached_property
539
- def pod_hook(self) -> GKEPodHook:
546
+ def pod_hook(self) -> GKEKubernetesHook:
540
547
  if self._cluster_url is None or self._ssl_ca_cert is None:
541
548
  raise AttributeError(
542
- "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
549
+ "Cluster url and ssl_ca_cert should be defined before using self.pod_hook method. "
543
550
  "Try to use self.get_kube_creds method",
544
551
  )
545
- return GKEPodHook(
552
+
553
+ return GKEKubernetesHook(
546
554
  gcp_conn_id=self.gcp_conn_id,
547
555
  impersonation_chain=self.impersonation_chain,
548
556
  cluster_url=self._cluster_url,
@@ -554,17 +562,10 @@ class GKEStartKueueInsideClusterOperator(GoogleCloudBaseOperator):
554
562
  def _get_yaml_content_from_file(kueue_yaml_url) -> list[dict]:
555
563
  """Download content of YAML file and separate it into several dictionaries."""
556
564
  response = requests.get(kueue_yaml_url, allow_redirects=True)
557
- yaml_dicts = []
558
- if response.status_code == 200:
559
- yaml_data = response.text
560
- documents = re.split(r"---\n", yaml_data)
561
-
562
- for document in documents:
563
- document_dict = yaml.safe_load(document)
564
- yaml_dicts.append(document_dict)
565
- else:
565
+ if response.status_code != 200:
566
566
  raise AirflowException("Was not able to read the yaml file from given URL")
567
- return yaml_dicts
567
+
568
+ return list(yaml.safe_load_all(response.text))
568
569
 
569
570
  def execute(self, context: Context):
570
571
  self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
@@ -658,7 +659,7 @@ class GKEStartPodOperator(KubernetesPodOperator):
658
659
  location: str,
659
660
  cluster_name: str,
660
661
  use_internal_ip: bool = False,
661
- project_id: str | None = None,
662
+ project_id: str = PROVIDE_PROJECT_ID,
662
663
  gcp_conn_id: str = "google_cloud_default",
663
664
  impersonation_chain: str | Sequence[str] | None = None,
664
665
  regional: bool | None = None,
@@ -738,21 +739,20 @@ class GKEStartPodOperator(KubernetesPodOperator):
738
739
  )
739
740
 
740
741
  @cached_property
741
- def hook(self) -> GKEPodHook:
742
+ def hook(self) -> GKEKubernetesHook:
742
743
  if self._cluster_url is None or self._ssl_ca_cert is None:
743
744
  raise AttributeError(
744
745
  "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
745
746
  "Try to use self.get_kube_creds method",
746
747
  )
747
748
 
748
- hook = GKEPodHook(
749
+ return GKEKubernetesHook(
749
750
  gcp_conn_id=self.gcp_conn_id,
750
751
  cluster_url=self._cluster_url,
751
752
  ssl_ca_cert=self._ssl_ca_cert,
752
753
  impersonation_chain=self.impersonation_chain,
753
754
  enable_tcp_keepalive=True,
754
755
  )
755
- return hook
756
756
 
757
757
  def execute(self, context: Context):
758
758
  """Execute process of creating pod and executing provided command inside it."""
@@ -856,7 +856,7 @@ class GKEStartJobOperator(KubernetesJobOperator):
856
856
  location: str,
857
857
  cluster_name: str,
858
858
  use_internal_ip: bool = False,
859
- project_id: str | None = None,
859
+ project_id: str = PROVIDE_PROJECT_ID,
860
860
  gcp_conn_id: str = "google_cloud_default",
861
861
  impersonation_chain: str | Sequence[str] | None = None,
862
862
  deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
@@ -897,19 +897,18 @@ class GKEStartJobOperator(KubernetesJobOperator):
897
897
  )
898
898
 
899
899
  @cached_property
900
- def hook(self) -> GKEJobHook:
900
+ def hook(self) -> GKEKubernetesHook:
901
901
  if self._cluster_url is None or self._ssl_ca_cert is None:
902
902
  raise AttributeError(
903
903
  "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
904
904
  "Try to use self.get_kube_creds method",
905
905
  )
906
906
 
907
- hook = GKEJobHook(
907
+ return GKEKubernetesHook(
908
908
  gcp_conn_id=self.gcp_conn_id,
909
909
  cluster_url=self._cluster_url,
910
910
  ssl_ca_cert=self._ssl_ca_cert,
911
911
  )
912
- return hook
913
912
 
914
913
  def execute(self, context: Context):
915
914
  """Execute process of creating Job."""
@@ -993,7 +992,7 @@ class GKEDescribeJobOperator(GoogleCloudBaseOperator):
993
992
  location: str,
994
993
  namespace: str,
995
994
  cluster_name: str,
996
- project_id: str | None = None,
995
+ project_id: str = PROVIDE_PROJECT_ID,
997
996
  use_internal_ip: bool = False,
998
997
  gcp_conn_id: str = "google_cloud_default",
999
998
  impersonation_chain: str | Sequence[str] | None = None,
@@ -1023,7 +1022,7 @@ class GKEDescribeJobOperator(GoogleCloudBaseOperator):
1023
1022
  )
1024
1023
 
1025
1024
  @cached_property
1026
- def hook(self) -> GKEJobHook:
1025
+ def hook(self) -> GKEKubernetesHook:
1027
1026
  self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
1028
1027
  cluster_name=self.cluster_name,
1029
1028
  project_id=self.project_id,
@@ -1031,7 +1030,7 @@ class GKEDescribeJobOperator(GoogleCloudBaseOperator):
1031
1030
  cluster_hook=self.cluster_hook,
1032
1031
  ).fetch_cluster_info()
1033
1032
 
1034
- return GKEJobHook(
1033
+ return GKEKubernetesHook(
1035
1034
  gcp_conn_id=self.gcp_conn_id,
1036
1035
  cluster_url=self._cluster_url,
1037
1036
  ssl_ca_cert=self._ssl_ca_cert,
@@ -1094,7 +1093,7 @@ class GKEListJobsOperator(GoogleCloudBaseOperator):
1094
1093
  location: str,
1095
1094
  cluster_name: str,
1096
1095
  namespace: str | None = None,
1097
- project_id: str | None = None,
1096
+ project_id: str = PROVIDE_PROJECT_ID,
1098
1097
  use_internal_ip: bool = False,
1099
1098
  do_xcom_push: bool = True,
1100
1099
  gcp_conn_id: str = "google_cloud_default",
@@ -1124,7 +1123,7 @@ class GKEListJobsOperator(GoogleCloudBaseOperator):
1124
1123
  )
1125
1124
 
1126
1125
  @cached_property
1127
- def hook(self) -> GKEJobHook:
1126
+ def hook(self) -> GKEKubernetesHook:
1128
1127
  self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
1129
1128
  cluster_name=self.cluster_name,
1130
1129
  project_id=self.project_id,
@@ -1132,7 +1131,7 @@ class GKEListJobsOperator(GoogleCloudBaseOperator):
1132
1131
  cluster_hook=self.cluster_hook,
1133
1132
  ).fetch_cluster_info()
1134
1133
 
1135
- return GKEJobHook(
1134
+ return GKEKubernetesHook(
1136
1135
  gcp_conn_id=self.gcp_conn_id,
1137
1136
  cluster_url=self._cluster_url,
1138
1137
  ssl_ca_cert=self._ssl_ca_cert,
@@ -1194,7 +1193,7 @@ class GKECreateCustomResourceOperator(KubernetesCreateResourceOperator):
1194
1193
  location: str,
1195
1194
  cluster_name: str,
1196
1195
  use_internal_ip: bool = False,
1197
- project_id: str | None = None,
1196
+ project_id: str = PROVIDE_PROJECT_ID,
1198
1197
  gcp_conn_id: str = "google_cloud_default",
1199
1198
  impersonation_chain: str | Sequence[str] | None = None,
1200
1199
  **kwargs,
@@ -1230,13 +1229,13 @@ class GKECreateCustomResourceOperator(KubernetesCreateResourceOperator):
1230
1229
  )
1231
1230
 
1232
1231
  @cached_property
1233
- def hook(self) -> GKECustomResourceHook:
1232
+ def hook(self) -> GKEKubernetesHook:
1234
1233
  if self._cluster_url is None or self._ssl_ca_cert is None:
1235
1234
  raise AttributeError(
1236
1235
  "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
1237
1236
  "Try to use self.get_kube_creds method",
1238
1237
  )
1239
- return GKECustomResourceHook(
1238
+ return GKEKubernetesHook(
1240
1239
  gcp_conn_id=self.gcp_conn_id,
1241
1240
  cluster_url=self._cluster_url,
1242
1241
  ssl_ca_cert=self._ssl_ca_cert,
@@ -1296,7 +1295,7 @@ class GKEDeleteCustomResourceOperator(KubernetesDeleteResourceOperator):
1296
1295
  location: str,
1297
1296
  cluster_name: str,
1298
1297
  use_internal_ip: bool = False,
1299
- project_id: str | None = None,
1298
+ project_id: str = PROVIDE_PROJECT_ID,
1300
1299
  gcp_conn_id: str = "google_cloud_default",
1301
1300
  impersonation_chain: str | Sequence[str] | None = None,
1302
1301
  **kwargs,
@@ -1332,13 +1331,13 @@ class GKEDeleteCustomResourceOperator(KubernetesDeleteResourceOperator):
1332
1331
  )
1333
1332
 
1334
1333
  @cached_property
1335
- def hook(self) -> GKECustomResourceHook:
1334
+ def hook(self) -> GKEKubernetesHook:
1336
1335
  if self._cluster_url is None or self._ssl_ca_cert is None:
1337
1336
  raise AttributeError(
1338
1337
  "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
1339
1338
  "Try to use self.get_kube_creds method",
1340
1339
  )
1341
- return GKECustomResourceHook(
1340
+ return GKEKubernetesHook(
1342
1341
  gcp_conn_id=self.gcp_conn_id,
1343
1342
  cluster_url=self._cluster_url,
1344
1343
  ssl_ca_cert=self._ssl_ca_cert,
@@ -1435,7 +1434,7 @@ class GKEDeleteJobOperator(KubernetesDeleteJobOperator):
1435
1434
  location: str,
1436
1435
  cluster_name: str,
1437
1436
  use_internal_ip: bool = False,
1438
- project_id: str | None = None,
1437
+ project_id: str = PROVIDE_PROJECT_ID,
1439
1438
  gcp_conn_id: str = "google_cloud_default",
1440
1439
  impersonation_chain: str | Sequence[str] | None = None,
1441
1440
  **kwargs,
@@ -1471,14 +1470,14 @@ class GKEDeleteJobOperator(KubernetesDeleteJobOperator):
1471
1470
  )
1472
1471
 
1473
1472
  @cached_property
1474
- def hook(self) -> GKEJobHook:
1473
+ def hook(self) -> GKEKubernetesHook:
1475
1474
  if self._cluster_url is None or self._ssl_ca_cert is None:
1476
1475
  raise AttributeError(
1477
1476
  "Cluster url and ssl_ca_cert should be defined before using self.hook method. "
1478
1477
  "Try to use self.get_kube_creds method",
1479
1478
  )
1480
1479
 
1481
- return GKEJobHook(
1480
+ return GKEKubernetesHook(
1482
1481
  gcp_conn_id=self.gcp_conn_id,
1483
1482
  cluster_url=self._cluster_url,
1484
1483
  ssl_ca_cert=self._ssl_ca_cert,
@@ -1494,3 +1493,211 @@ class GKEDeleteJobOperator(KubernetesDeleteJobOperator):
1494
1493
  ).fetch_cluster_info()
1495
1494
 
1496
1495
  return super().execute(context)
1496
+
1497
+
1498
+ class GKESuspendJobOperator(GoogleCloudBaseOperator):
1499
+ """
1500
+ Suspend Job by given name.
1501
+
1502
+ .. seealso::
1503
+ For more information on how to use this operator, take a look at the guide:
1504
+ :ref:`howto/operator:GKESuspendJobOperator`
1505
+
1506
+ :param name: The name of the Job to suspend
1507
+ :param project_id: The Google Developers Console project id.
1508
+ :param location: The name of the Google Kubernetes Engine zone or region in which the cluster
1509
+ resides.
1510
+ :param cluster_name: The name of the Google Kubernetes Engine cluster.
1511
+ :param namespace: The name of the Google Kubernetes Engine namespace.
1512
+ :param use_internal_ip: Use the internal IP address as the endpoint.
1513
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
1514
+ :param impersonation_chain: Optional service account to impersonate using short-term
1515
+ credentials, or chained list of accounts required to get the access_token
1516
+ of the last account in the list, which will be impersonated in the request.
1517
+ If set as a string, the account must grant the originating account
1518
+ the Service Account Token Creator IAM role.
1519
+ If set as a sequence, the identities from the list must grant
1520
+ Service Account Token Creator IAM role to the directly preceding identity, with first
1521
+ account from the list granting this role to the originating account (templated).
1522
+ """
1523
+
1524
+ template_fields: Sequence[str] = (
1525
+ "project_id",
1526
+ "gcp_conn_id",
1527
+ "name",
1528
+ "namespace",
1529
+ "cluster_name",
1530
+ "location",
1531
+ "impersonation_chain",
1532
+ )
1533
+ operator_extra_links = (KubernetesEngineJobLink(),)
1534
+
1535
+ def __init__(
1536
+ self,
1537
+ *,
1538
+ name: str,
1539
+ location: str,
1540
+ namespace: str,
1541
+ cluster_name: str,
1542
+ project_id: str = PROVIDE_PROJECT_ID,
1543
+ use_internal_ip: bool = False,
1544
+ gcp_conn_id: str = "google_cloud_default",
1545
+ impersonation_chain: str | Sequence[str] | None = None,
1546
+ **kwargs,
1547
+ ) -> None:
1548
+ super().__init__(**kwargs)
1549
+
1550
+ self.project_id = project_id
1551
+ self.gcp_conn_id = gcp_conn_id
1552
+ self.location = location
1553
+ self.name = name
1554
+ self.namespace = namespace
1555
+ self.cluster_name = cluster_name
1556
+ self.use_internal_ip = use_internal_ip
1557
+ self.impersonation_chain = impersonation_chain
1558
+
1559
+ self.job: V1Job | None = None
1560
+ self._ssl_ca_cert: str
1561
+ self._cluster_url: str
1562
+
1563
+ @cached_property
1564
+ def cluster_hook(self) -> GKEHook:
1565
+ return GKEHook(
1566
+ gcp_conn_id=self.gcp_conn_id,
1567
+ location=self.location,
1568
+ impersonation_chain=self.impersonation_chain,
1569
+ )
1570
+
1571
+ @cached_property
1572
+ def hook(self) -> GKEKubernetesHook:
1573
+ self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
1574
+ cluster_name=self.cluster_name,
1575
+ project_id=self.project_id,
1576
+ use_internal_ip=self.use_internal_ip,
1577
+ cluster_hook=self.cluster_hook,
1578
+ ).fetch_cluster_info()
1579
+
1580
+ return GKEKubernetesHook(
1581
+ gcp_conn_id=self.gcp_conn_id,
1582
+ cluster_url=self._cluster_url,
1583
+ ssl_ca_cert=self._ssl_ca_cert,
1584
+ )
1585
+
1586
+ def execute(self, context: Context) -> None:
1587
+ self.job = self.hook.patch_namespaced_job(
1588
+ job_name=self.name,
1589
+ namespace=self.namespace,
1590
+ body={"spec": {"suspend": True}},
1591
+ )
1592
+ self.log.info(
1593
+ "Job %s from cluster %s was suspended.",
1594
+ self.name,
1595
+ self.cluster_name,
1596
+ )
1597
+ KubernetesEngineJobLink.persist(context=context, task_instance=self)
1598
+
1599
+ return k8s.V1Job.to_dict(self.job)
1600
+
1601
+
1602
+ class GKEResumeJobOperator(GoogleCloudBaseOperator):
1603
+ """
1604
+ Resume Job by given name.
1605
+
1606
+ .. seealso::
1607
+ For more information on how to use this operator, take a look at the guide:
1608
+ :ref:`howto/operator:GKEResumeJobOperator`
1609
+
1610
+ :param name: The name of the Job to resume
1611
+ :param project_id: The Google Developers Console project id.
1612
+ :param location: The name of the Google Kubernetes Engine zone or region in which the cluster
1613
+ resides.
1614
+ :param cluster_name: The name of the Google Kubernetes Engine cluster.
1615
+ :param namespace: The name of the Google Kubernetes Engine namespace.
1616
+ :param use_internal_ip: Use the internal IP address as the endpoint.
1617
+ :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
1618
+ :param impersonation_chain: Optional service account to impersonate using short-term
1619
+ credentials, or chained list of accounts required to get the access_token
1620
+ of the last account in the list, which will be impersonated in the request.
1621
+ If set as a string, the account must grant the originating account
1622
+ the Service Account Token Creator IAM role.
1623
+ If set as a sequence, the identities from the list must grant
1624
+ Service Account Token Creator IAM role to the directly preceding identity, with first
1625
+ account from the list granting this role to the originating account (templated).
1626
+ """
1627
+
1628
+ template_fields: Sequence[str] = (
1629
+ "project_id",
1630
+ "gcp_conn_id",
1631
+ "name",
1632
+ "namespace",
1633
+ "cluster_name",
1634
+ "location",
1635
+ "impersonation_chain",
1636
+ )
1637
+ operator_extra_links = (KubernetesEngineJobLink(),)
1638
+
1639
+ def __init__(
1640
+ self,
1641
+ *,
1642
+ name: str,
1643
+ location: str,
1644
+ namespace: str,
1645
+ cluster_name: str,
1646
+ project_id: str = PROVIDE_PROJECT_ID,
1647
+ use_internal_ip: bool = False,
1648
+ gcp_conn_id: str = "google_cloud_default",
1649
+ impersonation_chain: str | Sequence[str] | None = None,
1650
+ **kwargs,
1651
+ ) -> None:
1652
+ super().__init__(**kwargs)
1653
+
1654
+ self.project_id = project_id
1655
+ self.gcp_conn_id = gcp_conn_id
1656
+ self.location = location
1657
+ self.name = name
1658
+ self.namespace = namespace
1659
+ self.cluster_name = cluster_name
1660
+ self.use_internal_ip = use_internal_ip
1661
+ self.impersonation_chain = impersonation_chain
1662
+
1663
+ self.job: V1Job | None = None
1664
+ self._ssl_ca_cert: str
1665
+ self._cluster_url: str
1666
+
1667
+ @cached_property
1668
+ def cluster_hook(self) -> GKEHook:
1669
+ return GKEHook(
1670
+ gcp_conn_id=self.gcp_conn_id,
1671
+ location=self.location,
1672
+ impersonation_chain=self.impersonation_chain,
1673
+ )
1674
+
1675
+ @cached_property
1676
+ def hook(self) -> GKEKubernetesHook:
1677
+ self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
1678
+ cluster_name=self.cluster_name,
1679
+ project_id=self.project_id,
1680
+ use_internal_ip=self.use_internal_ip,
1681
+ cluster_hook=self.cluster_hook,
1682
+ ).fetch_cluster_info()
1683
+
1684
+ return GKEKubernetesHook(
1685
+ gcp_conn_id=self.gcp_conn_id,
1686
+ cluster_url=self._cluster_url,
1687
+ ssl_ca_cert=self._ssl_ca_cert,
1688
+ )
1689
+
1690
+ def execute(self, context: Context) -> None:
1691
+ self.job = self.hook.patch_namespaced_job(
1692
+ job_name=self.name,
1693
+ namespace=self.namespace,
1694
+ body={"spec": {"suspend": False}},
1695
+ )
1696
+ self.log.info(
1697
+ "Job %s from cluster %s was resumed.",
1698
+ self.name,
1699
+ self.cluster_name,
1700
+ )
1701
+ KubernetesEngineJobLink.persist(context=context, task_instance=self)
1702
+
1703
+ return k8s.V1Job.to_dict(self.job)
@@ -27,6 +27,7 @@ from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarni
27
27
  from airflow.providers.google.cloud.hooks.life_sciences import LifeSciencesHook
28
28
  from airflow.providers.google.cloud.links.life_sciences import LifeSciencesLink
29
29
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
30
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
30
31
 
31
32
  if TYPE_CHECKING:
32
33
  from airflow.utils.context import Context
@@ -82,7 +83,7 @@ class LifeSciencesRunPipelineOperator(GoogleCloudBaseOperator):
82
83
  *,
83
84
  body: dict,
84
85
  location: str,
85
- project_id: str | None = None,
86
+ project_id: str = PROVIDE_PROJECT_ID,
86
87
  gcp_conn_id: str = "google_cloud_default",
87
88
  api_version: str = "v2beta",
88
89
  impersonation_chain: str | Sequence[str] | None = None,
@@ -39,6 +39,7 @@ from airflow.providers.google.cloud.links.mlengine import (
39
39
  )
40
40
  from airflow.providers.google.cloud.operators.cloud_base import GoogleCloudBaseOperator
41
41
  from airflow.providers.google.cloud.triggers.mlengine import MLEngineStartTrainingJobTrigger
42
+ from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
42
43
 
43
44
  if TYPE_CHECKING:
44
45
  from airflow.utils.context import Context
@@ -345,7 +346,7 @@ class MLEngineManageModelOperator(GoogleCloudBaseOperator):
345
346
  *,
346
347
  model: dict,
347
348
  operation: str = "create",
348
- project_id: str | None = None,
349
+ project_id: str = PROVIDE_PROJECT_ID,
349
350
  gcp_conn_id: str = "google_cloud_default",
350
351
  impersonation_chain: str | Sequence[str] | None = None,
351
352
  **kwargs,
@@ -417,7 +418,7 @@ class MLEngineCreateModelOperator(GoogleCloudBaseOperator):
417
418
  self,
418
419
  *,
419
420
  model: dict,
420
- project_id: str | None = None,
421
+ project_id: str = PROVIDE_PROJECT_ID,
421
422
  gcp_conn_id: str = "google_cloud_default",
422
423
  impersonation_chain: str | Sequence[str] | None = None,
423
424
  **kwargs,
@@ -493,7 +494,7 @@ class MLEngineGetModelOperator(GoogleCloudBaseOperator):
493
494
  self,
494
495
  *,
495
496
  model_name: str,
496
- project_id: str | None = None,
497
+ project_id: str = PROVIDE_PROJECT_ID,
497
498
  gcp_conn_id: str = "google_cloud_default",
498
499
  impersonation_chain: str | Sequence[str] | None = None,
499
500
  **kwargs,
@@ -573,7 +574,7 @@ class MLEngineDeleteModelOperator(GoogleCloudBaseOperator):
573
574
  *,
574
575
  model_name: str,
575
576
  delete_contents: bool = False,
576
- project_id: str | None = None,
577
+ project_id: str = PROVIDE_PROJECT_ID,
577
578
  gcp_conn_id: str = "google_cloud_default",
578
579
  impersonation_chain: str | Sequence[str] | None = None,
579
580
  **kwargs,
@@ -680,7 +681,7 @@ class MLEngineManageVersionOperator(GoogleCloudBaseOperator):
680
681
  version_name: str | None = None,
681
682
  version: dict | None = None,
682
683
  operation: str = "create",
683
- project_id: str | None = None,
684
+ project_id: str = PROVIDE_PROJECT_ID,
684
685
  gcp_conn_id: str = "google_cloud_default",
685
686
  impersonation_chain: str | Sequence[str] | None = None,
686
687
  **kwargs,
@@ -773,7 +774,7 @@ class MLEngineCreateVersionOperator(GoogleCloudBaseOperator):
773
774
  *,
774
775
  model_name: str,
775
776
  version: dict,
776
- project_id: str | None = None,
777
+ project_id: str = PROVIDE_PROJECT_ID,
777
778
  gcp_conn_id: str = "google_cloud_default",
778
779
  impersonation_chain: str | Sequence[str] | None = None,
779
780
  **kwargs,
@@ -866,7 +867,7 @@ class MLEngineSetDefaultVersionOperator(GoogleCloudBaseOperator):
866
867
  *,
867
868
  model_name: str,
868
869
  version_name: str,
869
- project_id: str | None = None,
870
+ project_id: str = PROVIDE_PROJECT_ID,
870
871
  gcp_conn_id: str = "google_cloud_default",
871
872
  impersonation_chain: str | Sequence[str] | None = None,
872
873
  **kwargs,
@@ -956,7 +957,7 @@ class MLEngineListVersionsOperator(GoogleCloudBaseOperator):
956
957
  self,
957
958
  *,
958
959
  model_name: str,
959
- project_id: str | None = None,
960
+ project_id: str = PROVIDE_PROJECT_ID,
960
961
  gcp_conn_id: str = "google_cloud_default",
961
962
  impersonation_chain: str | Sequence[str] | None = None,
962
963
  **kwargs,
@@ -1045,7 +1046,7 @@ class MLEngineDeleteVersionOperator(GoogleCloudBaseOperator):
1045
1046
  *,
1046
1047
  model_name: str,
1047
1048
  version_name: str,
1048
- project_id: str | None = None,
1049
+ project_id: str = PROVIDE_PROJECT_ID,
1049
1050
  gcp_conn_id: str = "google_cloud_default",
1050
1051
  impersonation_chain: str | Sequence[str] | None = None,
1051
1052
  **kwargs,
@@ -1467,7 +1468,7 @@ class MLEngineTrainingCancelJobOperator(GoogleCloudBaseOperator):
1467
1468
  self,
1468
1469
  *,
1469
1470
  job_id: str,
1470
- project_id: str | None = None,
1471
+ project_id: str = PROVIDE_PROJECT_ID,
1471
1472
  gcp_conn_id: str = "google_cloud_default",
1472
1473
  impersonation_chain: str | Sequence[str] | None = None,
1473
1474
  **kwargs,