|
22 | 22 |
|
23 | 23 | from __future__ import annotations |
24 | 24 |
|
| 25 | +import shlex |
25 | 26 | from typing import ClassVar |
26 | 27 |
|
27 | 28 | from swiss_ai_model_launch.launchers.launch_args import ( |
@@ -89,18 +90,23 @@ def _compose_framework_args(launch_args: LaunchArgs) -> str: |
89 | 90 | def _ocf_labels(launch_args: LaunchArgs) -> str: |
90 | 91 | """Build the --label flags surfacing launch metadata into the DNT entry. |
91 | 92 |
|
92 | | - $USER / $SLURM_* are expanded by the runtime shell on the compute node, |
93 | | - so they don't need to be known at script-render time. served_model_name |
94 | | - is quoted because it commonly contains '/' and other shell-meaningful |
95 | | - chars even though the value itself is safe. |
| 93 | + $USER / $SLURM_* / $(date ...) are left unquoted intentionally — they're |
| 94 | + runtime-expanded by the SBATCH shell. Values that come from user input |
| 95 | + at render time (framework, served_model_name) go through shlex.quote so |
| 96 | + spaces, quotes, $-constructs, command substitutions, or stray ; in them |
| 97 | + can't break the rank script or inject code at job-launch time. |
96 | 98 | """ |
| 99 | + user_input = [ |
| 100 | + f"framework={launch_args.framework}", |
| 101 | + f"served_model_name={launch_args.served_model_name}", |
| 102 | + ] |
| 103 | + quoted = " \\\n".join(f" --label {shlex.quote(kv)}" for kv in user_input) |
97 | 104 | return ( |
98 | 105 | " --label launched_by=$USER \\\n" |
99 | 106 | " --label slurm_job_id=$SLURM_JOB_ID \\\n" |
100 | 107 | " --label slurm_partition=${SLURM_JOB_PARTITION:-unknown} \\\n" |
101 | 108 | " --label worker_group_id=$SLURM_JOB_ID \\\n" |
102 | | - f" --label framework={launch_args.framework} \\\n" |
103 | | - f' --label served_model_name="{launch_args.served_model_name}" \\\n' |
| 109 | + f"{quoted} \\\n" |
104 | 110 | " --label started_at=$(date -u +%FT%TZ) \\\n" |
105 | 111 | ) |
106 | 112 |
|
|
0 commit comments