apache-airflow-providers-google 10.17.0rc1__py3-none-any.whl → 10.18.0rc1__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.
- airflow/providers/google/__init__.py +3 -3
- airflow/providers/google/cloud/hooks/automl.py +1 -1
- airflow/providers/google/cloud/hooks/bigquery.py +64 -33
- airflow/providers/google/cloud/hooks/cloud_composer.py +250 -2
- airflow/providers/google/cloud/hooks/cloud_sql.py +154 -7
- airflow/providers/google/cloud/hooks/cloud_storage_transfer_service.py +7 -2
- airflow/providers/google/cloud/hooks/compute_ssh.py +2 -1
- airflow/providers/google/cloud/hooks/dataflow.py +246 -32
- airflow/providers/google/cloud/hooks/dataplex.py +6 -2
- airflow/providers/google/cloud/hooks/dlp.py +14 -14
- airflow/providers/google/cloud/hooks/gcs.py +6 -2
- airflow/providers/google/cloud/hooks/gdm.py +2 -2
- airflow/providers/google/cloud/hooks/kubernetes_engine.py +2 -2
- airflow/providers/google/cloud/hooks/mlengine.py +8 -4
- airflow/providers/google/cloud/hooks/pubsub.py +1 -1
- airflow/providers/google/cloud/hooks/secret_manager.py +252 -4
- airflow/providers/google/cloud/hooks/vertex_ai/custom_job.py +1431 -74
- airflow/providers/google/cloud/links/vertex_ai.py +2 -1
- airflow/providers/google/cloud/log/gcs_task_handler.py +2 -1
- airflow/providers/google/cloud/operators/automl.py +13 -12
- airflow/providers/google/cloud/operators/bigquery.py +36 -22
- airflow/providers/google/cloud/operators/bigquery_dts.py +4 -3
- airflow/providers/google/cloud/operators/bigtable.py +7 -6
- airflow/providers/google/cloud/operators/cloud_build.py +12 -11
- airflow/providers/google/cloud/operators/cloud_composer.py +147 -2
- airflow/providers/google/cloud/operators/cloud_memorystore.py +17 -16
- airflow/providers/google/cloud/operators/cloud_sql.py +60 -17
- airflow/providers/google/cloud/operators/cloud_storage_transfer_service.py +35 -16
- airflow/providers/google/cloud/operators/compute.py +12 -11
- airflow/providers/google/cloud/operators/datacatalog.py +21 -20
- airflow/providers/google/cloud/operators/dataflow.py +59 -42
- airflow/providers/google/cloud/operators/datafusion.py +11 -10
- airflow/providers/google/cloud/operators/datapipeline.py +3 -2
- airflow/providers/google/cloud/operators/dataprep.py +5 -4
- airflow/providers/google/cloud/operators/dataproc.py +19 -16
- airflow/providers/google/cloud/operators/datastore.py +8 -7
- airflow/providers/google/cloud/operators/dlp.py +31 -30
- airflow/providers/google/cloud/operators/functions.py +4 -3
- airflow/providers/google/cloud/operators/gcs.py +66 -41
- airflow/providers/google/cloud/operators/kubernetes_engine.py +232 -12
- airflow/providers/google/cloud/operators/life_sciences.py +2 -1
- airflow/providers/google/cloud/operators/mlengine.py +11 -10
- airflow/providers/google/cloud/operators/pubsub.py +6 -5
- airflow/providers/google/cloud/operators/spanner.py +7 -6
- airflow/providers/google/cloud/operators/speech_to_text.py +2 -1
- airflow/providers/google/cloud/operators/stackdriver.py +11 -10
- airflow/providers/google/cloud/operators/tasks.py +14 -13
- airflow/providers/google/cloud/operators/text_to_speech.py +2 -1
- airflow/providers/google/cloud/operators/translate_speech.py +2 -1
- airflow/providers/google/cloud/operators/vertex_ai/custom_job.py +333 -26
- airflow/providers/google/cloud/operators/vertex_ai/generative_model.py +20 -12
- airflow/providers/google/cloud/operators/vertex_ai/pipeline_job.py +0 -1
- airflow/providers/google/cloud/operators/vision.py +13 -12
- airflow/providers/google/cloud/operators/workflows.py +10 -9
- airflow/providers/google/cloud/secrets/secret_manager.py +2 -1
- airflow/providers/google/cloud/sensors/bigquery_dts.py +2 -1
- airflow/providers/google/cloud/sensors/bigtable.py +2 -1
- airflow/providers/google/cloud/sensors/cloud_storage_transfer_service.py +2 -1
- airflow/providers/google/cloud/sensors/dataflow.py +239 -52
- airflow/providers/google/cloud/sensors/datafusion.py +2 -1
- airflow/providers/google/cloud/sensors/dataproc.py +3 -2
- airflow/providers/google/cloud/sensors/gcs.py +14 -12
- airflow/providers/google/cloud/sensors/tasks.py +2 -1
- airflow/providers/google/cloud/sensors/workflows.py +2 -1
- airflow/providers/google/cloud/transfers/adls_to_gcs.py +8 -2
- airflow/providers/google/cloud/transfers/azure_blob_to_gcs.py +7 -1
- airflow/providers/google/cloud/transfers/azure_fileshare_to_gcs.py +7 -1
- airflow/providers/google/cloud/transfers/bigquery_to_gcs.py +2 -1
- airflow/providers/google/cloud/transfers/bigquery_to_mssql.py +1 -1
- airflow/providers/google/cloud/transfers/bigquery_to_sql.py +1 -0
- airflow/providers/google/cloud/transfers/gcs_to_bigquery.py +5 -6
- airflow/providers/google/cloud/transfers/gcs_to_gcs.py +22 -12
- airflow/providers/google/cloud/triggers/bigquery.py +14 -3
- airflow/providers/google/cloud/triggers/cloud_composer.py +68 -0
- airflow/providers/google/cloud/triggers/cloud_sql.py +2 -1
- airflow/providers/google/cloud/triggers/cloud_storage_transfer_service.py +2 -1
- airflow/providers/google/cloud/triggers/dataflow.py +504 -4
- airflow/providers/google/cloud/triggers/dataproc.py +110 -26
- airflow/providers/google/cloud/triggers/mlengine.py +2 -1
- airflow/providers/google/cloud/triggers/vertex_ai.py +94 -0
- airflow/providers/google/common/hooks/base_google.py +45 -7
- airflow/providers/google/firebase/hooks/firestore.py +2 -2
- airflow/providers/google/firebase/operators/firestore.py +2 -1
- airflow/providers/google/get_provider_info.py +3 -2
- {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0rc1.dist-info}/METADATA +8 -8
- {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0rc1.dist-info}/RECORD +88 -89
- airflow/providers/google/cloud/example_dags/example_cloud_sql_query.py +0 -289
- {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0rc1.dist-info}/WHEEL +0 -0
- {apache_airflow_providers_google-10.17.0rc1.dist-info → apache_airflow_providers_google-10.18.0rc1.dist-info}/entry_points.txt +0 -0
@@ -29,6 +29,8 @@ from typing import TYPE_CHECKING, Sequence
|
|
29
29
|
|
30
30
|
import pendulum
|
31
31
|
|
32
|
+
from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
|
33
|
+
|
32
34
|
if TYPE_CHECKING:
|
33
35
|
from airflow.utils.context import Context
|
34
36
|
|
@@ -119,7 +121,7 @@ class GCSCreateBucketOperator(GoogleCloudBaseOperator):
|
|
119
121
|
resource: dict | None = None,
|
120
122
|
storage_class: str = "MULTI_REGIONAL",
|
121
123
|
location: str = "US",
|
122
|
-
project_id: str
|
124
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
123
125
|
labels: dict | None = None,
|
124
126
|
gcp_conn_id: str = "google_cloud_default",
|
125
127
|
impersonation_chain: str | Sequence[str] | None = None,
|
@@ -297,7 +299,7 @@ class GCSDeleteObjectsOperator(GoogleCloudBaseOperator):
|
|
297
299
|
*,
|
298
300
|
bucket_name: str,
|
299
301
|
objects: list[str] | None = None,
|
300
|
-
prefix: str | None = None,
|
302
|
+
prefix: str | list[str] | None = None,
|
301
303
|
gcp_conn_id: str = "google_cloud_default",
|
302
304
|
impersonation_chain: str | Sequence[str] | None = None,
|
303
305
|
**kwargs,
|
@@ -309,12 +311,14 @@ class GCSDeleteObjectsOperator(GoogleCloudBaseOperator):
|
|
309
311
|
self.impersonation_chain = impersonation_chain
|
310
312
|
|
311
313
|
if objects is None and prefix is None:
|
312
|
-
err_message = "(Task {task_id}) Either
|
314
|
+
err_message = "(Task {task_id}) Either objects or prefix should be set. Both are None.".format(
|
313
315
|
**kwargs
|
314
316
|
)
|
315
317
|
raise ValueError(err_message)
|
318
|
+
if objects is not None and prefix is not None:
|
319
|
+
err_message = "(Task {task_id}) Objects or prefix should be set. Both provided.".format(**kwargs)
|
320
|
+
raise ValueError(err_message)
|
316
321
|
|
317
|
-
self._objects: list[str] = []
|
318
322
|
super().__init__(**kwargs)
|
319
323
|
|
320
324
|
def execute(self, context: Context) -> None:
|
@@ -324,15 +328,14 @@ class GCSDeleteObjectsOperator(GoogleCloudBaseOperator):
|
|
324
328
|
)
|
325
329
|
|
326
330
|
if self.objects is not None:
|
327
|
-
|
331
|
+
objects = self.objects
|
328
332
|
else:
|
329
|
-
|
330
|
-
self.log.info("Deleting %s objects from %s", len(
|
331
|
-
for object_name in
|
333
|
+
objects = hook.list(bucket_name=self.bucket_name, prefix=self.prefix)
|
334
|
+
self.log.info("Deleting %s objects from %s", len(objects), self.bucket_name)
|
335
|
+
for object_name in objects:
|
332
336
|
hook.delete(bucket_name=self.bucket_name, object_name=object_name)
|
333
337
|
|
334
|
-
def
|
335
|
-
"""Implement on_complete as execute() resolves object names."""
|
338
|
+
def get_openlineage_facets_on_start(self):
|
336
339
|
from openlineage.client.facet import (
|
337
340
|
LifecycleStateChange,
|
338
341
|
LifecycleStateChangeDatasetFacet,
|
@@ -342,8 +345,17 @@ class GCSDeleteObjectsOperator(GoogleCloudBaseOperator):
|
|
342
345
|
|
343
346
|
from airflow.providers.openlineage.extractors import OperatorLineage
|
344
347
|
|
345
|
-
|
346
|
-
|
348
|
+
objects = []
|
349
|
+
if self.objects is not None:
|
350
|
+
objects = self.objects
|
351
|
+
elif self.prefix is not None:
|
352
|
+
prefixes = [self.prefix] if isinstance(self.prefix, str) else self.prefix
|
353
|
+
for pref in prefixes:
|
354
|
+
# Use parent if not a file (dot not in name) and not a dir (ends with slash)
|
355
|
+
if "." not in pref.split("/")[-1] and not pref.endswith("/"):
|
356
|
+
pref = Path(pref).parent.as_posix()
|
357
|
+
pref = "/" if pref in (".", "", "/") else pref.rstrip("/")
|
358
|
+
objects.append(pref)
|
347
359
|
|
348
360
|
bucket_url = f"gs://{self.bucket_name}"
|
349
361
|
input_datasets = [
|
@@ -360,7 +372,7 @@ class GCSDeleteObjectsOperator(GoogleCloudBaseOperator):
|
|
360
372
|
)
|
361
373
|
},
|
362
374
|
)
|
363
|
-
for object_name in
|
375
|
+
for object_name in objects
|
364
376
|
]
|
365
377
|
|
366
378
|
return OperatorLineage(inputs=input_datasets)
|
@@ -774,8 +786,8 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
774
786
|
self.upload_continue_on_fail = upload_continue_on_fail
|
775
787
|
self.upload_num_attempts = upload_num_attempts
|
776
788
|
|
777
|
-
self.
|
778
|
-
self.
|
789
|
+
self._source_prefix_interp: str | None = None
|
790
|
+
self._destination_prefix_interp: str | None = None
|
779
791
|
|
780
792
|
def execute(self, context: Context) -> list[str]:
|
781
793
|
# Define intervals and prefixes.
|
@@ -803,11 +815,11 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
803
815
|
timespan_start = timespan_start.in_timezone(timezone.utc)
|
804
816
|
timespan_end = timespan_end.in_timezone(timezone.utc)
|
805
817
|
|
806
|
-
|
818
|
+
self._source_prefix_interp = GCSTimeSpanFileTransformOperator.interpolate_prefix(
|
807
819
|
self.source_prefix,
|
808
820
|
timespan_start,
|
809
821
|
)
|
810
|
-
|
822
|
+
self._destination_prefix_interp = GCSTimeSpanFileTransformOperator.interpolate_prefix(
|
811
823
|
self.destination_prefix,
|
812
824
|
timespan_start,
|
813
825
|
)
|
@@ -828,9 +840,9 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
828
840
|
)
|
829
841
|
|
830
842
|
# Fetch list of files.
|
831
|
-
|
843
|
+
blobs_to_transform = source_hook.list_by_timespan(
|
832
844
|
bucket_name=self.source_bucket,
|
833
|
-
prefix=
|
845
|
+
prefix=self._source_prefix_interp,
|
834
846
|
timespan_start=timespan_start,
|
835
847
|
timespan_end=timespan_end,
|
836
848
|
)
|
@@ -840,7 +852,7 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
840
852
|
temp_output_dir_path = Path(temp_output_dir)
|
841
853
|
|
842
854
|
# TODO: download in parallel.
|
843
|
-
for blob_to_transform in
|
855
|
+
for blob_to_transform in blobs_to_transform:
|
844
856
|
destination_file = temp_input_dir_path / blob_to_transform
|
845
857
|
destination_file.parent.mkdir(parents=True, exist_ok=True)
|
846
858
|
try:
|
@@ -877,6 +889,8 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
877
889
|
|
878
890
|
self.log.info("Transformation succeeded. Output temporarily located at %s", temp_output_dir_path)
|
879
891
|
|
892
|
+
files_uploaded = []
|
893
|
+
|
880
894
|
# TODO: upload in parallel.
|
881
895
|
for upload_file in temp_output_dir_path.glob("**/*"):
|
882
896
|
if upload_file.is_dir():
|
@@ -884,8 +898,8 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
884
898
|
|
885
899
|
upload_file_name = str(upload_file.relative_to(temp_output_dir_path))
|
886
900
|
|
887
|
-
if self.
|
888
|
-
upload_file_name = f"{
|
901
|
+
if self._destination_prefix_interp is not None:
|
902
|
+
upload_file_name = f"{self._destination_prefix_interp.rstrip('/')}/{upload_file_name}"
|
889
903
|
|
890
904
|
self.log.info("Uploading file %s to %s", upload_file, upload_file_name)
|
891
905
|
|
@@ -897,35 +911,46 @@ class GCSTimeSpanFileTransformOperator(GoogleCloudBaseOperator):
|
|
897
911
|
chunk_size=self.chunk_size,
|
898
912
|
num_max_attempts=self.upload_num_attempts,
|
899
913
|
)
|
900
|
-
|
914
|
+
files_uploaded.append(str(upload_file_name))
|
901
915
|
except GoogleCloudError:
|
902
916
|
if not self.upload_continue_on_fail:
|
903
917
|
raise
|
904
918
|
|
905
|
-
return
|
919
|
+
return files_uploaded
|
906
920
|
|
907
921
|
def get_openlineage_facets_on_complete(self, task_instance):
|
908
|
-
"""Implement on_complete as execute() resolves object
|
922
|
+
"""Implement on_complete as execute() resolves object prefixes."""
|
909
923
|
from openlineage.client.run import Dataset
|
910
924
|
|
911
925
|
from airflow.providers.openlineage.extractors import OperatorLineage
|
912
926
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
)
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
)
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
927
|
+
def _parse_prefix(pref):
|
928
|
+
# Use parent if not a file (dot not in name) and not a dir (ends with slash)
|
929
|
+
if "." not in pref.split("/")[-1] and not pref.endswith("/"):
|
930
|
+
pref = Path(pref).parent.as_posix()
|
931
|
+
return "/" if pref in (".", "/", "") else pref.rstrip("/")
|
932
|
+
|
933
|
+
input_prefix, output_prefix = "/", "/"
|
934
|
+
if self._source_prefix_interp is not None:
|
935
|
+
input_prefix = _parse_prefix(self._source_prefix_interp)
|
936
|
+
|
937
|
+
if self._destination_prefix_interp is not None:
|
938
|
+
output_prefix = _parse_prefix(self._destination_prefix_interp)
|
939
|
+
|
940
|
+
return OperatorLineage(
|
941
|
+
inputs=[
|
942
|
+
Dataset(
|
943
|
+
namespace=f"gs://{self.source_bucket}",
|
944
|
+
name=input_prefix,
|
945
|
+
)
|
946
|
+
],
|
947
|
+
outputs=[
|
948
|
+
Dataset(
|
949
|
+
namespace=f"gs://{self.destination_bucket}",
|
950
|
+
name=output_prefix,
|
951
|
+
)
|
952
|
+
],
|
953
|
+
)
|
929
954
|
|
930
955
|
|
931
956
|
class GCSDeleteBucketOperator(GoogleCloudBaseOperator):
|
@@ -29,13 +29,13 @@ import yaml
|
|
29
29
|
from deprecated import deprecated
|
30
30
|
from google.api_core.exceptions import AlreadyExists
|
31
31
|
from google.cloud.container_v1.types import Cluster
|
32
|
-
from kubernetes.client import V1JobList
|
32
|
+
from kubernetes.client import V1JobList, models as k8s
|
33
33
|
from kubernetes.utils.create_from_yaml import FailToCreateError
|
34
34
|
from packaging.version import parse as parse_version
|
35
35
|
|
36
36
|
from airflow.configuration import conf
|
37
37
|
from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
|
38
|
-
from airflow.providers.cncf.kubernetes.operators.job import
|
38
|
+
from airflow.providers.cncf.kubernetes.operators.job import KubernetesJobOperator
|
39
39
|
from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
|
40
40
|
from airflow.providers.cncf.kubernetes.operators.resource import (
|
41
41
|
KubernetesCreateResourceOperator,
|
@@ -47,6 +47,7 @@ from airflow.providers.google.cloud.hooks.kubernetes_engine import (
|
|
47
47
|
GKEDeploymentHook,
|
48
48
|
GKEHook,
|
49
49
|
GKEJobHook,
|
50
|
+
GKEKubernetesHook,
|
50
51
|
GKEPodHook,
|
51
52
|
)
|
52
53
|
from airflow.providers.google.cloud.links.kubernetes_engine import (
|
@@ -61,9 +62,20 @@ from airflow.providers.google.cloud.triggers.kubernetes_engine import (
|
|
61
62
|
GKEOperationTrigger,
|
62
63
|
GKEStartPodTrigger,
|
63
64
|
)
|
65
|
+
from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID
|
64
66
|
from airflow.providers_manager import ProvidersManager
|
65
67
|
from airflow.utils.timezone import utcnow
|
66
68
|
|
69
|
+
try:
|
70
|
+
from airflow.providers.cncf.kubernetes.operators.job import KubernetesDeleteJobOperator
|
71
|
+
except ImportError:
|
72
|
+
from airflow.exceptions import AirflowOptionalProviderFeatureException
|
73
|
+
|
74
|
+
raise AirflowOptionalProviderFeatureException(
|
75
|
+
"Failed to import KubernetesDeleteJobOperator. This operator is only available in cncf-kubernetes "
|
76
|
+
"provider version >=8.1.0"
|
77
|
+
)
|
78
|
+
|
67
79
|
if TYPE_CHECKING:
|
68
80
|
from kubernetes.client.models import V1Job, V1Pod
|
69
81
|
|
@@ -166,7 +178,7 @@ class GKEDeleteClusterOperator(GoogleCloudBaseOperator):
|
|
166
178
|
*,
|
167
179
|
name: str,
|
168
180
|
location: str,
|
169
|
-
project_id: str
|
181
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
170
182
|
gcp_conn_id: str = "google_cloud_default",
|
171
183
|
api_version: str = "v2",
|
172
184
|
impersonation_chain: str | Sequence[str] | None = None,
|
@@ -310,7 +322,7 @@ class GKECreateClusterOperator(GoogleCloudBaseOperator):
|
|
310
322
|
*,
|
311
323
|
location: str,
|
312
324
|
body: dict | Cluster,
|
313
|
-
project_id: str
|
325
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
314
326
|
gcp_conn_id: str = "google_cloud_default",
|
315
327
|
api_version: str = "v2",
|
316
328
|
impersonation_chain: str | Sequence[str] | None = None,
|
@@ -496,7 +508,7 @@ class GKEStartKueueInsideClusterOperator(GoogleCloudBaseOperator):
|
|
496
508
|
cluster_name: str,
|
497
509
|
kueue_version: str,
|
498
510
|
use_internal_ip: bool = False,
|
499
|
-
project_id: str
|
511
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
500
512
|
gcp_conn_id: str = "google_cloud_default",
|
501
513
|
impersonation_chain: str | Sequence[str] | None = None,
|
502
514
|
**kwargs,
|
@@ -658,7 +670,7 @@ class GKEStartPodOperator(KubernetesPodOperator):
|
|
658
670
|
location: str,
|
659
671
|
cluster_name: str,
|
660
672
|
use_internal_ip: bool = False,
|
661
|
-
project_id: str
|
673
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
662
674
|
gcp_conn_id: str = "google_cloud_default",
|
663
675
|
impersonation_chain: str | Sequence[str] | None = None,
|
664
676
|
regional: bool | None = None,
|
@@ -856,7 +868,7 @@ class GKEStartJobOperator(KubernetesJobOperator):
|
|
856
868
|
location: str,
|
857
869
|
cluster_name: str,
|
858
870
|
use_internal_ip: bool = False,
|
859
|
-
project_id: str
|
871
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
860
872
|
gcp_conn_id: str = "google_cloud_default",
|
861
873
|
impersonation_chain: str | Sequence[str] | None = None,
|
862
874
|
deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
|
@@ -993,7 +1005,7 @@ class GKEDescribeJobOperator(GoogleCloudBaseOperator):
|
|
993
1005
|
location: str,
|
994
1006
|
namespace: str,
|
995
1007
|
cluster_name: str,
|
996
|
-
project_id: str
|
1008
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
997
1009
|
use_internal_ip: bool = False,
|
998
1010
|
gcp_conn_id: str = "google_cloud_default",
|
999
1011
|
impersonation_chain: str | Sequence[str] | None = None,
|
@@ -1094,7 +1106,7 @@ class GKEListJobsOperator(GoogleCloudBaseOperator):
|
|
1094
1106
|
location: str,
|
1095
1107
|
cluster_name: str,
|
1096
1108
|
namespace: str | None = None,
|
1097
|
-
project_id: str
|
1109
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
1098
1110
|
use_internal_ip: bool = False,
|
1099
1111
|
do_xcom_push: bool = True,
|
1100
1112
|
gcp_conn_id: str = "google_cloud_default",
|
@@ -1194,7 +1206,7 @@ class GKECreateCustomResourceOperator(KubernetesCreateResourceOperator):
|
|
1194
1206
|
location: str,
|
1195
1207
|
cluster_name: str,
|
1196
1208
|
use_internal_ip: bool = False,
|
1197
|
-
project_id: str
|
1209
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
1198
1210
|
gcp_conn_id: str = "google_cloud_default",
|
1199
1211
|
impersonation_chain: str | Sequence[str] | None = None,
|
1200
1212
|
**kwargs,
|
@@ -1296,7 +1308,7 @@ class GKEDeleteCustomResourceOperator(KubernetesDeleteResourceOperator):
|
|
1296
1308
|
location: str,
|
1297
1309
|
cluster_name: str,
|
1298
1310
|
use_internal_ip: bool = False,
|
1299
|
-
project_id: str
|
1311
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
1300
1312
|
gcp_conn_id: str = "google_cloud_default",
|
1301
1313
|
impersonation_chain: str | Sequence[str] | None = None,
|
1302
1314
|
**kwargs,
|
@@ -1435,7 +1447,7 @@ class GKEDeleteJobOperator(KubernetesDeleteJobOperator):
|
|
1435
1447
|
location: str,
|
1436
1448
|
cluster_name: str,
|
1437
1449
|
use_internal_ip: bool = False,
|
1438
|
-
project_id: str
|
1450
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
1439
1451
|
gcp_conn_id: str = "google_cloud_default",
|
1440
1452
|
impersonation_chain: str | Sequence[str] | None = None,
|
1441
1453
|
**kwargs,
|
@@ -1494,3 +1506,211 @@ class GKEDeleteJobOperator(KubernetesDeleteJobOperator):
|
|
1494
1506
|
).fetch_cluster_info()
|
1495
1507
|
|
1496
1508
|
return super().execute(context)
|
1509
|
+
|
1510
|
+
|
1511
|
+
class GKESuspendJobOperator(GoogleCloudBaseOperator):
|
1512
|
+
"""
|
1513
|
+
Suspend Job by given name.
|
1514
|
+
|
1515
|
+
.. seealso::
|
1516
|
+
For more information on how to use this operator, take a look at the guide:
|
1517
|
+
:ref:`howto/operator:GKESuspendJobOperator`
|
1518
|
+
|
1519
|
+
:param name: The name of the Job to suspend
|
1520
|
+
:param project_id: The Google Developers Console project id.
|
1521
|
+
:param location: The name of the Google Kubernetes Engine zone or region in which the cluster
|
1522
|
+
resides.
|
1523
|
+
:param cluster_name: The name of the Google Kubernetes Engine cluster.
|
1524
|
+
:param namespace: The name of the Google Kubernetes Engine namespace.
|
1525
|
+
:param use_internal_ip: Use the internal IP address as the endpoint.
|
1526
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
1527
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
1528
|
+
credentials, or chained list of accounts required to get the access_token
|
1529
|
+
of the last account in the list, which will be impersonated in the request.
|
1530
|
+
If set as a string, the account must grant the originating account
|
1531
|
+
the Service Account Token Creator IAM role.
|
1532
|
+
If set as a sequence, the identities from the list must grant
|
1533
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
1534
|
+
account from the list granting this role to the originating account (templated).
|
1535
|
+
"""
|
1536
|
+
|
1537
|
+
template_fields: Sequence[str] = (
|
1538
|
+
"project_id",
|
1539
|
+
"gcp_conn_id",
|
1540
|
+
"name",
|
1541
|
+
"namespace",
|
1542
|
+
"cluster_name",
|
1543
|
+
"location",
|
1544
|
+
"impersonation_chain",
|
1545
|
+
)
|
1546
|
+
operator_extra_links = (KubernetesEngineJobLink(),)
|
1547
|
+
|
1548
|
+
def __init__(
|
1549
|
+
self,
|
1550
|
+
*,
|
1551
|
+
name: str,
|
1552
|
+
location: str,
|
1553
|
+
namespace: str,
|
1554
|
+
cluster_name: str,
|
1555
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
1556
|
+
use_internal_ip: bool = False,
|
1557
|
+
gcp_conn_id: str = "google_cloud_default",
|
1558
|
+
impersonation_chain: str | Sequence[str] | None = None,
|
1559
|
+
**kwargs,
|
1560
|
+
) -> None:
|
1561
|
+
super().__init__(**kwargs)
|
1562
|
+
|
1563
|
+
self.project_id = project_id
|
1564
|
+
self.gcp_conn_id = gcp_conn_id
|
1565
|
+
self.location = location
|
1566
|
+
self.name = name
|
1567
|
+
self.namespace = namespace
|
1568
|
+
self.cluster_name = cluster_name
|
1569
|
+
self.use_internal_ip = use_internal_ip
|
1570
|
+
self.impersonation_chain = impersonation_chain
|
1571
|
+
|
1572
|
+
self.job: V1Job | None = None
|
1573
|
+
self._ssl_ca_cert: str
|
1574
|
+
self._cluster_url: str
|
1575
|
+
|
1576
|
+
@cached_property
|
1577
|
+
def cluster_hook(self) -> GKEHook:
|
1578
|
+
return GKEHook(
|
1579
|
+
gcp_conn_id=self.gcp_conn_id,
|
1580
|
+
location=self.location,
|
1581
|
+
impersonation_chain=self.impersonation_chain,
|
1582
|
+
)
|
1583
|
+
|
1584
|
+
@cached_property
|
1585
|
+
def hook(self) -> GKEKubernetesHook:
|
1586
|
+
self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
|
1587
|
+
cluster_name=self.cluster_name,
|
1588
|
+
project_id=self.project_id,
|
1589
|
+
use_internal_ip=self.use_internal_ip,
|
1590
|
+
cluster_hook=self.cluster_hook,
|
1591
|
+
).fetch_cluster_info()
|
1592
|
+
|
1593
|
+
return GKEKubernetesHook(
|
1594
|
+
gcp_conn_id=self.gcp_conn_id,
|
1595
|
+
cluster_url=self._cluster_url,
|
1596
|
+
ssl_ca_cert=self._ssl_ca_cert,
|
1597
|
+
)
|
1598
|
+
|
1599
|
+
def execute(self, context: Context) -> None:
|
1600
|
+
self.job = self.hook.patch_namespaced_job(
|
1601
|
+
job_name=self.name,
|
1602
|
+
namespace=self.namespace,
|
1603
|
+
body={"spec": {"suspend": True}},
|
1604
|
+
)
|
1605
|
+
self.log.info(
|
1606
|
+
"Job %s from cluster %s was suspended.",
|
1607
|
+
self.name,
|
1608
|
+
self.cluster_name,
|
1609
|
+
)
|
1610
|
+
KubernetesEngineJobLink.persist(context=context, task_instance=self)
|
1611
|
+
|
1612
|
+
return k8s.V1Job.to_dict(self.job)
|
1613
|
+
|
1614
|
+
|
1615
|
+
class GKEResumeJobOperator(GoogleCloudBaseOperator):
|
1616
|
+
"""
|
1617
|
+
Resume Job by given name.
|
1618
|
+
|
1619
|
+
.. seealso::
|
1620
|
+
For more information on how to use this operator, take a look at the guide:
|
1621
|
+
:ref:`howto/operator:GKEResumeJobOperator`
|
1622
|
+
|
1623
|
+
:param name: The name of the Job to resume
|
1624
|
+
:param project_id: The Google Developers Console project id.
|
1625
|
+
:param location: The name of the Google Kubernetes Engine zone or region in which the cluster
|
1626
|
+
resides.
|
1627
|
+
:param cluster_name: The name of the Google Kubernetes Engine cluster.
|
1628
|
+
:param namespace: The name of the Google Kubernetes Engine namespace.
|
1629
|
+
:param use_internal_ip: Use the internal IP address as the endpoint.
|
1630
|
+
:param gcp_conn_id: The connection ID to use connecting to Google Cloud.
|
1631
|
+
:param impersonation_chain: Optional service account to impersonate using short-term
|
1632
|
+
credentials, or chained list of accounts required to get the access_token
|
1633
|
+
of the last account in the list, which will be impersonated in the request.
|
1634
|
+
If set as a string, the account must grant the originating account
|
1635
|
+
the Service Account Token Creator IAM role.
|
1636
|
+
If set as a sequence, the identities from the list must grant
|
1637
|
+
Service Account Token Creator IAM role to the directly preceding identity, with first
|
1638
|
+
account from the list granting this role to the originating account (templated).
|
1639
|
+
"""
|
1640
|
+
|
1641
|
+
template_fields: Sequence[str] = (
|
1642
|
+
"project_id",
|
1643
|
+
"gcp_conn_id",
|
1644
|
+
"name",
|
1645
|
+
"namespace",
|
1646
|
+
"cluster_name",
|
1647
|
+
"location",
|
1648
|
+
"impersonation_chain",
|
1649
|
+
)
|
1650
|
+
operator_extra_links = (KubernetesEngineJobLink(),)
|
1651
|
+
|
1652
|
+
def __init__(
|
1653
|
+
self,
|
1654
|
+
*,
|
1655
|
+
name: str,
|
1656
|
+
location: str,
|
1657
|
+
namespace: str,
|
1658
|
+
cluster_name: str,
|
1659
|
+
project_id: str = PROVIDE_PROJECT_ID,
|
1660
|
+
use_internal_ip: bool = False,
|
1661
|
+
gcp_conn_id: str = "google_cloud_default",
|
1662
|
+
impersonation_chain: str | Sequence[str] | None = None,
|
1663
|
+
**kwargs,
|
1664
|
+
) -> None:
|
1665
|
+
super().__init__(**kwargs)
|
1666
|
+
|
1667
|
+
self.project_id = project_id
|
1668
|
+
self.gcp_conn_id = gcp_conn_id
|
1669
|
+
self.location = location
|
1670
|
+
self.name = name
|
1671
|
+
self.namespace = namespace
|
1672
|
+
self.cluster_name = cluster_name
|
1673
|
+
self.use_internal_ip = use_internal_ip
|
1674
|
+
self.impersonation_chain = impersonation_chain
|
1675
|
+
|
1676
|
+
self.job: V1Job | None = None
|
1677
|
+
self._ssl_ca_cert: str
|
1678
|
+
self._cluster_url: str
|
1679
|
+
|
1680
|
+
@cached_property
|
1681
|
+
def cluster_hook(self) -> GKEHook:
|
1682
|
+
return GKEHook(
|
1683
|
+
gcp_conn_id=self.gcp_conn_id,
|
1684
|
+
location=self.location,
|
1685
|
+
impersonation_chain=self.impersonation_chain,
|
1686
|
+
)
|
1687
|
+
|
1688
|
+
@cached_property
|
1689
|
+
def hook(self) -> GKEKubernetesHook:
|
1690
|
+
self._cluster_url, self._ssl_ca_cert = GKEClusterAuthDetails(
|
1691
|
+
cluster_name=self.cluster_name,
|
1692
|
+
project_id=self.project_id,
|
1693
|
+
use_internal_ip=self.use_internal_ip,
|
1694
|
+
cluster_hook=self.cluster_hook,
|
1695
|
+
).fetch_cluster_info()
|
1696
|
+
|
1697
|
+
return GKEKubernetesHook(
|
1698
|
+
gcp_conn_id=self.gcp_conn_id,
|
1699
|
+
cluster_url=self._cluster_url,
|
1700
|
+
ssl_ca_cert=self._ssl_ca_cert,
|
1701
|
+
)
|
1702
|
+
|
1703
|
+
def execute(self, context: Context) -> None:
|
1704
|
+
self.job = self.hook.patch_namespaced_job(
|
1705
|
+
job_name=self.name,
|
1706
|
+
namespace=self.namespace,
|
1707
|
+
body={"spec": {"suspend": False}},
|
1708
|
+
)
|
1709
|
+
self.log.info(
|
1710
|
+
"Job %s from cluster %s was resumed.",
|
1711
|
+
self.name,
|
1712
|
+
self.cluster_name,
|
1713
|
+
)
|
1714
|
+
KubernetesEngineJobLink.persist(context=context, task_instance=self)
|
1715
|
+
|
1716
|
+
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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,
|