This is an automated email from the ASF dual-hosted git repository.
henry3260 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 3570a75d2df Added dagrun delete command to airflowctl (#68046)
3570a75d2df is described below
commit 3570a75d2df4dea62a33e7d37e9669faf26ebfea
Author: Justin Pakzad <[email protected]>
AuthorDate: Thu Jul 2 09:52:45 2026 -0400
Added dagrun delete command to airflowctl (#68046)
* Add dagrun delete command to airflowctl
* Adjust docstring to Dag
---
.../airflowctl_tests/test_airflowctl_commands.py | 2 +
airflow-ctl/docs/images/command_hashes.txt | 2 +-
airflow-ctl/docs/images/output_dagrun.svg | 70 ++++++++++++----------
airflow-ctl/src/airflowctl/api/operations.py | 8 +++
airflow-ctl/src/airflowctl/ctl/help_texts.yaml | 1 +
.../tests/airflow_ctl/api/test_operations.py | 9 +++
6 files changed, 58 insertions(+), 34 deletions(-)
diff --git
a/airflow-ctl-tests/tests/airflowctl_tests/test_airflowctl_commands.py
b/airflow-ctl-tests/tests/airflowctl_tests/test_airflowctl_commands.py
index 2d14b1d66f5..924cbde90d5 100644
--- a/airflow-ctl-tests/tests/airflowctl_tests/test_airflowctl_commands.py
+++ b/airflow-ctl-tests/tests/airflowctl_tests/test_airflowctl_commands.py
@@ -102,6 +102,8 @@ TEST_COMMANDS = [
'xcom list example_bash_operator "manual__{date_param}" runme_0',
'xcom edit example_bash_operator "manual__{date_param}" runme_0 {xcom_key}
\'{{"updated": "value"}}\'',
'xcom delete example_bash_operator "manual__{date_param}" runme_0
{xcom_key}',
+ # Delete Dag run command - needs to run after xcom ops
+ 'dagrun delete example_bash_operator "manual__{date_param}"',
# Jobs commands
"jobs list",
# Pools commands
diff --git a/airflow-ctl/docs/images/command_hashes.txt
b/airflow-ctl/docs/images/command_hashes.txt
index 4f43fd10bdf..36eec17c2eb 100644
--- a/airflow-ctl/docs/images/command_hashes.txt
+++ b/airflow-ctl/docs/images/command_hashes.txt
@@ -5,7 +5,7 @@ backfill:74c8737b0a62a86ed3605fa9e6165874
config:a3d936cb15fe3b547bf6c82cf93d923f
connections:942f9f88cb908c28bf5c19159fc5065b
dags:5ad68174a1111563dff870a241914b30
-dagrun:c32e0011aa9a845456c778786717208e
+dagrun:07035226eaaff0a557d3ad9aab4b41b5
jobs:a5b644c5da8889443bb40ee10b599270
pools:19efe105b9515ab1926ebcaf0e028d71
providers:34502fe09dc0b8b0a13e7e46efdffda6
diff --git a/airflow-ctl/docs/images/output_dagrun.svg
b/airflow-ctl/docs/images/output_dagrun.svg
index 48e96c89420..5e3798302cc 100644
--- a/airflow-ctl/docs/images/output_dagrun.svg
+++ b/airflow-ctl/docs/images/output_dagrun.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 933 318.4"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 933 342.79999999999995"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -19,82 +19,86 @@
font-weight: 700;
}
- .terminal-3834720684-matrix {
+ .terminal-4060510586-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-3834720684-title {
+ .terminal-4060510586-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-3834720684-r1 { fill: #ff8700 }
-.terminal-3834720684-r2 { fill: #c5c8c6 }
-.terminal-3834720684-r3 { fill: #808080 }
-.terminal-3834720684-r4 { fill: #68a0b3 }
+ .terminal-4060510586-r1 { fill: #ff8700 }
+.terminal-4060510586-r2 { fill: #c5c8c6 }
+.terminal-4060510586-r3 { fill: #808080 }
+.terminal-4060510586-r4 { fill: #68a0b3 }
</style>
<defs>
- <clipPath id="terminal-3834720684-clip-terminal">
- <rect x="0" y="0" width="914.0" height="267.4" />
+ <clipPath id="terminal-4060510586-clip-terminal">
+ <rect x="0" y="0" width="914.0" height="291.79999999999995" />
</clipPath>
- <clipPath id="terminal-3834720684-line-0">
+ <clipPath id="terminal-4060510586-line-0">
<rect x="0" y="1.5" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-1">
+<clipPath id="terminal-4060510586-line-1">
<rect x="0" y="25.9" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-2">
+<clipPath id="terminal-4060510586-line-2">
<rect x="0" y="50.3" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-3">
+<clipPath id="terminal-4060510586-line-3">
<rect x="0" y="74.7" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-4">
+<clipPath id="terminal-4060510586-line-4">
<rect x="0" y="99.1" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-5">
+<clipPath id="terminal-4060510586-line-5">
<rect x="0" y="123.5" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-6">
+<clipPath id="terminal-4060510586-line-6">
<rect x="0" y="147.9" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-7">
+<clipPath id="terminal-4060510586-line-7">
<rect x="0" y="172.3" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-8">
+<clipPath id="terminal-4060510586-line-8">
<rect x="0" y="196.7" width="915" height="24.65"/>
</clipPath>
-<clipPath id="terminal-3834720684-line-9">
+<clipPath id="terminal-4060510586-line-9">
<rect x="0" y="221.1" width="915" height="24.65"/>
</clipPath>
+<clipPath id="terminal-4060510586-line-10">
+ <rect x="0" y="245.5" width="915" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="931" height="316.4" rx="8"/>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="931" height="340.8" rx="8"/>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
- <g transform="translate(9, 41)"
clip-path="url(#terminal-3834720684-clip-terminal)">
+ <g transform="translate(9, 41)"
clip-path="url(#terminal-4060510586-clip-terminal)">
- <g class="terminal-3834720684-matrix">
- <text class="terminal-3834720684-r1" x="0" y="20" textLength="73.2"
clip-path="url(#terminal-3834720684-line-0)">Usage:</text><text
class="terminal-3834720684-r3" x="85.4" y="20" textLength="207.4"
clip-path="url(#terminal-3834720684-line-0)">airflowctl dagrun</text><text
class="terminal-3834720684-r2" x="292.8" y="20" textLength="24.4"
clip-path="url(#terminal-3834720684-line-0)"> [</text><text
class="terminal-3834720684-r4" x="317.2" y="20" textLength="24.4" clip-path="ur
[...]
-</text><text class="terminal-3834720684-r2" x="915" y="44.4" textLength="12.2"
clip-path="url(#terminal-3834720684-line-1)">
-</text><text class="terminal-3834720684-r2" x="0" y="68.8" textLength="305"
clip-path="url(#terminal-3834720684-line-2)">Perform DagRun operations</text><text
class="terminal-3834720684-r2" x="915" y="68.8" textLength="12.2"
clip-path="url(#terminal-3834720684-line-2)">
-</text><text class="terminal-3834720684-r2" x="915" y="93.2" textLength="12.2"
clip-path="url(#terminal-3834720684-line-3)">
-</text><text class="terminal-3834720684-r1" x="0" y="117.6" textLength="256.2"
clip-path="url(#terminal-3834720684-line-4)">Positional Arguments:</text><text
class="terminal-3834720684-r2" x="915" y="117.6" textLength="12.2"
clip-path="url(#terminal-3834720684-line-4)">
-</text><text class="terminal-3834720684-r4" x="24.4" y="142" textLength="85.4"
clip-path="url(#terminal-3834720684-line-5)">COMMAND</text><text
class="terminal-3834720684-r2" x="915" y="142" textLength="12.2"
clip-path="url(#terminal-3834720684-line-5)">
-</text><text class="terminal-3834720684-r4" x="48.8" y="166.4"
textLength="36.6" clip-path="url(#terminal-3834720684-line-6)">get</text><text
class="terminal-3834720684-r2" x="170.8" y="166.4" textLength="475.8"
clip-path="url(#terminal-3834720684-line-6)">Retrieve a Dag run by Dag ID and run ID</text><text
class="terminal-3834720684-r2" x="915" y="166.4" textLength="12.2"
clip-path="url(#terminal-3834720684-line-6)">
-</text><text class="terminal-3834720684-r4" x="48.8" y="190.8"
textLength="48.8" clip-path="url(#terminal-3834720684-line-7)">list</text><text
class="terminal-3834720684-r2" x="170.8" y="190.8" textLength="707.6"
clip-path="url(#terminal-3834720684-line-7)">List Dag runs, optionally filtered by state and date range</text><text
class="terminal-3834720684-r2" x="915" y="190.8" textLength="12.2"
clip-path="url(#terminal-3834720684-line-7)">
-</text><text class="terminal-3834720684-r2" x="915" y="215.2"
textLength="12.2" clip-path="url(#terminal-3834720684-line-8)">
-</text><text class="terminal-3834720684-r1" x="0" y="239.6" textLength="97.6"
clip-path="url(#terminal-3834720684-line-9)">Options:</text><text
class="terminal-3834720684-r2" x="915" y="239.6" textLength="12.2"
clip-path="url(#terminal-3834720684-line-9)">
-</text><text class="terminal-3834720684-r4" x="24.4" y="264" textLength="24.4"
clip-path="url(#terminal-3834720684-line-10)">-h</text><text
class="terminal-3834720684-r2" x="48.8" y="264" textLength="24.4"
clip-path="url(#terminal-3834720684-line-10)">, </text><text
class="terminal-3834720684-r4" x="73.2" y="264" textLength="73.2"
clip-path="url(#terminal-3834720684-line-10)">--help</text><text
class="terminal-3834720684-r2" x="170.8" y="264" textLength="378.2"
clip-path="url(#termi [...]
+ <g class="terminal-4060510586-matrix">
+ <text class="terminal-4060510586-r1" x="0" y="20" textLength="73.2"
clip-path="url(#terminal-4060510586-line-0)">Usage:</text><text
class="terminal-4060510586-r3" x="85.4" y="20" textLength="207.4"
clip-path="url(#terminal-4060510586-line-0)">airflowctl dagrun</text><text
class="terminal-4060510586-r2" x="292.8" y="20" textLength="24.4"
clip-path="url(#terminal-4060510586-line-0)"> [</text><text
class="terminal-4060510586-r4" x="317.2" y="20" textLength="24.4" clip-path="ur
[...]
+</text><text class="terminal-4060510586-r2" x="915" y="44.4" textLength="12.2"
clip-path="url(#terminal-4060510586-line-1)">
+</text><text class="terminal-4060510586-r2" x="0" y="68.8" textLength="305"
clip-path="url(#terminal-4060510586-line-2)">Perform DagRun operations</text><text
class="terminal-4060510586-r2" x="915" y="68.8" textLength="12.2"
clip-path="url(#terminal-4060510586-line-2)">
+</text><text class="terminal-4060510586-r2" x="915" y="93.2" textLength="12.2"
clip-path="url(#terminal-4060510586-line-3)">
+</text><text class="terminal-4060510586-r1" x="0" y="117.6" textLength="256.2"
clip-path="url(#terminal-4060510586-line-4)">Positional Arguments:</text><text
class="terminal-4060510586-r2" x="915" y="117.6" textLength="12.2"
clip-path="url(#terminal-4060510586-line-4)">
+</text><text class="terminal-4060510586-r4" x="24.4" y="142" textLength="85.4"
clip-path="url(#terminal-4060510586-line-5)">COMMAND</text><text
class="terminal-4060510586-r2" x="915" y="142" textLength="12.2"
clip-path="url(#terminal-4060510586-line-5)">
+</text><text class="terminal-4060510586-r4" x="48.8" y="166.4"
textLength="73.2"
clip-path="url(#terminal-4060510586-line-6)">delete</text><text
class="terminal-4060510586-r2" x="170.8" y="166.4" textLength="451.4"
clip-path="url(#terminal-4060510586-line-6)">Delete a Dag run by Dag ID and run ID</text><text
class="terminal-4060510586-r2" x="915" y="166.4" textLength="12.2"
clip-path="url(#terminal-4060510586-line-6)">
+</text><text class="terminal-4060510586-r4" x="48.8" y="190.8"
textLength="36.6" clip-path="url(#terminal-4060510586-line-7)">get</text><text
class="terminal-4060510586-r2" x="170.8" y="190.8" textLength="475.8"
clip-path="url(#terminal-4060510586-line-7)">Retrieve a Dag run by Dag ID and run ID</text><text
class="terminal-4060510586-r2" x="915" y="190.8" textLength="12.2"
clip-path="url(#terminal-4060510586-line-7)">
+</text><text class="terminal-4060510586-r4" x="48.8" y="215.2"
textLength="48.8" clip-path="url(#terminal-4060510586-line-8)">list</text><text
class="terminal-4060510586-r2" x="170.8" y="215.2" textLength="707.6"
clip-path="url(#terminal-4060510586-line-8)">List Dag runs, optionally filtered by state and date range</text><text
class="terminal-4060510586-r2" x="915" y="215.2" textLength="12.2"
clip-path="url(#terminal-4060510586-line-8)">
+</text><text class="terminal-4060510586-r2" x="915" y="239.6"
textLength="12.2" clip-path="url(#terminal-4060510586-line-9)">
+</text><text class="terminal-4060510586-r1" x="0" y="264" textLength="97.6"
clip-path="url(#terminal-4060510586-line-10)">Options:</text><text
class="terminal-4060510586-r2" x="915" y="264" textLength="12.2"
clip-path="url(#terminal-4060510586-line-10)">
+</text><text class="terminal-4060510586-r4" x="24.4" y="288.4"
textLength="24.4" clip-path="url(#terminal-4060510586-line-11)">-h</text><text
class="terminal-4060510586-r2" x="48.8" y="288.4" textLength="24.4"
clip-path="url(#terminal-4060510586-line-11)">, </text><text
class="terminal-4060510586-r4" x="73.2" y="288.4" textLength="73.2"
clip-path="url(#terminal-4060510586-line-11)">--help</text><text
class="terminal-4060510586-r2" x="170.8" y="288.4" textLength="378.2"
clip-path="ur [...]
</text>
</g>
</g>
diff --git a/airflow-ctl/src/airflowctl/api/operations.py
b/airflow-ctl/src/airflowctl/api/operations.py
index 94f39a3a915..ad0de6d008b 100644
--- a/airflow-ctl/src/airflowctl/api/operations.py
+++ b/airflow-ctl/src/airflowctl/api/operations.py
@@ -662,6 +662,14 @@ class DagRunOperations(BaseOperations):
except ServerResponseError as e:
raise e
+ def delete(self, dag_id: str, dag_run_id: str) -> str |
ServerResponseError:
+ """Delete a Dag run."""
+ try:
+ self.client.delete(f"/dags/{dag_id}/dagRuns/{dag_run_id}")
+ return dag_run_id
+ except ServerResponseError as e:
+ raise e
+
class JobsOperations(BaseOperations):
"""Job operations."""
diff --git a/airflow-ctl/src/airflowctl/ctl/help_texts.yaml
b/airflow-ctl/src/airflowctl/ctl/help_texts.yaml
index 88cc0a15c9d..d0ebdcfeaeb 100644
--- a/airflow-ctl/src/airflowctl/ctl/help_texts.yaml
+++ b/airflow-ctl/src/airflowctl/ctl/help_texts.yaml
@@ -70,6 +70,7 @@ dags:
dagrun:
get: "Retrieve a Dag run by Dag ID and run ID"
list: "List Dag runs, optionally filtered by state and date range"
+ delete: "Delete a Dag run by Dag ID and run ID"
jobs:
list: "List scheduler, triggerer, and other Airflow jobs"
diff --git a/airflow-ctl/tests/airflow_ctl/api/test_operations.py
b/airflow-ctl/tests/airflow_ctl/api/test_operations.py
index 5d8d0c0f689..53dfb321717 100644
--- a/airflow-ctl/tests/airflow_ctl/api/test_operations.py
+++ b/airflow-ctl/tests/airflow_ctl/api/test_operations.py
@@ -1309,6 +1309,15 @@ class TestDagRunOperations:
assert "state" not in captured_params
assert captured_params["limit"] == "5"
+ def test_delete(self):
+ def handle_request(request: httpx.Request) -> httpx.Response:
+ assert request.url.path ==
f"/api/v2/dags/{self.dag_id}/dagRuns/{self.dag_run_id}"
+ return httpx.Response(204)
+
+ client = make_api_client(transport=httpx.MockTransport(handle_request))
+ response = client.dag_runs.delete(dag_id=self.dag_id,
dag_run_id=self.dag_run_id)
+ assert response == self.dag_run_id
+
class TestJobsOperations:
job_response = JobResponse(