This is an automated email from the ASF dual-hosted git repository.

shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new ee142ce32c9 Fail AzureVirtualMachineStateSensor fast on an invalid 
target_state (#70372)
ee142ce32c9 is described below

commit ee142ce32c9cc7671758dcbe643904e7fb959df1
Author: Shahar Epstein <[email protected]>
AuthorDate: Fri Jul 24 15:07:49 2026 +0300

    Fail AzureVirtualMachineStateSensor fast on an invalid target_state (#70372)
    
    target_state is a template field, so the rendered value can only be checked 
at
    run time. Checking it from poke() puts it inside the error handling of
    BaseSensorOperator.execute(): under silent_fail the error is logged and 
treated
    as "not ready yet", so a misconfigured sensor polls until its timeout (7 
days by
    default) instead of failing; under never_fail or soft_fail it becomes a 
skip, so
    the sensor reports no failure at all and downstream tasks proceed.
    
    Checking once in execute(), before the poll loop and before deferring, 
keeps the
    run-time check the template field requires while restoring an immediate,
    unambiguous failure.
---
 .../src/airflow/providers/microsoft/azure/sensors/compute.py     | 9 ++++-----
 .../azure/tests/unit/microsoft/azure/sensors/test_compute.py     | 8 ++++++--
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git 
a/providers/microsoft/azure/src/airflow/providers/microsoft/azure/sensors/compute.py
 
b/providers/microsoft/azure/src/airflow/providers/microsoft/azure/sensors/compute.py
index 648b111432d..e40ca5f4fcf 100644
--- 
a/providers/microsoft/azure/src/airflow/providers/microsoft/azure/sensors/compute.py
+++ 
b/providers/microsoft/azure/src/airflow/providers/microsoft/azure/sensors/compute.py
@@ -68,11 +68,6 @@ class AzureVirtualMachineStateSensor(BaseSensorOperator):
         self.deferrable = deferrable
 
     def poke(self, context: Context) -> bool:
-        # target_state is a template field; validate the rendered value here, 
not in __init__.
-        if self.target_state not in self.VALID_STATES:
-            raise ValueError(
-                f"Invalid target_state: {self.target_state}. Must be one of 
{sorted(self.VALID_STATES)}"
-            )
         hook = AzureComputeHook(azure_conn_id=self.azure_conn_id)
         current_state = hook.get_power_state(self.resource_group_name, 
self.vm_name)
         self.log.info("VM %s power state: %s", self.vm_name, current_state)
@@ -85,6 +80,10 @@ class AzureVirtualMachineStateSensor(BaseSensorOperator):
         In deferrable mode, the polling is deferred to the triggerer. Otherwise
         the sensor waits synchronously.
         """
+        if self.target_state not in self.VALID_STATES:
+            raise ValueError(
+                f"Invalid target_state: {self.target_state}. Must be one of 
{sorted(self.VALID_STATES)}"
+            )
         if not self.deferrable:
             super().execute(context=context)
         else:
diff --git 
a/providers/microsoft/azure/tests/unit/microsoft/azure/sensors/test_compute.py 
b/providers/microsoft/azure/tests/unit/microsoft/azure/sensors/test_compute.py
index 85c168ab89b..5d3c93b0305 100644
--- 
a/providers/microsoft/azure/tests/unit/microsoft/azure/sensors/test_compute.py
+++ 
b/providers/microsoft/azure/tests/unit/microsoft/azure/sensors/test_compute.py
@@ -43,15 +43,19 @@ class TestAzureVirtualMachineStateSensor:
         assert sensor.target_state == "running"
         assert sensor.azure_conn_id == CONN_ID
 
-    def test_invalid_target_state_rejected_at_poke(self):
+    @pytest.mark.parametrize("deferrable", [False, True])
+    def test_invalid_target_state_rejected_at_execute(self, deferrable):
         sensor = AzureVirtualMachineStateSensor(
             task_id="sense_vm",
             resource_group_name=RESOURCE_GROUP,
             vm_name=VM_NAME,
             target_state="invalid_state",
+            deferrable=deferrable,
+            silent_fail=True,
+            timeout=0,
         )
         with pytest.raises(ValueError, match="Invalid target_state"):
-            sensor.poke(context=None)
+            sensor.execute(context=None)
 
     def test_templated_target_state_constructs(self):
         sensor = AzureVirtualMachineStateSensor(

Reply via email to