Skip to content

Commit ec83e16

Browse files
committed
allow specifying script source
1 parent d104db3 commit ec83e16

4 files changed

Lines changed: 103 additions & 30 deletions

File tree

coman/src/cli.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use strum::VariantNames;
55

66
use crate::{
77
config::{ComputePlatform, get_config_dir, get_data_dir, get_project_local_config_file},
8-
cscs::api_client::client::EdfSpec as EdfSpecEnum,
8+
cscs::api_client::client::{EdfSpec as EdfSpecEnum, ScriptSpec as ScriptSpecEnum},
99
util::types::DockerImageUrl,
1010
};
1111

@@ -57,12 +57,47 @@ pub enum CscsCommands {
5757
},
5858
}
5959

60+
#[derive(Args, Clone, Debug)]
61+
#[group(multiple = false)]
62+
pub struct ScriptSpec {
63+
#[arg(
64+
long,
65+
help = "generate and upload script file based on template (on by default unless `--local` or `--remote` are passed)"
66+
)]
67+
generate_script: bool,
68+
#[arg(long, value_name = "PATH", help = "upload local script file")]
69+
local_script: Option<PathBuf>,
70+
#[arg(long, value_name = "PATH", help = "use script file already present on remote")]
71+
remote_script: Option<PathBuf>,
72+
}
73+
impl Default for ScriptSpec {
74+
fn default() -> Self {
75+
Self {
76+
generate_script: true,
77+
local_script: Default::default(),
78+
remote_script: Default::default(),
79+
}
80+
}
81+
}
82+
83+
impl From<ScriptSpec> for ScriptSpecEnum {
84+
fn from(val: ScriptSpec) -> Self {
85+
if let Some(local_script) = val.local_script {
86+
ScriptSpecEnum::Local(local_script)
87+
} else if let Some(remote_script) = val.remote_script {
88+
ScriptSpecEnum::Remote(remote_script)
89+
} else {
90+
ScriptSpecEnum::Generate
91+
}
92+
}
93+
}
94+
6095
#[derive(Args, Clone, Debug)]
6196
#[group(multiple = false)]
6297
pub struct EdfSpec {
6398
#[arg(
6499
long,
65-
help = "generate and upload edf file based on template (on by default unless `--local`, `--remote` or `--no-edf` are passed)"
100+
help = "generate and upload edf file based on template (on by default unless `--local` or `--remote` are passed)"
66101
)]
67102
generate_edf: bool,
68103
#[arg(long, value_name = "PATH", help = "upload local edf file")]
@@ -111,8 +146,6 @@ pub enum CscsJobCommands {
111146
Submit {
112147
#[clap(short, long, help = "name of the job")]
113148
name: Option<String>,
114-
#[clap(short, long, help = "the path to the srun script file to use")]
115-
script_file: Option<PathBuf>,
116149
#[clap(
117150
short,
118151
long,
@@ -131,6 +164,8 @@ pub enum CscsJobCommands {
131164
stderr: Option<PathBuf>,
132165
#[command(flatten)]
133166
edf_spec: Option<EdfSpec>,
167+
#[command(flatten)]
168+
script_spec: Option<ScriptSpec>,
134169
#[clap(trailing_var_arg = true, help = "The command to run in the container")]
135170
command: Option<Vec<String>>,
136171
},

coman/src/cscs/api_client/client.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ use crate::{
2525
util::types::DockerImageUrl,
2626
};
2727
#[derive(Debug, Clone, Default)]
28+
pub enum ScriptSpec {
29+
#[default]
30+
Generate,
31+
Local(PathBuf),
32+
Remote(PathBuf),
33+
}
34+
#[derive(Debug, Clone, Default)]
2835
pub enum EdfSpec {
2936
#[default]
3037
Generate,
@@ -34,7 +41,6 @@ pub enum EdfSpec {
3441

3542
#[derive(Debug, Clone, Default)]
3643
pub struct JobStartOptions {
37-
pub script_file: Option<PathBuf>,
3844
pub image: Option<DockerImageUrl>,
3945
pub command: Option<Vec<String>>,
4046
pub stdout: Option<PathBuf>,
@@ -43,6 +49,7 @@ pub struct JobStartOptions {
4349
pub env: Vec<(String, String)>,
4450
pub mount: Vec<(String, String)>,
4551
pub edf_spec: EdfSpec,
52+
pub script_spec: ScriptSpec,
4653
}
4754

4855
pub struct CscsApi {

coman/src/cscs/handlers.rs

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010
use color_eyre::{Result, eyre::eyre};
1111
use reqwest::Url;
1212

13-
use super::api_client::client::EdfSpec;
13+
use super::api_client::client::{EdfSpec, ScriptSpec};
1414
use crate::{
1515
config::{ComputePlatform, Config},
1616
cscs::{
@@ -236,8 +236,49 @@ async fn handle_edf(
236236
EdfSpec::Remote(path) => Ok(path),
237237
}
238238
}
239+
async fn handle_script(
240+
api_client: &CscsApi,
241+
job_name: &str,
242+
base_path: &Path,
243+
current_system: &str,
244+
environment_path: &Path,
245+
workdir: &str,
246+
options: &JobStartOptions,
247+
) -> Result<PathBuf> {
248+
let config = Config::new().unwrap();
249+
let script_path = base_path.join("script.sh");
250+
match options.script_spec.clone() {
251+
ScriptSpec::Generate => {
252+
let script_template = config.cscs.sbatch_script_template;
253+
let mut tera = tera::Tera::default();
254+
tera.add_raw_template("script.sh", &script_template)?;
255+
let mut context = tera::Context::new();
256+
context.insert("name", &job_name);
257+
context.insert(
258+
"command",
259+
&options.command.clone().unwrap_or(config.cscs.command).join(" "),
260+
);
261+
context.insert("environment_file", &environment_path.to_path_buf());
262+
context.insert("container_workdir", &workdir);
263+
let script = tera.render("script.sh", &context)?;
264+
api_client
265+
.upload(current_system, script_path.clone(), script.into_bytes())
266+
.await?;
267+
268+
Ok(script_path)
269+
}
270+
ScriptSpec::Local(local_path) => {
271+
let script = std::fs::read_to_string(local_path)?;
272+
api_client
273+
.upload(current_system, script_path.clone(), script.into_bytes())
274+
.await?;
275+
276+
Ok(script_path)
277+
}
278+
ScriptSpec::Remote(script_path) => Ok(script_path),
279+
}
280+
}
239281

240-
#[allow(clippy::too_many_arguments)]
241282
pub async fn cscs_job_start(
242283
name: Option<String>,
243284
options: JobStartOptions,
@@ -276,6 +317,7 @@ pub async fn cscs_job_start(
276317

277318
let mut envvars = config.cscs.env.clone();
278319
envvars.extend(options.env.clone());
320+
279321
let environment_path = handle_edf(
280322
&api_client,
281323
&base_path,
@@ -286,27 +328,16 @@ pub async fn cscs_job_start(
286328
)
287329
.await?;
288330

289-
// upload script
290-
let script_path = base_path.join("script.sh");
291-
let script_template = options
292-
.script_file
293-
.clone()
294-
.map(std::fs::read_to_string)
295-
.unwrap_or(Ok(config.cscs.sbatch_script_template))?;
296-
let mut tera = tera::Tera::default();
297-
tera.add_raw_template("script.sh", &script_template)?;
298-
let mut context = tera::Context::new();
299-
context.insert("name", &job_name);
300-
context.insert(
301-
"command",
302-
&options.command.clone().unwrap_or(config.cscs.command).join(" "),
303-
);
304-
context.insert("environment_file", &environment_path);
305-
context.insert("container_workdir", &container_workdir);
306-
let script = tera.render("script.sh", &context)?;
307-
api_client
308-
.upload(current_system, script_path.clone(), script.into_bytes())
309-
.await?;
331+
let script_path = handle_script(
332+
&api_client,
333+
&job_name,
334+
&base_path,
335+
current_system,
336+
&environment_path,
337+
&container_workdir,
338+
&options,
339+
)
340+
.await?;
310341

311342
// start job
312343
api_client

coman/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ async fn main() -> Result<()> {
7373
}
7474
cli::CscsJobCommands::Submit {
7575
name,
76-
script_file,
7776
image,
7877
command,
7978
workdir,
@@ -82,11 +81,11 @@ async fn main() -> Result<()> {
8281
stdout,
8382
stderr,
8483
edf_spec,
84+
script_spec,
8585
} => {
8686
cli_cscs_job_start(
8787
name,
8888
JobStartOptions {
89-
script_file,
9089
image,
9190
command,
9291
container_workdir: workdir,
@@ -95,6 +94,7 @@ async fn main() -> Result<()> {
9594
stdout,
9695
stderr,
9796
edf_spec: edf_spec.unwrap_or_default().into(),
97+
script_spec: script_spec.unwrap_or_default().into(),
9898
},
9999
system,
100100
platform,

0 commit comments

Comments
 (0)