-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpreflight_cleanup.rs
More file actions
167 lines (152 loc) · 5.97 KB
/
Copy pathpreflight_cleanup.rs
File metadata and controls
167 lines (152 loc) · 5.97 KB
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
166
167
//! Container-specific preflight cleanup functionality
//!
//! This module provides preflight cleanup functionality specifically designed
//! for Docker container-based E2E testing. Since containers are managed by
//! testcontainers and automatically cleaned up, this module only handles
//! directory cleanup operations.
use crate::shared::command::CommandExecutor;
use crate::testing::e2e::context::TestContext;
use crate::testing::e2e::tasks::preflight_cleanup::{
cleanup_build_directory, cleanup_data_environment, cleanup_templates_directory,
PreflightCleanupError,
};
use tracing::{info, warn};
/// Performs pre-flight cleanup for Docker-based E2E tests
///
/// This function cleans up any artifacts remaining from previous test runs that may have
/// failed to clean up properly. It's designed for Docker-based E2E tests that use
/// testcontainers for container lifecycle management. It cleans up directories
/// and any hanging Docker containers from previous interrupted test runs.
///
/// # Arguments
///
/// * `env` - The test environment containing configuration and services
///
/// # Returns
///
/// Returns `Ok(())` if cleanup succeeds or if there were no resources to clean up.
///
/// # Errors
///
/// Returns an error if directory cleanup fails and would prevent new test runs.
pub fn preflight_cleanup_previous_resources(
env: &TestContext,
) -> Result<(), PreflightCleanupError> {
info!(
operation = "preflight_cleanup_docker",
"Starting pre-flight cleanup for Docker-based E2E tests"
);
// Clean the build directory to ensure fresh template state for E2E tests
cleanup_build_directory(env)?;
// Clean the templates directory to ensure fresh embedded template extraction for E2E tests
cleanup_templates_directory(env)?;
// Clean the data directory to ensure fresh environment state for E2E tests
cleanup_data_environment(env)?;
// Clean up any hanging Docker containers from interrupted test runs
cleanup_hanging_docker_containers(env);
info!(
operation = "preflight_cleanup_docker",
status = "success",
"Pre-flight cleanup for Docker-based E2E tests completed successfully"
);
Ok(())
}
/// Clean up hanging Docker containers from interrupted test runs
///
/// This function handles the case where testcontainers didn't clean up properly
/// due to abrupt test termination. It removes containers with the instance name
/// to prevent container name conflicts in subsequent test runs.
///
/// # Safety
///
/// This function is only intended for E2E test environments and should never
/// be called in production code paths. It specifically targets test containers.
///
/// # Arguments
///
/// * `env` - The test environment containing the instance name
fn cleanup_hanging_docker_containers(env: &TestContext) {
let instance_name = env.environment.instance_name().as_str();
let command_executor = CommandExecutor::new();
info!(
operation = "hanging_container_cleanup",
container_name = instance_name,
"Checking for hanging Docker containers from previous test runs"
);
// First, check if the container exists
let check_result = command_executor.run_command(
"docker",
&["ps", "-aq", "--filter", &format!("name={instance_name}")],
None,
);
match check_result {
Ok(output) => {
if output.stdout_trimmed().is_empty() {
info!(
operation = "hanging_container_cleanup",
container_name = instance_name,
status = "clean",
"No hanging containers found"
);
return;
}
info!(
operation = "hanging_container_cleanup",
container_name = instance_name,
"Found hanging container, attempting cleanup"
);
// Try to stop the container (in case it's running)
match command_executor.run_command("docker", &["stop", instance_name], None) {
Ok(_) => {
info!(
operation = "hanging_container_cleanup",
container_name = instance_name,
action = "stop",
status = "success",
"Container stopped successfully"
);
}
Err(e) => {
// Container might not be running, which is okay
warn!(
operation = "hanging_container_cleanup",
container_name = instance_name,
action = "stop",
status = "skipped",
error = %e,
"Could not stop container (probably not running)"
);
}
}
// Remove the container
match command_executor.run_command("docker", &["rm", instance_name], None) {
Ok(_) => {
info!(
operation = "hanging_container_cleanup",
container_name = instance_name,
status = "success",
"Hanging container cleaned up successfully"
);
}
Err(e) => {
warn!(
operation = "hanging_container_cleanup",
container_name = instance_name,
status = "failed",
error = %e,
"Failed to remove hanging container (this may cause test failures)"
);
}
}
}
Err(e) => {
warn!(
operation = "hanging_container_cleanup",
container_name = instance_name,
status = "check_failed",
error = %e,
"Could not check for hanging containers"
);
}
}
}