-
Notifications
You must be signed in to change notification settings - Fork 132
/
mod.rs
165 lines (144 loc) · 4.38 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#![allow(dead_code)]
extern crate custom_error;
extern crate serde_yaml;
pub mod output_extensions;
pub mod process_guard;
use self::custom_error::custom_error;
use self::output_extensions::ProcessOutput;
use std::process::{Command, Output, Stdio};
use std::{thread, time};
custom_error! {pub ProcessError
ProcessExited{message: String} = "could not start process '{message}'",
}
/// Runs command, wait for output and returns it output
///
/// # Arguments
///
/// * `command` - Command which will be invoked
///
pub fn run_process_and_get_output(mut command: Command) -> Output {
println!("Running command: {:?}", &command);
let content = command
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.expect("failed to execute process");
println!("Standard Output: {}", content.as_lossy_string());
println!("Standard Error: {}", content.err_as_lossy_string());
content
}
/// Runs command for n times with m second interval.
///
/// # Panics
///
/// Panics if max_attempts is exceeded and none of attempts return successful exit code.
///
/// # Arguments
///
/// * `command` - Command which will be invoked
/// * `timeout` - Timeout after unsuccesful attempt (in seconds)
/// * `max_attempts` - Maximum number of attempts
/// * `command_description` - User description of command
/// * `error_description` - User description of error
///
/// # Example
///
/// use process_utils::run_process_until_exited_successfully;
///
/// process_utils::run_process_until_exited_successfully(
/// jcli_wrapper::run_rest_stats_command_default(),
/// 2,
/// 5,
/// "get stats from jormungandr node",
/// "jormungandr node is not up"
/// );
///
pub fn run_process_until_exited_successfully(
mut command: Command,
timeout: u64,
max_attempts: i32,
command_description: &str,
error_description: &str,
) {
let one_second = time::Duration::from_millis(&timeout * 1000);
let mut attempts = max_attempts.clone();
loop {
if command
.status()
.expect(&format!(
"failed to get exit status of command: {}",
&command_description
))
.success()
{
break;
}
if attempts <= 0 {
break;
}
println!(
"non-zero status with message(). waiting {} s and trying again ({} of {})",
&timeout,
&max_attempts - &attempts + 1,
&max_attempts
);
attempts = attempts - 1;
thread::sleep(one_second);
}
if attempts <= 0 {
panic!(
"{} (tried to connect {} times with {} s interval)",
&error_description, &max_attempts, &timeout
);
}
println!("Success: {}", &command_description);
}
pub fn run_process_until_response_matches<F: Fn(Output) -> bool>(
mut command: Command,
is_output_ok: F,
timeout: u64,
max_attempts: i32,
command_description: &str,
error_description: &str,
) -> Result<(), ProcessError> {
let one_second = time::Duration::from_millis(&timeout * 1000);
let mut attempts = max_attempts.clone();
println!("Running command {:?} in loop", command);
loop {
let output = command
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.expect(&format!("cannot get output from command {:?}", &command));
println!("Standard Output: {}", output.as_lossy_string());
println!("Standard Error: {}", output.err_as_lossy_string());
if output.status.success() && is_output_ok(output) {
break;
}
if attempts <= 0 {
break;
}
println!(
"non-zero status with message(). waiting {} s and trying again ({} of {})",
&timeout,
&max_attempts - &attempts + 1,
&max_attempts
);
attempts = attempts - 1;
thread::sleep(one_second);
}
if attempts <= 0 {
return Err(ProcessError::ProcessExited {
message: format!(
"{} (tried to connect {} times with {} s interval)",
&error_description, &max_attempts, &timeout
),
});
}
println!("Success: {}", &command_description);
Ok(())
}