VerifySSHConnectionCtx ensures a fresh SSH connection succeeds before we hand control off to the system SSH binary.
(ctx context.Context, ip, keyFile string, port int)
| 447 | // VerifySSHConnectionCtx ensures a fresh SSH connection succeeds before we hand |
| 448 | // control off to the system SSH binary. |
| 449 | func VerifySSHConnectionCtx(ctx context.Context, ip, keyFile string, port int) error { |
| 450 | const ( |
| 451 | maxAttempts = 3 |
| 452 | retryDelay = 2 * time.Second |
| 453 | ) |
| 454 | |
| 455 | var lastErr error |
| 456 | for attempt := 1; attempt <= maxAttempts; attempt++ { |
| 457 | client, err := RobustSSHConnectCtx(ctx, ip, keyFile, port, 30) |
| 458 | if err == nil { |
| 459 | _, cmdErr := ExecuteSSHCommand(client, "true") |
| 460 | client.Close() |
| 461 | if cmdErr == nil { |
| 462 | return nil |
| 463 | } |
| 464 | lastErr = cmdErr |
| 465 | } else { |
| 466 | lastErr = err |
| 467 | } |
| 468 | |
| 469 | if attempt < maxAttempts { |
| 470 | if err := sleepWithContext(ctx, retryDelay); err != nil { |
| 471 | return fmt.Errorf("SSH connection cancelled") |
| 472 | } |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | if lastErr == nil { |
| 477 | lastErr = fmt.Errorf("unknown verification error") |
| 478 | } |
| 479 | |
| 480 | return fmt.Errorf("SSH verification failed: %w", lastErr) |
| 481 | } |
| 482 | |
| 483 | func ExecuteSSHCommand(client *SSHClient, command string) (string, error) { |
| 484 | if client == nil || client.client == nil { |