Skip to content

Commit 26bbb29

Browse files
authored
Merge pull request #370 from ArangoDB-Community/feature-3.8/DE-202-basic-admin-endpoints
Support basic Admin API
2 parents 54eff03 + d0cbb42 commit 26bbb29

20 files changed

+808
-17
lines changed

.circleci/config.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
- run:
6262
name: Test
6363
command:
64-
dotnet test -c Release --filter "Feature!=StreamTransaction&RunningMode!=Cluster&Feature!=Analyzer"
64+
dotnet test -c Release --filter "Feature!=StreamTransaction&RunningMode!=Cluster&Feature!=Analyzer&ServerVersion!=3_8_PLUS"
6565

6666
"test-arangodb-3_5":
6767
working_directory: ~/arangodb-net-standard
@@ -80,7 +80,7 @@ jobs:
8080
- run:
8181
name: Test
8282
command:
83-
dotnet test -c Release --filter "RunningMode!=Cluster"
83+
dotnet test -c Release --filter "RunningMode!=Cluster&ServerVersion!=3_8_PLUS"
8484

8585
"test-arangodb-3_6":
8686
working_directory: ~/arangodb-net-standard
@@ -99,7 +99,7 @@ jobs:
9999
- run:
100100
name: Test
101101
command:
102-
dotnet test -c Release --filter "RunningMode!=Cluster"
102+
dotnet test -c Release --filter "RunningMode!=Cluster&ServerVersion!=3_8_PLUS"
103103

104104
"test-arangodb-3_7":
105105
working_directory: ~/arangodb-net-standard
@@ -118,7 +118,7 @@ jobs:
118118
- run:
119119
name: Test
120120
command:
121-
dotnet test -c Release --filter RunningMode!=Cluster
121+
dotnet test -c Release --filter "RunningMode!=Cluster&ServerVersion!=3_8_PLUS"
122122

123123
"test-arangodb-3_8":
124124
working_directory: ~/arangodb-net-standard
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Net;
4+
using System.Threading.Tasks;
5+
using ArangoDBNetStandard;
6+
using ArangoDBNetStandard.AdminApi;
7+
using ArangoDBNetStandard.AdminApi.Models;
8+
using ArangoDBNetStandard.Transport;
9+
using Moq;
10+
using Xunit;
11+
12+
namespace ArangoDBNetStandardTest.AdminApi
13+
{
14+
public class AdminApiClientTest : IClassFixture<AdminApiClientTestFixture>, IAsyncLifetime
15+
{
16+
private AdminApiClient _adminApi;
17+
private ArangoDBClient _adb;
18+
19+
public AdminApiClientTest(AdminApiClientTestFixture fixture)
20+
{
21+
_adb = fixture.ArangoDBClient;
22+
_adminApi = _adb.Admin;
23+
}
24+
25+
public Task InitializeAsync()
26+
{
27+
return Task.CompletedTask;
28+
}
29+
30+
public Task DisposeAsync()
31+
{
32+
return Task.CompletedTask;
33+
}
34+
35+
/// <summary>
36+
/// Works only on version 3.8 onwards.
37+
/// </summary>
38+
/// <returns></returns>
39+
[Fact]
40+
[Trait("ServerVersion", "3_8_PLUS")]
41+
public async Task GetLogsAsync_ShouldSucceed()
42+
{
43+
var getResponse = await _adminApi.GetLogsAsync();
44+
Assert.NotNull(getResponse);
45+
}
46+
47+
[Fact]
48+
public async Task PostReloadRoutingInfoAsync_ShouldSucceed()
49+
{
50+
var postResponse = await _adminApi.PostReloadRoutingInfoAsync();
51+
Assert.True(postResponse);
52+
}
53+
54+
/// <summary>
55+
/// This test will run only in a cluster
56+
/// </summary>
57+
/// <returns></returns>
58+
[Fact]
59+
[Trait("RunningMode", "Cluster")]
60+
public async Task GetServerIdAsync_ShouldSucceed()
61+
{
62+
var getResponse = await _adminApi.GetServerIdAsync();
63+
Assert.NotNull(getResponse);
64+
Assert.False(getResponse.Error);
65+
Assert.NotNull(getResponse.Id);
66+
}
67+
68+
[Fact]
69+
public async Task GetServerRoleAsync_ShouldSucceed()
70+
{
71+
var getResponse = await _adminApi.GetServerRoleAsync();
72+
Assert.NotNull(getResponse);
73+
Assert.False(getResponse.Error);
74+
Assert.NotNull(getResponse.Role);
75+
}
76+
77+
[Fact]
78+
public async Task GetServerEngineTypeAsync_ShouldSucceed()
79+
{
80+
var getResponse = await _adminApi.GetServerEngineTypeAsync();
81+
Assert.NotNull(getResponse);
82+
Assert.NotNull(getResponse.Name);
83+
}
84+
85+
[Fact]
86+
public async Task GetServerVersionAsync_ShouldSucceed()
87+
{
88+
var getResponse = await _adminApi.GetServerVersionAsync();
89+
Assert.NotNull(getResponse);
90+
Assert.NotNull(getResponse.License);
91+
Assert.NotNull(getResponse.Version);
92+
Assert.NotNull(getResponse.Server);
93+
}
94+
}
95+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using ArangoDBNetStandard;
2+
using ArangoDBNetStandard.CollectionApi.Models;
3+
using ArangoDBNetStandard.IndexApi.Models;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace ArangoDBNetStandardTest.AdminApi
8+
{
9+
public class AdminApiClientTestFixture : ApiClientTestFixtureBase
10+
{
11+
public ArangoDBClient ArangoDBClient { get; internal set; }
12+
13+
public AdminApiClientTestFixture()
14+
{
15+
}
16+
17+
public override async Task InitializeAsync()
18+
{
19+
await base.InitializeAsync();
20+
string dbName = nameof(AdminApiClientTestFixture);
21+
await CreateDatabase(dbName);
22+
Console.WriteLine("Database " + dbName + " created successfully");
23+
ArangoDBClient = GetArangoDBClient(dbName);
24+
try
25+
{
26+
var dbRes = await ArangoDBClient.Database.GetCurrentDatabaseInfoAsync();
27+
if (dbRes.Error)
28+
throw new Exception("GetCurrentDatabaseInfoAsync failed: " + dbRes.Code.ToString());
29+
else
30+
{
31+
Console.WriteLine("Running tests in database " + dbRes.Result.Name);
32+
}
33+
}
34+
catch (ApiErrorException ex)
35+
{
36+
Console.WriteLine(ex.Message);
37+
throw ex;
38+
}
39+
}
40+
}
41+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
using System.Net;
2+
using System.Threading.Tasks;
3+
using ArangoDBNetStandard.Serialization;
4+
using ArangoDBNetStandard.Transport;
5+
using ArangoDBNetStandard.AdminApi.Models;
6+
7+
namespace ArangoDBNetStandard.AdminApi
8+
{
9+
/// <summary>
10+
/// A client for interacting with ArangoDB Admin API,
11+
/// implementing <see cref="IAdminApiClient"/>.
12+
/// </summary>
13+
public class AdminApiClient : ApiClientBase, IAdminApiClient
14+
{
15+
/// <summary>
16+
/// The transport client used to communicate with the ArangoDB host.
17+
/// </summary>
18+
protected IApiClientTransport _client;
19+
20+
/// <summary>
21+
/// The root path of the API.
22+
/// </summary>
23+
protected readonly string _adminApiPath = "_admin";
24+
25+
/// <summary>
26+
/// Creates an instance of <see cref="AdminApiClient"/>
27+
/// using the provided transport layer and the default JSON serialization.
28+
/// </summary>
29+
/// <param name="client">Transport client that the API client will use to communicate with ArangoDB</param>
30+
public AdminApiClient(IApiClientTransport client)
31+
: base(new JsonNetApiClientSerialization())
32+
{
33+
_client = client;
34+
}
35+
36+
/// <summary>
37+
/// Creates an instance of <see cref="AdminApiClient"/>
38+
/// using the provided transport and serialization layers.
39+
/// </summary>
40+
/// <param name="client">Transport client that the API client will use to communicate with ArangoDB.</param>
41+
/// <param name="serializer">Serializer to be used.</param>
42+
public AdminApiClient(IApiClientTransport client, IApiClientSerialization serializer)
43+
: base(serializer)
44+
{
45+
_client = client;
46+
}
47+
48+
/// <summary>
49+
/// Retrieves log messages from the server.
50+
/// GET /_admin/log/entries
51+
/// Works on ArangoDB 3.8 or later.
52+
/// </summary>
53+
/// <param name="query">Query string parameters</param>
54+
/// <returns></returns>
55+
/// <remarks>
56+
/// For further information see
57+
/// https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server
58+
/// </remarks>
59+
public virtual async Task<GetLogsResponse> GetLogsAsync(GetLogsQuery query = null)
60+
{
61+
string uri = $"{_adminApiPath}/log/entries";
62+
if (query != null)
63+
{
64+
uri += '?' + query.ToQueryString();
65+
}
66+
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
67+
{
68+
if (response.IsSuccessStatusCode)
69+
{
70+
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
71+
return DeserializeJsonFromStream<GetLogsResponse>(stream);
72+
}
73+
throw await GetApiErrorException(response).ConfigureAwait(false);
74+
}
75+
}
76+
77+
/// <summary>
78+
/// Reloads the routing table.
79+
/// POST /_admin/routing/reload
80+
/// </summary>
81+
/// <returns></returns>
82+
/// <remarks>
83+
/// For further information see
84+
/// https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#reloads-the-routing-information
85+
/// </remarks>
86+
public virtual async Task<bool> PostReloadRoutingInfoAsync()
87+
{
88+
string uri = $"{_adminApiPath}/routing/reload";
89+
var body = new byte[] { };
90+
using (var response = await _client.PostAsync(uri, body).ConfigureAwait(false))
91+
{
92+
if (response.IsSuccessStatusCode)
93+
{
94+
return true;
95+
}
96+
throw await GetApiErrorException(response).ConfigureAwait(false);
97+
}
98+
}
99+
100+
/// <summary>
101+
/// Retrieves the internal id of the server.
102+
/// The method will fail if the server is not running in cluster mode.
103+
/// GET /_admin/server/id
104+
/// </summary>
105+
/// <returns></returns>
106+
/// <remarks>
107+
/// For further information see
108+
/// https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#return-id-of-a-server-in-a-cluster
109+
/// </remarks>
110+
public virtual async Task<GetServerIdResponse> GetServerIdAsync()
111+
{
112+
string uri = $"{_adminApiPath}/server/id";
113+
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
114+
{
115+
if (response.IsSuccessStatusCode)
116+
{
117+
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
118+
return DeserializeJsonFromStream<GetServerIdResponse>(stream);
119+
}
120+
throw await GetApiErrorException(response).ConfigureAwait(false);
121+
}
122+
}
123+
124+
/// <summary>
125+
/// Retrieves the role of the server in a cluster.
126+
/// GET /_admin/server/role
127+
/// </summary>
128+
/// <returns></returns>
129+
/// <remarks>
130+
/// For further information see
131+
/// https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#return-the-role-of-a-server-in-a-cluster
132+
/// </remarks>
133+
public virtual async Task<GetServerRoleResponse> GetServerRoleAsync()
134+
{
135+
string uri = $"{_adminApiPath}/server/role";
136+
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
137+
{
138+
if (response.IsSuccessStatusCode)
139+
{
140+
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
141+
return DeserializeJsonFromStream<GetServerRoleResponse>(stream);
142+
}
143+
throw await GetApiErrorException(response).ConfigureAwait(false);
144+
}
145+
}
146+
147+
/// <summary>
148+
/// Retrieves the server database engine type.
149+
/// GET /_api/engine
150+
/// </summary>
151+
/// <returns></returns>
152+
/// <remarks>
153+
/// For further information see
154+
/// https://www.arangodb.com/docs/stable/http/miscellaneous-functions.html#return-server-database-engine-type
155+
/// </remarks>
156+
public virtual async Task<GetServerEngineTypeResponse> GetServerEngineTypeAsync()
157+
{
158+
string uri = "_api/engine";
159+
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
160+
{
161+
if (response.IsSuccessStatusCode)
162+
{
163+
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
164+
return DeserializeJsonFromStream<GetServerEngineTypeResponse>(stream);
165+
}
166+
throw await GetApiErrorException(response).ConfigureAwait(false);
167+
}
168+
}
169+
170+
/// <summary>
171+
/// Retrieves the server version.
172+
/// GET /_api/version
173+
/// </summary>
174+
/// <param name="query">Query string parameters</param>
175+
/// <returns></returns>
176+
/// <remarks>
177+
/// For further information see
178+
/// https://www.arangodb.com/docs/stable/http/miscellaneous-functions.html#return-server-version
179+
/// </remarks>
180+
public virtual async Task<GetServerVersionResponse> GetServerVersionAsync(GetServerVersionQuery query = null)
181+
{
182+
string uri = "_api/version";
183+
if (query != null)
184+
{
185+
uri += '?' + query.ToQueryString();
186+
}
187+
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
188+
{
189+
if (response.IsSuccessStatusCode)
190+
{
191+
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
192+
return DeserializeJsonFromStream<GetServerVersionResponse>(stream);
193+
}
194+
throw await GetApiErrorException(response).ConfigureAwait(false);
195+
}
196+
}
197+
}
198+
}

0 commit comments

Comments
 (0)