start_command/
docker_recovery_options.rs1use crate::args_parser::WrapperOptions;
13use crate::recovery_delay::parse_on_kill_resume_delay_value;
14
15fn parse_on_kill_resume_value(value: &str) -> Result<u32, String> {
16 let text = value.trim();
17 match text.parse::<u32>() {
18 Ok(count) if count >= 1 && text.chars().all(|c| c.is_ascii_digit()) => Ok(count),
19 _ => Err(format!(
20 "Invalid --on-kill-resume value: \"{}\". Expected a positive integer.",
21 value
22 )),
23 }
24}
25
26pub fn parse_docker_recovery_option(
31 args: &[String],
32 index: usize,
33 options: &mut WrapperOptions,
34) -> Result<usize, String> {
35 let arg = args[index].as_str();
36 if arg == "--on-kill-resume" || arg == "--recovery-command" || arg == "--on-kill-resume-delay" {
37 let Some(value) = args.get(index + 1).filter(|value| !value.starts_with('-')) else {
38 let kind = match arg {
39 "--on-kill-resume" => "count",
40 "--recovery-command" => "command",
41 _ => "seconds",
42 };
43 return Err(format!("Option {} requires a {} argument", arg, kind));
44 };
45 match arg {
46 "--on-kill-resume" => options.on_kill_resume = Some(parse_on_kill_resume_value(value)?),
47 "--recovery-command" => options.recovery_command = Some(value.clone()),
48 _ => options.on_kill_resume_delay = Some(parse_on_kill_resume_delay_value(value)?),
49 }
50 return Ok(2);
51 }
52 if let Some(value) = arg.strip_prefix("--on-kill-resume-delay=") {
53 options.on_kill_resume_delay = Some(parse_on_kill_resume_delay_value(value)?);
54 return Ok(1);
55 }
56 if let Some(value) = arg.strip_prefix("--on-kill-resume=") {
57 options.on_kill_resume = Some(parse_on_kill_resume_value(value)?);
58 return Ok(1);
59 }
60 if let Some(value) = arg.strip_prefix("--recovery-command=") {
61 options.recovery_command = Some(value.to_string());
62 return Ok(1);
63 }
64 Ok(0)
65}
66
67pub fn validate_docker_recovery_options(options: &mut WrapperOptions) -> Result<(), String> {
71 if let Some(command) = options.recovery_command.as_deref() {
72 if command.trim().is_empty() {
73 return Err("--recovery-command requires a non-empty command".to_string());
74 }
75 options.on_kill_resume.get_or_insert(1);
76 }
77 if options.on_kill_resume.is_none() {
78 if options.on_kill_resume_delay.is_some() {
79 return Err(
80 "--on-kill-resume-delay requires --on-kill-resume or --recovery-command"
81 .to_string(),
82 );
83 }
84 return Ok(());
85 }
86 let flag = if options.recovery_command.is_some() {
87 "--recovery-command"
88 } else {
89 "--on-kill-resume"
90 };
91 if options.isolated.as_deref() != Some("docker") {
92 return Err(format!(
93 "{} option is only valid with --isolated docker as the only isolation level",
94 flag
95 ));
96 }
97 if !options.detached {
98 return Err(format!("{} option requires --detached", flag));
99 }
100 Ok(())
101}