Skip to content

Commit a08fec9

Browse files
committed
fix #1923 add support for the shard stores API
1 parent 99fe463 commit a08fec9

File tree

8 files changed

+344
-0
lines changed

8 files changed

+344
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Elasticsearch.Net;
4+
5+
namespace Nest
6+
{
7+
public partial interface IElasticClient
8+
{
9+
/// <summary>
10+
/// Indices level stats provide statistics on different operations happening on an index. The API provides statistics on
11+
/// the index level scope (though most stats can also be retrieved using node level scope).
12+
/// <para> </para>http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-stats.html
13+
/// </summary>
14+
/// <param name="selector">Optionaly further describe the indices stats operation</param>
15+
IIndicesShardStoresResponse IndicesShardStores(Func<IndicesShardStoresDescriptor, IIndicesShardStoresRequest> selector = null);
16+
17+
/// <inheritdoc/>
18+
IIndicesShardStoresResponse IndicesShardStores(IIndicesShardStoresRequest request);
19+
20+
/// <inheritdoc/>
21+
Task<IIndicesShardStoresResponse> IndicesShardStoresAsync(Func<IndicesShardStoresDescriptor, IIndicesShardStoresRequest> selector = null);
22+
23+
/// <inheritdoc/>
24+
Task<IIndicesShardStoresResponse> IndicesShardStoresAsync(IIndicesShardStoresRequest request);
25+
26+
}
27+
28+
public partial class ElasticClient
29+
{
30+
/// <inheritdoc/>
31+
public IIndicesShardStoresResponse IndicesShardStores(Func<IndicesShardStoresDescriptor, IIndicesShardStoresRequest> selector = null) =>
32+
this.IndicesShardStores(selector.InvokeOrDefault(new IndicesShardStoresDescriptor()));
33+
34+
/// <inheritdoc/>
35+
public IIndicesShardStoresResponse IndicesShardStores(IIndicesShardStoresRequest request) =>
36+
this.Dispatcher.Dispatch<IIndicesShardStoresRequest, IndicesShardStoresRequestParameters, IndicesShardStoresResponse>(
37+
request,
38+
(p, d) => this.LowLevelDispatch.IndicesShardStoresDispatch<IndicesShardStoresResponse>(p)
39+
);
40+
41+
/// <inheritdoc/>
42+
public Task<IIndicesShardStoresResponse> IndicesShardStoresAsync(Func<IndicesShardStoresDescriptor, IIndicesShardStoresRequest> selector = null) =>
43+
this.IndicesShardStoresAsync(selector.InvokeOrDefault(new IndicesShardStoresDescriptor()));
44+
45+
/// <inheritdoc/>
46+
public Task<IIndicesShardStoresResponse> IndicesShardStoresAsync(IIndicesShardStoresRequest request) =>
47+
this.Dispatcher.DispatchAsync<IIndicesShardStoresRequest, IndicesShardStoresRequestParameters, IndicesShardStoresResponse, IIndicesShardStoresResponse>(
48+
request,
49+
(p, d) => this.LowLevelDispatch.IndicesShardStoresDispatchAsync<IndicesShardStoresResponse>(p)
50+
);
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System.Collections.Generic;
2+
3+
namespace Nest
4+
{
5+
public partial interface IIndicesShardStoresRequest
6+
{
7+
IEnumerable<TypeName> Types { get; set; }
8+
}
9+
10+
public partial class IndicesShardStoresRequest
11+
{
12+
private IEnumerable<TypeName> _types;
13+
public IEnumerable<TypeName> Types
14+
{
15+
get { return _types; }
16+
set
17+
{
18+
if (value.HasAny()) this.RequestState.RequestParameters.AddQueryString("types", value);
19+
else this.RequestState.RequestParameters.RemoveQueryString("types");
20+
this._types = value;
21+
}
22+
}
23+
}
24+
25+
[DescriptorFor("IndicesShardStores")]
26+
public partial class IndicesShardStoresDescriptor
27+
{
28+
private IEnumerable<TypeName> _types;
29+
IEnumerable<TypeName> IIndicesShardStoresRequest.Types
30+
{
31+
get { return _types; }
32+
set
33+
{
34+
if (value.HasAny()) this.RequestState.RequestParameters.AddQueryString("types", value);
35+
else this.RequestState.RequestParameters.RemoveQueryString("types");
36+
this._types = value;
37+
}
38+
}
39+
40+
//<summary>A comma-separated list of fields for `completion` metric (supports wildcards)</summary>
41+
public IndicesShardStoresDescriptor Types(params TypeName[] types) =>
42+
Assign(a => a.Types = types);
43+
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System.Collections.Generic;
2+
using System.Runtime.Serialization;
3+
using Newtonsoft.Json;
4+
5+
namespace Nest
6+
{
7+
public interface IIndicesShardStoresResponse : IResponse
8+
{
9+
[JsonProperty(PropertyName = "indices")]
10+
[JsonConverter(typeof(VerbatimDictionaryKeysJsonConverter))]
11+
Dictionary<string, IndicesShardStores> Indices { get; set; }
12+
}
13+
14+
[JsonObject]
15+
public class IndicesShardStoresResponse : ResponseBase, IIndicesShardStoresResponse
16+
{
17+
public Dictionary<string, IndicesShardStores> Indices { get; set; }
18+
}
19+
20+
public class IndicesShardStores
21+
{
22+
[JsonProperty(PropertyName = "shards")]
23+
[JsonConverter(typeof(VerbatimDictionaryKeysJsonConverter))]
24+
public Dictionary<string, ShardStoreWrapper> Shards { get; set; }
25+
}
26+
27+
public class ShardStoreWrapper
28+
{
29+
public IEnumerable<ShardStore> Stores { get; set; }
30+
}
31+
32+
[JsonConverter(typeof(ShardStoreJsonConverter))]
33+
public class ShardStore
34+
{
35+
[JsonProperty("id")]
36+
public string Id { get; set; }
37+
38+
[JsonProperty("name")]
39+
public string Name { get; set; }
40+
41+
[JsonProperty("transport_address")]
42+
public string TransportAddress { get; set; }
43+
44+
[JsonProperty("version")]
45+
public long Version { get; set; }
46+
47+
[JsonProperty("store_exeption")]
48+
public ShardStoreException StoreException { get; set; }
49+
50+
[JsonProperty("allocation")]
51+
public ShardStoreAllocation Allocation { get; set; }
52+
53+
[JsonProperty("attributes")]
54+
[JsonConverter(typeof(VerbatimDictionaryKeysJsonConverter))]
55+
public Dictionary<string, object> Attributes { get; set; }
56+
}
57+
58+
public class ShardStoreException
59+
{
60+
[JsonProperty("type")]
61+
public string Type { get; set; }
62+
[JsonProperty("reason")]
63+
public string Reason { get; set; }
64+
}
65+
66+
public enum ShardStoreAllocation
67+
{
68+
[EnumMember(Value = "primary")]
69+
Primary,
70+
[EnumMember(Value = "replica")]
71+
Replica,
72+
[EnumMember(Value = "unused")]
73+
Unused
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Linq;
6+
7+
namespace Nest
8+
{
9+
internal class ShardStoreJsonConverter : JsonConverter
10+
{
11+
private readonly VerbatimDictionaryKeysJsonConverter _dictionaryConverter =
12+
new VerbatimDictionaryKeysJsonConverter();
13+
14+
private readonly PropertyJsonConverter _elasticTypeConverter = new PropertyJsonConverter();
15+
16+
public override bool CanRead => true;
17+
public override bool CanWrite => false;
18+
public override bool CanConvert(Type objectType) => objectType == typeof(IDictionary<string, IFieldMapping>);
19+
20+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
21+
{
22+
throw new NotImplementedException();
23+
}
24+
25+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
26+
{
27+
var r = new ShardStore();
28+
JObject o = JObject.Load(reader);
29+
var properties = o.Properties().ToListOrNullIfEmpty();
30+
var id = properties.First();
31+
properties.AddRange(id.Value.Value<JObject>().Properties());
32+
33+
r.Id = id.Name;
34+
35+
foreach (var p in properties)
36+
{
37+
switch(p.Name)
38+
{
39+
case "name":
40+
r.Name = p.Value.Value<string>();
41+
break;
42+
case "transport_address":
43+
r.TransportAddress = p.Value.Value<string>();
44+
break;
45+
case "version":
46+
r.Version = p.Value.Value<long>();
47+
break;
48+
case "store_exception":
49+
r.StoreException = p.Value.ToObject<ShardStoreException>();
50+
break;
51+
case "allocation":
52+
r.Allocation = p.Value.ToObject<ShardStoreAllocation>();
53+
break;
54+
case "attributes":
55+
r.Attributes = p.Value.ToObject<Dictionary<string, object>>();
56+
break;
57+
}
58+
}
59+
return r;
60+
}
61+
}
62+
}

Diff for: src/Nest/Nest.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,10 @@
698698
<Compile Include="Indices\Monitoring\IndicesSegments\SegmentsResponse.cs" />
699699
<Compile Include="Indices\Monitoring\IndicesSegments\ShardSegmentRouting.cs" />
700700
<Compile Include="Indices\Monitoring\IndicesSegments\ShardsSegment.cs" />
701+
<Compile Include="Indices\Monitoring\IndicesShardStores\ElasticClient-IndicesShardStores.cs" />
702+
<Compile Include="Indices\Monitoring\IndicesShardStores\ShardStoreJsonConverter.cs" />
703+
<Compile Include="Indices\Monitoring\IndicesShardStores\IndicesShardStoresRequest.cs" />
704+
<Compile Include="Indices\Monitoring\IndicesShardStores\IndicesShardStoresResponse.cs" />
701705
<Compile Include="Indices\Monitoring\IndicesStats\ElasticClient-IndicesStats.cs" />
702706
<Compile Include="Indices\Monitoring\IndicesStats\IndexStats.cs" />
703707
<Compile Include="Indices\Monitoring\IndicesStats\IndicesStats.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Elasticsearch.Net;
6+
using FluentAssertions;
7+
using Nest;
8+
using Tests.Framework;
9+
using Tests.Framework.Integration;
10+
using Xunit;
11+
12+
namespace Tests.Indices.Monitoring.IndicesShardStores
13+
{
14+
[Collection(IntegrationContext.OwnIndex)]
15+
public class IndicesShardStoresApiTests : ApiIntegrationTestBase<IIndicesShardStoresResponse, IIndicesShardStoresRequest, IndicesShardStoresDescriptor, IndicesShardStoresRequest>
16+
{
17+
public IndicesShardStoresApiTests(OwnIndexCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
18+
19+
private static string IndexWithUnassignedShards = "nest-" + RandomString();
20+
21+
protected override void BeforeAllCalls(IElasticClient client, IDictionary<ClientMethod, string> values)
22+
{
23+
client.CreateIndex(IndexWithUnassignedShards, s => s
24+
.Settings(settings => settings
25+
.NumberOfShards(1)
26+
.NumberOfReplicas(2)
27+
)
28+
);
29+
client.Index(new IndexRequest<object>(IndexWithUnassignedShards)
30+
{
31+
Document = new { x = 1 },
32+
Refresh = true
33+
});
34+
}
35+
36+
protected override LazyResponses ClientUsage() => Calls(
37+
fluent: (client, f) => client.IndicesShardStores(f),
38+
fluentAsync: (client, f) => client.IndicesShardStoresAsync(f),
39+
request: (client, r) => client.IndicesShardStores(r),
40+
requestAsync: (client, r) => client.IndicesShardStoresAsync(r)
41+
);
42+
protected override IndicesShardStoresRequest Initializer =>
43+
new IndicesShardStoresRequest(IndexWithUnassignedShards)
44+
{
45+
Status = new[] { "all" }
46+
};
47+
protected override Func<IndicesShardStoresDescriptor, IIndicesShardStoresRequest> Fluent => s =>
48+
s.Index(IndexWithUnassignedShards)
49+
.Status("all");
50+
51+
protected override bool ExpectIsValid => true;
52+
protected override int ExpectStatusCode => 200;
53+
protected override HttpMethod HttpMethod => HttpMethod.GET;
54+
protected override string UrlPath => $"/{IndexWithUnassignedShards}/_shard_stores";
55+
56+
[I] public Task AssertResponse() => AssertOnAllResponses(r =>
57+
{
58+
r.Indices.Should().NotBeEmpty();
59+
var indicesShardStore = r.Indices[IndexWithUnassignedShards];
60+
indicesShardStore.Should().NotBeNull();
61+
indicesShardStore.Shards.Should().NotBeEmpty().And.ContainKey("0");
62+
var shardStoreWrapper = indicesShardStore.Shards["0"];
63+
shardStoreWrapper.Stores.Should().NotBeNullOrEmpty();
64+
65+
var shardStore = shardStoreWrapper.Stores.First();
66+
shardStore.Id.Should().NotBeNullOrWhiteSpace();
67+
shardStore.Name.Should().NotBeNullOrWhiteSpace();
68+
shardStore.TransportAddress.Should().NotBeNullOrWhiteSpace();
69+
shardStore.Version.Should().BeGreaterThan(0);
70+
shardStore.Allocation.Should().Be(ShardStoreAllocation.Primary);
71+
});
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Threading.Tasks;
2+
using Elasticsearch.Net;
3+
using Nest;
4+
using Tests.Framework;
5+
using Tests.Framework.MockData;
6+
using static Tests.Framework.UrlTester;
7+
8+
namespace Tests.Indices.Monitoring.IndicesShardStores
9+
{
10+
public class IndicesShardStoresUrlTests
11+
{
12+
[U] public async Task Urls()
13+
{
14+
await GET($"/_shard_stores")
15+
.Fluent(c => c.IndicesShardStores())
16+
.Request(c => c.IndicesShardStores(new IndicesShardStoresRequest()))
17+
.FluentAsync(c => c.IndicesShardStoresAsync())
18+
.RequestAsync(c => c.IndicesShardStoresAsync(new IndicesShardStoresRequest()))
19+
;
20+
21+
var index = "index1,index2";
22+
await GET($"/index1%2Cindex2/_shard_stores")
23+
.Fluent(c => c.IndicesShardStores(s=>s.Index(index)))
24+
.Request(c => c.IndicesShardStores(new IndicesShardStoresRequest(index)))
25+
.FluentAsync(c => c.IndicesShardStoresAsync(s=>s.Index(index)))
26+
.RequestAsync(c => c.IndicesShardStoresAsync(new IndicesShardStoresRequest(index)))
27+
;
28+
29+
}
30+
}
31+
}

Diff for: src/Tests/Tests.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,8 @@
547547
<Compile Include="Indices\StatusManagement\ForceMerge\ForceMergeUrlTests.cs" />
548548
<Compile Include="Search\SearchTemplate\RenderSearchTemplate\RenderSearchTemplateApiTests.cs" />
549549
<Compile Include="Search\SearchTemplate\RenderSearchTemplate\RenderSearchTemplateUrlTests.cs" />
550+
<Compile Include="Indices\Monitoring\IndicesShardStores\IndicesShardStoresApiTests.cs" />
551+
<Compile Include="Indices\Monitoring\IndicesShardStores\IndicesShardStoresUrlTests.cs" />
550552
<None Include="index.asciidoc" />
551553
<None Include="paket.references" />
552554
<None Include="tests.yaml" />

0 commit comments

Comments
 (0)