apache-airflow-providers-amazon 9.8.0rc1__py3-none-any.whl → 9.9.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.
Files changed (31) hide show
  1. airflow/providers/amazon/__init__.py +1 -1
  2. airflow/providers/amazon/aws/executors/aws_lambda/__init__.py +21 -0
  3. airflow/providers/amazon/aws/executors/aws_lambda/docker/Dockerfile +107 -0
  4. airflow/providers/amazon/aws/executors/aws_lambda/docker/__init__.py +16 -0
  5. airflow/providers/amazon/aws/executors/aws_lambda/docker/app.py +129 -0
  6. airflow/providers/amazon/aws/executors/aws_lambda/lambda_executor.py +479 -0
  7. airflow/providers/amazon/aws/executors/aws_lambda/utils.py +70 -0
  8. airflow/providers/amazon/aws/executors/ecs/ecs_executor.py +1 -1
  9. airflow/providers/amazon/aws/executors/ecs/ecs_executor_config.py +4 -8
  10. airflow/providers/amazon/aws/hooks/base_aws.py +20 -4
  11. airflow/providers/amazon/aws/hooks/eks.py +14 -5
  12. airflow/providers/amazon/aws/hooks/s3.py +101 -34
  13. airflow/providers/amazon/aws/hooks/sns.py +10 -1
  14. airflow/providers/amazon/aws/log/cloudwatch_task_handler.py +12 -5
  15. airflow/providers/amazon/aws/operators/batch.py +1 -2
  16. airflow/providers/amazon/aws/operators/cloud_formation.py +0 -2
  17. airflow/providers/amazon/aws/operators/comprehend.py +0 -2
  18. airflow/providers/amazon/aws/operators/dms.py +0 -2
  19. airflow/providers/amazon/aws/operators/ecs.py +1 -1
  20. airflow/providers/amazon/aws/operators/eks.py +13 -0
  21. airflow/providers/amazon/aws/operators/emr.py +4 -4
  22. airflow/providers/amazon/aws/operators/glue.py +0 -6
  23. airflow/providers/amazon/aws/operators/rds.py +0 -4
  24. airflow/providers/amazon/aws/operators/redshift_cluster.py +90 -63
  25. airflow/providers/amazon/aws/operators/sns.py +15 -1
  26. airflow/providers/amazon/aws/sensors/redshift_cluster.py +13 -10
  27. airflow/providers/amazon/get_provider_info.py +68 -0
  28. {apache_airflow_providers_amazon-9.8.0rc1.dist-info → apache_airflow_providers_amazon-9.9.0rc1.dist-info}/METADATA +15 -19
  29. {apache_airflow_providers_amazon-9.8.0rc1.dist-info → apache_airflow_providers_amazon-9.9.0rc1.dist-info}/RECORD +31 -25
  30. {apache_airflow_providers_amazon-9.8.0rc1.dist-info → apache_airflow_providers_amazon-9.9.0rc1.dist-info}/WHEEL +0 -0
  31. {apache_airflow_providers_amazon-9.8.0rc1.dist-info → apache_airflow_providers_amazon-9.9.0rc1.dist-info}/entry_points.txt +0 -0
@@ -193,6 +193,7 @@ class S3Hook(AwsBaseHook):
193
193
  ) -> None:
194
194
  kwargs["client_type"] = "s3"
195
195
  kwargs["aws_conn_id"] = aws_conn_id
196
+ self._requester_pays = kwargs.pop("requester_pays", False)
196
197
 
197
198
  if transfer_config_args and not isinstance(transfer_config_args, dict):
198
199
  raise TypeError(f"transfer_config_args expected dict, got {type(transfer_config_args).__name__}.")
@@ -409,12 +410,15 @@ class S3Hook(AwsBaseHook):
409
410
  }
410
411
 
411
412
  paginator = self.get_conn().get_paginator("list_objects_v2")
412
- response = paginator.paginate(
413
- Bucket=bucket_name,
414
- Prefix=prefix,
415
- Delimiter=delimiter,
416
- PaginationConfig=config,
417
- )
413
+ params = {
414
+ "Bucket": bucket_name,
415
+ "Prefix": prefix,
416
+ "Delimiter": delimiter,
417
+ "PaginationConfig": config,
418
+ }
419
+ if self._requester_pays:
420
+ params["RequestPayer"] = "requester"
421
+ response = paginator.paginate(**params)
418
422
 
419
423
  prefixes: list[str] = []
420
424
  for page in response:
@@ -437,7 +441,13 @@ class S3Hook(AwsBaseHook):
437
441
  """
438
442
  head_object_val: dict[str, Any] | None = None
439
443
  try:
440
- head_object_val = await client.head_object(Bucket=bucket_name, Key=key)
444
+ params = {
445
+ "Bucket": bucket_name,
446
+ "Key": key,
447
+ }
448
+ if self._requester_pays:
449
+ params["RequestPayer"] = "requester"
450
+ head_object_val = await client.head_object(**params)
441
451
  return head_object_val
442
452
  except ClientError as e:
443
453
  if e.response["ResponseMetadata"]["HTTPStatusCode"] == 404:
@@ -472,12 +482,15 @@ class S3Hook(AwsBaseHook):
472
482
  }
473
483
 
474
484
  paginator = client.get_paginator("list_objects_v2")
475
- response = paginator.paginate(
476
- Bucket=bucket_name,
477
- Prefix=prefix,
478
- Delimiter=delimiter,
479
- PaginationConfig=config,
480
- )
485
+ params = {
486
+ "Bucket": bucket_name,
487
+ "Prefix": prefix,
488
+ "Delimiter": delimiter,
489
+ "PaginationConfig": config,
490
+ }
491
+ if self._requester_pays:
492
+ params["RequestPayer"] = "requester"
493
+ response = paginator.paginate(**params)
481
494
 
482
495
  prefixes = []
483
496
  async for page in response:
@@ -501,7 +514,14 @@ class S3Hook(AwsBaseHook):
501
514
  prefix = re.split(r"[\[\*\?]", key, 1)[0] if key else ""
502
515
  delimiter = ""
503
516
  paginator = client.get_paginator("list_objects_v2")
504
- response = paginator.paginate(Bucket=bucket_name, Prefix=prefix, Delimiter=delimiter)
517
+ params = {
518
+ "Bucket": bucket_name,
519
+ "Prefix": prefix,
520
+ "Delimiter": delimiter,
521
+ }
522
+ if self._requester_pays:
523
+ params["RequestPayer"] = "requester"
524
+ response = paginator.paginate(**params)
505
525
  async for page in response:
506
526
  if "Contents" in page:
507
527
  for row in page["Contents"]:
@@ -622,14 +642,21 @@ class S3Hook(AwsBaseHook):
622
642
  prefix = re.split(r"[\[*?]", key, 1)[0]
623
643
 
624
644
  paginator = client.get_paginator("list_objects_v2")
625
- response = paginator.paginate(Bucket=bucket, Prefix=prefix, Delimiter=delimiter)
645
+ params = {
646
+ "Bucket": bucket,
647
+ "Prefix": prefix,
648
+ "Delimiter": delimiter,
649
+ }
650
+ if self._requester_pays:
651
+ params["RequestPayer"] = "requester"
652
+ response = paginator.paginate(**params)
626
653
  async for page in response:
627
654
  if "Contents" in page:
628
655
  keys.extend(k for k in page["Contents"] if isinstance(k.get("Size"), (int, float)))
629
656
  return keys
630
657
 
631
- @staticmethod
632
658
  async def _list_keys_async(
659
+ self,
633
660
  client: AioBaseClient,
634
661
  bucket_name: str | None = None,
635
662
  prefix: str | None = None,
@@ -655,12 +682,15 @@ class S3Hook(AwsBaseHook):
655
682
  }
656
683
 
657
684
  paginator = client.get_paginator("list_objects_v2")
658
- response = paginator.paginate(
659
- Bucket=bucket_name,
660
- Prefix=prefix,
661
- Delimiter=delimiter,
662
- PaginationConfig=config,
663
- )
685
+ params = {
686
+ "Bucket": bucket_name,
687
+ "Prefix": prefix,
688
+ "Delimiter": delimiter,
689
+ "PaginationConfig": config,
690
+ }
691
+ if self._requester_pays:
692
+ params["RequestPayer"] = "requester"
693
+ response = paginator.paginate(**params)
664
694
 
665
695
  keys = []
666
696
  async for page in response:
@@ -863,13 +893,16 @@ class S3Hook(AwsBaseHook):
863
893
  }
864
894
 
865
895
  paginator = self.get_conn().get_paginator("list_objects_v2")
866
- response = paginator.paginate(
867
- Bucket=bucket_name,
868
- Prefix=_prefix,
869
- Delimiter=delimiter,
870
- PaginationConfig=config,
871
- StartAfter=start_after_key,
872
- )
896
+ params = {
897
+ "Bucket": bucket_name,
898
+ "Prefix": _prefix,
899
+ "Delimiter": delimiter,
900
+ "PaginationConfig": config,
901
+ "StartAfter": start_after_key,
902
+ }
903
+ if self._requester_pays:
904
+ params["RequestPayer"] = "requester"
905
+ response = paginator.paginate(**params)
873
906
 
874
907
  keys: list[str] = []
875
908
  for page in response:
@@ -909,7 +942,14 @@ class S3Hook(AwsBaseHook):
909
942
  }
910
943
 
911
944
  paginator = self.get_conn().get_paginator("list_objects_v2")
912
- response = paginator.paginate(Bucket=bucket_name, Prefix=prefix, PaginationConfig=config)
945
+ params = {
946
+ "Bucket": bucket_name,
947
+ "Prefix": prefix,
948
+ "PaginationConfig": config,
949
+ }
950
+ if self._requester_pays:
951
+ params["RequestPayer"] = "requester"
952
+ response = paginator.paginate(**params)
913
953
 
914
954
  files = []
915
955
  for page in response:
@@ -931,7 +971,13 @@ class S3Hook(AwsBaseHook):
931
971
  :return: metadata of an object
932
972
  """
933
973
  try:
934
- return self.get_conn().head_object(Bucket=bucket_name, Key=key)
974
+ params = {
975
+ "Bucket": bucket_name,
976
+ "Key": key,
977
+ }
978
+ if self._requester_pays:
979
+ params["RequestPayer"] = "requester"
980
+ return self.get_conn().head_object(**params)
935
981
  except ClientError as e:
936
982
  if e.response["ResponseMetadata"]["HTTPStatusCode"] == 404:
937
983
  return None
@@ -975,8 +1021,11 @@ class S3Hook(AwsBaseHook):
975
1021
  if arg_name in S3Transfer.ALLOWED_DOWNLOAD_ARGS
976
1022
  }
977
1023
 
1024
+ params = sanitize_extra_args()
1025
+ if self._requester_pays:
1026
+ params["RequestPayer"] = "requester"
978
1027
  obj = self.resource.Object(bucket_name, key)
979
- obj.load(**sanitize_extra_args())
1028
+ obj.load(**params)
980
1029
  return obj
981
1030
 
982
1031
  @unify_bucket_name_and_key
@@ -1022,11 +1071,14 @@ class S3Hook(AwsBaseHook):
1022
1071
  """
1023
1072
  expression = expression or "SELECT * FROM S3Object"
1024
1073
  expression_type = expression_type or "SQL"
1074
+ extra_args = {}
1025
1075
 
1026
1076
  if input_serialization is None:
1027
1077
  input_serialization = {"CSV": {}}
1028
1078
  if output_serialization is None:
1029
1079
  output_serialization = {"CSV": {}}
1080
+ if self._requester_pays:
1081
+ extra_args["RequestPayer"] = "requester"
1030
1082
 
1031
1083
  response = self.get_conn().select_object_content(
1032
1084
  Bucket=bucket_name,
@@ -1035,6 +1087,7 @@ class S3Hook(AwsBaseHook):
1035
1087
  ExpressionType=expression_type,
1036
1088
  InputSerialization=input_serialization,
1037
1089
  OutputSerialization=output_serialization,
1090
+ ExtraArgs=extra_args,
1038
1091
  )
1039
1092
 
1040
1093
  return b"".join(
@@ -1124,6 +1177,8 @@ class S3Hook(AwsBaseHook):
1124
1177
  filename = filename_gz
1125
1178
  if acl_policy:
1126
1179
  extra_args["ACL"] = acl_policy
1180
+ if self._requester_pays:
1181
+ extra_args["RequestPayer"] = "requester"
1127
1182
 
1128
1183
  client = self.get_conn()
1129
1184
  client.upload_file(
@@ -1270,6 +1325,8 @@ class S3Hook(AwsBaseHook):
1270
1325
  extra_args["ServerSideEncryption"] = "AES256"
1271
1326
  if acl_policy:
1272
1327
  extra_args["ACL"] = acl_policy
1328
+ if self._requester_pays:
1329
+ extra_args["RequestPayer"] = "requester"
1273
1330
 
1274
1331
  client = self.get_conn()
1275
1332
  client.upload_fileobj(
@@ -1330,6 +1387,8 @@ class S3Hook(AwsBaseHook):
1330
1387
  kwargs["ACL"] = acl_policy
1331
1388
  if meta_data_directive:
1332
1389
  kwargs["MetadataDirective"] = meta_data_directive
1390
+ if self._requester_pays:
1391
+ kwargs["RequestPayer"] = "requester"
1333
1392
 
1334
1393
  dest_bucket_name, dest_bucket_key = self.get_s3_bucket_key(
1335
1394
  dest_bucket_name, dest_bucket_key, "dest_bucket_name", "dest_bucket_key"
@@ -1412,12 +1471,17 @@ class S3Hook(AwsBaseHook):
1412
1471
  keys = [keys]
1413
1472
 
1414
1473
  s3 = self.get_conn()
1474
+ extra_kwargs = {}
1475
+ if self._requester_pays:
1476
+ extra_kwargs["RequestPayer"] = "requester"
1415
1477
 
1416
1478
  # We can only send a maximum of 1000 keys per request.
1417
1479
  # For details see:
1418
1480
  # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.delete_objects
1419
1481
  for chunk in chunks(keys, chunk_size=1000):
1420
- response = s3.delete_objects(Bucket=bucket, Delete={"Objects": [{"Key": k} for k in chunk]})
1482
+ response = s3.delete_objects(
1483
+ Bucket=bucket, Delete={"Objects": [{"Key": k} for k in chunk]}, **extra_kwargs
1484
+ )
1421
1485
  deleted_keys = [x["Key"] for x in response.get("Deleted", [])]
1422
1486
  self.log.info("Deleted: %s", deleted_keys)
1423
1487
  if "Errors" in response:
@@ -1496,9 +1560,12 @@ class S3Hook(AwsBaseHook):
1496
1560
  file = NamedTemporaryFile(dir=local_path, prefix="airflow_tmp_", delete=False) # type: ignore
1497
1561
 
1498
1562
  with file:
1563
+ extra_args = {**self.extra_args}
1564
+ if self._requester_pays:
1565
+ extra_args["RequestPayer"] = "requester"
1499
1566
  s3_obj.download_fileobj(
1500
1567
  file,
1501
- ExtraArgs=self.extra_args,
1568
+ ExtraArgs=extra_args,
1502
1569
  Config=self.transfer_config,
1503
1570
  )
1504
1571
  get_hook_lineage_collector().add_input_asset(
@@ -60,6 +60,8 @@ class SnsHook(AwsBaseHook):
60
60
  message: str,
61
61
  subject: str | None = None,
62
62
  message_attributes: dict | None = None,
63
+ message_deduplication_id: str | None = None,
64
+ message_group_id: str | None = None,
63
65
  ):
64
66
  """
65
67
  Publish a message to a SNS topic or an endpoint.
@@ -77,7 +79,10 @@ class SnsHook(AwsBaseHook):
77
79
  - str = String
78
80
  - int, float = Number
79
81
  - iterable = String.Array
80
-
82
+ :param message_deduplication_id: Every message must have a unique message_deduplication_id.
83
+ This parameter applies only to FIFO (first-in-first-out) topics.
84
+ :param message_group_id: Tag that specifies that a message belongs to a specific message group.
85
+ This parameter applies only to FIFO (first-in-first-out) topics.
81
86
  """
82
87
  publish_kwargs: dict[str, str | dict] = {
83
88
  "TargetArn": target_arn,
@@ -88,6 +93,10 @@ class SnsHook(AwsBaseHook):
88
93
  # Construct args this way because boto3 distinguishes from missing args and those set to None
89
94
  if subject:
90
95
  publish_kwargs["Subject"] = subject
96
+ if message_deduplication_id:
97
+ publish_kwargs["MessageDeduplicationId"] = message_deduplication_id
98
+ if message_group_id:
99
+ publish_kwargs["MessageGroupId"] = message_group_id
91
100
  if message_attributes:
92
101
  publish_kwargs["MessageAttributes"] = {
93
102
  key: _get_message_attribute(val) for key, val in message_attributes.items()
@@ -125,10 +125,10 @@ class CloudWatchRemoteLogIO(LoggingMixin): # noqa: D101
125
125
  def proc(logger: structlog.typing.WrappedLogger, method_name: str, event: structlog.typing.EventDict):
126
126
  if not logger or not (stream_name := relative_path_from_logger(logger)):
127
127
  return event
128
- # Only init the handler stream_name once. We cannot do it above when we init the handler because
129
- # we don't yet know the log path at that point.
130
- if not _handler.log_stream_name:
131
- _handler.log_stream_name = stream_name.as_posix().replace(":", "_")
128
+ # We can't set the log stream name in the above init handler because
129
+ # the log path isn't known at that stage.
130
+ # Instead, we should always rely on the path (log stream name) provided by the logger.
131
+ _handler.log_stream_name = stream_name.as_posix().replace(":", "_")
132
132
  name = event.get("logger_name") or event.get("logger", "")
133
133
  level = structlog.stdlib.NAME_TO_LEVEL.get(method_name.lower(), logging.INFO)
134
134
  msg = copy.copy(event)
@@ -149,7 +149,14 @@ class CloudWatchRemoteLogIO(LoggingMixin): # noqa: D101
149
149
  return (proc,)
150
150
 
151
151
  def close(self):
152
- self.handler.close()
152
+ # Use the flush method to ensure all logs are sent to CloudWatch.
153
+ # Closing the handler sets `shutting_down` to True, which prevents any further logs from being sent.
154
+ # When `shutting_down` is True, means the logging system is in the process of shutting down,
155
+ # during which it attempts to flush the logs which are queued.
156
+ if self.handler is None or self.handler.shutting_down:
157
+ return
158
+
159
+ self.handler.flush()
153
160
 
154
161
  def upload(self, path: os.PathLike | str, ti: RuntimeTI):
155
162
  # No-op, as we upload via the processor as we go
@@ -32,7 +32,6 @@ from typing import TYPE_CHECKING, Any
32
32
 
33
33
  from airflow.configuration import conf
34
34
  from airflow.exceptions import AirflowException
35
- from airflow.models.mappedoperator import MappedOperator
36
35
  from airflow.providers.amazon.aws.hooks.batch_client import BatchClientHook
37
36
  from airflow.providers.amazon.aws.links.batch import (
38
37
  BatchJobDefinitionLink,
@@ -145,7 +144,7 @@ class BatchOperator(AwsBaseOperator[BatchClientHook]):
145
144
  def operator_extra_links(self):
146
145
  op_extra_links = [BatchJobDetailsLink()]
147
146
 
148
- if isinstance(self, MappedOperator):
147
+ if self.is_mapped:
149
148
  wait_for_completion = self.partial_kwargs.get(
150
149
  "wait_for_completion"
151
150
  ) or self.expand_input.value.get("wait_for_completion")
@@ -98,13 +98,11 @@ class CloudFormationDeleteStackOperator(AwsBaseOperator[CloudFormationHook]):
98
98
  *,
99
99
  stack_name: str,
100
100
  cloudformation_parameters: dict | None = None,
101
- aws_conn_id: str | None = "aws_default",
102
101
  **kwargs,
103
102
  ):
104
103
  super().__init__(**kwargs)
105
104
  self.cloudformation_parameters = cloudformation_parameters or {}
106
105
  self.stack_name = stack_name
107
- self.aws_conn_id = aws_conn_id
108
106
 
109
107
  def execute(self, context: Context):
110
108
  self.log.info("CloudFormation Parameters: %s", self.cloudformation_parameters)
@@ -289,7 +289,6 @@ class ComprehendCreateDocumentClassifierOperator(AwsBaseOperator[ComprehendHook]
289
289
  waiter_delay: int = 60,
290
290
  waiter_max_attempts: int = 20,
291
291
  deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
292
- aws_conn_id: str | None = "aws_default",
293
292
  **kwargs,
294
293
  ):
295
294
  super().__init__(**kwargs)
@@ -305,7 +304,6 @@ class ComprehendCreateDocumentClassifierOperator(AwsBaseOperator[ComprehendHook]
305
304
  self.waiter_delay = waiter_delay
306
305
  self.waiter_max_attempts = waiter_max_attempts
307
306
  self.deferrable = deferrable
308
- self.aws_conn_id = aws_conn_id
309
307
 
310
308
  def execute(self, context: Context) -> str:
311
309
  if self.output_data_config:
@@ -91,7 +91,6 @@ class DmsCreateTaskOperator(AwsBaseOperator[DmsHook]):
91
91
  table_mappings: dict,
92
92
  migration_type: str = "full-load",
93
93
  create_task_kwargs: dict | None = None,
94
- aws_conn_id: str | None = "aws_default",
95
94
  **kwargs,
96
95
  ):
97
96
  super().__init__(**kwargs)
@@ -102,7 +101,6 @@ class DmsCreateTaskOperator(AwsBaseOperator[DmsHook]):
102
101
  self.migration_type = migration_type
103
102
  self.table_mappings = table_mappings
104
103
  self.create_task_kwargs = create_task_kwargs or {}
105
- self.aws_conn_id = aws_conn_id
106
104
 
107
105
  def execute(self, context: Context):
108
106
  """
@@ -517,7 +517,7 @@ class EcsRunTaskOperator(EcsBaseOperator):
517
517
  if self.reattach:
518
518
  # Generate deterministic UUID which refers to unique TaskInstanceKey
519
519
  ti: TaskInstance = context["ti"]
520
- self._started_by = generate_uuid(*map(str, ti.key.primary))
520
+ self._started_by = generate_uuid(*map(str, [ti.dag_id, ti.task_id, ti.run_id, ti.map_index]))
521
521
  self.log.info("Try to find run with startedBy=%r", self._started_by)
522
522
  self._try_reattach_task(started_by=self._started_by)
523
523
 
@@ -1056,6 +1056,7 @@ class EksPodOperator(KubernetesPodOperator):
1056
1056
  in_cluster=self.in_cluster,
1057
1057
  namespace=self.namespace,
1058
1058
  name=self.pod_name,
1059
+ trigger_kwargs={"eks_cluster_name": cluster_name},
1059
1060
  **kwargs,
1060
1061
  )
1061
1062
  # There is no need to manage the kube_config file, as it will be generated automatically.
@@ -1072,3 +1073,15 @@ class EksPodOperator(KubernetesPodOperator):
1072
1073
  eks_cluster_name=self.cluster_name, pod_namespace=self.namespace
1073
1074
  ) as self.config_file:
1074
1075
  return super().execute(context)
1076
+
1077
+ def trigger_reentry(self, context: Context, event: dict[str, Any]) -> Any:
1078
+ eks_hook = EksHook(
1079
+ aws_conn_id=self.aws_conn_id,
1080
+ region_name=self.region,
1081
+ )
1082
+ eks_cluster_name = event["eks_cluster_name"]
1083
+ pod_namespace = event["namespace"]
1084
+ with eks_hook.generate_config_file(
1085
+ eks_cluster_name=eks_cluster_name, pod_namespace=pod_namespace
1086
+ ) as self.config_file:
1087
+ return super().trigger_reentry(context, event)
@@ -984,7 +984,7 @@ class EmrServerlessCreateApplicationOperator(AwsBaseOperator[EmrServerlessHook])
984
984
  :param region_name: AWS region_name. If not specified then the default boto3 behaviour is used.
985
985
  :param verify: Whether or not to verify SSL certificates. See:
986
986
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html
987
- :waiter_max_attempts: Number of times the waiter should poll the application to check the state.
987
+ :param waiter_max_attempts: Number of times the waiter should poll the application to check the state.
988
988
  If not set, the waiter will use its default value.
989
989
  :param waiter_delay: Number of seconds between polling the state of the application.
990
990
  :param deferrable: If True, the operator will wait asynchronously for application to be created.
@@ -1128,7 +1128,7 @@ class EmrServerlessStartJobOperator(AwsBaseOperator[EmrServerlessHook]):
1128
1128
  :param verify: Whether or not to verify SSL certificates. See:
1129
1129
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html
1130
1130
  :param name: Name for the EMR Serverless job. If not provided, a default name will be assigned.
1131
- :waiter_max_attempts: Number of times the waiter should poll the application to check the state.
1131
+ :param waiter_max_attempts: Number of times the waiter should poll the application to check the state.
1132
1132
  If not set, the waiter will use its default value.
1133
1133
  :param waiter_delay: Number of seconds between polling the state of the job run.
1134
1134
  :param deferrable: If True, the operator will wait asynchronously for the crawl to complete.
@@ -1438,7 +1438,7 @@ class EmrServerlessStopApplicationOperator(AwsBaseOperator[EmrServerlessHook]):
1438
1438
  Otherwise, trying to stop an app with running jobs will return an error.
1439
1439
  If you want to wait for the jobs to finish gracefully, use
1440
1440
  :class:`airflow.providers.amazon.aws.sensors.emr.EmrServerlessJobSensor`
1441
- :waiter_max_attempts: Number of times the waiter should poll the application to check the state.
1441
+ :param waiter_max_attempts: Number of times the waiter should poll the application to check the state.
1442
1442
  Default is 25.
1443
1443
  :param waiter_delay: Number of seconds between polling the state of the application.
1444
1444
  Default is 60 seconds.
@@ -1573,7 +1573,7 @@ class EmrServerlessDeleteApplicationOperator(EmrServerlessStopApplicationOperato
1573
1573
  :param region_name: AWS region_name. If not specified then the default boto3 behaviour is used.
1574
1574
  :param verify: Whether or not to verify SSL certificates. See:
1575
1575
  https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html
1576
- :waiter_max_attempts: Number of times the waiter should poll the application to check the state.
1576
+ :param waiter_max_attempts: Number of times the waiter should poll the application to check the state.
1577
1577
  Defaults to 25.
1578
1578
  :param waiter_delay: Number of seconds between polling the state of the application.
1579
1579
  Defaults to 60 seconds.
@@ -313,7 +313,6 @@ class GlueDataQualityOperator(AwsBaseOperator[GlueDataQualityHook]):
313
313
  description: str = "AWS Glue Data Quality Rule Set With Airflow",
314
314
  update_rule_set: bool = False,
315
315
  data_quality_ruleset_kwargs: dict | None = None,
316
- aws_conn_id: str | None = "aws_default",
317
316
  **kwargs,
318
317
  ):
319
318
  super().__init__(**kwargs)
@@ -322,7 +321,6 @@ class GlueDataQualityOperator(AwsBaseOperator[GlueDataQualityHook]):
322
321
  self.description = description
323
322
  self.update_rule_set = update_rule_set
324
323
  self.data_quality_ruleset_kwargs = data_quality_ruleset_kwargs or {}
325
- self.aws_conn_id = aws_conn_id
326
324
 
327
325
  def validate_inputs(self) -> None:
328
326
  if not self.ruleset.startswith("Rules") or not self.ruleset.endswith("]"):
@@ -421,7 +419,6 @@ class GlueDataQualityRuleSetEvaluationRunOperator(AwsBaseOperator[GlueDataQualit
421
419
  waiter_delay: int = 60,
422
420
  waiter_max_attempts: int = 20,
423
421
  deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
424
- aws_conn_id: str | None = "aws_default",
425
422
  **kwargs,
426
423
  ):
427
424
  super().__init__(**kwargs)
@@ -437,7 +434,6 @@ class GlueDataQualityRuleSetEvaluationRunOperator(AwsBaseOperator[GlueDataQualit
437
434
  self.waiter_delay = waiter_delay
438
435
  self.waiter_max_attempts = waiter_max_attempts
439
436
  self.deferrable = deferrable
440
- self.aws_conn_id = aws_conn_id
441
437
 
442
438
  def validate_inputs(self) -> None:
443
439
  glue_table = self.datasource.get("GlueTable", {})
@@ -584,7 +580,6 @@ class GlueDataQualityRuleRecommendationRunOperator(AwsBaseOperator[GlueDataQuali
584
580
  waiter_delay: int = 60,
585
581
  waiter_max_attempts: int = 20,
586
582
  deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
587
- aws_conn_id: str | None = "aws_default",
588
583
  **kwargs,
589
584
  ):
590
585
  super().__init__(**kwargs)
@@ -598,7 +593,6 @@ class GlueDataQualityRuleRecommendationRunOperator(AwsBaseOperator[GlueDataQuali
598
593
  self.waiter_delay = waiter_delay
599
594
  self.waiter_max_attempts = waiter_max_attempts
600
595
  self.deferrable = deferrable
601
- self.aws_conn_id = aws_conn_id
602
596
 
603
597
  def execute(self, context: Context) -> str:
604
598
  glue_table = self.datasource.get("GlueTable", {})
@@ -54,12 +54,8 @@ class RdsBaseOperator(AwsBaseOperator[RdsHook]):
54
54
  def __init__(
55
55
  self,
56
56
  *args,
57
- aws_conn_id: str | None = "aws_conn_id",
58
- region_name: str | None = None,
59
57
  **kwargs,
60
58
  ):
61
- self.aws_conn_id = aws_conn_id
62
- self.region_name = region_name
63
59
  super().__init__(*args, **kwargs)
64
60
 
65
61
  self._await_interval = 60 # seconds