@@ -22,6 +22,20 @@ class _DetectionState(Enum):
2222
2323
2424def is_ec2_instance (timeout ):
25+ """
26+ Check if the current environment is running on an AWS EC2 instance.
27+
28+ If we query the AWS Instance Metadata Service (IMDS) for the instance identity document
29+ and receive content back, then we assume we are running on an EC2 instance.
30+ This function is compatible with IMDSv1 and IMDSv2 since we send the token in the request.
31+ It will ignore the token if on IMDSv1 and use the token if on IMDSv2.
32+
33+ Args:
34+ timeout: Timeout value for the metadata service request.
35+
36+ Returns:
37+ _DetectionState: DETECTED if running on EC2, NOT_DETECTED otherwise.
38+ """
2539 try :
2640 fetcher = IMDSFetcher (timeout = timeout , num_attempts = 1 )
2741 document = fetcher ._get_request (
@@ -39,6 +53,15 @@ def is_ec2_instance(timeout):
3953
4054
4155def is_aws_lambda ():
56+ """
57+ Check if the current environment is running in AWS Lambda.
58+
59+ If we check for the LAMBDA_TASK_ROOT environment variable and it exists,
60+ then we assume we are running in AWS Lambda.
61+
62+ Returns:
63+ _DetectionState: DETECTED if LAMBDA_TASK_ROOT env var exists, NOT_DETECTED otherwise.
64+ """
4265 return (
4366 _DetectionState .DETECTED
4467 if "LAMBDA_TASK_ROOT" in os .environ
@@ -47,6 +70,15 @@ def is_aws_lambda():
4770
4871
4972def is_valid_arn_for_wif (arn : str ) -> bool :
73+ """
74+ Validate if an AWS ARN is suitable for Web Identity Federation (WIF).
75+
76+ Args:
77+ arn: The AWS ARN string to validate.
78+
79+ Returns:
80+ bool: True if ARN is valid for WIF, False otherwise.
81+ """
5082 patterns = [
5183 r"^arn:[^:]+:iam::[^:]+:user/.+$" ,
5284 r"^arn:[^:]+:sts::[^:]+:assumed-role/.+$" ,
@@ -55,6 +87,18 @@ def is_valid_arn_for_wif(arn: str) -> bool:
5587
5688
5789def has_aws_identity (timeout ):
90+ """
91+ Check if the current environment has a valid AWS identity for authentication.
92+
93+ If we retrieve an ARN from the caller identity and it is a valid WIF ARN,
94+ then we assume we have a valid AWS identity for authentication.
95+
96+ Args:
97+ timeout: Timeout value for AWS API calls.
98+
99+ Returns:
100+ _DetectionState: DETECTED if valid AWS identity exists, NOT_DETECTED otherwise.
101+ """
58102 try :
59103 config = Config (
60104 connect_timeout = timeout ,
@@ -75,6 +119,19 @@ def has_aws_identity(timeout):
75119
76120
77121def is_azure_vm (timeout ):
122+ """
123+ Check if the current environment is running on an Azure Virtual Machine.
124+
125+ If we query the Azure Instance Metadata Service and receive an HTTP 200 response,
126+ then we assume we are running on an Azure VM.
127+
128+ Args:
129+ timeout: Timeout value for the metadata service request.
130+
131+ Returns:
132+ _DetectionState: DETECTED if on Azure VM, TIMEOUT if request times out,
133+ NOT_DETECTED otherwise.
134+ """
78135 try :
79136 token_resp = requests .get (
80137 "http://169.254.169.254/metadata/instance?api-version=2021-02-01" ,
@@ -93,6 +150,17 @@ def is_azure_vm(timeout):
93150
94151
95152def is_azure_function ():
153+ """
154+ Check if the current environment is running in Azure Functions.
155+
156+ If we check for Azure Functions environment variables (FUNCTIONS_WORKER_RUNTIME,
157+ FUNCTIONS_EXTENSION_VERSION, AzureWebJobsStorage) and they all exist,
158+ then we assume we are running in Azure Functions.
159+
160+ Returns:
161+ _DetectionState: DETECTED if all Azure Functions env vars are present,
162+ NOT_DETECTED otherwise.
163+ """
96164 service_vars = [
97165 "FUNCTIONS_WORKER_RUNTIME" ,
98166 "FUNCTIONS_EXTENSION_VERSION" ,
@@ -108,6 +176,21 @@ def is_azure_function():
108176def is_managed_identity_available_on_azure_vm (
109177 timeout , resource = DEFAULT_ENTRA_SNOWFLAKE_RESOURCE
110178):
179+ """
180+ Check if Azure Managed Identity is available and accessible on an Azure VM.
181+
182+ If we attempt to mint an access token from the Azure Instance Metadata Service
183+ managed identity endpoint and receive an HTTP 200 response,
184+ then we assume managed identity is available.
185+
186+ Args:
187+ timeout: Timeout value for the metadata service request.
188+ resource: The Azure resource URI to request a token for.
189+
190+ Returns:
191+ _DetectionState: DETECTED if managed identity is available, TIMEOUT if request
192+ times out, NOT_DETECTED otherwise.
193+ """
111194 endpoint = f"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource={ resource } "
112195 headers = {"Metadata" : "true" }
113196 try :
@@ -124,6 +207,24 @@ def is_managed_identity_available_on_azure_vm(
124207
125208
126209def has_azure_managed_identity (on_azure_vm , on_azure_function , timeout ):
210+ """
211+ Determine if Azure Managed Identity is available in the current environment.
212+
213+ If we are on Azure Functions and the IDENTITY_HEADER environment variable exists,
214+ then we assume managed identity is available.
215+ If we are on an Azure VM and can mint an access token from the managed identity endpoint,
216+ then we assume managed identity is available.
217+ Assumes timeout state if either VM or Function detection timed out.
218+
219+ Args:
220+ on_azure_vm: Detection state for Azure VM.
221+ on_azure_function: Detection state for Azure Function.
222+ timeout: Timeout value for managed identity checks.
223+
224+ Returns:
225+ _DetectionState: DETECTED if managed identity is available, TIMEOUT if
226+ detection timed out, NOT_DETECTED otherwise.
227+ """
127228 if on_azure_function == _DetectionState .DETECTED :
128229 return (
129230 _DetectionState .DETECTED
@@ -141,6 +242,19 @@ def has_azure_managed_identity(on_azure_vm, on_azure_function, timeout):
141242
142243
143244def is_gce_vm (timeout ):
245+ """
246+ Check if the current environment is running on Google Compute Engine (GCE).
247+
248+ If we query the Google metadata server and receive a response with the
249+ "Metadata-Flavor: Google" header, then we assume we are running on GCE.
250+
251+ Args:
252+ timeout: Timeout value for the metadata service request.
253+
254+ Returns:
255+ _DetectionState: DETECTED if on GCE, TIMEOUT if request times out,
256+ NOT_DETECTED otherwise.
257+ """
144258 try :
145259 response = requests .get ("http://metadata.google.internal" , timeout = timeout )
146260 return (
@@ -155,6 +269,16 @@ def is_gce_vm(timeout):
155269
156270
157271def is_gce_cloud_run_service ():
272+ """
273+ Check if the current environment is running in Google Cloud Run service.
274+
275+ If we check for Cloud Run service environment variables (K_SERVICE, K_REVISION,
276+ K_CONFIGURATION) and they all exist, then we assume we are running in Cloud Run service.
277+
278+ Returns:
279+ _DetectionState: DETECTED if all Cloud Run service env vars are present,
280+ NOT_DETECTED otherwise.
281+ """
158282 service_vars = ["K_SERVICE" , "K_REVISION" , "K_CONFIGURATION" ]
159283 return (
160284 _DetectionState .DETECTED
@@ -164,6 +288,16 @@ def is_gce_cloud_run_service():
164288
165289
166290def is_gce_cloud_run_job ():
291+ """
292+ Check if the current environment is running in Google Cloud Run job.
293+
294+ If we check for Cloud Run job environment variables (CLOUD_RUN_JOB, CLOUD_RUN_EXECUTION)
295+ and they both exist, then we assume we are running in a Cloud Run job.
296+
297+ Returns:
298+ _DetectionState: DETECTED if all Cloud Run job env vars are present,
299+ NOT_DETECTED otherwise.
300+ """
167301 job_vars = ["CLOUD_RUN_JOB" , "CLOUD_RUN_EXECUTION" ]
168302 return (
169303 _DetectionState .DETECTED
@@ -173,6 +307,19 @@ def is_gce_cloud_run_job():
173307
174308
175309def has_gcp_identity (timeout ):
310+ """
311+ Check if the current environment has a valid Google Cloud Platform identity.
312+
313+ If we query the GCP metadata service for the default service account email
314+ and receive a non-empty response, then we assume we have a valid GCP identity.
315+
316+ Args:
317+ timeout: Timeout value for the metadata service request.
318+
319+ Returns:
320+ _DetectionState: DETECTED if valid GCP identity exists, TIMEOUT if request
321+ times out, NOT_DETECTED otherwise.
322+ """
176323 try :
177324 response = requests .get (
178325 "http://metadata/computeMetadata/v1/instance/service-accounts/default/email" ,
@@ -190,6 +337,15 @@ def has_gcp_identity(timeout):
190337
191338
192339def is_github_action ():
340+ """
341+ Check if the current environment is running in GitHub Actions.
342+
343+ If we check for the GITHUB_ACTIONS environment variable and it exists,
344+ then we assume we are running in GitHub Actions.
345+
346+ Returns:
347+ _DetectionState: DETECTED if GITHUB_ACTIONS env var exists, NOT_DETECTED otherwise.
348+ """
193349 return (
194350 _DetectionState .DETECTED
195351 if "GITHUB_ACTIONS" in os .environ
@@ -198,6 +354,17 @@ def is_github_action():
198354
199355
200356def detect_platforms (timeout : int | float | None ) -> list [str ]:
357+ """
358+ Detect all potential platforms that the current environment may be running on.
359+
360+ Args:
361+ timeout: Timeout value for platform detection requests. Defaults to 0.2 seconds
362+ if None is provided.
363+
364+ Returns:
365+ list[str]: List of detected platform names. Platforms that timed out will have
366+ "_timeout" suffix appended to their name.
367+ """
201368 if timeout is None :
202369 timeout = 0.2
203370
0 commit comments