From 30ee98cf55bdf9282b02598b6af9b0f86ba75c90 Mon Sep 17 00:00:00 2001
From: Russ Cam <russ.cam@forloop.co.uk>
Date: Thu, 4 Jun 2020 16:01:39 +1000
Subject: [PATCH] Add Voting Config Exclusions APIs

Relates: #4718, elastic/elasticsearch#55760

This commit adds the voting config exclusions APIs to the high level client.
Custom response builder types are required because the APIs return
\n as the response, which the client will attempt to deserialize to a
response object.
---
 .../DeleteVotingConfigExclusionsRequest.cs    | 39 ++++++++++++
 .../DeleteVotingConfigExclusionsResponse.cs   | 10 ++++
 .../PostVotingConfigExclusionsRequest.cs      | 39 ++++++++++++
 .../PostVotingConfigExclusionsResponse.cs     | 10 ++++
 src/Nest/Descriptors.Cluster.cs               | 24 ++++++++
 src/Nest/ElasticClient.Cluster.cs             | 48 +++++++++++++++
 src/Nest/Requests.Cluster.cs                  | 60 +++++++++++++++++++
 .../DeleteVotingConfigExclusionsApiTests.cs   | 44 ++++++++++++++
 .../DeleteingVotingConfigExclusionsTests.cs   | 22 +++++++
 .../PostVotingConfigExclusionsApiTests.cs     | 43 +++++++++++++
 .../PostingVotingConfigExclusionsTests.cs     | 22 +++++++
 11 files changed, 361 insertions(+)
 create mode 100644 src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsRequest.cs
 create mode 100644 src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsResponse.cs
 create mode 100644 src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsRequest.cs
 create mode 100644 src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsResponse.cs
 create mode 100644 tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsApiTests.cs
 create mode 100644 tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteingVotingConfigExclusionsTests.cs
 create mode 100644 tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsApiTests.cs
 create mode 100644 tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostingVotingConfigExclusionsTests.cs

diff --git a/src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsRequest.cs b/src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsRequest.cs
new file mode 100644
index 00000000000..d34a0a0fabd
--- /dev/null
+++ b/src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsRequest.cs
@@ -0,0 +1,39 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Elasticsearch.Net;
+using Elasticsearch.Net.Specification.ClusterApi;
+
+namespace Nest
+{
+	[MapsApi("cluster.delete_voting_config_exclusions")]
+	public partial interface IDeleteVotingConfigExclusionsRequest { }
+
+	public partial class DeleteVotingConfigExclusionsRequest
+	{
+		protected sealed override void RequestDefaults(DeleteVotingConfigExclusionsRequestParameters parameters) =>
+			parameters.CustomResponseBuilder = new DeleteVotingConfigExclusionsResponseBuilder();
+	}
+
+	public partial class DeleteVotingConfigExclusionsDescriptor
+	{
+		protected sealed override void RequestDefaults(DeleteVotingConfigExclusionsRequestParameters parameters) =>
+			parameters.CustomResponseBuilder = new DeleteVotingConfigExclusionsResponseBuilder();
+	}
+
+	/// <summary>
+	/// Response is a single newline character, so skip trying to deserialize to an object
+	/// </summary>
+	internal class DeleteVotingConfigExclusionsResponseBuilder : CustomResponseBuilderBase
+	{
+		public override object DeserializeResponse(IElasticsearchSerializer builtInSerializer, IApiCallDetails response, Stream stream) =>
+			new DeleteVotingConfigExclusionsResponse();
+
+		public override Task<object> DeserializeResponseAsync(IElasticsearchSerializer builtInSerializer, IApiCallDetails response, Stream stream, CancellationToken ctx = default) =>
+			Task.FromResult<object>(new DeleteVotingConfigExclusionsResponse());
+	}
+}
diff --git a/src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsResponse.cs b/src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsResponse.cs
new file mode 100644
index 00000000000..33c7f1b4d61
--- /dev/null
+++ b/src/Nest/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsResponse.cs
@@ -0,0 +1,10 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+namespace Nest
+{
+	public class DeleteVotingConfigExclusionsResponse : ResponseBase
+	{
+	}
+}
diff --git a/src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsRequest.cs b/src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsRequest.cs
new file mode 100644
index 00000000000..94ff82133b3
--- /dev/null
+++ b/src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsRequest.cs
@@ -0,0 +1,39 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Elasticsearch.Net;
+using Elasticsearch.Net.Specification.ClusterApi;
+
+namespace Nest
+{
+	[MapsApi("cluster.post_voting_config_exclusions")]
+	public partial interface IPostVotingConfigExclusionsRequest { }
+
+	public partial class PostVotingConfigExclusionsRequest
+	{
+		protected sealed override void RequestDefaults(PostVotingConfigExclusionsRequestParameters parameters) =>
+			parameters.CustomResponseBuilder = new PostVotingConfigExclusionsResponseBuilder();
+	}
+
+	public partial class PostVotingConfigExclusionsDescriptor
+	{
+		protected sealed override void RequestDefaults(PostVotingConfigExclusionsRequestParameters parameters) =>
+			parameters.CustomResponseBuilder = new PostVotingConfigExclusionsResponseBuilder();
+	}
+
+	/// <summary>
+	/// Response is a single newline character, so skip trying to deserialize to an object
+	/// </summary>
+	internal class PostVotingConfigExclusionsResponseBuilder : CustomResponseBuilderBase
+	{
+		public override object DeserializeResponse(IElasticsearchSerializer builtInSerializer, IApiCallDetails response, Stream stream) =>
+			new PostVotingConfigExclusionsResponse();
+
+		public override Task<object> DeserializeResponseAsync(IElasticsearchSerializer builtInSerializer, IApiCallDetails response, Stream stream, CancellationToken ctx = default) =>
+			Task.FromResult<object>(new PostVotingConfigExclusionsResponse());
+	}
+}
diff --git a/src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsResponse.cs b/src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsResponse.cs
new file mode 100644
index 00000000000..bc93f3e7ad7
--- /dev/null
+++ b/src/Nest/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsResponse.cs
@@ -0,0 +1,10 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+namespace Nest
+{
+	public class PostVotingConfigExclusionsResponse : ResponseBase
+	{
+	}
+}
diff --git a/src/Nest/Descriptors.Cluster.cs b/src/Nest/Descriptors.Cluster.cs
index c1aa3d83e0b..ac3b811366e 100644
--- a/src/Nest/Descriptors.Cluster.cs
+++ b/src/Nest/Descriptors.Cluster.cs
@@ -42,6 +42,16 @@ public partial class ClusterAllocationExplainDescriptor : RequestDescriptorBase<
 		public ClusterAllocationExplainDescriptor IncludeYesDecisions(bool? includeyesdecisions = true) => Qs("include_yes_decisions", includeyesdecisions);
 	}
 
+	///<summary>Descriptor for DeleteVotingConfigExclusions <para>https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</para></summary>
+	public partial class DeleteVotingConfigExclusionsDescriptor : RequestDescriptorBase<DeleteVotingConfigExclusionsDescriptor, DeleteVotingConfigExclusionsRequestParameters, IDeleteVotingConfigExclusionsRequest>, IDeleteVotingConfigExclusionsRequest
+	{
+		internal override ApiUrls ApiUrls => ApiUrlsLookups.ClusterDeleteVotingConfigExclusions;
+		// values part of the url path
+		// Request parameters
+		///<summary>Specifies whether to wait for all excluded nodes to be removed from the cluster before clearing the voting configuration exclusions list.</summary>
+		public DeleteVotingConfigExclusionsDescriptor WaitForRemoval(bool? waitforremoval = true) => Qs("wait_for_removal", waitforremoval);
+	}
+
 	///<summary>Descriptor for GetSettings <para>https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html</para></summary>
 	public partial class ClusterGetSettingsDescriptor : RequestDescriptorBase<ClusterGetSettingsDescriptor, ClusterGetSettingsRequestParameters, IClusterGetSettingsRequest>, IClusterGetSettingsRequest
 	{
@@ -119,6 +129,20 @@ public partial class ClusterPendingTasksDescriptor : RequestDescriptorBase<Clust
 		public ClusterPendingTasksDescriptor MasterTimeout(Time mastertimeout) => Qs("master_timeout", mastertimeout);
 	}
 
+	///<summary>Descriptor for PostVotingConfigExclusions <para>https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</para></summary>
+	public partial class PostVotingConfigExclusionsDescriptor : RequestDescriptorBase<PostVotingConfigExclusionsDescriptor, PostVotingConfigExclusionsRequestParameters, IPostVotingConfigExclusionsRequest>, IPostVotingConfigExclusionsRequest
+	{
+		internal override ApiUrls ApiUrls => ApiUrlsLookups.ClusterPostVotingConfigExclusions;
+		// values part of the url path
+		// Request parameters
+		///<summary>A comma-separated list of the persistent ids of the nodes to exclude from the voting configuration. If specified, you may not also specify ?node_names.</summary>
+		public PostVotingConfigExclusionsDescriptor NodeIds(string nodeids) => Qs("node_ids", nodeids);
+		///<summary>A comma-separated list of the names of the nodes to exclude from the voting configuration. If specified, you may not also specify ?node_ids.</summary>
+		public PostVotingConfigExclusionsDescriptor NodeNames(string nodenames) => Qs("node_names", nodenames);
+		///<summary>Explicit operation timeout</summary>
+		public PostVotingConfigExclusionsDescriptor Timeout(Time timeout) => Qs("timeout", timeout);
+	}
+
 	///<summary>Descriptor for PutSettings <para>https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html</para></summary>
 	public partial class ClusterPutSettingsDescriptor : RequestDescriptorBase<ClusterPutSettingsDescriptor, ClusterPutSettingsRequestParameters, IClusterPutSettingsRequest>, IClusterPutSettingsRequest
 	{
diff --git a/src/Nest/ElasticClient.Cluster.cs b/src/Nest/ElasticClient.Cluster.cs
index b77a8c018f5..dc398dab4be 100644
--- a/src/Nest/ElasticClient.Cluster.cs
+++ b/src/Nest/ElasticClient.Cluster.cs
@@ -61,6 +61,30 @@ internal ClusterNamespace(ElasticClient client): base(client)
 		/// </summary>
 		public Task<ClusterAllocationExplainResponse> AllocationExplainAsync(IClusterAllocationExplainRequest request, CancellationToken ct = default) => DoRequestAsync<IClusterAllocationExplainRequest, ClusterAllocationExplainResponse>(request, request.RequestParameters, ct);
 		/// <summary>
+		/// <c>DELETE</c> request to the <c>cluster.delete_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public DeleteVotingConfigExclusionsResponse DeleteVotingConfigExclusions(Func<DeleteVotingConfigExclusionsDescriptor, IDeleteVotingConfigExclusionsRequest> selector = null) => DeleteVotingConfigExclusions(selector.InvokeOrDefault(new DeleteVotingConfigExclusionsDescriptor()));
+		/// <summary>
+		/// <c>DELETE</c> request to the <c>cluster.delete_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public Task<DeleteVotingConfigExclusionsResponse> DeleteVotingConfigExclusionsAsync(Func<DeleteVotingConfigExclusionsDescriptor, IDeleteVotingConfigExclusionsRequest> selector = null, CancellationToken ct = default) => DeleteVotingConfigExclusionsAsync(selector.InvokeOrDefault(new DeleteVotingConfigExclusionsDescriptor()), ct);
+		/// <summary>
+		/// <c>DELETE</c> request to the <c>cluster.delete_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public DeleteVotingConfigExclusionsResponse DeleteVotingConfigExclusions(IDeleteVotingConfigExclusionsRequest request) => DoRequest<IDeleteVotingConfigExclusionsRequest, DeleteVotingConfigExclusionsResponse>(request, request.RequestParameters);
+		/// <summary>
+		/// <c>DELETE</c> request to the <c>cluster.delete_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public Task<DeleteVotingConfigExclusionsResponse> DeleteVotingConfigExclusionsAsync(IDeleteVotingConfigExclusionsRequest request, CancellationToken ct = default) => DoRequestAsync<IDeleteVotingConfigExclusionsRequest, DeleteVotingConfigExclusionsResponse>(request, request.RequestParameters, ct);
+		/// <summary>
 		/// <c>GET</c> request to the <c>cluster.get_settings</c> API, read more about this API online:
 		/// <para></para>
 		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html</a>
@@ -133,6 +157,30 @@ internal ClusterNamespace(ElasticClient client): base(client)
 		/// </summary>
 		public Task<ClusterPendingTasksResponse> PendingTasksAsync(IClusterPendingTasksRequest request, CancellationToken ct = default) => DoRequestAsync<IClusterPendingTasksRequest, ClusterPendingTasksResponse>(request, request.RequestParameters, ct);
 		/// <summary>
+		/// <c>POST</c> request to the <c>cluster.post_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public PostVotingConfigExclusionsResponse PostVotingConfigExclusions(Func<PostVotingConfigExclusionsDescriptor, IPostVotingConfigExclusionsRequest> selector = null) => PostVotingConfigExclusions(selector.InvokeOrDefault(new PostVotingConfigExclusionsDescriptor()));
+		/// <summary>
+		/// <c>POST</c> request to the <c>cluster.post_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public Task<PostVotingConfigExclusionsResponse> PostVotingConfigExclusionsAsync(Func<PostVotingConfigExclusionsDescriptor, IPostVotingConfigExclusionsRequest> selector = null, CancellationToken ct = default) => PostVotingConfigExclusionsAsync(selector.InvokeOrDefault(new PostVotingConfigExclusionsDescriptor()), ct);
+		/// <summary>
+		/// <c>POST</c> request to the <c>cluster.post_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public PostVotingConfigExclusionsResponse PostVotingConfigExclusions(IPostVotingConfigExclusionsRequest request) => DoRequest<IPostVotingConfigExclusionsRequest, PostVotingConfigExclusionsResponse>(request, request.RequestParameters);
+		/// <summary>
+		/// <c>POST</c> request to the <c>cluster.post_voting_config_exclusions</c> API, read more about this API online:
+		/// <para></para>
+		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</a>
+		/// </summary>
+		public Task<PostVotingConfigExclusionsResponse> PostVotingConfigExclusionsAsync(IPostVotingConfigExclusionsRequest request, CancellationToken ct = default) => DoRequestAsync<IPostVotingConfigExclusionsRequest, PostVotingConfigExclusionsResponse>(request, request.RequestParameters, ct);
+		/// <summary>
 		/// <c>PUT</c> request to the <c>cluster.put_settings</c> API, read more about this API online:
 		/// <para></para>
 		/// <a href = "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html">https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html</a>
diff --git a/src/Nest/Requests.Cluster.cs b/src/Nest/Requests.Cluster.cs
index 9eeb09d792f..18ef232f202 100644
--- a/src/Nest/Requests.Cluster.cs
+++ b/src/Nest/Requests.Cluster.cs
@@ -58,6 +58,26 @@ public bool? IncludeYesDecisions
 		}
 	}
 
+	[InterfaceDataContract]
+	public partial interface IDeleteVotingConfigExclusionsRequest : IRequest<DeleteVotingConfigExclusionsRequestParameters>
+	{
+	}
+
+	///<summary>Request for DeleteVotingConfigExclusions <para>https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</para></summary>
+	public partial class DeleteVotingConfigExclusionsRequest : PlainRequestBase<DeleteVotingConfigExclusionsRequestParameters>, IDeleteVotingConfigExclusionsRequest
+	{
+		protected IDeleteVotingConfigExclusionsRequest Self => this;
+		internal override ApiUrls ApiUrls => ApiUrlsLookups.ClusterDeleteVotingConfigExclusions;
+		// values part of the url path
+		// Request parameters
+		///<summary>Specifies whether to wait for all excluded nodes to be removed from the cluster before clearing the voting configuration exclusions list.</summary>
+		public bool? WaitForRemoval
+		{
+			get => Q<bool? >("wait_for_removal");
+			set => Q("wait_for_removal", value);
+		}
+	}
+
 	[InterfaceDataContract]
 	public partial interface IClusterGetSettingsRequest : IRequest<ClusterGetSettingsRequestParameters>
 	{
@@ -234,6 +254,46 @@ public Time MasterTimeout
 		}
 	}
 
+	[InterfaceDataContract]
+	public partial interface IPostVotingConfigExclusionsRequest : IRequest<PostVotingConfigExclusionsRequestParameters>
+	{
+	}
+
+	///<summary>Request for PostVotingConfigExclusions <para>https://www.elastic.co/guide/en/elasticsearch/reference/master/voting-config-exclusions.html</para></summary>
+	public partial class PostVotingConfigExclusionsRequest : PlainRequestBase<PostVotingConfigExclusionsRequestParameters>, IPostVotingConfigExclusionsRequest
+	{
+		protected IPostVotingConfigExclusionsRequest Self => this;
+		internal override ApiUrls ApiUrls => ApiUrlsLookups.ClusterPostVotingConfigExclusions;
+		// values part of the url path
+		// Request parameters
+		///<summary>
+		/// A comma-separated list of the persistent ids of the nodes to exclude from the voting configuration. If specified, you may not also specify
+		/// ?node_names.
+		///</summary>
+		public string NodeIds
+		{
+			get => Q<string>("node_ids");
+			set => Q("node_ids", value);
+		}
+
+		///<summary>
+		/// A comma-separated list of the names of the nodes to exclude from the voting configuration. If specified, you may not also specify
+		/// ?node_ids.
+		///</summary>
+		public string NodeNames
+		{
+			get => Q<string>("node_names");
+			set => Q("node_names", value);
+		}
+
+		///<summary>Explicit operation timeout</summary>
+		public Time Timeout
+		{
+			get => Q<Time>("timeout");
+			set => Q("timeout", value);
+		}
+	}
+
 	[InterfaceDataContract]
 	public partial interface IClusterPutSettingsRequest : IRequest<ClusterPutSettingsRequestParameters>
 	{
diff --git a/tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsApiTests.cs b/tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsApiTests.cs
new file mode 100644
index 00000000000..01d31d4f27b
--- /dev/null
+++ b/tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteVotingConfigExclusionsApiTests.cs
@@ -0,0 +1,44 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System;
+using System.Threading;
+using Elasticsearch.Net;
+using FluentAssertions;
+using Nest;
+using Tests.Cluster.TaskManagement.GetTask;
+using Tests.Core.Extensions;
+using Tests.Core.ManagedElasticsearch.Clusters;
+using Tests.Core.ManagedElasticsearch.NodeSeeders;
+using Tests.Domain;
+using Tests.Framework.EndpointTests;
+using Tests.Framework.EndpointTests.TestState;
+
+namespace Tests.Cluster.VotingConfigExclusions.DeleteVotingConfigExclusions
+{
+	public class DeleteVotingConfigExclusionsApiTests : ApiIntegrationTestBase<WritableCluster, DeleteVotingConfigExclusionsResponse, IDeleteVotingConfigExclusionsRequest, DeleteVotingConfigExclusionsDescriptor, DeleteVotingConfigExclusionsRequest>
+	{
+		public DeleteVotingConfigExclusionsApiTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
+
+		protected override bool ExpectIsValid => true;
+		protected override int ExpectStatusCode => 200;
+
+		protected override Func<DeleteVotingConfigExclusionsDescriptor, IDeleteVotingConfigExclusionsRequest> Fluent => s => s
+			.WaitForRemoval();
+
+		protected override HttpMethod HttpMethod => HttpMethod.DELETE;
+
+		protected override DeleteVotingConfigExclusionsRequest Initializer => new DeleteVotingConfigExclusionsRequest { WaitForRemoval = true };
+		protected override string UrlPath => $"/_cluster/voting_config_exclusions?wait_for_removal=true";
+
+		protected override LazyResponses ClientUsage() => Calls(
+			(client, f) => client.Cluster.DeleteVotingConfigExclusions(f),
+			(client, f) => client.Cluster.DeleteVotingConfigExclusionsAsync(f),
+			(client, r) => client.Cluster.DeleteVotingConfigExclusions(r),
+			(client, r) => client.Cluster.DeleteVotingConfigExclusionsAsync(r)
+		);
+
+		protected override void ExpectResponse(DeleteVotingConfigExclusionsResponse response) => response.ShouldBeValid();
+	}
+}
diff --git a/tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteingVotingConfigExclusionsTests.cs b/tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteingVotingConfigExclusionsTests.cs
new file mode 100644
index 00000000000..446157a08bc
--- /dev/null
+++ b/tests/Tests/Cluster/VotingConfigExclusions/DeleteVotingConfigExclusions/DeleteingVotingConfigExclusionsTests.cs
@@ -0,0 +1,22 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System.Threading.Tasks;
+using Elastic.Elasticsearch.Xunit.XunitPlumbing;
+using Nest;
+using Tests.Framework.EndpointTests;
+using static Tests.Framework.EndpointTests.UrlTester;
+
+namespace Tests.Cluster.VotingConfigExclusions.DeleteVotingConfigExclusions
+{
+	public class DeleteingVotingConfigExclusionsTests : UrlTestsBase
+	{
+		[U] public override async Task Urls() =>
+			await DELETE("/_cluster/voting_config_exclusions")
+				.Fluent(c => c.Cluster.DeleteVotingConfigExclusions())
+				.Request(c => c.Cluster.DeleteVotingConfigExclusions(new DeleteVotingConfigExclusionsRequest()))
+				.FluentAsync(c => c.Cluster.DeleteVotingConfigExclusionsAsync())
+				.RequestAsync(c => c.Cluster.DeleteVotingConfigExclusionsAsync(new DeleteVotingConfigExclusionsRequest()));
+	}
+}
diff --git a/tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsApiTests.cs b/tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsApiTests.cs
new file mode 100644
index 00000000000..650ef4ee657
--- /dev/null
+++ b/tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostVotingConfigExclusionsApiTests.cs
@@ -0,0 +1,43 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System;
+using System.Threading;
+using Elasticsearch.Net;
+using FluentAssertions;
+using Nest;
+using Tests.Cluster.TaskManagement.GetTask;
+using Tests.Core.Extensions;
+using Tests.Core.ManagedElasticsearch.Clusters;
+using Tests.Core.ManagedElasticsearch.NodeSeeders;
+using Tests.Domain;
+using Tests.Framework.EndpointTests;
+using Tests.Framework.EndpointTests.TestState;
+
+namespace Tests.Cluster.VotingConfigExclusions.PostVotingConfigExclusions
+{
+	public class PostVotingConfigExclusionsApiTests : ApiIntegrationTestBase<WritableCluster, PostVotingConfigExclusionsResponse, IPostVotingConfigExclusionsRequest, PostVotingConfigExclusionsDescriptor, PostVotingConfigExclusionsRequest>
+	{
+		public PostVotingConfigExclusionsApiTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
+
+		protected override bool ExpectIsValid => true;
+		protected override int ExpectStatusCode => 200;
+
+		protected override Func<PostVotingConfigExclusionsDescriptor, IPostVotingConfigExclusionsRequest> Fluent => s => s
+			.NodeNames("node1,node2");
+		protected override HttpMethod HttpMethod => HttpMethod.POST;
+
+		protected override PostVotingConfigExclusionsRequest Initializer => new PostVotingConfigExclusionsRequest { NodeNames = "node1,node2" };
+		protected override string UrlPath => $"/_cluster/voting_config_exclusions?node_names=node1%2Cnode2";
+
+		protected override LazyResponses ClientUsage() => Calls(
+			(client, f) => client.Cluster.PostVotingConfigExclusions(f),
+			(client, f) => client.Cluster.PostVotingConfigExclusionsAsync(f),
+			(client, r) => client.Cluster.PostVotingConfigExclusions(r),
+			(client, r) => client.Cluster.PostVotingConfigExclusionsAsync(r)
+		);
+
+		protected override void ExpectResponse(PostVotingConfigExclusionsResponse response) => response.ShouldBeValid();
+	}
+}
diff --git a/tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostingVotingConfigExclusionsTests.cs b/tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostingVotingConfigExclusionsTests.cs
new file mode 100644
index 00000000000..50ba6301a6d
--- /dev/null
+++ b/tests/Tests/Cluster/VotingConfigExclusions/PostVotingConfigExclusions/PostingVotingConfigExclusionsTests.cs
@@ -0,0 +1,22 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System.Threading.Tasks;
+using Elastic.Elasticsearch.Xunit.XunitPlumbing;
+using Nest;
+using Tests.Framework.EndpointTests;
+using static Tests.Framework.EndpointTests.UrlTester;
+
+namespace Tests.Cluster.VotingConfigExclusions.PostVotingConfigExclusions
+{
+	public class PostingVotingConfigExclusionsTests : UrlTestsBase
+	{
+		[U] public override async Task Urls() =>
+			await POST("/_cluster/voting_config_exclusions?node_names=node1%2Cnode2")
+				.Fluent(c => c.Cluster.PostVotingConfigExclusions(f => f.NodeNames("node1,node2")))
+				.Request(c => c.Cluster.PostVotingConfigExclusions(new PostVotingConfigExclusionsRequest{ NodeNames = "node1,node2" }))
+				.FluentAsync(c => c.Cluster.PostVotingConfigExclusionsAsync(f => f.NodeNames("node1,node2")))
+				.RequestAsync(c => c.Cluster.PostVotingConfigExclusionsAsync(new PostVotingConfigExclusionsRequest{ NodeNames = "node1,node2" }));
+	}
+}
