eureka-js-client
Version:
A JavaScript implementation the Netflix OSS service registry, Eureka.
460 lines (459 loc) • 14 kB
HTML
<html lang="en">
<head>
<title>Code coverage report for src/DnsClusterResolver.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../prettify.css" />
<link rel="stylesheet" href="../base.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>
<a href="../index.html">all files</a> / <a href="index.html">src/</a> DnsClusterResolver.js
</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
<span class='fraction'>106/106</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">92.98% </span>
<span class="quiet">Branches</span>
<span class='fraction'>53/57</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">95.65% </span>
<span class="quiet">Functions</span>
<span class='fraction'>22/23</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Lines</span>
<span class='fraction'>75/75</span>
</div>
<div class='fl pad1y'>
<span class="strong">1 statement, 1 branch</span>
<span class="quiet">Ignored</span>
</div>
</div>
</div>
<div class='status-line high'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet">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
129
130
131</td><td class="line-coverage quiet"><span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">18×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">10×</span>
<span class="cline-any cline-yes">10×</span>
<span class="cline-any cline-yes">10×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">21×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">18×</span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">16×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-yes">20×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">19×</span>
<span class="cline-any cline-yes">19×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import dns from 'dns';
import async from 'async';
import shuffle from 'lodash/shuffle';
import xor from 'lodash/xor';
import Logger from './Logger';
<span class="fstat-no" title="function not covered" >function noop() {</span>}
/*
Locates a Eureka host using DNS lookups. The DNS records are looked up by a naming
convention and TXT records must be created according to the Eureka Wiki here:
https://github.com/Netflix/eureka/wiki/Configuring-Eureka-in-AWS-Cloud
Naming convention: txt.<REGION>.<HOST>
*/
export default class DnsClusterResolver {
constructor(config, logger) {
this.logger = logger || new Logger();
this.serverList = undefined;
this.config = config;
if (!this.config.eureka.ec2Region) {
throw new Error(
'EC2 region was undefined. ' +
'config.eureka.ec2Region must be set to resolve Eureka using DNS records.'
);
}
if (this.config.eureka.clusterRefreshInterval) {
this.startClusterRefresh();
}
}
resolveEurekaUrl(callback, retryAttempt = 0) {
this.getCurrentCluster((err) => {
if (err) return callback(err);
if (retryAttempt > 0) {
this.serverList.push(this.serverList.shift());
}
const { port, servicePath, ssl } = this.config.eureka;
const protocol = s</span>sl ? <span class="branch-0 cbranch-no" title="branch not covered" >'https' : 'http';
callback(null, `${protocol}://${this.serverList[0]}:${port}${servicePath}`);
});
}
getCurrentCluster(callback) {
if (this.serverList) {
return callback(null, this.serverList);
}
this.refreshCurrentCluster((err) => {
if (err) return callback(err);
return callback(null, this.serverList);
});
}
startClusterRefresh() {
const refreshTimer = setInterval(() => {
this.refreshCurrentCluster((err) => {
if (<span class="missing-if-branch" title="else path not taken" >E</span>err) this.logger.warn(err.message);
});
}, this.config.eureka.clusterRefreshInterval);
refreshTimer.unref();
}
refreshCurrentCluster(callback = <span class="branch-1 cbranch-no" title="branch not covered" >noop) {</span>
this.resolveClusterHosts((err, hosts) => {
if (err) return callback(err);
// if the cluster is the same (aside from order), we want to maintain our order
if (xor(this.serverList, hosts).length) {
this.serverList = hosts;
this.logger.info('Eureka cluster located, hosts will be used in the following order',
this.serverList);
} else {
this.logger.debug('Eureka cluster hosts unchanged, maintaining current server list.');
}
callback();
});
}
resolveClusterHosts(callback = <span class="branch-1 cbranch-no" title="branch not covered" >noop) {</span>
const { ec2Region, host, preferSameZone } = this.config.eureka;
const { dataCenterInfo } = this.config.instance;
const metadata = dataCenterInfo ? dataCenterInfo.metadata : undefined;
const availabilityZone = metadata ? metadata['availability-zone'] : undefined;
const dnsHost = `txt.${ec2Region}.${host}`;
dns.resolveTxt(dnsHost, (err, addresses) => {
if (err) {
return callback(new Error(
`Error resolving eureka cluster for region [${ec2Region}] using DNS: [${err}]`
));
}
const zoneRecords = [].concat(...addresses);
const dnsTasks = {};
zoneRecords.forEach((zoneRecord) => {
dnsTasks[zoneRecord] = (cb) => {
this.resolveZoneHosts(`txt.${zoneRecord}`, cb);
};
});
async.parallel(dnsTasks, (error, results) => {
if (error) return callback(error);
const hosts = [];
const myZoneHosts = [];
Object.keys(results).forEach((zone) => {
if (preferSameZone && availabilityZone && zone.lastIndexOf(availabilityZone, 0) === 0) {
myZoneHosts.push(...results[zone]);
} else {
hosts.push(...results[zone]);
}
});
const combinedHosts = [].concat(shuffle(myZoneHosts), shuffle(hosts));
if (!combinedHosts.length) {
return callback(
new Error(`Unable to locate any Eureka hosts in any zone via DNS @ ${dnsHost}`));
}
callback(null, combinedHosts);
});
});
}
resolveZoneHosts(zoneRecord, callback) {
dns.resolveTxt(zoneRecord, (err, results) => {
if (err) {
this.logger.warn(`Failed to resolve cluster zone ${zoneRecord}`, err.message);
return callback(new Error(`Error resolving cluster zone ${zoneRecord}: [${err}]`));
}
this.logger.debug(`Found Eureka Servers @ ${zoneRecord}`, results);
callback(null, ([].concat(...results)).filter((value) => (!!value)));
});
}
}
</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage
generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Fri May 31 2019 10:52:39 GMT-0700 (PDT)
</div>
</div>
<script src="../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../sorter.js"></script>
</body>
</html>