Programmatically controlling a Sauce Connect Tunnel
I recently decided that I wanted to create and control Sauce Connect tunnels from within my own test code and could not find any examples of how this could be done. After some research and experimentation, I was successful and so I wanted to document the method that I am using in case anyone else finds a need to do the same. Note that my test framework is written in Java and the method that I outline should work with any JVM language. Modifying this to work with another setup is left as an exercise to the reader.
I have been writing test automation for some of our websites recently and leveraging Sauce Labs when I needed specific browsers, browser version, and operating systems for those tests. Using Sauce Labs resources to test our non-public development and test sites requires the use of Sauce Connect to create a network tunnel between the Sauce Labs datacenter and our datacenter. I have borrowed the diagram below from Paul Hammant to show such a setup.
The existing documentation around Sauce Connect describes how to setup and start a tunnel manually and to run it as a long running service. This was not suitable for my needs. If you do more digging you will find a Jenkins plugin that will handle starting and stopping tunnels for you as part of your jobs. After evaluating this I found it also did not meet my needs. And finally if you dig really hard you will find a Maven plugin that will start and stop your Sauce Connect tunnel as part of your build process. This came closer to what I was looking for, but still I was looking for more control.
What I have implemented allows complete control of a Sauce Connect tunnel from within test code. This allows test specific controls such as unique tunnel naming, test specific black lists, wiring the tunnel to a proxy server, among other things. It actually turns out to be fairly simple to accomplish this by leveraging work that has already been accomplished by others and just taking it a little further. I will first the code you need, then delve a little into what it is doing.
Add the following dependency to your project. Be sure to use the most recent version.
<dependency> <groupId>com.saucelabs</groupId> <artifactId>ci-sauce</artifactId> <version>1.111</version> </dependency>
Process tunnel = sauceTunnelManager.openConnection( sauceUser, // username sauceKey, // apiKey port, // port null, // sauceConnectJar tunnelOptions, // Tunnel options null, // printStream null, // verboseLogging null // sauceConnectPath );
sauceTunnelManager.closeTunnelsForPlan( sauceUser, // username (same as start tunnel) tunnelOptions, // tunnelOptions (same as start tunnel) null);
This code uses the Sauce Connect Jenkins plugin to do the heavy lifting work. This turns out to be exactly what the Maven plugin is doing. The ci-sauce library actually contains all the code for the windows and unix versions of the Sauce Connect software. When you you make a call into the library to the openConnection() method, it extracts the appropriate software and runs it in a separate process.
When you call closeTunnelsForPlan() you have to pass the same user and tunnelOptions that you used when you started the tunnel so that it identifies the correct tunnel to shutdown.
- sauceUser : Your SauceLabs username.
- sauceKey : The API key from your SauceLabs account.
- Port : The port you want the tunnel to listen on. Null will use the default port of 4445. A zero value will use any open port. This is important if you need to run multiple tunnels on the same computer.
- tunnelOptions : This is a string of command line options to set things like the tunnel name, proxy settings, black list patterns. See the Sauce Connect documentation for available options. See the example below for formatting.
--tunnel-identifier TunnelName@Env-0001 --fast-fail-regexps www.unstable.com,www.thirdparty.com
- Updates: Sauce Labs releases updates to the Sauce Connect software pretty frequently. To upgrade the version of the tunnel software your tests use is as simple as updating the version of the CI-Sauce dependency in your project. Just like that, the new version is downloaded and used in your tests going forward. Very simple.
- Tunnel Name: It is important to ensure that the name of your tunnel is unique. If you use the name of an existing tunnel, then the other tunnel will be shutdown automatically when your new tunnel starts. I use a naming convention based on the test parameters and a random number.