Skip to content

Commit c672d2f

Browse files
committed
Fix cluster state sniffing failures due to new _nodes response
Closes #2339
1 parent 033b5ed commit c672d2f

File tree

6 files changed

+40
-29
lines changed

6 files changed

+40
-29
lines changed

src/Elasticsearch.Net/Transport/Pipeline/RequestPipeline.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ private void ThrowBadAuthPipelineExceptionWhenNeeded(IApiCallDetails response)
301301
throw new PipelineException(PipelineFailure.BadAuthentication, response.OriginalException) { Response = response };
302302
}
303303

304-
public string SniffPath => "_nodes/_all/settings?flat_settings&timeout=" + this.PingTimeout.ToTimeUnit();
304+
public string SniffPath => "_nodes/http,settings?flat_settings&timeout=" + this.PingTimeout.ToTimeUnit();
305305

306306
public IEnumerable<Node> SniffNodes => this._connectionPool
307307
.CreateView((e, n)=> { using (new Auditable(e, this.AuditTrail, this._dateTimeProvider) { Node = n }) {} })

src/Elasticsearch.Net/Transport/Sniff/SniffResponse.cs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,63 +11,65 @@ internal class SniffResponse
1111
private static Regex AddressRe { get; } = new Regex(@"^((?<fqdn>[^/]+)/)?(?<ip>[^:]+):(?<port>\d+)$");
1212

1313
public string cluster_name { get; set; }
14-
public Dictionary<string, SniffNode> nodes { get; set; }
14+
public Dictionary<string, NodeInfo> nodes { get; set; }
1515

1616
public IEnumerable<Node> ToNodes(bool forceHttp = false)
1717
{
18-
foreach (var kv in nodes.Where(n=>n.Value.HttpEnabled))
18+
foreach (var kv in nodes.Where(n => n.Value.HttpEnabled))
1919
{
20-
yield return new Node(this.ParseToUri(kv.Value.http_address, forceHttp))
20+
yield return new Node(this.ParseToUri(kv.Value.http?.bound_address.FirstOrDefault(), forceHttp))
2121
{
2222
Name = kv.Value.name,
2323
Id = kv.Key,
2424
MasterEligible = kv.Value.MasterEligible,
2525
HoldsData = kv.Value.HoldsData,
26-
HttpEnabled = kv.Value.HttpEnabled,
2726
};
2827
}
2928
}
3029

31-
private Uri ParseToUri(string httpAdress, bool forceHttp)
30+
private Uri ParseToUri(string boundAddress, bool forceHttp)
3231
{
33-
if (httpAdress.IsNullOrEmpty()) return null;
32+
if (boundAddress.IsNullOrEmpty()) return null;
3433
var suffix = forceHttp ? "s" : string.Empty;
35-
var match = AddressRe.Match(httpAdress);
36-
if (!match.Success) throw new Exception($"Can not parse http_address: {httpAdress} to Uri");
34+
var match = AddressRe.Match(boundAddress);
35+
if (!match.Success) throw new Exception($"Can not parse bound_address: {boundAddress} to Uri");
3736

3837
var fqdn = match.Groups["fqdn"].Value?.Trim();
3938
var ip = match.Groups["ip"].Value?.Trim();
4039
var port = match.Groups["port"].Value?.Trim();
4140
var host = !fqdn.IsNullOrEmpty() ? fqdn : ip;
4241

4342
return new Uri($"http{suffix}://{host}:{port}");
44-
4543
}
46-
4744
}
4845

49-
internal class SniffNode
46+
internal class NodeInfo
5047
{
5148
public string name { get; set; }
5249
public string transport_address { get; set; }
53-
public string http_address { get; set; }
5450
public string host { get; set; }
5551
public string ip { get; set; }
5652
public string version { get; set; }
57-
public string build { get; set; }
53+
public string build_hash { get; set; }
54+
public IList<string> roles { get; set; }
55+
public NodeInfoHttp http { get; set; }
5856
public IDictionary<string, string> settings { get; set; }
5957

60-
internal bool MasterEligible => !((this.settings?.ContainsKey("node.master")).GetValueOrDefault(false) && Convert.ToBoolean(this.settings["node.master"]) == false);
61-
internal bool HoldsData => !((this.settings?.ContainsKey("node.data")).GetValueOrDefault(false) && Convert.ToBoolean(this.settings["node.data"]) == false);
58+
internal bool MasterEligible => this.roles?.Contains("master") ?? false;
59+
internal bool HoldsData => this.roles?.Contains("data") ?? false;
6260
internal bool HttpEnabled
6361
{
6462
get
6563
{
66-
if (this.settings == null) return true;
67-
if (!this.settings.ContainsKey("http.enabled")) return true;
68-
return Convert.ToBoolean(this.settings["http.enabled"]) ;
64+
if (this.settings != null && this.settings.ContainsKey("http.enabled"))
65+
return Convert.ToBoolean(this.settings["http.enabled"]);
66+
return http != null;
6967
}
7068
}
7169
}
7270

71+
internal class NodeInfoHttp
72+
{
73+
public IList<string> bound_address { get; set; }
74+
}
7375
}

src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ public void SetsSniffPathUsingToTimespan()
250250
var sniffingPipeline = CreatePipeline(uris =>
251251
new SniffingConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime) as RequestPipeline;
252252

253-
sniffingPipeline.SniffPath.Should().Be("_nodes/_all/settings?flat_settings&timeout=2s");
253+
sniffingPipeline.SniffPath.Should().Be("_nodes/http,settings?flat_settings&timeout=2s");
254254
}
255255
}
256256
}

src/Tests/Framework/VirtualClustering/MockResponses/SniffingResponse.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,28 @@ private static object CreateNodeResponse(Node node, string name, bool randomFqdn
3939
{
4040
name = name,
4141
transport_address = $"127.0.0.1:{node.Uri.Port + 1000}]",
42-
http_address = node.HttpEnabled ? $"{fqdn}127.0.0.1:{node.Uri.Port}" : null,
4342
host = Guid.NewGuid().ToString("N").Substring(0, 8),
4443
ip = "127.0.0.1",
4544
version = TestClient.Configuration.ElasticsearchVersion.Version,
46-
build = Guid.NewGuid().ToString("N").Substring(0, 8),
47-
settings = new Dictionary<string, object> {
45+
build_hash = Guid.NewGuid().ToString("N").Substring(0, 8),
46+
roles = new List<string>(),
47+
http = node.HttpEnabled ? new
48+
{
49+
bound_address = new []
50+
{
51+
$"{fqdn}127.0.0.1:{node.Uri.Port}"
52+
}
53+
} : null,
54+
settings = new Dictionary<string, object>
55+
{
4856
{ "cluster.name", ClusterName },
49-
{ "name", name },
57+
{ "node.name", name }
5058
}
5159
};
52-
if (!node.MasterEligible) nodeResponse.settings.Add("node.master", false);
53-
if (!node.HoldsData) nodeResponse.settings.Add("node.data", false);
54-
if (!node.HttpEnabled) nodeResponse.settings.Add("http.enabled", false);
60+
if (node.MasterEligible) nodeResponse.roles.Add("master");
61+
if (node.HoldsData) nodeResponse.roles.Add("data");
62+
if (!node.HttpEnabled)
63+
nodeResponse.settings.Add("http.enabled", false);
5564
return nodeResponse;
5665
}
5766

src/Tests/Framework/VirtualClustering/VirtualClusterConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void UpdateCluster(VirtualCluster cluster)
3636
}
3737
}
3838

39-
public bool IsSniffRequest(RequestData requestData) => requestData.Path.StartsWith("_nodes/_all/settings", StringComparison.Ordinal);
39+
public bool IsSniffRequest(RequestData requestData) => requestData.Path.StartsWith("_nodes/http,settings", StringComparison.Ordinal);
4040
public bool IsPingRequest(RequestData requestData) => requestData.Path == "/" && requestData.Method == HttpMethod.HEAD;
4141

4242
public override ElasticsearchResponse<TReturn> Request<TReturn>(RequestData requestData)

src/Tests/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# mode either u (unit test), i (integration test) or m (mixed mode)
2-
mode: i
2+
mode: u
33
# the elasticsearch version that should be started
44
# Can be a snapshot version of sonatype or "latest" to get the latest snapshot of sonatype
55
elasticsearch_version: 5.0.0-rc1

0 commit comments

Comments
 (0)