@@ -59,18 +59,31 @@ def create(
5959
6060@app .command ()
6161def run (
62- dag_id : str = typer .Argument (..., help = "DAG ID to run " ),
62+ dag_input : str = typer .Argument (..., help = "DAG ID or path to DAG YAML file " ),
6363 resume : bool = typer .Option (False , "--resume" , help = "Resume from last checkpoint" ),
6464 fail_fast : bool = typer .Option (True , "--fail-fast/--no-fail-fast" , help = "Stop on first failure" ),
6565 server_url : str = typer .Option ("http://localhost:8000" , "--server" , help = "Maestro server URL" )
6666):
67- """Run a previously created DAG """
67+ """Run a DAG - either by ID or by creating from a YAML file """
6868 api_client .base_url = server_url
6969 check_server_connection ()
7070
7171 try :
72+ # Check if the input is a file path or a DAG ID
73+ if os .path .exists (dag_input ) and dag_input .endswith (('.yaml' , '.yml' )):
74+ # It's a file path - create the DAG first
75+ dag_file_path = os .path .abspath (dag_input )
76+ console .print (f"[blue]Creating DAG from file: { dag_file_path } [/blue]" )
77+ create_response = api_client .create_dag (dag_file_path )
78+ dag_id = create_response ['dag_id' ]
79+ console .print (f"[bold green]✓ DAG created successfully with ID: { dag_id } [/bold green]" )
80+ else :
81+ # It's a DAG ID
82+ dag_id = dag_input
83+
84+ # Now run the DAG
7285 response = api_client .run_dag (dag_id , resume , fail_fast )
73- console .print (f"[bold green]✓ { response [ 'message' ] } [/bold green]" )
86+ console .print (f"[bold green]✓ DAG started successfully! [/bold green]" )
7487 console .print (f"[cyan]DAG ID:[/cyan] { response ['dag_id' ]} " )
7588 console .print (f"[cyan]Execution ID:[/cyan] { response ['execution_id' ]} " )
7689 console .print (f"[cyan]Status:[/cyan] [yellow]{ response ['status' ]} [/yellow]" )
@@ -85,49 +98,6 @@ def run(
8598 console .print (f"[red]Error: { e } [/red]" )
8699 raise typer .Exit (1 )
87100
88- @app .command ()
89- def submit (
90- dag_file : str = typer .Argument (..., help = "Path to the DAG YAML file" ),
91- resume : bool = typer .Option (False , "--resume" , help = "Resume from last checkpoint" ),
92- fail_fast : bool = typer .Option (True , "--fail-fast/--no-fail-fast" , help = "Stop on first failure" ),
93- server_url : str = typer .Option ("http://localhost:8000" , "--server" , help = "Maestro server URL" )
94- ):
95- """Submit a DAG for execution (legacy command)"""
96- console .print ("[yellow]Warning: 'maestro submit' is a legacy command. Use 'maestro create' followed by 'maestro run' for better control.[/yellow]" )
97- api_client .base_url = server_url
98- check_server_connection ()
99-
100- try :
101- # Convert a relative path to absolute
102- dag_file_path = os .path .abspath (dag_file )
103-
104- if not os .path .exists (dag_file_path ):
105- console .print (f"[red]Error: DAG file not found: { dag_file_path } [/red]" )
106- raise typer .Exit (1 )
107-
108- # First, create the DAG
109- create_response = api_client .create_dag (dag_file_path )
110- dag_id = create_response ['dag_id' ]
111- console .print (f"[bold green]✓ DAG created successfully with ID: { dag_id } [/bold green]" )
112-
113- # Then, run the DAG
114- run_response = api_client .run_dag (dag_id , resume , fail_fast )
115-
116- console .print (f"[bold green]✓ DAG submitted successfully![/bold green]" )
117- console .print (f"[cyan]DAG ID:[/cyan] { run_response ['dag_id' ]} " )
118- console .print (f"[cyan]Execution ID:[/cyan] { run_response ['execution_id' ]} " )
119- console .print (f"[cyan]Status:[/cyan] [yellow]{ run_response ['status' ]} [/yellow]" )
120- console .print ()
121- console .print ("[bold blue]Available commands:[/bold blue]" )
122- console .print (f" • [bold]maestro status { run_response ['dag_id' ]} [/bold] - Check DAG status" )
123- console .print (f" • [bold]maestro log { run_response ['dag_id' ]} [/bold] - View logs" )
124- console .print (f" • [bold]maestro attach { run_response ['dag_id' ]} [/bold] - Attach to live log stream" )
125- console .print (f" • [bold]maestro stop { run_response ['dag_id' ]} [/bold] - Stop execution" )
126- console .print ()
127-
128- except Exception as e :
129- console .print (f"[red]Error: { e } [/red]" )
130- raise typer .Exit (1 )
131101
132102@app .command ()
133103def status (
@@ -150,7 +120,7 @@ def status(
150120 table .add_row ("Execution ID" , response ["execution_id" ])
151121 table .add_row ("Status" , response ["status" ])
152122 table .add_row ("Started" , response ["started_at" ] or "N/A" )
153- table .add_row ("Completed" , response ["completed_at" ] or "Running... " )
123+ table .add_row ("Completed" , response ["completed_at" ] or "N/A " )
154124 table .add_row ("Thread ID" , response ["thread_id" ] or "N/A" )
155125
156126 console .print (table )
@@ -281,17 +251,40 @@ def handle_exit(signum, frame):
281251
282252@app .command ()
283253def rm (
284- dag_id : str = typer .Argument (..., help = "DAG ID to remove" ),
285- force : bool = typer .Option (False , "--force" , "-f" , help = "Force removal of a running DAG" ),
254+ dag_id : Optional [str ] = typer .Argument (None , help = "DAG ID to remove" ),
255+ all : bool = typer .Option (False , "--all" , "-a" , help = "Remove all non-running DAGs (or all DAGs with --force)" ),
256+ force : bool = typer .Option (False , "--force" , "-f" , help = "Force removal, even for running DAGs" ),
286257 server_url : str = typer .Option ("http://localhost:8000" , "--server" , help = "Maestro server URL" )
287258):
288259 """Remove a DAG and its executions"""
289260 api_client .base_url = server_url
290261 check_server_connection ()
291262
292263 try :
293- response = api_client .remove_dag (dag_id , force )
294- console .print (f"[bold green]✓ { response ['message' ]} [/bold green]" )
264+ if all :
265+ # Get all DAGs
266+ dags = api_client .list_dags_v1 ()
267+ removed_count = 0
268+
269+ for dag in dags :
270+ # Remove all non-running DAGs, or all if --force is used
271+ if force or dag ['status' ] not in ['running' ]:
272+ response = api_client .remove_dag (dag ['dag_id' ], force )
273+ console .print (f"[bold green]✓ Removed DAG: { dag ['dag_id' ]} (status: { dag ['status' ]} )[/bold green]" )
274+ removed_count += 1
275+ else :
276+ console .print (f"[yellow]⚠ Skipped running DAG: { dag ['dag_id' ]} [/yellow]" )
277+
278+ if removed_count == 0 :
279+ console .print ("[yellow]No DAGs to remove.[/yellow]" )
280+ else :
281+ console .print (f"[bold green]✓ Removed { removed_count } DAG(s).[/bold green]" )
282+ else :
283+ if not dag_id :
284+ console .print ("[red]Error: Please provide a DAG ID or use --all flag[/red]" )
285+ raise typer .Exit (1 )
286+ response = api_client .remove_dag (dag_id , force )
287+ console .print (f"[bold green]✓ { response ['message' ]} [/bold green]" )
295288 except Exception as e :
296289 console .print (f"[red]Error: { e } [/red]" )
297290 raise typer .Exit (1 )
@@ -388,7 +381,7 @@ def list_dags(
388381 dag ["execution_id" ][:8 ] + "..." if dag ["execution_id" ] else "N/A" ,
389382 f"[{ status_style } ]{ dag .get ('status' , 'N/A' )} [/{ status_style } ]" ,
390383 dag .get ("started_at" , "N/A" ),
391- dag .get ("completed_at" , "N/A" ) or "Running..." ,
384+ dag .get ("completed_at" , "N/A" ),
392385 str (dag .get ("thread_id" , "N/A" ))
393386 )
394387
0 commit comments