This repository was archived by the owner on Jan 19, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtunnel.js
128 lines (107 loc) · 4.45 KB
/
tunnel.js
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
const sauceConnectLauncher = require("sauce-connect-launcher");
const path = require("path");
const _ = require("lodash");
const logger = require("./logger");
const settings = require("./settings");
const analytics = require("./global_analytics");
module.exports = class Tunnel {
constructor(options, sauceConnectLauncherMock) {
this.options = _.assign({}, options);
if (process.env.SC_NO_AUTODETECT === "true") {
this.options.tunnel.noAutodetect = true;
}
this.sauceConnectLauncher = sauceConnectLauncher;
if (sauceConnectLauncherMock) {
this.sauceConnectLauncher = sauceConnectLauncherMock;
}
}
initialize() {
return new Promise((resolve, reject) => {
if (!this.options.tunnel.username) {
return reject("Sauce tunnel support is missing configuration: Sauce username.");
}
if (!this.options.tunnel.accessKey) {
return reject("Sauce tunnel support is missing configuration: Sauce access key.");
}
analytics.push("sauce-connect-launcher-download");
const options = _.assign({}, this.options.tunnel, { logger: logger.debug });
/*eslint-disable no-console */
return this.sauceConnectLauncher.download(options, (err) => {
if (err) {
analytics.mark("sauce-connect-launcher-download", "failed");
logger.err("Failed to download sauce connect binary:");
logger.err(err);
logger.err("sauce-connect-launcher will attempt to re-download " +
"next time it is run.");
return reject(err);
} else {
analytics.mark("sauce-connect-launcher-download");
return resolve();
}
});
});
}
open() {
this.tunnelInfo = null;
let connectFailures = 0;
logger.log(`Opening sauce tunnel [${this.options.tunnel.tunnelIdentifier}]`
+ ` for user ${this.options.tunnel.username}`);
const connect = (/*runDiagnostics*/) => {
return new Promise((resolve, reject) => {
const logFilePath = `${path.resolve(settings.tempDir)}/build-${
settings.buildId}_sauceconnect_${this.options.tunnel.tunnelIdentifier}.log`;
const sauceOptions = _.assign({}, this.options.tunnel, {
readyFileId: this.options.tunnel.tunnelIdentifier,
verbose: settings.debug,
verboseDebugging: settings.debug,
logfile: logFilePath,
port: settings.BASE_SELENIUM_PORT_OFFSET
});
logger.debug(`calling sauceConnectLauncher() w/ ${JSON.stringify(sauceOptions)}`);
this.sauceConnectLauncher(sauceOptions, (err, sauceConnectProcess) => {
if (err) {
logger.debug("Error from sauceConnectLauncher():");
logger.debug(err.message);
if (err.message && err.message.indexOf("Could not start Sauce Connect") > -1) {
return reject(err.message);
} else if (settings.BAILED) {
connectFailures++;
// If some other parallel tunnel construction attempt has tripped the BAILED flag
// Stop retrying and report back a failure.
return reject(new Error("Bailed due to maximum number of tunnel retries."));
} else {
connectFailures++;
if (connectFailures >= settings.MAX_CONNECT_RETRIES) {
// We've met or exceeded the number of max retries, stop trying to connect.
// Make sure other attempts don't try to re-state this error.
settings.BAILED = true;
return reject(new Error(`Failed to create a secure sauce tunnel after ${
connectFailures} attempts.`));
} else {
// Otherwise, keep retrying, and hope this is merely a blip and not an outage.
logger.err(`>>> Sauce Tunnel Connection Failed! Retrying ${
connectFailures} of ${settings.MAX_CONNECT_RETRIES} attempts...`);
return connect()
.then(resolve)
.catch(reject);
}
}
} else {
this.tunnelInfo = { process: sauceConnectProcess };
return resolve();
}
});
});
};
return connect();
}
close() {
return new Promise((resolve) => {
if (this.tunnelInfo) {
logger.log(`Closing sauce tunnel [${this.options.tunnel.tunnelIdentifier}]`);
return this.tunnelInfo.process.close(() => resolve());
}
return resolve();
});
}
};