Skip to content

Commit

Permalink
Add tunnel readiness check after SauceConnect start (#258)
Browse files Browse the repository at this point in the history
  • Loading branch information
valfirst authored Jun 4, 2024
1 parent a36ea41 commit 8001a2c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand All @@ -34,6 +35,8 @@
public abstract class AbstractSauceTunnelManager implements SauceTunnelManager {

protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSauceTunnelManager.class);
private static final Duration READINESS_CHECK_TIMEOUT = Duration.ofSeconds(15);
private static final Duration READINESS_CHECK_POLLING_INTERVAL = Duration.ofSeconds(3);

/** Should Sauce Connect output be suppressed? */
protected boolean quietMode;
Expand Down Expand Up @@ -498,8 +501,10 @@ public Process openConnection(

} else {
// everything okay, continue the build
if (outputGobbler.getTunnelId() != null) {
tunnelInformation.setTunnelId(outputGobbler.getTunnelId());
String provisionedTunnelId = outputGobbler.getTunnelId();
if (provisionedTunnelId != null) {
tunnelInformation.setTunnelId(provisionedTunnelId);
waitForReadiness(provisionedTunnelId);
}
logMessage(
printStream, "Sauce Connect " + getCurrentVersion() + " now launched for: " + name);
Expand Down Expand Up @@ -537,7 +542,34 @@ public Process openConnection(
}
}

public SystemErrorGobbler makeErrorGobbler(PrintStream printStream, InputStream errorStream) {
private void waitForReadiness(String tunnelId) {
long pollingIntervalMillis = READINESS_CHECK_POLLING_INTERVAL.toMillis();
long endTime = System.currentTimeMillis() + READINESS_CHECK_TIMEOUT.toMillis();
try {
do {
long iterationStartTime = System.currentTimeMillis();
Boolean isReady = scEndpoint.getTunnelInformation(tunnelId).isReady;
if (Boolean.TRUE.equals(isReady)) {
LOGGER.info("Tunnel with ID {} is ready for use", tunnelId);
return;
}
LOGGER.info("Waiting for readiness of tunnel with ID {}", tunnelId);
long iterationEndTime = System.currentTimeMillis();

long iterationPollingTimeout = pollingIntervalMillis - (iterationEndTime - iterationStartTime);
if (iterationPollingTimeout > 0) {
TimeUnit.MILLISECONDS.sleep(iterationPollingTimeout);
}
}
while (System.currentTimeMillis() <= endTime);
LOGGER.warn("Wait for readiness of tunnel with ID {} is timed out", tunnelId);
}
catch (IOException | InterruptedException e) {
LOGGER.warn("Unable to check readiness of tunnel with ID {}", tunnelId, e);
}
}

public SystemErrorGobbler makeErrorGobbler(PrintStream printStream, InputStream errorStream) {
return new SystemErrorGobbler("ErrorGobbler", errorStream, printStream);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
@ExtendWith(MockitoExtension.class)
class SauceConnectFourManagerTest {

private static final String STARTED_SC_LOG = "/started_sc.log";
private static final String STARTED_TUNNEL_ID = "a3ccd3985ed04e7ba0fefc7fa401e9c8";

@Mock private Process mockProcess;
@Mock private SauceREST mockSauceRest;
@Mock private SauceConnectEndpoint mockSCEndpoint;
Expand All @@ -58,8 +61,11 @@ private InputStream getResourceAsStream(String resourceName) {
@ValueSource(booleans = {true, false})
void testOpenConnectionSuccessfully(boolean cleanUpOnExit) throws IOException {
when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of());
TunnelInformation readyTunnel = new TunnelInformation();
readyTunnel.isReady = true;
when(mockSCEndpoint.getTunnelInformation(STARTED_TUNNEL_ID)).thenReturn(readyTunnel);
tunnelManager.setCleanUpOnExit(cleanUpOnExit);
Process process = testOpenConnection("/started_sc.log");
Process process = testOpenConnection(STARTED_SC_LOG);
assertEquals(mockProcess, process);
}

Expand All @@ -75,7 +81,13 @@ void openConnectionTest_closes() throws IOException, InterruptedException {
@Test
void testOpenConnectionWithExtraSpacesInArgs() throws IOException {
when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of());
testOpenConnection("/started_sc.log", " username-with-spaces-around ");
TunnelInformation notReadyTunnel = new TunnelInformation();
notReadyTunnel.isReady = false;
TunnelInformation readyTunnel = new TunnelInformation();
readyTunnel.isReady = true;
when(mockSCEndpoint.getTunnelInformation(STARTED_TUNNEL_ID)).thenReturn(notReadyTunnel,
readyTunnel);
testOpenConnection(STARTED_SC_LOG, " username-with-spaces-around ");
}

private Process testOpenConnection(String logFile) throws IOException {
Expand Down Expand Up @@ -121,10 +133,12 @@ void openConnectionTest_existing_tunnel() throws IOException {
TunnelInformation started = new TunnelInformation();
started.tunnelIdentifier = "8949e55fb5e14fd6bf6230b7a609b494";
started.status = "running";
started.isReady = true;

when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of(started));
when(mockSCEndpoint.getTunnelInformation(STARTED_TUNNEL_ID)).thenReturn(started);

Process process = testOpenConnection("/started_sc.log");
Process process = testOpenConnection(STARTED_SC_LOG);
assertEquals(mockProcess, process);

verify(mockSCEndpoint).getTunnelsInformationForAUser();
Expand Down

0 comments on commit 8001a2c

Please sign in to comment.