acryl-datahub 0.15.0.1rc2__py3-none-any.whl → 0.15.0.1rc4__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.
Potentially problematic release.
This version of acryl-datahub might be problematic. Click here for more details.
- {acryl_datahub-0.15.0.1rc2.dist-info → acryl_datahub-0.15.0.1rc4.dist-info}/METADATA +2359 -2359
- {acryl_datahub-0.15.0.1rc2.dist-info → acryl_datahub-0.15.0.1rc4.dist-info}/RECORD +10 -10
- datahub/__init__.py +1 -1
- datahub/ingestion/source/aws/aws_common.py +231 -27
- datahub/ingestion/source/powerbi/powerbi-lexical-grammar.rule +16 -2
- datahub/ingestion/source/sql/hive.py +606 -8
- datahub/ingestion/source/tableau/tableau.py +11 -7
- {acryl_datahub-0.15.0.1rc2.dist-info → acryl_datahub-0.15.0.1rc4.dist-info}/WHEEL +0 -0
- {acryl_datahub-0.15.0.1rc2.dist-info → acryl_datahub-0.15.0.1rc4.dist-info}/entry_points.txt +0 -0
- {acryl_datahub-0.15.0.1rc2.dist-info → acryl_datahub-0.15.0.1rc4.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
datahub/__init__.py,sha256=
|
|
1
|
+
datahub/__init__.py,sha256=xj1tZWzMrO5870oYWLdzPRRtS9Tvh00hceW9--1K46o,576
|
|
2
2
|
datahub/__main__.py,sha256=pegIvQ9hzK7IhqVeUi1MeADSZ2QlP-D3K0OQdEg55RU,106
|
|
3
3
|
datahub/entrypoints.py,sha256=3-qSfXAx3Z0FEkBV5tlO8fQr4xk4ySeDRMVTpS5Xd6A,7793
|
|
4
4
|
datahub/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -216,7 +216,7 @@ datahub/ingestion/source/abs/profiling.py,sha256=yKNCKpr6w7qpCH-baeSkNE9VjkN6eBo
|
|
|
216
216
|
datahub/ingestion/source/abs/report.py,sha256=fzkTdTewYlWrTk4f2Cyl-e8RV4qw9wEVtm0cdKD-Xgw,542
|
|
217
217
|
datahub/ingestion/source/abs/source.py,sha256=pzxW-R_cWGKPneEhX8JWdTZiX2k1kAZOPKgMxp9mAEI,24533
|
|
218
218
|
datahub/ingestion/source/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
219
|
-
datahub/ingestion/source/aws/aws_common.py,sha256=
|
|
219
|
+
datahub/ingestion/source/aws/aws_common.py,sha256=DfdQgkJ_s2isFx8WvqKTlAcBk4KE8SgfpmA5BgC3fgY,17716
|
|
220
220
|
datahub/ingestion/source/aws/glue.py,sha256=fX0dtaVVq174ZS0aBJvZFYK8ligfZX5EU3pdS3j1KQs,56215
|
|
221
221
|
datahub/ingestion/source/aws/s3_boto_utils.py,sha256=Wyp9k9tapsCuw9dyH4FCXJr_wmeLaYFoCtKvrV6SEDk,3892
|
|
222
222
|
datahub/ingestion/source/aws/s3_util.py,sha256=OFypcgmVC6jnZM90-gjcPpAMtTV1lbnreCaMhCzNlzs,2149
|
|
@@ -358,7 +358,7 @@ datahub/ingestion/source/neo4j/neo4j_source.py,sha256=L9WiZ5yZrIDMrgj3gYU9j6zz3T
|
|
|
358
358
|
datahub/ingestion/source/powerbi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
359
359
|
datahub/ingestion/source/powerbi/config.py,sha256=9cgMrwp3DQqv14iTqulAONkbVe5nhycJ1ElkA_275go,22732
|
|
360
360
|
datahub/ingestion/source/powerbi/dataplatform_instance_resolver.py,sha256=-njW1kJOy-LY5JFwJLhVQ0bMBj9NQz5TZhQqsSi_KsM,2285
|
|
361
|
-
datahub/ingestion/source/powerbi/powerbi-lexical-grammar.rule,sha256=
|
|
361
|
+
datahub/ingestion/source/powerbi/powerbi-lexical-grammar.rule,sha256=5df3qvalCS9hZ46DPXs6XDcw9-IofGf8Eol_rUC7LHI,20329
|
|
362
362
|
datahub/ingestion/source/powerbi/powerbi.py,sha256=7UsAEqaFlkWONcXJdQ2hotUYYn46ks6Fe71KXEMh7lI,54495
|
|
363
363
|
datahub/ingestion/source/powerbi/m_query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
364
364
|
datahub/ingestion/source/powerbi/m_query/data_classes.py,sha256=EbaEasEOGZ73jz0cQofH9ez65wSvRBof0R6GQaIVLnM,2009
|
|
@@ -451,7 +451,7 @@ datahub/ingestion/source/sql/clickhouse.py,sha256=jzvaXP5Wr0SMhj2rtuvVE821xnfpKi
|
|
|
451
451
|
datahub/ingestion/source/sql/cockroachdb.py,sha256=XaD7eae34plU9ISRC6PzYX9q6RdT2qkzjH6CpTOgkx4,1443
|
|
452
452
|
datahub/ingestion/source/sql/druid.py,sha256=lhO9CCOlHV-6LjBuAxAxtB9I1pvPtsGSdr63bz6_ilA,2837
|
|
453
453
|
datahub/ingestion/source/sql/hana.py,sha256=0PIvcX0Rz59NyR7Ag5Bv1MBV_UbJwxl9UAopo_xe_CA,1342
|
|
454
|
-
datahub/ingestion/source/sql/hive.py,sha256=
|
|
454
|
+
datahub/ingestion/source/sql/hive.py,sha256=Ueicc3EhKQSC77IDzl_xcTDDalbH1pvB8mox1oFI4Hw,29738
|
|
455
455
|
datahub/ingestion/source/sql/hive_metastore.py,sha256=PisLrswev583xW0xDJ5yfKWCWm_ZTl1OeuaMcv_SvXc,35865
|
|
456
456
|
datahub/ingestion/source/sql/mariadb.py,sha256=Hm102kmfs_1rd4lsTYhzVMZq5S3B6cyfvpHSzJjqvMw,737
|
|
457
457
|
datahub/ingestion/source/sql/mysql.py,sha256=nDWK4YbqomcJgnit9b8geUGrp_3eix4bt0_k94o7g-0,3350
|
|
@@ -491,7 +491,7 @@ datahub/ingestion/source/state_provider/datahub_ingestion_checkpointing_provider
|
|
|
491
491
|
datahub/ingestion/source/state_provider/file_ingestion_checkpointing_provider.py,sha256=xsH7Ao_05VTjqpkzLkhdf5B1ULMzFoD8vkJJIJU9w-U,4077
|
|
492
492
|
datahub/ingestion/source/state_provider/state_provider_registry.py,sha256=SVq4mIyGNmLXE9OZx1taOiNPqDoQp03-Ot9rYnB5F3k,401
|
|
493
493
|
datahub/ingestion/source/tableau/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
494
|
-
datahub/ingestion/source/tableau/tableau.py,sha256=
|
|
494
|
+
datahub/ingestion/source/tableau/tableau.py,sha256=5oyAoF7h92zUTh9NIaYipyRXUFUZSz1oo8hwn46RM2w,138661
|
|
495
495
|
datahub/ingestion/source/tableau/tableau_common.py,sha256=9gQLq_3BlAsKll83uVlnWJRWaIDtFtREUyuimXF13Z0,26219
|
|
496
496
|
datahub/ingestion/source/tableau/tableau_constant.py,sha256=ZcAeHsQUXVVL26ORly0ByZk_GJAFbxaKuJAlX_sYMac,2686
|
|
497
497
|
datahub/ingestion/source/tableau/tableau_server_wrapper.py,sha256=nSyx9RzC6TCQDm-cTVJ657qT8iDwzk_8JMKpohhmOc4,1046
|
|
@@ -981,8 +981,8 @@ datahub_provider/operators/datahub_assertion_operator.py,sha256=uvTQ-jk2F0sbqqxp
|
|
|
981
981
|
datahub_provider/operators/datahub_assertion_sensor.py,sha256=lCBj_3x1cf5GMNpHdfkpHuyHfVxsm6ff5x2Z5iizcAo,140
|
|
982
982
|
datahub_provider/operators/datahub_operation_operator.py,sha256=aevDp2FzX7FxGlXrR0khoHNbxbhKR2qPEX5e8O2Jyzw,174
|
|
983
983
|
datahub_provider/operators/datahub_operation_sensor.py,sha256=8fcdVBCEPgqy1etTXgLoiHoJrRt_nzFZQMdSzHqSG7M,168
|
|
984
|
-
acryl_datahub-0.15.0.
|
|
985
|
-
acryl_datahub-0.15.0.
|
|
986
|
-
acryl_datahub-0.15.0.
|
|
987
|
-
acryl_datahub-0.15.0.
|
|
988
|
-
acryl_datahub-0.15.0.
|
|
984
|
+
acryl_datahub-0.15.0.1rc4.dist-info/METADATA,sha256=i_9pmgefT8nmwwsz_l6hvTGQHT3yUBsFF8kImMd9aco,173642
|
|
985
|
+
acryl_datahub-0.15.0.1rc4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
986
|
+
acryl_datahub-0.15.0.1rc4.dist-info/entry_points.txt,sha256=xnPSPLK3bJGADxe4TDS4wL4u0FT_PGlahDa-ENYdYCQ,9512
|
|
987
|
+
acryl_datahub-0.15.0.1rc4.dist-info/top_level.txt,sha256=iLjSrLK5ox1YVYcglRUkcvfZPvKlobBWx7CTUXx8_GI,25
|
|
988
|
+
acryl_datahub-0.15.0.1rc4.dist-info/RECORD,,
|
datahub/__init__.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
1
3
|
from datetime import datetime, timedelta, timezone
|
|
2
|
-
from
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from http import HTTPStatus
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union
|
|
3
7
|
|
|
4
8
|
import boto3
|
|
9
|
+
import requests
|
|
5
10
|
from boto3.session import Session
|
|
6
11
|
from botocore.config import DEFAULT_TIMEOUT, Config
|
|
7
12
|
from botocore.utils import fix_s3_host
|
|
@@ -14,6 +19,8 @@ from datahub.configuration.common import (
|
|
|
14
19
|
)
|
|
15
20
|
from datahub.configuration.source_common import EnvConfigMixin
|
|
16
21
|
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
17
24
|
if TYPE_CHECKING:
|
|
18
25
|
from mypy_boto3_dynamodb import DynamoDBClient
|
|
19
26
|
from mypy_boto3_glue import GlueClient
|
|
@@ -22,6 +29,26 @@ if TYPE_CHECKING:
|
|
|
22
29
|
from mypy_boto3_sts import STSClient
|
|
23
30
|
|
|
24
31
|
|
|
32
|
+
class AwsEnvironment(Enum):
|
|
33
|
+
EC2 = "EC2"
|
|
34
|
+
ECS = "ECS"
|
|
35
|
+
EKS = "EKS"
|
|
36
|
+
LAMBDA = "LAMBDA"
|
|
37
|
+
APP_RUNNER = "APP_RUNNER"
|
|
38
|
+
BEANSTALK = "ELASTIC_BEANSTALK"
|
|
39
|
+
CLOUD_FORMATION = "CLOUD_FORMATION"
|
|
40
|
+
UNKNOWN = "UNKNOWN"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AwsServicePrincipal(Enum):
|
|
44
|
+
LAMBDA = "lambda.amazonaws.com"
|
|
45
|
+
EKS = "eks.amazonaws.com"
|
|
46
|
+
APP_RUNNER = "apprunner.amazonaws.com"
|
|
47
|
+
ECS = "ecs.amazonaws.com"
|
|
48
|
+
ELASTIC_BEANSTALK = "elasticbeanstalk.amazonaws.com"
|
|
49
|
+
EC2 = "ec2.amazonaws.com"
|
|
50
|
+
|
|
51
|
+
|
|
25
52
|
class AwsAssumeRoleConfig(PermissiveConfigModel):
|
|
26
53
|
# Using the PermissiveConfigModel to allow the user to pass additional arguments.
|
|
27
54
|
|
|
@@ -34,6 +61,163 @@ class AwsAssumeRoleConfig(PermissiveConfigModel):
|
|
|
34
61
|
)
|
|
35
62
|
|
|
36
63
|
|
|
64
|
+
def get_instance_metadata_token() -> Optional[str]:
|
|
65
|
+
"""Get IMDSv2 token"""
|
|
66
|
+
try:
|
|
67
|
+
response = requests.put(
|
|
68
|
+
"http://169.254.169.254/latest/api/token",
|
|
69
|
+
headers={"X-aws-ec2-metadata-token-ttl-seconds": "21600"},
|
|
70
|
+
timeout=1,
|
|
71
|
+
)
|
|
72
|
+
if response.status_code == HTTPStatus.OK:
|
|
73
|
+
return response.text
|
|
74
|
+
except requests.exceptions.RequestException:
|
|
75
|
+
logger.debug("Failed to get IMDSv2 token")
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def is_running_on_ec2() -> bool:
|
|
80
|
+
"""Check if code is running on EC2 using IMDSv2"""
|
|
81
|
+
token = get_instance_metadata_token()
|
|
82
|
+
if not token:
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
response = requests.get(
|
|
87
|
+
"http://169.254.169.254/latest/meta-data/instance-id",
|
|
88
|
+
headers={"X-aws-ec2-metadata-token": token},
|
|
89
|
+
timeout=1,
|
|
90
|
+
)
|
|
91
|
+
return response.status_code == HTTPStatus.OK
|
|
92
|
+
except requests.exceptions.RequestException:
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def detect_aws_environment() -> AwsEnvironment:
|
|
97
|
+
"""
|
|
98
|
+
Detect the AWS environment we're running in.
|
|
99
|
+
Order matters as some environments may have multiple indicators.
|
|
100
|
+
"""
|
|
101
|
+
# Check Lambda first as it's most specific
|
|
102
|
+
if os.getenv("AWS_LAMBDA_FUNCTION_NAME"):
|
|
103
|
+
if os.getenv("AWS_EXECUTION_ENV", "").startswith("CloudFormation"):
|
|
104
|
+
return AwsEnvironment.CLOUD_FORMATION
|
|
105
|
+
return AwsEnvironment.LAMBDA
|
|
106
|
+
|
|
107
|
+
# Check EKS (IRSA)
|
|
108
|
+
if os.getenv("AWS_WEB_IDENTITY_TOKEN_FILE") and os.getenv("AWS_ROLE_ARN"):
|
|
109
|
+
return AwsEnvironment.EKS
|
|
110
|
+
|
|
111
|
+
# Check App Runner
|
|
112
|
+
if os.getenv("AWS_APP_RUNNER_SERVICE_ID"):
|
|
113
|
+
return AwsEnvironment.APP_RUNNER
|
|
114
|
+
|
|
115
|
+
# Check ECS
|
|
116
|
+
if os.getenv("ECS_CONTAINER_METADATA_URI_V4") or os.getenv(
|
|
117
|
+
"ECS_CONTAINER_METADATA_URI"
|
|
118
|
+
):
|
|
119
|
+
return AwsEnvironment.ECS
|
|
120
|
+
|
|
121
|
+
# Check Elastic Beanstalk
|
|
122
|
+
if os.getenv("ELASTIC_BEANSTALK_ENVIRONMENT_NAME"):
|
|
123
|
+
return AwsEnvironment.BEANSTALK
|
|
124
|
+
|
|
125
|
+
if is_running_on_ec2():
|
|
126
|
+
return AwsEnvironment.EC2
|
|
127
|
+
|
|
128
|
+
return AwsEnvironment.UNKNOWN
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_instance_role_arn() -> Optional[str]:
|
|
132
|
+
"""Get role ARN from EC2 instance metadata using IMDSv2"""
|
|
133
|
+
token = get_instance_metadata_token()
|
|
134
|
+
if not token:
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
response = requests.get(
|
|
139
|
+
"http://169.254.169.254/latest/meta-data/iam/security-credentials/",
|
|
140
|
+
headers={"X-aws-ec2-metadata-token": token},
|
|
141
|
+
timeout=1,
|
|
142
|
+
)
|
|
143
|
+
if response.status_code == 200:
|
|
144
|
+
role_name = response.text.strip()
|
|
145
|
+
if role_name:
|
|
146
|
+
sts = boto3.client("sts")
|
|
147
|
+
identity = sts.get_caller_identity()
|
|
148
|
+
return identity.get("Arn")
|
|
149
|
+
except Exception as e:
|
|
150
|
+
logger.debug(f"Failed to get instance role ARN: {e}")
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def get_lambda_role_arn() -> Optional[str]:
|
|
155
|
+
"""Get the Lambda function's role ARN"""
|
|
156
|
+
try:
|
|
157
|
+
function_name = os.getenv("AWS_LAMBDA_FUNCTION_NAME")
|
|
158
|
+
if not function_name:
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
lambda_client = boto3.client("lambda")
|
|
162
|
+
function_config = lambda_client.get_function_configuration(
|
|
163
|
+
FunctionName=function_name
|
|
164
|
+
)
|
|
165
|
+
return function_config.get("Role")
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.debug(f"Failed to get Lambda role ARN: {e}")
|
|
168
|
+
return None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def get_current_identity() -> Tuple[Optional[str], Optional[str]]:
|
|
172
|
+
"""
|
|
173
|
+
Get the current role ARN and source type based on the runtime environment.
|
|
174
|
+
Returns (role_arn, credential_source)
|
|
175
|
+
"""
|
|
176
|
+
env = detect_aws_environment()
|
|
177
|
+
|
|
178
|
+
if env == AwsEnvironment.LAMBDA:
|
|
179
|
+
role_arn = get_lambda_role_arn()
|
|
180
|
+
return role_arn, AwsServicePrincipal.LAMBDA.value
|
|
181
|
+
|
|
182
|
+
elif env == AwsEnvironment.EKS:
|
|
183
|
+
role_arn = os.getenv("AWS_ROLE_ARN")
|
|
184
|
+
return role_arn, AwsServicePrincipal.EKS.value
|
|
185
|
+
|
|
186
|
+
elif env == AwsEnvironment.APP_RUNNER:
|
|
187
|
+
try:
|
|
188
|
+
sts = boto3.client("sts")
|
|
189
|
+
identity = sts.get_caller_identity()
|
|
190
|
+
return identity.get("Arn"), AwsServicePrincipal.APP_RUNNER.value
|
|
191
|
+
except Exception as e:
|
|
192
|
+
logger.debug(f"Failed to get App Runner role: {e}")
|
|
193
|
+
|
|
194
|
+
elif env == AwsEnvironment.ECS:
|
|
195
|
+
try:
|
|
196
|
+
metadata_uri = os.getenv("ECS_CONTAINER_METADATA_URI_V4") or os.getenv(
|
|
197
|
+
"ECS_CONTAINER_METADATA_URI"
|
|
198
|
+
)
|
|
199
|
+
if metadata_uri:
|
|
200
|
+
response = requests.get(f"{metadata_uri}/task", timeout=1)
|
|
201
|
+
if response.status_code == HTTPStatus.OK:
|
|
202
|
+
task_metadata = response.json()
|
|
203
|
+
if "TaskARN" in task_metadata:
|
|
204
|
+
return (
|
|
205
|
+
task_metadata.get("TaskARN"),
|
|
206
|
+
AwsServicePrincipal.ECS.value,
|
|
207
|
+
)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
logger.debug(f"Failed to get ECS task role: {e}")
|
|
210
|
+
|
|
211
|
+
elif env == AwsEnvironment.BEANSTALK:
|
|
212
|
+
# Beanstalk uses EC2 instance metadata
|
|
213
|
+
return get_instance_role_arn(), AwsServicePrincipal.ELASTIC_BEANSTALK.value
|
|
214
|
+
|
|
215
|
+
elif env == AwsEnvironment.EC2:
|
|
216
|
+
return get_instance_role_arn(), AwsServicePrincipal.EC2.value
|
|
217
|
+
|
|
218
|
+
return None, None
|
|
219
|
+
|
|
220
|
+
|
|
37
221
|
def assume_role(
|
|
38
222
|
role: AwsAssumeRoleConfig,
|
|
39
223
|
aws_region: Optional[str],
|
|
@@ -95,7 +279,7 @@ class AwsConnectionConfig(ConfigModel):
|
|
|
95
279
|
)
|
|
96
280
|
aws_profile: Optional[str] = Field(
|
|
97
281
|
default=None,
|
|
98
|
-
description="
|
|
282
|
+
description="The [named profile](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) to use from AWS credentials. Falls back to default profile if not specified and no access keys provided. Profiles are configured in ~/.aws/credentials or ~/.aws/config.",
|
|
99
283
|
)
|
|
100
284
|
aws_region: Optional[str] = Field(None, description="AWS region code.")
|
|
101
285
|
|
|
@@ -145,6 +329,7 @@ class AwsConnectionConfig(ConfigModel):
|
|
|
145
329
|
|
|
146
330
|
def get_session(self) -> Session:
|
|
147
331
|
if self.aws_access_key_id and self.aws_secret_access_key:
|
|
332
|
+
# Explicit credentials take precedence
|
|
148
333
|
session = Session(
|
|
149
334
|
aws_access_key_id=self.aws_access_key_id,
|
|
150
335
|
aws_secret_access_key=self.aws_secret_access_key,
|
|
@@ -152,38 +337,57 @@ class AwsConnectionConfig(ConfigModel):
|
|
|
152
337
|
region_name=self.aws_region,
|
|
153
338
|
)
|
|
154
339
|
elif self.aws_profile:
|
|
340
|
+
# Named profile is second priority
|
|
155
341
|
session = Session(
|
|
156
342
|
region_name=self.aws_region, profile_name=self.aws_profile
|
|
157
343
|
)
|
|
158
344
|
else:
|
|
159
|
-
# Use boto3's credential autodetection
|
|
345
|
+
# Use boto3's credential autodetection
|
|
160
346
|
session = Session(region_name=self.aws_region)
|
|
161
347
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
348
|
+
target_roles = self._normalized_aws_roles()
|
|
349
|
+
if target_roles:
|
|
350
|
+
current_role_arn, credential_source = get_current_identity()
|
|
351
|
+
|
|
352
|
+
# Only assume role if:
|
|
353
|
+
# 1. We're not in a known AWS environment with a role, or
|
|
354
|
+
# 2. We need to assume a different role than our current one
|
|
355
|
+
should_assume_role = current_role_arn is None or any(
|
|
356
|
+
role.RoleArn != current_role_arn for role in target_roles
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
if should_assume_role:
|
|
360
|
+
env = detect_aws_environment()
|
|
361
|
+
logger.debug(f"Assuming role(s) from {env.value} environment")
|
|
362
|
+
|
|
363
|
+
current_credentials = session.get_credentials()
|
|
364
|
+
if current_credentials is None:
|
|
365
|
+
raise ValueError("No credentials available for role assumption")
|
|
366
|
+
|
|
367
|
+
credentials = {
|
|
368
|
+
"AccessKeyId": current_credentials.access_key,
|
|
369
|
+
"SecretAccessKey": current_credentials.secret_key,
|
|
370
|
+
"SessionToken": current_credentials.token,
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
for role in target_roles:
|
|
374
|
+
if self._should_refresh_credentials():
|
|
375
|
+
credentials = assume_role(
|
|
376
|
+
role=role,
|
|
377
|
+
aws_region=self.aws_region,
|
|
378
|
+
credentials=credentials,
|
|
379
|
+
)
|
|
380
|
+
if isinstance(credentials["Expiration"], datetime):
|
|
381
|
+
self._credentials_expiration = credentials["Expiration"]
|
|
382
|
+
|
|
383
|
+
session = Session(
|
|
384
|
+
aws_access_key_id=credentials["AccessKeyId"],
|
|
385
|
+
aws_secret_access_key=credentials["SecretAccessKey"],
|
|
386
|
+
aws_session_token=credentials["SessionToken"],
|
|
387
|
+
region_name=self.aws_region,
|
|
177
388
|
)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
session = Session(
|
|
182
|
-
aws_access_key_id=credentials["AccessKeyId"],
|
|
183
|
-
aws_secret_access_key=credentials["SecretAccessKey"],
|
|
184
|
-
aws_session_token=credentials["SessionToken"],
|
|
185
|
-
region_name=self.aws_region,
|
|
186
|
-
)
|
|
389
|
+
else:
|
|
390
|
+
logger.debug(f"Using existing role from {credential_source}")
|
|
187
391
|
|
|
188
392
|
return session
|
|
189
393
|
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
// | empty_string
|
|
22
22
|
// | empty_string "," argument_list
|
|
23
23
|
// - Added sql_string in any_literal
|
|
24
|
+
// - Added WS_INLINE? in field expression
|
|
25
|
+
// Added to ignore any comments
|
|
26
|
+
// %ignore WS // Ignore whitespace
|
|
27
|
+
// %ignore CPP_COMMENT // Ignore single-line comments
|
|
28
|
+
// %ignore C_COMMENT // Ignore multi-line comments
|
|
24
29
|
|
|
25
30
|
lexical_unit: lexical_elements?
|
|
26
31
|
|
|
@@ -245,6 +250,8 @@ operator_or_punctuator: ","
|
|
|
245
250
|
| "=>"
|
|
246
251
|
| ".."
|
|
247
252
|
| "..."
|
|
253
|
+
| "{{"
|
|
254
|
+
| "}}"
|
|
248
255
|
|
|
249
256
|
document: section_document
|
|
250
257
|
| expression_document
|
|
@@ -275,6 +282,7 @@ expression: logical_or_expression
|
|
|
275
282
|
| if_expression
|
|
276
283
|
| error_raising_expression
|
|
277
284
|
| error_handling_expression
|
|
285
|
+
| outer_expression
|
|
278
286
|
|
|
279
287
|
|
|
280
288
|
logical_or_expression: logical_and_expression
|
|
@@ -376,6 +384,8 @@ sql_content: /(?:[^\"\\]|\\[\"]|\"\"|\#\(lf\))+/
|
|
|
376
384
|
|
|
377
385
|
sql_string: "\"" sql_content "\""
|
|
378
386
|
|
|
387
|
+
outer_expression: "{{" expression "}}"
|
|
388
|
+
|
|
379
389
|
argument_list: WS_INLINE? expression
|
|
380
390
|
| WS_INLINE? expression WS_INLINE? "," WS_INLINE? argument_list
|
|
381
391
|
| WS_INLINE? sql_string
|
|
@@ -409,7 +419,7 @@ record_expression: "[" field_list? "]"
|
|
|
409
419
|
field_list: field
|
|
410
420
|
| field "," field_list
|
|
411
421
|
|
|
412
|
-
field: field_name WS_INLINE? "=" WS_INLINE? expression
|
|
422
|
+
field: WS_INLINE? field_name WS_INLINE? "=" WS_INLINE? expression
|
|
413
423
|
|
|
414
424
|
field_name: generalized_identifier
|
|
415
425
|
| quoted_identifier
|
|
@@ -621,4 +631,8 @@ any_literal: record_literal
|
|
|
621
631
|
%import common.DIGIT
|
|
622
632
|
%import common.LF
|
|
623
633
|
%import common.CR
|
|
624
|
-
%import common.ESCAPED_STRING
|
|
634
|
+
%import common.ESCAPED_STRING
|
|
635
|
+
|
|
636
|
+
%ignore WS // Ignore whitespace
|
|
637
|
+
%ignore CPP_COMMENT // Ignore single-line comments
|
|
638
|
+
%ignore C_COMMENT // Ignore multi-line comments
|