netmito/config/client/
tasks.rs

1use clap::{Args, Subcommand};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::{
6    config::client::parse_resources,
7    entity::state::{TaskExecState, TaskState},
8    schema::{ChangeTaskReq, RemoteResourceDownload, TaskSpec, TasksQueryReq, UpdateTaskLabelsReq},
9};
10
11use super::{parse_key_val, parse_watch_task, ArtifactsArgs};
12
13#[derive(Serialize, Debug, Deserialize, Args, derive_more::From, Clone)]
14pub struct TasksArgs {
15    #[command(subcommand)]
16    pub command: TasksCommands,
17}
18
19#[derive(Subcommand, Serialize, Debug, Deserialize, derive_more::From, Clone)]
20pub enum TasksCommands {
21    /// Submit a task
22    Submit(SubmitTaskArgs),
23    /// Get the info of a task
24    Get(GetTaskArgs),
25    /// Query tasks subject to the filter
26    Query(QueryTasksArgs),
27    /// Cancel a task
28    Cancel(CancelTaskArgs),
29    /// Replace labels of a task
30    UpdateLabels(UpdateTaskLabelsArgs),
31    /// Update the spec of a task
32    Change(ChangeTaskArgs),
33    /// Query, upload, download or delete an artifact
34    Artifacts(ArtifactsArgs),
35}
36
37#[derive(Serialize, Debug, Deserialize, Args, Clone)]
38pub struct SubmitTaskArgs {
39    /// The name of the group this task is submitted to
40    #[arg(short = 'g', long = "group")]
41    pub group_name: Option<String>,
42    /// The tags of the task, used to filter workers to execute the task
43    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
44    pub tags: Vec<String>,
45    /// The labels of the task, used for querying tasks
46    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
47    pub labels: Vec<String>,
48    /// The timeout of the task.
49    #[arg(long, value_parser = humantime_serde::re::humantime::parse_duration, default_value="10min")]
50    pub timeout: std::time::Duration,
51    /// The priority of the task.
52    #[arg(short, long, default_value_t = 0)]
53    pub priority: i32,
54    /// The environment variables to set
55    #[arg(short, long, num_args = 0.., value_delimiter = ',', value_parser = parse_key_val::<String, String>)]
56    pub envs: Vec<(String, String)>,
57    /// Whether to collect the terminal standard output and error of the executed task.
58    #[arg(long = "terminal")]
59    pub terminal_output: bool,
60    /// The command to run
61    #[arg(last = true)]
62    pub command: Vec<String>,
63    #[arg(short, long, num_args = 0.., value_delimiter = ',', value_parser = parse_resources)]
64    pub resources: Vec<RemoteResourceDownload>,
65    /// The UUID and the state of the task to watch before triggering this task.
66    /// Should specify it as `UUID,STATE`, e.g. `123e4567-e89b-12d3-a456-426614174000,ExecSpawned`.
67    #[arg(long, value_parser = parse_watch_task::<Uuid, TaskExecState>)]
68    pub watch: Option<(Uuid, TaskExecState)>,
69}
70
71#[derive(Serialize, Debug, Deserialize, Args, Clone)]
72pub struct GetTaskArgs {
73    /// The UUID of the task
74    pub uuid: Uuid,
75}
76
77#[derive(Serialize, Debug, Deserialize, Args, Clone)]
78pub struct QueryTasksArgs {
79    /// The username of the creator who submitted the tasks
80    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
81    pub creators: Vec<String>,
82    /// The name of the group the tasks belong to
83    #[arg(short, long)]
84    pub group: Option<String>,
85    /// The tags of the tasks
86    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
87    pub tags: Vec<String>,
88    /// The labels of the tasks
89    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
90    pub labels: Vec<String>,
91    /// The state of the tasks
92    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
93    pub state: Vec<TaskState>,
94    /// The exit status of the tasks, support operators like `=`(default), `!=`, `<`, `<=`, `>`, `>=`
95    #[arg(short, long)]
96    pub exit_status: Option<String>,
97    /// The priority of the tasks, support operators like `=`(default), `!=`, `<`, `<=`, `>`, `>=`
98    #[arg(short, long)]
99    pub priority: Option<String>,
100    /// The limit of the tasks to query
101    #[arg(long)]
102    pub limit: Option<u64>,
103    /// The offset of the tasks to query
104    #[arg(long)]
105    pub offset: Option<u64>,
106    /// Whether to output the verbose information of workers
107    #[arg(short, long)]
108    pub verbose: bool,
109    /// Only count the number of workers
110    #[arg(long)]
111    pub count: bool,
112}
113
114#[derive(Serialize, Debug, Deserialize, Args, Clone)]
115pub struct CancelTaskArgs {
116    /// The UUID of the task
117    pub uuid: Uuid,
118}
119
120#[derive(Serialize, Debug, Deserialize, Args, Clone)]
121pub struct UpdateTaskLabelsArgs {
122    /// The UUID of the task
123    pub uuid: Uuid,
124    /// The labels to replace
125    #[arg(num_args = 0..)]
126    pub labels: Vec<String>,
127}
128
129#[derive(Serialize, Debug, Deserialize, Args, Clone)]
130pub struct ChangeTaskArgs {
131    /// The UUID of the task
132    pub uuid: Uuid,
133    /// The tags of the task, used to filter workers to execute the task
134    #[arg(short, long, num_args = 0.., value_delimiter = ',')]
135    pub tags: Vec<String>,
136    /// The timeout of the task.
137    #[arg(long, value_parser = humantime_serde::re::humantime::parse_duration)]
138    pub timeout: Option<std::time::Duration>,
139    /// The priority of the task.
140    #[arg(short, long)]
141    pub priority: Option<i32>,
142    /// The environment variables to set
143    #[arg(short, long, num_args = 0.., value_delimiter = ',', value_parser = parse_key_val::<String, String>)]
144    pub envs: Vec<(String, String)>,
145    /// Whether to collect the terminal standard output and error of the executed task.
146    #[arg(long = "terminal")]
147    pub terminal_output: bool,
148    /// The command to run
149    #[arg(last = true)]
150    pub command: Vec<String>,
151    #[arg(skip)]
152    pub resources: Vec<RemoteResourceDownload>,
153    /// The UUID and the state of the task to watch before triggering this task.
154    /// Should specify it as `UUID,STATE`, e.g. `123e4567-e89b-12d3-a456-426614174000,ExecSpawned`.
155    #[arg(long, value_parser = parse_watch_task::<Uuid, TaskExecState>)]
156    pub watch: Option<(Uuid, TaskExecState)>,
157}
158
159impl From<QueryTasksArgs> for TasksQueryReq {
160    fn from(args: QueryTasksArgs) -> Self {
161        Self {
162            creator_usernames: if args.creators.is_empty() {
163                None
164            } else {
165                Some(args.creators.into_iter().collect())
166            },
167            group_name: args.group,
168            tags: if args.tags.is_empty() {
169                None
170            } else {
171                Some(args.tags.into_iter().collect())
172            },
173            labels: if args.labels.is_empty() {
174                None
175            } else {
176                Some(args.labels.into_iter().collect())
177            },
178            states: if args.state.is_empty() {
179                None
180            } else {
181                Some(args.state.into_iter().collect())
182            },
183            exit_status: args.exit_status,
184            priority: args.priority,
185            limit: args.limit,
186            offset: args.offset,
187            count: args.count,
188        }
189    }
190}
191
192impl From<ChangeTaskArgs> for ChangeTaskReq {
193    fn from(args: ChangeTaskArgs) -> Self {
194        let task_spec = if args.command.is_empty() {
195            None
196        } else {
197            Some(TaskSpec::new(
198                args.command,
199                args.envs,
200                args.resources,
201                args.terminal_output,
202                args.watch,
203            ))
204        };
205        Self {
206            tags: if args.tags.is_empty() {
207                None
208            } else {
209                Some(args.tags.into_iter().collect())
210            },
211            timeout: args.timeout,
212            priority: args.priority,
213            task_spec,
214        }
215    }
216}
217
218impl From<UpdateTaskLabelsArgs> for UpdateTaskLabelsReq {
219    fn from(args: UpdateTaskLabelsArgs) -> Self {
220        Self {
221            labels: args.labels.into_iter().collect(),
222        }
223    }
224}