Skip to content

Commit f9765fe

Browse files
committed
test(bootstrap): add tests for auto-cleanup diagnosis behavior
Verify that the corrupted state diagnosis correctly reflects automatic cleanup: retryable flag is true, explanation mentions automatic cleanup, recovery steps no longer include manual docker volume rm, and the fallback command interpolates the gateway name. Refs #463
1 parent 2878653 commit f9765fe

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

crates/openshell-bootstrap/src/errors.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,87 @@ mod tests {
481481
assert!(d.summary.contains("Corrupted"));
482482
}
483483

484+
#[test]
485+
fn test_diagnose_corrupted_state_is_retryable_after_auto_cleanup() {
486+
// After the auto-cleanup fix (#463), corrupted state errors should be
487+
// marked retryable because deploy_gateway_with_logs now automatically
488+
// cleans up Docker resources on failure.
489+
let d = diagnose_failure(
490+
"mygw",
491+
"K8s namespace not ready",
492+
Some("configmaps \"extension-apiserver-authentication\" is forbidden"),
493+
)
494+
.expect("should match corrupted state pattern");
495+
assert!(
496+
d.retryable,
497+
"corrupted state should be retryable after auto-cleanup"
498+
);
499+
assert!(
500+
d.explanation.contains("automatically cleaned up"),
501+
"explanation should mention automatic cleanup, got: {}",
502+
d.explanation
503+
);
504+
}
505+
506+
#[test]
507+
fn test_diagnose_corrupted_state_recovery_no_manual_volume_rm() {
508+
// The recovery steps should no longer include a manual docker volume rm
509+
// command, since cleanup is now automatic. The first step should tell
510+
// the user to simply retry.
511+
let d = diagnose_failure("mygw", "cannot get resource \"namespaces\"", None)
512+
.expect("should match corrupted state pattern");
513+
514+
let all_commands: Vec<String> = d
515+
.recovery_steps
516+
.iter()
517+
.filter_map(|s| s.command.clone())
518+
.collect();
519+
let all_commands_joined = all_commands.join(" ");
520+
521+
assert!(
522+
!all_commands_joined.contains("docker volume rm"),
523+
"recovery steps should not include manual docker volume rm, got: {all_commands_joined}"
524+
);
525+
526+
// First step should be a description-only step (no command) about retrying
527+
assert!(
528+
d.recovery_steps[0].command.is_none(),
529+
"first recovery step should be description-only (automatic cleanup)"
530+
);
531+
assert!(
532+
d.recovery_steps[0]
533+
.description
534+
.contains("cleanup was automatic"),
535+
"first recovery step should mention automatic cleanup"
536+
);
537+
}
538+
539+
#[test]
540+
fn test_diagnose_corrupted_state_fallback_step_includes_gateway_name() {
541+
// The fallback recovery step should interpolate the gateway name so
542+
// users can copy-paste the command.
543+
let d = diagnose_failure("my-gateway", "is forbidden", None)
544+
.expect("should match corrupted state pattern");
545+
546+
assert!(
547+
d.recovery_steps.len() >= 2,
548+
"should have at least 2 recovery steps"
549+
);
550+
let fallback = &d.recovery_steps[1];
551+
let cmd = fallback
552+
.command
553+
.as_deref()
554+
.expect("fallback step should have a command");
555+
assert!(
556+
cmd.contains("my-gateway"),
557+
"fallback command should contain gateway name, got: {cmd}"
558+
);
559+
assert!(
560+
cmd.contains("openshell gateway destroy"),
561+
"fallback command should include gateway destroy, got: {cmd}"
562+
);
563+
}
564+
484565
#[test]
485566
fn test_diagnose_no_default_route() {
486567
let diagnosis = diagnose_failure(

0 commit comments

Comments
 (0)