Add packaging to cluster stats response (#41048)

This commit adds a packaging_types field to the cluster stats response
that outlines the build flavors and types present in a cluster.
This commit is contained in:
Jason Tedor 2019-04-10 13:38:44 -04:00
parent 884c3fd7ca
commit 24446ceae0
No known key found for this signature in database
GPG Key ID: FA89F05560F16BC5
4 changed files with 74 additions and 3 deletions

View File

@ -195,13 +195,19 @@ Will return, for example:
},
"discovery_types": {
...
}
},
"packaging_types": [
{
...
}
]
}
}
--------------------------------------------------
// TESTRESPONSE[s/"plugins": \[[^\]]*\]/"plugins": $body.$_path/]
// TESTRESPONSE[s/"network_types": \{[^\}]*\}/"network_types": $body.$_path/]
// TESTRESPONSE[s/"discovery_types": \{[^\}]*\}/"discovery_types": $body.$_path/]
// TESTRESPONSE[s/"packaging_types": \[[^\]]*\]/"packaging_types": $body.$_path/]
// TESTRESPONSE[s/: true|false/: $body.$_path/]
// TESTRESPONSE[s/: (\-)?[0-9]+/: $body.$_path/]
// TESTRESPONSE[s/: "[^"]*"/: $body.$_path/]
@ -209,7 +215,8 @@ Will return, for example:
// 1. Ignore the contents of the `plugins` object because we don't know all of
// the plugins that will be in it. And because we figure folks don't need to
// see an exhaustive list anyway.
// 2. Similarly, ignore the contents of `network_types` and `discovery_types`.
// 2. Similarly, ignore the contents of `network_types`, `discovery_types`, and
// `packaging_types`.
// 3. All of the numbers and strings on the right hand side of *every* field in
// the response are ignored. So we're really only asserting things about the
// the shape of this response, not the values in it.

View File

@ -77,3 +77,15 @@
cluster.stats: {}
- is_true: nodes.discovery_types
---
"get cluster stats returns packaging types":
- skip:
version: " - 7.0.99"
reason: "packaging types are added for v7.1.0"
- do:
cluster.stats: {}
- is_true: nodes.packaging_types

View File

@ -27,6 +27,7 @@ import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
@ -61,6 +62,7 @@ public class ClusterStatsNodes implements ToXContentFragment {
private final Set<PluginInfo> plugins;
private final NetworkTypes networkTypes;
private final DiscoveryTypes discoveryTypes;
private final PackagingTypes packagingTypes;
ClusterStatsNodes(List<ClusterStatsNodeResponse> nodeResponses) {
this.versions = new HashSet<>();
@ -93,6 +95,7 @@ public class ClusterStatsNodes implements ToXContentFragment {
this.jvm = new JvmStats(nodeInfos, nodeStats);
this.networkTypes = new NetworkTypes(nodeInfos);
this.discoveryTypes = new DiscoveryTypes(nodeInfos);
this.packagingTypes = new PackagingTypes(nodeInfos);
}
public Counts getCounts() {
@ -172,6 +175,8 @@ public class ClusterStatsNodes implements ToXContentFragment {
builder.endObject();
discoveryTypes.toXContent(builder, params);
packagingTypes.toXContent(builder, params);
return builder;
}
@ -650,4 +655,38 @@ public class ClusterStatsNodes implements ToXContentFragment {
}
}
static class PackagingTypes implements ToXContentFragment {
private final Map<Tuple<String, String>, AtomicInteger> packagingTypes;
PackagingTypes(final List<NodeInfo> nodeInfos) {
final Map<Tuple<String, String>, AtomicInteger> packagingTypes = new HashMap<>();
for (final NodeInfo nodeInfo : nodeInfos) {
final String flavor = nodeInfo.getBuild().flavor().displayName();
final String type = nodeInfo.getBuild().type().displayName();
packagingTypes.computeIfAbsent(Tuple.tuple(flavor, type), k -> new AtomicInteger()).incrementAndGet();
}
this.packagingTypes = Collections.unmodifiableMap(packagingTypes);
}
@Override
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
builder.startArray("packaging_types");
{
for (final Map.Entry<Tuple<String, String>, AtomicInteger> entry : packagingTypes.entrySet()) {
builder.startObject();
{
builder.field("flavor", entry.getKey().v1());
builder.field("type", entry.getKey().v2());
builder.field("count", entry.getValue().get());
}
builder.endObject();
}
}
builder.endArray();
return builder;
}
}
}

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.monitoring.collector.cluster;
import org.elasticsearch.Build;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
import org.elasticsearch.action.admin.cluster.node.info.PluginsAndModules;
@ -268,6 +269,11 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase<Cl
when(mockJvmInfo.getBundledJdk()).thenReturn(true);
when(mockJvmInfo.getUsingBundledJdk()).thenReturn(true);
final Build mockBuild = mock(Build.class);
when(mockBuild.flavor()).thenReturn(Build.Flavor.DEFAULT);
when(mockBuild.type()).thenReturn(Build.Type.DOCKER);
when(mockNodeInfo.getBuild()).thenReturn(mockBuild);
final NodeStats mockNodeStats = mock(NodeStats.class);
when(mockNodeStats.getTimestamp()).thenReturn(0L);
@ -521,7 +527,14 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase<Cl
+ "},"
+ "\"discovery_types\":{"
+ "\"_disco\":1"
+ "}"
+ "},"
+ "\"packaging_types\":["
+ "{"
+ "\"flavor\":\"default\","
+ "\"type\":\"docker\","
+ "\"count\":1"
+ "}"
+ "]"
+ "}"
+ "},"
+ "\"cluster_state\":{"