diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
index 250bbd520da..c4567e22e0b 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
@@ -21,18 +21,15 @@ package org.elasticsearch.client;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.flush.FlushRequest;
 import org.elasticsearch.action.admin.indices.flush.FlushResponse;
 import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest;
@@ -45,7 +42,6 @@ import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRespon
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
 import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
@@ -55,15 +51,14 @@ import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
 import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.rest.RestStatus;
 
 import java.io.IOException;
@@ -93,9 +88,9 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public DeleteIndexResponse delete(DeleteIndexRequest deleteIndexRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse delete(DeleteIndexRequest deleteIndexRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(deleteIndexRequest, RequestConverters::deleteIndex, options,
-                DeleteIndexResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -106,9 +101,9 @@ public final class IndicesClient {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      */
-    public void deleteAsync(DeleteIndexRequest deleteIndexRequest, RequestOptions options, ActionListener<DeleteIndexResponse> listener) {
+    public void deleteAsync(DeleteIndexRequest deleteIndexRequest, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(deleteIndexRequest, RequestConverters::deleteIndex, options,
-                DeleteIndexResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -147,9 +142,9 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse putMapping(PutMappingRequest putMappingRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, RequestConverters::putMapping, options,
-                PutMappingResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -160,9 +155,10 @@ public final class IndicesClient {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      */
-    public void putMappingAsync(PutMappingRequest putMappingRequest, RequestOptions options,  ActionListener<PutMappingResponse> listener) {
+    public void putMappingAsync(PutMappingRequest putMappingRequest, RequestOptions options,
+                                ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, RequestConverters::putMapping, options,
-                PutMappingResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -231,9 +227,9 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public IndicesAliasesResponse updateAliases(IndicesAliasesRequest indicesAliasesRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse updateAliases(IndicesAliasesRequest indicesAliasesRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(indicesAliasesRequest, RequestConverters::updateAliases, options,
-                IndicesAliasesResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -245,9 +241,9 @@ public final class IndicesClient {
      * @param listener the listener to be notified upon request completion
      */
     public void updateAliasesAsync(IndicesAliasesRequest indicesAliasesRequest, RequestOptions options,
-                                   ActionListener<IndicesAliasesResponse> listener) {
+                                   ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(indicesAliasesRequest, RequestConverters::updateAliases, options,
-                IndicesAliasesResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -286,9 +282,9 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public CloseIndexResponse close(CloseIndexRequest closeIndexRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse close(CloseIndexRequest closeIndexRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(closeIndexRequest, RequestConverters::closeIndex, options,
-                CloseIndexResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -299,9 +295,9 @@ public final class IndicesClient {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      */
-    public void closeAsync(CloseIndexRequest closeIndexRequest, RequestOptions options, ActionListener<CloseIndexResponse> listener) {
+    public void closeAsync(CloseIndexRequest closeIndexRequest, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(closeIndexRequest, RequestConverters::closeIndex, options,
-                CloseIndexResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
 
@@ -706,9 +702,9 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public UpdateSettingsResponse putSettings(UpdateSettingsRequest updateSettingsRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse putSettings(UpdateSettingsRequest updateSettingsRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(updateSettingsRequest, RequestConverters::indexPutSettings, options,
-                UpdateSettingsResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -720,9 +716,9 @@ public final class IndicesClient {
      * @param listener the listener to be notified upon request completion
      */
     public void putSettingsAsync(UpdateSettingsRequest updateSettingsRequest, RequestOptions options,
-                                 ActionListener<UpdateSettingsResponse> listener) {
+                                 ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(updateSettingsRequest, RequestConverters::indexPutSettings, options,
-                UpdateSettingsResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -734,10 +730,10 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public PutIndexTemplateResponse putTemplate(PutIndexTemplateRequest putIndexTemplateRequest,
-                                                RequestOptions options) throws IOException {
+    public AcknowledgedResponse putTemplate(PutIndexTemplateRequest putIndexTemplateRequest,
+                                            RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(putIndexTemplateRequest, RequestConverters::putTemplate, options,
-            PutIndexTemplateResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -749,9 +745,9 @@ public final class IndicesClient {
      * @param listener the listener to be notified upon request completion
      */
     public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest, RequestOptions options,
-                                 ActionListener<PutIndexTemplateResponse> listener) {
+                                 ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, RequestConverters::putTemplate, options,
-            PutIndexTemplateResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/LicenseClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/LicenseClient.java
index 589f187f397..ca6539daa04 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/LicenseClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/LicenseClient.java
@@ -21,6 +21,7 @@ package org.elasticsearch.client;
 
 import org.apache.http.HttpEntity;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.io.Streams;
 import org.elasticsearch.common.xcontent.DeprecationHandler;
@@ -30,7 +31,6 @@ import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
 import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
 import org.elasticsearch.protocol.xpack.license.GetLicenseResponse;
 import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
@@ -106,9 +106,9 @@ public final class LicenseClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public DeleteLicenseResponse deleteLicense(DeleteLicenseRequest request, RequestOptions options) throws IOException {
+    public AcknowledgedResponse deleteLicense(DeleteLicenseRequest request, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::deleteLicense, options,
-            DeleteLicenseResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -116,9 +116,9 @@ public final class LicenseClient {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      */
-    public void deleteLicenseAsync(DeleteLicenseRequest request, RequestOptions options, ActionListener<DeleteLicenseResponse> listener) {
+    public void deleteLicenseAsync(DeleteLicenseRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::deleteLicense, options,
-            DeleteLicenseResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
index 50d7465ae33..e705ca12806 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
@@ -27,7 +27,6 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.ActionRequest;
 import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
 import org.elasticsearch.action.bulk.BulkRequest;
@@ -53,6 +52,7 @@ import org.elasticsearch.action.search.MultiSearchResponse;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.SearchScrollRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.update.UpdateRequest;
 import org.elasticsearch.action.update.UpdateResponse;
 import org.elasticsearch.common.CheckedConsumer;
@@ -916,9 +916,9 @@ public class RestHighLevelClient implements Closeable {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public DeleteStoredScriptResponse deleteScript(DeleteStoredScriptRequest request, RequestOptions options) throws IOException {
+    public AcknowledgedResponse deleteScript(DeleteStoredScriptRequest request, RequestOptions options) throws IOException {
         return performRequestAndParseEntity(request, RequestConverters::deleteScript, options,
-            DeleteStoredScriptResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -930,9 +930,9 @@ public class RestHighLevelClient implements Closeable {
      * @param listener the listener to be notified upon request completion
      */
     public void deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions options,
-                                  ActionListener<DeleteStoredScriptResponse> listener) {
+                                  ActionListener<AcknowledgedResponse> listener) {
         performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options,
-            DeleteStoredScriptResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
index 319eb96a9f8..7df0df4836d 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
@@ -21,23 +21,21 @@ package org.elasticsearch.client;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
-import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
-import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
 import java.io.IOException;
 
@@ -95,9 +93,9 @@ public final class SnapshotClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public PutRepositoryResponse createRepository(PutRepositoryRequest putRepositoryRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse createRepository(PutRepositoryRequest putRepositoryRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(putRepositoryRequest, RequestConverters::createRepository, options,
-            PutRepositoryResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -109,9 +107,9 @@ public final class SnapshotClient {
      * @param listener the listener to be notified upon request completion
      */
     public void createRepositoryAsync(PutRepositoryRequest putRepositoryRequest, RequestOptions options,
-                                      ActionListener<PutRepositoryResponse> listener) {
+                                      ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest, RequestConverters::createRepository, options,
-            PutRepositoryResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -123,10 +121,10 @@ public final class SnapshotClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public DeleteRepositoryResponse deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options)
+    public AcknowledgedResponse deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options)
         throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository, options,
-            DeleteRepositoryResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -138,9 +136,9 @@ public final class SnapshotClient {
      * @param listener the listener to be notified upon request completion
      */
     public void deleteRepositoryAsync(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options,
-                                      ActionListener<DeleteRepositoryResponse> listener) {
+                                      ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository, options,
-            DeleteRepositoryResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -294,9 +292,9 @@ public final class SnapshotClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public DeleteSnapshotResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
+    public AcknowledgedResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
-            DeleteSnapshotResponse::fromXContent, emptySet());
+            AcknowledgedResponse::fromXContent, emptySet());
     }
 
     /**
@@ -309,8 +307,8 @@ public final class SnapshotClient {
      * @param listener the listener to be notified upon request completion
      */
     public void deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
-                            ActionListener<DeleteSnapshotResponse> listener) {
+                            ActionListener<AcknowledgedResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
-            DeleteSnapshotResponse::fromXContent, listener, emptySet());
+            AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 }
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
index 36a45999b51..533f6bcb22e 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
@@ -27,18 +27,15 @@ import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.action.admin.indices.alias.Alias;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.flush.FlushRequest;
 import org.elasticsearch.action.admin.indices.flush.FlushResponse;
 import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest;
@@ -51,7 +48,6 @@ import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRespon
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
 import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
@@ -61,20 +57,19 @@ import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
 import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
 import org.elasticsearch.action.admin.indices.shrink.ResizeType;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
 import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.WriteRequest;
 import org.elasticsearch.action.support.broadcast.BroadcastResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.metadata.AliasMetaData;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
@@ -411,7 +406,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         mappingBuilder.endObject().endObject().endObject();
         putMappingRequest.source(mappingBuilder);
 
-        PutMappingResponse putMappingResponse =
+        AcknowledgedResponse putMappingResponse =
                 execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
         assertTrue(putMappingResponse.isAcknowledged());
 
@@ -431,7 +426,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         mappingBuilder.endObject().endObject().endObject();
         putMappingRequest.source(mappingBuilder);
 
-        PutMappingResponse putMappingResponse =
+        AcknowledgedResponse putMappingResponse =
             execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
         assertTrue(putMappingResponse.isAcknowledged());
 
@@ -467,7 +462,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         mappingBuilder.endObject().endObject().endObject();
         putMappingRequest.source(mappingBuilder);
 
-        PutMappingResponse putMappingResponse =
+        AcknowledgedResponse putMappingResponse =
             execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
         assertTrue(putMappingResponse.isAcknowledged());
 
@@ -497,7 +492,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
             createIndex(indexName, Settings.EMPTY);
 
             DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
-            DeleteIndexResponse deleteIndexResponse =
+            AcknowledgedResponse deleteIndexResponse =
                     execute(deleteIndexRequest, highLevelClient().indices()::delete, highLevelClient().indices()::deleteAsync);
             assertTrue(deleteIndexResponse.isAcknowledged());
 
@@ -529,7 +524,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         AliasActions addAction = new AliasActions(AliasActions.Type.ADD).index(index).aliases(alias);
         addAction.routing("routing").searchRouting("search_routing").filter("{\"term\":{\"year\":2016}}");
         aliasesAddRequest.addAliasAction(addAction);
-        IndicesAliasesResponse aliasesAddResponse = execute(aliasesAddRequest, highLevelClient().indices()::updateAliases,
+        AcknowledgedResponse aliasesAddResponse = execute(aliasesAddRequest, highLevelClient().indices()::updateAliases,
                 highLevelClient().indices()::updateAliasesAsync);
         assertTrue(aliasesAddResponse.isAcknowledged());
         assertThat(aliasExists(alias), equalTo(true));
@@ -547,7 +542,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         aliasesAddRemoveRequest.addAliasAction(addAction);
         AliasActions removeAction = new AliasActions(AliasActions.Type.REMOVE).index(index).alias(alias);
         aliasesAddRemoveRequest.addAliasAction(removeAction);
-        IndicesAliasesResponse aliasesAddRemoveResponse = execute(aliasesAddRemoveRequest, highLevelClient().indices()::updateAliases,
+        AcknowledgedResponse aliasesAddRemoveResponse = execute(aliasesAddRemoveRequest, highLevelClient().indices()::updateAliases,
                 highLevelClient().indices()::updateAliasesAsync);
         assertTrue(aliasesAddRemoveResponse.isAcknowledged());
         assertThat(aliasExists(alias), equalTo(false));
@@ -558,7 +553,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         IndicesAliasesRequest aliasesRemoveIndexRequest = new IndicesAliasesRequest();
         AliasActions removeIndexAction = new AliasActions(AliasActions.Type.REMOVE_INDEX).index(index);
         aliasesRemoveIndexRequest.addAliasAction(removeIndexAction);
-        IndicesAliasesResponse aliasesRemoveIndexResponse = execute(aliasesRemoveIndexRequest, highLevelClient().indices()::updateAliases,
+        AcknowledgedResponse aliasesRemoveIndexResponse = execute(aliasesRemoveIndexRequest, highLevelClient().indices()::updateAliases,
                 highLevelClient().indices()::updateAliasesAsync);
         assertTrue(aliasesRemoveIndexResponse.isAcknowledged());
         assertThat(aliasExists(alias), equalTo(false));
@@ -654,7 +649,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus()));
 
         CloseIndexRequest closeIndexRequest = new CloseIndexRequest(index);
-        CloseIndexResponse closeIndexResponse = execute(closeIndexRequest, highLevelClient().indices()::close,
+        AcknowledgedResponse closeIndexResponse = execute(closeIndexRequest, highLevelClient().indices()::close,
                 highLevelClient().indices()::closeAsync);
         assertTrue(closeIndexResponse.isAcknowledged());
 
@@ -1144,7 +1139,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         assertThat(dynamicSetting.getDefault(Settings.EMPTY), not(dynamicSettingValue));
         UpdateSettingsRequest dynamicSettingRequest = new UpdateSettingsRequest();
         dynamicSettingRequest.settings(Settings.builder().put(dynamicSettingKey, dynamicSettingValue).build());
-        UpdateSettingsResponse response = execute(dynamicSettingRequest, highLevelClient().indices()::putSettings,
+        AcknowledgedResponse response = execute(dynamicSettingRequest, highLevelClient().indices()::putSettings,
                 highLevelClient().indices()::putSettingsAsync);
 
         assertTrue(response.isAcknowledged());
@@ -1227,7 +1222,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
             .mapping("doc", "host_name", "type=keyword", "description", "type=text")
             .alias(new Alias("alias-1").indexRouting("abc")).alias(new Alias("{index}-write").searchRouting("xyz"));
 
-        PutIndexTemplateResponse putTemplateResponse = execute(putTemplateRequest,
+        AcknowledgedResponse putTemplateResponse = execute(putTemplateRequest,
             highLevelClient().indices()::putTemplate, highLevelClient().indices()::putTemplateAsync);
         assertThat(putTemplateResponse.isAcknowledged(), equalTo(true));
 
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SearchIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SearchIT.java
index 3151e9badb6..9c9c5425f00 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/SearchIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/SearchIT.java
@@ -59,9 +59,6 @@ import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.aggregations.BucketOrder;
 import org.elasticsearch.search.aggregations.bucket.range.Range;
 import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
-import org.elasticsearch.search.aggregations.bucket.significant.SignificantTerms;
-import org.elasticsearch.search.aggregations.bucket.significant.SignificantTermsAggregationBuilder;
-import org.elasticsearch.search.aggregations.bucket.significant.heuristics.PercentageScore;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
 import org.elasticsearch.search.aggregations.matrix.stats.MatrixStats;
@@ -270,33 +267,6 @@ public class SearchIT extends ESRestHighLevelClientTestCase {
         assertEquals(2, type2.getDocCount());
         assertEquals(0, type2.getAggregations().asList().size());
     }
-    
-    public void testSearchWithSignificantTermsAgg() throws IOException {
-        SearchRequest searchRequest = new SearchRequest();
-        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
-        searchSourceBuilder.query(new MatchQueryBuilder("num","50"));
-        searchSourceBuilder.aggregation(new SignificantTermsAggregationBuilder("agg1", ValueType.STRING)
-                .field("type.keyword")
-                .minDocCount(1)
-                .significanceHeuristic(new PercentageScore()));
-        searchSourceBuilder.size(0);
-        searchRequest.source(searchSourceBuilder);
-        SearchResponse searchResponse = execute(searchRequest, highLevelClient()::search, highLevelClient()::searchAsync);
-        assertSearchHeader(searchResponse);
-        assertNull(searchResponse.getSuggest());
-        assertEquals(Collections.emptyMap(), searchResponse.getProfileResults());
-        assertEquals(0, searchResponse.getHits().getHits().length);
-        assertEquals(0f, searchResponse.getHits().getMaxScore(), 0f);
-        SignificantTerms significantTermsAgg = searchResponse.getAggregations().get("agg1");
-        assertEquals("agg1", significantTermsAgg.getName());
-        assertEquals(1, significantTermsAgg.getBuckets().size());
-        SignificantTerms.Bucket type1 = significantTermsAgg.getBucketByKey("type1");
-        assertEquals(1, type1.getDocCount());
-        assertEquals(1, type1.getSubsetDf());
-        assertEquals(1, type1.getSubsetSize());
-        assertEquals(3, type1.getSupersetDf());
-        assertEquals(1d/3d, type1.getSignificanceScore(), 0d);
-    }    
 
     public void testSearchWithRangeAgg() throws IOException {
         {
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
index 06aec70a018..4616234f145 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotIT.java
@@ -21,24 +21,22 @@ package org.elasticsearch.client;
 
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
-import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
-import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
-import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.repositories.fs.FsRepository;
 import org.elasticsearch.rest.RestStatus;
@@ -55,7 +53,7 @@ import static org.hamcrest.Matchers.is;
 
 public class SnapshotIT extends ESRestHighLevelClientTestCase {
 
-    private PutRepositoryResponse createTestRepository(String repository, String type, String settings) throws IOException {
+    private AcknowledgedResponse createTestRepository(String repository, String type, String settings) throws IOException {
         PutRepositoryRequest request = new PutRepositoryRequest(repository);
         request.settings(settings, XContentType.JSON);
         request.type(type);
@@ -71,7 +69,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
     }
 
     public void testCreateRepository() throws IOException {
-        PutRepositoryResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
+        AcknowledgedResponse response = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
         assertTrue(response.isAcknowledged());
     }
 
@@ -117,14 +115,14 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
         assertThat(1, equalTo(response.repositories().size()));
 
         DeleteRepositoryRequest deleteRequest = new DeleteRepositoryRequest(repository);
-        DeleteRepositoryResponse deleteResponse = execute(deleteRequest, highLevelClient().snapshot()::deleteRepository,
+        AcknowledgedResponse deleteResponse = execute(deleteRequest, highLevelClient().snapshot()::deleteRepository,
             highLevelClient().snapshot()::deleteRepositoryAsync);
 
         assertTrue(deleteResponse.isAcknowledged());
     }
 
     public void testVerifyRepository() throws IOException {
-        PutRepositoryResponse putRepositoryResponse = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
+        AcknowledgedResponse putRepositoryResponse = createTestRepository("test", FsRepository.TYPE, "{\"location\": \".\"}");
         assertTrue(putRepositoryResponse.isAcknowledged());
 
         VerifyRepositoryRequest request = new VerifyRepositoryRequest("test");
@@ -153,7 +151,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
         String snapshot1 = "test_snapshot1";
         String snapshot2 = "test_snapshot2";
 
-        PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
+        AcknowledgedResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
         assertTrue(putRepositoryResponse.isAcknowledged());
 
         CreateSnapshotRequest createSnapshotRequest1 = new CreateSnapshotRequest(repository, snapshot1);
@@ -187,7 +185,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
         String testSnapshot = "snapshot";
         String testIndex = "test_index";
 
-        PutRepositoryResponse putRepositoryResponse = createTestRepository(testRepository, FsRepository.TYPE, "{\"location\": \".\"}");
+        AcknowledgedResponse putRepositoryResponse = createTestRepository(testRepository, FsRepository.TYPE, "{\"location\": \".\"}");
         assertTrue(putRepositoryResponse.isAcknowledged());
 
         createIndex(testIndex, Settings.EMPTY);
@@ -216,7 +214,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
         String testIndex = "test_index";
         String restoredIndex = testIndex + "_restored";
 
-        PutRepositoryResponse putRepositoryResponse = createTestRepository(testRepository, FsRepository.TYPE, "{\"location\": \".\"}");
+        AcknowledgedResponse putRepositoryResponse = createTestRepository(testRepository, FsRepository.TYPE, "{\"location\": \".\"}");
         assertTrue(putRepositoryResponse.isAcknowledged());
 
         createIndex(testIndex, Settings.EMPTY);
@@ -250,7 +248,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
         String repository = "test_repository";
         String snapshot = "test_snapshot";
 
-        PutRepositoryResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
+        AcknowledgedResponse putRepositoryResponse = createTestRepository(repository, FsRepository.TYPE, "{\"location\": \".\"}");
         assertTrue(putRepositoryResponse.isAcknowledged());
 
         CreateSnapshotRequest createSnapshotRequest = new CreateSnapshotRequest(repository, snapshot);
@@ -260,7 +258,7 @@ public class SnapshotIT extends ESRestHighLevelClientTestCase {
         assertEquals(RestStatus.OK, createSnapshotResponse.status());
 
         DeleteSnapshotRequest request = new DeleteSnapshotRequest(repository, snapshot);
-        DeleteSnapshotResponse response = execute(request, highLevelClient().snapshot()::delete, highLevelClient().snapshot()::deleteAsync);
+        AcknowledgedResponse response = execute(request, highLevelClient().snapshot()::delete, highLevelClient().snapshot()::deleteAsync);
 
         assertTrue(response.isAcknowledged());
     }
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java
index e6d380a4cc0..14734c4ab60 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java
@@ -23,9 +23,9 @@ import org.apache.http.entity.StringEntity;
 import org.apache.http.util.EntityUtils;
 import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContent;
 import org.elasticsearch.common.xcontent.XContentType;
@@ -90,7 +90,7 @@ public class StoredScriptsIT extends ESRestHighLevelClientTestCase {
         deleteRequest.masterNodeTimeout("50s");
         deleteRequest.timeout("50s");
 
-        DeleteStoredScriptResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteScript,
+        AcknowledgedResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteScript,
             highLevelClient()::deleteScriptAsync);
 
         assertThat(deleteResponse.isAcknowledged(), equalTo(true));
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
index 36d562c501f..2da4d306c28 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
@@ -25,7 +25,6 @@ import org.elasticsearch.action.LatchedActionListener;
 import org.elasticsearch.action.admin.indices.alias.Alias;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
@@ -33,11 +32,9 @@ import org.elasticsearch.action.admin.indices.analyze.DetailAnalyzeResponse;
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.flush.FlushRequest;
 import org.elasticsearch.action.admin.indices.flush.FlushResponse;
 import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest;
@@ -50,7 +47,6 @@ import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRespon
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
 import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
@@ -60,20 +56,19 @@ import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
 import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
 import org.elasticsearch.action.admin.indices.shrink.ResizeType;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.validate.query.QueryExplanation;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
 import org.elasticsearch.action.support.ActiveShardCount;
 import org.elasticsearch.action.support.DefaultShardOperationFailedException;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ESRestHighLevelClientTestCase;
 import org.elasticsearch.client.GetAliasesResponse;
 import org.elasticsearch.client.RequestOptions;
@@ -220,7 +215,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             // end::delete-index-request-indicesOptions
 
             // tag::delete-index-execute
-            DeleteIndexResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT);
             // end::delete-index-execute
 
             // tag::delete-index-response
@@ -255,10 +250,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             DeleteIndexRequest request = new DeleteIndexRequest("posts");
 
             // tag::delete-index-execute-listener
-            ActionListener<DeleteIndexResponse> listener =
-                    new ActionListener<DeleteIndexResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                    new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(DeleteIndexResponse deleteIndexResponse) {
+                public void onResponse(AcknowledgedResponse deleteIndexResponse) {
                     // <1>
                 }
 
@@ -480,7 +475,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
                     "}", // <1>
                     XContentType.JSON);
                 // end::put-mapping-request-source
-                PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+                AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
                 assertTrue(putMappingResponse.isAcknowledged());
             }
 
@@ -494,7 +489,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
                 jsonMap.put("properties", properties);
                 request.source(jsonMap); // <1>
                 //end::put-mapping-map
-                PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+                AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
                 assertTrue(putMappingResponse.isAcknowledged());
             }
             {
@@ -515,14 +510,14 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
                 builder.endObject();
                 request.source(builder); // <1>
                 //end::put-mapping-xcontent
-                PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+                AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
                 assertTrue(putMappingResponse.isAcknowledged());
             }
             {
                 //tag::put-mapping-shortcut
                 request.source("message", "type=text"); // <1>
                 //end::put-mapping-shortcut
-                PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+                AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
                 assertTrue(putMappingResponse.isAcknowledged());
             }
 
@@ -536,7 +531,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             // end::put-mapping-request-masterTimeout
 
             // tag::put-mapping-execute
-            PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
             // end::put-mapping-execute
 
             // tag::put-mapping-response
@@ -558,10 +553,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             PutMappingRequest request = new PutMappingRequest("twitter").type("tweet");
 
             // tag::put-mapping-execute-listener
-            ActionListener<PutMappingResponse> listener =
-                new ActionListener<PutMappingResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                new ActionListener<AcknowledgedResponse>() {
                     @Override
-                    public void onResponse(PutMappingResponse putMappingResponse) {
+                    public void onResponse(AcknowledgedResponse putMappingResponse) {
                         // <1>
                     }
 
@@ -601,7 +596,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
                     "  }\n" +
                     "}", // <1>
                 XContentType.JSON);
-            PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
             assertTrue(putMappingResponse.isAcknowledged());
         }
 
@@ -658,7 +653,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
                     "  }\n" +
                     "}", // <1>
                 XContentType.JSON);
-            PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
             assertTrue(putMappingResponse.isAcknowledged());
         }
 
@@ -731,7 +726,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
                     "  }\n" +
                     "}", // <1>
                 XContentType.JSON);
-            PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
             assertTrue(putMappingResponse.isAcknowledged());
         }
 
@@ -1497,7 +1492,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             // end::close-index-request-indicesOptions
 
             // tag::close-index-execute
-            CloseIndexResponse closeIndexResponse = client.indices().close(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse closeIndexResponse = client.indices().close(request, RequestOptions.DEFAULT);
             // end::close-index-execute
 
             // tag::close-index-response
@@ -1506,10 +1501,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             assertTrue(acknowledged);
 
             // tag::close-index-execute-listener
-            ActionListener<CloseIndexResponse> listener =
-                    new ActionListener<CloseIndexResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                    new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(CloseIndexResponse closeIndexResponse) {
+                public void onResponse(AcknowledgedResponse closeIndexResponse) {
                     // <1>
                 }
 
@@ -1649,7 +1644,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             // end::update-aliases-request-masterTimeout
 
             // tag::update-aliases-execute
-            IndicesAliasesResponse indicesAliasesResponse =
+            AcknowledgedResponse indicesAliasesResponse =
                     client.indices().updateAliases(request, RequestOptions.DEFAULT);
             // end::update-aliases-execute
 
@@ -1665,10 +1660,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             request.addAliasAction(aliasAction);
 
             // tag::update-aliases-execute-listener
-            ActionListener<IndicesAliasesResponse> listener =
-                    new ActionListener<IndicesAliasesResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                    new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(IndicesAliasesResponse indicesAliasesResponse) {
+                public void onResponse(AcknowledgedResponse indicesAliasesResponse) {
                     // <1>
                 }
 
@@ -2056,7 +2051,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
         // end::put-settings-request-indicesOptions
 
         // tag::put-settings-execute
-        UpdateSettingsResponse updateSettingsResponse =
+        AcknowledgedResponse updateSettingsResponse =
                 client.indices().putSettings(request, RequestOptions.DEFAULT);
         // end::put-settings-execute
 
@@ -2066,11 +2061,11 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
         assertTrue(acknowledged);
 
         // tag::put-settings-execute-listener
-        ActionListener<UpdateSettingsResponse> listener =
-                new ActionListener<UpdateSettingsResponse>() {
+        ActionListener<AcknowledgedResponse> listener =
+                new ActionListener<AcknowledgedResponse>() {
 
             @Override
-            public void onResponse(UpdateSettingsResponse updateSettingsResponse) {
+            public void onResponse(AcknowledgedResponse updateSettingsResponse) {
                 // <1>
             }
 
@@ -2219,7 +2214,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
         request.create(false); // make test happy
 
         // tag::put-template-execute
-        PutIndexTemplateResponse putTemplateResponse = client.indices().putTemplate(request, RequestOptions.DEFAULT);
+        AcknowledgedResponse putTemplateResponse = client.indices().putTemplate(request, RequestOptions.DEFAULT);
         // end::put-template-execute
 
         // tag::put-template-response
@@ -2228,10 +2223,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
         assertTrue(acknowledged);
 
         // tag::put-template-execute-listener
-        ActionListener<PutIndexTemplateResponse> listener =
-            new ActionListener<PutIndexTemplateResponse>() {
+        ActionListener<AcknowledgedResponse> listener =
+            new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(PutIndexTemplateResponse putTemplateResponse) {
+                public void onResponse(AcknowledgedResponse putTemplateResponse) {
                     // <1>
                 }
 
@@ -2461,7 +2456,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
             .indices("my_index")
             .type("_doc")
             .source("my_field", "type=text,analyzer=english");
-        PutMappingResponse pmResp = client.indices().putMapping(pmReq, RequestOptions.DEFAULT);
+        AcknowledgedResponse pmResp = client.indices().putMapping(pmReq, RequestOptions.DEFAULT);
         assertTrue(pmResp.isAcknowledged());
 
         {
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/LicensingDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/LicensingDocumentationIT.java
index 6146030999c..3737bd70a8d 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/LicensingDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/LicensingDocumentationIT.java
@@ -22,12 +22,12 @@ package org.elasticsearch.client.documentation;
 import org.elasticsearch.Build;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.LatchedActionListener;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ESRestHighLevelClientTestCase;
 import org.elasticsearch.client.RequestOptions;
 import org.elasticsearch.client.RestHighLevelClient;
 import org.elasticsearch.common.Booleans;
 import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
 import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
 import org.elasticsearch.protocol.xpack.license.GetLicenseResponse;
 import org.elasticsearch.protocol.xpack.license.LicensesStatus;
@@ -120,7 +120,7 @@ public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {
             //tag::delete-license-execute
             DeleteLicenseRequest request = new DeleteLicenseRequest();
 
-            DeleteLicenseResponse response = client.license().deleteLicense(request, RequestOptions.DEFAULT);
+            AcknowledgedResponse response = client.license().deleteLicense(request, RequestOptions.DEFAULT);
             //end::delete-license-execute
 
             //tag::delete-license-response
@@ -132,9 +132,9 @@ public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {
         {
             DeleteLicenseRequest request = new DeleteLicenseRequest();
             // tag::delete-license-execute-listener
-            ActionListener<DeleteLicenseResponse> listener = new ActionListener<DeleteLicenseResponse>() {
+            ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(DeleteLicenseResponse deleteLicenseResponse) {
+                public void onResponse(AcknowledgedResponse deleteLicenseResponse) {
                     // <1>
                 }
 
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
new file mode 100644
index 00000000000..97bee813938
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.documentation;
+
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.LatchedActionListener;
+import org.elasticsearch.client.ESRestHighLevelClientTestCase;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.protocol.xpack.ml.PutJobRequest;
+import org.elasticsearch.protocol.xpack.ml.PutJobResponse;
+import org.elasticsearch.protocol.xpack.ml.job.config.AnalysisConfig;
+import org.elasticsearch.protocol.xpack.ml.job.config.DataDescription;
+import org.elasticsearch.protocol.xpack.ml.job.config.Detector;
+import org.elasticsearch.protocol.xpack.ml.job.config.Job;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.greaterThan;
+
+public class MlClientDocumentationIT extends ESRestHighLevelClientTestCase {
+
+    public void testCreateJob() throws Exception {
+        RestHighLevelClient client = highLevelClient();
+
+        //tag::x-pack-ml-put-job-detector
+        Detector.Builder detectorBuilder = new Detector.Builder()
+            .setFunction("sum")                                    // <1>
+            .setFieldName("total")                                 // <2>
+            .setDetectorDescription("Sum of total");               // <3>
+        //end::x-pack-ml-put-job-detector
+
+        //tag::x-pack-ml-put-job-analysis-config
+        List<Detector> detectors = Collections.singletonList(detectorBuilder.build());       // <1>
+        AnalysisConfig.Builder analysisConfigBuilder = new AnalysisConfig.Builder(detectors) // <2>
+            .setBucketSpan(TimeValue.timeValueMinutes(10));                                  // <3>
+        //end::x-pack-ml-put-job-analysis-config
+
+        //tag::x-pack-ml-put-job-data-description
+        DataDescription.Builder dataDescriptionBuilder = new DataDescription.Builder()
+            .setTimeField("timestamp");  // <1>
+        //end::x-pack-ml-put-job-data-description
+
+        {
+            String id = "job_1";
+
+            //tag::x-pack-ml-put-job-config
+            Job.Builder jobBuilder = new Job.Builder(id)      // <1>
+                .setAnalysisConfig(analysisConfigBuilder)     // <2>
+                .setDataDescription(dataDescriptionBuilder)   // <3>
+                .setDescription("Total sum of requests");     // <4>
+            //end::x-pack-ml-put-job-config
+
+            //tag::x-pack-ml-put-job-request
+            PutJobRequest request = new PutJobRequest(jobBuilder.build()); // <1>
+            //end::x-pack-ml-put-job-request
+
+            //tag::x-pack-ml-put-job-execute
+            PutJobResponse response = client.machineLearning().putJob(request, RequestOptions.DEFAULT);
+            //end::x-pack-ml-put-job-execute
+
+            //tag::x-pack-ml-put-job-response
+            Date createTime = response.getResponse().getCreateTime(); // <1>
+            //end::x-pack-ml-put-job-response
+            assertThat(createTime.getTime(), greaterThan(0L));
+        }
+        {
+            String id = "job_2";
+            Job.Builder jobBuilder = new Job.Builder(id)
+                .setAnalysisConfig(analysisConfigBuilder)
+                .setDataDescription(dataDescriptionBuilder)
+                .setDescription("Total sum of requests");
+
+            PutJobRequest request = new PutJobRequest(jobBuilder.build());
+            // tag::x-pack-ml-put-job-execute-listener
+            ActionListener<PutJobResponse> listener = new ActionListener<PutJobResponse>() {
+                @Override
+                public void onResponse(PutJobResponse response) {
+                    // <1>
+                }
+
+                @Override
+                public void onFailure(Exception e) {
+                    // <2>
+                }
+            };
+            // end::x-pack-ml-put-job-execute-listener
+
+            // Replace the empty listener by a blocking listener in test
+            final CountDownLatch latch = new CountDownLatch(1);
+            listener = new LatchedActionListener<>(listener, latch);
+
+            // tag::x-pack-ml-put-job-execute-async
+            client.machineLearning().putJobAsync(request, RequestOptions.DEFAULT, listener); // <1>
+            // end::x-pack-ml-put-job-execute-async
+
+            assertTrue(latch.await(30L, TimeUnit.SECONDS));
+        }
+    }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
index 922fcb984d9..d1aed55f44e 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java
@@ -22,27 +22,25 @@ package org.elasticsearch.client.documentation;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.LatchedActionListener;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
-import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
-import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
-import org.elasticsearch.action.support.IndicesOptions;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStats;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
+import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ESRestHighLevelClientTestCase;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.RequestOptions;
@@ -163,7 +161,7 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
         // end::create-repository-request-verify
 
         // tag::create-repository-execute
-        PutRepositoryResponse response = client.snapshot().createRepository(request, RequestOptions.DEFAULT);
+        AcknowledgedResponse response = client.snapshot().createRepository(request, RequestOptions.DEFAULT);
         // end::create-repository-execute
 
         // tag::create-repository-response
@@ -178,10 +176,10 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
             PutRepositoryRequest request = new PutRepositoryRequest(repositoryName);
 
             // tag::create-repository-execute-listener
-            ActionListener<PutRepositoryResponse> listener =
-                new ActionListener<PutRepositoryResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                new ActionListener<AcknowledgedResponse>() {
                     @Override
-                    public void onResponse(PutRepositoryResponse putRepositoryResponse) {
+                    public void onResponse(AcknowledgedResponse putRepositoryResponse) {
                         // <1>
                     }
 
@@ -388,7 +386,7 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
         // end::delete-repository-request-timeout
 
         // tag::delete-repository-execute
-        DeleteRepositoryResponse response = client.snapshot().deleteRepository(request, RequestOptions.DEFAULT);
+        AcknowledgedResponse response = client.snapshot().deleteRepository(request, RequestOptions.DEFAULT);
         // end::delete-repository-execute
 
         // tag::delete-repository-response
@@ -403,10 +401,10 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
             DeleteRepositoryRequest request = new DeleteRepositoryRequest();
 
             // tag::delete-repository-execute-listener
-            ActionListener<DeleteRepositoryResponse> listener =
-                new ActionListener<DeleteRepositoryResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                new ActionListener<AcknowledgedResponse>() {
                     @Override
-                    public void onResponse(DeleteRepositoryResponse deleteRepositoryResponse) {
+                    public void onResponse(AcknowledgedResponse deleteRepositoryResponse) {
                         // <1>
                     }
 
@@ -752,7 +750,7 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
         // end::delete-snapshot-request-masterTimeout
 
         // tag::delete-snapshot-execute
-        DeleteSnapshotResponse response = client.snapshot().delete(request, RequestOptions.DEFAULT);
+        AcknowledgedResponse response = client.snapshot().delete(request, RequestOptions.DEFAULT);
         // end::delete-snapshot-execute
 
         // tag::delete-snapshot-response
@@ -767,10 +765,10 @@ public class SnapshotClientDocumentationIT extends ESRestHighLevelClientTestCase
             DeleteSnapshotRequest request = new DeleteSnapshotRequest();
 
             // tag::delete-snapshot-execute-listener
-            ActionListener<DeleteSnapshotResponse> listener =
-                new ActionListener<DeleteSnapshotResponse>() {
+            ActionListener<AcknowledgedResponse> listener =
+                new ActionListener<AcknowledgedResponse>() {
                     @Override
-                    public void onResponse(DeleteSnapshotResponse deleteSnapshotResponse) {
+                    public void onResponse(AcknowledgedResponse deleteSnapshotResponse) {
                         // <1>
                     }
 
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java
index 0aadae73ce6..b1374ca85b6 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java
@@ -23,9 +23,9 @@ import org.apache.http.util.EntityUtils;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.LatchedActionListener;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ESRestHighLevelClientTestCase;
 import org.elasticsearch.client.RequestOptions;
 import org.elasticsearch.client.Response;
@@ -154,7 +154,7 @@ public class StoredScriptsDocumentationIT extends ESRestHighLevelClientTestCase
         // end::delete-stored-script-request-timeout
 
         // tag::delete-stored-script-execute
-        DeleteStoredScriptResponse deleteResponse = client.deleteScript(deleteRequest, RequestOptions.DEFAULT);
+        AcknowledgedResponse deleteResponse = client.deleteScript(deleteRequest, RequestOptions.DEFAULT);
         // end::delete-stored-script-execute
 
         // tag::delete-stored-script-response
@@ -164,10 +164,10 @@ public class StoredScriptsDocumentationIT extends ESRestHighLevelClientTestCase
         putStoredScript("calculate-score", scriptSource);
 
         // tag::delete-stored-script-execute-listener
-        ActionListener<DeleteStoredScriptResponse> listener =
-            new ActionListener<DeleteStoredScriptResponse>() {
+        ActionListener<AcknowledgedResponse> listener =
+            new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(DeleteStoredScriptResponse response) {
+                public void onResponse(AcknowledgedResponse response) {
                     // <1>
                 }
 
diff --git a/distribution/bwc/build.gradle b/distribution/bwc/build.gradle
index b84bf1df2fe..b515c606cc3 100644
--- a/distribution/bwc/build.gradle
+++ b/distribution/bwc/build.gradle
@@ -157,7 +157,7 @@ subprojects {
       environment('JAVA_HOME', getJavaHome(it, 8))
     } else if ("6.2".equals(bwcBranch)) {
       environment('JAVA_HOME', getJavaHome(it, 9))
-    } else if (["6.3", "6.x"].contains(bwcBranch)) {
+    } else if (["6.3", "6.4", "6.x"].contains(bwcBranch)) {
       environment('JAVA_HOME', getJavaHome(it, 10))
     } else {
       environment('JAVA_HOME', project.compilerJavaHome)
diff --git a/docs/java-rest/high-level/ml/put_job.asciidoc b/docs/java-rest/high-level/ml/put_job.asciidoc
new file mode 100644
index 00000000000..d51bb63d405
--- /dev/null
+++ b/docs/java-rest/high-level/ml/put_job.asciidoc
@@ -0,0 +1,161 @@
+[[java-rest-high-x-pack-ml-put-job]]
+=== Put Job API
+
+The Put Job API can be used to create a new {ml} job
+in the cluster. The API accepts a `PutJobRequest` object
+as a request and returns a `PutJobResponse`.
+
+[[java-rest-high-x-pack-ml-put-job-request]]
+==== Put Job Request
+
+A `PutJobRequest` requires the following argument:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-request]
+--------------------------------------------------
+<1> The configuration of the {ml} job to create as a `Job`
+
+[[java-rest-high-x-pack-ml-put-job-config]]
+==== Job Configuration
+
+The `Job` object contains all the details about the {ml} job
+configuration.
+
+A `Job` requires the following arguments:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-config]
+--------------------------------------------------
+<1> The job ID
+<2> An analysis configuration
+<3> A data description
+<4> Optionally, a human-readable description
+
+[[java-rest-high-x-pack-ml-put-job-analysis-config]]
+==== Analysis Configuration
+
+The analysis configuration of the {ml} job is defined in the `AnalysisConfig`.
+`AnalysisConfig` reflects all the configuration
+settings that can be defined using the REST API.
+
+Using the REST API, we could define this analysis configuration:
+
+[source,js]
+--------------------------------------------------
+"analysis_config" : {
+  "bucket_span" : "10m",
+  "detectors" : [
+    {
+      "detector_description" : "Sum of total",
+      "function" : "sum",
+      "field_name" : "total"
+    }
+  ]
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+Using the `AnalysisConfig` object and the high level REST client, the list
+of detectors must be built first.
+
+An example of building a `Detector` instance is as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-detector]
+--------------------------------------------------
+<1> The function to use
+<2> The field to apply the function to
+<3> Optionally, a human-readable description
+
+Then the same configuration would be:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-analysis-config]
+--------------------------------------------------
+<1> Create a list of detectors
+<2> Pass the list of detectors to the analysis config builder constructor
+<3> The bucket span
+
+[[java-rest-high-x-pack-ml-put-job-data-description]]
+==== Data Description
+
+After defining the analysis config, the next thing to define is the
+data description, using a `DataDescription` instance. `DataDescription`
+reflects all the configuration settings that can be defined using the
+REST API.
+
+Using the REST API, we could define this metrics configuration:
+
+[source,js]
+--------------------------------------------------
+"data_description" : {
+  "time_field" : "timestamp"
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+Using the `DataDescription` object and the high level REST client, the same
+configuration would be:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-data-description]
+--------------------------------------------------
+<1> The time field
+
+[[java-rest-high-x-pack-ml-put-job-execution]]
+==== Execution
+
+The Put Job API can be executed through a `MachineLearningClient`
+instance. Such an instance can be retrieved from a `RestHighLevelClient`
+using the `machineLearning()` method:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-execute]
+--------------------------------------------------
+
+[[java-rest-high-x-pack-ml-put-job-response]]
+==== Response
+
+The returned `PutJobResponse` returns the full representation of
+the new {ml} job if it has been successfully created. This will
+contain the creation time and other fields initialized using
+default values:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-response]
+--------------------------------------------------
+<1> The creation time is a field that was not passed in the `Job` object in the request
+
+[[java-rest-high-x-pack-ml-put-job-async]]
+==== Asynchronous Execution
+
+This request can be executed asynchronously:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-execute-async]
+--------------------------------------------------
+<1> The `PutMlJobRequest` to execute and the `ActionListener` to use when
+the execution completes
+
+The asynchronous method does not block and returns immediately. Once it is
+completed the `ActionListener` is called back using the `onResponse` method
+if the execution successfully completed or using the `onFailure` method if
+it failed.
+
+A typical listener for `PutJobResponse` looks like:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-put-job-execute-listener]
+--------------------------------------------------
+<1> Called when the execution is successfully completed. The response is
+provided as an argument
+<2> Called in case of failure. The raised exception is provided as an argument
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 9d7d66434f7..808546f2c27 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -200,6 +200,14 @@ include::licensing/put-license.asciidoc[]
 include::licensing/get-license.asciidoc[]
 include::licensing/delete-license.asciidoc[]
 
+== Machine Learning APIs
+
+The Java High Level REST Client supports the following Machine Learning APIs:
+
+* <<java-rest-high-x-pack-ml-put-job>>
+
+include::ml/put_job.asciidoc[]
+
 == Migration APIs
 
 The Java High Level REST Client supports the following Migration APIs:
diff --git a/libs/dissect/build.gradle b/libs/dissect/build.gradle
new file mode 100644
index 00000000000..c09a2a4ebd1
--- /dev/null
+++ b/libs/dissect/build.gradle
@@ -0,0 +1,50 @@
+import org.elasticsearch.gradle.precommit.PrecommitTasks
+
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+archivesBaseName = 'elasticsearch-dissect'
+
+dependencies {
+     if (isEclipse == false || project.path == ":libs:dissect-tests") {
+        testCompile("org.elasticsearch.test:framework:${version}") {
+            exclude group: 'org.elasticsearch', module: 'dissect'
+        }
+    }
+    testCompile "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
+    testCompile("com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}")
+    testCompile("com.fasterxml.jackson.core:jackson-databind:${versions.jackson}")
+}
+
+forbiddenApisMain {
+    signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt')]
+}
+
+if (isEclipse) {
+    // in eclipse the project is under a fake root, we need to change around the source sets
+    sourceSets {
+        if (project.path == ":libs:dissect") {
+            main.java.srcDirs = ['java']
+            main.resources.srcDirs = ['resources']
+        } else {
+            test.java.srcDirs = ['java']
+            test.resources.srcDirs = ['resources']
+        }
+    }
+}
diff --git a/libs/dissect/src/main/eclipse-build.gradle b/libs/dissect/src/main/eclipse-build.gradle
new file mode 100644
index 00000000000..c2b72bd21e1
--- /dev/null
+++ b/libs/dissect/src/main/eclipse-build.gradle
@@ -0,0 +1,3 @@
+
+// this is just shell gradle file for eclipse to have separate projects for dissect src and tests
+apply from: '../../build.gradle'
diff --git a/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectException.java b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectException.java
new file mode 100644
index 00000000000..a2f1ab33640
--- /dev/null
+++ b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectException.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+/**
+ * Parent class for all dissect related exceptions. Consumers may catch this exception or more specific child exceptions.
+ */
+public abstract class DissectException extends RuntimeException {
+    DissectException(String message) {
+        super(message);
+    }
+
+    /**
+     * Error while parsing a dissect pattern
+     */
+    static class PatternParse extends DissectException {
+        PatternParse(String pattern, String reason) {
+            super("Unable to parse pattern: " + pattern + " Reason: " + reason);
+        }
+    }
+
+    /**
+     * Error while parsing a dissect key
+     */
+    static class KeyParse extends DissectException {
+        KeyParse(String key, String reason) {
+            super("Unable to parse key: " + key + " Reason: " + reason);
+        }
+    }
+
+    /**
+     * Unable to find a match between pattern and source string
+     */
+    static class FindMatch extends DissectException {
+        FindMatch(String pattern, String source) {
+            super("Unable to find match for dissect pattern: " + pattern + " against source: " + source);
+
+        }
+    }
+}
diff --git a/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectKey.java b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectKey.java
new file mode 100644
index 00000000000..67a6842182d
--- /dev/null
+++ b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectKey.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+import java.util.EnumSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * <p>A Key of a dissect pattern. This class models the name and modifiers and provides some validation.</p>
+ * <p>For dissect pattern of {@code %{a} %{+a} %{b}} the dissect keys are:
+ * <ul>
+ * <li>{@code a}</li>
+ * <li>{@code +a}</li>
+ * <li>{@code b}</li>
+ * </ul>
+ * This class represents a single key.
+ * <p>A single key is composed of a name and it's modifiers. For the key {@code +a}, {@code a} is the name and {@code +} is the modifier.
+ * @see DissectParser
+ */
+public final class DissectKey {
+    private static final Pattern LEFT_MODIFIER_PATTERN = Pattern.compile("([+*&?])(.*?)(->)?$", Pattern.DOTALL);
+    private static final Pattern RIGHT_PADDING_PATTERN = Pattern.compile("^(.*?)(->)?$", Pattern.DOTALL);
+    private static final Pattern APPEND_WITH_ORDER_PATTERN = Pattern.compile("[+](.*?)(/)([0-9]+)(->)?$", Pattern.DOTALL);
+    private final Modifier modifier;
+    private boolean skip;
+    private boolean skipRightPadding;
+    private int appendPosition;
+    private String name;
+
+    /**
+     * Constructor - parses the String key into it's name and modifier(s)
+     *
+     * @param key The key without the leading <code>%{</code> or trailing <code>}</code>, for example {@code a->}
+     */
+    DissectKey(String key) {
+        skip = key == null || key.isEmpty();
+        modifier = Modifier.findModifier(key);
+        switch (modifier) {
+            case NONE:
+                Matcher matcher = RIGHT_PADDING_PATTERN.matcher(key);
+                while (matcher.find()) {
+                    name = matcher.group(1);
+                    skipRightPadding = matcher.group(2) != null;
+                }
+                skip = name.isEmpty();
+                break;
+            case NAMED_SKIP:
+                matcher = LEFT_MODIFIER_PATTERN.matcher(key);
+                while (matcher.find()) {
+                    name = matcher.group(2);
+                    skipRightPadding = matcher.group(3) != null;
+                }
+                skip = true;
+                break;
+            case APPEND:
+                matcher = LEFT_MODIFIER_PATTERN.matcher(key);
+                while (matcher.find()) {
+                    name = matcher.group(2);
+                    skipRightPadding = matcher.group(3) != null;
+                }
+                break;
+            case FIELD_NAME:
+                matcher = LEFT_MODIFIER_PATTERN.matcher(key);
+                while (matcher.find()) {
+                    name = matcher.group(2);
+                    skipRightPadding = matcher.group(3) != null;
+                }
+                break;
+            case FIELD_VALUE:
+                matcher = LEFT_MODIFIER_PATTERN.matcher(key);
+                while (matcher.find()) {
+                    name = matcher.group(2);
+                    skipRightPadding = matcher.group(3) != null;
+                }
+                break;
+            case APPEND_WITH_ORDER:
+                matcher = APPEND_WITH_ORDER_PATTERN.matcher(key);
+                while (matcher.find()) {
+                    name = matcher.group(1);
+                    appendPosition = Short.valueOf(matcher.group(3));
+                    skipRightPadding = matcher.group(4) != null;
+                }
+                break;
+        }
+
+        if (name == null || (name.isEmpty() && !skip)) {
+            throw new DissectException.KeyParse(key, "The key name could be determined");
+        }
+    }
+
+    /**
+     * Copy constructor to explicitly override the modifier.
+     * @param key The key to copy (except for the modifier)
+     * @param modifier the modifer to use for this copy
+     */
+    DissectKey(DissectKey key, DissectKey.Modifier modifier){
+        this.modifier = modifier;
+        this.skipRightPadding = key.skipRightPadding;
+        this.skip = key.skip;
+        this.name = key.name;
+        this.appendPosition = key.appendPosition;
+    }
+
+    Modifier getModifier() {
+        return modifier;
+    }
+
+    boolean skip() {
+        return skip;
+    }
+
+    boolean skipRightPadding() {
+        return skipRightPadding;
+    }
+
+    int getAppendPosition() {
+        return appendPosition;
+    }
+
+    String getName() {
+        return name;
+    }
+
+    //generated
+    @Override
+    public String toString() {
+        return "DissectKey{" +
+            "modifier=" + modifier +
+            ", skip=" + skip +
+            ", appendPosition=" + appendPosition +
+            ", name='" + name + '\'' +
+            '}';
+    }
+
+    public enum Modifier {
+        NONE(""), APPEND_WITH_ORDER("/"), APPEND("+"), FIELD_NAME("*"), FIELD_VALUE("&"), NAMED_SKIP("?");
+
+        private static final Pattern MODIFIER_PATTERN = Pattern.compile("[/+*&?]");
+
+        private final String modifier;
+
+        @Override
+        public String toString() {
+            return modifier;
+        }
+
+        Modifier(final String modifier) {
+            this.modifier = modifier;
+        }
+
+        //package private for testing
+        static Modifier fromString(String modifier) {
+            return EnumSet.allOf(Modifier.class).stream().filter(km -> km.modifier.equals(modifier))
+                .findFirst().orElseThrow(() -> new IllegalArgumentException("Found invalid modifier.")); //throw should never happen
+        }
+
+        private static Modifier findModifier(String key) {
+            Modifier modifier = Modifier.NONE;
+            if (key != null && !key.isEmpty()) {
+                Matcher matcher = MODIFIER_PATTERN.matcher(key);
+                int matches = 0;
+                while (matcher.find()) {
+                    Modifier priorModifier = modifier;
+                    modifier = Modifier.fromString(matcher.group());
+                    if (++matches > 1 && !(APPEND.equals(priorModifier) && APPEND_WITH_ORDER.equals(modifier))) {
+                        throw new DissectException.KeyParse(key, "multiple modifiers are not allowed.");
+                    }
+                }
+            }
+            return modifier;
+        }
+    }
+}
diff --git a/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectMatch.java b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectMatch.java
new file mode 100644
index 00000000000..9217413e075
--- /dev/null
+++ b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectMatch.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Represents the matches of a {@link DissectParser#parse(String)}. Handles the appending and referencing based on the key instruction.
+ */
+final class DissectMatch {
+
+    private final String appendSeparator;
+    private final Map<String, String> results;
+    private final Map<String, String> simpleResults;
+    private final Map<String, ReferenceResult> referenceResults;
+    private final Map<String, AppendResult> appendResults;
+    private int implicitAppendOrder = -1000;
+    private final int maxMatches;
+    private final int maxResults;
+    private final int appendCount;
+    private final int referenceCount;
+    private final int simpleCount;
+    private int matches = 0;
+
+    DissectMatch(String appendSeparator, int maxMatches, int maxResults, int appendCount, int referenceCount) {
+        if (maxMatches <= 0 || maxResults <= 0) {
+            throw new IllegalArgumentException("Expected results are zero, can not construct DissectMatch");//should never happen
+        }
+        this.maxMatches = maxMatches;
+        this.maxResults = maxResults;
+        this.appendCount = appendCount;
+        this.referenceCount = referenceCount;
+        this.appendSeparator = appendSeparator;
+        results = new HashMap<>(maxResults);
+        this.simpleCount = maxMatches - referenceCount - appendCount;
+        simpleResults = simpleCount <= 0 ? null : new HashMap<>(simpleCount);
+        referenceResults = referenceCount <= 0 ? null : new HashMap<>(referenceCount);
+        appendResults = appendCount <= 0 ? null : new HashMap<>(appendCount);
+    }
+
+    /**
+     * Add the key/value that was found as result of the parsing
+     * @param key the {@link DissectKey}
+     * @param value the discovered value for the key
+     */
+    void add(DissectKey key, String value) {
+        matches++;
+        if (key.skip()) {
+            return;
+        }
+        switch (key.getModifier()) {
+            case NONE:
+                simpleResults.put(key.getName(), value);
+                break;
+            case APPEND:
+                appendResults.computeIfAbsent(key.getName(), k -> new AppendResult(appendSeparator)).addValue(value, implicitAppendOrder++);
+                break;
+            case APPEND_WITH_ORDER:
+                appendResults.computeIfAbsent(key.getName(),
+                    k -> new AppendResult(appendSeparator)).addValue(value, key.getAppendPosition());
+                break;
+            case FIELD_NAME:
+                referenceResults.computeIfAbsent(key.getName(), k -> new ReferenceResult()).setKey(value);
+                break;
+            case FIELD_VALUE:
+                referenceResults.computeIfAbsent(key.getName(), k -> new ReferenceResult()).setValue(value);
+                break;
+        }
+    }
+
+    boolean fullyMatched() {
+        return matches == maxMatches;
+    }
+
+    /**
+     * Checks if results are valid.
+     * @param results the results to check
+     * @return true if all dissect keys have been matched and the results are of the expected size.
+     */
+    boolean isValid(Map<String, String> results) {
+        return fullyMatched() && results.size() == maxResults;
+    }
+
+    /**
+     * Gets all the current matches. Pass the results of this to isValid to determine if a fully successful match has occured.
+     *
+     * @return the map of the results.
+     */
+    Map<String, String> getResults() {
+        results.clear();
+        if (simpleCount > 0) {
+            results.putAll(simpleResults);
+        }
+        if (referenceCount > 0) {
+            referenceResults.forEach((k, v) -> results.put(v.getKey(), v.getValue()));
+        }
+        if (appendCount > 0) {
+            appendResults.forEach((k, v) -> results.put(k, v.getAppendResult()));
+        }
+
+        return results;
+    }
+
+    /**
+     * a result that will need to be part of an append operation.
+     */
+    private final class AppendResult {
+        private final List<AppendValue> values = new ArrayList<>();
+        private final String appendSeparator;
+
+        private AppendResult(String appendSeparator) {
+            this.appendSeparator = appendSeparator;
+        }
+
+        private void addValue(String value, int order) {
+            values.add(new AppendValue(value, order));
+        }
+
+        private String getAppendResult() {
+            Collections.sort(values);
+            return values.stream().map(AppendValue::getValue).collect(Collectors.joining(appendSeparator));
+        }
+    }
+
+    /**
+     * An appendable value that can be sorted based on the provided order
+     */
+    private final class AppendValue implements Comparable<AppendValue> {
+        private final String value;
+        private final int order;
+
+        private AppendValue(String value, int order) {
+            this.value = value;
+            this.order = order;
+        }
+
+        private String getValue() {
+            return value;
+        }
+
+        private int getOrder() {
+            return order;
+        }
+
+        @Override
+        public int compareTo(AppendValue o) {
+            return Integer.compare(this.order, o.getOrder());
+        }
+    }
+
+    /**
+     * A result that needs to be converted to a key/value reference
+     */
+    private final class ReferenceResult {
+
+        private String key;
+
+        private String getKey() {
+            return key;
+        }
+
+        private String getValue() {
+            return value;
+        }
+
+        private String value;
+
+        private void setValue(String value) {
+            this.value = value;
+        }
+
+        private void setKey(String key) {
+            this.key = key;
+        }
+    }
+}
diff --git a/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectParser.java b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectParser.java
new file mode 100644
index 00000000000..407d73134b6
--- /dev/null
+++ b/libs/dissect/src/main/java/org/elasticsearch/dissect/DissectParser.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * <p>Splits (dissects) a string into its parts based on a pattern.</p><p>A dissect pattern is composed of a set of keys and delimiters.
+ * For example the dissect pattern: <pre>%{a} %{b},%{c}</pre> has 3 keys (a,b,c) and two delimiters (space and comma). This pattern will
+ * match a string of the form: <pre>foo bar,baz</pre> and will result a key/value pairing of <pre>a=foo, b=bar, and c=baz.</pre>
+ * <p>Matches are all or nothing. For example, the same pattern will NOT match <pre>foo bar baz</pre> since all of the delimiters did not
+ * match. (the comma did not match)
+ * <p>Dissect patterns can optionally have modifiers. These modifiers instruct the parser to change it's behavior. For example the
+ * dissect pattern of <pre>%{a},%{b}:%{c}</pre> would not match <pre>foo,bar,baz</pre> since there the colon never matches.
+ * <p>Modifiers appear to the left or the right of the key name. The supported modifiers are:
+ * <ul>
+ * <li>{@code ->} Instructs the parser to ignore repeating delimiters to the right of the key. Example: <pre>
+ * pattern: {@code %{a->} %{b} %{c}}
+ * string: {@code foo         bar baz}
+ * result: {@code a=foo, b=bar, c=baz}
+ * </pre></li>
+ * <li>{@code +} Instructs the parser to appends this key's value to value of prior key with the same name.
+ * Example: <pre>
+ * pattern: {@code %{a} %{+a} %{+a}}
+ * string: {@code foo bar baz}
+ * result: {@code a=foobarbaz}
+ * </pre></li>
+ * <li>{@code /} Instructs the parser to appends this key's value to value of a key based based on the order specified after the
+ * {@code /}. Requires the {@code +} modifier to also be present in the key. Example: <pre>
+ * pattern: {@code %{a} %{+a/2} %{+a/1}}
+ * string: {@code foo bar baz}
+ * result: {@code a=foobazbar}
+ * </pre>
+ * </li>
+ * <li>{@code *} Instructs the parser to ignore the name of this key, instead use the value of key as the key name.
+ * Requires another key with the same name and the {@code &} modifier to be the value. Example: <pre>
+ * pattern: {@code %{*a} %{b} %{&a}}
+ * string: {@code foo bar baz}
+ * result: {@code foo=baz, b=bar}
+ * </pre></li>
+ * <li>{@code &} Instructs the parser to ignore this key and place the matched value to a key of the same name with the {@code *} modifier.
+ * Requires another key with the same name and the {@code *} modifier.
+ * Example: <pre>
+ * pattern: {@code %{*a} %{b} %{&a}}
+ * string: {@code foo bar baz}
+ * result: {@code foo=baz, b=bar}
+ * </pre></li>
+ * <li>{@code ?} Instructs the parser to ignore this key. The key name exists only for the purpose of human readability. Example
+ * <pre>
+ *  pattern: {@code %{a} %{?skipme} %{c}}
+ *  string: {@code foo bar baz}
+ *  result: {@code a=foo, c=baz}
+ * </pre>
+ * </ul>
+ * <p>Empty key names patterns are also supported. They behave just like the {@code ?} modifier, except the name is not required.
+ * The result will simply be ignored. Example
+ * <pre>
+ * pattern: {@code %{a} %{} %{c}}
+ * string: {@code foo bar baz}
+ * result: {@code a=foo, c=baz}
+ * </pre>
+
+ * <p>
+ * Inspired by the Logstash Dissect Filter by Guy Boertje
+ */
+public final class DissectParser {
+    private static final Pattern LEADING_DELIMITER_PATTERN = Pattern.compile("^(.*?)%");
+    private static final Pattern KEY_DELIMITER_FIELD_PATTERN = Pattern.compile("%\\{([^}]*?)}([^%]*)", Pattern.DOTALL);
+    private static final EnumSet<DissectKey.Modifier> ASSOCIATE_MODIFIERS = EnumSet.of(
+        DissectKey.Modifier.FIELD_NAME,
+        DissectKey.Modifier.FIELD_VALUE);
+    private static final EnumSet<DissectKey.Modifier> APPEND_MODIFIERS = EnumSet.of(
+        DissectKey.Modifier.APPEND,
+        DissectKey.Modifier.APPEND_WITH_ORDER);
+    private static final Function<DissectPair, String> KEY_NAME = val -> val.getKey().getName();
+    private final List<DissectPair> matchPairs;
+    private final String pattern;
+    private String leadingDelimiter = "";
+    private final int maxMatches;
+    private final int maxResults;
+    private final int appendCount;
+    private final int referenceCount;
+    private final String appendSeparator;
+
+    public DissectParser(String pattern, String appendSeparator) {
+        this.pattern = pattern;
+        this.appendSeparator = appendSeparator == null ? "" : appendSeparator;
+        Matcher matcher = LEADING_DELIMITER_PATTERN.matcher(pattern);
+        while (matcher.find()) {
+            leadingDelimiter = matcher.group(1);
+        }
+        List<DissectPair> matchPairs = new ArrayList<>();
+        matcher = KEY_DELIMITER_FIELD_PATTERN.matcher(pattern.substring(leadingDelimiter.length()));
+        while (matcher.find()) {
+            DissectKey key = new DissectKey(matcher.group(1));
+            String delimiter = matcher.group(2);
+            matchPairs.add(new DissectPair(key, delimiter));
+        }
+        this.maxMatches = matchPairs.size();
+        this.maxResults = Long.valueOf(matchPairs.stream()
+            .filter(dissectPair -> !dissectPair.getKey().skip()).map(KEY_NAME).distinct().count()).intValue();
+        if (this.maxMatches == 0 || maxResults == 0) {
+            throw new DissectException.PatternParse(pattern, "Unable to find any keys or delimiters.");
+        }
+        //append validation - look through all of the keys to see if there are any keys that need to participate in an append operation
+        // but don't have the '+' defined
+        Set<String> appendKeyNames = matchPairs.stream()
+            .filter(dissectPair -> APPEND_MODIFIERS.contains(dissectPair.getKey().getModifier()))
+            .map(KEY_NAME).distinct().collect(Collectors.toSet());
+        if (appendKeyNames.size() > 0) {
+            List<DissectPair> modifiedMatchPairs = new ArrayList<>(matchPairs.size());
+            for (DissectPair p : matchPairs) {
+                if (p.getKey().getModifier().equals(DissectKey.Modifier.NONE) && appendKeyNames.contains(p.getKey().getName())) {
+                    modifiedMatchPairs.add(new DissectPair(new DissectKey(p.getKey(), DissectKey.Modifier.APPEND), p.getDelimiter()));
+                } else {
+                    modifiedMatchPairs.add(p);
+                }
+            }
+            matchPairs = modifiedMatchPairs;
+        }
+        appendCount = appendKeyNames.size();
+
+        //reference validation - ensure that '*' and '&' come in pairs
+        Map<String, List<DissectPair>> referenceGroupings = matchPairs.stream()
+            .filter(dissectPair -> ASSOCIATE_MODIFIERS.contains(dissectPair.getKey().getModifier()))
+            .collect(Collectors.groupingBy(KEY_NAME));
+        for (Map.Entry<String, List<DissectPair>> entry : referenceGroupings.entrySet()) {
+            if (entry.getValue().size() != 2) {
+                throw new DissectException.PatternParse(pattern, "Found invalid key/reference associations: '"
+                    + entry.getValue().stream().map(KEY_NAME).collect(Collectors.joining(",")) +
+                    "' Please ensure each '*<key>' is matched with a matching '&<key>");
+            }
+        }
+
+        referenceCount = referenceGroupings.size() * 2;
+        this.matchPairs = Collections.unmodifiableList(matchPairs);
+    }
+
+
+    /**
+     * <p>Entry point to dissect a string into it's parts.</p>
+     *
+     * @param inputString The string to dissect
+     * @return the key/value Map of the results
+     * @throws DissectException if unable to dissect a pair into it's parts.
+     */
+    public Map<String, String> parse(String inputString) {
+        /**
+         *
+         * This implements a naive string matching algorithm. The string is walked left to right, comparing each byte against
+         * another string's bytes looking for matches. If the bytes match, then a second cursor looks ahead to see if all the bytes
+         * of the other string matches. If they all match, record it and advances the primary cursor to the match point. If it can not match
+         * all of the bytes then progress the main cursor. Repeat till the end of the input string. Since the string being searching for
+         * (the delimiter) is generally small and rare the naive approach is efficient.
+         *
+         * In this case the the string that is walked is the input string, and the string being searched for is the current delimiter.
+         * For example for a dissect pattern of {@code %{a},%{b}:%{c}} the delimiters (comma then colon) are searched for in the
+         * input string. At class construction the list of keys+delimiters are found (dissectPairs), which allows the use of that ordered
+         * list to know which delimiter to use for the search. The delimiters is progressed once the current delimiter is matched.
+         *
+         * There are two special cases that requires additional parsing beyond the standard naive algorithm. Consecutive delimiters should
+         * results in a empty matches unless the {@code ->} is provided. For example given the dissect pattern of
+         * {@code %{a},%{b},%{c},%{d}} and input string of {@code foo,,,} the match should be successful with empty values for b,c and d.
+         * However, if the key modifier {@code ->}, is present it will simply skip over any delimiters just to the right of the key
+         * without assigning any values. For example {@code %{a->},{%b}} will match the input string of {@code foo,,,,,,bar} with a=foo and
+         * b=bar.
+         *
+         */
+        DissectMatch dissectMatch = new DissectMatch(appendSeparator, maxMatches, maxResults, appendCount, referenceCount);
+        Iterator<DissectPair> it = matchPairs.iterator();
+        //ensure leading delimiter matches
+        if (inputString != null && inputString.length() > leadingDelimiter.length()
+            && leadingDelimiter.equals(inputString.substring(0, leadingDelimiter.length()))) {
+            byte[] input = inputString.getBytes(StandardCharsets.UTF_8);
+            //grab the first key/delimiter pair
+            DissectPair dissectPair = it.next();
+            DissectKey key = dissectPair.getKey();
+            byte[] delimiter = dissectPair.getDelimiter().getBytes(StandardCharsets.UTF_8);
+            //start dissection after the first delimiter
+            int i = leadingDelimiter.length();
+            int valueStart = i;
+            int lookAheadMatches;
+            //start walking the input string byte by byte, look ahead for matches where needed
+            //if a match is found jump forward to the end of the match
+            for (; i < input.length; i++) {
+                lookAheadMatches = 0;
+                //potential match between delimiter and input string
+                if (delimiter.length > 0 && input[i] == delimiter[0]) {
+                    //look ahead to see if the entire delimiter matches the input string
+                    for (int j = 0; j < delimiter.length; j++) {
+                        if (i + j < input.length && input[i + j] == delimiter[j]) {
+                            lookAheadMatches++;
+                        }
+                    }
+                    //found a full delimiter match
+                    if (lookAheadMatches == delimiter.length) {
+                        //record the key/value tuple
+                        byte[] value = Arrays.copyOfRange(input, valueStart, i);
+                        dissectMatch.add(key, new String(value, StandardCharsets.UTF_8));
+                        //jump to the end of the match
+                        i += lookAheadMatches;
+                        //look for consecutive delimiters (e.g. a,,,,d,e)
+                        while (i < input.length) {
+                            lookAheadMatches = 0;
+                            for (int j = 0; j < delimiter.length; j++) {
+                                if (i + j < input.length && input[i + j] == delimiter[j]) {
+                                    lookAheadMatches++;
+                                }
+                            }
+                            //found consecutive delimiters
+                            if (lookAheadMatches == delimiter.length) {
+                                //jump to the end of the match
+                                i += lookAheadMatches;
+                                if (!key.skipRightPadding()) {
+                                    //progress the keys/delimiter if possible
+                                    if (!it.hasNext()) {
+                                        break; //the while loop
+                                    }
+                                    dissectPair = it.next();
+                                    key = dissectPair.getKey();
+                                    //add the key with an empty value for the empty delimiter
+                                    dissectMatch.add(key, "");
+                                }
+                            } else {
+                                break; //the while loop
+                            }
+                        }
+                        //progress the keys/delimiter if possible
+                        if (!it.hasNext()) {
+                            break; //the for loop
+                        }
+                        dissectPair = it.next();
+                        key = dissectPair.getKey();
+                        delimiter = dissectPair.getDelimiter().getBytes(StandardCharsets.UTF_8);
+                        //i is always one byte after the last found delimiter, aka the start of the next value
+                        valueStart = i;
+                    }
+                }
+            }
+            //the last key, grab the rest of the input (unless consecutive delimiters already grabbed the last key)
+            //and there is no trailing delimiter
+            if (!dissectMatch.fullyMatched() && delimiter.length == 0 ) {
+                byte[] value = Arrays.copyOfRange(input, valueStart, input.length);
+                String valueString = new String(value, StandardCharsets.UTF_8);
+                dissectMatch.add(key, valueString);
+            }
+        }
+        Map<String, String> results = dissectMatch.getResults();
+
+        if (!dissectMatch.isValid(results)) {
+            throw new DissectException.FindMatch(pattern, inputString);
+        }
+        return results;
+    }
+
+    /**
+     * A tuple class to hold the dissect key and delimiter
+     */
+    private class DissectPair {
+
+        private final DissectKey key;
+        private final String delimiter;
+
+        private DissectPair(DissectKey key, String delimiter) {
+            this.key = key;
+            this.delimiter = delimiter;
+        }
+
+        private DissectKey getKey() {
+            return key;
+        }
+
+        private String getDelimiter() {
+            return delimiter;
+        }
+    }
+
+}
+
+
+
diff --git a/libs/dissect/src/test/eclipse-build.gradle b/libs/dissect/src/test/eclipse-build.gradle
new file mode 100644
index 00000000000..56d632f23b1
--- /dev/null
+++ b/libs/dissect/src/test/eclipse-build.gradle
@@ -0,0 +1,7 @@
+
+// this is just shell gradle file for eclipse to have separate projects for dissect src and tests
+apply from: '../../build.gradle'
+
+dependencies {
+  testCompile project(':libs:dissect')
+}
diff --git a/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectKeyTests.java b/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectKeyTests.java
new file mode 100644
index 00000000000..0f3f7ed041d
--- /dev/null
+++ b/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectKeyTests.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+import org.elasticsearch.test.ESTestCase;
+import org.hamcrest.CoreMatchers;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+public class DissectKeyTests extends ESTestCase {
+
+    public void testNoModifier() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        DissectKey dissectKey = new DissectKey(keyName);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NONE));
+        assertThat(dissectKey.skip(), is(false));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testAppendModifier() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        DissectKey dissectKey = new DissectKey("+" + keyName);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.APPEND));
+        assertThat(dissectKey.skip(), is(false));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testAppendWithOrderModifier() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        int length = randomIntBetween(1, 100);
+        DissectKey dissectKey = new DissectKey("+" + keyName + "/" + length);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.APPEND_WITH_ORDER));
+        assertThat(dissectKey.skip(), is(false));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(length));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testAppendWithOrderModifierNoName() {
+        int length = randomIntBetween(1, 100);
+        DissectException e = expectThrows(DissectException.class, () -> new DissectKey("+/" + length));
+        assertThat(e.getMessage(), CoreMatchers.containsString("Unable to parse key"));
+    }
+
+    public void testOrderModifierWithoutAppend() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        int length = randomIntBetween(1, 100);
+        DissectException e = expectThrows(DissectException.class, () -> new DissectKey(keyName + "/" + length));
+        assertThat(e.getMessage(), CoreMatchers.containsString("Unable to parse key"));
+    }
+
+    public void testFieldNameModifier() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        DissectKey dissectKey = new DissectKey("*" + keyName);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.FIELD_NAME));
+        assertThat(dissectKey.skip(), is(false));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testFieldValueModifiers() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        DissectKey dissectKey = new DissectKey("&" + keyName);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.FIELD_VALUE));
+        assertThat(dissectKey.skip(), is(false));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testRightPaddingModifiers() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        DissectKey dissectKey = new DissectKey(keyName + "->");
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NONE));
+        assertThat(dissectKey.skip(), is(false));
+        assertThat(dissectKey.skipRightPadding(), is(true));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+
+        dissectKey = new DissectKey("*" + keyName + "->");
+        assertThat(dissectKey.skipRightPadding(), is(true));
+
+        dissectKey = new DissectKey("&" + keyName + "->");
+        assertThat(dissectKey.skipRightPadding(), is(true));
+
+        dissectKey = new DissectKey("+" + keyName + "->");
+        assertThat(dissectKey.skipRightPadding(), is(true));
+
+        dissectKey = new DissectKey("?" + keyName + "->");
+        assertThat(dissectKey.skipRightPadding(), is(true));
+
+        dissectKey = new DissectKey("+" + keyName + "/2->");
+        assertThat(dissectKey.skipRightPadding(), is(true));
+    }
+
+    public void testMultipleLeftModifiers() {
+        String keyName = randomAlphaOfLengthBetween(1, 10);
+        List<String> validModifiers = EnumSet.allOf(DissectKey.Modifier.class).stream()
+            .filter(m -> !m.equals(DissectKey.Modifier.NONE))
+            .map(DissectKey.Modifier::toString)
+            .collect(Collectors.toList());
+        String modifier1 = randomFrom(validModifiers);
+        String modifier2 = randomFrom(validModifiers);
+        DissectException e = expectThrows(DissectException.class, () -> new DissectKey(modifier1 + modifier2 + keyName));
+        assertThat(e.getMessage(), CoreMatchers.containsString("Unable to parse key"));
+    }
+
+    public void testSkipKey() {
+        String keyName = "";
+        DissectKey dissectKey = new DissectKey(keyName);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NONE));
+        assertThat(dissectKey.skip(), is(true));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+    public void testNamedSkipKey() {
+        String keyName = "myname";
+        DissectKey dissectKey = new DissectKey("?" +keyName);
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NAMED_SKIP));
+        assertThat(dissectKey.skip(), is(true));
+        assertThat(dissectKey.skipRightPadding(), is(false));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testSkipKeyWithPadding() {
+        String keyName = "";
+        DissectKey dissectKey = new DissectKey(keyName  + "->");
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NONE));
+        assertThat(dissectKey.skip(), is(true));
+        assertThat(dissectKey.skipRightPadding(), is(true));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+    public void testNamedEmptySkipKeyWithPadding() {
+        String keyName = "";
+        DissectKey dissectKey = new DissectKey("?" +keyName + "->");
+        assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NAMED_SKIP));
+        assertThat(dissectKey.skip(), is(true));
+        assertThat(dissectKey.skipRightPadding(), is(true));
+        assertThat(dissectKey.getAppendPosition(), equalTo(0));
+        assertThat(dissectKey.getName(), equalTo(keyName));
+    }
+
+    public void testInvalidModifiers() {
+        //should never happen due to regex
+        IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> DissectKey.Modifier.fromString("x"));
+        assertThat(e.getMessage(), CoreMatchers.containsString("invalid modifier"));
+    }
+}
diff --git a/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectMatchTests.java b/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectMatchTests.java
new file mode 100644
index 00000000000..d562afb6363
--- /dev/null
+++ b/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectMatchTests.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+import org.elasticsearch.common.collect.MapBuilder;
+import org.elasticsearch.test.ESTestCase;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.stream.IntStream;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class DissectMatchTests extends ESTestCase {
+
+    public void testIllegalArgs() {
+        expectThrows(IllegalArgumentException.class, () -> new DissectMatch("", 0, 1, 0, 0));
+        expectThrows(IllegalArgumentException.class, () -> new DissectMatch("", 1, 0, 0, 0));
+    }
+
+    public void testValidAndFullyMatched() {
+        int expectedMatches = randomIntBetween(1, 26);
+        DissectMatch dissectMatch = new DissectMatch("", expectedMatches, expectedMatches, 0, 0);
+        IntStream.range(97, 97 + expectedMatches)  //allow for a-z values
+            .forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[]{(byte) i}, StandardCharsets.UTF_8)), ""));
+        assertThat(dissectMatch.fullyMatched(), equalTo(true));
+        assertThat(dissectMatch.isValid(dissectMatch.getResults()), equalTo(true));
+    }
+
+    public void testNotValidAndFullyMatched() {
+        int expectedMatches = randomIntBetween(1, 26);
+        DissectMatch dissectMatch = new DissectMatch("", expectedMatches, expectedMatches, 0, 0);
+        IntStream.range(97, 97 + expectedMatches - 1)  //allow for a-z values
+            .forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[]{(byte) i}, StandardCharsets.UTF_8)), ""));
+        assertThat(dissectMatch.fullyMatched(), equalTo(false));
+        assertThat(dissectMatch.isValid(dissectMatch.getResults()), equalTo(false));
+    }
+
+    public void testGetResultsIdempotent(){
+        int expectedMatches = randomIntBetween(1, 26);
+        DissectMatch dissectMatch = new DissectMatch("", expectedMatches, expectedMatches, 0, 0);
+        IntStream.range(97, 97 + expectedMatches)  //allow for a-z values
+            .forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[]{(byte) i}, StandardCharsets.UTF_8)), ""));
+        assertThat(dissectMatch.getResults(), equalTo(dissectMatch.getResults()));
+    }
+
+    public void testAppend(){
+        DissectMatch dissectMatch = new DissectMatch("-", 3, 1, 3, 0);
+        dissectMatch.add(new DissectKey("+a"), "x");
+        dissectMatch.add(new DissectKey("+a"), "y");
+        dissectMatch.add(new DissectKey("+a"), "z");
+        Map<String, String> results = dissectMatch.getResults();
+        assertThat(dissectMatch.isValid(results), equalTo(true));
+        assertThat(results, equalTo(MapBuilder.newMapBuilder().put("a", "x-y-z").map()));
+    }
+
+    public void testAppendWithOrder(){
+        DissectMatch dissectMatch = new DissectMatch("-", 3, 1, 3, 0);
+        dissectMatch.add(new DissectKey("+a/3"), "x");
+        dissectMatch.add(new DissectKey("+a"), "y");
+        dissectMatch.add(new DissectKey("+a/1"), "z");
+        Map<String, String> results = dissectMatch.getResults();
+        assertThat(dissectMatch.isValid(results), equalTo(true));
+        assertThat(results, equalTo(MapBuilder.newMapBuilder().put("a", "y-z-x").map()));
+    }
+
+    public void testReference(){
+        DissectMatch dissectMatch = new DissectMatch("-", 2, 1, 0, 1);
+        dissectMatch.add(new DissectKey("&a"), "x");
+        dissectMatch.add(new DissectKey("*a"), "y");
+        Map<String, String> results = dissectMatch.getResults();
+        assertThat(dissectMatch.isValid(results), equalTo(true));
+        assertThat(results, equalTo(MapBuilder.newMapBuilder().put("y", "x").map()));
+    }
+
+}
diff --git a/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectParserTests.java b/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectParserTests.java
new file mode 100644
index 00000000000..c22cec98eb7
--- /dev/null
+++ b/libs/dissect/src/test/java/org/elasticsearch/dissect/DissectParserTests.java
@@ -0,0 +1,386 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.dissect;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.elasticsearch.test.ESTestCase;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Matchers;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import static com.carrotsearch.randomizedtesting.RandomizedTest.randomAsciiAlphanumOfLengthBetween;
+
+public class DissectParserTests extends ESTestCase {
+
+    public void testJavaDocExamples() {
+        assertMatch("%{a} %{b},%{c}", "foo bar,baz", Arrays.asList("a", "b", "c"), Arrays.asList("foo", "bar", "baz"));
+        assertMiss("%{a},%{b}:%{c}", "foo,bar,baz");
+        assertMatch("%{a->} %{b} %{c}", "foo         bar baz", Arrays.asList("a", "b", "c"), Arrays.asList("foo", "bar", "baz"));
+        assertMatch("%{a} %{+a} %{+a}", "foo bar baz", Arrays.asList("a"), Arrays.asList("foobarbaz"));
+        assertMatch("%{a} %{+a/2} %{+a/1}", "foo bar baz", Arrays.asList("a"), Arrays.asList("foobazbar"));
+        assertMatch("%{*a} %{b} %{&a}", "foo bar baz", Arrays.asList("foo", "b"), Arrays.asList("baz", "bar"));
+        assertMatch("%{a} %{} %{c}", "foo bar baz", Arrays.asList("a", "c"), Arrays.asList("foo", "baz"));
+        assertMatch("%{a} %{?skipme} %{c}", "foo bar baz", Arrays.asList("a", "c"), Arrays.asList("foo", "baz"));
+        assertMatch("%{a},%{b},%{c},%{d}", "foo,,,", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "", ""));
+        assertMatch("%{a->},%{b}", "foo,,,,,,bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+    }
+
+    /**
+     * Borrowed from Logstash's test cases:
+     * https://github.com/logstash-plugins/logstash-filter-dissect/blob/master/src/test/java/org/logstash/dissect/DissectorTest.java
+     * Append Note - Logstash appends with the delimiter as the separator between values, this uses a user defined separator
+     */
+    public void testLogstashSpecs() {
+        assertMatch("%{a} %{b->} %{c}", "foo bar   baz", Arrays.asList("a", "b", "c"), Arrays.asList("foo", "bar", "baz"));
+        assertMiss("%{a}%{b} %{c}", null);
+        assertMiss("%{a} %{b}%{c} %{d}", "foo bar baz");
+        assertMiss("%{a} %{b} %{c}%{d}", "foo bar baz quux");
+        assertMatch("%{a} %{b->} %{c}", "foo bar   baz", Arrays.asList("a", "b", "c"), Arrays.asList("foo", "bar", "baz"));
+        assertMatch("%{a} %{} %{c}", "foo bar baz", Arrays.asList("a", "c"), Arrays.asList("foo", "baz"));
+        assertMatch("%{a} %{b} %{+b} %{z}", "foo bar baz quux", Arrays.asList("a", "b", "z"), Arrays.asList("foo", "bar baz", "quux"), " ");
+        assertMatch("%{a}------->%{b}", "foo------->bar baz quux", Arrays.asList("a", "b"), Arrays.asList("foo", "bar baz quux"));
+        assertMatch("%{a}------->%{}", "foo------->bar baz quux", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{a} » %{b}»%{c}€%{d}", "foo » bar»baz€quux",
+            Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "bar", "baz", "quux"));
+        assertMatch("%{a} %{b} %{+a}", "foo bar baz quux", Arrays.asList("a", "b"), Arrays.asList("foo baz quux", "bar"), " ");
+        //Logstash supports implicit ordering based anchored by the the key without the '+'
+        //This implementation will only honor implicit ordering for appending right to left else explicit order (/N) is required.
+        //The results of this test differ from Logstash.
+        assertMatch("%{+a} %{a} %{+a} %{b}", "December 31 1999 quux",
+            Arrays.asList("a", "b"), Arrays.asList("December 31 1999", "quux"), " ");
+        //Same test as above, but with same result as Logstash using explicit ordering in the pattern
+        assertMatch("%{+a/1} %{a} %{+a/2} %{b}", "December 31 1999 quux",
+            Arrays.asList("a", "b"), Arrays.asList("31 December 1999", "quux"), " ");
+        assertMatch("%{+a/2} %{+a/4} %{+a/1} %{+a/3}", "bar quux foo baz", Arrays.asList("a"), Arrays.asList("foo bar baz quux"), " ");
+        assertMatch("%{+a} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{+a} %{b} %{+a} %{c}", "foo bar baz quux",
+            Arrays.asList("a", "b", "c"), Arrays.asList("foo baz", "bar", "quux"), " ");
+        assertMatch("%{} %{syslog_timestamp} %{hostname} %{rt}: %{reason} %{+reason} %{src_ip}/%{src_port}->%{dst_ip}/%{dst_port} " +
+                "%{polrt} %{+polrt} %{+polrt} %{from_zone} %{to_zone} %{rest}",
+            "42 2016-05-25T14:47:23Z host.name.com RT_FLOW - RT_FLOW_SESSION_DENY: session denied 2.2.2.20/60000->1.1.1.10/8090 None " +
+                "6(0) DEFAULT-DENY ZONE-UNTRUST ZONE-DMZ UNKNOWN UNKNOWN N/A(N/A) ge-0/0/0.0",
+            Arrays.asList("syslog_timestamp", "hostname", "rt", "reason", "src_ip", "src_port", "dst_ip", "dst_port", "polrt"
+                , "from_zone", "to_zone", "rest"),
+            Arrays.asList("2016-05-25T14:47:23Z", "host.name.com", "RT_FLOW - RT_FLOW_SESSION_DENY", "session denied", "2.2.2.20", "60000"
+                , "1.1.1.10", "8090", "None 6(0) DEFAULT-DENY", "ZONE-UNTRUST", "ZONE-DMZ", "UNKNOWN UNKNOWN N/A(N/A) ge-0/0/0.0"), " ");
+        assertBadKey("%{+/2}");
+        assertBadKey("%{&+a_field}");
+        assertMatch("%{a->}   %{b->}---%{c}", "foo            bar------------baz",
+            Arrays.asList("a", "b", "c"), Arrays.asList("foo", "bar", "baz"));
+        assertMatch("%{->}-%{a}", "-----666", Arrays.asList("a"), Arrays.asList("666"));
+        assertMatch("%{?skipme->}-%{a}", "-----666", Arrays.asList("a"), Arrays.asList("666"));
+        assertMatch("%{a},%{b},%{c},%{d},%{e},%{f}", "111,,333,,555,666",
+            Arrays.asList("a", "b", "c", "d", "e", "f"), Arrays.asList("111", "", "333", "", "555", "666"));
+        assertMatch("%{a}.࿏.%{b}", "⟳༒.࿏.༒⟲", Arrays.asList("a", "b"), Arrays.asList("⟳༒", "༒⟲"));
+        assertMatch("%{a}", "子", Arrays.asList("a"), Arrays.asList("子"));
+        assertMatch("%{a}{\n}%{b}", "aaa{\n}bbb", Arrays.asList("a", "b"), Arrays.asList("aaa", "bbb"));
+        assertMiss("MACHINE[%{a}] %{b}", "1234567890 MACHINE[foo] bar");
+        assertMiss("%{a} %{b} %{c}", "foo:bar:baz");
+        assertMatch("/var/%{key1}/log/%{key2}.log", "/var/foo/log/bar.log", Arrays.asList("key1", "key2"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a->}   %{b}-.-%{c}-%{d}-..-%{e}-%{f}-%{g}-%{h}", "foo            bar-.-baz-1111-..-22-333-4444-55555",
+            Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h"),
+            Arrays.asList("foo", "bar", "baz", "1111", "22", "333", "4444", "55555"));
+    }
+
+    public void testBasicMatch() {
+        String valueFirstInput = "";
+        String keyFirstPattern = "";
+        String delimiterFirstInput = "";
+        String delimiterFirstPattern = "";
+        //parallel arrays
+        List<String> expectedKeys = Arrays.asList(generateRandomStringArray(100, 10, false, false));
+        List<String> expectedValues = new ArrayList<>(expectedKeys.size());
+        for (String key : expectedKeys) {
+            String value = randomAsciiAlphanumOfLengthBetween(1, 100);
+            String delimiter = Integer.toString(randomInt()); //int to ensures values and delimiters don't overlap, else validation can fail
+            keyFirstPattern += "%{" + key + "}" + delimiter;
+            valueFirstInput += value + delimiter;
+            delimiterFirstPattern += delimiter + "%{" + key + "}";
+            delimiterFirstInput += delimiter + value;
+            expectedValues.add(value);
+        }
+        assertMatch(keyFirstPattern, valueFirstInput, expectedKeys, expectedValues);
+        assertMatch(delimiterFirstPattern, delimiterFirstInput, expectedKeys, expectedValues);
+    }
+
+    public void testBasicMatchUnicode() {
+        String valueFirstInput = "";
+        String keyFirstPattern = "";
+        String delimiterFirstInput = "";
+        String delimiterFirstPattern = "";
+        //parallel arrays
+        List<String> expectedKeys = new ArrayList<>();
+        List<String> expectedValues = new ArrayList<>();
+        for (int i = 0; i < randomIntBetween(1, 100); i++) {
+            String key = randomAsciiAlphanumOfLengthBetween(1, 100);
+            String value = randomRealisticUnicodeOfCodepointLengthBetween(1, 100);
+            String delimiter = Integer.toString(randomInt()); //int to ensures values and delimiters don't overlap, else validation can fail
+            keyFirstPattern += "%{" + key + "}" + delimiter;
+            valueFirstInput += value + delimiter;
+            delimiterFirstPattern += delimiter + "%{" + key + "}";
+            delimiterFirstInput += delimiter + value;
+            expectedKeys.add(key);
+            expectedValues.add(value);
+        }
+        assertMatch(keyFirstPattern, valueFirstInput, expectedKeys, expectedValues);
+        assertMatch(delimiterFirstPattern, delimiterFirstInput, expectedKeys, expectedValues);
+    }
+
+    public void testMatchUnicode() {
+        assertMatch("%{a} %{b}", "foo 子", Arrays.asList("a", "b"), Arrays.asList("foo", "子"));
+        assertMatch("%{a}࿏%{b} %{c}", "⟳༒࿏༒⟲ 子", Arrays.asList("a", "b", "c"), Arrays.asList("⟳༒", "༒⟲", "子"));
+        assertMatch("%{a}࿏%{+a} %{+a}", "⟳༒࿏༒⟲ 子", Arrays.asList("a"), Arrays.asList("⟳༒༒⟲子"));
+        assertMatch("%{a}࿏%{+a/2} %{+a/1}", "⟳༒࿏༒⟲ 子", Arrays.asList("a"), Arrays.asList("⟳༒子༒⟲"));
+        assertMatch("%{a->}࿏%{b}", "⟳༒࿏࿏࿏࿏࿏༒⟲", Arrays.asList("a", "b"), Arrays.asList("⟳༒", "༒⟲"));
+        assertMatch("%{*a}࿏%{&a}", "⟳༒࿏༒⟲", Arrays.asList("⟳༒"), Arrays.asList("༒⟲"));
+        assertMatch("%{}࿏%{a}", "⟳༒࿏༒⟲", Arrays.asList("a"), Arrays.asList("༒⟲"));
+    }
+
+    public void testMatchRemainder() {
+        assertMatch("%{a}", "foo bar the rest", Arrays.asList("a"), Arrays.asList("foo bar the rest"));
+        assertMatch("%{a} %{b}", "foo bar the rest", Arrays.asList("a", "b"), Arrays.asList("foo", "bar the rest"));
+        assertMatch("%{} %{b}", "foo bar the rest", Arrays.asList("b"), Arrays.asList("bar the rest"));
+        assertMatch("%{a} %{b->}", "foo bar the rest", Arrays.asList("a", "b"), Arrays.asList("foo", "bar the rest"));
+        assertMatch("%{*a} %{&a}", "foo bar the rest", Arrays.asList("foo"), Arrays.asList("bar the rest"));
+        assertMatch("%{a} %{+a}", "foo bar the rest", Arrays.asList("a"), Arrays.asList("foo bar the rest"), " ");
+    }
+
+    public void testAppend() {
+        assertMatch("%{a} %{+a} %{+a}", "foo bar baz", Arrays.asList("a"), Arrays.asList("foobarbaz"));
+        assertMatch("%{a} %{+a} %{b} %{+b}", "foo bar baz lol", Arrays.asList("a", "b"), Arrays.asList("foobar", "bazlol"));
+        assertMatch("%{a} %{+a/2} %{+a/1}", "foo bar baz", Arrays.asList("a"), Arrays.asList("foobazbar"));
+        assertMatch("%{a} %{+a/2} %{+a/1}", "foo bar baz", Arrays.asList("a"), Arrays.asList("foo baz bar"), " ");
+    }
+
+    public void testAssociate() {
+        assertMatch("%{*a} %{&a}", "foo bar", Arrays.asList("foo"), Arrays.asList("bar"));
+        assertMatch("%{&a} %{*a}", "foo bar", Arrays.asList("bar"), Arrays.asList("foo"));
+        assertMatch("%{*a} %{&a} %{*b} %{&b}", "foo bar baz lol", Arrays.asList("foo", "baz"), Arrays.asList("bar", "lol"));
+        assertMatch("%{*a} %{&a} %{c} %{*b} %{&b}", "foo bar x baz lol",
+            Arrays.asList("foo", "baz", "c"), Arrays.asList("bar", "lol", "x"));
+        assertBadPattern("%{*a} %{a}");
+        assertBadPattern("%{a} %{&a}");
+        assertMiss("%{*a} %{&a} {a} %{*b} %{&b}", "foo bar x baz lol");
+    }
+
+    public void testAppendAndAssociate() {
+        assertMatch("%{a} %{+a} %{*b} %{&b}", "foo bar baz lol", Arrays.asList("a", "baz"), Arrays.asList("foobar", "lol"));
+        assertMatch("%{a->} %{+a/2} %{+a/1} %{*b} %{&b}", "foo      bar baz lol x",
+            Arrays.asList("a", "lol"), Arrays.asList("foobazbar", "x"));
+    }
+
+    public void testEmptyKey() {
+        assertMatch("%{} %{b}", "foo bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{a} %{}", "foo bar", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{->} %{b}", "foo        bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{->} %{b}", "        bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{a} %{->}", "foo  bar       ", Arrays.asList("a"), Arrays.asList("foo"));
+    }
+
+    public void testNamedSkipKey() {
+        assertMatch("%{?foo} %{b}", "foo bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{?} %{b}", "foo bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{a} %{?bar}", "foo bar", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{?foo->} %{b}", "foo        bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{?->} %{b}", "foo        bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{?foo->} %{b}", "        bar", Arrays.asList("b"), Arrays.asList("bar"));
+        assertMatch("%{a} %{->?bar}", "foo  bar       ", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{a} %{?skipme} %{?skipme}", "foo  bar  baz", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{a} %{?} %{?}", "foo  bar  baz", Arrays.asList("a"), Arrays.asList("foo"));
+    }
+
+    public void testConsecutiveDelimiters() {
+        //leading
+        assertMatch("%{->},%{a}", ",,,,,foo", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{a->},%{b}", ",,,,,foo", Arrays.asList("a", "b"), Arrays.asList("", "foo"));
+        //trailing
+        assertMatch("%{a->},", "foo,,,,,", Arrays.asList("a"), Arrays.asList("foo"));
+        assertMatch("%{a} %{b},", "foo bar,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a} %{b->},", "foo bar,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        //middle
+        assertMatch("%{a->},%{b}", "foo,,,,,bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a->} %{b}", "foo     bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a->}x%{b}", "fooxxxxxbar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a->} xyz%{b}", "foo xyz xyz xyz xyz xyzbar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        //skipped with empty values
+        assertMatch("%{a},%{b},%{c},%{d}", "foo,,,", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "", ""));
+        assertMatch("%{a},%{b},%{c},%{d}", "foo,,bar,baz", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "bar", "baz"));
+        assertMatch("%{a},%{b},%{c},%{d}", "foo,,,baz", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "", "baz"));
+        assertMatch("%{a},%{b},%{c},%{d}", ",bar,,baz", Arrays.asList("a", "b", "c", "d"), Arrays.asList("", "bar", "", "baz"));
+        assertMatch("%{->},%{a->},%{b}", ",,,bar,,baz", Arrays.asList("a", "b"), Arrays.asList("bar", "baz"));
+    }
+
+    public void testAppendWithConsecutiveDelimiters() {
+        assertMatch("%{+a/1},%{+a/3}-%{+a/2} %{b}", "foo,bar----baz lol", Arrays.asList("a", "b"), Arrays.asList("foobar", ""));
+        assertMatch("%{+a/1},%{+a/3->}-%{+a/2} %{b}", "foo,bar----baz lol", Arrays.asList("a", "b"), Arrays.asList("foobazbar", "lol"));
+    }
+
+    public void testSkipRightPadding() {
+        assertMatch("%{a->} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a->} %{b}", "foo            bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{->} %{a}", "foo            bar", Arrays.asList("a"), Arrays.asList("bar"));
+        assertMatch("%{a->} %{+a->} %{*b->} %{&b->} %{c}", "foo       bar    baz  lol    x",
+            Arrays.asList("a", "baz", "c"), Arrays.asList("foobar", "lol", "x"));
+    }
+
+    public void testTrimmedEnd() {
+        assertMatch("%{a} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch("%{a} %{b->} ", "foo bar        ", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        //only whitespace is trimmed in the absence of trailing characters
+        assertMatch("%{a} %{b->}", "foo bar,,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar,,,,,,"));
+        //consecutive delimiters + right padding can be used to skip over the trailing delimiters
+        assertMatch("%{a} %{b->},", "foo bar,,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+    }
+
+    public void testLeadingDelimiter() {
+        assertMatch(",,,%{a} %{b}", ",,,foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
+        assertMatch(",%{a} %{b}", ",,foo bar", Arrays.asList("a", "b"), Arrays.asList(",foo", "bar"));
+    }
+
+    /**
+     * Runtime errors
+     */
+    public void testMiss() {
+        assertMiss("%{a}%{b}", "foo");
+        assertMiss("%{a},%{b}", "foo bar");
+        assertMiss("%{a}, %{b}", "foo,bar");
+        assertMiss("x%{a},%{b}", "foo,bar");
+        assertMiss("x%{},%{b}", "foo,bar");
+        assertMiss("leading_delimiter_long%{a}", "foo");
+        assertMiss("%{a}trailing_delimiter_long", "foo");
+        assertMiss("leading_delimiter_long%{a}trailing_delimiter_long", "foo");
+        assertMiss("%{a}x", "foo");
+        assertMiss("%{a},%{b}x", "foo,bar");
+    }
+
+    /**
+     * Construction errors
+     */
+    public void testBadPatternOrKey() {
+        assertBadPattern("");
+        assertBadPattern("{}");
+        assertBadPattern("%{*a} %{&b}");
+        assertBadKey("%{*}");
+        assertBadKey("%{++}");
+    }
+
+    public void testSyslog() {
+        assertMatch("%{timestamp} %{+timestamp} %{+timestamp} %{logsource} %{program}[%{pid}]: %{message}",
+            "Mar 16 00:01:25 evita postfix/smtpd[1713]: connect from camomile.cloud9.net[168.100.1.3]",
+            Arrays.asList("timestamp", "logsource", "program", "pid", "message"),
+            Arrays.asList("Mar 16 00:01:25", "evita", "postfix/smtpd", "1713", "connect from camomile.cloud9.net[168.100.1.3]"), " ");
+    }
+
+    public void testApacheLog() {
+        assertMatch("%{clientip} %{ident} %{auth} [%{timestamp}] \"%{verb} %{request} HTTP/%{httpversion}\" %{response} %{bytes}" +
+                " \"%{referrer}\" \"%{agent}\" %{->}",
+            "31.184.238.164 - - [24/Jul/2014:05:35:37 +0530] \"GET /logs/access.log HTTP/1.0\" 200 69849 " +
+                "\"http://8rursodiol.enjin.com\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) " +
+                "Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36\" \"www.dlwindianrailways.com\"",
+            Arrays.asList("clientip", "ident", "auth", "timestamp", "verb", "request", "httpversion", "response", "bytes",
+                "referrer", "agent"),
+            Arrays.asList("31.184.238.164", "-", "-", "24/Jul/2014:05:35:37 +0530", "GET", "/logs/access.log", "1.0", "200", "69849",
+                "http://8rursodiol.enjin.com", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36" +
+                    " (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"));
+    }
+
+    /**
+     * Shared specification between Beats, Logstash, and Ingest node
+     */
+    public void testJsonSpecification() throws Exception {
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode rootNode = mapper.readTree(this.getClass().getResourceAsStream("/specification/tests.json"));
+        Iterator<JsonNode> tests = rootNode.elements();
+        while (tests.hasNext()) {
+            JsonNode test = tests.next();
+            boolean skip = test.path("skip").asBoolean();
+            if (!skip) {
+                String name = test.path("name").asText();
+                logger.debug("Running Json specification: " + name);
+                String pattern = test.path("tok").asText();
+                String input = test.path("msg").asText();
+                String append = test.path("append").asText();
+                boolean fail = test.path("fail").asBoolean();
+                Iterator<Map.Entry<String, JsonNode>> expected = test.path("expected").fields();
+                List<String> expectedKeys = new ArrayList<>();
+                List<String> expectedValues = new ArrayList<>();
+                expected.forEachRemaining(entry -> {
+                    expectedKeys.add(entry.getKey());
+                    expectedValues.add(entry.getValue().asText());
+                });
+                if (fail) {
+                    assertFail(pattern, input);
+                } else {
+                    assertMatch(pattern, input, expectedKeys, expectedValues, append);
+                }
+            }
+        }
+    }
+
+    private DissectException assertFail(String pattern, String input){
+        return expectThrows(DissectException.class, () -> new DissectParser(pattern, null).parse(input));
+    }
+
+    private void assertMiss(String pattern, String input) {
+        DissectException e = assertFail(pattern, input);
+        assertThat(e.getMessage(), CoreMatchers.containsString("Unable to find match for dissect pattern"));
+        assertThat(e.getMessage(), CoreMatchers.containsString(pattern));
+        assertThat(e.getMessage(), input == null ? CoreMatchers.containsString("null") : CoreMatchers.containsString(input));
+    }
+
+    private void assertBadPattern(String pattern) {
+        DissectException e = assertFail(pattern, null);
+        assertThat(e.getMessage(), CoreMatchers.containsString("Unable to parse pattern"));
+        assertThat(e.getMessage(), CoreMatchers.containsString(pattern));
+    }
+
+    private void assertBadKey(String pattern, String key) {
+        DissectException e = assertFail(pattern, null);
+        assertThat(e.getMessage(), CoreMatchers.containsString("Unable to parse key"));
+        assertThat(e.getMessage(), CoreMatchers.containsString(key));
+    }
+
+    private void assertBadKey(String pattern) {
+        assertBadKey(pattern, pattern.replace("%{", "").replace("}", ""));
+    }
+
+    private void assertMatch(String pattern, String input, List<String> expectedKeys, List<String> expectedValues) {
+        assertMatch(pattern, input, expectedKeys, expectedValues, null);
+    }
+
+    private void assertMatch(String pattern, String input, List<String> expectedKeys, List<String> expectedValues, String appendSeperator) {
+        Map<String, String> results = new DissectParser(pattern, appendSeperator).parse(input);
+        List<String> foundKeys = new ArrayList<>(results.keySet());
+        List<String> foundValues = new ArrayList<>(results.values());
+        Collections.sort(foundKeys);
+        Collections.sort(foundValues);
+        Collections.sort(expectedKeys);
+        Collections.sort(expectedValues);
+        assertThat(foundKeys, Matchers.equalTo(expectedKeys));
+        assertThat(foundValues, Matchers.equalTo(expectedValues));
+    }
+}
diff --git a/libs/dissect/src/test/resources/specification/tests.json b/libs/dissect/src/test/resources/specification/tests.json
new file mode 100644
index 00000000000..1cb85ce6519
--- /dev/null
+++ b/libs/dissect/src/test/resources/specification/tests.json
@@ -0,0 +1,363 @@
+[
+  {
+    "name": "When all the defined fields are captured by we have remaining data",
+    "tok": "level=%{level} ts=%{timestamp} caller=%{caller} msg=\"%{message}\"",
+    "msg": "level=info ts=2018-06-27T17:19:13.036579993Z caller=main.go:222 msg=\"Starting OK\" version=\"(version=2.3.1, branch=HEAD, revision=188ca45bd85ce843071e768d855722a9d9dabe03)\"}",
+    "expected": {
+      "caller": "main.go:222",
+      "level": "info",
+      "message": "Starting OK",
+      "timestamp": "2018-06-27T17:19:13.036579993Z"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "Complex stack trace",
+    "tok": "%{day}-%{month}-%{year} %{hour} %{severity} [%{thread_id}] %{origin} %{message}",
+    "msg": "18-Apr-2018 06:53:20.411 INFO [http-nio-8080-exec-1] org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header\n Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.\n java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens\n    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:426)\n    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:687)\n    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\n    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)\n    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)\n    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n    at java.lang.Thread.run(Thread.java:748)",
+    "expected": {
+      "day": "18",
+      "hour": "06:53:20.411",
+      "message": "Error parsing HTTP request header\n Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.\n java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens\n    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:426)\n    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:687)\n    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\n    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)\n    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)\n    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n    at java.lang.Thread.run(Thread.java:748)",
+      "month": "Apr",
+      "origin": "org.apache.coyote.http11.Http11Processor.service",
+      "severity": "INFO",
+      "thread_id": "http-nio-8080-exec-1",
+      "year": "2018"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "success when delimiter found at the beginning and end of the string",
+    "tok": "/var/log/%{key}.log",
+    "msg": "/var/log/foobar.log",
+    "expected": {
+      "key": "foobar"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "fails when delimiter is not found at the beginning of the string",
+    "tok": "/var/log/%{key}.log",
+    "msg": "foobar",
+    "expected": null,
+    "skip": false,
+    "fail": true,
+    "append": ""
+  },
+  {
+    "name": "fails when delimiter is not found after the key",
+    "tok": "/var/log/%{key}.log",
+    "msg": "/var/log/foobar",
+    "expected": null,
+    "skip": false,
+    "fail": true,
+    "append": ""
+  },
+  {
+    "name": "simple dissect",
+    "tok": "%{key}",
+    "msg": "foobar",
+    "expected": {
+      "key": "foobar"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "dissect two replacement",
+    "tok": "%{key1} %{key2}",
+    "msg": "foo bar",
+    "expected": {
+      "key1": "foo",
+      "key2": "bar"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "fail on partial match",
+    "tok": "%{key1} %{key2} %{key3}",
+    "msg": "foo bar",
+    "expected": null,
+    "skip": false,
+    "fail": true,
+    "append": ""
+  },
+  {
+    "name": "one level dissect not end of string",
+    "tok": "/var/%{key}/log",
+    "msg": "/var/foobar/log",
+    "expected": {
+      "key": "foobar"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "one level dissect",
+    "tok": "/var/%{key}",
+    "msg": "/var/foobar/log",
+    "expected": {
+      "key": "foobar/log"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "multiple keys dissect end of string",
+    "tok": "/var/%{key}/log/%{key1}",
+    "msg": "/var/foobar/log/apache",
+    "expected": {
+      "key": "foobar",
+      "key1": "apache"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "multiple keys not end of string",
+    "tok": "/var/%{key}/log/%{key1}.log",
+    "msg": "/var/foobar/log/apache.log",
+    "expected": {
+      "key": "foobar",
+      "key1": "apache"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "append with order",
+    "tok": "%{+key/3} %{+key/1} %{+key/2}",
+    "msg": "1 2 3",
+    "expected": {
+      "key": "231"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "append with order and separator",
+    "tok": "%{+key/3} %{+key/1} %{+key/2}",
+    "msg": "1 2 3",
+    "expected": {
+      "key": "2::3::1"
+    },
+    "skip": false,
+    "fail": false,
+    "append": "::"
+  },
+  {
+    "name": "append with order and right padding",
+    "tok": "%{+key/3} %{+key/1-\u003e} %{+key/2}",
+    "msg": "1 2              3",
+    "expected": {
+      "key": "231"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "simple append",
+    "tok": "%{key}-%{+key}-%{+key}",
+    "msg": "1-2-3",
+    "expected": {
+      "key": "123"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "simple append with separator",
+    "tok": "%{key}-%{+key}-%{+key}",
+    "msg": "1-2-3",
+    "expected": {
+      "key": "1,2,3"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ","
+  },
+  {
+    "name": "reference field",
+    "tok": "%{*key} %{\u0026key}",
+    "msg": "hello world",
+    "expected": {
+      "hello": "world"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "reference field alt order",
+    "tok": "%{\u0026key} %{*key}",
+    "msg": "hello world",
+    "expected": {
+      "world": "hello"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "nameless skip field",
+    "tok": "%{} %{key}",
+    "msg": "hello world",
+    "expected": {
+      "key": "world"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "named skip field",
+    "tok": "%{?skipme} %{key}",
+    "msg": "hello world",
+    "expected": {
+      "key": "world"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "reference without pairing",
+    "tok": "%{key} %{\u0026key}",
+    "msg": "hello world",
+    "expected": null,
+    "skip": false,
+    "fail": true,
+    "append": ""
+  },
+  {
+    "name": "missing fields (consecutive delimiters)",
+    "tok": "%{name},%{addr1},%{addr2},%{addr3},%{city},%{zip}",
+    "msg": "Jane Doe,4321 Fifth Avenue,,,New York,87432",
+    "expected": {
+      "addr1": "4321 Fifth Avenue",
+      "addr2": "",
+      "addr3": "",
+      "city": "New York",
+      "name": "Jane Doe",
+      "zip": "87432"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "missing fields with right padding (consecutive delimiters)",
+    "tok": "%{name},%{addr1-\u003e},%{city},%{zip}",
+    "msg": "Jane Doe,4321 Fifth Avenue,,,New York,87432",
+    "expected": {
+      "addr1": "4321 Fifth Avenue",
+      "city": "New York",
+      "name": "Jane Doe",
+      "zip": "87432"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "ignore right padding",
+    "tok": "%{id} %{function-\u003e} %{server}",
+    "msg": "00000043 ViewReceive     machine-321",
+    "expected": {
+      "function": "ViewReceive",
+      "id": "00000043",
+      "server": "machine-321"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "padding on the last key need a delimiter",
+    "tok": "%{id} %{function} %{server-\u003e} ",
+    "msg": "00000043 ViewReceive machine-321    ",
+    "expected": {
+      "function": "ViewReceive",
+      "id": "00000043",
+      "server": "machine-321"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "ignore left padding",
+    "tok": "%{id-\u003e} %{function} %{server}",
+    "msg": "00000043    ViewReceive machine-321",
+    "expected": {
+      "function": "ViewReceive",
+      "id": "00000043",
+      "server": "machine-321"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "when the delimiters contains `{` and `}`",
+    "tok": "{%{a}}{%{b}} %{rest}",
+    "msg": "{c}{d} anything",
+    "expected": {
+      "a": "c",
+      "b": "d",
+      "rest": "anything"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  },
+  {
+    "name": "no keys defined",
+    "tok": "anything",
+    "msg": "anything",
+    "expected": null,
+    "skip": false,
+    "fail": true,
+    "append": ""
+  },
+  {
+    "name": "invalid key",
+    "tok": "%{some?thing}",
+    "msg": "anything",
+    "expected": null,
+    "skip": false,
+    "fail": true,
+    "append": ""
+  },
+  {
+    "name": "matches non-ascii",
+    "tok": "%{a}࿏%{b} %{c}",
+    "msg": "⟳༒࿏༒⟲ 子",
+    "expected": {
+      "a": "⟳༒",
+      "b": "༒⟲",
+      "c": "子"
+    },
+    "skip": false,
+    "fail": false,
+    "append": ""
+  }
+
+]
\ No newline at end of file
diff --git a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java
index c59023b8622..a4a0076626a 100644
--- a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java
+++ b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/WhitelistLoader.java
@@ -53,7 +53,7 @@ public final class WhitelistLoader {
      *     a Painless type name with the exception that any dollar symbols used as part of inner classes will
      *     be replaced with dot symbols. </li>
      *     <li> short Java type name - The text after the final dot symbol of any specified Java class. A
-     *     short type Java name may be excluded by using the 'only_fqn' token during Painless class parsing
+     *     short type Java name may be excluded by using the 'no_import' token during Painless class parsing
      *     as described later. </li>
      * </ul>
      *
@@ -65,7 +65,7 @@ public final class WhitelistLoader {
      *   <li> Primitive types may be specified starting with 'class' and followed by the Java type name,
      *   an opening bracket, a newline, a closing bracket, and a final newline. </li>
      *   <li> Complex types may be specified starting with 'class' and followed the fully-qualified Java
-     *   class name, optionally followed by an 'only_fqn' token, an opening bracket, a newline,
+     *   class name, optionally followed by an 'no_import' token, an opening bracket, a newline,
      *   constructor/method/field specifications, a closing bracket, and a final newline. Within a complex
      *   type the following may be parsed:
      *   <ul>
@@ -109,7 +109,7 @@ public final class WhitelistLoader {
      *
      * # complex types
      *
-     * class my.package.Example only_fqn {
+     * class my.package.Example no_import {
      *   # constructors
      *   ()
      *   (int)
@@ -145,7 +145,7 @@ public final class WhitelistLoader {
 
                 String whitelistClassOrigin = null;
                 String javaClassName = null;
-                boolean onlyFQNJavaClassName = false;
+                boolean noImport = false;
                 List<WhitelistConstructor> whitelistConstructors = null;
                 List<WhitelistMethod> whitelistMethods = null;
                 List<WhitelistField> whitelistFields = null;
@@ -160,7 +160,7 @@ public final class WhitelistLoader {
                     }
 
                     // Handle a new class by resetting all the variables necessary to construct a new WhitelistClass for the whitelist.
-                    // Expects the following format: 'class' ID 'only_fqn'? '{' '\n'
+                    // Expects the following format: 'class' ID 'no_import'? '{' '\n'
                     if (line.startsWith("class ")) {
                         // Ensure the final token of the line is '{'.
                         if (line.endsWith("{") == false) {
@@ -172,8 +172,8 @@ public final class WhitelistLoader {
                         String[] tokens = line.substring(5, line.length() - 1).trim().split("\\s+");
 
                         // Ensure the correct number of tokens.
-                        if (tokens.length == 2 && "only_fqn".equals(tokens[1])) {
-                            onlyFQNJavaClassName = true;
+                        if (tokens.length == 2 && "no_import".equals(tokens[1])) {
+                            noImport = true;
                         } else if (tokens.length != 1) {
                             throw new IllegalArgumentException("invalid class definition: failed to parse class name [" + line + "]");
                         }
@@ -194,13 +194,13 @@ public final class WhitelistLoader {
                             throw new IllegalArgumentException("invalid class definition: extraneous closing bracket");
                         }
 
-                        whitelistClasses.add(new WhitelistClass(whitelistClassOrigin, javaClassName, onlyFQNJavaClassName,
+                        whitelistClasses.add(new WhitelistClass(whitelistClassOrigin, javaClassName, noImport,
                             whitelistConstructors, whitelistMethods, whitelistFields));
 
                         // Set all the variables to null to ensure a new class definition is found before other parsable values.
                         whitelistClassOrigin = null;
                         javaClassName = null;
-                        onlyFQNJavaClassName = false;
+                        noImport = false;
                         whitelistConstructors = null;
                         whitelistMethods = null;
                         whitelistFields = null;
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java
index 0346867d35a..e644453a4c1 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java
@@ -293,7 +293,7 @@ public final class PainlessLookupBuilder {
 
         if (canonicalClassName.equals(importedCanonicalClassName)) {
             if (importClassName == true) {
-                throw new IllegalArgumentException("must use only_fqn parameter on class [" + canonicalClassName + "] with no package");
+                throw new IllegalArgumentException("must use no_import parameter on class [" + canonicalClassName + "] with no package");
             }
         } else {
             Class<?> importedPainlessClass = canonicalClassNamesToClasses.get(importedCanonicalClassName);
@@ -301,7 +301,8 @@ public final class PainlessLookupBuilder {
             if (importedPainlessClass == null) {
                 if (importClassName) {
                     if (existingPainlessClassBuilder != null) {
-                        throw new IllegalArgumentException("inconsistent only_fqn parameters found for class [" + canonicalClassName + "]");
+                        throw new IllegalArgumentException(
+                                "inconsistent no_import parameters found for class [" + canonicalClassName + "]");
                     }
 
                     canonicalClassNamesToClasses.put(importedCanonicalClassName, clazz);
@@ -310,7 +311,7 @@ public final class PainlessLookupBuilder {
                 throw new IllegalArgumentException("imported class [" + importedCanonicalClassName + "] cannot represent multiple " +
                         "classes [" + canonicalClassName + "] and [" + typeToCanonicalTypeName(importedPainlessClass) + "]");
             } else if (importClassName == false) {
-                throw new IllegalArgumentException("inconsistent only_fqn parameters found for class [" + canonicalClassName + "]");
+                throw new IllegalArgumentException("inconsistent no_import parameters found for class [" + canonicalClassName + "]");
             }
         }
     }
diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt
index f424f6acf25..a3ff479533b 100644
--- a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt
+++ b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt
@@ -24,31 +24,31 @@
 
 #### Primitive types
 
-class void only_fqn {
+class void no_import {
 }
 
-class boolean only_fqn {
+class boolean no_import {
 }
 
-class byte only_fqn {
+class byte no_import {
 }
 
-class short only_fqn {
+class short no_import {
 }
 
-class char only_fqn {
+class char no_import {
 }
 
-class int only_fqn {
+class int no_import {
 }
 
-class long only_fqn {
+class long no_import {
 }
 
-class float only_fqn {
+class float no_import {
 }
 
-class double only_fqn {
+class double no_import {
 }
 
 #### Painless debugging API
@@ -134,7 +134,7 @@ class org.elasticsearch.index.mapper.IpFieldMapper$IpFieldType$IpScriptDocValues
 
 # for testing.
 # currently FeatureTest exposes overloaded constructor, field load store, and overloaded static methods
-class org.elasticsearch.painless.FeatureTest only_fqn {
+class org.elasticsearch.painless.FeatureTest no_import {
   int z
   ()
   (int,int)
diff --git a/modules/repository-url/src/test/java/org/elasticsearch/repositories/url/URLSnapshotRestoreTests.java b/modules/repository-url/src/test/java/org/elasticsearch/repositories/url/URLSnapshotRestoreTests.java
index 9eb5e37a51c..1a006f56bc3 100644
--- a/modules/repository-url/src/test/java/org/elasticsearch/repositories/url/URLSnapshotRestoreTests.java
+++ b/modules/repository-url/src/test/java/org/elasticsearch/repositories/url/URLSnapshotRestoreTests.java
@@ -20,9 +20,9 @@
 package org.elasticsearch.repositories.url;
 
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.ByteSizeUnit;
@@ -120,7 +120,7 @@ public class URLSnapshotRestoreTests extends ESIntegTestCase {
         assertThat(getSnapshotsResponse.getSnapshots().size(), equalTo(1));
 
         logger.info("--> delete snapshot");
-        DeleteSnapshotResponse deleteSnapshotResponse = client.admin().cluster().prepareDeleteSnapshot("test-repo", "test-snap").get();
+        AcknowledgedResponse deleteSnapshotResponse = client.admin().cluster().prepareDeleteSnapshot("test-repo", "test-snap").get();
         assertAcked(deleteSnapshotResponse);
 
         logger.info("--> list available shapshot again, no snapshots should be returned");
diff --git a/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/Netty4Transport.java b/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/Netty4Transport.java
index 90138bc5990..e310f3012a9 100644
--- a/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/Netty4Transport.java
+++ b/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/Netty4Transport.java
@@ -54,7 +54,6 @@ import org.elasticsearch.common.util.concurrent.EsExecutors;
 import org.elasticsearch.indices.breaker.CircuitBreakerService;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TcpTransport;
-import org.elasticsearch.transport.TransportRequestOptions;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -147,7 +146,6 @@ public class Netty4Transport extends TcpTransport {
 
         bootstrap.handler(getClientChannelInitializer());
 
-        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(defaultConnectionProfile.getConnectTimeout().millis()));
         bootstrap.option(ChannelOption.TCP_NODELAY, TCP_NO_DELAY.get(settings));
         bootstrap.option(ChannelOption.SO_KEEPALIVE, TCP_KEEP_ALIVE.get(settings));
 
@@ -175,14 +173,8 @@ public class Netty4Transport extends TcpTransport {
         String name = profileSettings.profileName;
         if (logger.isDebugEnabled()) {
             logger.debug("using profile[{}], worker_count[{}], port[{}], bind_host[{}], publish_host[{}], compress[{}], "
-                    + "connect_timeout[{}], connections_per_node[{}/{}/{}/{}/{}], receive_predictor[{}->{}]",
+                    + "receive_predictor[{}->{}]",
                 name, workerCount, profileSettings.portOrRange, profileSettings.bindHosts, profileSettings.publishHosts, compress,
-                defaultConnectionProfile.getConnectTimeout(),
-                defaultConnectionProfile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY),
-                defaultConnectionProfile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK),
-                defaultConnectionProfile.getNumConnectionsPerType(TransportRequestOptions.Type.REG),
-                defaultConnectionProfile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE),
-                defaultConnectionProfile.getNumConnectionsPerType(TransportRequestOptions.Type.PING),
                 receivePredictorMin, receivePredictorMax);
         }
 
diff --git a/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIT.java b/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIT.java
index d3980c19110..d74baee3d56 100644
--- a/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIT.java
+++ b/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIT.java
@@ -19,8 +19,8 @@
 package org.elasticsearch.index.mapper.size;
 
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.plugin.mapper.MapperSizePlugin;
@@ -62,7 +62,7 @@ public class SizeMappingIT extends ESIntegTestCase {
         XContentBuilder updateMappingBuilder =
             jsonBuilder().startObject().startObject("properties").startObject("otherField").field("type", "text")
                 .endObject().endObject().endObject();
-        PutMappingResponse putMappingResponse =
+        AcknowledgedResponse putMappingResponse =
             client().admin().indices().preparePutMapping(index).setType(type).setSource(updateMappingBuilder).get();
         assertAcked(putMappingResponse);
 
@@ -84,7 +84,7 @@ public class SizeMappingIT extends ESIntegTestCase {
         // update some field in the mapping
         XContentBuilder updateMappingBuilder =
             jsonBuilder().startObject().startObject("_size").field("enabled", false).endObject().endObject();
-        PutMappingResponse putMappingResponse =
+        AcknowledgedResponse putMappingResponse =
             client().admin().indices().preparePutMapping(index).setType(type).setSource(updateMappingBuilder).get();
         assertAcked(putMappingResponse);
 
diff --git a/plugins/repository-hdfs/src/test/java/org/elasticsearch/repositories/hdfs/HdfsTests.java b/plugins/repository-hdfs/src/test/java/org/elasticsearch/repositories/hdfs/HdfsTests.java
index c328563b4b6..5c5ab4ee426 100644
--- a/plugins/repository-hdfs/src/test/java/org/elasticsearch/repositories/hdfs/HdfsTests.java
+++ b/plugins/repository-hdfs/src/test/java/org/elasticsearch/repositories/hdfs/HdfsTests.java
@@ -19,9 +19,9 @@
 package org.elasticsearch.repositories.hdfs;
 
 import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.bootstrap.JavaVersion;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
@@ -48,7 +48,7 @@ public class HdfsTests extends ESSingleNodeTestCase {
         assumeFalse("https://github.com/elastic/elasticsearch/issues/31498", JavaVersion.current().equals(JavaVersion.parse("11")));
         Client client = client();
 
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("hdfs")
                 .setSettings(Settings.builder()
                         .put("uri", "hdfs:///")
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryAction.java
index c5c72bb97f1..a31984e2227 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryAction.java
@@ -20,11 +20,12 @@
 package org.elasticsearch.action.admin.cluster.repositories.delete;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
 /**
  * Unregister repository action
  */
-public class DeleteRepositoryAction extends Action<DeleteRepositoryResponse> {
+public class DeleteRepositoryAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteRepositoryAction INSTANCE = new DeleteRepositoryAction();
     public static final String NAME = "cluster:admin/repository/delete";
@@ -34,8 +35,8 @@ public class DeleteRepositoryAction extends Action<DeleteRepositoryResponse> {
     }
 
     @Override
-    public DeleteRepositoryResponse newResponse() {
-        return new DeleteRepositoryResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryRequestBuilder.java
index 2b56b71f6fc..b6e8de24c5d 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryRequestBuilder.java
@@ -20,12 +20,13 @@
 package org.elasticsearch.action.admin.cluster.repositories.delete;
 
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 
 /**
  * Builder for unregister repository request
  */
-public class DeleteRepositoryRequestBuilder extends AcknowledgedRequestBuilder<DeleteRepositoryRequest, DeleteRepositoryResponse, DeleteRepositoryRequestBuilder> {
+public class DeleteRepositoryRequestBuilder extends AcknowledgedRequestBuilder<DeleteRepositoryRequest, AcknowledgedResponse, DeleteRepositoryRequestBuilder> {
 
     /**
      * Constructs unregister repository request builder
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryResponse.java
deleted file mode 100644
index f67d74cd118..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryResponse.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.cluster.repositories.delete;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * Unregister repository response
- */
-public class DeleteRepositoryResponse extends AcknowledgedResponse {
-
-    DeleteRepositoryResponse() {
-    }
-
-    DeleteRepositoryResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static DeleteRepositoryResponse fromXContent(XContentParser parser) {
-        return new DeleteRepositoryResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java
index 6baf834278b..a39bb12e31e 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.cluster.repositories.delete;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -37,7 +38,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Transport action for unregister repository operation
  */
-public class TransportDeleteRepositoryAction extends TransportMasterNodeAction<DeleteRepositoryRequest, DeleteRepositoryResponse> {
+public class TransportDeleteRepositoryAction extends TransportMasterNodeAction<DeleteRepositoryRequest, AcknowledgedResponse> {
 
     private final RepositoriesService repositoriesService;
 
@@ -55,8 +56,8 @@ public class TransportDeleteRepositoryAction extends TransportMasterNodeAction<D
     }
 
     @Override
-    protected DeleteRepositoryResponse newResponse() {
-        return new DeleteRepositoryResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -65,14 +66,14 @@ public class TransportDeleteRepositoryAction extends TransportMasterNodeAction<D
     }
 
     @Override
-    protected void masterOperation(final DeleteRepositoryRequest request, ClusterState state, final ActionListener<DeleteRepositoryResponse> listener) {
+    protected void masterOperation(final DeleteRepositoryRequest request, ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         repositoriesService.unregisterRepository(
                 new RepositoriesService.UnregisterRepositoryRequest("delete_repository [" + request.name() + "]", request.name())
                         .masterNodeTimeout(request.masterNodeTimeout()).ackTimeout(request.timeout()),
                 new ActionListener<ClusterStateUpdateResponse>() {
                     @Override
                     public void onResponse(ClusterStateUpdateResponse unregisterRepositoryResponse) {
-                        listener.onResponse(new DeleteRepositoryResponse(unregisterRepositoryResponse.isAcknowledged()));
+                        listener.onResponse(new AcknowledgedResponse(unregisterRepositoryResponse.isAcknowledged()));
                     }
 
                     @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryAction.java
index 801e0a513b0..7c98f591e0e 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryAction.java
@@ -20,11 +20,12 @@
 package org.elasticsearch.action.admin.cluster.repositories.put;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
 /**
  * Register repository action
  */
-public class PutRepositoryAction extends Action<PutRepositoryResponse> {
+public class PutRepositoryAction extends Action<AcknowledgedResponse> {
 
     public static final PutRepositoryAction INSTANCE = new PutRepositoryAction();
     public static final String NAME = "cluster:admin/repository/put";
@@ -34,8 +35,8 @@ public class PutRepositoryAction extends Action<PutRepositoryResponse> {
     }
 
     @Override
-    public PutRepositoryResponse newResponse() {
-        return new PutRepositoryResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryRequestBuilder.java
index 21b8e8713a1..ea62bb4eee6 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryRequestBuilder.java
@@ -20,6 +20,7 @@
 package org.elasticsearch.action.admin.cluster.repositories.put;
 
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentType;
@@ -29,7 +30,7 @@ import java.util.Map;
 /**
  * Register repository request builder
  */
-public class PutRepositoryRequestBuilder extends AcknowledgedRequestBuilder<PutRepositoryRequest, PutRepositoryResponse, PutRepositoryRequestBuilder> {
+public class PutRepositoryRequestBuilder extends AcknowledgedRequestBuilder<PutRepositoryRequest, AcknowledgedResponse, PutRepositoryRequestBuilder> {
 
     /**
      * Constructs register repository request
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryResponse.java
deleted file mode 100644
index 23aae119e0d..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryResponse.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.cluster.repositories.put;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * Register repository response
- */
-public class PutRepositoryResponse extends AcknowledgedResponse {
-
-    PutRepositoryResponse() {
-    }
-
-    PutRepositoryResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static PutRepositoryResponse fromXContent(XContentParser parser) {
-        return new PutRepositoryResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java
index 2ac4950c327..6f0339f46ee 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.cluster.repositories.put;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -37,7 +38,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Transport action for register repository operation
  */
-public class TransportPutRepositoryAction extends TransportMasterNodeAction<PutRepositoryRequest, PutRepositoryResponse> {
+public class TransportPutRepositoryAction extends TransportMasterNodeAction<PutRepositoryRequest, AcknowledgedResponse> {
 
     private final RepositoriesService repositoriesService;
 
@@ -55,8 +56,8 @@ public class TransportPutRepositoryAction extends TransportMasterNodeAction<PutR
     }
 
     @Override
-    protected PutRepositoryResponse newResponse() {
-        return new PutRepositoryResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -65,7 +66,7 @@ public class TransportPutRepositoryAction extends TransportMasterNodeAction<PutR
     }
 
     @Override
-    protected void masterOperation(final PutRepositoryRequest request, ClusterState state, final ActionListener<PutRepositoryResponse> listener) {
+    protected void masterOperation(final PutRepositoryRequest request, ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
 
         repositoriesService.registerRepository(
                 new RepositoriesService.RegisterRepositoryRequest("put_repository [" + request.name() + "]",
@@ -76,7 +77,7 @@ public class TransportPutRepositoryAction extends TransportMasterNodeAction<PutR
 
             @Override
             public void onResponse(ClusterStateUpdateResponse response) {
-                listener.onResponse(new PutRepositoryResponse(response.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotAction.java
index ac04ea66905..64f4e60fb2d 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotAction.java
@@ -20,11 +20,12 @@
 package org.elasticsearch.action.admin.cluster.snapshots.delete;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
 /**
  * Delete snapshot action
  */
-public class DeleteSnapshotAction extends Action<DeleteSnapshotResponse> {
+public class DeleteSnapshotAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteSnapshotAction INSTANCE = new DeleteSnapshotAction();
     public static final String NAME = "cluster:admin/snapshot/delete";
@@ -34,8 +35,8 @@ public class DeleteSnapshotAction extends Action<DeleteSnapshotResponse> {
     }
 
     @Override
-    public DeleteSnapshotResponse newResponse() {
-        return new DeleteSnapshotResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotRequestBuilder.java
index 2a3f8a0889a..9b723de0e6c 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotRequestBuilder.java
@@ -19,13 +19,14 @@
 
 package org.elasticsearch.action.admin.cluster.snapshots.delete;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
 import org.elasticsearch.client.ElasticsearchClient;
 
 /**
  * Delete snapshot request builder
  */
-public class DeleteSnapshotRequestBuilder extends MasterNodeOperationRequestBuilder<DeleteSnapshotRequest, DeleteSnapshotResponse, DeleteSnapshotRequestBuilder> {
+public class DeleteSnapshotRequestBuilder extends MasterNodeOperationRequestBuilder<DeleteSnapshotRequest, AcknowledgedResponse, DeleteSnapshotRequestBuilder> {
 
     /**
      * Constructs delete snapshot request builder
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java
deleted file mode 100644
index ac6e74d3970..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponse.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.cluster.snapshots.delete;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * Delete snapshot response
- */
-public class DeleteSnapshotResponse extends AcknowledgedResponse {
-
-    DeleteSnapshotResponse() {
-    }
-
-    DeleteSnapshotResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static DeleteSnapshotResponse fromXContent(XContentParser parser) {
-        return new DeleteSnapshotResponse(parseAcknowledged(parser));
-    }
-
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java
index 916e2f945ec..b3c9f089e63 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.cluster.snapshots.delete;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -36,7 +37,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Transport action for delete snapshot operation
  */
-public class TransportDeleteSnapshotAction extends TransportMasterNodeAction<DeleteSnapshotRequest, DeleteSnapshotResponse> {
+public class TransportDeleteSnapshotAction extends TransportMasterNodeAction<DeleteSnapshotRequest, AcknowledgedResponse> {
     private final SnapshotsService snapshotsService;
 
     @Inject
@@ -53,8 +54,8 @@ public class TransportDeleteSnapshotAction extends TransportMasterNodeAction<Del
     }
 
     @Override
-    protected DeleteSnapshotResponse newResponse() {
-        return new DeleteSnapshotResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -64,11 +65,11 @@ public class TransportDeleteSnapshotAction extends TransportMasterNodeAction<Del
     }
 
     @Override
-    protected void masterOperation(final DeleteSnapshotRequest request, ClusterState state, final ActionListener<DeleteSnapshotResponse> listener) {
+    protected void masterOperation(final DeleteSnapshotRequest request, ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         snapshotsService.deleteSnapshot(request.repository(), request.snapshot(), new SnapshotsService.DeleteSnapshotListener() {
             @Override
             public void onResponse() {
-                listener.onResponse(new DeleteSnapshotResponse(true));
+                listener.onResponse(new AcknowledgedResponse(true));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptAction.java
index 070d8d055ea..7ba8ee0754f 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.cluster.storedscripts;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class DeleteStoredScriptAction extends Action<DeleteStoredScriptResponse> {
+public class DeleteStoredScriptAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteStoredScriptAction INSTANCE = new DeleteStoredScriptAction();
     public static final String NAME = "cluster:admin/script/delete";
@@ -31,7 +32,7 @@ public class DeleteStoredScriptAction extends Action<DeleteStoredScriptResponse>
     }
 
     @Override
-    public DeleteStoredScriptResponse newResponse() {
-        return new DeleteStoredScriptResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptRequestBuilder.java
index 1b48a45be3c..132f9dc08a3 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptRequestBuilder.java
@@ -20,10 +20,11 @@
 package org.elasticsearch.action.admin.cluster.storedscripts;
 
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 
 public class DeleteStoredScriptRequestBuilder extends AcknowledgedRequestBuilder<DeleteStoredScriptRequest,
-        DeleteStoredScriptResponse, DeleteStoredScriptRequestBuilder> {
+    AcknowledgedResponse, DeleteStoredScriptRequestBuilder> {
 
     public DeleteStoredScriptRequestBuilder(ElasticsearchClient client, DeleteStoredScriptAction action) {
         super(client, action, new DeleteStoredScriptRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java
deleted file mode 100644
index 741c105866f..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.cluster.storedscripts;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-public class DeleteStoredScriptResponse extends AcknowledgedResponse {
-
-    DeleteStoredScriptResponse() {
-    }
-
-    public DeleteStoredScriptResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static DeleteStoredScriptResponse fromXContent(XContentParser parser) {
-        return new DeleteStoredScriptResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptAction.java
index 41c345fd007..8e5475283c2 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptAction.java
@@ -20,9 +20,10 @@
 package org.elasticsearch.action.admin.cluster.storedscripts;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
 
-public class PutStoredScriptAction extends Action<PutStoredScriptResponse> {
+public class PutStoredScriptAction extends Action<AcknowledgedResponse> {
 
     public static final PutStoredScriptAction INSTANCE = new PutStoredScriptAction();
     public static final String NAME = "cluster:admin/script/put";
@@ -34,7 +35,7 @@ public class PutStoredScriptAction extends Action<PutStoredScriptResponse> {
 
 
     @Override
-    public PutStoredScriptResponse newResponse() {
-        return new PutStoredScriptResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptRequestBuilder.java
index e98f7c7e3e6..dc505596607 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptRequestBuilder.java
@@ -20,12 +20,13 @@
 package org.elasticsearch.action.admin.cluster.storedscripts;
 
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.xcontent.XContentType;
 
 public class PutStoredScriptRequestBuilder extends AcknowledgedRequestBuilder<PutStoredScriptRequest,
-        PutStoredScriptResponse, PutStoredScriptRequestBuilder> {
+    AcknowledgedResponse, PutStoredScriptRequestBuilder> {
 
     public PutStoredScriptRequestBuilder(ElasticsearchClient client, PutStoredScriptAction action) {
         super(client, action, new PutStoredScriptRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptResponse.java
deleted file mode 100644
index a511c7dd47e..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptResponse.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.cluster.storedscripts;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-
-public class PutStoredScriptResponse extends AcknowledgedResponse {
-
-    PutStoredScriptResponse() {
-    }
-
-    public PutStoredScriptResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java
index b7ae06dbdbb..c351ae4a670 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.cluster.storedscripts;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -33,8 +34,7 @@ import org.elasticsearch.script.ScriptService;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 
-public class TransportDeleteStoredScriptAction extends TransportMasterNodeAction<DeleteStoredScriptRequest,
-        DeleteStoredScriptResponse> {
+public class TransportDeleteStoredScriptAction extends TransportMasterNodeAction<DeleteStoredScriptRequest, AcknowledgedResponse> {
 
     private final ScriptService scriptService;
 
@@ -53,13 +53,13 @@ public class TransportDeleteStoredScriptAction extends TransportMasterNodeAction
     }
 
     @Override
-    protected DeleteStoredScriptResponse newResponse() {
-        return new DeleteStoredScriptResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(DeleteStoredScriptRequest request, ClusterState state,
-                                   ActionListener<DeleteStoredScriptResponse> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
         scriptService.deleteStoredScript(clusterService, request, listener);
     }
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportPutStoredScriptAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportPutStoredScriptAction.java
index 8b4079aee73..abeb5327c1a 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportPutStoredScriptAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportPutStoredScriptAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.cluster.storedscripts;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -33,7 +34,7 @@ import org.elasticsearch.script.ScriptService;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 
-public class TransportPutStoredScriptAction extends TransportMasterNodeAction<PutStoredScriptRequest, PutStoredScriptResponse> {
+public class TransportPutStoredScriptAction extends TransportMasterNodeAction<PutStoredScriptRequest, AcknowledgedResponse> {
 
     private final ScriptService scriptService;
 
@@ -52,13 +53,13 @@ public class TransportPutStoredScriptAction extends TransportMasterNodeAction<Pu
     }
 
     @Override
-    protected PutStoredScriptResponse newResponse() {
-        return new PutStoredScriptResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(PutStoredScriptRequest request, ClusterState state,
-                                   ActionListener<PutStoredScriptResponse> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
         scriptService.putStoredScript(clusterService, request, listener);
     }
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesAction.java
index 378e017855a..7f7743f8173 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.alias;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class IndicesAliasesAction extends Action<IndicesAliasesResponse> {
+public class IndicesAliasesAction extends Action<AcknowledgedResponse> {
 
     public static final IndicesAliasesAction INSTANCE = new IndicesAliasesAction();
     public static final String NAME = "indices:admin/aliases";
@@ -31,7 +32,7 @@ public class IndicesAliasesAction extends Action<IndicesAliasesResponse> {
     }
 
     @Override
-    public IndicesAliasesResponse newResponse() {
-        return new IndicesAliasesResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesRequestBuilder.java
index 3a74c349e78..6608da9189b 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesRequestBuilder.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.alias;
 
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.index.query.QueryBuilder;
 
@@ -30,7 +31,7 @@ import java.util.Map;
  * Builder for request to modify many aliases at once.
  */
 public class IndicesAliasesRequestBuilder
-        extends AcknowledgedRequestBuilder<IndicesAliasesRequest, IndicesAliasesResponse, IndicesAliasesRequestBuilder> {
+        extends AcknowledgedRequestBuilder<IndicesAliasesRequest, AcknowledgedResponse, IndicesAliasesRequestBuilder> {
 
     public IndicesAliasesRequestBuilder(ElasticsearchClient client, IndicesAliasesAction action) {
         super(client, action, new IndicesAliasesRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesResponse.java
deleted file mode 100644
index 31ebcbf0f0a..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesResponse.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.alias;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.ConstructingObjectParser;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * A response for a add/remove alias action.
- */
-public class IndicesAliasesResponse extends AcknowledgedResponse {
-
-    private static final ConstructingObjectParser<IndicesAliasesResponse, Void> PARSER = new ConstructingObjectParser<>("indices_aliases",
-            true, args -> new IndicesAliasesResponse((boolean) args[0]));
-    static {
-        declareAcknowledgedField(PARSER);
-    }
-
-    IndicesAliasesResponse() {
-    }
-
-    IndicesAliasesResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static IndicesAliasesResponse fromXContent(XContentParser parser) {
-        return new IndicesAliasesResponse(parseAcknowledged(parser));
-    }
-}
\ No newline at end of file
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/TransportIndicesAliasesAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/TransportIndicesAliasesAction.java
index d137665c197..d6ecaf8b2c9 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/alias/TransportIndicesAliasesAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/alias/TransportIndicesAliasesAction.java
@@ -23,6 +23,7 @@ import com.carrotsearch.hppc.cursors.ObjectCursor;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -52,7 +53,7 @@ import static java.util.Collections.unmodifiableList;
 /**
  * Add/remove aliases action
  */
-public class TransportIndicesAliasesAction extends TransportMasterNodeAction<IndicesAliasesRequest, IndicesAliasesResponse> {
+public class TransportIndicesAliasesAction extends TransportMasterNodeAction<IndicesAliasesRequest, AcknowledgedResponse> {
 
     private final MetaDataIndexAliasesService indexAliasesService;
 
@@ -71,8 +72,8 @@ public class TransportIndicesAliasesAction extends TransportMasterNodeAction<Ind
     }
 
     @Override
-    protected IndicesAliasesResponse newResponse() {
-        return new IndicesAliasesResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -85,7 +86,7 @@ public class TransportIndicesAliasesAction extends TransportMasterNodeAction<Ind
     }
 
     @Override
-    protected void masterOperation(final IndicesAliasesRequest request, final ClusterState state, final ActionListener<IndicesAliasesResponse> listener) {
+    protected void masterOperation(final IndicesAliasesRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
 
         //Expand the indices names
         List<AliasActions> actions = request.aliasActions();
@@ -127,7 +128,7 @@ public class TransportIndicesAliasesAction extends TransportMasterNodeAction<Ind
         indexAliasesService.indicesAliases(updateRequest, new ActionListener<ClusterStateUpdateResponse>() {
             @Override
             public void onResponse(ClusterStateUpdateResponse response) {
-                listener.onResponse(new IndicesAliasesResponse(response.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexAction.java
index 5c3d60dd440..68a911ff586 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.close;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class CloseIndexAction extends Action<CloseIndexResponse> {
+public class CloseIndexAction extends Action<AcknowledgedResponse> {
 
     public static final CloseIndexAction INSTANCE = new CloseIndexAction();
     public static final String NAME = "indices:admin/close";
@@ -31,7 +32,7 @@ public class CloseIndexAction extends Action<CloseIndexResponse> {
     }
 
     @Override
-    public CloseIndexResponse newResponse() {
-        return new CloseIndexResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexRequestBuilder.java
index a45e8d38f04..e69c6fed87d 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexRequestBuilder.java
@@ -21,12 +21,14 @@ package org.elasticsearch.action.admin.indices.close;
 
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 
 /**
  * Builder for close index request
  */
-public class CloseIndexRequestBuilder extends AcknowledgedRequestBuilder<CloseIndexRequest, CloseIndexResponse, CloseIndexRequestBuilder> {
+public class CloseIndexRequestBuilder
+    extends AcknowledgedRequestBuilder<CloseIndexRequest, AcknowledgedResponse, CloseIndexRequestBuilder> {
 
     public CloseIndexRequestBuilder(ElasticsearchClient client, CloseIndexAction action) {
         super(client, action, new CloseIndexRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponse.java
deleted file mode 100644
index 96a3e150af1..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponse.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.close;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * A response for a close index action.
- */
-public class CloseIndexResponse extends AcknowledgedResponse {
-    CloseIndexResponse() {
-    }
-
-    CloseIndexResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static CloseIndexResponse fromXContent(XContentParser parser) {
-        return new CloseIndexResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java
index 0bd6370e88a..f2e284656e5 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.DestructiveOperations;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -44,7 +45,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Close index action
  */
-public class TransportCloseIndexAction extends TransportMasterNodeAction<CloseIndexRequest, CloseIndexResponse> {
+public class TransportCloseIndexAction extends TransportMasterNodeAction<CloseIndexRequest, AcknowledgedResponse> {
 
     private final MetaDataIndexStateService indexStateService;
     private final DestructiveOperations destructiveOperations;
@@ -75,12 +76,12 @@ public class TransportCloseIndexAction extends TransportMasterNodeAction<CloseIn
     }
 
     @Override
-    protected CloseIndexResponse newResponse() {
-        return new CloseIndexResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
-    protected void doExecute(Task task, CloseIndexRequest request, ActionListener<CloseIndexResponse> listener) {
+    protected void doExecute(Task task, CloseIndexRequest request, ActionListener<AcknowledgedResponse> listener) {
         destructiveOperations.failDestructive(request.indices());
         if (closeIndexEnabled == false) {
             throw new IllegalStateException("closing indices is disabled - set [" + CLUSTER_INDICES_CLOSE_ENABLE_SETTING.getKey() + ": true] to enable it. NOTE: closed indices still consume a significant amount of diskspace");
@@ -94,10 +95,10 @@ public class TransportCloseIndexAction extends TransportMasterNodeAction<CloseIn
     }
 
     @Override
-    protected void masterOperation(final CloseIndexRequest request, final ClusterState state, final ActionListener<CloseIndexResponse> listener) {
+    protected void masterOperation(final CloseIndexRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         final Index[] concreteIndices = indexNameExpressionResolver.concreteIndices(state, request);
         if (concreteIndices == null || concreteIndices.length == 0) {
-            listener.onResponse(new CloseIndexResponse(true));
+            listener.onResponse(new AcknowledgedResponse(true));
             return;
         }
         CloseIndexClusterStateUpdateRequest updateRequest = new CloseIndexClusterStateUpdateRequest()
@@ -108,7 +109,7 @@ public class TransportCloseIndexAction extends TransportMasterNodeAction<CloseIn
 
             @Override
             public void onResponse(ClusterStateUpdateResponse response) {
-                listener.onResponse(new CloseIndexResponse(response.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexAction.java
index 680501af3b7..6fde9089cef 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.delete;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class DeleteIndexAction extends Action<DeleteIndexResponse> {
+public class DeleteIndexAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteIndexAction INSTANCE = new DeleteIndexAction();
     public static final String NAME = "indices:admin/delete";
@@ -31,7 +32,7 @@ public class DeleteIndexAction extends Action<DeleteIndexResponse> {
     }
 
     @Override
-    public DeleteIndexResponse newResponse() {
-        return new DeleteIndexResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexRequestBuilder.java
index 2fd31d9a3ab..376a115b196 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexRequestBuilder.java
@@ -21,9 +21,10 @@ package org.elasticsearch.action.admin.indices.delete;
 
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 
-public class DeleteIndexRequestBuilder extends AcknowledgedRequestBuilder<DeleteIndexRequest, DeleteIndexResponse, DeleteIndexRequestBuilder> {
+public class DeleteIndexRequestBuilder extends AcknowledgedRequestBuilder<DeleteIndexRequest, AcknowledgedResponse, DeleteIndexRequestBuilder> {
 
     public DeleteIndexRequestBuilder(ElasticsearchClient client, DeleteIndexAction action, String... indices) {
         super(client, action, new DeleteIndexRequest(indices));
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java
deleted file mode 100644
index b86549f536d..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponse.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.delete;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * A response for a delete index action.
- */
-public class DeleteIndexResponse extends AcknowledgedResponse {
-
-    DeleteIndexResponse() {
-    }
-
-    DeleteIndexResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static DeleteIndexResponse fromXContent(XContentParser parser) {
-        return new DeleteIndexResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java
index e51046f85be..62421da8916 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.DestructiveOperations;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -44,7 +45,7 @@ import java.util.Set;
 /**
  * Delete index action.
  */
-public class TransportDeleteIndexAction extends TransportMasterNodeAction<DeleteIndexRequest, DeleteIndexResponse> {
+public class TransportDeleteIndexAction extends TransportMasterNodeAction<DeleteIndexRequest, AcknowledgedResponse> {
 
     private final MetaDataDeleteIndexService deleteIndexService;
     private final DestructiveOperations destructiveOperations;
@@ -64,12 +65,12 @@ public class TransportDeleteIndexAction extends TransportMasterNodeAction<Delete
     }
 
     @Override
-    protected DeleteIndexResponse newResponse() {
-        return new DeleteIndexResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
-    protected void doExecute(Task task, DeleteIndexRequest request, ActionListener<DeleteIndexResponse> listener) {
+    protected void doExecute(Task task, DeleteIndexRequest request, ActionListener<AcknowledgedResponse> listener) {
         destructiveOperations.failDestructive(request.indices());
         super.doExecute(task, request, listener);
     }
@@ -80,10 +81,10 @@ public class TransportDeleteIndexAction extends TransportMasterNodeAction<Delete
     }
 
     @Override
-    protected void masterOperation(final DeleteIndexRequest request, final ClusterState state, final ActionListener<DeleteIndexResponse> listener) {
+    protected void masterOperation(final DeleteIndexRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         final Set<Index> concreteIndices = new HashSet<>(Arrays.asList(indexNameExpressionResolver.concreteIndices(state, request)));
         if (concreteIndices.isEmpty()) {
-            listener.onResponse(new DeleteIndexResponse(true));
+            listener.onResponse(new AcknowledgedResponse(true));
             return;
         }
 
@@ -95,7 +96,7 @@ public class TransportDeleteIndexAction extends TransportMasterNodeAction<Delete
 
             @Override
             public void onResponse(ClusterStateUpdateResponse response) {
-                listener.onResponse(new DeleteIndexResponse(response.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingAction.java
index 63ab198f816..ac845e6644c 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.mapping.put;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class PutMappingAction extends Action<PutMappingResponse> {
+public class PutMappingAction extends Action<AcknowledgedResponse> {
 
     public static final PutMappingAction INSTANCE = new PutMappingAction();
     public static final String NAME = "indices:admin/mapping/put";
@@ -31,7 +32,7 @@ public class PutMappingAction extends Action<PutMappingResponse> {
     }
 
     @Override
-    public PutMappingResponse newResponse() {
-        return new PutMappingResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java
index 3429b35073c..1556ee2341d 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java
@@ -27,6 +27,7 @@ import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.IndicesRequest;
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.master.AcknowledgedRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.bytes.BytesReference;
@@ -57,7 +58,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError;
  *
  * @see org.elasticsearch.client.Requests#putMappingRequest(String...)
  * @see org.elasticsearch.client.IndicesAdminClient#putMapping(PutMappingRequest)
- * @see PutMappingResponse
+ * @see AcknowledgedResponse
  */
 public class PutMappingRequest extends AcknowledgedRequest<PutMappingRequest> implements IndicesRequest.Replaceable, ToXContentObject {
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java
index 7baba39d96a..f0f39303c24 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.mapping.put;
 
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentType;
@@ -31,7 +32,8 @@ import java.util.Map;
 /**
  * Builder for a put mapping request
  */
-public class PutMappingRequestBuilder extends AcknowledgedRequestBuilder<PutMappingRequest, PutMappingResponse, PutMappingRequestBuilder> {
+public class PutMappingRequestBuilder
+    extends AcknowledgedRequestBuilder<PutMappingRequest, AcknowledgedResponse, PutMappingRequestBuilder> {
 
     public PutMappingRequestBuilder(ElasticsearchClient client, PutMappingAction action) {
         super(client, action, new PutMappingRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java
deleted file mode 100644
index 4b2eac95c3a..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.mapping.put;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * The response of put mapping operation.
- */
-public class PutMappingResponse extends AcknowledgedResponse {
-
-    protected PutMappingResponse() {
-    }
-
-    protected PutMappingResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static PutMappingResponse fromXContent(XContentParser parser) {
-        return new PutMappingResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java
index 38cd5efe13a..9f29ffe4883 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java
@@ -22,6 +22,7 @@ package org.elasticsearch.action.admin.indices.mapping.put;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -40,7 +41,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Put mapping action.
  */
-public class TransportPutMappingAction extends TransportMasterNodeAction<PutMappingRequest, PutMappingResponse> {
+public class TransportPutMappingAction extends TransportMasterNodeAction<PutMappingRequest, AcknowledgedResponse> {
 
     private final MetaDataMappingService metaDataMappingService;
 
@@ -59,8 +60,8 @@ public class TransportPutMappingAction extends TransportMasterNodeAction<PutMapp
     }
 
     @Override
-    protected PutMappingResponse newResponse() {
-        return new PutMappingResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -75,7 +76,7 @@ public class TransportPutMappingAction extends TransportMasterNodeAction<PutMapp
     }
 
     @Override
-    protected void masterOperation(final PutMappingRequest request, final ClusterState state, final ActionListener<PutMappingResponse> listener) {
+    protected void masterOperation(final PutMappingRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         try {
             final Index[] concreteIndices = request.getConcreteIndex() == null ? indexNameExpressionResolver.concreteIndices(state, request) : new Index[] {request.getConcreteIndex()};
             PutMappingClusterStateUpdateRequest updateRequest = new PutMappingClusterStateUpdateRequest()
@@ -87,7 +88,7 @@ public class TransportPutMappingAction extends TransportMasterNodeAction<PutMapp
 
                 @Override
                 public void onResponse(ClusterStateUpdateResponse response) {
-                    listener.onResponse(new PutMappingResponse(response.isAcknowledged()));
+                    listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
                 }
 
                 @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java
index 83eca833103..953129b5a37 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java
@@ -22,6 +22,7 @@ package org.elasticsearch.action.admin.indices.settings.put;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -37,7 +38,7 @@ import org.elasticsearch.index.Index;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 
-public class TransportUpdateSettingsAction extends TransportMasterNodeAction<UpdateSettingsRequest, UpdateSettingsResponse> {
+public class TransportUpdateSettingsAction extends TransportMasterNodeAction<UpdateSettingsRequest, AcknowledgedResponse> {
 
     private final MetaDataUpdateSettingsService updateSettingsService;
 
@@ -71,12 +72,12 @@ public class TransportUpdateSettingsAction extends TransportMasterNodeAction<Upd
     }
 
     @Override
-    protected UpdateSettingsResponse newResponse() {
-        return new UpdateSettingsResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
-    protected void masterOperation(final UpdateSettingsRequest request, final ClusterState state, final ActionListener<UpdateSettingsResponse> listener) {
+    protected void masterOperation(final UpdateSettingsRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         final Index[] concreteIndices = indexNameExpressionResolver.concreteIndices(state, request);
         UpdateSettingsClusterStateUpdateRequest clusterStateUpdateRequest = new UpdateSettingsClusterStateUpdateRequest()
                 .indices(concreteIndices)
@@ -88,7 +89,7 @@ public class TransportUpdateSettingsAction extends TransportMasterNodeAction<Upd
         updateSettingsService.updateSettings(clusterStateUpdateRequest, new ActionListener<ClusterStateUpdateResponse>() {
             @Override
             public void onResponse(ClusterStateUpdateResponse response) {
-                listener.onResponse(new UpdateSettingsResponse(response.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsAction.java
index 7f82c8f29e7..eb6574fb530 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.settings.put;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class UpdateSettingsAction extends Action<UpdateSettingsResponse> {
+public class UpdateSettingsAction extends Action<AcknowledgedResponse> {
 
     public static final UpdateSettingsAction INSTANCE = new UpdateSettingsAction();
     public static final String NAME = "indices:admin/settings/update";
@@ -31,7 +32,7 @@ public class UpdateSettingsAction extends Action<UpdateSettingsResponse> {
     }
 
     @Override
-    public UpdateSettingsResponse newResponse() {
-        return new UpdateSettingsResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequestBuilder.java
index 8cf86fadc16..834f3ba3014 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequestBuilder.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.settings.put;
 
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentType;
@@ -30,7 +31,7 @@ import java.util.Map;
 /**
  * Builder for an update index settings request
  */
-public class UpdateSettingsRequestBuilder extends AcknowledgedRequestBuilder<UpdateSettingsRequest, UpdateSettingsResponse, UpdateSettingsRequestBuilder> {
+public class UpdateSettingsRequestBuilder extends AcknowledgedRequestBuilder<UpdateSettingsRequest, AcknowledgedResponse, UpdateSettingsRequestBuilder> {
 
     public UpdateSettingsRequestBuilder(ElasticsearchClient client, UpdateSettingsAction action, String... indices) {
         super(client, action, new UpdateSettingsRequest(indices));
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsResponse.java
deleted file mode 100644
index 6792d185926..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsResponse.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.settings.put;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * A response for an update index settings action
- */
-public class UpdateSettingsResponse extends AcknowledgedResponse {
-
-    UpdateSettingsResponse() {
-    }
-
-    UpdateSettingsResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static UpdateSettingsResponse fromXContent(XContentParser parser) {
-        return new UpdateSettingsResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateAction.java
index 47f37b9e6cf..a8614277b40 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.template.delete;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class DeleteIndexTemplateAction extends Action<DeleteIndexTemplateResponse> {
+public class DeleteIndexTemplateAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteIndexTemplateAction INSTANCE = new DeleteIndexTemplateAction();
     public static final String NAME = "indices:admin/template/delete";
@@ -31,7 +32,7 @@ public class DeleteIndexTemplateAction extends Action<DeleteIndexTemplateRespons
     }
 
     @Override
-    public DeleteIndexTemplateResponse newResponse() {
-        return new DeleteIndexTemplateResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateRequestBuilder.java
index 620c432fe98..5f1119f0f0d 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateRequestBuilder.java
@@ -18,10 +18,11 @@
  */
 package org.elasticsearch.action.admin.indices.template.delete;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
 import org.elasticsearch.client.ElasticsearchClient;
 
-public class DeleteIndexTemplateRequestBuilder extends MasterNodeOperationRequestBuilder<DeleteIndexTemplateRequest, DeleteIndexTemplateResponse, DeleteIndexTemplateRequestBuilder> {
+public class DeleteIndexTemplateRequestBuilder extends MasterNodeOperationRequestBuilder<DeleteIndexTemplateRequest, AcknowledgedResponse, DeleteIndexTemplateRequestBuilder> {
 
     public DeleteIndexTemplateRequestBuilder(ElasticsearchClient client, DeleteIndexTemplateAction action) {
         super(client, action, new DeleteIndexTemplateRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateResponse.java
deleted file mode 100644
index a95f18bf13d..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/DeleteIndexTemplateResponse.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.action.admin.indices.template.delete;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-
-/**
- * A response for a delete index template.
- */
-public class DeleteIndexTemplateResponse extends AcknowledgedResponse {
-
-    DeleteIndexTemplateResponse() {
-    }
-
-    protected DeleteIndexTemplateResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java
index db5ddd326d7..7f9fc032106 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.template.delete;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -36,7 +37,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Delete index action.
  */
-public class TransportDeleteIndexTemplateAction extends TransportMasterNodeAction<DeleteIndexTemplateRequest, DeleteIndexTemplateResponse> {
+public class TransportDeleteIndexTemplateAction extends TransportMasterNodeAction<DeleteIndexTemplateRequest, AcknowledgedResponse> {
 
     private final MetaDataIndexTemplateService indexTemplateService;
 
@@ -55,8 +56,8 @@ public class TransportDeleteIndexTemplateAction extends TransportMasterNodeActio
     }
 
     @Override
-    protected DeleteIndexTemplateResponse newResponse() {
-        return new DeleteIndexTemplateResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -65,11 +66,11 @@ public class TransportDeleteIndexTemplateAction extends TransportMasterNodeActio
     }
 
     @Override
-    protected void masterOperation(final DeleteIndexTemplateRequest request, final ClusterState state, final ActionListener<DeleteIndexTemplateResponse> listener) {
+    protected void masterOperation(final DeleteIndexTemplateRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         indexTemplateService.removeTemplates(new MetaDataIndexTemplateService.RemoveRequest(request.name()).masterTimeout(request.masterNodeTimeout()), new MetaDataIndexTemplateService.RemoveListener() {
             @Override
             public void onResponse(MetaDataIndexTemplateService.RemoveResponse response) {
-                listener.onResponse(new DeleteIndexTemplateResponse(response.acknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.acknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateAction.java
index 399170eaece..1edc49e9914 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.template.put;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class PutIndexTemplateAction extends Action<PutIndexTemplateResponse> {
+public class PutIndexTemplateAction extends Action<AcknowledgedResponse> {
 
     public static final PutIndexTemplateAction INSTANCE = new PutIndexTemplateAction();
     public static final String NAME = "indices:admin/template/put";
@@ -31,7 +32,7 @@ public class PutIndexTemplateAction extends Action<PutIndexTemplateResponse> {
     }
 
     @Override
-    public PutIndexTemplateResponse newResponse() {
-        return new PutIndexTemplateResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateRequestBuilder.java
index 3c14b1ab18f..c10df6aafa5 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateRequestBuilder.java
@@ -19,6 +19,7 @@
 package org.elasticsearch.action.admin.indices.template.put;
 
 import org.elasticsearch.action.admin.indices.alias.Alias;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.common.bytes.BytesReference;
@@ -31,7 +32,7 @@ import java.util.List;
 import java.util.Map;
 
 public class PutIndexTemplateRequestBuilder
-    extends MasterNodeOperationRequestBuilder<PutIndexTemplateRequest, PutIndexTemplateResponse, PutIndexTemplateRequestBuilder> {
+    extends MasterNodeOperationRequestBuilder<PutIndexTemplateRequest, AcknowledgedResponse, PutIndexTemplateRequestBuilder> {
 
     public PutIndexTemplateRequestBuilder(ElasticsearchClient client, PutIndexTemplateAction action) {
         super(client, action, new PutIndexTemplateRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateResponse.java
deleted file mode 100644
index b2dab55a3d9..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateResponse.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.action.admin.indices.template.put;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-/**
- * A response for a put index template action.
- */
-public class PutIndexTemplateResponse extends AcknowledgedResponse {
-
-    protected PutIndexTemplateResponse() {
-    }
-
-    protected PutIndexTemplateResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static PutIndexTemplateResponse fromXContent(XContentParser parser) {
-        return new PutIndexTemplateResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java
index 7b46dc602d0..bd8621a1a7d 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.template.put;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -38,7 +39,7 @@ import org.elasticsearch.transport.TransportService;
 /**
  * Put index template action.
  */
-public class TransportPutIndexTemplateAction extends TransportMasterNodeAction<PutIndexTemplateRequest, PutIndexTemplateResponse> {
+public class TransportPutIndexTemplateAction extends TransportMasterNodeAction<PutIndexTemplateRequest, AcknowledgedResponse> {
 
     private final MetaDataIndexTemplateService indexTemplateService;
     private final IndexScopedSettings indexScopedSettings;
@@ -59,8 +60,8 @@ public class TransportPutIndexTemplateAction extends TransportMasterNodeAction<P
     }
 
     @Override
-    protected PutIndexTemplateResponse newResponse() {
-        return new PutIndexTemplateResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -69,7 +70,7 @@ public class TransportPutIndexTemplateAction extends TransportMasterNodeAction<P
     }
 
     @Override
-    protected void masterOperation(final PutIndexTemplateRequest request, final ClusterState state, final ActionListener<PutIndexTemplateResponse> listener) {
+    protected void masterOperation(final PutIndexTemplateRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         String cause = request.cause();
         if (cause.length() == 0) {
             cause = "api";
@@ -91,7 +92,7 @@ public class TransportPutIndexTemplateAction extends TransportMasterNodeAction<P
                 new MetaDataIndexTemplateService.PutListener() {
                     @Override
                     public void onResponse(MetaDataIndexTemplateService.PutResponse response) {
-                        listener.onResponse(new PutIndexTemplateResponse(response.acknowledged()));
+                        listener.onResponse(new AcknowledgedResponse(response.acknowledged()));
                     }
 
                     @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java
index dda4a5203ff..918b8a06056 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java
@@ -25,6 +25,7 @@ import org.elasticsearch.action.PrimaryMissingActionException;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.DefaultShardOperationFailedException;
 import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.node.NodeClient;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -205,9 +206,9 @@ public class TransportUpgradeAction extends TransportBroadcastByNodeAction<Upgra
 
     private void updateSettings(final UpgradeResponse upgradeResponse, final ActionListener<UpgradeResponse> listener) {
         UpgradeSettingsRequest upgradeSettingsRequest = new UpgradeSettingsRequest(upgradeResponse.versions());
-        client.executeLocally(UpgradeSettingsAction.INSTANCE, upgradeSettingsRequest, new ActionListener<UpgradeSettingsResponse>() {
+        client.executeLocally(UpgradeSettingsAction.INSTANCE, upgradeSettingsRequest, new ActionListener<AcknowledgedResponse>() {
             @Override
-            public void onResponse(UpgradeSettingsResponse updateSettingsResponse) {
+            public void onResponse(AcknowledgedResponse updateSettingsResponse) {
                 listener.onResponse(upgradeResponse);
             }
 
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java
index 2e428e85efc..7c4aa406b21 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java
@@ -22,6 +22,7 @@ package org.elasticsearch.action.admin.indices.upgrade.post;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
@@ -35,7 +36,7 @@ import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 
-public class TransportUpgradeSettingsAction extends TransportMasterNodeAction<UpgradeSettingsRequest, UpgradeSettingsResponse> {
+public class TransportUpgradeSettingsAction extends TransportMasterNodeAction<UpgradeSettingsRequest, AcknowledgedResponse> {
 
     private final MetaDataUpdateSettingsService updateSettingsService;
 
@@ -58,12 +59,12 @@ public class TransportUpgradeSettingsAction extends TransportMasterNodeAction<Up
     }
 
     @Override
-    protected UpgradeSettingsResponse newResponse() {
-        return new UpgradeSettingsResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
-    protected void masterOperation(final UpgradeSettingsRequest request, final ClusterState state, final ActionListener<UpgradeSettingsResponse> listener) {
+    protected void masterOperation(final UpgradeSettingsRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
         UpgradeSettingsClusterStateUpdateRequest clusterStateUpdateRequest = new UpgradeSettingsClusterStateUpdateRequest()
                 .ackTimeout(request.timeout())
                 .versions(request.versions())
@@ -72,7 +73,7 @@ public class TransportUpgradeSettingsAction extends TransportMasterNodeAction<Up
         updateSettingsService.upgradeIndexSettings(clusterStateUpdateRequest, new ActionListener<ClusterStateUpdateResponse>() {
             @Override
             public void onResponse(ClusterStateUpdateResponse response) {
-                listener.onResponse(new UpgradeSettingsResponse(response.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(response.isAcknowledged()));
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsAction.java
index 5f1ee88e34e..9b1ff0f616a 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsAction.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsAction.java
@@ -20,8 +20,9 @@
 package org.elasticsearch.action.admin.indices.upgrade.post;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class UpgradeSettingsAction extends Action<UpgradeSettingsResponse> {
+public class UpgradeSettingsAction extends Action<AcknowledgedResponse> {
 
     public static final UpgradeSettingsAction INSTANCE = new UpgradeSettingsAction();
     public static final String NAME = "internal:indices/admin/upgrade";
@@ -31,7 +32,7 @@ public class UpgradeSettingsAction extends Action<UpgradeSettingsResponse> {
     }
 
     @Override
-    public UpgradeSettingsResponse newResponse() {
-        return new UpgradeSettingsResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsRequestBuilder.java b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsRequestBuilder.java
index 9ce5aeb2d2d..e3a48066bbf 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsRequestBuilder.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsRequestBuilder.java
@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.upgrade.post;
 
 import org.elasticsearch.Version;
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.common.collect.Tuple;
 
@@ -29,7 +30,7 @@ import java.util.Map;
 /**
  * Builder for an update index settings request
  */
-public class UpgradeSettingsRequestBuilder extends AcknowledgedRequestBuilder<UpgradeSettingsRequest, UpgradeSettingsResponse, UpgradeSettingsRequestBuilder> {
+public class UpgradeSettingsRequestBuilder extends AcknowledgedRequestBuilder<UpgradeSettingsRequest, AcknowledgedResponse, UpgradeSettingsRequestBuilder> {
 
     public UpgradeSettingsRequestBuilder(ElasticsearchClient client, UpgradeSettingsAction action) {
         super(client, action, new UpgradeSettingsRequest());
diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsResponse.java
deleted file mode 100644
index 0d3ac16a6fe..00000000000
--- a/server/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/UpgradeSettingsResponse.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.upgrade.post;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-
-/**
- * A response for an update index settings action
- */
-public class UpgradeSettingsResponse extends AcknowledgedResponse {
-
-    UpgradeSettingsResponse() {
-    }
-
-    UpgradeSettingsResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-}
diff --git a/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java b/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java
index 654b398e79c..21a0d3f21a8 100644
--- a/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java
+++ b/server/src/main/java/org/elasticsearch/action/support/master/AcknowledgedResponse.java
@@ -98,11 +98,6 @@ public class AcknowledgedResponse extends ActionResponse implements ToXContentOb
                 ObjectParser.ValueType.BOOLEAN);
     }
 
-    @Deprecated
-    public static boolean parseAcknowledged(XContentParser parser) {
-        return ACKNOWLEDGED_FLAG_PARSER.apply(parser, null);
-    }
-
     public static AcknowledgedResponse fromXContent(XContentParser parser) throws IOException {
         return new AcknowledgedResponse(ACKNOWLEDGED_FLAG_PARSER.apply(parser, null));
     }
diff --git a/server/src/main/java/org/elasticsearch/client/ClusterAdminClient.java b/server/src/main/java/org/elasticsearch/client/ClusterAdminClient.java
index f6c71c90f9d..624c7999637 100644
--- a/server/src/main/java/org/elasticsearch/client/ClusterAdminClient.java
+++ b/server/src/main/java/org/elasticsearch/client/ClusterAdminClient.java
@@ -51,13 +51,11 @@ import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequestBuilde
 import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageResponse;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequestBuilder;
-import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequestBuilder;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequestBuilder;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequestBuilder;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
@@ -75,7 +73,6 @@ import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotReq
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequestBuilder;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequestBuilder;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
@@ -93,13 +90,11 @@ import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequestBuilder;
 import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequestBuilder;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequestBuilder;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequestBuilder;
-import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksRequest;
 import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksRequestBuilder;
 import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksResponse;
@@ -416,12 +411,12 @@ public interface ClusterAdminClient extends ElasticsearchClient {
     /**
      * Registers a snapshot repository.
      */
-    ActionFuture<PutRepositoryResponse> putRepository(PutRepositoryRequest request);
+    ActionFuture<AcknowledgedResponse> putRepository(PutRepositoryRequest request);
 
     /**
      * Registers a snapshot repository.
      */
-    void putRepository(PutRepositoryRequest request, ActionListener<PutRepositoryResponse> listener);
+    void putRepository(PutRepositoryRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Registers a snapshot repository.
@@ -431,12 +426,12 @@ public interface ClusterAdminClient extends ElasticsearchClient {
     /**
      * Unregisters a repository.
      */
-    ActionFuture<DeleteRepositoryResponse> deleteRepository(DeleteRepositoryRequest request);
+    ActionFuture<AcknowledgedResponse> deleteRepository(DeleteRepositoryRequest request);
 
     /**
      * Unregisters a repository.
      */
-    void deleteRepository(DeleteRepositoryRequest request, ActionListener<DeleteRepositoryResponse> listener);
+    void deleteRepository(DeleteRepositoryRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Unregisters a repository.
@@ -506,12 +501,12 @@ public interface ClusterAdminClient extends ElasticsearchClient {
     /**
      * Delete snapshot.
      */
-    ActionFuture<DeleteSnapshotResponse> deleteSnapshot(DeleteSnapshotRequest request);
+    ActionFuture<AcknowledgedResponse> deleteSnapshot(DeleteSnapshotRequest request);
 
     /**
      * Delete snapshot.
      */
-    void deleteSnapshot(DeleteSnapshotRequest request, ActionListener<DeleteSnapshotResponse> listener);
+    void deleteSnapshot(DeleteSnapshotRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Delete snapshot.
@@ -672,12 +667,12 @@ public interface ClusterAdminClient extends ElasticsearchClient {
     /**
      * Delete a script from the cluster state
      */
-    void deleteStoredScript(DeleteStoredScriptRequest request, ActionListener<DeleteStoredScriptResponse> listener);
+    void deleteStoredScript(DeleteStoredScriptRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Delete a script from the cluster state
      */
-    ActionFuture<DeleteStoredScriptResponse> deleteStoredScript(DeleteStoredScriptRequest request);
+    ActionFuture<AcknowledgedResponse> deleteStoredScript(DeleteStoredScriptRequest request);
 
     /**
      * Delete a script from the cluster state
@@ -692,12 +687,12 @@ public interface ClusterAdminClient extends ElasticsearchClient {
     /**
      * Store a script in the cluster state
      */
-    void putStoredScript(PutStoredScriptRequest request, ActionListener<PutStoredScriptResponse> listener);
+    void putStoredScript(PutStoredScriptRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Store a script in the cluster state
      */
-    ActionFuture<PutStoredScriptResponse> putStoredScript(PutStoredScriptRequest request);
+    ActionFuture<AcknowledgedResponse> putStoredScript(PutStoredScriptRequest request);
 
     /**
      * Get a script from the cluster state
diff --git a/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java b/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java
index 81de57f91af..60e9334c87d 100644
--- a/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java
+++ b/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java
@@ -23,7 +23,6 @@ import org.elasticsearch.action.ActionFuture;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistRequestBuilder;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistResponse;
 import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
@@ -37,13 +36,11 @@ import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheReque
 import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequestBuilder;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
@@ -70,7 +67,6 @@ import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequestBuil
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequestBuilder;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
@@ -91,7 +87,6 @@ import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequestBui
 import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequestBuilder;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.admin.indices.shards.IndicesShardStoreRequestBuilder;
 import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresRequest;
 import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresResponse;
@@ -103,13 +98,11 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequestBuilder;
 import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequestBuilder;
-import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequestBuilder;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequestBuilder;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusRequest;
 import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusRequestBuilder;
 import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusResponse;
@@ -119,6 +112,7 @@ import org.elasticsearch.action.admin.indices.upgrade.post.UpgradeResponse;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequestBuilder;
 import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.Nullable;
 
 /**
@@ -281,7 +275,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @return The result future
      * @see org.elasticsearch.client.Requests#deleteIndexRequest(String)
      */
-    ActionFuture<DeleteIndexResponse> delete(DeleteIndexRequest request);
+    ActionFuture<AcknowledgedResponse> delete(DeleteIndexRequest request);
 
     /**
      * Deletes an index based on the index name.
@@ -290,7 +284,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @param listener A listener to be notified with a result
      * @see org.elasticsearch.client.Requests#deleteIndexRequest(String)
      */
-    void delete(DeleteIndexRequest request, ActionListener<DeleteIndexResponse> listener);
+    void delete(DeleteIndexRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Deletes an index based on the index name.
@@ -306,7 +300,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @return The result future
      * @see org.elasticsearch.client.Requests#closeIndexRequest(String)
      */
-    ActionFuture<CloseIndexResponse> close(CloseIndexRequest request);
+    ActionFuture<AcknowledgedResponse> close(CloseIndexRequest request);
 
     /**
      * Closes an index based on the index name.
@@ -315,7 +309,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @param listener A listener to be notified with a result
      * @see org.elasticsearch.client.Requests#closeIndexRequest(String)
      */
-    void close(CloseIndexRequest request, ActionListener<CloseIndexResponse> listener);
+    void close(CloseIndexRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Closes one or more indices based on their index name.
@@ -524,7 +518,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @return A result future
      * @see org.elasticsearch.client.Requests#putMappingRequest(String...)
      */
-    ActionFuture<PutMappingResponse> putMapping(PutMappingRequest request);
+    ActionFuture<AcknowledgedResponse> putMapping(PutMappingRequest request);
 
     /**
      * Add mapping definition for a type into one or more indices.
@@ -533,7 +527,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @param listener A listener to be notified with a result
      * @see org.elasticsearch.client.Requests#putMappingRequest(String...)
      */
-    void putMapping(PutMappingRequest request, ActionListener<PutMappingResponse> listener);
+    void putMapping(PutMappingRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Add mapping definition for a type into one or more indices.
@@ -547,7 +541,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @return The result future
      * @see Requests#indexAliasesRequest()
      */
-    ActionFuture<IndicesAliasesResponse> aliases(IndicesAliasesRequest request);
+    ActionFuture<AcknowledgedResponse> aliases(IndicesAliasesRequest request);
 
     /**
      * Allows to add/remove aliases from indices.
@@ -556,7 +550,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @param listener A listener to be notified with a result
      * @see Requests#indexAliasesRequest()
      */
-    void aliases(IndicesAliasesRequest request, ActionListener<IndicesAliasesResponse> listener);
+    void aliases(IndicesAliasesRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Allows to add/remove aliases from indices.
@@ -652,7 +646,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @param request the update settings request
      * @return The result future
      */
-    ActionFuture<UpdateSettingsResponse> updateSettings(UpdateSettingsRequest request);
+    ActionFuture<AcknowledgedResponse> updateSettings(UpdateSettingsRequest request);
 
     /**
      * Updates settings of one or more indices.
@@ -660,7 +654,7 @@ public interface IndicesAdminClient extends ElasticsearchClient {
      * @param request  the update settings request
      * @param listener A listener to be notified with the response
      */
-    void updateSettings(UpdateSettingsRequest request, ActionListener<UpdateSettingsResponse> listener);
+    void updateSettings(UpdateSettingsRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Update indices settings.
@@ -701,12 +695,12 @@ public interface IndicesAdminClient extends ElasticsearchClient {
     /**
      * Puts an index template.
      */
-    ActionFuture<PutIndexTemplateResponse> putTemplate(PutIndexTemplateRequest request);
+    ActionFuture<AcknowledgedResponse> putTemplate(PutIndexTemplateRequest request);
 
     /**
      * Puts an index template.
      */
-    void putTemplate(PutIndexTemplateRequest request, ActionListener<PutIndexTemplateResponse> listener);
+    void putTemplate(PutIndexTemplateRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Puts an index template.
@@ -718,12 +712,12 @@ public interface IndicesAdminClient extends ElasticsearchClient {
     /**
      * Deletes index template.
      */
-    ActionFuture<DeleteIndexTemplateResponse> deleteTemplate(DeleteIndexTemplateRequest request);
+    ActionFuture<AcknowledgedResponse> deleteTemplate(DeleteIndexTemplateRequest request);
 
     /**
      * Deletes an index template.
      */
-    void deleteTemplate(DeleteIndexTemplateRequest request, ActionListener<DeleteIndexTemplateResponse> listener);
+    void deleteTemplate(DeleteIndexTemplateRequest request, ActionListener<AcknowledgedResponse> listener);
 
     /**
      * Deletes an index template.
diff --git a/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java b/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java
index 3d508a3d9ba..86d9d2c445f 100644
--- a/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java
+++ b/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java
@@ -65,7 +65,6 @@ import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageResponse;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryAction;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequestBuilder;
-import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesAction;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequestBuilder;
@@ -73,7 +72,6 @@ import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRe
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryAction;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequestBuilder;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryAction;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequestBuilder;
@@ -97,7 +95,6 @@ import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRes
 import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotAction;
 import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequestBuilder;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsAction;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequestBuilder;
@@ -121,7 +118,6 @@ import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptAction;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequestBuilder;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptAction;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequestBuilder;
@@ -129,7 +125,6 @@ import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRespo
 import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptAction;
 import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequestBuilder;
-import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksAction;
 import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksRequest;
 import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksRequestBuilder;
@@ -137,7 +132,6 @@ import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksResponse;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistAction;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistRequestBuilder;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistResponse;
@@ -156,7 +150,6 @@ import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRespo
 import org.elasticsearch.action.admin.indices.close.CloseIndexAction;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequestBuilder;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
@@ -164,7 +157,6 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsAction;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
@@ -200,7 +192,6 @@ import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexAction;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequestBuilder;
@@ -228,7 +219,6 @@ import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsAction;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequestBuilder;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.admin.indices.shards.IndicesShardStoreRequestBuilder;
 import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresAction;
 import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresRequest;
@@ -244,7 +234,6 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateAction;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequestBuilder;
-import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequestBuilder;
@@ -252,7 +241,6 @@ import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResp
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequestBuilder;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusAction;
 import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusRequest;
 import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusRequestBuilder;
@@ -939,12 +927,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<PutRepositoryResponse> putRepository(PutRepositoryRequest request) {
+        public ActionFuture<AcknowledgedResponse> putRepository(PutRepositoryRequest request) {
             return execute(PutRepositoryAction.INSTANCE, request);
         }
 
         @Override
-        public void putRepository(PutRepositoryRequest request, ActionListener<PutRepositoryResponse> listener) {
+        public void putRepository(PutRepositoryRequest request, ActionListener<AcknowledgedResponse> listener) {
             execute(PutRepositoryAction.INSTANCE, request, listener);
         }
 
@@ -985,12 +973,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
 
 
         @Override
-        public ActionFuture<DeleteSnapshotResponse> deleteSnapshot(DeleteSnapshotRequest request) {
+        public ActionFuture<AcknowledgedResponse> deleteSnapshot(DeleteSnapshotRequest request) {
             return execute(DeleteSnapshotAction.INSTANCE, request);
         }
 
         @Override
-        public void deleteSnapshot(DeleteSnapshotRequest request, ActionListener<DeleteSnapshotResponse> listener) {
+        public void deleteSnapshot(DeleteSnapshotRequest request, ActionListener<AcknowledgedResponse> listener) {
             execute(DeleteSnapshotAction.INSTANCE, request, listener);
         }
 
@@ -1001,12 +989,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
 
 
         @Override
-        public ActionFuture<DeleteRepositoryResponse> deleteRepository(DeleteRepositoryRequest request) {
+        public ActionFuture<AcknowledgedResponse> deleteRepository(DeleteRepositoryRequest request) {
             return execute(DeleteRepositoryAction.INSTANCE, request);
         }
 
         @Override
-        public void deleteRepository(DeleteRepositoryRequest request, ActionListener<DeleteRepositoryResponse> listener) {
+        public void deleteRepository(DeleteRepositoryRequest request, ActionListener<AcknowledgedResponse> listener) {
             execute(DeleteRepositoryAction.INSTANCE, request, listener);
         }
 
@@ -1197,23 +1185,23 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public void putStoredScript(final PutStoredScriptRequest request, ActionListener<PutStoredScriptResponse> listener){
+        public void putStoredScript(final PutStoredScriptRequest request, ActionListener<AcknowledgedResponse> listener){
             execute(PutStoredScriptAction.INSTANCE, request, listener);
 
         }
 
         @Override
-        public ActionFuture<PutStoredScriptResponse> putStoredScript(final PutStoredScriptRequest request){
+        public ActionFuture<AcknowledgedResponse> putStoredScript(final PutStoredScriptRequest request){
             return execute(PutStoredScriptAction.INSTANCE, request);
         }
 
         @Override
-        public void deleteStoredScript(DeleteStoredScriptRequest request, ActionListener<DeleteStoredScriptResponse> listener){
+        public void deleteStoredScript(DeleteStoredScriptRequest request, ActionListener<AcknowledgedResponse> listener){
             execute(DeleteStoredScriptAction.INSTANCE, request, listener);
         }
 
         @Override
-        public ActionFuture<DeleteStoredScriptResponse> deleteStoredScript(DeleteStoredScriptRequest request){
+        public ActionFuture<AcknowledgedResponse> deleteStoredScript(DeleteStoredScriptRequest request){
             return execute(DeleteStoredScriptAction.INSTANCE, request);
         }
 
@@ -1284,12 +1272,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<IndicesAliasesResponse> aliases(final IndicesAliasesRequest request) {
+        public ActionFuture<AcknowledgedResponse> aliases(final IndicesAliasesRequest request) {
             return execute(IndicesAliasesAction.INSTANCE, request);
         }
 
         @Override
-        public void aliases(final IndicesAliasesRequest request, final ActionListener<IndicesAliasesResponse> listener) {
+        public void aliases(final IndicesAliasesRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(IndicesAliasesAction.INSTANCE, request, listener);
         }
 
@@ -1374,12 +1362,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<DeleteIndexResponse> delete(final DeleteIndexRequest request) {
+        public ActionFuture<AcknowledgedResponse> delete(final DeleteIndexRequest request) {
             return execute(DeleteIndexAction.INSTANCE, request);
         }
 
         @Override
-        public void delete(final DeleteIndexRequest request, final ActionListener<DeleteIndexResponse> listener) {
+        public void delete(final DeleteIndexRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(DeleteIndexAction.INSTANCE, request, listener);
         }
 
@@ -1389,12 +1377,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<CloseIndexResponse> close(final CloseIndexRequest request) {
+        public ActionFuture<AcknowledgedResponse> close(final CloseIndexRequest request) {
             return execute(CloseIndexAction.INSTANCE, request);
         }
 
         @Override
-        public void close(final CloseIndexRequest request, final ActionListener<CloseIndexResponse> listener) {
+        public void close(final CloseIndexRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(CloseIndexAction.INSTANCE, request, listener);
         }
 
@@ -1479,12 +1467,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<PutMappingResponse> putMapping(final PutMappingRequest request) {
+        public ActionFuture<AcknowledgedResponse> putMapping(final PutMappingRequest request) {
             return execute(PutMappingAction.INSTANCE, request);
         }
 
         @Override
-        public void putMapping(final PutMappingRequest request, final ActionListener<PutMappingResponse> listener) {
+        public void putMapping(final PutMappingRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(PutMappingAction.INSTANCE, request, listener);
         }
 
@@ -1614,12 +1602,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<UpdateSettingsResponse> updateSettings(final UpdateSettingsRequest request) {
+        public ActionFuture<AcknowledgedResponse> updateSettings(final UpdateSettingsRequest request) {
             return execute(UpdateSettingsAction.INSTANCE, request);
         }
 
         @Override
-        public void updateSettings(final UpdateSettingsRequest request, final ActionListener<UpdateSettingsResponse> listener) {
+        public void updateSettings(final UpdateSettingsRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(UpdateSettingsAction.INSTANCE, request, listener);
         }
 
@@ -1654,12 +1642,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<PutIndexTemplateResponse> putTemplate(final PutIndexTemplateRequest request) {
+        public ActionFuture<AcknowledgedResponse> putTemplate(final PutIndexTemplateRequest request) {
             return execute(PutIndexTemplateAction.INSTANCE, request);
         }
 
         @Override
-        public void putTemplate(final PutIndexTemplateRequest request, final ActionListener<PutIndexTemplateResponse> listener) {
+        public void putTemplate(final PutIndexTemplateRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(PutIndexTemplateAction.INSTANCE, request, listener);
         }
 
@@ -1684,12 +1672,12 @@ public abstract class AbstractClient extends AbstractComponent implements Client
         }
 
         @Override
-        public ActionFuture<DeleteIndexTemplateResponse> deleteTemplate(final DeleteIndexTemplateRequest request) {
+        public ActionFuture<AcknowledgedResponse> deleteTemplate(final DeleteIndexTemplateRequest request) {
             return execute(DeleteIndexTemplateAction.INSTANCE, request);
         }
 
         @Override
-        public void deleteTemplate(final DeleteIndexTemplateRequest request, final ActionListener<DeleteIndexTemplateResponse> listener) {
+        public void deleteTemplate(final DeleteIndexTemplateRequest request, final ActionListener<AcknowledgedResponse> listener) {
             execute(DeleteIndexTemplateAction.INSTANCE, request, listener);
         }
 
diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java
index 024cc44dd6a..af8289d03c1 100644
--- a/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java
+++ b/server/src/main/java/org/elasticsearch/cluster/metadata/TemplateUpgradeService.java
@@ -24,9 +24,8 @@ import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterChangedEvent;
 import org.elasticsearch.cluster.ClusterState;
@@ -147,9 +146,9 @@ public class TemplateUpgradeService extends AbstractComponent implements Cluster
             PutIndexTemplateRequest request =
                 new PutIndexTemplateRequest(change.getKey()).source(change.getValue(), XContentType.JSON);
             request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
-            client.admin().indices().putTemplate(request, new ActionListener<PutIndexTemplateResponse>() {
+            client.admin().indices().putTemplate(request, new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(PutIndexTemplateResponse response) {
+                public void onResponse(AcknowledgedResponse response) {
                     if (response.isAcknowledged() == false) {
                         anyUpgradeFailed.set(true);
                         logger.warn("Error updating template [{}], request was not acknowledged", change.getKey());
@@ -169,9 +168,9 @@ public class TemplateUpgradeService extends AbstractComponent implements Cluster
         for (String template : deletions) {
             DeleteIndexTemplateRequest request = new DeleteIndexTemplateRequest(template);
             request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
-            client.admin().indices().deleteTemplate(request, new ActionListener<DeleteIndexTemplateResponse>() {
+            client.admin().indices().deleteTemplate(request, new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(DeleteIndexTemplateResponse response) {
+                public void onResponse(AcknowledgedResponse response) {
                     if (response.isAcknowledged() == false) {
                         anyUpgradeFailed.set(true);
                         logger.warn("Error deleting template [{}], request was not acknowledged", template);
diff --git a/server/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java b/server/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java
index 03a0f3b42a1..de8691b3b68 100644
--- a/server/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java
+++ b/server/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java
@@ -297,13 +297,13 @@ public final class ClusterSettings extends AbstractScopedSettings {
                     TcpTransport.TCP_REUSE_ADDRESS_PROFILE,
                     TcpTransport.TCP_SEND_BUFFER_SIZE_PROFILE,
                     TcpTransport.TCP_RECEIVE_BUFFER_SIZE_PROFILE,
-                    TcpTransport.CONNECTIONS_PER_NODE_RECOVERY,
-                    TcpTransport.CONNECTIONS_PER_NODE_BULK,
-                    TcpTransport.CONNECTIONS_PER_NODE_REG,
-                    TcpTransport.CONNECTIONS_PER_NODE_STATE,
-                    TcpTransport.CONNECTIONS_PER_NODE_PING,
+                    TransportService.CONNECTIONS_PER_NODE_RECOVERY,
+                    TransportService.CONNECTIONS_PER_NODE_BULK,
+                    TransportService.CONNECTIONS_PER_NODE_REG,
+                    TransportService.CONNECTIONS_PER_NODE_STATE,
+                    TransportService.CONNECTIONS_PER_NODE_PING,
+                    TransportService.TCP_CONNECT_TIMEOUT,
                     TcpTransport.PING_SCHEDULE,
-                    TcpTransport.TCP_CONNECT_TIMEOUT,
                     NetworkService.NETWORK_SERVER,
                     TcpTransport.TCP_NO_DELAY,
                     TcpTransport.TCP_KEEP_ALIVE,
diff --git a/server/src/main/java/org/elasticsearch/index/shard/GlobalCheckpointListeners.java b/server/src/main/java/org/elasticsearch/index/shard/GlobalCheckpointListeners.java
new file mode 100644
index 00000000000..e279badec4a
--- /dev/null
+++ b/server/src/main/java/org/elasticsearch/index/shard/GlobalCheckpointListeners.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.shard;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.message.ParameterizedMessage;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+import static org.elasticsearch.index.seqno.SequenceNumbers.NO_OPS_PERFORMED;
+import static org.elasticsearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO;
+
+/**
+ * Represents a collection of global checkpoint listeners. This collection can be added to, and all listeners present at the time of an
+ * update will be notified together. All listeners will be notified when the shard is closed.
+ */
+public class GlobalCheckpointListeners implements Closeable {
+
+    /**
+     * A global checkpoint listener consisting of a callback that is notified when the global checkpoint is updated or the shard is closed.
+     */
+    @FunctionalInterface
+    public interface GlobalCheckpointListener {
+        /**
+         * Callback when the global checkpoint is updated or the shard is closed. If the shard is closed, the value of the global checkpoint
+         * will be set to {@link org.elasticsearch.index.seqno.SequenceNumbers#UNASSIGNED_SEQ_NO} and the exception will be non-null. If the
+         * global checkpoint is updated, the exception will be null.
+         *
+         * @param globalCheckpoint the updated global checkpoint
+         * @param e                if non-null, the shard is closed
+         */
+        void accept(long globalCheckpoint, IndexShardClosedException e);
+    }
+
+    // guarded by this
+    private boolean closed;
+    private volatile List<GlobalCheckpointListener> listeners;
+    private long lastKnownGlobalCheckpoint = UNASSIGNED_SEQ_NO;
+
+    private final ShardId shardId;
+    private final Executor executor;
+    private final Logger logger;
+
+    /**
+     * Construct a global checkpoint listeners collection.
+     *
+     * @param shardId  the shard ID on which global checkpoint updates can be listened to
+     * @param executor the executor for listener notifications
+     * @param logger   a shard-level logger
+     */
+    GlobalCheckpointListeners(
+            final ShardId shardId,
+            final Executor executor,
+            final Logger logger) {
+        this.shardId = Objects.requireNonNull(shardId);
+        this.executor = Objects.requireNonNull(executor);
+        this.logger = Objects.requireNonNull(logger);
+    }
+
+    /**
+     * Add a global checkpoint listener. If the global checkpoint is above the current global checkpoint known to the listener then the
+     * listener will be asynchronously notified on the executor used to construct this collection of global checkpoint listeners. If the
+     * shard is closed then the listener will be asynchronously notified on the executor used to construct this collection of global
+     * checkpoint listeners. The listener will only be notified of at most one event, either the global checkpoint is updated or the shard
+     * is closed. A listener must re-register after one of these events to receive subsequent events.
+     *
+     * @param currentGlobalCheckpoint the current global checkpoint known to the listener
+     * @param listener                the listener
+     */
+    synchronized void add(final long currentGlobalCheckpoint, final GlobalCheckpointListener listener) {
+        if (closed) {
+            executor.execute(() -> notifyListener(listener, UNASSIGNED_SEQ_NO, new IndexShardClosedException(shardId)));
+            return;
+        }
+        if (lastKnownGlobalCheckpoint > currentGlobalCheckpoint) {
+            // notify directly
+            executor.execute(() -> notifyListener(listener, lastKnownGlobalCheckpoint, null));
+            return;
+        } else {
+            if (listeners == null) {
+                listeners = new ArrayList<>();
+            }
+            listeners.add(listener);
+        }
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        closed = true;
+        notifyListeners(UNASSIGNED_SEQ_NO, new IndexShardClosedException(shardId));
+    }
+
+    synchronized int pendingListeners() {
+        return listeners == null ? 0 : listeners.size();
+    }
+
+    /**
+     * Invoke to notify all registered listeners of an updated global checkpoint.
+     *
+     * @param globalCheckpoint the updated global checkpoint
+     */
+    synchronized void globalCheckpointUpdated(final long globalCheckpoint) {
+        assert globalCheckpoint >= NO_OPS_PERFORMED;
+        assert globalCheckpoint > lastKnownGlobalCheckpoint
+                : "updated global checkpoint [" + globalCheckpoint + "]"
+                + " is not more than the last known global checkpoint [" + lastKnownGlobalCheckpoint + "]";
+        lastKnownGlobalCheckpoint = globalCheckpoint;
+        notifyListeners(globalCheckpoint, null);
+    }
+
+    private void notifyListeners(final long globalCheckpoint, final IndexShardClosedException e) {
+        assert Thread.holdsLock(this);
+        assert (globalCheckpoint == UNASSIGNED_SEQ_NO && e != null) || (globalCheckpoint >= NO_OPS_PERFORMED && e == null);
+        if (listeners != null) {
+            // capture the current listeners
+            final List<GlobalCheckpointListener> currentListeners = listeners;
+            listeners = null;
+            if (currentListeners != null) {
+                executor.execute(() -> {
+                    for (final GlobalCheckpointListener listener : currentListeners) {
+                        notifyListener(listener, globalCheckpoint, e);
+                    }
+                });
+            }
+        }
+    }
+
+    private void notifyListener(final GlobalCheckpointListener listener, final long globalCheckpoint, final IndexShardClosedException e) {
+        try {
+            listener.accept(globalCheckpoint, e);
+        } catch (final Exception caught) {
+            if (globalCheckpoint != UNASSIGNED_SEQ_NO) {
+                logger.warn(
+                        new ParameterizedMessage(
+                                "error notifying global checkpoint listener of updated global checkpoint [{}]",
+                                globalCheckpoint),
+                        caught);
+            } else {
+                logger.warn("error notifying global checkpoint listener of closed shard", caught);
+            }
+        }
+    }
+
+}
diff --git a/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java
index 76510a756a6..25073d7ce15 100644
--- a/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java
+++ b/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java
@@ -163,6 +163,8 @@ import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
 import static org.elasticsearch.index.mapper.SourceToParse.source;
+import static org.elasticsearch.index.seqno.SequenceNumbers.NO_OPS_PERFORMED;
+import static org.elasticsearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO;
 
 public class IndexShard extends AbstractIndexShardComponent implements IndicesClusterStateService.Shard {
 
@@ -191,6 +193,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
 
     private final SearchOperationListener searchOperationListener;
 
+    private final GlobalCheckpointListeners globalCheckpointListeners;
     private final ReplicationTracker replicationTracker;
 
     protected volatile ShardRouting shardRouting;
@@ -300,8 +303,10 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
         this.checkIndexOnStartup = indexSettings.getValue(IndexSettings.INDEX_CHECK_ON_STARTUP);
         this.translogConfig = new TranslogConfig(shardId, shardPath().resolveTranslog(), indexSettings, bigArrays);
         final String aId = shardRouting.allocationId().getId();
+        this.globalCheckpointListeners = new GlobalCheckpointListeners(shardId, threadPool.executor(ThreadPool.Names.LISTENER), logger);
         this.replicationTracker =
-                new ReplicationTracker(shardId, aId, indexSettings, SequenceNumbers.UNASSIGNED_SEQ_NO, globalCheckpoint -> {});
+                new ReplicationTracker(shardId, aId, indexSettings, UNASSIGNED_SEQ_NO, globalCheckpointListeners::globalCheckpointUpdated);
+
         // the query cache is a node-level thing, however we want the most popular filters
         // to be computed on a per-shard basis
         if (IndexModule.INDEX_QUERY_CACHE_EVERYTHING_SETTING.get(settings)) {
@@ -671,7 +676,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
     public Engine.IndexResult applyIndexOperationOnPrimary(long version, VersionType versionType, SourceToParse sourceToParse,
                                                            long autoGeneratedTimestamp, boolean isRetry) throws IOException {
         assert versionType.validateVersionForWrites(version);
-        return applyIndexOperation(SequenceNumbers.UNASSIGNED_SEQ_NO, operationPrimaryTerm, version, versionType, autoGeneratedTimestamp,
+        return applyIndexOperation(UNASSIGNED_SEQ_NO, operationPrimaryTerm, version, versionType, autoGeneratedTimestamp,
             isRetry, Engine.Operation.Origin.PRIMARY, sourceToParse);
     }
 
@@ -772,7 +777,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
     public Engine.DeleteResult applyDeleteOperationOnPrimary(long version, String type, String id, VersionType versionType)
         throws IOException {
         assert versionType.validateVersionForWrites(version);
-        return applyDeleteOperation(SequenceNumbers.UNASSIGNED_SEQ_NO, operationPrimaryTerm, version, type, id, versionType,
+        return applyDeleteOperation(UNASSIGNED_SEQ_NO, operationPrimaryTerm, version, type, id, versionType,
             Engine.Operation.Origin.PRIMARY);
     }
 
@@ -1199,7 +1204,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
                 } finally {
                     // playing safe here and close the engine even if the above succeeds - close can be called multiple times
                     // Also closing refreshListeners to prevent us from accumulating any more listeners
-                    IOUtils.close(engine, refreshListeners);
+                    IOUtils.close(engine, globalCheckpointListeners, refreshListeners);
                     indexShardOperationPermits.close();
                 }
             }
@@ -1771,6 +1776,19 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
         replicationTracker.updateGlobalCheckpointForShard(allocationId, globalCheckpoint);
     }
 
+    /**
+     * Add a global checkpoint listener. If the global checkpoint is above the current global checkpoint known to the listener then the
+     * listener will fire immediately on the calling thread.
+     *
+     * @param currentGlobalCheckpoint the current global checkpoint known to the listener
+     * @param listener                the listener
+     */
+    public void addGlobalCheckpointListener(
+            final long currentGlobalCheckpoint,
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener) {
+        this.globalCheckpointListeners.add(currentGlobalCheckpoint, listener);
+    }
+
     /**
      * Waits for all operations up to the provided sequence number to complete.
      *
@@ -2315,8 +2333,8 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
                                 updateGlobalCheckpointOnReplica(globalCheckpoint, "primary term transition");
                                 final long currentGlobalCheckpoint = getGlobalCheckpoint();
                                 final long localCheckpoint;
-                                if (currentGlobalCheckpoint == SequenceNumbers.UNASSIGNED_SEQ_NO) {
-                                    localCheckpoint = SequenceNumbers.NO_OPS_PERFORMED;
+                                if (currentGlobalCheckpoint == UNASSIGNED_SEQ_NO) {
+                                    localCheckpoint = NO_OPS_PERFORMED;
                                 } else {
                                     localCheckpoint = currentGlobalCheckpoint;
                                 }
diff --git a/server/src/main/java/org/elasticsearch/script/ScriptService.java b/server/src/main/java/org/elasticsearch/script/ScriptService.java
index 9768547b898..d37cefb3a01 100644
--- a/server/src/main/java/org/elasticsearch/script/ScriptService.java
+++ b/server/src/main/java/org/elasticsearch/script/ScriptService.java
@@ -19,14 +19,12 @@
 
 package org.elasticsearch.script;
 
-import org.elasticsearch.core.internal.io.IOUtils;
 import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
 import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
 import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
 import org.elasticsearch.cluster.ClusterChangedEvent;
 import org.elasticsearch.cluster.ClusterState;
@@ -46,6 +44,7 @@ import org.elasticsearch.common.settings.Setting;
 import org.elasticsearch.common.settings.Setting.Property;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.core.internal.io.IOUtils;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -417,7 +416,7 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
     }
 
     public void putStoredScript(ClusterService clusterService, PutStoredScriptRequest request,
-                                ActionListener<PutStoredScriptResponse> listener) {
+                                ActionListener<AcknowledgedResponse> listener) {
         int max = SCRIPT_MAX_SIZE_IN_BYTES.get(settings);
 
         if (request.content().length() > max) {
@@ -454,11 +453,11 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
         }
 
         clusterService.submitStateUpdateTask("put-script-" + request.id(),
-            new AckedClusterStateUpdateTask<PutStoredScriptResponse>(request, listener) {
+            new AckedClusterStateUpdateTask<AcknowledgedResponse>(request, listener) {
 
             @Override
-            protected PutStoredScriptResponse newResponse(boolean acknowledged) {
-                return new PutStoredScriptResponse(acknowledged);
+            protected AcknowledgedResponse newResponse(boolean acknowledged) {
+                return new AcknowledgedResponse(acknowledged);
             }
 
             @Override
@@ -473,13 +472,13 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
     }
 
     public void deleteStoredScript(ClusterService clusterService, DeleteStoredScriptRequest request,
-                                   ActionListener<DeleteStoredScriptResponse> listener) {
+                                   ActionListener<AcknowledgedResponse> listener) {
         clusterService.submitStateUpdateTask("delete-script-" + request.id(),
-            new AckedClusterStateUpdateTask<DeleteStoredScriptResponse>(request, listener) {
+            new AckedClusterStateUpdateTask<AcknowledgedResponse>(request, listener) {
 
             @Override
-            protected DeleteStoredScriptResponse newResponse(boolean acknowledged) {
-                return new DeleteStoredScriptResponse(acknowledged);
+            protected AcknowledgedResponse newResponse(boolean acknowledged) {
+                return new AcknowledgedResponse(acknowledged);
             }
 
             @Override
diff --git a/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java b/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java
index b94902132fe..1a837f7d6d9 100644
--- a/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java
+++ b/server/src/main/java/org/elasticsearch/tasks/TaskResultsService.java
@@ -25,9 +25,9 @@ import org.elasticsearch.ResourceAlreadyExistsException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.Requests;
 import org.elasticsearch.cluster.ClusterState;
@@ -113,9 +113,9 @@ public class TaskResultsService extends AbstractComponent {
                 // The index already exists but doesn't have our mapping
                 client.admin().indices().preparePutMapping(TASK_INDEX).setType(TASK_TYPE)
                     .setSource(taskResultIndexMapping(), XContentType.JSON)
-                    .execute(new ActionListener<PutMappingResponse>() {
+                    .execute(new ActionListener<AcknowledgedResponse>() {
                                  @Override
-                                 public void onResponse(PutMappingResponse putMappingResponse) {
+                                 public void onResponse(AcknowledgedResponse putMappingResponse) {
                                      doStoreResult(taskResult, listener);
                                  }
 
diff --git a/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java b/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java
index f2b89ff5977..1ff8b701a83 100644
--- a/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java
+++ b/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java
@@ -60,15 +60,21 @@ public class ConnectionManager implements Closeable {
     private final Transport transport;
     private final ThreadPool threadPool;
     private final TimeValue pingSchedule;
+    private final ConnectionProfile defaultProfile;
     private final Lifecycle lifecycle = new Lifecycle();
     private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
     private final DelegatingNodeConnectionListener connectionListener = new DelegatingNodeConnectionListener();
 
     public ConnectionManager(Settings settings, Transport transport, ThreadPool threadPool) {
+        this(settings, transport, threadPool, buildDefaultConnectionProfile(settings));
+    }
+
+    public ConnectionManager(Settings settings, Transport transport, ThreadPool threadPool, ConnectionProfile defaultProfile) {
         this.logger = Loggers.getLogger(getClass(), settings);
         this.transport = transport;
         this.threadPool = threadPool;
         this.pingSchedule = TcpTransport.PING_SCHEDULE.get(settings);
+        this.defaultProfile = defaultProfile;
         this.lifecycle.moveToStarted();
 
         if (pingSchedule.millis() > 0) {
@@ -84,6 +90,10 @@ public class ConnectionManager implements Closeable {
         this.connectionListener.listeners.remove(listener);
     }
 
+    public Transport.Connection openConnection(DiscoveryNode node, ConnectionProfile connectionProfile) {
+        return transport.openConnection(node, ConnectionProfile.resolveConnectionProfile(connectionProfile, defaultProfile));
+    }
+
     /**
      * Connects to a node with the given connection profile. If the node is already connected this method has no effect.
      * Once a successful is established, it can be validated before being exposed.
@@ -91,6 +101,7 @@ public class ConnectionManager implements Closeable {
     public void connectToNode(DiscoveryNode node, ConnectionProfile connectionProfile,
                               CheckedBiConsumer<Transport.Connection, ConnectionProfile, IOException> connectionValidator)
         throws ConnectTransportException {
+        ConnectionProfile resolvedProfile = ConnectionProfile.resolveConnectionProfile(connectionProfile, defaultProfile);
         if (node == null) {
             throw new ConnectTransportException(null, "can't connect to a null node");
         }
@@ -104,8 +115,8 @@ public class ConnectionManager implements Closeable {
                 }
                 boolean success = false;
                 try {
-                    connection = transport.openConnection(node, connectionProfile);
-                    connectionValidator.accept(connection, connectionProfile);
+                    connection = transport.openConnection(node, resolvedProfile);
+                    connectionValidator.accept(connection, resolvedProfile);
                     // we acquire a connection lock, so no way there is an existing connection
                     connectedNodes.put(node, connection);
                     if (logger.isDebugEnabled()) {
@@ -279,4 +290,23 @@ public class ConnectionManager implements Closeable {
             }
         }
     }
+
+    static ConnectionProfile buildDefaultConnectionProfile(Settings settings) {
+        int connectionsPerNodeRecovery = TransportService.CONNECTIONS_PER_NODE_RECOVERY.get(settings);
+        int connectionsPerNodeBulk = TransportService.CONNECTIONS_PER_NODE_BULK.get(settings);
+        int connectionsPerNodeReg = TransportService.CONNECTIONS_PER_NODE_REG.get(settings);
+        int connectionsPerNodeState = TransportService.CONNECTIONS_PER_NODE_STATE.get(settings);
+        int connectionsPerNodePing = TransportService.CONNECTIONS_PER_NODE_PING.get(settings);
+        ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
+        builder.setConnectTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings));
+        builder.setHandshakeTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings));
+        builder.addConnections(connectionsPerNodeBulk, TransportRequestOptions.Type.BULK);
+        builder.addConnections(connectionsPerNodePing, TransportRequestOptions.Type.PING);
+        // if we are not master eligible we don't need a dedicated channel to publish the state
+        builder.addConnections(DiscoveryNode.isMasterNode(settings) ? connectionsPerNodeState : 0, TransportRequestOptions.Type.STATE);
+        // if we are not a data-node we don't need any dedicated channels for recovery
+        builder.addConnections(DiscoveryNode.isDataNode(settings) ? connectionsPerNodeRecovery : 0, TransportRequestOptions.Type.RECOVERY);
+        builder.addConnections(connectionsPerNodeReg, TransportRequestOptions.Type.REG);
+        return builder.build();
+    }
 }
diff --git a/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java b/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java
index e14f684bf72..b9ed42ca00a 100644
--- a/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java
+++ b/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -61,14 +62,35 @@ public final class ConnectionProfile {
     private final TimeValue connectTimeout;
     private final TimeValue handshakeTimeout;
 
-    private ConnectionProfile(List<ConnectionTypeHandle> handles, int numConnections, TimeValue connectTimeout, TimeValue handshakeTimeout)
-    {
+    private ConnectionProfile(List<ConnectionTypeHandle> handles, int numConnections, TimeValue connectTimeout,
+                              TimeValue handshakeTimeout) {
         this.handles = handles;
         this.numConnections = numConnections;
         this.connectTimeout = connectTimeout;
         this.handshakeTimeout = handshakeTimeout;
     }
 
+    /**
+     * takes a {@link ConnectionProfile} resolves it to a fully specified (i.e., no nulls) profile
+     */
+    public static ConnectionProfile resolveConnectionProfile(@Nullable ConnectionProfile profile, ConnectionProfile fallbackProfile) {
+        Objects.requireNonNull(fallbackProfile);
+        if (profile == null) {
+            return fallbackProfile;
+        } else if (profile.getConnectTimeout() != null && profile.getHandshakeTimeout() != null) {
+            return profile;
+        } else {
+            ConnectionProfile.Builder builder = new ConnectionProfile.Builder(profile);
+            if (profile.getConnectTimeout() == null) {
+                builder.setConnectTimeout(fallbackProfile.getConnectTimeout());
+            }
+            if (profile.getHandshakeTimeout() == null) {
+                builder.setHandshakeTimeout(fallbackProfile.getHandshakeTimeout());
+            }
+            return builder.build();
+        }
+    }
+
     /**
      * A builder to build a new {@link ConnectionProfile}
      */
diff --git a/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java b/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java
index 355a9c655c9..67c0e1a5aa6 100644
--- a/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java
+++ b/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java
@@ -108,8 +108,8 @@ final class RemoteClusterConnection extends AbstractComponent implements Transpo
         this.nodePredicate = nodePredicate;
         this.clusterAlias = clusterAlias;
         ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
-        builder.setConnectTimeout(TcpTransport.TCP_CONNECT_TIMEOUT.get(settings));
-        builder.setHandshakeTimeout(TcpTransport.TCP_CONNECT_TIMEOUT.get(settings));
+        builder.setConnectTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings));
+        builder.setHandshakeTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings));
         builder.addConnections(6, TransportRequestOptions.Type.REG, TransportRequestOptions.Type.PING); // TODO make this configurable?
         builder.addConnections(0, // we don't want this to be used for anything else but search
             TransportRequestOptions.Type.BULK,
diff --git a/server/src/main/java/org/elasticsearch/transport/TcpTransport.java b/server/src/main/java/org/elasticsearch/transport/TcpTransport.java
index 064c76cc03f..0b82417cfaa 100644
--- a/server/src/main/java/org/elasticsearch/transport/TcpTransport.java
+++ b/server/src/main/java/org/elasticsearch/transport/TcpTransport.java
@@ -29,7 +29,6 @@ import org.elasticsearch.action.NotifyOnceListener;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.cluster.node.DiscoveryNode;
 import org.elasticsearch.common.Booleans;
-import org.elasticsearch.common.Nullable;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.breaker.CircuitBreaker;
 import org.elasticsearch.common.bytes.BytesArray;
@@ -135,18 +134,6 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
     // the scheduled internal ping interval setting, defaults to disabled (-1)
     public static final Setting<TimeValue> PING_SCHEDULE =
         timeSetting("transport.ping_schedule", TimeValue.timeValueSeconds(-1), Setting.Property.NodeScope);
-    public static final Setting<Integer> CONNECTIONS_PER_NODE_RECOVERY =
-        intSetting("transport.connections_per_node.recovery", 2, 1, Setting.Property.NodeScope);
-    public static final Setting<Integer> CONNECTIONS_PER_NODE_BULK =
-        intSetting("transport.connections_per_node.bulk", 3, 1, Setting.Property.NodeScope);
-    public static final Setting<Integer> CONNECTIONS_PER_NODE_REG =
-        intSetting("transport.connections_per_node.reg", 6, 1, Setting.Property.NodeScope);
-    public static final Setting<Integer> CONNECTIONS_PER_NODE_STATE =
-        intSetting("transport.connections_per_node.state", 1, 1, Setting.Property.NodeScope);
-    public static final Setting<Integer> CONNECTIONS_PER_NODE_PING =
-        intSetting("transport.connections_per_node.ping", 1, 1, Setting.Property.NodeScope);
-    public static final Setting<TimeValue> TCP_CONNECT_TIMEOUT =
-        timeSetting("transport.tcp.connect_timeout", NetworkService.TCP_CONNECT_TIMEOUT, Setting.Property.NodeScope);
     public static final Setting<Boolean> TCP_NO_DELAY =
         boolSetting("transport.tcp_no_delay", NetworkService.TCP_NO_DELAY, Setting.Property.NodeScope);
     public static final Setting<Boolean> TCP_KEEP_ALIVE =
@@ -154,11 +141,9 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
     public static final Setting<Boolean> TCP_REUSE_ADDRESS =
         boolSetting("transport.tcp.reuse_address", NetworkService.TCP_REUSE_ADDRESS, Setting.Property.NodeScope);
     public static final Setting<ByteSizeValue> TCP_SEND_BUFFER_SIZE =
-        Setting.byteSizeSetting("transport.tcp.send_buffer_size", NetworkService.TCP_SEND_BUFFER_SIZE,
-            Setting.Property.NodeScope);
+        Setting.byteSizeSetting("transport.tcp.send_buffer_size", NetworkService.TCP_SEND_BUFFER_SIZE, Setting.Property.NodeScope);
     public static final Setting<ByteSizeValue> TCP_RECEIVE_BUFFER_SIZE =
-        Setting.byteSizeSetting("transport.tcp.receive_buffer_size", NetworkService.TCP_RECEIVE_BUFFER_SIZE,
-            Setting.Property.NodeScope);
+        Setting.byteSizeSetting("transport.tcp.receive_buffer_size", NetworkService.TCP_RECEIVE_BUFFER_SIZE, Setting.Property.NodeScope);
 
 
     public static final Setting.AffixSetting<Boolean> TCP_NO_DELAY_PROFILE = affixKeySetting("transport.profiles.", "tcp_no_delay",
@@ -213,7 +198,6 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
     protected final boolean compress;
     private volatile BoundTransportAddress boundAddress;
     private final String transportName;
-    protected final ConnectionProfile defaultConnectionProfile;
 
     private final ConcurrentMap<Long, HandshakeResponseHandler> pendingHandshakes = new ConcurrentHashMap<>();
     private final CounterMetric numHandshakes = new CounterMetric();
@@ -237,7 +221,6 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
         this.compress = Transport.TRANSPORT_TCP_COMPRESS.get(settings);
         this.networkService = networkService;
         this.transportName = transportName;
-        defaultConnectionProfile = buildDefaultConnectionProfile(settings);
         final Settings defaultFeatures = DEFAULT_FEATURES_SETTING.get(settings);
         if (defaultFeatures == null) {
             this.features = new String[0];
@@ -261,25 +244,6 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
         }
     }
 
-    static ConnectionProfile buildDefaultConnectionProfile(Settings settings) {
-        int connectionsPerNodeRecovery = CONNECTIONS_PER_NODE_RECOVERY.get(settings);
-        int connectionsPerNodeBulk = CONNECTIONS_PER_NODE_BULK.get(settings);
-        int connectionsPerNodeReg = CONNECTIONS_PER_NODE_REG.get(settings);
-        int connectionsPerNodeState = CONNECTIONS_PER_NODE_STATE.get(settings);
-        int connectionsPerNodePing = CONNECTIONS_PER_NODE_PING.get(settings);
-        ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
-        builder.setConnectTimeout(TCP_CONNECT_TIMEOUT.get(settings));
-        builder.setHandshakeTimeout(TCP_CONNECT_TIMEOUT.get(settings));
-        builder.addConnections(connectionsPerNodeBulk, TransportRequestOptions.Type.BULK);
-        builder.addConnections(connectionsPerNodePing, TransportRequestOptions.Type.PING);
-        // if we are not master eligible we don't need a dedicated channel to publish the state
-        builder.addConnections(DiscoveryNode.isMasterNode(settings) ? connectionsPerNodeState : 0, TransportRequestOptions.Type.STATE);
-        // if we are not a data-node we don't need any dedicated channels for recovery
-        builder.addConnections(DiscoveryNode.isDataNode(settings) ? connectionsPerNodeRecovery : 0, TransportRequestOptions.Type.RECOVERY);
-        builder.addConnections(connectionsPerNodeReg, TransportRequestOptions.Type.REG);
-        return builder.build();
-    }
-
     @Override
     protected void doStart() {
     }
@@ -456,41 +420,21 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
         }
     }
 
-    /**
-     * takes a {@link ConnectionProfile} that have been passed as a parameter to the public methods
-     * and resolves it to a fully specified (i.e., no nulls) profile
-     */
-    protected static ConnectionProfile resolveConnectionProfile(@Nullable ConnectionProfile connectionProfile,
-                                                      ConnectionProfile defaultConnectionProfile) {
-        Objects.requireNonNull(defaultConnectionProfile);
-        if (connectionProfile == null) {
-            return defaultConnectionProfile;
-        } else if (connectionProfile.getConnectTimeout() != null && connectionProfile.getHandshakeTimeout() != null) {
-            return connectionProfile;
-        } else {
-            ConnectionProfile.Builder builder = new ConnectionProfile.Builder(connectionProfile);
-            if (connectionProfile.getConnectTimeout() == null) {
-                builder.setConnectTimeout(defaultConnectionProfile.getConnectTimeout());
-            }
-            if (connectionProfile.getHandshakeTimeout() == null) {
-                builder.setHandshakeTimeout(defaultConnectionProfile.getHandshakeTimeout());
-            }
-            return builder.build();
-        }
-    }
-
-    protected ConnectionProfile resolveConnectionProfile(ConnectionProfile connectionProfile) {
-        return resolveConnectionProfile(connectionProfile, defaultConnectionProfile);
+    // This allows transport implementations to potentially override specific connection profiles. This
+    // primarily exists for the test implementations.
+    protected ConnectionProfile maybeOverrideConnectionProfile(ConnectionProfile connectionProfile) {
+        return connectionProfile;
     }
 
     @Override
     public NodeChannels openConnection(DiscoveryNode node, ConnectionProfile connectionProfile) {
+        Objects.requireNonNull(connectionProfile, "connection profile cannot be null");
         if (node == null) {
             throw new ConnectTransportException(null, "can't open connection to a null node");
         }
         boolean success = false;
         NodeChannels nodeChannels = null;
-        connectionProfile = resolveConnectionProfile(connectionProfile);
+        connectionProfile = maybeOverrideConnectionProfile(connectionProfile);
         closeLock.readLock().lock(); // ensure we don't open connections while we are closing
         try {
             ensureOpen();
diff --git a/server/src/main/java/org/elasticsearch/transport/TransportService.java b/server/src/main/java/org/elasticsearch/transport/TransportService.java
index d7ece36d7fd..8eca6504b70 100644
--- a/server/src/main/java/org/elasticsearch/transport/TransportService.java
+++ b/server/src/main/java/org/elasticsearch/transport/TransportService.java
@@ -36,6 +36,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
 import org.elasticsearch.common.io.stream.Streamable;
 import org.elasticsearch.common.io.stream.Writeable;
 import org.elasticsearch.common.logging.Loggers;
+import org.elasticsearch.common.network.NetworkService;
 import org.elasticsearch.common.regex.Regex;
 import org.elasticsearch.common.settings.ClusterSettings;
 import org.elasticsearch.common.settings.Setting;
@@ -43,6 +44,7 @@ import org.elasticsearch.common.settings.Setting.Property;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.transport.BoundTransportAddress;
 import org.elasticsearch.common.transport.TransportAddress;
+import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.util.concurrent.AbstractRunnable;
 import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
 import org.elasticsearch.common.util.concurrent.FutureUtils;
@@ -71,10 +73,24 @@ import java.util.function.Predicate;
 import java.util.function.Supplier;
 
 import static java.util.Collections.emptyList;
+import static org.elasticsearch.common.settings.Setting.intSetting;
 import static org.elasticsearch.common.settings.Setting.listSetting;
+import static org.elasticsearch.common.settings.Setting.timeSetting;
 
 public class TransportService extends AbstractLifecycleComponent implements TransportConnectionListener {
 
+    public static final Setting<Integer> CONNECTIONS_PER_NODE_RECOVERY =
+        intSetting("transport.connections_per_node.recovery", 2, 1, Setting.Property.NodeScope);
+    public static final Setting<Integer> CONNECTIONS_PER_NODE_BULK =
+        intSetting("transport.connections_per_node.bulk", 3, 1, Setting.Property.NodeScope);
+    public static final Setting<Integer> CONNECTIONS_PER_NODE_REG =
+        intSetting("transport.connections_per_node.reg", 6, 1, Setting.Property.NodeScope);
+    public static final Setting<Integer> CONNECTIONS_PER_NODE_STATE =
+        intSetting("transport.connections_per_node.state", 1, 1, Setting.Property.NodeScope);
+    public static final Setting<Integer> CONNECTIONS_PER_NODE_PING =
+        intSetting("transport.connections_per_node.ping", 1, 1, Setting.Property.NodeScope);
+    public static final Setting<TimeValue> TCP_CONNECT_TIMEOUT =
+        timeSetting("transport.tcp.connect_timeout", NetworkService.TCP_CONNECT_TIMEOUT, Setting.Property.NodeScope);
     public static final String DIRECT_RESPONSE_PROFILE = ".direct";
     public static final String HANDSHAKE_ACTION_NAME = "internal:transport/handshake";
 
@@ -111,7 +127,6 @@ public class TransportService extends AbstractLifecycleComponent implements Tran
             Function.identity(), Property.Dynamic, Property.NodeScope);
 
     private final Logger tracerLog;
-    private final ConnectionProfile defaultConnectionProfile;
 
     volatile String[] tracerLogInclude;
     volatile String[] tracerLogExclude;
@@ -182,7 +197,6 @@ public class TransportService extends AbstractLifecycleComponent implements Tran
         this.connectToRemoteCluster = RemoteClusterService.ENABLE_REMOTE_CLUSTERS.get(settings);
         remoteClusterService = new RemoteClusterService(settings, this);
         responseHandlers = transport.getResponseHandlers();
-        defaultConnectionProfile = TcpTransport.buildDefaultConnectionProfile(settings);
         if (clusterSettings != null) {
             clusterSettings.addSettingsUpdateConsumer(TRACE_LOG_INCLUDE_SETTING, this::setTracerLogInclude);
             clusterSettings.addSettingsUpdateConsumer(TRACE_LOG_EXCLUDE_SETTING, this::setTracerLogExclude);
@@ -350,8 +364,7 @@ public class TransportService extends AbstractLifecycleComponent implements Tran
             return;
         }
 
-        ConnectionProfile resolvedProfile = TcpTransport.resolveConnectionProfile(connectionProfile, defaultConnectionProfile);
-        connectionManager.connectToNode(node, resolvedProfile, (newConnection, actualProfile) -> {
+        connectionManager.connectToNode(node, connectionProfile, (newConnection, actualProfile) -> {
             // We don't validate cluster names to allow for CCS connections.
             final DiscoveryNode remote = handshake(newConnection, actualProfile.getHandshakeTimeout().millis(), cn -> true).discoveryNode;
             if (validateConnections && node.equals(remote) == false) {
@@ -364,13 +377,13 @@ public class TransportService extends AbstractLifecycleComponent implements Tran
      * Establishes and returns a new connection to the given node. The connection is NOT maintained by this service, it's the callers
      * responsibility to close the connection once it goes out of scope.
      * @param node the node to connect to
-     * @param profile the connection profile to use
+     * @param connectionProfile the connection profile to use
      */
-    public Transport.Connection openConnection(final DiscoveryNode node, ConnectionProfile profile) throws IOException {
+    public Transport.Connection openConnection(final DiscoveryNode node, ConnectionProfile connectionProfile) throws IOException {
         if (isLocalNode(node)) {
             return localNodeConnection;
         } else {
-            return transport.openConnection(node, profile);
+            return connectionManager.openConnection(node, connectionProfile);
         }
     }
 
diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryResponseTests.java
deleted file mode 100644
index fe97e778dad..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/delete/DeleteRepositoryResponseTests.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.action.admin.cluster.repositories.delete;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class DeleteRepositoryResponseTests extends AbstractStreamableXContentTestCase<DeleteRepositoryResponse> {
-
-    @Override
-    protected DeleteRepositoryResponse doParseInstance(XContentParser parser) {
-        return DeleteRepositoryResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected DeleteRepositoryResponse createBlankInstance() {
-        return new DeleteRepositoryResponse();
-    }
-
-    @Override
-    protected DeleteRepositoryResponse createTestInstance() {
-        return new DeleteRepositoryResponse(randomBoolean());
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryResponseTests.java
deleted file mode 100644
index a4dbc6a9d9b..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/cluster/repositories/put/PutRepositoryResponseTests.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.action.admin.cluster.repositories.put;
-
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-import java.io.IOException;
-
-import static org.elasticsearch.test.ESTestCase.randomBoolean;
-
-public class PutRepositoryResponseTests extends AbstractStreamableXContentTestCase<PutRepositoryResponse> {
-
-    @Override
-    protected PutRepositoryResponse doParseInstance(XContentParser parser) throws IOException {
-        return PutRepositoryResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected PutRepositoryResponse createBlankInstance() {
-        return new PutRepositoryResponse();
-    }
-
-    @Override
-    protected PutRepositoryResponse createTestInstance() {
-        return new PutRepositoryResponse(randomBoolean());
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponseTests.java
deleted file mode 100644
index d77dadfb81e..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/cluster/snapshots/delete/DeleteSnapshotResponseTests.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.cluster.snapshots.delete;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class DeleteSnapshotResponseTests extends AbstractStreamableXContentTestCase<DeleteSnapshotResponse> {
-
-    @Override
-    protected DeleteSnapshotResponse doParseInstance(XContentParser parser) {
-        return DeleteSnapshotResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected DeleteSnapshotResponse createBlankInstance() {
-        return new DeleteSnapshotResponse();
-    }
-
-    @Override
-    protected DeleteSnapshotResponse createTestInstance() {
-        return new DeleteSnapshotResponse(randomBoolean());
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java
deleted file mode 100644
index 375a6722630..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.elasticsearch.action.admin.cluster.storedscripts;/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-import java.io.IOException;
-
-public class DeleteStoredScriptResponseTests extends AbstractStreamableXContentTestCase<DeleteStoredScriptResponse> {
-
-    @Override
-    protected DeleteStoredScriptResponse doParseInstance(XContentParser parser) throws IOException {
-        return DeleteStoredScriptResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected DeleteStoredScriptResponse createBlankInstance() {
-        return new DeleteStoredScriptResponse();
-    }
-
-    @Override
-    protected DeleteStoredScriptResponse createTestInstance() {
-        return new DeleteStoredScriptResponse(randomBoolean());
-    }
-
-    @Override
-    protected DeleteStoredScriptResponse mutateInstance(DeleteStoredScriptResponse instance) throws IOException {
-        return new DeleteStoredScriptResponse(instance.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesResponseTests.java
deleted file mode 100644
index b3eb9c81e8f..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/alias/IndicesAliasesResponseTests.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.alias;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class IndicesAliasesResponseTests extends AbstractStreamableXContentTestCase<IndicesAliasesResponse> {
-
-    @Override
-    protected IndicesAliasesResponse doParseInstance(XContentParser parser) {
-        return IndicesAliasesResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected IndicesAliasesResponse createTestInstance() {
-        return new IndicesAliasesResponse(randomBoolean());
-    }
-
-    @Override
-    protected IndicesAliasesResponse createBlankInstance() {
-        return new IndicesAliasesResponse();
-    }
-
-    @Override
-    protected IndicesAliasesResponse mutateInstance(IndicesAliasesResponse response) {
-        return new IndicesAliasesResponse(response.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java
deleted file mode 100644
index 3dd4f1e68ce..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/close/CloseIndexResponseTests.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.close;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class CloseIndexResponseTests extends AbstractStreamableXContentTestCase<CloseIndexResponse> {
-
-    @Override
-    protected CloseIndexResponse doParseInstance(XContentParser parser) {
-        return CloseIndexResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected CloseIndexResponse createTestInstance() {
-        return new CloseIndexResponse(randomBoolean());
-    }
-
-    @Override
-    protected CloseIndexResponse createBlankInstance() {
-        return new CloseIndexResponse();
-    }
-
-    @Override
-    protected CloseIndexResponse mutateInstance(CloseIndexResponse response) {
-        return new CloseIndexResponse(response.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexIT.java b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexIT.java
index c27d9ef65b2..ee49486eab0 100644
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexIT.java
+++ b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexIT.java
@@ -24,10 +24,10 @@ import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.UnavailableShardsException;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.ActiveShardCount;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.cluster.metadata.MetaData;
@@ -207,9 +207,9 @@ public class CreateIndexIT extends ESIntegTestCase {
         synchronized (indexVersionLock) { // not necessarily needed here but for completeness we lock here too
             indexVersion.incrementAndGet();
         }
-        client().admin().indices().prepareDelete("test").execute(new ActionListener<DeleteIndexResponse>() { // this happens async!!!
+        client().admin().indices().prepareDelete("test").execute(new ActionListener<AcknowledgedResponse>() { // this happens async!!!
                 @Override
-                public void onResponse(DeleteIndexResponse deleteIndexResponse) {
+                public void onResponse(AcknowledgedResponse deleteIndexResponse) {
                     Thread thread = new Thread() {
                      @Override
                     public void run() {
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponseTests.java
deleted file mode 100644
index 4f3313e3d6b..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/delete/DeleteIndexResponseTests.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.delete;
-
-import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class DeleteIndexResponseTests extends AbstractStreamableXContentTestCase<DeleteIndexResponse> {
-
-    public void testToXContent() {
-        DeleteIndexResponse response = new DeleteIndexResponse(true);
-        String output = Strings.toString(response);
-        assertEquals("{\"acknowledged\":true}", output);
-    }
-
-    @Override
-    protected DeleteIndexResponse doParseInstance(XContentParser parser) {
-        return DeleteIndexResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected DeleteIndexResponse createTestInstance() {
-        return new DeleteIndexResponse(randomBoolean());
-    }
-
-    @Override
-    protected DeleteIndexResponse createBlankInstance() {
-        return new DeleteIndexResponse();
-    }
-
-    @Override
-    protected DeleteIndexResponse mutateInstance(DeleteIndexResponse response) {
-        return new DeleteIndexResponse(response.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java
deleted file mode 100644
index d687b251e34..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.mapping.put;
-
-import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class PutMappingResponseTests extends AbstractStreamableXContentTestCase<PutMappingResponse> {
-
-    public void testToXContent() {
-        PutMappingResponse response = new PutMappingResponse(true);
-        String output = Strings.toString(response);
-        assertEquals("{\"acknowledged\":true}", output);
-    }
-
-    @Override
-    protected PutMappingResponse doParseInstance(XContentParser parser) {
-        return PutMappingResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected PutMappingResponse createTestInstance() {
-        return new PutMappingResponse(randomBoolean());
-    }
-
-    @Override
-    protected PutMappingResponse createBlankInstance() {
-        return new PutMappingResponse();
-    }
-
-    @Override
-    protected PutMappingResponse mutateInstance(PutMappingResponse response) {
-        return new PutMappingResponse(response.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsResponseTests.java
deleted file mode 100644
index a3fb484f02e..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsResponseTests.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.settings.put;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class UpdateSettingsResponseTests extends AbstractStreamableXContentTestCase<UpdateSettingsResponse> {
-
-    @Override
-    protected UpdateSettingsResponse doParseInstance(XContentParser parser) {
-        return UpdateSettingsResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected UpdateSettingsResponse createTestInstance() {
-        return new UpdateSettingsResponse(randomBoolean());
-    }
-
-    @Override
-    protected UpdateSettingsResponse createBlankInstance() {
-        return new UpdateSettingsResponse();
-    }
-
-    @Override
-    protected UpdateSettingsResponse mutateInstance(UpdateSettingsResponse response) {
-        return new UpdateSettingsResponse(response.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateResponseTests.java
deleted file mode 100644
index 096d62bf2bb..00000000000
--- a/server/src/test/java/org/elasticsearch/action/admin/indices/template/put/PutIndexTemplateResponseTests.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.action.admin.indices.template.put;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class PutIndexTemplateResponseTests extends AbstractStreamableXContentTestCase<PutIndexTemplateResponse> {
-    @Override
-    protected PutIndexTemplateResponse doParseInstance(XContentParser parser) {
-        return PutIndexTemplateResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected PutIndexTemplateResponse createTestInstance() {
-        return new PutIndexTemplateResponse(randomBoolean());
-    }
-
-    @Override
-    protected PutIndexTemplateResponse createBlankInstance() {
-        return new PutIndexTemplateResponse();
-    }
-
-    @Override
-    protected PutIndexTemplateResponse mutateInstance(PutIndexTemplateResponse response) {
-        return new PutIndexTemplateResponse(response.isAcknowledged() == false);
-    }
-}
diff --git a/server/src/test/java/org/elasticsearch/blocks/SimpleBlocksIT.java b/server/src/test/java/org/elasticsearch/blocks/SimpleBlocksIT.java
index 699b919cf05..9009b3592f8 100644
--- a/server/src/test/java/org/elasticsearch/blocks/SimpleBlocksIT.java
+++ b/server/src/test/java/org/elasticsearch/blocks/SimpleBlocksIT.java
@@ -22,9 +22,9 @@ package org.elasticsearch.blocks;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
 import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequestBuilder;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.block.ClusterBlockException;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.common.settings.Settings;
@@ -147,7 +147,7 @@ public class SimpleBlocksIT extends ESIntegTestCase {
 
         UpdateSettingsRequestBuilder settingsRequest = client().admin().indices().prepareUpdateSettings(index);
         settingsRequest.setSettings(newSettings);
-        UpdateSettingsResponse settingsResponse = settingsRequest.execute().actionGet();
+        AcknowledgedResponse settingsResponse = settingsRequest.execute().actionGet();
         assertThat(settingsResponse, notNullValue());
     }
 }
diff --git a/server/src/test/java/org/elasticsearch/cluster/ack/AckClusterUpdateSettingsIT.java b/server/src/test/java/org/elasticsearch/cluster/ack/AckClusterUpdateSettingsIT.java
index a11ceddf287..274c48748fe 100644
--- a/server/src/test/java/org/elasticsearch/cluster/ack/AckClusterUpdateSettingsIT.java
+++ b/server/src/test/java/org/elasticsearch/cluster/ack/AckClusterUpdateSettingsIT.java
@@ -22,9 +22,9 @@ package org.elasticsearch.cluster.ack;
 import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
 import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
 import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.routing.IndexRoutingTable;
@@ -163,7 +163,7 @@ public class AckClusterUpdateSettingsIT extends ESIntegTestCase {
         createIndex("test");
         ensureGreen();
         removePublishTimeout();
-        CloseIndexResponse closeIndexResponse = client().admin().indices().prepareClose("test").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client().admin().indices().prepareClose("test").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
 
         OpenIndexResponse openIndexResponse = client().admin().indices().prepareOpen("test").setTimeout("0s").get();
diff --git a/server/src/test/java/org/elasticsearch/cluster/ack/AckIT.java b/server/src/test/java/org/elasticsearch/cluster/ack/AckIT.java
index f51a4f11ae1..2cd8a2c27c7 100644
--- a/server/src/test/java/org/elasticsearch/cluster/ack/AckIT.java
+++ b/server/src/test/java/org/elasticsearch/cluster/ack/AckIT.java
@@ -21,11 +21,8 @@ package org.elasticsearch.cluster.ack;
 
 import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteResponse;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.metadata.AliasMetaData;
@@ -79,7 +76,7 @@ public class AckIT extends ESIntegTestCase {
 
     public void testUpdateSettingsNoAcknowledgement() {
         createIndex("test");
-        UpdateSettingsResponse updateSettingsResponse = client().admin().indices().prepareUpdateSettings("test").setTimeout("0s")
+        AcknowledgedResponse updateSettingsResponse = client().admin().indices().prepareUpdateSettings("test").setTimeout("0s")
                 .setSettings(Settings.builder().put("refresh_interval", 9999, TimeUnit.MILLISECONDS)).get();
         assertThat(updateSettingsResponse.isAcknowledged(), equalTo(false));
     }
@@ -229,7 +226,7 @@ public class AckIT extends ESIntegTestCase {
     public void testIndicesAliasesNoAcknowledgement() {
         createIndex("test");
 
-        IndicesAliasesResponse indicesAliasesResponse = client().admin().indices().prepareAliases().addAlias("test", "alias").setTimeout("0s").get();
+        AcknowledgedResponse indicesAliasesResponse = client().admin().indices().prepareAliases().addAlias("test", "alias").setTimeout("0s").get();
         assertThat(indicesAliasesResponse.isAcknowledged(), equalTo(false));
     }
 
@@ -249,7 +246,7 @@ public class AckIT extends ESIntegTestCase {
         createIndex("test");
         ensureGreen();
 
-        CloseIndexResponse closeIndexResponse = client().admin().indices().prepareClose("test").setTimeout("0s").get();
+        AcknowledgedResponse closeIndexResponse = client().admin().indices().prepareClose("test").setTimeout("0s").get();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(false));
     }
 
@@ -282,7 +279,7 @@ public class AckIT extends ESIntegTestCase {
         createIndex("test");
         ensureGreen();
 
-        PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("test").setSource("field", "type=keyword").setTimeout("0s").get();
+        AcknowledgedResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("test").setSource("field", "type=keyword").setTimeout("0s").get();
         assertThat(putMappingResponse.isAcknowledged(), equalTo(false));
     }
 
diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/TemplateUpgradeServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/TemplateUpgradeServiceTests.java
index 069dafa9754..776a0a158ae 100644
--- a/server/src/test/java/org/elasticsearch/cluster/metadata/TemplateUpgradeServiceTests.java
+++ b/server/src/test/java/org/elasticsearch/cluster/metadata/TemplateUpgradeServiceTests.java
@@ -22,9 +22,8 @@ package org.elasticsearch.cluster.metadata;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.AdminClient;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.IndicesAdminClient;
@@ -171,8 +170,8 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
         int additionsCount = randomIntBetween(0, 5);
         int deletionsCount = randomIntBetween(0, 3);
 
-        List<ActionListener<PutIndexTemplateResponse>> putTemplateListeners = new ArrayList<>();
-        List<ActionListener<DeleteIndexTemplateResponse>> deleteTemplateListeners = new ArrayList<>();
+        List<ActionListener<AcknowledgedResponse>> putTemplateListeners = new ArrayList<>();
+        List<ActionListener<AcknowledgedResponse>> deleteTemplateListeners = new ArrayList<>();
 
         Client mockClient = mock(Client.class);
         AdminClient mockAdminClient = mock(AdminClient.class);
@@ -227,7 +226,7 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
             if (randomBoolean()) {
                 putTemplateListeners.get(i).onFailure(new RuntimeException("test - ignore"));
             } else {
-                putTemplateListeners.get(i).onResponse(new PutIndexTemplateResponse(randomBoolean()) {
+                putTemplateListeners.get(i).onResponse(new AcknowledgedResponse(randomBoolean()) {
 
                 });
             }
@@ -240,7 +239,7 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
                 assertThat(prevUpdatesInProgress - service.upgradesInProgress.get(), equalTo(1));
             } else {
                 int prevUpdatesInProgress = service.upgradesInProgress.get();
-                deleteTemplateListeners.get(i).onResponse(new DeleteIndexTemplateResponse(randomBoolean()) {
+                deleteTemplateListeners.get(i).onResponse(new AcknowledgedResponse(randomBoolean()) {
 
                 });
                 assertThat(prevUpdatesInProgress - service.upgradesInProgress.get(), equalTo(1));
@@ -256,9 +255,9 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
     @SuppressWarnings("unchecked")
     public void testClusterStateUpdate() throws InterruptedException {
 
-        final AtomicReference<ActionListener<PutIndexTemplateResponse>> addedListener = new AtomicReference<>();
-        final AtomicReference<ActionListener<PutIndexTemplateResponse>> changedListener = new AtomicReference<>();
-        final AtomicReference<ActionListener<DeleteIndexTemplateResponse>> removedListener = new AtomicReference<>();
+        final AtomicReference<ActionListener<AcknowledgedResponse>> addedListener = new AtomicReference<>();
+        final AtomicReference<ActionListener<AcknowledgedResponse>> changedListener = new AtomicReference<>();
+        final AtomicReference<ActionListener<AcknowledgedResponse>> removedListener = new AtomicReference<>();
         final Semaphore updateInvocation = new Semaphore(0);
         final Semaphore calculateInvocation = new Semaphore(0);
         final Semaphore changedInvocation = new Semaphore(0);
@@ -373,11 +372,11 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
         assertThat(updateInvocation.availablePermits(), equalTo(0));
         assertThat(finishInvocation.availablePermits(), equalTo(0));
 
-        addedListener.getAndSet(null).onResponse(new PutIndexTemplateResponse(true) {
+        addedListener.getAndSet(null).onResponse(new AcknowledgedResponse(true) {
         });
-        changedListener.getAndSet(null).onResponse(new PutIndexTemplateResponse(true) {
+        changedListener.getAndSet(null).onResponse(new AcknowledgedResponse(true) {
         });
-        removedListener.getAndSet(null).onResponse(new DeleteIndexTemplateResponse(true) {
+        removedListener.getAndSet(null).onResponse(new AcknowledgedResponse(true) {
         });
 
         // 3 upgrades should be completed, in addition to the final calculate
diff --git a/server/src/test/java/org/elasticsearch/discovery/AbstractDisruptionTestCase.java b/server/src/test/java/org/elasticsearch/discovery/AbstractDisruptionTestCase.java
index 50dfd92d82e..0f3288b1973 100644
--- a/server/src/test/java/org/elasticsearch/discovery/AbstractDisruptionTestCase.java
+++ b/server/src/test/java/org/elasticsearch/discovery/AbstractDisruptionTestCase.java
@@ -44,7 +44,7 @@ import org.elasticsearch.test.disruption.NetworkDisruption.TwoPartitions;
 import org.elasticsearch.test.disruption.ServiceDisruptionScheme;
 import org.elasticsearch.test.disruption.SlowClusterStateProcessing;
 import org.elasticsearch.test.transport.MockTransportService;
-import org.elasticsearch.transport.TcpTransport;
+import org.elasticsearch.transport.TransportService;
 import org.junit.Before;
 
 import java.util.Arrays;
@@ -139,7 +139,7 @@ public abstract class AbstractDisruptionTestCase extends ESIntegTestCase {
             .put(FaultDetection.PING_RETRIES_SETTING.getKey(), "1") // for hitting simulated network failures quickly
             .put("discovery.zen.join_timeout", "10s")  // still long to induce failures but to long so test won't time out
             .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "1s") // <-- for hitting simulated network failures quickly
-            .put(TcpTransport.TCP_CONNECT_TIMEOUT.getKey(), "10s") // Network delay disruption waits for the min between this
+            .put(TransportService.TCP_CONNECT_TIMEOUT.getKey(), "10s") // Network delay disruption waits for the min between this
             // value and the time of disruption and does not recover immediately
             // when disruption is stop. We should make sure we recover faster
             // then the default of 30s, causing ensureGreen and friends to time out
diff --git a/server/src/test/java/org/elasticsearch/index/shard/GlobalCheckpointListenersTests.java b/server/src/test/java/org/elasticsearch/index/shard/GlobalCheckpointListenersTests.java
new file mode 100644
index 00000000000..d9240602d85
--- /dev/null
+++ b/server/src/test/java/org/elasticsearch/index/shard/GlobalCheckpointListenersTests.java
@@ -0,0 +1,423 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.shard;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.message.ParameterizedMessage;
+import org.elasticsearch.index.Index;
+import org.elasticsearch.test.ESTestCase;
+import org.mockito.ArgumentCaptor;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.List;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.elasticsearch.index.seqno.SequenceNumbers.NO_OPS_PERFORMED;
+import static org.elasticsearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO;
+import static org.hamcrest.Matchers.equalTo;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class GlobalCheckpointListenersTests extends ESTestCase {
+
+    final ShardId shardId = new ShardId(new Index("index", "uuid"), 0);
+
+    public void testGlobalCheckpointUpdated() throws IOException {
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, logger);
+        globalCheckpointListeners.globalCheckpointUpdated(NO_OPS_PERFORMED);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        final long[] globalCheckpoints = new long[numberOfListeners];
+        for (int i = 0; i < numberOfListeners; i++) {
+            final int index = i;
+            final AtomicBoolean invoked = new AtomicBoolean();
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener =
+                    (g, e) -> {
+                        if (invoked.compareAndSet(false, true) == false) {
+                            throw new IllegalStateException("listener invoked twice");
+                        }
+                        assert g != UNASSIGNED_SEQ_NO;
+                        assert e == null;
+                        globalCheckpoints[index] = g;
+                    };
+            globalCheckpointListeners.add(NO_OPS_PERFORMED, listener);
+        }
+        final long globalCheckpoint = randomLongBetween(NO_OPS_PERFORMED, Long.MAX_VALUE);
+        globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint);
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+        }
+
+        // test the listeners are not invoked twice
+        final long nextGlobalCheckpoint = randomLongBetween(globalCheckpoint + 1, Long.MAX_VALUE);
+        globalCheckpointListeners.globalCheckpointUpdated(nextGlobalCheckpoint);
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+        }
+
+        // closing should also not notify the listeners
+        globalCheckpointListeners.close();
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+        }
+    }
+
+    public void testListenersReadyToBeNotified() throws IOException {
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, logger);
+        final long globalCheckpoint = randomLongBetween(NO_OPS_PERFORMED + 1, Long.MAX_VALUE);
+        globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        final long[] globalCheckpoints = new long[numberOfListeners];
+        for (int i = 0; i < numberOfListeners; i++) {
+            final int index = i;
+            final AtomicBoolean invoked = new AtomicBoolean();
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener =
+                    (g, e) -> {
+                        if (invoked.compareAndSet(false, true) == false) {
+                            throw new IllegalStateException("listener invoked twice");
+                        }
+                        assert g != UNASSIGNED_SEQ_NO;
+                        assert e == null;
+                        globalCheckpoints[index] = g;
+                    };
+            globalCheckpointListeners.add(randomLongBetween(NO_OPS_PERFORMED, globalCheckpoint - 1), listener);
+            // the listener should be notified immediately
+            assertThat(globalCheckpoints[index], equalTo(globalCheckpoint));
+        }
+
+        // test the listeners are not invoked twice
+        final long nextGlobalCheckpoint = randomLongBetween(globalCheckpoint + 1, Long.MAX_VALUE);
+        globalCheckpointListeners.globalCheckpointUpdated(nextGlobalCheckpoint);
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+        }
+
+        // closing should also not notify the listeners
+        globalCheckpointListeners.close();
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+        }
+    }
+
+    public void testFailingListenerReadyToBeNotified() {
+        final Logger mockLogger = mock(Logger.class);
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, mockLogger);
+        final long globalCheckpoint = randomLongBetween(NO_OPS_PERFORMED + 1, Long.MAX_VALUE);
+        globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        final long[] globalCheckpoints = new long[numberOfListeners];
+        for (int i = 0; i < numberOfListeners; i++) {
+            final int index = i;
+            final boolean failure = randomBoolean();
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener =
+                    (g, e) -> {
+                        assert globalCheckpoint != UNASSIGNED_SEQ_NO;
+                        assert e == null;
+                        if (failure) {
+                            globalCheckpoints[index] = Long.MIN_VALUE;
+                            throw new RuntimeException("failure");
+                        } else {
+                            globalCheckpoints[index] = globalCheckpoint;
+                        }
+                    };
+            globalCheckpointListeners.add(randomLongBetween(NO_OPS_PERFORMED, globalCheckpoint - 1), listener);
+            // the listener should be notified immediately
+            if (failure) {
+                assertThat(globalCheckpoints[i], equalTo(Long.MIN_VALUE));
+                final ArgumentCaptor<ParameterizedMessage> message = ArgumentCaptor.forClass(ParameterizedMessage.class);
+                final ArgumentCaptor<RuntimeException> t = ArgumentCaptor.forClass(RuntimeException.class);
+                verify(mockLogger).warn(message.capture(), t.capture());
+                reset(mockLogger);
+                assertThat(
+                        message.getValue().getFormat(),
+                        equalTo("error notifying global checkpoint listener of updated global checkpoint [{}]"));
+                assertNotNull(message.getValue().getParameters());
+                assertThat(message.getValue().getParameters().length, equalTo(1));
+                assertThat(message.getValue().getParameters()[0], equalTo(globalCheckpoint));
+                assertNotNull(t.getValue());
+                assertThat(t.getValue().getMessage(), equalTo("failure"));
+            } else {
+                assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+            }
+        }
+    }
+
+    public void testClose() throws IOException {
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, logger);
+        globalCheckpointListeners.globalCheckpointUpdated(NO_OPS_PERFORMED);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        final IndexShardClosedException[] exceptions = new IndexShardClosedException[numberOfListeners];
+        for (int i = 0; i < numberOfListeners; i++) {
+            final int index = i;
+            final AtomicBoolean invoked = new AtomicBoolean();
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener =
+                    (globalCheckpoint, e) -> {
+                        if (invoked.compareAndSet(false, true) == false) {
+                            throw new IllegalStateException("listener invoked twice");
+                        }
+                        assert globalCheckpoint == UNASSIGNED_SEQ_NO;
+                        assert e != null;
+                        exceptions[index] = e;
+                    };
+            globalCheckpointListeners.add(NO_OPS_PERFORMED, listener);
+        }
+        globalCheckpointListeners.close();
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertNotNull(exceptions[i]);
+            assertThat(exceptions[i].getShardId(), equalTo(shardId));
+        }
+
+        // test the listeners are not invoked twice
+        for (int i = 0; i < numberOfListeners; i++) {
+            exceptions[i] = null;
+        }
+        globalCheckpointListeners.close();
+        for (int i = 0; i < numberOfListeners; i++) {
+            assertNull(exceptions[i]);
+        }
+    }
+
+    public void testAddAfterClose() throws InterruptedException, IOException {
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, logger);
+        globalCheckpointListeners.globalCheckpointUpdated(NO_OPS_PERFORMED);
+        globalCheckpointListeners.close();
+        final AtomicBoolean invoked = new AtomicBoolean();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final GlobalCheckpointListeners.GlobalCheckpointListener listener = (g, e) -> {
+            assert g == UNASSIGNED_SEQ_NO;
+            assert e != null;
+            if (invoked.compareAndSet(false, true) == false) {
+                latch.countDown();
+                throw new IllegalStateException("listener invoked twice");
+            }
+            latch.countDown();
+        };
+        globalCheckpointListeners.add(randomLongBetween(NO_OPS_PERFORMED, Long.MAX_VALUE), listener);
+        latch.await();
+        assertTrue(invoked.get());
+    }
+
+    public void testFailingListenerOnUpdate() {
+        final Logger mockLogger = mock(Logger.class);
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, mockLogger);
+        globalCheckpointListeners.globalCheckpointUpdated(NO_OPS_PERFORMED);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        final boolean[] failures = new boolean[numberOfListeners];
+        final long[] globalCheckpoints = new long[numberOfListeners];
+        for (int i = 0; i < numberOfListeners; i++) {
+            final int index = i;
+            final boolean failure = randomBoolean();
+            failures[index] = failure;
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener =
+                    (g, e) -> {
+                        assert g != UNASSIGNED_SEQ_NO;
+                        assert e == null;
+                        if (failure) {
+                            globalCheckpoints[index] = Long.MIN_VALUE;
+                            throw new RuntimeException("failure");
+                        } else {
+                            globalCheckpoints[index] = g;
+                        }
+                    };
+            globalCheckpointListeners.add(NO_OPS_PERFORMED, listener);
+        }
+        final long globalCheckpoint = randomLongBetween(NO_OPS_PERFORMED, Long.MAX_VALUE);
+        globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint);
+        for (int i = 0; i < numberOfListeners; i++) {
+            if (failures[i]) {
+                assertThat(globalCheckpoints[i], equalTo(Long.MIN_VALUE));
+            } else {
+                assertThat(globalCheckpoints[i], equalTo(globalCheckpoint));
+            }
+        }
+        int failureCount = 0;
+        for (int i = 0; i < numberOfListeners; i++) {
+            if (failures[i]) {
+                failureCount++;
+            }
+        }
+        if (failureCount > 0) {
+            final ArgumentCaptor<ParameterizedMessage> message = ArgumentCaptor.forClass(ParameterizedMessage.class);
+            final ArgumentCaptor<RuntimeException> t = ArgumentCaptor.forClass(RuntimeException.class);
+            verify(mockLogger, times(failureCount)).warn(message.capture(), t.capture());
+            assertThat(
+                    message.getValue().getFormat(),
+                    equalTo("error notifying global checkpoint listener of updated global checkpoint [{}]"));
+            assertNotNull(message.getValue().getParameters());
+            assertThat(message.getValue().getParameters().length, equalTo(1));
+            assertThat(message.getValue().getParameters()[0], equalTo(globalCheckpoint));
+            assertNotNull(t.getValue());
+            assertThat(t.getValue().getMessage(), equalTo("failure"));
+        }
+    }
+
+    public void testFailingListenerOnClose() throws IOException {
+        final Logger mockLogger = mock(Logger.class);
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, Runnable::run, mockLogger);
+        globalCheckpointListeners.globalCheckpointUpdated(NO_OPS_PERFORMED);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        final boolean[] failures = new boolean[numberOfListeners];
+        final IndexShardClosedException[] exceptions = new IndexShardClosedException[numberOfListeners];
+        for (int i = 0; i < numberOfListeners; i++) {
+            final int index = i;
+            final boolean failure = randomBoolean();
+            failures[index] = failure;
+            final GlobalCheckpointListeners.GlobalCheckpointListener listener =
+                    (g, e) -> {
+                        assert g == UNASSIGNED_SEQ_NO;
+                        assert e != null;
+                        if (failure) {
+                            throw new RuntimeException("failure");
+                        } else {
+                            exceptions[index] = e;
+                        }
+                    };
+            globalCheckpointListeners.add(NO_OPS_PERFORMED, listener);
+        }
+        globalCheckpointListeners.close();
+        for (int i = 0; i < numberOfListeners; i++) {
+            if (failures[i]) {
+                assertNull(exceptions[i]);
+            } else {
+                assertNotNull(exceptions[i]);
+                assertThat(exceptions[i].getShardId(), equalTo(shardId));
+            }
+        }
+        int failureCount = 0;
+        for (int i = 0; i < numberOfListeners; i++) {
+            if (failures[i]) {
+                failureCount++;
+            }
+        }
+        if (failureCount > 0) {
+            final ArgumentCaptor<String> message = ArgumentCaptor.forClass(String.class);
+            final ArgumentCaptor<RuntimeException> t = ArgumentCaptor.forClass(RuntimeException.class);
+            verify(mockLogger, times(failureCount)).warn(message.capture(), t.capture());
+            assertThat(message.getValue(), equalTo("error notifying global checkpoint listener of closed shard"));
+            assertNotNull(t.getValue());
+            assertThat(t.getValue().getMessage(), equalTo("failure"));
+        }
+    }
+
+    public void testNotificationUsesExecutor() {
+        final AtomicInteger count = new AtomicInteger();
+        final Executor executor = command -> {
+            count.incrementAndGet();
+            command.run();
+        };
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, executor, logger);
+        globalCheckpointListeners.globalCheckpointUpdated(NO_OPS_PERFORMED);
+        final int numberOfListeners = randomIntBetween(0, 16);
+        for (int i = 0; i < numberOfListeners; i++) {
+            globalCheckpointListeners.add(NO_OPS_PERFORMED, (g, e) -> {});
+        }
+        globalCheckpointListeners.globalCheckpointUpdated(randomLongBetween(NO_OPS_PERFORMED, Long.MAX_VALUE));
+        assertThat(count.get(), equalTo(1));
+    }
+
+    public void testConcurrency() throws BrokenBarrierException, InterruptedException {
+        final ExecutorService executor = Executors.newFixedThreadPool(randomIntBetween(1, 8));
+        final GlobalCheckpointListeners globalCheckpointListeners = new GlobalCheckpointListeners(shardId, executor, logger);
+        final AtomicLong globalCheckpoint = new AtomicLong(NO_OPS_PERFORMED);
+        globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint.get());
+        // we are going to synchronize the actions of three threads: the updating thread, the listener thread, and the main test thread
+        final CyclicBarrier barrier = new CyclicBarrier(3);
+        final int numberOfIterations = randomIntBetween(1, 1024);
+        final AtomicBoolean closed = new AtomicBoolean();
+        final Thread updatingThread = new Thread(() -> {
+            // synchronize starting with the listener thread and the main test thread
+            awaitQuietly(barrier);
+            for (int i = 0; i < numberOfIterations; i++) {
+                if (rarely() && closed.get() == false) {
+                    closed.set(true);
+                    try {
+                        globalCheckpointListeners.close();
+                    } catch (final IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                }
+                if (closed.get() == false) {
+                    globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint.incrementAndGet());
+                }
+            }
+            // synchronize ending with the listener thread and the main test thread
+            awaitQuietly(barrier);
+        });
+
+        final List<AtomicBoolean> invocations = new CopyOnWriteArrayList<>();
+        final Thread listenersThread = new Thread(() -> {
+            // synchronize starting with the updating thread and the main test thread
+            awaitQuietly(barrier);
+            for (int i = 0; i < numberOfIterations; i++) {
+                final AtomicBoolean invocation = new AtomicBoolean();
+                invocations.add(invocation);
+                // sometimes this will notify the listener immediately
+                globalCheckpointListeners.add(
+                        globalCheckpoint.get(),
+                        (g, e) -> {
+                            if (invocation.compareAndSet(false, true) == false) {
+                                throw new IllegalStateException("listener invoked twice");
+                            }
+                        });
+            }
+            // synchronize ending with the updating thread and the main test thread
+            awaitQuietly(barrier);
+        });
+        updatingThread.start();
+        listenersThread.start();
+        // synchronize starting with the updating thread and the listener thread
+        barrier.await();
+        // synchronize ending with the updating thread and the listener thread
+        barrier.await();
+        // one last update to ensure all listeners are notified
+        if (closed.get() == false) {
+            globalCheckpointListeners.globalCheckpointUpdated(globalCheckpoint.incrementAndGet());
+        }
+        assertThat(globalCheckpointListeners.pendingListeners(), equalTo(0));
+        executor.shutdown();
+        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
+        for (final AtomicBoolean invocation : invocations) {
+            assertTrue(invocation.get());
+        }
+        updatingThread.join();
+        listenersThread.join();
+    }
+
+    private void awaitQuietly(final CyclicBarrier barrier) {
+        try {
+            barrier.await();
+        } catch (final BrokenBarrierException | InterruptedException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+}
diff --git a/server/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java b/server/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java
index bda6de8aa7d..182747e7dda 100644
--- a/server/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java
+++ b/server/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java
@@ -91,6 +91,7 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
 
@@ -101,6 +102,8 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.NONE;
 import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
 import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
 import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
+import static org.elasticsearch.index.seqno.SequenceNumbers.NO_OPS_PERFORMED;
+import static org.elasticsearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO;
 import static org.elasticsearch.index.shard.IndexShardTestCase.getTranslog;
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
@@ -729,4 +732,48 @@ public class IndexShardIT extends ESSingleNodeTestCase {
         assertTrue(shard.isSearchIdle());
         assertHitCount(client().prepareSearch().get(), 3);
     }
+
+    public void testGlobalCheckpointListeners() throws Exception {
+        createIndex("test", Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 0).build());
+        ensureGreen();
+        final IndicesService indicesService = getInstanceFromNode(IndicesService.class);
+        final IndexService test = indicesService.indexService(resolveIndex("test"));
+        final IndexShard shard = test.getShardOrNull(0);
+        final int numberOfUpdates = randomIntBetween(1, 128);
+        for (int i = 0; i < numberOfUpdates; i++) {
+            final int index = i;
+            final AtomicLong globalCheckpoint = new AtomicLong();
+            shard.addGlobalCheckpointListener(
+                    i - 1,
+                    (g, e) -> {
+                        assert g >= NO_OPS_PERFORMED;
+                        assert e == null;
+                        globalCheckpoint.set(g);
+                    });
+            client().prepareIndex("test", "_doc", Integer.toString(i)).setSource("{}", XContentType.JSON).get();
+            assertBusy(() -> assertThat(globalCheckpoint.get(), equalTo((long) index)));
+            // adding a listener expecting a lower global checkpoint should fire immediately
+            final AtomicLong immediateGlobalCheckpint = new AtomicLong();
+            shard.addGlobalCheckpointListener(
+                    randomLongBetween(NO_OPS_PERFORMED, i - 1),
+                    (g, e) -> {
+                        assert g >= NO_OPS_PERFORMED;
+                        assert e == null;
+                        immediateGlobalCheckpint.set(g);
+                    });
+            assertBusy(() -> assertThat(immediateGlobalCheckpint.get(), equalTo((long) index)));
+        }
+        final AtomicBoolean invoked = new AtomicBoolean();
+        shard.addGlobalCheckpointListener(
+                numberOfUpdates - 1,
+                (g, e) -> {
+                    invoked.set(true);
+                    assert g == UNASSIGNED_SEQ_NO;
+                    assert e != null;
+                    assertThat(e.getShardId(), equalTo(shard.shardId()));
+                });
+        shard.close("closed", randomBoolean());
+        assertBusy(() -> assertTrue(invoked.get()));
+    }
+
 }
diff --git a/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java b/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java
index 05e38d2aed0..5091af5a540 100644
--- a/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java
+++ b/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java
@@ -2400,6 +2400,7 @@ public class IndexShardTests extends IndexShardTestCase {
         closeShards(sourceShard, targetShard);
     }
 
+    @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32766")
     public void testDocStats() throws IOException {
         IndexShard indexShard = null;
         try {
diff --git a/server/src/test/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java b/server/src/test/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java
index 5278a6c01d7..f4db4925da4 100644
--- a/server/src/test/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java
+++ b/server/src/test/java/org/elasticsearch/indexlifecycle/IndexLifecycleActionIT.java
@@ -21,7 +21,7 @@ package org.elasticsearch.indexlifecycle;
 
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
 import org.elasticsearch.cluster.routing.RoutingNode;
@@ -191,7 +191,7 @@ public class IndexLifecycleActionIT extends ESIntegTestCase {
 
         logger.info("Deleting index [test]");
         // last, lets delete the index
-        DeleteIndexResponse deleteIndexResponse = client().admin().indices().prepareDelete("test").execute().actionGet();
+        AcknowledgedResponse deleteIndexResponse = client().admin().indices().prepareDelete("test").execute().actionGet();
         assertThat(deleteIndexResponse.isAcknowledged(), equalTo(true));
 
         clusterState = client().admin().cluster().prepareState().get().getState();
diff --git a/server/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationIT.java b/server/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationIT.java
index 5f9ce852e2a..0a03343cc1d 100644
--- a/server/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationIT.java
+++ b/server/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationIT.java
@@ -19,7 +19,6 @@
 package org.elasticsearch.indices;
 
 import org.elasticsearch.action.ActionRequestBuilder;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequestBuilder;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequestBuilder;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistRequestBuilder;
@@ -41,6 +40,7 @@ import org.elasticsearch.action.search.MultiSearchResponse;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.settings.Setting;
 import org.elasticsearch.common.settings.Setting.Property;
@@ -269,7 +269,7 @@ public class IndicesOptionsIntegrationIT extends ESIntegTestCase {
         ensureGreen("test1");
         waitForRelocation();
 
-        PutRepositoryResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("dummy-repo")
+        AcknowledgedResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("dummy-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())).get();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
         client().admin().cluster().prepareCreateSnapshot("dummy-repo", "snap1").setWaitForCompletion(true).get();
@@ -394,7 +394,7 @@ public class IndicesOptionsIntegrationIT extends ESIntegTestCase {
         ensureGreen("foobar");
         waitForRelocation();
 
-        PutRepositoryResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("dummy-repo")
+        AcknowledgedResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("dummy-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())).get();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
         client().admin().cluster().prepareCreateSnapshot("dummy-repo", "snap1").setWaitForCompletion(true).get();
diff --git a/server/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java b/server/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java
index 094cf83186c..f28d253087d 100644
--- a/server/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java
+++ b/server/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java
@@ -21,10 +21,10 @@ package org.elasticsearch.indices.mapping;
 
 import org.elasticsearch.Version;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.cluster.metadata.MappingMetaData;
@@ -115,7 +115,7 @@ public class UpdateMappingIntegrationIT extends ESIntegTestCase {
                 .execute().actionGet();
         client().admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
 
-        PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("_doc")
+        AcknowledgedResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("_doc")
                 .setSource("{\"properties\":{\"date\":{\"type\":\"integer\"}}}", XContentType.JSON)
                 .execute().actionGet();
 
@@ -135,7 +135,7 @@ public class UpdateMappingIntegrationIT extends ESIntegTestCase {
                 ).execute().actionGet();
         client().admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
 
-        PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("_doc")
+        AcknowledgedResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("_doc")
                 .setSource("{\"properties\":{\"date\":{\"type\":\"integer\"}}}", XContentType.JSON)
                 .execute().actionGet();
 
@@ -192,7 +192,7 @@ public class UpdateMappingIntegrationIT extends ESIntegTestCase {
                 .execute().actionGet();
         client().admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
 
-        PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("type")
+        AcknowledgedResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("type")
                 .setSource("{\"type\":{\"properties\":{\"body\":{\"type\":\"text\"}}}}", XContentType.JSON)
                 .execute().actionGet();
 
@@ -218,7 +218,7 @@ public class UpdateMappingIntegrationIT extends ESIntegTestCase {
 
         logger.info("Emptying _default_ mappings");
         // now remove it
-        PutMappingResponse putResponse = client().admin().indices().preparePutMapping("test").setType(MapperService.DEFAULT_MAPPING).setSource(
+        AcknowledgedResponse putResponse = client().admin().indices().preparePutMapping("test").setType(MapperService.DEFAULT_MAPPING).setSource(
                 JsonXContent.contentBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING)
                         .endObject().endObject()
         ).get();
@@ -291,7 +291,7 @@ public class UpdateMappingIntegrationIT extends ESIntegTestCase {
                         String typeName = "type";
                         String fieldName = Thread.currentThread().getName() + "_" + i;
 
-                        PutMappingResponse response = client1.admin().indices().preparePutMapping(indexName).setType(typeName).setSource(
+                        AcknowledgedResponse response = client1.admin().indices().preparePutMapping(indexName).setType(typeName).setSource(
                                 JsonXContent.contentBuilder().startObject().startObject(typeName)
                                         .startObject("properties").startObject(fieldName).field("type", "text").endObject().endObject()
                                         .endObject().endObject()
diff --git a/server/src/test/java/org/elasticsearch/indices/state/OpenCloseIndexIT.java b/server/src/test/java/org/elasticsearch/indices/state/OpenCloseIndexIT.java
index 2a867915b0f..96bb9ab8a1c 100644
--- a/server/src/test/java/org/elasticsearch/indices/state/OpenCloseIndexIT.java
+++ b/server/src/test/java/org/elasticsearch/indices/state/OpenCloseIndexIT.java
@@ -22,12 +22,11 @@ package org.elasticsearch.indices.state;
 import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.common.Strings;
@@ -63,7 +62,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("test1").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1");
 
@@ -102,7 +101,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         createIndex("test1");
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1", "test2")
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("test1", "test2")
                 .setIndicesOptions(IndicesOptions.lenientExpandOpen()).execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1");
@@ -136,9 +135,9 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        CloseIndexResponse closeIndexResponse1 = client.admin().indices().prepareClose("test1").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse1 = client.admin().indices().prepareClose("test1").execute().actionGet();
         assertThat(closeIndexResponse1.isAcknowledged(), equalTo(true));
-        CloseIndexResponse closeIndexResponse2 = client.admin().indices().prepareClose("test2").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse2 = client.admin().indices().prepareClose("test2").execute().actionGet();
         assertThat(closeIndexResponse2.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1", "test2");
         assertIndexIsOpened("test3");
@@ -158,7 +157,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test*").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("test*").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1", "test2");
         assertIndexIsOpened("a");
@@ -175,7 +174,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("_all").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("_all").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1", "test2", "test3");
 
@@ -191,7 +190,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("*").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("*").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1", "test2", "test3");
 
@@ -249,7 +248,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
         //closing the index
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("test1").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1");
 
@@ -265,10 +264,10 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        IndicesAliasesResponse aliasesResponse = client.admin().indices().prepareAliases().addAlias("test1", "test1-alias").execute().actionGet();
+        AcknowledgedResponse aliasesResponse = client.admin().indices().prepareAliases().addAlias("test1", "test1-alias").execute().actionGet();
         assertThat(aliasesResponse.isAcknowledged(), equalTo(true));
 
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1-alias").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("test1-alias").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1");
 
@@ -284,12 +283,12 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
         ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
         assertThat(healthResponse.isTimedOut(), equalTo(false));
 
-        IndicesAliasesResponse aliasesResponse1 = client.admin().indices().prepareAliases().addAlias("test1", "test-alias").execute().actionGet();
+        AcknowledgedResponse aliasesResponse1 = client.admin().indices().prepareAliases().addAlias("test1", "test-alias").execute().actionGet();
         assertThat(aliasesResponse1.isAcknowledged(), equalTo(true));
-        IndicesAliasesResponse aliasesResponse2 = client.admin().indices().prepareAliases().addAlias("test2", "test-alias").execute().actionGet();
+        AcknowledgedResponse aliasesResponse2 = client.admin().indices().prepareAliases().addAlias("test2", "test-alias").execute().actionGet();
         assertThat(aliasesResponse2.isAcknowledged(), equalTo(true));
 
-        CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test-alias").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client.admin().indices().prepareClose("test-alias").execute().actionGet();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
         assertIndexIsClosed("test1", "test2");
 
@@ -380,7 +379,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
                 enableIndexBlock("test", blockSetting);
 
                 // Closing an index is not blocked
-                CloseIndexResponse closeIndexResponse = client().admin().indices().prepareClose("test").execute().actionGet();
+                AcknowledgedResponse closeIndexResponse = client().admin().indices().prepareClose("test").execute().actionGet();
                 assertAcked(closeIndexResponse);
                 assertIndexIsClosed("test");
 
@@ -405,7 +404,7 @@ public class OpenCloseIndexIT extends ESIntegTestCase {
             }
         }
 
-        CloseIndexResponse closeIndexResponse = client().admin().indices().prepareClose("test").execute().actionGet();
+        AcknowledgedResponse closeIndexResponse = client().admin().indices().prepareClose("test").execute().actionGet();
         assertAcked(closeIndexResponse);
         assertIndexIsClosed("test");
 
diff --git a/server/src/test/java/org/elasticsearch/indices/state/RareClusterStateIT.java b/server/src/test/java/org/elasticsearch/indices/state/RareClusterStateIT.java
index d25120c8733..df22e81aa6a 100644
--- a/server/src/test/java/org/elasticsearch/indices/state/RareClusterStateIT.java
+++ b/server/src/test/java/org/elasticsearch/indices/state/RareClusterStateIT.java
@@ -22,8 +22,8 @@ package org.elasticsearch.indices.state;
 import org.elasticsearch.ElasticsearchParseException;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ClusterStateUpdateTask;
 import org.elasticsearch.cluster.block.ClusterBlocks;
@@ -235,9 +235,9 @@ public class RareClusterStateIT extends ESIntegTestCase {
 
         // Add a new mapping...
         final AtomicReference<Object> putMappingResponse = new AtomicReference<>();
-        client().admin().indices().preparePutMapping("index").setType("type").setSource("field", "type=long").execute(new ActionListener<PutMappingResponse>() {
+        client().admin().indices().preparePutMapping("index").setType("type").setSource("field", "type=long").execute(new ActionListener<AcknowledgedResponse>() {
             @Override
-            public void onResponse(PutMappingResponse response) {
+            public void onResponse(AcknowledgedResponse response) {
                 putMappingResponse.set(response);
             }
 
@@ -286,8 +286,8 @@ public class RareClusterStateIT extends ESIntegTestCase {
         // Now make sure the indexing request finishes successfully
         disruption.stopDisrupting();
         assertBusy(() -> {
-            assertThat(putMappingResponse.get(), instanceOf(PutMappingResponse.class));
-            PutMappingResponse resp = (PutMappingResponse) putMappingResponse.get();
+            assertThat(putMappingResponse.get(), instanceOf(AcknowledgedResponse.class));
+            AcknowledgedResponse resp = (AcknowledgedResponse) putMappingResponse.get();
             assertTrue(resp.isAcknowledged());
             assertThat(docIndexResponse.get(), instanceOf(IndexResponse.class));
             IndexResponse docResp = (IndexResponse) docIndexResponse.get();
@@ -349,9 +349,9 @@ public class RareClusterStateIT extends ESIntegTestCase {
         internalCluster().setDisruptionScheme(disruption);
         disruption.startDisrupting();
         final AtomicReference<Object> putMappingResponse = new AtomicReference<>();
-        client().admin().indices().preparePutMapping("index").setType("type").setSource("field", "type=long").execute(new ActionListener<PutMappingResponse>() {
+        client().admin().indices().preparePutMapping("index").setType("type").setSource("field", "type=long").execute(new ActionListener<AcknowledgedResponse>() {
             @Override
-            public void onResponse(PutMappingResponse response) {
+            public void onResponse(AcknowledgedResponse response) {
                 putMappingResponse.set(response);
             }
 
@@ -397,8 +397,8 @@ public class RareClusterStateIT extends ESIntegTestCase {
         // Now make sure the indexing request finishes successfully
         disruption.stopDisrupting();
         assertBusy(() -> {
-            assertThat(putMappingResponse.get(), instanceOf(PutMappingResponse.class));
-            PutMappingResponse resp = (PutMappingResponse) putMappingResponse.get();
+            assertThat(putMappingResponse.get(), instanceOf(AcknowledgedResponse.class));
+            AcknowledgedResponse resp = (AcknowledgedResponse) putMappingResponse.get();
             assertTrue(resp.isAcknowledged());
             assertThat(docIndexResponse.get(), instanceOf(IndexResponse.class));
             IndexResponse docResp = (IndexResponse) docIndexResponse.get();
diff --git a/server/src/test/java/org/elasticsearch/indices/state/SimpleIndexStateIT.java b/server/src/test/java/org/elasticsearch/indices/state/SimpleIndexStateIT.java
index 5ec6d82117a..2b3f5072708 100644
--- a/server/src/test/java/org/elasticsearch/indices/state/SimpleIndexStateIT.java
+++ b/server/src/test/java/org/elasticsearch/indices/state/SimpleIndexStateIT.java
@@ -22,10 +22,10 @@ package org.elasticsearch.indices.state;
 import org.apache.logging.log4j.Logger;
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
-import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
 import org.elasticsearch.action.support.ActiveShardCount;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.cluster.routing.ShardRoutingState;
@@ -61,7 +61,7 @@ public class SimpleIndexStateIT extends ESIntegTestCase {
         client().prepareIndex("test", "type1", "1").setSource("field1", "value1").get();
 
         logger.info("--> closing test index...");
-        CloseIndexResponse closeIndexResponse = client().admin().indices().prepareClose("test").get();
+        AcknowledgedResponse closeIndexResponse = client().admin().indices().prepareClose("test").get();
         assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
 
         stateResponse = client().admin().cluster().prepareState().get();
diff --git a/server/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java b/server/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java
index 0137f136d3e..871e5071ec7 100644
--- a/server/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java
+++ b/server/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java
@@ -19,8 +19,8 @@
 
 package org.elasticsearch.repositories.blobstore;
 
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.UUIDs;
 import org.elasticsearch.common.settings.Settings;
@@ -85,7 +85,7 @@ public class BlobStoreRepositoryTests extends ESSingleNodeTestCase {
         final String repositoryName = "test-repo";
 
         logger.info("-->  creating repository");
-        PutRepositoryResponse putRepositoryResponse =
+        AcknowledgedResponse putRepositoryResponse =
             client.admin().cluster().preparePutRepository(repositoryName)
                                     .setType(REPO_TYPE)
                                     .setSettings(Settings.builder().put(node().settings()).put("location", location))
@@ -237,7 +237,7 @@ public class BlobStoreRepositoryTests extends ESSingleNodeTestCase {
         final Path location = ESIntegTestCase.randomRepoPath(node().settings());
         final String repositoryName = "test-repo";
 
-        PutRepositoryResponse putRepositoryResponse =
+        AcknowledgedResponse putRepositoryResponse =
             client.admin().cluster().preparePutRepository(repositoryName)
                                     .setType(REPO_TYPE)
                                     .setSettings(Settings.builder().put(node().settings()).put("location", location))
diff --git a/server/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchIT.java b/server/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchIT.java
index 0c4c6e510eb..58b2b863963 100644
--- a/server/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchIT.java
+++ b/server/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchIT.java
@@ -23,13 +23,13 @@ import org.apache.lucene.analysis.TokenStreamToAutomaton;
 import org.apache.lucene.search.suggest.document.ContextSuggestField;
 import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
 import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.segments.IndexShardSegments;
 import org.elasticsearch.action.admin.indices.segments.ShardSegments;
 import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.search.SearchPhaseExecutionException;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.FieldMemoryStats;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.settings.Settings;
@@ -562,7 +562,7 @@ public class CompletionSuggestSearchIT extends ESIntegTestCase {
                 .setSource(jsonBuilder().startObject().field(FIELD, "Foo Fighters").endObject()).get();
         ensureGreen(INDEX);
 
-        PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
+        AcknowledgedResponse putMappingResponse = client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
                 .startObject(TYPE).startObject("properties")
                 .startObject(FIELD)
                 .field("type", "text")
@@ -742,7 +742,7 @@ public class CompletionSuggestSearchIT extends ESIntegTestCase {
                 .setSettings(Settings.builder().put("index.number_of_replicas", 0).put("index.number_of_shards", 2))
                 .execute().actionGet();
         ensureGreen();
-        PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
+        AcknowledgedResponse putMappingResponse = client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
                 .startObject(TYPE).startObject("properties")
                 .startObject(FIELD)
                 .field("type", "completion").field("analyzer", "simple")
diff --git a/server/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java b/server/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java
index a008846e2d3..7f008d8721a 100644
--- a/server/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java
+++ b/server/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java
@@ -23,9 +23,7 @@ import com.carrotsearch.hppc.IntHashSet;
 import com.carrotsearch.hppc.IntSet;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionFuture;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStats;
@@ -33,6 +31,7 @@ import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.support.ActiveShardCount;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.AdminClient;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.node.NodeClient;
@@ -180,7 +179,7 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
                 .getMetaData().persistentSettings().getAsInt(ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES_SETTING.getKey(), -1), equalTo(2));
 
         logger.info("--> create repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())).execute().actionGet();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
 
@@ -235,7 +234,7 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
         });
 
         logger.info("--> create repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", tempDir)).execute().actionGet();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
 
@@ -351,7 +350,7 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
 
         logger.info("--> create repository");
         logger.info("--> creating repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("mock").setSettings(
                         Settings.builder()
                                 .put("location", randomRepoPath())
@@ -399,7 +398,7 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
 
         logger.info("--> creating repository");
         Path repo = randomRepoPath();
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("mock").setSettings(
                         Settings.builder()
                                 .put("location", repo)
@@ -422,14 +421,14 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
 
         logger.info("--> execution was blocked on node [{}], aborting snapshot", blockedNode);
 
-        ActionFuture<DeleteSnapshotResponse> deleteSnapshotResponseFuture = internalCluster().client(nodes.get(0)).admin().cluster().prepareDeleteSnapshot("test-repo", "test-snap").execute();
+        ActionFuture<AcknowledgedResponse> deleteSnapshotResponseFuture = internalCluster().client(nodes.get(0)).admin().cluster().prepareDeleteSnapshot("test-repo", "test-snap").execute();
         // Make sure that abort makes some progress
         Thread.sleep(100);
         unblockNode("test-repo", blockedNode);
         logger.info("--> stopping node [{}]", blockedNode);
         stopNode(blockedNode);
         try {
-            DeleteSnapshotResponse deleteSnapshotResponse = deleteSnapshotResponseFuture.actionGet();
+            AcknowledgedResponse deleteSnapshotResponse = deleteSnapshotResponseFuture.actionGet();
             assertThat(deleteSnapshotResponse.isAcknowledged(), equalTo(true));
         } catch (SnapshotMissingException ex) {
             // When master node is closed during this test, it sometime manages to delete the snapshot files before
@@ -496,7 +495,7 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
         assertTrue(client().admin().indices().prepareExists("test-idx-none").get().isExists());
 
         logger.info("--> creating repository");
-        PutRepositoryResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("test-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())).execute().actionGet();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
 
@@ -603,7 +602,7 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
         cluster().wipeIndices("_all");
 
         logger.info("--> create repository");
-        PutRepositoryResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("test-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())).execute().actionGet();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
         int numberOfShards = 6;
diff --git a/server/src/test/java/org/elasticsearch/snapshots/MinThreadsSnapshotRestoreIT.java b/server/src/test/java/org/elasticsearch/snapshots/MinThreadsSnapshotRestoreIT.java
index 6279ed28903..885baa883ed 100644
--- a/server/src/test/java/org/elasticsearch/snapshots/MinThreadsSnapshotRestoreIT.java
+++ b/server/src/test/java/org/elasticsearch/snapshots/MinThreadsSnapshotRestoreIT.java
@@ -20,7 +20,7 @@
 package org.elasticsearch.snapshots;
 
 import org.elasticsearch.action.ActionFuture;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.plugins.Plugin;
@@ -83,7 +83,7 @@ public class MinThreadsSnapshotRestoreIT extends AbstractSnapshotIntegTestCase {
         String blockedNode = internalCluster().getMasterName();
         ((MockRepository)internalCluster().getInstance(RepositoriesService.class, blockedNode).repository(repo)).blockOnDataFiles(true);
         logger.info("--> start deletion of first snapshot");
-        ActionFuture<DeleteSnapshotResponse> future =
+        ActionFuture<AcknowledgedResponse> future =
             client().admin().cluster().prepareDeleteSnapshot(repo, snapshot2).execute();
         logger.info("--> waiting for block to kick in on node [{}]", blockedNode);
         waitForBlock(blockedNode, repo, TimeValue.timeValueSeconds(10));
@@ -129,7 +129,7 @@ public class MinThreadsSnapshotRestoreIT extends AbstractSnapshotIntegTestCase {
         String blockedNode = internalCluster().getMasterName();
         ((MockRepository)internalCluster().getInstance(RepositoriesService.class, blockedNode).repository(repo)).blockOnDataFiles(true);
         logger.info("--> start deletion of snapshot");
-        ActionFuture<DeleteSnapshotResponse> future = client().admin().cluster().prepareDeleteSnapshot(repo, snapshot1).execute();
+        ActionFuture<AcknowledgedResponse> future = client().admin().cluster().prepareDeleteSnapshot(repo, snapshot1).execute();
         logger.info("--> waiting for block to kick in on node [{}]", blockedNode);
         waitForBlock(blockedNode, repo, TimeValue.timeValueSeconds(10));
 
@@ -184,7 +184,7 @@ public class MinThreadsSnapshotRestoreIT extends AbstractSnapshotIntegTestCase {
         String blockedNode = internalCluster().getMasterName();
         ((MockRepository)internalCluster().getInstance(RepositoriesService.class, blockedNode).repository(repo)).blockOnDataFiles(true);
         logger.info("--> start deletion of snapshot");
-        ActionFuture<DeleteSnapshotResponse> future = client().admin().cluster().prepareDeleteSnapshot(repo, snapshot2).execute();
+        ActionFuture<AcknowledgedResponse> future = client().admin().cluster().prepareDeleteSnapshot(repo, snapshot2).execute();
         logger.info("--> waiting for block to kick in on node [{}]", blockedNode);
         waitForBlock(blockedNode, repo, TimeValue.timeValueSeconds(10));
 
diff --git a/server/src/test/java/org/elasticsearch/snapshots/RepositoriesIT.java b/server/src/test/java/org/elasticsearch/snapshots/RepositoriesIT.java
index d39d33b9d3e..903948c158d 100644
--- a/server/src/test/java/org/elasticsearch/snapshots/RepositoriesIT.java
+++ b/server/src/test/java/org/elasticsearch/snapshots/RepositoriesIT.java
@@ -18,11 +18,10 @@
  */
 package org.elasticsearch.snapshots;
 
-import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.metadata.MetaData;
 import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
@@ -51,7 +50,7 @@ public class RepositoriesIT extends AbstractSnapshotIntegTestCase {
         Path location = randomRepoPath();
 
         logger.info("-->  creating repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo-1")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo-1")
                 .setType("fs").setSettings(Settings.builder()
                                 .put("location", location)
                 ).get();
@@ -145,7 +144,7 @@ public class RepositoriesIT extends AbstractSnapshotIntegTestCase {
 
     public void testRepositoryAckTimeout() throws Exception {
         logger.info("-->  creating repository test-repo-1 with 0s timeout - shouldn't ack");
-        PutRepositoryResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("test-repo-1")
+        AcknowledgedResponse putRepositoryResponse = client().admin().cluster().preparePutRepository("test-repo-1")
                 .setType("fs").setSettings(Settings.builder()
                                 .put("location", randomRepoPath())
                                 .put("compress", randomBoolean())
@@ -164,7 +163,7 @@ public class RepositoriesIT extends AbstractSnapshotIntegTestCase {
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
 
         logger.info("-->  deleting repository test-repo-2 with 0s timeout - shouldn't ack");
-        DeleteRepositoryResponse deleteRepositoryResponse = client().admin().cluster().prepareDeleteRepository("test-repo-2")
+        AcknowledgedResponse deleteRepositoryResponse = client().admin().cluster().prepareDeleteRepository("test-repo-2")
                 .setTimeout("0s").get();
         assertThat(deleteRepositoryResponse.isAcknowledged(), equalTo(false));
 
diff --git a/server/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java b/server/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java
index eb335d068dd..632a1ecbee1 100644
--- a/server/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java
+++ b/server/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java
@@ -23,9 +23,7 @@ import org.apache.lucene.util.SetOnce;
 import org.elasticsearch.ExceptionsHelper;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionFuture;
-import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
-import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
 import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotIndexShardStage;
@@ -45,6 +43,7 @@ import org.elasticsearch.action.ingest.DeletePipelineRequest;
 import org.elasticsearch.action.ingest.GetPipelineResponse;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.ActiveShardCount;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ClusterStateListener;
@@ -433,7 +432,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
         Client client = client();
 
         logger.info("-->  creating repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())).get();
         assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
 
@@ -1693,7 +1692,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
         Client client = client();
         Path repositoryLocation = randomRepoPath();
         logger.info("-->  creating repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("mock").setSettings(
                         Settings.builder()
                                 .put("location", repositoryLocation)
@@ -1890,7 +1889,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
         Client client = client();
         Path repositoryLocation = randomRepoPath();
         logger.info("-->  creating repository");
-        PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
+        AcknowledgedResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
                 .setType("mock").setSettings(
                         Settings.builder()
                                 .put("location", repositoryLocation)
@@ -3071,7 +3070,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
         refresh();
 
         logger.info("--> creating repository");
-        PutRepositoryResponse putRepositoryResponse =
+        AcknowledgedResponse putRepositoryResponse =
             client().admin().cluster().preparePutRepository(repo).setType("mock").setSettings(Settings.builder()
                 .put("location", randomRepoPath())
                 .put("random", randomAlphaOfLength(10))
@@ -3432,7 +3431,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
             internalCluster().getInstances(ClusterService.class).forEach(clusterService -> clusterService.addListener(listener));
 
             // Delete the snapshot while it is being initialized
-            ActionFuture<DeleteSnapshotResponse> delete = client.admin().cluster().prepareDeleteSnapshot("repository", "snap").execute();
+            ActionFuture<AcknowledgedResponse> delete = client.admin().cluster().prepareDeleteSnapshot("repository", "snap").execute();
 
             // The deletion must set the snapshot in the ABORTED state
             assertBusy(() -> {
diff --git a/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java b/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java
index 64e8a426004..3c099c32bde 100644
--- a/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java
+++ b/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java
@@ -35,6 +35,7 @@ import java.net.InetAddress;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import static org.hamcrest.Matchers.equalTo;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -62,6 +63,73 @@ public class ConnectionManagerTests extends ESTestCase {
         threadPool.shutdown();
     }
 
+    public void testConnectionProfileResolve() {
+        final ConnectionProfile defaultProfile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY);
+        assertEquals(defaultProfile, ConnectionProfile.resolveConnectionProfile(null, defaultProfile));
+
+        final ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
+        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.BULK);
+        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.RECOVERY);
+        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.REG);
+        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.STATE);
+        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.PING);
+
+        final boolean connectionTimeoutSet = randomBoolean();
+        if (connectionTimeoutSet) {
+            builder.setConnectTimeout(TimeValue.timeValueMillis(randomNonNegativeLong()));
+        }
+        final boolean connectionHandshakeSet = randomBoolean();
+        if (connectionHandshakeSet) {
+            builder.setHandshakeTimeout(TimeValue.timeValueMillis(randomNonNegativeLong()));
+        }
+
+        final ConnectionProfile profile = builder.build();
+        final ConnectionProfile resolved = ConnectionProfile.resolveConnectionProfile(profile, defaultProfile);
+        assertNotEquals(resolved, defaultProfile);
+        assertThat(resolved.getNumConnections(), equalTo(profile.getNumConnections()));
+        assertThat(resolved.getHandles(), equalTo(profile.getHandles()));
+
+        assertThat(resolved.getConnectTimeout(),
+            equalTo(connectionTimeoutSet ? profile.getConnectTimeout() : defaultProfile.getConnectTimeout()));
+        assertThat(resolved.getHandshakeTimeout(),
+            equalTo(connectionHandshakeSet ? profile.getHandshakeTimeout() : defaultProfile.getHandshakeTimeout()));
+    }
+
+    public void testDefaultConnectionProfile() {
+        ConnectionProfile profile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY);
+        assertEquals(13, profile.getNumConnections());
+        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
+        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
+        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
+        assertEquals(2, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
+        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
+
+        profile = ConnectionManager.buildDefaultConnectionProfile(Settings.builder().put("node.master", false).build());
+        assertEquals(12, profile.getNumConnections());
+        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
+        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
+        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
+        assertEquals(2, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
+        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
+
+        profile = ConnectionManager.buildDefaultConnectionProfile(Settings.builder().put("node.data", false).build());
+        assertEquals(11, profile.getNumConnections());
+        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
+        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
+        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
+        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
+        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
+
+        profile = ConnectionManager.buildDefaultConnectionProfile(Settings.builder().put("node.data", false)
+            .put("node.master", false).build());
+        assertEquals(10, profile.getNumConnections());
+        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
+        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
+        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
+        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
+        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
+    }
+
     public void testConnectAndDisconnect() {
         AtomicInteger nodeConnectedCount = new AtomicInteger();
         AtomicInteger nodeDisconnectedCount = new AtomicInteger();
diff --git a/server/src/test/java/org/elasticsearch/transport/TcpTransportTests.java b/server/src/test/java/org/elasticsearch/transport/TcpTransportTests.java
index 8474b994712..a3d2e1bbc57 100644
--- a/server/src/test/java/org/elasticsearch/transport/TcpTransportTests.java
+++ b/server/src/test/java/org/elasticsearch/transport/TcpTransportTests.java
@@ -29,7 +29,6 @@ import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.util.BigArrays;
 import org.elasticsearch.common.util.PageCacheRecycler;
 import org.elasticsearch.test.ESTestCase;
@@ -305,72 +304,6 @@ public class TcpTransportTests extends ESTestCase {
         }
     }
 
-    public void testConnectionProfileResolve() {
-        final ConnectionProfile defaultProfile = TcpTransport.buildDefaultConnectionProfile(Settings.EMPTY);
-        assertEquals(defaultProfile, TcpTransport.resolveConnectionProfile(null, defaultProfile));
-
-        final ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
-        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.BULK);
-        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.RECOVERY);
-        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.REG);
-        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.STATE);
-        builder.addConnections(randomIntBetween(0, 5), TransportRequestOptions.Type.PING);
-
-        final boolean connectionTimeoutSet = randomBoolean();
-        if (connectionTimeoutSet) {
-            builder.setConnectTimeout(TimeValue.timeValueMillis(randomNonNegativeLong()));
-        }
-        final boolean connectionHandshakeSet = randomBoolean();
-        if (connectionHandshakeSet) {
-            builder.setHandshakeTimeout(TimeValue.timeValueMillis(randomNonNegativeLong()));
-        }
-
-        final ConnectionProfile profile = builder.build();
-        final ConnectionProfile resolved = TcpTransport.resolveConnectionProfile(profile, defaultProfile);
-        assertNotEquals(resolved, defaultProfile);
-        assertThat(resolved.getNumConnections(), equalTo(profile.getNumConnections()));
-        assertThat(resolved.getHandles(), equalTo(profile.getHandles()));
-
-        assertThat(resolved.getConnectTimeout(),
-            equalTo(connectionTimeoutSet ? profile.getConnectTimeout() : defaultProfile.getConnectTimeout()));
-        assertThat(resolved.getHandshakeTimeout(),
-            equalTo(connectionHandshakeSet ? profile.getHandshakeTimeout() : defaultProfile.getHandshakeTimeout()));
-    }
-
-    public void testDefaultConnectionProfile() {
-        ConnectionProfile profile = TcpTransport.buildDefaultConnectionProfile(Settings.EMPTY);
-        assertEquals(13, profile.getNumConnections());
-        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
-        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
-        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
-        assertEquals(2, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
-        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
-
-        profile = TcpTransport.buildDefaultConnectionProfile(Settings.builder().put("node.master", false).build());
-        assertEquals(12, profile.getNumConnections());
-        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
-        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
-        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
-        assertEquals(2, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
-        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
-
-        profile = TcpTransport.buildDefaultConnectionProfile(Settings.builder().put("node.data", false).build());
-        assertEquals(11, profile.getNumConnections());
-        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
-        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
-        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
-        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
-        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
-
-        profile = TcpTransport.buildDefaultConnectionProfile(Settings.builder().put("node.data", false).put("node.master", false).build());
-        assertEquals(10, profile.getNumConnections());
-        assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING));
-        assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG));
-        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.STATE));
-        assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY));
-        assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK));
-    }
-
     public void testDecodeWithIncompleteHeader() throws IOException {
         BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14);
         streamOutput.write('E');
diff --git a/test/build.gradle b/test/build.gradle
index 2055896bda4..d0a3065e7c8 100644
--- a/test/build.gradle
+++ b/test/build.gradle
@@ -28,19 +28,10 @@ subprojects {
   apply plugin: 'nebula.maven-base-publish'
   apply plugin: 'nebula.maven-scm'
 
-
-  // the main files are actually test files, so use the appropriate forbidden api sigs
-  forbiddenApisMain {
-    signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
-                      PrecommitTasks.getResource('/forbidden/es-signatures.txt'),
-                      PrecommitTasks.getResource('/forbidden/es-test-signatures.txt')]
-  }
-
   // TODO: should we have licenses for our test deps?
   dependencyLicenses.enabled = false
   dependenciesInfo.enabled = false
 
   // TODO: why is the test framework pulled in...
-  forbiddenApisMain.enabled = false
   jarHell.enabled = false
 }
diff --git a/test/fixtures/build.gradle b/test/fixtures/build.gradle
index e69de29bb2d..153124e84b0 100644
--- a/test/fixtures/build.gradle
+++ b/test/fixtures/build.gradle
@@ -0,0 +1,5 @@
+
+subprojects {
+  // fixtures are mostly external and by default we don't want to check forbidden apis
+  forbiddenApisMain.enabled = false
+}
diff --git a/test/framework/build.gradle b/test/framework/build.gradle
index 5f1bc524da5..ab513a1b0bb 100644
--- a/test/framework/build.gradle
+++ b/test/framework/build.gradle
@@ -41,8 +41,9 @@ compileTestJava.options.compilerArgs << '-Xlint:-rawtypes'
 
 // the main files are actually test files, so use the appropriate forbidden api sigs
 forbiddenApisMain {
-  signaturesURLs = [PrecommitTasks.getResource('/forbidden/all-signatures.txt'),
-                    PrecommitTasks.getResource('/forbidden/test-signatures.txt')]
+  signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
+                    PrecommitTasks.getResource('/forbidden/es-all-signatures.txt'),
+                    PrecommitTasks.getResource('/forbidden/es-test-signatures.txt')]
 }
 
 // TODO: should we have licenses for our test deps?
diff --git a/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java b/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java
index 3fded43d858..5298c3995ce 100644
--- a/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/indices/analysis/AnalysisFactoryTestCase.java
@@ -67,7 +67,7 @@ public abstract class AnalysisFactoryTestCase extends ESTestCase {
         Matcher m = UNDERSCORE_THEN_ANYTHING.matcher(s);
         StringBuffer sb = new StringBuffer();
         while (m.find()) {
-            m.appendReplacement(sb, m.group(1).toUpperCase());
+            m.appendReplacement(sb, m.group(1).toUpperCase(Locale.ROOT));
         }
         m.appendTail(sb);
         sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java
index 0a11325311d..58593cbe2fd 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractBuilderTestCase.java
@@ -21,7 +21,6 @@ package org.elasticsearch.test;
 
 import com.carrotsearch.randomizedtesting.RandomizedTest;
 import com.carrotsearch.randomizedtesting.SeedUtils;
-
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.util.Accountable;
 import org.elasticsearch.Version;
@@ -42,6 +41,7 @@ import org.elasticsearch.common.settings.Setting;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.settings.SettingsModule;
 import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.core.internal.io.IOUtils;
 import org.elasticsearch.env.Environment;
 import org.elasticsearch.env.TestEnvironment;
 import org.elasticsearch.index.Index;
@@ -194,8 +194,8 @@ public abstract class AbstractBuilderTestCase extends ESTestCase {
 
     @AfterClass
     public static void afterClass() throws Exception {
-        org.apache.lucene.util.IOUtils.close(serviceHolder);
-        org.apache.lucene.util.IOUtils.close(serviceHolderWithNoType);
+        IOUtils.close(serviceHolder);
+        IOUtils.close(serviceHolderWithNoType);
         serviceHolder = null;
         serviceHolderWithNoType = null;
     }
diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
index 1498a69cf6a..922a6e0d276 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
@@ -54,6 +54,7 @@ import org.elasticsearch.cluster.ClusterModule;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.common.CheckedBiFunction;
 import org.elasticsearch.common.CheckedRunnable;
+import org.elasticsearch.common.SuppressForbidden;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.io.PathUtils;
 import org.elasticsearch.common.io.PathUtilsForTesting;
@@ -198,13 +199,9 @@ public abstract class ESTestCase extends LuceneTestCase {
     }
 
     static {
-        System.setProperty("log4j.shutdownHookEnabled", "false");
-        System.setProperty("log4j2.disable.jmx", "true");
-
+        setTestSysProps();
         LogConfigurator.loadLog4jPlugins();
 
-        // Enable Netty leak detection and monitor logger for logged leak errors
-        System.setProperty("io.netty.leakDetection.level", "paranoid");
         String leakLoggerName = "io.netty.util.ResourceLeakDetector";
         Logger leakLogger = LogManager.getLogger(leakLoggerName);
         Appender leakAppender = new AbstractAppender(leakLoggerName, null,
@@ -243,6 +240,14 @@ public abstract class ESTestCase extends LuceneTestCase {
         Collections.sort(javaZoneIds);
         JAVA_ZONE_IDS = Collections.unmodifiableList(javaZoneIds);
     }
+    @SuppressForbidden(reason = "force log4j and netty sysprops")
+    private static void setTestSysProps() {
+        System.setProperty("log4j.shutdownHookEnabled", "false");
+        System.setProperty("log4j2.disable.jmx", "true");
+
+        // Enable Netty leak detection and monitor logger for logged leak errors
+        System.setProperty("io.netty.leakDetection.level", "paranoid");
+    }
 
     protected final Logger logger = Loggers.getLogger(getClass());
     protected final DeprecationLogger deprecationLogger = new DeprecationLogger(logger);
diff --git a/test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java b/test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java
index d27a9453478..72d90a850ca 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/InternalTestCluster.java
@@ -385,9 +385,9 @@ public final class InternalTestCluster extends TestCluster {
 
         // randomize tcp settings
         if (random.nextBoolean()) {
-            builder.put(TcpTransport.CONNECTIONS_PER_NODE_RECOVERY.getKey(), random.nextInt(2) + 1);
-            builder.put(TcpTransport.CONNECTIONS_PER_NODE_BULK.getKey(), random.nextInt(3) + 1);
-            builder.put(TcpTransport.CONNECTIONS_PER_NODE_REG.getKey(), random.nextInt(6) + 1);
+            builder.put(TransportService.CONNECTIONS_PER_NODE_RECOVERY.getKey(), random.nextInt(2) + 1);
+            builder.put(TransportService.CONNECTIONS_PER_NODE_BULK.getKey(), random.nextInt(3) + 1);
+            builder.put(TransportService.CONNECTIONS_PER_NODE_REG.getKey(), random.nextInt(6) + 1);
         }
 
         if (random.nextBoolean()) {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/fixture/AbstractHttpFixture.java b/test/framework/src/main/java/org/elasticsearch/test/fixture/AbstractHttpFixture.java
index daa70298224..7fb4e7c55ff 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/fixture/AbstractHttpFixture.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/fixture/AbstractHttpFixture.java
@@ -20,6 +20,8 @@
 package org.elasticsearch.test.fixture;
 
 import com.sun.net.httpserver.HttpServer;
+import org.elasticsearch.common.SuppressForbidden;
+import org.elasticsearch.common.io.PathUtils;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -32,7 +34,6 @@ import java.net.SocketAddress;
 import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.util.HashMap;
 import java.util.List;
@@ -48,6 +49,7 @@ import static java.util.Collections.singletonMap;
 /**
  * Base class for test fixtures that requires a {@link HttpServer} to work.
  */
+@SuppressForbidden(reason = "uses httpserver by design")
 public abstract class AbstractHttpFixture {
 
     protected static final Map<String, String> TEXT_PLAIN_CONTENT_TYPE = contentType("text/plain; charset=utf-8");
@@ -62,7 +64,7 @@ public abstract class AbstractHttpFixture {
     private final Path workingDirectory;
 
     protected AbstractHttpFixture(final String workingDir) {
-        this.workingDirectory = Paths.get(Objects.requireNonNull(workingDir));
+        this.workingDirectory = PathUtils.get(Objects.requireNonNull(workingDir));
     }
 
     /**
diff --git a/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java b/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java
index 48fc7982074..418f4ea7b36 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java
@@ -30,7 +30,6 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.get.GetResponse;
@@ -112,10 +111,6 @@ public class ElasticsearchAssertions {
         assertAcked(builder.get());
     }
 
-    public static void assertAcked(DeleteIndexResponse response) {
-        assertThat("Delete Index failed - not acked", response.isAcknowledged(), equalTo(true));
-    }
-
     /**
      * Assert that an index creation was fully acknowledged, meaning that both the index creation cluster
      * state update was successful and that the requisite number of shard copies were started before returning.
diff --git a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java
index aeffd26e214..cddcca59e6c 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java
@@ -22,6 +22,7 @@ import com.carrotsearch.randomizedtesting.ReproduceErrorMessageBuilder;
 import org.apache.logging.log4j.Logger;
 import org.apache.lucene.util.Constants;
 import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.SuppressForbidden;
 import org.elasticsearch.common.logging.Loggers;
 import org.elasticsearch.test.ESIntegTestCase;
 import org.elasticsearch.test.ESTestCase;
@@ -86,7 +87,12 @@ public class ReproduceInfoPrinter extends RunListener {
             gradleMessageBuilder.appendClientYamlSuiteProperties();
         }
 
-        System.err.println(b.toString());
+        printToErr(b.toString());
+    }
+
+    @SuppressForbidden(reason = "printing repro info")
+    private static void printToErr(String s) {
+        System.err.println(s);
     }
 
     protected static class GradleMessageBuilder extends ReproduceErrorMessageBuilder {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/transport/MockTransportService.java b/test/framework/src/main/java/org/elasticsearch/test/transport/MockTransportService.java
index 40a6ad6476d..15ab06d651e 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/transport/MockTransportService.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/transport/MockTransportService.java
@@ -309,7 +309,7 @@ public final class MockTransportService extends TransportService {
             }
 
             // TODO: Replace with proper setting
-            TimeValue connectingTimeout = TcpTransport.TCP_CONNECT_TIMEOUT.getDefault(Settings.EMPTY);
+            TimeValue connectingTimeout = TransportService.TCP_CONNECT_TIMEOUT.getDefault(Settings.EMPTY);
             try {
                 if (delay.millis() < connectingTimeout.millis()) {
                     Thread.sleep(delay.millis());
diff --git a/test/framework/src/main/java/org/elasticsearch/test/transport/StubbableConnectionManager.java b/test/framework/src/main/java/org/elasticsearch/test/transport/StubbableConnectionManager.java
index a74cb2752c2..486ccc805d0 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/transport/StubbableConnectionManager.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/transport/StubbableConnectionManager.java
@@ -78,6 +78,11 @@ public class StubbableConnectionManager extends ConnectionManager {
         nodeConnectedBehaviors.remove(transportAddress);
     }
 
+    @Override
+    public Transport.Connection openConnection(DiscoveryNode node, ConnectionProfile connectionProfile) {
+        return delegate.openConnection(node, connectionProfile);
+    }
+
     @Override
     public Transport.Connection getConnection(DiscoveryNode node) {
         TransportAddress address = node.getAddress();
diff --git a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java
index 50b7b8ce575..29997b16ba0 100644
--- a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java
@@ -29,6 +29,7 @@ import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListenerResponseHandler;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.cluster.node.DiscoveryNode;
+import org.elasticsearch.common.SuppressForbidden;
 import org.elasticsearch.common.io.stream.BytesStreamOutput;
 import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
 import org.elasticsearch.common.io.stream.StreamInput;
@@ -64,6 +65,7 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -1894,7 +1896,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
             // means that once we received an ACK from the client we just drop the packet on the floor (which is what we want) and we run
             // into a connection timeout quickly. Yet other implementations can for instance can terminate the connection within the 3 way
             // handshake which I haven't tested yet.
-            socket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0), 1);
+            socket.bind(getLocalEphemeral(), 1);
             socket.setReuseAddress(true);
             DiscoveryNode first = new DiscoveryNode("TEST", new TransportAddress(socket.getInetAddress(),
                 socket.getLocalPort()), emptyMap(),
@@ -1995,11 +1997,11 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
             assertEquals("handshake failed", exception.getCause().getMessage());
         }
 
+        ConnectionProfile connectionProfile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY);
         try (TransportService service = buildService("TS_TPC", Version.CURRENT, null);
              TcpTransport.NodeChannels connection = originalTransport.openConnection(
                  new DiscoveryNode("TS_TPC", "TS_TPC", service.boundAddress().publishAddress(), emptyMap(), emptySet(), version0),
-                 null
-             )) {
+                 connectionProfile)) {
             Version version = originalTransport.executeHandshake(connection.getNode(),
                 connection.channel(TransportRequestOptions.Type.PING), TimeValue.timeValueSeconds(10));
             assertEquals(version, Version.CURRENT);
@@ -2008,7 +2010,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
 
     public void testTcpHandshakeTimeout() throws IOException {
         try (ServerSocket socket = new MockServerSocket()) {
-            socket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0), 1);
+            socket.bind(getLocalEphemeral(), 1);
             socket.setReuseAddress(true);
             DiscoveryNode dummy = new DiscoveryNode("TEST", new TransportAddress(socket.getInetAddress(),
                 socket.getLocalPort()), emptyMap(),
@@ -2029,7 +2031,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
 
     public void testTcpHandshakeConnectionReset() throws IOException, InterruptedException {
         try (ServerSocket socket = new MockServerSocket()) {
-            socket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0), 1);
+            socket.bind(getLocalEphemeral(), 1);
             socket.setReuseAddress(true);
             DiscoveryNode dummy = new DiscoveryNode("TEST", new TransportAddress(socket.getInetAddress(),
                 socket.getLocalPort()), emptyMap(),
@@ -2665,4 +2667,8 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
 
     protected abstract void closeConnectionChannel(Transport transport, Transport.Connection connection) throws IOException;
 
+    @SuppressForbidden(reason = "need local ephemeral port")
+    private InetSocketAddress getLocalEphemeral() throws UnknownHostException {
+        return new InetSocketAddress(InetAddress.getLocalHost(), 0);
+    }
 }
diff --git a/test/framework/src/main/java/org/elasticsearch/transport/MockTcpTransport.java b/test/framework/src/main/java/org/elasticsearch/transport/MockTcpTransport.java
index bbff340c860..e6d80ac24d8 100644
--- a/test/framework/src/main/java/org/elasticsearch/transport/MockTcpTransport.java
+++ b/test/framework/src/main/java/org/elasticsearch/transport/MockTcpTransport.java
@@ -18,6 +18,7 @@
  */
 package org.elasticsearch.transport;
 
+import org.elasticsearch.cli.SuppressForbidden;
 import org.elasticsearch.core.internal.io.IOUtils;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
@@ -160,6 +161,7 @@ public class MockTcpTransport extends TcpTransport {
     }
 
     @Override
+    @SuppressForbidden(reason = "real socket for mocking remote connections")
     protected MockChannel initiateChannel(InetSocketAddress address, ActionListener<Void> connectListener) throws IOException {
         final MockSocket socket = new MockSocket();
         final MockChannel channel = new MockChannel(socket, address, "none");
@@ -189,12 +191,11 @@ public class MockTcpTransport extends TcpTransport {
     }
 
     @Override
-    protected ConnectionProfile resolveConnectionProfile(ConnectionProfile connectionProfile) {
-        ConnectionProfile connectionProfile1 = resolveConnectionProfile(connectionProfile, defaultConnectionProfile);
+    protected ConnectionProfile maybeOverrideConnectionProfile(ConnectionProfile connectionProfile) {
         ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
         Set<TransportRequestOptions.Type> allTypesWithConnection = new HashSet<>();
         Set<TransportRequestOptions.Type> allTypesWithoutConnection = new HashSet<>();
-        for (ConnectionProfile.ConnectionTypeHandle handle : connectionProfile1.getHandles()) {
+        for (ConnectionProfile.ConnectionTypeHandle handle : connectionProfile.getHandles()) {
             Set<TransportRequestOptions.Type> types = handle.getTypes();
             if (handle.length > 0) {
                 allTypesWithConnection.addAll(types);
@@ -207,8 +208,8 @@ public class MockTcpTransport extends TcpTransport {
         if (allTypesWithoutConnection.isEmpty() == false) {
             builder.addConnections(0, allTypesWithoutConnection.toArray(new TransportRequestOptions.Type[0]));
         }
-        builder.setHandshakeTimeout(connectionProfile1.getHandshakeTimeout());
-        builder.setConnectTimeout(connectionProfile1.getConnectTimeout());
+        builder.setHandshakeTimeout(connectionProfile.getHandshakeTimeout());
+        builder.setConnectTimeout(connectionProfile.getConnectTimeout());
         return builder.build();
     }
 
diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/MockNioTransport.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/MockNioTransport.java
index dc5305d951b..fbe61db6ee7 100644
--- a/test/framework/src/main/java/org/elasticsearch/transport/nio/MockNioTransport.java
+++ b/test/framework/src/main/java/org/elasticsearch/transport/nio/MockNioTransport.java
@@ -133,16 +133,15 @@ public class MockNioTransport extends TcpTransport {
     }
 
     @Override
-    protected ConnectionProfile resolveConnectionProfile(ConnectionProfile connectionProfile) {
-        ConnectionProfile resolvedProfile = resolveConnectionProfile(connectionProfile, defaultConnectionProfile);
-        if (resolvedProfile.getNumConnections() <= 3) {
-            return resolvedProfile;
+    protected ConnectionProfile maybeOverrideConnectionProfile(ConnectionProfile connectionProfile) {
+        if (connectionProfile.getNumConnections() <= 3) {
+            return connectionProfile;
         }
         ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
         Set<TransportRequestOptions.Type> allTypesWithConnection = new HashSet<>();
         Set<TransportRequestOptions.Type> allTypesWithoutConnection = new HashSet<>();
         for (TransportRequestOptions.Type type : TransportRequestOptions.Type.values()) {
-            int numConnections = resolvedProfile.getNumConnectionsPerType(type);
+            int numConnections = connectionProfile.getNumConnectionsPerType(type);
             if (numConnections > 0) {
                 allTypesWithConnection.add(type);
             } else {
@@ -155,8 +154,8 @@ public class MockNioTransport extends TcpTransport {
         if (allTypesWithoutConnection.isEmpty() == false) {
             builder.addConnections(0, allTypesWithoutConnection.toArray(new TransportRequestOptions.Type[0]));
         }
-        builder.setHandshakeTimeout(resolvedProfile.getHandshakeTimeout());
-        builder.setConnectTimeout(resolvedProfile.getConnectTimeout());
+        builder.setHandshakeTimeout(connectionProfile.getHandshakeTimeout());
+        builder.setConnectTimeout(connectionProfile.getConnectTimeout());
         return builder.build();
     }
 
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseAction.java
index e8d5b3f3f57..c0dbb02aed7 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseAction.java
@@ -6,9 +6,9 @@
 package org.elasticsearch.license;
 
 import org.elasticsearch.action.Action;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
-public class DeleteLicenseAction extends Action<DeleteLicenseResponse> {
+public class DeleteLicenseAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteLicenseAction INSTANCE = new DeleteLicenseAction();
     public static final String NAME = "cluster:admin/xpack/license/delete";
@@ -18,7 +18,7 @@ public class DeleteLicenseAction extends Action<DeleteLicenseResponse> {
     }
 
     @Override
-    public DeleteLicenseResponse newResponse() {
-        return new DeleteLicenseResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseRequestBuilder.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseRequestBuilder.java
index ad58cd3e1a5..1aaa246dbe6 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseRequestBuilder.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/DeleteLicenseRequestBuilder.java
@@ -6,11 +6,11 @@
 package org.elasticsearch.license;
 
 import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
 
-public class DeleteLicenseRequestBuilder extends AcknowledgedRequestBuilder<DeleteLicenseRequest, DeleteLicenseResponse,
+public class DeleteLicenseRequestBuilder extends AcknowledgedRequestBuilder<DeleteLicenseRequest, AcknowledgedResponse,
         DeleteLicenseRequestBuilder> {
 
     public DeleteLicenseRequestBuilder(ElasticsearchClient client) {
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java
index dfccd1d4190..80d1fb68f0e 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicensingClient.java
@@ -6,9 +6,9 @@
 package org.elasticsearch.license;
 
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
 import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
 import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
 
@@ -40,7 +40,7 @@ public class LicensingClient {
         return new DeleteLicenseRequestBuilder(client);
     }
 
-    public void deleteLicense(DeleteLicenseRequest request, ActionListener<DeleteLicenseResponse> listener) {
+    public void deleteLicense(DeleteLicenseRequest request, ActionListener<AcknowledgedResponse> listener) {
         client.execute(DeleteLicenseAction.INSTANCE, request, listener);
     }
 
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java
index 4a6b5e0116f..d1230808bd8 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java
@@ -8,21 +8,21 @@ package org.elasticsearch.license;
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
-import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
 import org.elasticsearch.cluster.block.ClusterBlockException;
 import org.elasticsearch.cluster.block.ClusterBlockLevel;
 import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
+import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 
-public class TransportDeleteLicenseAction extends TransportMasterNodeAction<DeleteLicenseRequest, DeleteLicenseResponse> {
+public class TransportDeleteLicenseAction extends TransportMasterNodeAction<DeleteLicenseRequest, AcknowledgedResponse> {
 
     private final LicenseService licenseService;
 
@@ -41,8 +41,8 @@ public class TransportDeleteLicenseAction extends TransportMasterNodeAction<Dele
     }
 
     @Override
-    protected DeleteLicenseResponse newResponse() {
-        return new DeleteLicenseResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -51,12 +51,12 @@ public class TransportDeleteLicenseAction extends TransportMasterNodeAction<Dele
     }
 
     @Override
-    protected void masterOperation(final DeleteLicenseRequest request, ClusterState state, final ActionListener<DeleteLicenseResponse>
+    protected void masterOperation(final DeleteLicenseRequest request, ClusterState state, final ActionListener<AcknowledgedResponse>
             listener) throws ElasticsearchException {
         licenseService.removeLicense(request, new ActionListener<ClusterStateUpdateResponse>() {
             @Override
             public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
-                listener.onResponse(new DeleteLicenseResponse(clusterStateUpdateResponse.isAcknowledged()));
+                listener.onResponse(new AcknowledgedResponse(clusterStateUpdateResponse.isAcknowledged()));
             }
 
             @Override
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java
index 1a80c6d873b..fb4ce0b90f4 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java
@@ -14,6 +14,7 @@ import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings;
 import org.elasticsearch.xpack.core.ssl.VerificationMode;
 
 import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
 
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -127,8 +128,16 @@ public class XPackSettings {
     public static final Setting<String> PASSWORD_HASHING_ALGORITHM = new Setting<>(
         "xpack.security.authc.password_hashing.algorithm", "bcrypt", Function.identity(), (v, s) -> {
         if (Hasher.getAvailableAlgoStoredHash().contains(v.toLowerCase(Locale.ROOT)) == false) {
-            throw new IllegalArgumentException("Invalid algorithm: " + v + ". Only pbkdf2 or bcrypt family algorithms can be used for " +
-                "password hashing.");
+            throw new IllegalArgumentException("Invalid algorithm: " + v + ". Valid values for password hashing are " +
+                Hasher.getAvailableAlgoStoredHash().toString());
+        } else if (v.regionMatches(true, 0, "pbkdf2", 0, "pbkdf2".length())) {
+            try {
+                SecretKeyFactory.getInstance("PBKDF2withHMACSHA512");
+            } catch (NoSuchAlgorithmException e) {
+                throw new IllegalArgumentException(
+                    "Support for PBKDF2WithHMACSHA512 must be available in order to use any of the " +
+                        "PBKDF2 algorithms for the [xpack.security.authc.password_hashing.algorithm] setting.", e);
+            }
         }
     }, Setting.Property.NodeScope);
 
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarAction.java
index a6e5f8da88c..da0756157b0 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarAction.java
@@ -19,7 +19,7 @@ import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 import java.io.IOException;
 import java.util.Objects;
 
-public class DeleteCalendarAction extends Action<DeleteCalendarAction.Response> {
+public class DeleteCalendarAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteCalendarAction INSTANCE = new DeleteCalendarAction();
     public static final String NAME = "cluster:admin/xpack/ml/calendars/delete";
@@ -29,8 +29,8 @@ public class DeleteCalendarAction extends Action<DeleteCalendarAction.Response>
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> {
@@ -82,19 +82,10 @@ public class DeleteCalendarAction extends Action<DeleteCalendarAction.Response>
         }
     }
 
-    public static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    public static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         public RequestBuilder(ElasticsearchClient client, DeleteCalendarAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        public Response() {}
-    }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarEventAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarEventAction.java
index 24fc55f59cc..3e64a542939 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarEventAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteCalendarEventAction.java
@@ -20,7 +20,7 @@ import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 import java.io.IOException;
 import java.util.Objects;
 
-public class DeleteCalendarEventAction extends Action<DeleteCalendarEventAction.Response> {
+public class DeleteCalendarEventAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteCalendarEventAction INSTANCE = new DeleteCalendarEventAction();
     public static final String NAME = "cluster:admin/xpack/ml/calendars/events/delete";
@@ -30,8 +30,8 @@ public class DeleteCalendarEventAction extends Action<DeleteCalendarEventAction.
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> {
@@ -89,19 +89,10 @@ public class DeleteCalendarEventAction extends Action<DeleteCalendarEventAction.
         }
     }
 
-    public static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    public static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         public RequestBuilder(ElasticsearchClient client, DeleteCalendarEventAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        private Response() {}
-    }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteDatafeedAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteDatafeedAction.java
index fba0fe4cf1f..fb3ac55cda0 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteDatafeedAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteDatafeedAction.java
@@ -23,7 +23,7 @@ import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 import java.io.IOException;
 import java.util.Objects;
 
-public class DeleteDatafeedAction extends Action<DeleteDatafeedAction.Response> {
+public class DeleteDatafeedAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteDatafeedAction INSTANCE = new DeleteDatafeedAction();
     public static final String NAME = "cluster:admin/xpack/ml/datafeeds/delete";
@@ -33,8 +33,8 @@ public class DeleteDatafeedAction extends Action<DeleteDatafeedAction.Response>
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> implements ToXContentFragment {
@@ -106,21 +106,10 @@ public class DeleteDatafeedAction extends Action<DeleteDatafeedAction.Response>
         }
     }
 
-    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, Response, RequestBuilder> {
+    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, AcknowledgedResponse, RequestBuilder> {
 
         public RequestBuilder(ElasticsearchClient client, DeleteDatafeedAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response() {
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-    }
-
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteFilterAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteFilterAction.java
index b271c6fbdf0..3870ad79555 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteFilterAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteFilterAction.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.util.Objects;
 
 
-public class DeleteFilterAction extends Action<DeleteFilterAction.Response> {
+public class DeleteFilterAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteFilterAction INSTANCE = new DeleteFilterAction();
     public static final String NAME = "cluster:admin/xpack/ml/filters/delete";
@@ -30,8 +30,8 @@ public class DeleteFilterAction extends Action<DeleteFilterAction.Response> {
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> {
@@ -84,21 +84,11 @@ public class DeleteFilterAction extends Action<DeleteFilterAction.Response> {
         }
     }
 
-    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, Response, RequestBuilder> {
+    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, AcknowledgedResponse, RequestBuilder> {
 
         public RequestBuilder(ElasticsearchClient client, DeleteFilterAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        public Response() {}
-    }
-
 }
 
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteJobAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteJobAction.java
index 71e5f8fad71..933e98b80ff 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteJobAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteJobAction.java
@@ -24,7 +24,7 @@ import java.io.IOException;
 import java.util.Map;
 import java.util.Objects;
 
-public class DeleteJobAction extends Action<DeleteJobAction.Response> {
+public class DeleteJobAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteJobAction INSTANCE = new DeleteJobAction();
     public static final String NAME = "cluster:admin/xpack/ml/job/delete";
@@ -34,8 +34,8 @@ public class DeleteJobAction extends Action<DeleteJobAction.Response> {
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> {
@@ -111,20 +111,10 @@ public class DeleteJobAction extends Action<DeleteJobAction.Response> {
         }
     }
 
-    static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, Response, RequestBuilder> {
+    static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, AcknowledgedResponse, RequestBuilder> {
 
         RequestBuilder(ElasticsearchClient client, DeleteJobAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        public Response() {}
-    }
-
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteModelSnapshotAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteModelSnapshotAction.java
index a80fbc78638..4bc079b387c 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteModelSnapshotAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/DeleteModelSnapshotAction.java
@@ -19,7 +19,7 @@ import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 
 import java.io.IOException;
 
-public class DeleteModelSnapshotAction extends Action<DeleteModelSnapshotAction.Response> {
+public class DeleteModelSnapshotAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteModelSnapshotAction INSTANCE = new DeleteModelSnapshotAction();
     public static final String NAME = "cluster:admin/xpack/ml/job/model_snapshots/delete";
@@ -29,8 +29,8 @@ public class DeleteModelSnapshotAction extends Action<DeleteModelSnapshotAction.
     }
 
     @Override
-    public DeleteModelSnapshotAction.Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends ActionRequest {
@@ -74,16 +74,7 @@ public class DeleteModelSnapshotAction extends Action<DeleteModelSnapshotAction.
         }
     }
 
-    public static class Response extends AcknowledgedResponse {
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        public Response() {}
-    }
-
-    public static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    public static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         public RequestBuilder(ElasticsearchClient client, DeleteModelSnapshotAction action) {
             super(client, action, new Request());
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/FinalizeJobExecutionAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/FinalizeJobExecutionAction.java
index 558d25f62de..9121ce1b75d 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/FinalizeJobExecutionAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/FinalizeJobExecutionAction.java
@@ -16,7 +16,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
 
 import java.io.IOException;
 
-public class FinalizeJobExecutionAction extends Action<FinalizeJobExecutionAction.Response> {
+public class FinalizeJobExecutionAction extends Action<AcknowledgedResponse> {
 
     public static final FinalizeJobExecutionAction INSTANCE = new FinalizeJobExecutionAction();
     public static final String NAME = "cluster:internal/xpack/ml/job/finalize_job_execution";
@@ -26,8 +26,8 @@ public class FinalizeJobExecutionAction extends Action<FinalizeJobExecutionActio
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends MasterNodeRequest<Request> {
@@ -64,21 +64,10 @@ public class FinalizeJobExecutionAction extends Action<FinalizeJobExecutionActio
     }
 
     public static class RequestBuilder
-            extends MasterNodeOperationRequestBuilder<Request, Response, RequestBuilder> {
+            extends MasterNodeOperationRequestBuilder<Request, AcknowledgedResponse, RequestBuilder> {
 
         public RequestBuilder(ElasticsearchClient client, FinalizeJobExecutionAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        public Response() {
-        }
-    }
-
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/OpenJobAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/OpenJobAction.java
index 0c7380349bd..c108a983aa1 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/OpenJobAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/OpenJobAction.java
@@ -31,7 +31,7 @@ import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 import java.io.IOException;
 import java.util.Objects;
 
-public class OpenJobAction extends Action<OpenJobAction.Response> {
+public class OpenJobAction extends Action<AcknowledgedResponse> {
 
     public static final OpenJobAction INSTANCE = new OpenJobAction();
     public static final String NAME = "cluster:admin/xpack/ml/job/open";
@@ -42,8 +42,8 @@ public class OpenJobAction extends Action<OpenJobAction.Response> {
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends MasterNodeRequest<Request> implements ToXContentObject {
@@ -244,30 +244,6 @@ public class OpenJobAction extends Action<OpenJobAction.Response> {
         }
     }
 
-    public static class Response extends AcknowledgedResponse {
-        public Response() {
-            super();
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-            AcknowledgedResponse that = (AcknowledgedResponse) o;
-            return isAcknowledged() == that.isAcknowledged();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(isAcknowledged());
-        }
-
-    }
-
     public interface JobTaskMatcher {
 
         static boolean match(Task task, String expectedJobId) {
@@ -276,7 +252,7 @@ public class OpenJobAction extends Action<OpenJobAction.Response> {
         }
     }
 
-    static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         RequestBuilder(ElasticsearchClient client, OpenJobAction action) {
             super(client, action, new Request());
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/StartDatafeedAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/StartDatafeedAction.java
index 5c45d33e744..9c4a67ec61f 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/StartDatafeedAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/StartDatafeedAction.java
@@ -34,7 +34,7 @@ import java.io.IOException;
 import java.util.Objects;
 import java.util.function.LongSupplier;
 
-public class StartDatafeedAction extends Action<StartDatafeedAction.Response> {
+public class StartDatafeedAction extends Action<AcknowledgedResponse> {
 
     public static final ParseField START_TIME = new ParseField("start");
     public static final ParseField END_TIME = new ParseField("end");
@@ -49,8 +49,8 @@ public class StartDatafeedAction extends Action<StartDatafeedAction.Response> {
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends MasterNodeRequest<Request> implements ToXContentObject {
@@ -279,31 +279,7 @@ public class StartDatafeedAction extends Action<StartDatafeedAction.Response> {
         }
     }
 
-    public static class Response extends AcknowledgedResponse {
-        public Response() {
-            super();
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-            AcknowledgedResponse that = (AcknowledgedResponse) o;
-            return isAcknowledged() == that.isAcknowledged();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(isAcknowledged());
-        }
-
-    }
-
-    static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         RequestBuilder(ElasticsearchClient client, StartDatafeedAction action) {
             super(client, action, new Request());
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateDetectorAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateDetectorAction.java
index 15dd8721f06..e0d6b8acd84 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateDetectorAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateDetectorAction.java
@@ -21,7 +21,7 @@ import org.elasticsearch.xpack.core.ml.job.config.Detector;
 import java.io.IOException;
 import java.util.Objects;
 
-public class ValidateDetectorAction extends Action<ValidateDetectorAction.Response> {
+public class ValidateDetectorAction extends Action<AcknowledgedResponse> {
 
     public static final ValidateDetectorAction INSTANCE = new ValidateDetectorAction();
     public static final String NAME = "cluster:admin/xpack/ml/job/validate/detector";
@@ -31,11 +31,11 @@ public class ValidateDetectorAction extends Action<ValidateDetectorAction.Respon
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
-    public static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    public static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         protected RequestBuilder(ElasticsearchClient client, ValidateDetectorAction action) {
             super(client, action, new Request());
@@ -105,16 +105,4 @@ public class ValidateDetectorAction extends Action<ValidateDetectorAction.Respon
         }
 
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response() {
-            super();
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-    }
-
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateJobConfigAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateJobConfigAction.java
index 4e77882c1fc..8854aa38c8f 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateJobConfigAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/action/ValidateJobConfigAction.java
@@ -22,7 +22,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 
-public class ValidateJobConfigAction extends Action<ValidateJobConfigAction.Response> {
+public class ValidateJobConfigAction extends Action<AcknowledgedResponse> {
 
     public static final ValidateJobConfigAction INSTANCE = new ValidateJobConfigAction();
     public static final String NAME = "cluster:admin/xpack/ml/job/validate";
@@ -32,11 +32,11 @@ public class ValidateJobConfigAction extends Action<ValidateJobConfigAction.Resp
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
-    public static class RequestBuilder extends ActionRequestBuilder<Request, Response> {
+    public static class RequestBuilder extends ActionRequestBuilder<Request, AcknowledgedResponse> {
 
         protected RequestBuilder(ElasticsearchClient client, ValidateJobConfigAction action) {
             super(client, action, new Request());
@@ -111,16 +111,4 @@ public class ValidateJobConfigAction extends Action<ValidateJobConfigAction.Resp
         }
 
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response() {
-            super();
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-    }
-
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/client/MachineLearningClient.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/client/MachineLearningClient.java
index 3308d6891e2..af2f3ad08fd 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/client/MachineLearningClient.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/client/MachineLearningClient.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.core.ml.client;
 import org.elasticsearch.action.ActionFuture;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.PlainActionFuture;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.ElasticsearchClient;
 import org.elasticsearch.xpack.core.ml.action.CloseJobAction;
 import org.elasticsearch.xpack.core.ml.action.DeleteDatafeedAction;
@@ -59,48 +60,48 @@ public class MachineLearningClient {
     }
 
     public void deleteDatafeed(DeleteDatafeedAction.Request request,
-            ActionListener<DeleteDatafeedAction.Response> listener) {
+            ActionListener<AcknowledgedResponse> listener) {
         client.execute(DeleteDatafeedAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<DeleteDatafeedAction.Response> deleteDatafeed(
+    public ActionFuture<AcknowledgedResponse> deleteDatafeed(
             DeleteDatafeedAction.Request request) {
-        PlainActionFuture<DeleteDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(DeleteDatafeedAction.INSTANCE, request, listener);
         return listener;
     }
 
     public void deleteFilter(DeleteFilterAction.Request request,
-            ActionListener<DeleteFilterAction.Response> listener) {
+            ActionListener<AcknowledgedResponse> listener) {
         client.execute(DeleteFilterAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<DeleteFilterAction.Response> deleteFilter(
+    public ActionFuture<AcknowledgedResponse> deleteFilter(
             DeleteFilterAction.Request request) {
-        PlainActionFuture<DeleteFilterAction.Response> listener = PlainActionFuture.newFuture();
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(DeleteFilterAction.INSTANCE, request, listener);
         return listener;
     }
 
     public void deleteJob(DeleteJobAction.Request request,
-            ActionListener<DeleteJobAction.Response> listener) {
+            ActionListener<AcknowledgedResponse> listener) {
         client.execute(DeleteJobAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<DeleteJobAction.Response> deleteJob(DeleteJobAction.Request request) {
-        PlainActionFuture<DeleteJobAction.Response> listener = PlainActionFuture.newFuture();
+    public ActionFuture<AcknowledgedResponse> deleteJob(DeleteJobAction.Request request) {
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(DeleteJobAction.INSTANCE, request, listener);
         return listener;
     }
 
     public void deleteModelSnapshot(DeleteModelSnapshotAction.Request request,
-            ActionListener<DeleteModelSnapshotAction.Response> listener) {
+            ActionListener<AcknowledgedResponse> listener) {
         client.execute(DeleteModelSnapshotAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<DeleteModelSnapshotAction.Response> deleteModelSnapshot(
+    public ActionFuture<AcknowledgedResponse> deleteModelSnapshot(
             DeleteModelSnapshotAction.Request request) {
-        PlainActionFuture<DeleteModelSnapshotAction.Response> listener = PlainActionFuture.newFuture();
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(DeleteModelSnapshotAction.INSTANCE, request, listener);
         return listener;
     }
@@ -233,12 +234,12 @@ public class MachineLearningClient {
     }
 
     public void openJob(OpenJobAction.Request request,
-            ActionListener<OpenJobAction.Response> listener) {
+            ActionListener<AcknowledgedResponse> listener) {
         client.execute(OpenJobAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<OpenJobAction.Response> openJob(OpenJobAction.Request request) {
-        PlainActionFuture<OpenJobAction.Response> listener = PlainActionFuture.newFuture();
+    public ActionFuture<AcknowledgedResponse> openJob(OpenJobAction.Request request) {
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(OpenJobAction.INSTANCE, request, listener);
         return listener;
     }
@@ -300,13 +301,13 @@ public class MachineLearningClient {
     }
 
     public void startDatafeed(StartDatafeedAction.Request request,
-            ActionListener<StartDatafeedAction.Response> listener) {
+            ActionListener<AcknowledgedResponse> listener) {
         client.execute(StartDatafeedAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<StartDatafeedAction.Response> startDatafeed(
+    public ActionFuture<AcknowledgedResponse> startDatafeed(
             StartDatafeedAction.Request request) {
-        PlainActionFuture<StartDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(StartDatafeedAction.INSTANCE, request, listener);
         return listener;
     }
@@ -359,25 +360,25 @@ public class MachineLearningClient {
     }
 
     public void validateDetector(ValidateDetectorAction.Request request,
-                                    ActionListener<ValidateDetectorAction.Response> listener) {
+                                    ActionListener<AcknowledgedResponse> listener) {
         client.execute(ValidateDetectorAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<ValidateDetectorAction.Response> validateDetector(
+    public ActionFuture<AcknowledgedResponse> validateDetector(
             ValidateDetectorAction.Request request) {
-        PlainActionFuture<ValidateDetectorAction.Response> listener = PlainActionFuture.newFuture();
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(ValidateDetectorAction.INSTANCE, request, listener);
         return listener;
     }
 
     public void validateJobConfig(ValidateJobConfigAction.Request request,
-                                 ActionListener<ValidateJobConfigAction.Response> listener) {
+                                 ActionListener<AcknowledgedResponse> listener) {
         client.execute(ValidateJobConfigAction.INSTANCE, request, listener);
     }
 
-    public ActionFuture<ValidateJobConfigAction.Response> validateJobConfig(
+    public ActionFuture<AcknowledgedResponse> validateJobConfig(
             ValidateJobConfigAction.Request request) {
-        PlainActionFuture<ValidateJobConfigAction.Response> listener = PlainActionFuture.newFuture();
+        PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
         client.execute(ValidateJobConfigAction.INSTANCE, request, listener);
         return listener;
     }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfig.java
index 5badd073c66..135ad755359 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfig.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfig.java
@@ -64,7 +64,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
     private static final ParseField OVERLAPPING_BUCKETS = new ParseField("overlapping_buckets");
     private static final ParseField RESULT_FINALIZATION_WINDOW = new ParseField("result_finalization_window");
     private static final ParseField MULTIVARIATE_BY_FIELDS = new ParseField("multivariate_by_fields");
-    private static final ParseField USER_PER_PARTITION_NORMALIZATION = new ParseField("use_per_partition_normalization");
 
     public static final String ML_CATEGORY_FIELD = "mlcategory";
     public static final Set<String> AUTO_CREATED_FIELDS = new HashSet<>(Collections.singletonList(ML_CATEGORY_FIELD));
@@ -98,7 +97,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         parser.declareBoolean(Builder::setOverlappingBuckets, OVERLAPPING_BUCKETS);
         parser.declareLong(Builder::setResultFinalizationWindow, RESULT_FINALIZATION_WINDOW);
         parser.declareBoolean(Builder::setMultivariateByFields, MULTIVARIATE_BY_FIELDS);
-        parser.declareBoolean(Builder::setUsePerPartitionNormalization, USER_PER_PARTITION_NORMALIZATION);
 
         return parser;
     }
@@ -117,12 +115,11 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
     private final Boolean overlappingBuckets;
     private final Long resultFinalizationWindow;
     private final Boolean multivariateByFields;
-    private final boolean usePerPartitionNormalization;
 
     private AnalysisConfig(TimeValue bucketSpan, String categorizationFieldName, List<String> categorizationFilters,
                            CategorizationAnalyzerConfig categorizationAnalyzerConfig, TimeValue latency, String summaryCountFieldName,
                            List<Detector> detectors, List<String> influencers, Boolean overlappingBuckets, Long resultFinalizationWindow,
-                           Boolean multivariateByFields, boolean usePerPartitionNormalization) {
+                           Boolean multivariateByFields) {
         this.detectors = detectors;
         this.bucketSpan = bucketSpan;
         this.latency = latency;
@@ -134,7 +131,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         this.overlappingBuckets = overlappingBuckets;
         this.resultFinalizationWindow = resultFinalizationWindow;
         this.multivariateByFields = multivariateByFields;
-        this.usePerPartitionNormalization = usePerPartitionNormalization;
     }
 
     public AnalysisConfig(StreamInput in) throws IOException {
@@ -165,7 +161,12 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
             }
         }
 
-        usePerPartitionNormalization = in.readBoolean();
+        // BWC for removed per-partition normalization
+        // Version check is temporarily against the latest to satisfy CI tests
+        // TODO change to V_6_5_0 after successful backport to 6.x
+        if (in.getVersion().before(Version.V_7_0_0_alpha1)) {
+            in.readBoolean();
+        }
     }
 
     @Override
@@ -195,7 +196,12 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
             out.writeBoolean(false);
         }
 
-        out.writeBoolean(usePerPartitionNormalization);
+        // BWC for removed per-partition normalization
+        // Version check is temporarily against the latest to satisfy CI tests
+        // TODO change to V_6_5_0 after successful backport to 6.x
+        if (out.getVersion().before(Version.V_7_0_0_alpha1)) {
+            out.writeBoolean(false);
+        }
     }
 
     /**
@@ -299,10 +305,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         return multivariateByFields;
     }
 
-    public boolean getUsePerPartitionNormalization() {
-        return usePerPartitionNormalization;
-    }
-
     /**
      * Return the set of fields required by the analysis.
      * These are the influencer fields, metric field, partition field,
@@ -403,9 +405,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         if (multivariateByFields != null) {
             builder.field(MULTIVARIATE_BY_FIELDS.getPreferredName(), multivariateByFields);
         }
-        if (usePerPartitionNormalization) {
-            builder.field(USER_PER_PARTITION_NORMALIZATION.getPreferredName(), usePerPartitionNormalization);
-        }
         builder.endObject();
         return builder;
     }
@@ -416,7 +415,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         if (o == null || getClass() != o.getClass()) return false;
         AnalysisConfig that = (AnalysisConfig) o;
         return Objects.equals(latency, that.latency) &&
-                usePerPartitionNormalization == that.usePerPartitionNormalization &&
                 Objects.equals(bucketSpan, that.bucketSpan) &&
                 Objects.equals(categorizationFieldName, that.categorizationFieldName) &&
                 Objects.equals(categorizationFilters, that.categorizationFilters) &&
@@ -434,7 +432,7 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         return Objects.hash(
                 bucketSpan, categorizationFieldName, categorizationFilters, categorizationAnalyzerConfig, latency,
                 summaryCountFieldName, detectors, influencers, overlappingBuckets, resultFinalizationWindow,
-                multivariateByFields, usePerPartitionNormalization
+                multivariateByFields
         );
     }
 
@@ -453,7 +451,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
         private Boolean overlappingBuckets;
         private Long resultFinalizationWindow;
         private Boolean multivariateByFields;
-        private boolean usePerPartitionNormalization = false;
 
         public Builder(List<Detector> detectors) {
             setDetectors(detectors);
@@ -472,7 +469,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
             this.overlappingBuckets = analysisConfig.overlappingBuckets;
             this.resultFinalizationWindow = analysisConfig.resultFinalizationWindow;
             this.multivariateByFields = analysisConfig.multivariateByFields;
-            this.usePerPartitionNormalization = analysisConfig.usePerPartitionNormalization;
         }
 
         public void setDetectors(List<Detector> detectors) {
@@ -535,10 +531,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
             this.multivariateByFields = multivariateByFields;
         }
 
-        public void setUsePerPartitionNormalization(boolean usePerPartitionNormalization) {
-            this.usePerPartitionNormalization = usePerPartitionNormalization;
-        }
-
         /**
          * Checks the configuration is valid
          * <ol>
@@ -571,16 +563,11 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
 
             overlappingBuckets = verifyOverlappingBucketsConfig(overlappingBuckets, detectors);
 
-            if (usePerPartitionNormalization) {
-                checkDetectorsHavePartitionFields(detectors);
-                checkNoInfluencersAreSet(influencers);
-            }
-
             verifyNoInconsistentNestedFieldNames();
 
             return new AnalysisConfig(bucketSpan, categorizationFieldName, categorizationFilters, categorizationAnalyzerConfig,
                     latency, summaryCountFieldName, detectors, influencers, overlappingBuckets,
-                    resultFinalizationWindow, multivariateByFields, usePerPartitionNormalization);
+                    resultFinalizationWindow, multivariateByFields);
         }
 
         private void verifyNoMetricFunctionsWhenSummaryCountFieldNameIsSet() {
@@ -704,23 +691,6 @@ public class AnalysisConfig implements ToXContentObject, Writeable {
             }
         }
 
-        private static void checkDetectorsHavePartitionFields(List<Detector> detectors) {
-            for (Detector detector : detectors) {
-                if (!Strings.isNullOrEmpty(detector.getPartitionFieldName())) {
-                    return;
-                }
-            }
-            throw ExceptionsHelper.badRequestException(Messages.getMessage(
-                    Messages.JOB_CONFIG_PER_PARTITION_NORMALIZATION_REQUIRES_PARTITION_FIELD));
-        }
-
-        private static void checkNoInfluencersAreSet(List<String> influencers) {
-            if (!influencers.isEmpty()) {
-                throw ExceptionsHelper.badRequestException(Messages.getMessage(
-                        Messages.JOB_CONFIG_PER_PARTITION_NORMALIZATION_CANNOT_USE_INFLUENCERS));
-            }
-        }
-
         private static boolean isValidRegex(String exp) {
             try {
                 Pattern.compile(exp);
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/messages/Messages.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/messages/Messages.java
index 289839b9342..7411115bda3 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/messages/Messages.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/messages/Messages.java
@@ -130,10 +130,6 @@ public final class Messages {
             "over_field_name cannot be used with function ''{0}''";
     public static final String JOB_CONFIG_OVERLAPPING_BUCKETS_INCOMPATIBLE_FUNCTION =
             "Overlapping buckets cannot be used with function ''{0}''";
-    public static final String JOB_CONFIG_PER_PARTITION_NORMALIZATION_CANNOT_USE_INFLUENCERS =
-            "A job configured with Per-Partition Normalization cannot use influencers";
-    public static final String JOB_CONFIG_PER_PARTITION_NORMALIZATION_REQUIRES_PARTITION_FIELD =
-            "If the job is configured with Per-Partition Normalization enabled a detector must have a partition field";
     public static final String JOB_CONFIG_UNKNOWN_FUNCTION = "Unknown function ''{0}''";
     public static final String JOB_CONFIG_UPDATE_ANALYSIS_LIMITS_MODEL_MEMORY_LIMIT_CANNOT_BE_DECREASED =
             "Invalid update value for analysis_limits: model_memory_limit cannot be decreased below current usage; " +
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java
index bc420c658d0..316417f4b23 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/ElasticsearchMappings.java
@@ -227,23 +227,6 @@ public class ElasticsearchMappings {
             .startObject(Bucket.SCHEDULED_EVENTS.getPreferredName())
                 .field(TYPE, KEYWORD)
             .endObject()
-            .startObject(Bucket.PARTITION_SCORES.getPreferredName())
-                .field(TYPE, NESTED)
-                .startObject(PROPERTIES)
-                    .startObject(AnomalyRecord.PARTITION_FIELD_NAME.getPreferredName())
-                        .field(TYPE, KEYWORD)
-                    .endObject()
-                    .startObject(AnomalyRecord.PARTITION_FIELD_VALUE.getPreferredName())
-                        .field(TYPE, KEYWORD)
-                    .endObject()
-                    .startObject(Bucket.INITIAL_ANOMALY_SCORE.getPreferredName())
-                        .field(TYPE, DOUBLE)
-                    .endObject()
-                    .startObject(AnomalyRecord.PROBABILITY.getPreferredName())
-                        .field(TYPE, DOUBLE)
-                    .endObject()
-                .endObject()
-            .endObject()
 
             .startObject(Bucket.BUCKET_INFLUENCERS.getPreferredName())
                 .field(TYPE, NESTED)
@@ -328,7 +311,7 @@ public class ElasticsearchMappings {
     }
 
     private static void addForecastFieldsToMapping(XContentBuilder builder) throws IOException {
-        
+
         // Forecast Output
         builder.startObject(Forecast.FORECAST_LOWER.getPreferredName())
             .field(TYPE, DOUBLE)
@@ -370,7 +353,7 @@ public class ElasticsearchMappings {
             .field(TYPE, LONG)
         .endObject();
     }
-    
+
     /**
      * AnomalyRecord fields to be added under the 'properties' section of the mapping
      * @param builder Add properties to this builder
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/JobStorageDeletionTask.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/JobStorageDeletionTask.java
index 54faafb8ee5..19cb42a220e 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/JobStorageDeletionTask.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/JobStorageDeletionTask.java
@@ -9,13 +9,13 @@ import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
 import org.apache.logging.log4j.Logger;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
 import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
 import org.elasticsearch.action.bulk.BulkItemResponse;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.metadata.AliasMetaData;
@@ -213,7 +213,7 @@ public class JobStorageDeletionTask extends Task {
                                 return;
                             }
                             executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, removeRequest,
-                                    ActionListener.<IndicesAliasesResponse>wrap(removeResponse -> finishedHandler.onResponse(true),
+                                    ActionListener.<AcknowledgedResponse>wrap(removeResponse -> finishedHandler.onResponse(true),
                                             finishedHandler::onFailure),
                                     client.admin().indices()::aliases);
                         },
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/Bucket.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/Bucket.java
index 8a88232a559..8a7fe2395b4 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/Bucket.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/Bucket.java
@@ -25,7 +25,6 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 
 /**
  * Bucket Result POJO
@@ -43,7 +42,6 @@ public class Bucket implements ToXContentObject, Writeable {
     public static final ParseField BUCKET_INFLUENCERS = new ParseField("bucket_influencers");
     public static final ParseField BUCKET_SPAN = new ParseField("bucket_span");
     public static final ParseField PROCESSING_TIME_MS = new ParseField("processing_time_ms");
-    public static final ParseField PARTITION_SCORES = new ParseField("partition_scores");
     public static final ParseField SCHEDULED_EVENTS = new ParseField("scheduled_events");
 
     // Used for QueryPage
@@ -58,6 +56,19 @@ public class Bucket implements ToXContentObject, Writeable {
     public static final ConstructingObjectParser<Bucket, Void> STRICT_PARSER = createParser(false);
     public static final ConstructingObjectParser<Bucket, Void> LENIENT_PARSER = createParser(true);
 
+    /* *
+     * Read and discard the old (prior to 6.5) perPartitionNormalization values
+     */
+    public static Bucket readOldPerPartitionNormalization(StreamInput in)  throws IOException {
+        in.readString();
+        in.readString();
+        in.readDouble();
+        in.readDouble();
+        in.readDouble();
+
+        return null;
+    }
+
     private static ConstructingObjectParser<Bucket, Void> createParser(boolean ignoreUnknownFields) {
         ConstructingObjectParser<Bucket, Void> parser = new ConstructingObjectParser<>(RESULT_TYPE_VALUE, ignoreUnknownFields,
                 a -> new Bucket((String) a[0], (Date) a[1], (long) a[2]));
@@ -82,8 +93,6 @@ public class Bucket implements ToXContentObject, Writeable {
         parser.declareObjectArray(Bucket::setBucketInfluencers, ignoreUnknownFields ?
                 BucketInfluencer.LENIENT_PARSER : BucketInfluencer.STRICT_PARSER, BUCKET_INFLUENCERS);
         parser.declareLong(Bucket::setProcessingTimeMs, PROCESSING_TIME_MS);
-        parser.declareObjectArray(Bucket::setPartitionScores, ignoreUnknownFields ?
-                PartitionScore.LENIENT_PARSER : PartitionScore.STRICT_PARSER, PARTITION_SCORES);
         parser.declareString((bucket, s) -> {}, Result.RESULT_TYPE);
         parser.declareStringArray(Bucket::setScheduledEvents, SCHEDULED_EVENTS);
 
@@ -100,7 +109,6 @@ public class Bucket implements ToXContentObject, Writeable {
     private boolean isInterim;
     private List<BucketInfluencer> bucketInfluencers = new ArrayList<>(); // Can't use emptyList as might be appended to
     private long processingTimeMs;
-    private List<PartitionScore> partitionScores = Collections.emptyList();
     private List<String> scheduledEvents = Collections.emptyList();
 
     public Bucket(String jobId, Date timestamp, long bucketSpan) {
@@ -120,7 +128,6 @@ public class Bucket implements ToXContentObject, Writeable {
         this.isInterim = other.isInterim;
         this.bucketInfluencers = new ArrayList<>(other.bucketInfluencers);
         this.processingTimeMs = other.processingTimeMs;
-        this.partitionScores = new ArrayList<>(other.partitionScores);
         this.scheduledEvents = new ArrayList<>(other.scheduledEvents);
     }
 
@@ -143,7 +150,10 @@ public class Bucket implements ToXContentObject, Writeable {
         if (in.getVersion().before(Version.V_5_5_0)) {
             in.readGenericValue();
         }
-        partitionScores = in.readList(PartitionScore::new);
+        // bwc for perPartitionNormalization
+        if (in.getVersion().before(Version.V_6_5_0)) {
+            in.readList(Bucket::readOldPerPartitionNormalization);
+        }
         if (in.getVersion().onOrAfter(Version.V_6_2_0)) {
             scheduledEvents = in.readList(StreamInput::readString);
             if (scheduledEvents.isEmpty()) {
@@ -174,7 +184,10 @@ public class Bucket implements ToXContentObject, Writeable {
         if (out.getVersion().before(Version.V_5_5_0)) {
             out.writeGenericValue(Collections.emptyMap());
         }
-        out.writeList(partitionScores);
+        // bwc for perPartitionNormalization
+        if (out.getVersion().before(Version.V_6_5_0)) {
+            out.writeList(Collections.emptyList());
+        }
         if (out.getVersion().onOrAfter(Version.V_6_2_0)) {
             out.writeStringList(scheduledEvents);
         }
@@ -195,9 +208,7 @@ public class Bucket implements ToXContentObject, Writeable {
         builder.field(Result.IS_INTERIM.getPreferredName(), isInterim);
         builder.field(BUCKET_INFLUENCERS.getPreferredName(), bucketInfluencers);
         builder.field(PROCESSING_TIME_MS.getPreferredName(), processingTimeMs);
-        if (partitionScores.isEmpty() == false) {
-            builder.field(PARTITION_SCORES.getPreferredName(), partitionScores);
-        }
+
         if (scheduledEvents.isEmpty() == false) {
             builder.field(SCHEDULED_EVENTS.getPreferredName(), scheduledEvents);
         }
@@ -304,14 +315,6 @@ public class Bucket implements ToXContentObject, Writeable {
         bucketInfluencers.add(bucketInfluencer);
     }
 
-    public List<PartitionScore> getPartitionScores() {
-        return partitionScores;
-    }
-
-    public void setPartitionScores(List<PartitionScore> scores) {
-        partitionScores = Objects.requireNonNull(scores);
-    }
-
     public List<String> getScheduledEvents() {
         return scheduledEvents;
     }
@@ -320,24 +323,10 @@ public class Bucket implements ToXContentObject, Writeable {
         this.scheduledEvents = ExceptionsHelper.requireNonNull(scheduledEvents, SCHEDULED_EVENTS.getPreferredName());
     }
 
-    public double partitionInitialAnomalyScore(String partitionValue) {
-        Optional<PartitionScore> first = partitionScores.stream().filter(s -> partitionValue.equals(s.getPartitionFieldValue()))
-                .findFirst();
-
-        return first.isPresent() ? first.get().getInitialRecordScore() : 0.0;
-    }
-
-    public double partitionAnomalyScore(String partitionValue) {
-        Optional<PartitionScore> first = partitionScores.stream().filter(s -> partitionValue.equals(s.getPartitionFieldValue()))
-                .findFirst();
-
-        return first.isPresent() ? first.get().getRecordScore() : 0.0;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobId, timestamp, eventCount, initialAnomalyScore, anomalyScore, records,
-                isInterim, bucketSpan, bucketInfluencers, partitionScores, processingTimeMs, scheduledEvents);
+                isInterim, bucketSpan, bucketInfluencers, processingTimeMs, scheduledEvents);
     }
 
     /**
@@ -360,7 +349,6 @@ public class Bucket implements ToXContentObject, Writeable {
                 && (this.anomalyScore == that.anomalyScore) && (this.initialAnomalyScore == that.initialAnomalyScore)
                 && Objects.equals(this.records, that.records) && Objects.equals(this.isInterim, that.isInterim)
                 && Objects.equals(this.bucketInfluencers, that.bucketInfluencers)
-                && Objects.equals(this.partitionScores, that.partitionScores)
                 && (this.processingTimeMs == that.processingTimeMs)
                 && Objects.equals(this.scheduledEvents, that.scheduledEvents);
     }
@@ -374,6 +362,6 @@ public class Bucket implements ToXContentObject, Writeable {
      * @return true if the bucket should be normalized or false otherwise
      */
     public boolean isNormalizable() {
-        return anomalyScore > 0.0 || partitionScores.stream().anyMatch(s -> s.getRecordScore() > 0);
+        return anomalyScore > 0.0;
     }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/PartitionScore.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/PartitionScore.java
deleted file mode 100644
index 3d0acc8fde6..00000000000
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/PartitionScore.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.core.ml.job.results;
-
-import org.elasticsearch.common.ParseField;
-import org.elasticsearch.common.io.stream.StreamInput;
-import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.io.stream.Writeable;
-import org.elasticsearch.common.xcontent.ConstructingObjectParser;
-import org.elasticsearch.common.xcontent.ToXContentObject;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-
-import java.io.IOException;
-import java.util.Objects;
-
-public class PartitionScore implements ToXContentObject, Writeable {
-    public static final ParseField PARTITION_SCORE = new ParseField("partition_score");
-
-    private final String partitionFieldValue;
-    private final String partitionFieldName;
-    private final double initialRecordScore;
-    private double recordScore;
-    private double probability;
-
-    public static final ConstructingObjectParser<PartitionScore, Void> STRICT_PARSER = createParser(false);
-    public static final ConstructingObjectParser<PartitionScore, Void> LENIENT_PARSER = createParser(true);
-
-    private static ConstructingObjectParser<PartitionScore, Void> createParser(boolean ignoreUnknownFields) {
-        ConstructingObjectParser<PartitionScore, Void> parser = new ConstructingObjectParser<>(PARTITION_SCORE.getPreferredName(),
-                ignoreUnknownFields, a -> new PartitionScore((String) a[0], (String) a[1], (Double) a[2], (Double) a[3], (Double) a[4]));
-
-        parser.declareString(ConstructingObjectParser.constructorArg(), AnomalyRecord.PARTITION_FIELD_NAME);
-        parser.declareString(ConstructingObjectParser.constructorArg(), AnomalyRecord.PARTITION_FIELD_VALUE);
-        parser.declareDouble(ConstructingObjectParser.constructorArg(), AnomalyRecord.INITIAL_RECORD_SCORE);
-        parser.declareDouble(ConstructingObjectParser.constructorArg(), AnomalyRecord.RECORD_SCORE);
-        parser.declareDouble(ConstructingObjectParser.constructorArg(), AnomalyRecord.PROBABILITY);
-
-        return parser;
-    }
-
-    public PartitionScore(String fieldName, String fieldValue, double initialRecordScore, double recordScore, double probability) {
-        partitionFieldName = fieldName;
-        partitionFieldValue = fieldValue;
-        this.initialRecordScore = initialRecordScore;
-        this.recordScore = recordScore;
-        this.probability = probability;
-    }
-
-    public PartitionScore(StreamInput in) throws IOException {
-        partitionFieldName = in.readString();
-        partitionFieldValue = in.readString();
-        initialRecordScore = in.readDouble();
-        recordScore = in.readDouble();
-        probability = in.readDouble();
-    }
-
-    @Override
-    public void writeTo(StreamOutput out) throws IOException {
-        out.writeString(partitionFieldName);
-        out.writeString(partitionFieldValue);
-        out.writeDouble(initialRecordScore);
-        out.writeDouble(recordScore);
-        out.writeDouble(probability);
-    }
-
-    @Override
-    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
-        builder.startObject();
-        builder.field(AnomalyRecord.PARTITION_FIELD_NAME.getPreferredName(), partitionFieldName);
-        builder.field(AnomalyRecord.PARTITION_FIELD_VALUE.getPreferredName(), partitionFieldValue);
-        builder.field(AnomalyRecord.INITIAL_RECORD_SCORE.getPreferredName(), initialRecordScore);
-        builder.field(AnomalyRecord.RECORD_SCORE.getPreferredName(), recordScore);
-        builder.field(AnomalyRecord.PROBABILITY.getPreferredName(), probability);
-        builder.endObject();
-        return builder;
-    }
-
-    public double getInitialRecordScore() {
-        return initialRecordScore;
-    }
-
-    public double getRecordScore() {
-        return recordScore;
-    }
-
-    public void setRecordScore(double recordScore) {
-        this.recordScore = recordScore;
-    }
-
-    public String getPartitionFieldName() {
-        return partitionFieldName;
-    }
-
-    public String getPartitionFieldValue() {
-        return partitionFieldValue;
-    }
-
-    public double getProbability() {
-        return probability;
-    }
-
-    public void setProbability(double probability) {
-        this.probability = probability;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(partitionFieldName, partitionFieldValue, probability, initialRecordScore, recordScore);
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (this == other) {
-            return true;
-        }
-
-        if (other instanceof PartitionScore == false) {
-            return false;
-        }
-
-        PartitionScore that = (PartitionScore) other;
-
-        // id is excluded from the test as it is generated by the datastore
-        return Objects.equals(this.partitionFieldValue, that.partitionFieldValue)
-                && Objects.equals(this.partitionFieldName, that.partitionFieldName) && (this.probability == that.probability)
-                && (this.initialRecordScore == that.initialRecordScore) && (this.recordScore == that.recordScore);
-    }
-}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/ReservedFieldNames.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/ReservedFieldNames.java
index fb9a697ac46..63c4278e541 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/ReservedFieldNames.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/results/ReservedFieldNames.java
@@ -81,7 +81,6 @@ public final class ReservedFieldNames {
             Bucket.EVENT_COUNT.getPreferredName(),
             Bucket.INITIAL_ANOMALY_SCORE.getPreferredName(),
             Bucket.PROCESSING_TIME_MS.getPreferredName(),
-            Bucket.PARTITION_SCORES.getPreferredName(),
             Bucket.SCHEDULED_EVENTS.getPreferredName(),
 
             BucketInfluencer.INITIAL_ANOMALY_SCORE.getPreferredName(), BucketInfluencer.ANOMALY_SCORE.getPreferredName(),
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/DeleteRollupJobAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/DeleteRollupJobAction.java
index e59c6738d86..df2c70c7653 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/DeleteRollupJobAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/DeleteRollupJobAction.java
@@ -22,7 +22,7 @@ import org.elasticsearch.xpack.core.rollup.RollupField;
 import java.io.IOException;
 import java.util.Objects;
 
-public class DeleteRollupJobAction extends Action<DeleteRollupJobAction.Response> {
+public class DeleteRollupJobAction extends Action<AcknowledgedResponse> {
 
     public static final DeleteRollupJobAction INSTANCE = new DeleteRollupJobAction();
     public static final String NAME = "cluster:admin/xpack/rollup/delete";
@@ -32,8 +32,8 @@ public class DeleteRollupJobAction extends Action<DeleteRollupJobAction.Response
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> implements ToXContent {
@@ -90,21 +90,10 @@ public class DeleteRollupJobAction extends Action<DeleteRollupJobAction.Response
         }
     }
 
-    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, Response, RequestBuilder> {
+    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, AcknowledgedResponse, RequestBuilder> {
 
         protected RequestBuilder(ElasticsearchClient client, DeleteRollupJobAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response() {
-            super();
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-    }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/PutRollupJobAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/PutRollupJobAction.java
index 962f4cceb6a..6c56e7f6f1f 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/PutRollupJobAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/PutRollupJobAction.java
@@ -25,7 +25,7 @@ import java.io.IOException;
 import java.util.Map;
 import java.util.Objects;
 
-public class PutRollupJobAction extends Action<PutRollupJobAction.Response> {
+public class PutRollupJobAction extends Action<AcknowledgedResponse> {
 
     public static final PutRollupJobAction INSTANCE = new PutRollupJobAction();
     public static final String NAME = "cluster:admin/xpack/rollup/put";
@@ -35,8 +35,8 @@ public class PutRollupJobAction extends Action<PutRollupJobAction.Response> {
     }
 
     @Override
-    public Response newResponse() {
-        return new Response();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     public static class Request extends AcknowledgedRequest<Request> implements IndicesRequest, ToXContentObject {
@@ -127,21 +127,10 @@ public class PutRollupJobAction extends Action<PutRollupJobAction.Response> {
         }
     }
 
-    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, Response, RequestBuilder> {
+    public static class RequestBuilder extends MasterNodeOperationRequestBuilder<Request, AcknowledgedResponse, RequestBuilder> {
 
         protected RequestBuilder(ElasticsearchClient client, PutRollupJobAction action) {
             super(client, action, new Request());
         }
     }
-
-    public static class Response extends AcknowledgedResponse {
-
-        public Response() {
-            super();
-        }
-
-        public Response(boolean acknowledged) {
-            super(acknowledged);
-        }
-    }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java
index c018ad5f73e..f37072b9cf0 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/PutUserRequest.java
@@ -13,10 +13,7 @@ import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.io.stream.StreamInput;
 import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.xpack.core.security.authc.support.CharArrays;
-import org.elasticsearch.xpack.core.security.support.MetadataUtils;
-import org.elasticsearch.xpack.core.security.support.Validation;
 
 import java.io.IOException;
 import java.util.Map;
@@ -34,6 +31,7 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
     private String email;
     private Map<String, Object> metadata;
     private char[] passwordHash;
+    private char[] password;
     private boolean enabled = true;
     private RefreshPolicy refreshPolicy = RefreshPolicy.IMMEDIATE;
 
@@ -45,18 +43,15 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
         ActionRequestValidationException validationException = null;
         if (username == null) {
             validationException = addValidationError("user is missing", validationException);
-        } else {
-            Validation.Error error = Validation.Users.validateUsername(username, false, Settings.EMPTY);
-            if (error != null) {
-                validationException = addValidationError(error.toString(), validationException);
-            }
         }
         if (roles == null) {
             validationException = addValidationError("roles are missing", validationException);
         }
-        if (metadata != null && MetadataUtils.containsReservedMetadata(metadata)) {
-            validationException = addValidationError("metadata keys may not start with [" + MetadataUtils.RESERVED_PREFIX + "]",
-                    validationException);
+        if (metadata != null && metadata.keySet().stream().anyMatch(s -> s.startsWith("_"))) {
+            validationException = addValidationError("metadata keys may not start with [_]", validationException);
+        }
+        if (password != null && passwordHash != null) {
+            validationException = addValidationError("only one of [password, passwordHash] can be provided", validationException);
         }
         // we do not check for a password hash here since it is possible that the user exists and we don't want to update the password
         return validationException;
@@ -86,8 +81,12 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
         this.passwordHash = passwordHash;
     }
 
-    public boolean enabled() {
-        return enabled;
+    public void enabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public void password(@Nullable char[] password) {
+        this.password = password;
     }
 
     /**
@@ -130,8 +129,8 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
         return passwordHash;
     }
 
-    public void enabled(boolean enabled) {
-        this.enabled = enabled;
+    public boolean enabled() {
+        return enabled;
     }
 
     @Override
@@ -139,16 +138,16 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
         return new String[] { username };
     }
 
+    @Nullable
+    public char[] password() {
+        return password;
+    }
+
     @Override
     public void readFrom(StreamInput in) throws IOException {
         super.readFrom(in);
         username = in.readString();
-        BytesReference passwordHashRef = in.readBytesReference();
-        if (passwordHashRef == BytesArray.EMPTY) {
-            passwordHash = null;
-        } else {
-            passwordHash = CharArrays.utf8BytesToChars(BytesReference.toBytes(passwordHashRef));
-        }
+        passwordHash = readCharArrayFromStream(in);
         roles = in.readStringArray();
         fullName = in.readOptionalString();
         email = in.readOptionalString();
@@ -161,13 +160,10 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
     public void writeTo(StreamOutput out) throws IOException {
         super.writeTo(out);
         out.writeString(username);
-        BytesReference passwordHashRef;
-        if (passwordHash == null) {
-            passwordHashRef = null;
-        } else {
-            passwordHashRef = new BytesArray(CharArrays.toUtf8Bytes(passwordHash));
+        writeCharArrayToStream(out, passwordHash);
+        if (password != null) {
+            throw new IllegalStateException("password cannot be serialized. it is only used for HL rest");
         }
-        out.writeBytesReference(passwordHashRef);
         out.writeStringArray(roles);
         out.writeOptionalString(fullName);
         out.writeOptionalString(email);
@@ -180,4 +176,23 @@ public class PutUserRequest extends ActionRequest implements UserRequest, WriteR
         refreshPolicy.writeTo(out);
         out.writeBoolean(enabled);
     }
+
+    private static char[] readCharArrayFromStream(StreamInput in) throws IOException {
+        BytesReference charBytesRef = in.readBytesReference();
+        if (charBytesRef == BytesArray.EMPTY) {
+            return null;
+        } else {
+            return CharArrays.utf8BytesToChars(BytesReference.toBytes(charBytesRef));
+        }
+    }
+
+    private static void writeCharArrayToStream(StreamOutput out, char[] chars) throws IOException {
+        final BytesReference charBytesRef;
+        if (chars == null) {
+            charBytesRef = null;
+        } else {
+            charBytesRef = new BytesArray(CharArrays.toUtf8Bytes(chars));
+        }
+        out.writeBytesReference(charBytesRef);
+    }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/client/WatcherClient.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/client/WatcherClient.java
index b9458c23ddc..39dea2298aa 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/client/WatcherClient.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/client/WatcherClient.java
@@ -7,7 +7,10 @@ package org.elasticsearch.xpack.core.watcher.client;
 
 import org.elasticsearch.action.ActionFuture;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
+import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
+import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
 import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
 import org.elasticsearch.protocol.xpack.watcher.PutWatchResponse;
 import org.elasticsearch.xpack.core.watcher.transport.actions.ack.AckWatchAction;
@@ -19,9 +22,7 @@ import org.elasticsearch.xpack.core.watcher.transport.actions.activate.ActivateW
 import org.elasticsearch.xpack.core.watcher.transport.actions.activate.ActivateWatchRequestBuilder;
 import org.elasticsearch.xpack.core.watcher.transport.actions.activate.ActivateWatchResponse;
 import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchAction;
-import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
 import org.elasticsearch.xpack.core.watcher.transport.actions.delete.DeleteWatchRequestBuilder;
-import org.elasticsearch.protocol.xpack.watcher.DeleteWatchResponse;
 import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchAction;
 import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchRequest;
 import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWatchRequestBuilder;
@@ -35,7 +36,6 @@ import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchReques
 import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceAction;
 import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceRequest;
 import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceRequestBuilder;
-import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceResponse;
 import org.elasticsearch.xpack.core.watcher.transport.actions.stats.WatcherStatsAction;
 import org.elasticsearch.xpack.core.watcher.transport.actions.stats.WatcherStatsRequest;
 import org.elasticsearch.xpack.core.watcher.transport.actions.stats.WatcherStatsRequestBuilder;
@@ -268,14 +268,14 @@ public class WatcherClient {
     /**
      * Perform an watcher service request to either start, stop or restart the service.
      */
-    public void watcherService(WatcherServiceRequest request, ActionListener<WatcherServiceResponse> listener) {
+    public void watcherService(WatcherServiceRequest request, ActionListener<AcknowledgedResponse> listener) {
         client.execute(WatcherServiceAction.INSTANCE, request, listener);
     }
 
     /**
      * Perform an watcher service request to either start, stop or restart the service.
      */
-    public ActionFuture<WatcherServiceResponse> watcherService(WatcherServiceRequest request) {
+    public ActionFuture<AcknowledgedResponse> watcherService(WatcherServiceRequest request) {
         return client.execute(WatcherServiceAction.INSTANCE, request);
     }
 
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceAction.java
index 0846bd10a80..30b0b54725b 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceAction.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceAction.java
@@ -6,9 +6,10 @@
 package org.elasticsearch.xpack.core.watcher.transport.actions.service;
 
 import org.elasticsearch.action.Action;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 
 
-public class WatcherServiceAction extends Action<WatcherServiceResponse> {
+public class WatcherServiceAction extends Action<AcknowledgedResponse> {
 
     public static final WatcherServiceAction INSTANCE = new WatcherServiceAction();
     public static final String NAME = "cluster:admin/xpack/watcher/service";
@@ -18,7 +19,7 @@ public class WatcherServiceAction extends Action<WatcherServiceResponse> {
     }
 
     @Override
-    public WatcherServiceResponse newResponse() {
-        return new WatcherServiceResponse();
+    public AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 }
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceRequestBuilder.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceRequestBuilder.java
index b43d02aac83..1ee4258a5a4 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceRequestBuilder.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceRequestBuilder.java
@@ -5,10 +5,11 @@
  */
 package org.elasticsearch.xpack.core.watcher.transport.actions.service;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
 import org.elasticsearch.client.ElasticsearchClient;
 
-public class WatcherServiceRequestBuilder extends MasterNodeOperationRequestBuilder<WatcherServiceRequest, WatcherServiceResponse,
+public class WatcherServiceRequestBuilder extends MasterNodeOperationRequestBuilder<WatcherServiceRequest, AcknowledgedResponse,
         WatcherServiceRequestBuilder> {
 
     public WatcherServiceRequestBuilder(ElasticsearchClient client) {
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceResponse.java
deleted file mode 100644
index 7df144e45d3..00000000000
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/watcher/transport/actions/service/WatcherServiceResponse.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.core.watcher.transport.actions.service;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-
-public class WatcherServiceResponse extends AcknowledgedResponse {
-
-    public WatcherServiceResponse() {
-    }
-
-    public WatcherServiceResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-}
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java
index 82fde59a8ae..abaa7e1c5d3 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java
@@ -6,13 +6,13 @@
 package org.elasticsearch.license;
 
 import org.elasticsearch.action.ActionFuture;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.node.Node;
 import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.protocol.xpack.license.DeleteLicenseResponse;
 import org.elasticsearch.protocol.xpack.license.LicensesStatus;
 import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
 import org.elasticsearch.test.ESSingleNodeTestCase;
@@ -183,7 +183,7 @@ public class LicensesTransportTests extends ESSingleNodeTestCase {
         // delete all licenses
         DeleteLicenseRequestBuilder deleteLicenseRequestBuilder =
                 new DeleteLicenseRequestBuilder(client().admin().cluster(), DeleteLicenseAction.INSTANCE);
-        DeleteLicenseResponse deleteLicenseResponse = deleteLicenseRequestBuilder.get();
+        AcknowledgedResponse deleteLicenseResponse = deleteLicenseRequestBuilder.get();
         assertThat(deleteLicenseResponse.isAcknowledged(), equalTo(true));
         // get licenses (expected no licenses)
         getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get();
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java
index 17934efe0a5..7689ae4088f 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java
@@ -5,9 +5,14 @@
  */
 package org.elasticsearch.xpack.core;
 
+import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.test.ESTestCase;
 import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
 
+import java.security.NoSuchAlgorithmException;
+
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.hasItem;
 import static org.hamcrest.Matchers.not;
 
@@ -25,4 +30,30 @@ public class XPackSettingsTests extends ESTestCase {
             assertThat(XPackSettings.DEFAULT_CIPHERS, not(hasItem("TLS_RSA_WITH_AES_256_CBC_SHA")));
         }
     }
+
+    public void testPasswordHashingAlgorithmSettingValidation() {
+        final boolean isPBKDF2Available = isSecretkeyFactoryAlgoAvailable("PBKDF2WithHMACSHA512");
+        final String pbkdf2Algo = randomFrom("PBKDF2_10000", "PBKDF2");
+        final Settings settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), pbkdf2Algo).build();
+        if (isPBKDF2Available) {
+            assertEquals(pbkdf2Algo, XPackSettings.PASSWORD_HASHING_ALGORITHM.get(settings));
+        } else {
+            IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
+                () -> XPackSettings.PASSWORD_HASHING_ALGORITHM.get(settings));
+            assertThat(e.getMessage(), containsString("Support for PBKDF2WithHMACSHA512 must be available"));
+        }
+
+        final String bcryptAlgo = randomFrom("BCRYPT", "BCRYPT11");
+        assertEquals(bcryptAlgo, XPackSettings.PASSWORD_HASHING_ALGORITHM.get(
+            Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), bcryptAlgo).build()));
+    }
+
+    private boolean isSecretkeyFactoryAlgoAvailable(String algorithmId) {
+        try {
+            SecretKeyFactory.getInstance(algorithmId);
+            return true;
+        } catch (NoSuchAlgorithmException e) {
+            return false;
+        }
+    }
 }
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/action/GetBucketActionResponseTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/action/GetBucketActionResponseTests.java
index 4fbb7a92496..ffd21834e58 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/action/GetBucketActionResponseTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/action/GetBucketActionResponseTests.java
@@ -11,7 +11,6 @@ import org.elasticsearch.xpack.core.ml.action.util.QueryPage;
 import org.elasticsearch.xpack.core.ml.job.results.AnomalyRecord;
 import org.elasticsearch.xpack.core.ml.job.results.Bucket;
 import org.elasticsearch.xpack.core.ml.job.results.BucketInfluencer;
-import org.elasticsearch.xpack.core.ml.job.results.PartitionScore;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -53,15 +52,6 @@ public class GetBucketActionResponseTests extends AbstractStreamableTestCase<Res
             if (randomBoolean()) {
                 bucket.setInterim(randomBoolean());
             }
-            if (randomBoolean()) {
-                int size = randomInt(10);
-                List<PartitionScore> partitionScores = new ArrayList<>(size);
-                for (int i = 0; i < size; i++) {
-                    partitionScores.add(new PartitionScore(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20),
-                            randomDouble(), randomDouble(), randomDouble()));
-                }
-                bucket.setPartitionScores(partitionScores);
-            }
             if (randomBoolean()) {
                 bucket.setProcessingTimeMs(randomLong());
             }
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfigTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfigTests.java
index 50c60a31427..d691124a90a 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfigTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/config/AnalysisConfigTests.java
@@ -97,11 +97,8 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
             builder.setResultFinalizationWindow(randomNonNegativeLong());
         }
 
-        boolean usePerPartitionNormalisation = randomBoolean();
-        builder.setUsePerPartitionNormalization(usePerPartitionNormalisation);
-        if (!usePerPartitionNormalisation) { // influencers can't be used with per partition normalisation
-            builder.setInfluencers(Arrays.asList(generateRandomStringArray(10, 10, false)));
-        }
+        builder.setInfluencers(Arrays.asList(generateRandomStringArray(10, 10, false)));
+
         return builder;
     }
 
@@ -690,40 +687,15 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
         assertEquals(Messages.getMessage(Messages.JOB_CONFIG_CATEGORIZATION_FILTERS_CONTAINS_EMPTY), e.getMessage());
     }
 
-
-    public void testCheckDetectorsHavePartitionFields() {
-        AnalysisConfig.Builder config = createValidConfig();
-        config.setUsePerPartitionNormalization(true);
-
-        ElasticsearchException e = ESTestCase.expectThrows(ElasticsearchException.class, config::build);
-
-        assertEquals(Messages.getMessage(Messages.JOB_CONFIG_PER_PARTITION_NORMALIZATION_REQUIRES_PARTITION_FIELD), e.getMessage());
-    }
-
     public void testCheckDetectorsHavePartitionFields_doesntThrowWhenValid() {
         AnalysisConfig.Builder config = createValidConfig();
         Detector.Builder builder = new Detector.Builder(config.build().getDetectors().get(0));
         builder.setPartitionFieldName("pField");
         config.build().getDetectors().set(0, builder.build());
-        config.setUsePerPartitionNormalization(true);
 
         config.build();
     }
 
-    public void testCheckNoInfluencersAreSet() {
-
-        AnalysisConfig.Builder config = createValidConfig();
-        Detector.Builder builder = new Detector.Builder(config.build().getDetectors().get(0));
-        builder.setPartitionFieldName("pField");
-        config.build().getDetectors().set(0, builder.build());
-        config.setInfluencers(Arrays.asList("inf1", "inf2"));
-        config.setUsePerPartitionNormalization(true);
-
-        ElasticsearchException e = ESTestCase.expectThrows(ElasticsearchException.class, config::build);
-
-        assertEquals(Messages.getMessage(Messages.JOB_CONFIG_PER_PARTITION_NORMALIZATION_CANNOT_USE_INFLUENCERS), e.getMessage());
-    }
-
     public void testVerify_GivenCategorizationFiltersContainInvalidRegex() {
         AnalysisConfig.Builder config = createValidCategorizationConfig();
         config.setCategorizationFilters(Arrays.asList("foo", "("));
@@ -756,7 +728,7 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
     @Override
     protected AnalysisConfig mutateInstance(AnalysisConfig instance) {
         AnalysisConfig.Builder builder = new AnalysisConfig.Builder(instance);
-        switch (between(0, 11)) {
+        switch (between(0, 10)) {
         case 0:
             List<Detector> detectors = new ArrayList<>(instance.getDetectors());
             Detector.Builder detector = new Detector.Builder();
@@ -832,7 +804,6 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
             List<String> influencers = new ArrayList<>(instance.getInfluencers());
             influencers.add(randomAlphaOfLengthBetween(5, 10));
             builder.setInfluencers(influencers);
-            builder.setUsePerPartitionNormalization(false);
             break;
         case 8:
             if (instance.getOverlappingBuckets() == null) {
@@ -855,13 +826,6 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
                 builder.setMultivariateByFields(instance.getMultivariateByFields() == false);
             }
             break;
-        case 11:
-            boolean usePerPartitionNormalization = instance.getUsePerPartitionNormalization() == false;
-            builder.setUsePerPartitionNormalization(usePerPartitionNormalization);
-            if (usePerPartitionNormalization) {
-                builder.setInfluencers(Collections.emptyList());
-            }
-            break;
         default:
             throw new AssertionError("Illegal randomisation branch");
         }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java
index f2fdea45ebe..af7cb4242f1 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java
@@ -384,8 +384,8 @@ public class MachineLearning extends Plugin implements ActionPlugin, AnalysisPlu
             autodetectProcessFactory = (job, autodetectParams, executorService, onProcessCrash) ->
                     new BlackHoleAutodetectProcess(job.getId());
             // factor of 1.0 makes renormalization a no-op
-            normalizerProcessFactory = (jobId, quantilesState, bucketSpan, perPartitionNormalization,
-                                        executorService) -> new MultiplyingNormalizerProcess(settings, 1.0);
+            normalizerProcessFactory = (jobId, quantilesState, bucketSpan, executorService) ->
+                    new MultiplyingNormalizerProcess(settings, 1.0);
         }
         NormalizerFactory normalizerFactory = new NormalizerFactory(normalizerProcessFactory,
                 threadPool.executor(MachineLearning.UTILITY_THREAD_POOL_NAME));
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarAction.java
index c171acd71b5..2facfd4678e 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarAction.java
@@ -10,6 +10,7 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
@@ -31,7 +32,7 @@ import java.util.function.Supplier;
 import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
 import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
 
-public class TransportDeleteCalendarAction extends HandledTransportAction<DeleteCalendarAction.Request, DeleteCalendarAction.Response> {
+public class TransportDeleteCalendarAction extends HandledTransportAction<DeleteCalendarAction.Request, AcknowledgedResponse> {
 
     private final Client client;
     private final JobManager jobManager;
@@ -49,7 +50,7 @@ public class TransportDeleteCalendarAction extends HandledTransportAction<Delete
     }
 
     @Override
-    protected void doExecute(Task task, DeleteCalendarAction.Request request, ActionListener<DeleteCalendarAction.Response> listener) {
+    protected void doExecute(Task task, DeleteCalendarAction.Request request, ActionListener<AcknowledgedResponse> listener) {
 
         final String calendarId = request.getCalendarId();
 
@@ -64,7 +65,7 @@ public class TransportDeleteCalendarAction extends HandledTransportAction<Delete
                                     return;
                                 }
                                 jobManager.updateProcessOnCalendarChanged(calendar.getJobIds());
-                                listener.onResponse(new DeleteCalendarAction.Response(true));
+                                listener.onResponse(new AcknowledgedResponse(true));
                             },
                             listener::onFailure));
                 },
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarEventAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarEventAction.java
index c52f144923e..854ff19e16f 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarEventAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteCalendarEventAction.java
@@ -15,6 +15,7 @@ import org.elasticsearch.action.get.GetRequest;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
 import org.elasticsearch.action.support.WriteRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
@@ -33,8 +34,7 @@ import java.util.Map;
 import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
 import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
 
-public class TransportDeleteCalendarEventAction extends HandledTransportAction<DeleteCalendarEventAction.Request,
-        DeleteCalendarEventAction.Response> {
+public class TransportDeleteCalendarEventAction extends HandledTransportAction<DeleteCalendarEventAction.Request, AcknowledgedResponse> {
 
     private final Client client;
     private final JobResultsProvider jobResultsProvider;
@@ -52,7 +52,7 @@ public class TransportDeleteCalendarEventAction extends HandledTransportAction<D
 
     @Override
     protected void doExecute(Task task, DeleteCalendarEventAction.Request request,
-                             ActionListener<DeleteCalendarEventAction.Response> listener) {
+                             ActionListener<AcknowledgedResponse> listener) {
         final String eventId = request.getEventId();
 
         ActionListener<Calendar> calendarListener = ActionListener.wrap(
@@ -90,7 +90,7 @@ public class TransportDeleteCalendarEventAction extends HandledTransportAction<D
         jobResultsProvider.calendar(request.getCalendarId(), calendarListener);
     }
 
-    private void deleteEvent(String eventId, Calendar calendar, ActionListener<DeleteCalendarEventAction.Response> listener) {
+    private void deleteEvent(String eventId, Calendar calendar, ActionListener<AcknowledgedResponse> listener) {
         DeleteRequest deleteRequest = new DeleteRequest(MlMetaIndex.INDEX_NAME, MlMetaIndex.TYPE, eventId);
         deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
 
@@ -103,7 +103,7 @@ public class TransportDeleteCalendarEventAction extends HandledTransportAction<D
                             listener.onFailure(new ResourceNotFoundException("No event with id [" + eventId + "]"));
                         } else {
                             jobManager.updateProcessOnCalendarChanged(calendar.getJobIds());
-                            listener.onResponse(new DeleteCalendarEventAction.Response(true));
+                            listener.onResponse(new AcknowledgedResponse(true));
                         }
                     }
 
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java
index 2582cb0082e..37210ce3c6c 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.ml.action;
 import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
@@ -19,6 +20,8 @@ import org.elasticsearch.cluster.metadata.MetaData;
 import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
+import org.elasticsearch.persistent.PersistentTasksService;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 import org.elasticsearch.xpack.core.XPackPlugin;
@@ -26,13 +29,11 @@ import org.elasticsearch.xpack.core.ml.MlMetadata;
 import org.elasticsearch.xpack.core.ml.MlTasks;
 import org.elasticsearch.xpack.core.ml.action.DeleteDatafeedAction;
 import org.elasticsearch.xpack.core.ml.action.IsolateDatafeedAction;
-import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
-import org.elasticsearch.persistent.PersistentTasksService;
 
 import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
 import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
 
-public class TransportDeleteDatafeedAction extends TransportMasterNodeAction<DeleteDatafeedAction.Request, DeleteDatafeedAction.Response> {
+public class TransportDeleteDatafeedAction extends TransportMasterNodeAction<DeleteDatafeedAction.Request, AcknowledgedResponse> {
 
     private Client client;
     private PersistentTasksService persistentTasksService;
@@ -54,13 +55,13 @@ public class TransportDeleteDatafeedAction extends TransportMasterNodeAction<Del
     }
 
     @Override
-    protected DeleteDatafeedAction.Response newResponse() {
-        return new DeleteDatafeedAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(DeleteDatafeedAction.Request request, ClusterState state,
-                                   ActionListener<DeleteDatafeedAction.Response> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
         if (request.isForce()) {
             forceDeleteDatafeed(request, state, listener);
         } else {
@@ -69,7 +70,7 @@ public class TransportDeleteDatafeedAction extends TransportMasterNodeAction<Del
     }
 
     private void forceDeleteDatafeed(DeleteDatafeedAction.Request request, ClusterState state,
-                                     ActionListener<DeleteDatafeedAction.Response> listener) {
+                                     ActionListener<AcknowledgedResponse> listener) {
         ActionListener<Boolean> finalListener = ActionListener.wrap(
                 response -> deleteDatafeedFromMetadata(request, listener),
                 listener::onFailure
@@ -110,13 +111,13 @@ public class TransportDeleteDatafeedAction extends TransportMasterNodeAction<Del
         }
     }
 
-    private void deleteDatafeedFromMetadata(DeleteDatafeedAction.Request request, ActionListener<DeleteDatafeedAction.Response> listener) {
+    private void deleteDatafeedFromMetadata(DeleteDatafeedAction.Request request, ActionListener<AcknowledgedResponse> listener) {
         clusterService.submitStateUpdateTask("delete-datafeed-" + request.getDatafeedId(),
-                new AckedClusterStateUpdateTask<DeleteDatafeedAction.Response>(request, listener) {
+                new AckedClusterStateUpdateTask<AcknowledgedResponse>(request, listener) {
 
                     @Override
-                    protected DeleteDatafeedAction.Response newResponse(boolean acknowledged) {
-                        return new DeleteDatafeedAction.Response(acknowledged);
+                    protected AcknowledgedResponse newResponse(boolean acknowledged) {
+                        return new AcknowledgedResponse(acknowledged);
                     }
 
                     @Override
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteFilterAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteFilterAction.java
index c7d3d64c58c..54acdf3712c 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteFilterAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteFilterAction.java
@@ -14,6 +14,7 @@ import org.elasticsearch.action.delete.DeleteRequest;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
 import org.elasticsearch.action.support.WriteRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.service.ClusterService;
@@ -38,7 +39,7 @@ import java.util.function.Supplier;
 import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
 import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
 
-public class TransportDeleteFilterAction extends HandledTransportAction<DeleteFilterAction.Request, DeleteFilterAction.Response> {
+public class TransportDeleteFilterAction extends HandledTransportAction<DeleteFilterAction.Request, AcknowledgedResponse> {
 
     private final Client client;
     private final ClusterService clusterService;
@@ -53,7 +54,7 @@ public class TransportDeleteFilterAction extends HandledTransportAction<DeleteFi
     }
 
     @Override
-    protected void doExecute(Task task, DeleteFilterAction.Request request, ActionListener<DeleteFilterAction.Response> listener) {
+    protected void doExecute(Task task, DeleteFilterAction.Request request, ActionListener<AcknowledgedResponse> listener) {
 
         final String filterId = request.getFilterId();
         ClusterState state = clusterService.state();
@@ -85,7 +86,7 @@ public class TransportDeleteFilterAction extends HandledTransportAction<DeleteFi
                             listener.onFailure(new ResourceNotFoundException("Could not delete filter with ID [" + filterId
                                     + "] because it does not exist"));
                         } else {
-                            listener.onResponse(new DeleteFilterAction.Response(true));
+                            listener.onResponse(new AcknowledgedResponse(true));
                         }
                     }
 
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java
index ad0d4068592..a74d1498f10 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java
@@ -9,6 +9,7 @@ import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
@@ -23,6 +24,8 @@ import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.node.NodeClosedException;
+import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
+import org.elasticsearch.persistent.PersistentTasksService;
 import org.elasticsearch.tasks.Task;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
@@ -32,8 +35,6 @@ import org.elasticsearch.xpack.core.ml.MlTasks;
 import org.elasticsearch.xpack.core.ml.action.DeleteJobAction;
 import org.elasticsearch.xpack.core.ml.action.KillProcessAction;
 import org.elasticsearch.xpack.core.ml.job.persistence.JobStorageDeletionTask;
-import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
-import org.elasticsearch.persistent.PersistentTasksService;
 import org.elasticsearch.xpack.ml.job.JobManager;
 
 import java.util.concurrent.TimeoutException;
@@ -41,7 +42,7 @@ import java.util.concurrent.TimeoutException;
 import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
 import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
 
-public class TransportDeleteJobAction extends TransportMasterNodeAction<DeleteJobAction.Request, DeleteJobAction.Response> {
+public class TransportDeleteJobAction extends TransportMasterNodeAction<DeleteJobAction.Request, AcknowledgedResponse> {
 
     private final Client client;
     private final JobManager jobManager;
@@ -65,13 +66,13 @@ public class TransportDeleteJobAction extends TransportMasterNodeAction<DeleteJo
     }
 
     @Override
-    protected DeleteJobAction.Response newResponse() {
-        return new DeleteJobAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(Task task, DeleteJobAction.Request request, ClusterState state,
-                                   ActionListener<DeleteJobAction.Response> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
 
         ActionListener<Boolean> markAsDeletingListener = ActionListener.wrap(
                 response -> {
@@ -110,7 +111,7 @@ public class TransportDeleteJobAction extends TransportMasterNodeAction<DeleteJo
 
     @Override
     protected void masterOperation(DeleteJobAction.Request request, ClusterState state,
-                                   ActionListener<DeleteJobAction.Response> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
         throw new UnsupportedOperationException("the Task parameter is required");
     }
 
@@ -120,12 +121,12 @@ public class TransportDeleteJobAction extends TransportMasterNodeAction<DeleteJo
     }
 
     private void normalDeleteJob(DeleteJobAction.Request request, JobStorageDeletionTask task,
-                                 ActionListener<DeleteJobAction.Response> listener) {
+                                 ActionListener<AcknowledgedResponse> listener) {
         jobManager.deleteJob(request, task, listener);
     }
 
     private void forceDeleteJob(DeleteJobAction.Request request, JobStorageDeletionTask task,
-                                ActionListener<DeleteJobAction.Response> listener) {
+                                ActionListener<AcknowledgedResponse> listener) {
 
         final ClusterState state = clusterService.state();
         final String jobId = request.getJobId();
@@ -219,17 +220,17 @@ public class TransportDeleteJobAction extends TransportMasterNodeAction<DeleteJo
         });
     }
 
-    void waitForDeletingJob(String jobId, TimeValue timeout, ActionListener<DeleteJobAction.Response> listener) {
+    void waitForDeletingJob(String jobId, TimeValue timeout, ActionListener<AcknowledgedResponse> listener) {
         ClusterStateObserver stateObserver = new ClusterStateObserver(clusterService, timeout, logger, threadPool.getThreadContext());
 
         ClusterState clusterState = stateObserver.setAndGetObservedState();
         if (jobIsDeletedFromState(jobId, clusterState)) {
-            listener.onResponse(new DeleteJobAction.Response(true));
+            listener.onResponse(new AcknowledgedResponse(true));
         } else {
             stateObserver.waitForNextChange(new ClusterStateObserver.Listener() {
                 @Override
                 public void onNewClusterState(ClusterState state) {
-                    listener.onResponse(new DeleteJobAction.Response(true));
+                    listener.onResponse(new AcknowledgedResponse(true));
                 }
 
                 @Override
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteModelSnapshotAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteModelSnapshotAction.java
index 398b9930f7d..b880bf6fa0c 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteModelSnapshotAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteModelSnapshotAction.java
@@ -10,6 +10,7 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.common.inject.Inject;
@@ -29,7 +30,7 @@ import java.util.Collections;
 import java.util.List;
 
 public class TransportDeleteModelSnapshotAction extends HandledTransportAction<DeleteModelSnapshotAction.Request,
-        DeleteModelSnapshotAction.Response> {
+    AcknowledgedResponse> {
 
     private final Client client;
     private final JobResultsProvider jobResultsProvider;
@@ -50,7 +51,7 @@ public class TransportDeleteModelSnapshotAction extends HandledTransportAction<D
 
     @Override
     protected void doExecute(Task task, DeleteModelSnapshotAction.Request request,
-                             ActionListener<DeleteModelSnapshotAction.Response> listener) {
+                             ActionListener<AcknowledgedResponse> listener) {
         // Verify the snapshot exists
         jobResultsProvider.modelSnapshots(
                 request.getJobId(), 0, 1, null, null, null, true, request.getSnapshotId(),
@@ -86,7 +87,7 @@ public class TransportDeleteModelSnapshotAction extends HandledTransportAction<D
                             auditor.info(request.getJobId(), msg);
                             logger.debug("[{}] {}", request.getJobId(), msg);
                             // We don't care about the bulk response, just that it succeeded
-                            listener.onResponse(new DeleteModelSnapshotAction.Response(true));
+                            listener.onResponse(new AcknowledgedResponse(true));
                         }
 
                         @Override
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportFinalizeJobExecutionAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportFinalizeJobExecutionAction.java
index ff611f92202..fb56e619839 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportFinalizeJobExecutionAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportFinalizeJobExecutionAction.java
@@ -7,6 +7,7 @@ package org.elasticsearch.xpack.ml.action;
 
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ClusterStateUpdateTask;
@@ -20,14 +21,14 @@ import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.transport.TransportService;
 import org.elasticsearch.xpack.core.XPackPlugin;
-import org.elasticsearch.xpack.core.ml.action.FinalizeJobExecutionAction;
 import org.elasticsearch.xpack.core.ml.MlMetadata;
+import org.elasticsearch.xpack.core.ml.action.FinalizeJobExecutionAction;
 import org.elasticsearch.xpack.core.ml.job.config.Job;
 
 import java.util.Date;
 
 public class TransportFinalizeJobExecutionAction extends TransportMasterNodeAction<FinalizeJobExecutionAction.Request,
-        FinalizeJobExecutionAction.Response> {
+    AcknowledgedResponse> {
 
     @Inject
     public TransportFinalizeJobExecutionAction(Settings settings, TransportService transportService,
@@ -44,13 +45,13 @@ public class TransportFinalizeJobExecutionAction extends TransportMasterNodeActi
     }
 
     @Override
-    protected FinalizeJobExecutionAction.Response newResponse() {
-        return new FinalizeJobExecutionAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(FinalizeJobExecutionAction.Request request, ClusterState state,
-                                   ActionListener<FinalizeJobExecutionAction.Response> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
         String jobIdString = String.join(",", request.getJobIds());
         String source = "finalize_job_execution [" + jobIdString + "]";
         logger.debug("finalizing jobs [{}]", jobIdString);
@@ -82,7 +83,7 @@ public class TransportFinalizeJobExecutionAction extends TransportMasterNodeActi
             public void clusterStateProcessed(String source, ClusterState oldState,
                                               ClusterState newState) {
                 logger.debug("finalized job [{}]", jobIdString);
-                listener.onResponse(new FinalizeJobExecutionAction.Response(true));
+                listener.onResponse(new AcknowledgedResponse(true));
             }
         });
     }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java
index c4e5793b451..56d03dd1aac 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportOpenJobAction.java
@@ -15,6 +15,7 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
@@ -92,7 +93,7 @@ import static org.elasticsearch.xpack.ml.job.process.autodetect.AutodetectProces
  In case of instability persistent tasks checks may fail and that is ok, in that case all bets are off.
  The open job api is a low through put api, so the fact that we redirect to elected master node shouldn't be an issue.
 */
-public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAction.Request, OpenJobAction.Response> {
+public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAction.Request, AcknowledgedResponse> {
 
     private final XPackLicenseState licenseState;
     private final PersistentTasksService persistentTasksService;
@@ -457,8 +458,8 @@ public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAct
     }
 
     @Override
-    protected OpenJobAction.Response newResponse() {
-        return new OpenJobAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
@@ -470,12 +471,12 @@ public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAct
     }
 
     @Override
-    protected void masterOperation(OpenJobAction.Request request, ClusterState state, ActionListener<OpenJobAction.Response> listener) {
+    protected void masterOperation(OpenJobAction.Request request, ClusterState state, ActionListener<AcknowledgedResponse> listener) {
         OpenJobAction.JobParams jobParams = request.getJobParams();
         if (licenseState.isMachineLearningAllowed()) {
 
             // Step 6. Clear job finished time once the job is started and respond
-            ActionListener<OpenJobAction.Response> clearJobFinishTime = ActionListener.wrap(
+            ActionListener<AcknowledgedResponse> clearJobFinishTime = ActionListener.wrap(
                 response -> {
                     if (response.isAcknowledged()) {
                         clearJobFinishedTime(jobParams.getJobId(), listener);
@@ -557,7 +558,7 @@ public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAct
         }
     }
 
-    private void waitForJobStarted(String taskId, OpenJobAction.JobParams jobParams, ActionListener<OpenJobAction.Response> listener) {
+    private void waitForJobStarted(String taskId, OpenJobAction.JobParams jobParams, ActionListener<AcknowledgedResponse> listener) {
         JobPredicate predicate = new JobPredicate();
         persistentTasksService.waitForPersistentTaskCondition(taskId, predicate, jobParams.getTimeout(),
                 new PersistentTasksService.WaitForPersistentTaskListener<OpenJobAction.JobParams>() {
@@ -572,7 +573,7 @@ public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAct
                         listener.onFailure(predicate.exception);
                     }
                 } else {
-                    listener.onResponse(new OpenJobAction.Response(predicate.opened));
+                    listener.onResponse(new AcknowledgedResponse(predicate.opened));
                 }
             }
 
@@ -589,7 +590,7 @@ public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAct
         });
     }
 
-    private void clearJobFinishedTime(String jobId, ActionListener<OpenJobAction.Response> listener) {
+    private void clearJobFinishedTime(String jobId, ActionListener<AcknowledgedResponse> listener) {
         clusterService.submitStateUpdateTask("clearing-job-finish-time-for-" + jobId, new ClusterStateUpdateTask() {
             @Override
             public ClusterState execute(ClusterState currentState) {
@@ -608,18 +609,18 @@ public class TransportOpenJobAction extends TransportMasterNodeAction<OpenJobAct
             @Override
             public void onFailure(String source, Exception e) {
                 logger.error("[" + jobId + "] Failed to clear finished_time; source [" + source + "]", e);
-                listener.onResponse(new OpenJobAction.Response(true));
+                listener.onResponse(new AcknowledgedResponse(true));
             }
 
             @Override
             public void clusterStateProcessed(String source, ClusterState oldState,
                                               ClusterState newState) {
-                listener.onResponse(new OpenJobAction.Response(true));
+                listener.onResponse(new AcknowledgedResponse(true));
             }
         });
     }
     private void cancelJobStart(PersistentTasksCustomMetaData.PersistentTask<OpenJobAction.JobParams> persistentTask, Exception exception,
-                                ActionListener<OpenJobAction.Response> listener) {
+                                ActionListener<AcknowledgedResponse> listener) {
         persistentTasksService.sendRemoveRequest(persistentTask.getId(),
                 new ActionListener<PersistentTasksCustomMetaData.PersistentTask<?>>() {
                     @Override
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportStartDatafeedAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportStartDatafeedAction.java
index fced6816128..0ea9eb77648 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportStartDatafeedAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportStartDatafeedAction.java
@@ -10,6 +10,7 @@ import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.ResourceAlreadyExistsException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
@@ -23,7 +24,11 @@ import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.license.LicenseUtils;
 import org.elasticsearch.license.XPackLicenseState;
+import org.elasticsearch.persistent.AllocatedPersistentTask;
 import org.elasticsearch.persistent.PersistentTaskState;
+import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
+import org.elasticsearch.persistent.PersistentTasksExecutor;
+import org.elasticsearch.persistent.PersistentTasksService;
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.tasks.TaskId;
 import org.elasticsearch.threadpool.ThreadPool;
@@ -38,14 +43,10 @@ import org.elasticsearch.xpack.core.ml.datafeed.DatafeedState;
 import org.elasticsearch.xpack.core.ml.job.config.Job;
 import org.elasticsearch.xpack.core.ml.job.config.JobState;
 import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
-import org.elasticsearch.persistent.AllocatedPersistentTask;
-import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
-import org.elasticsearch.persistent.PersistentTasksExecutor;
-import org.elasticsearch.persistent.PersistentTasksService;
 import org.elasticsearch.xpack.ml.MachineLearning;
-import org.elasticsearch.xpack.ml.datafeed.MlRemoteLicenseChecker;
 import org.elasticsearch.xpack.ml.datafeed.DatafeedManager;
 import org.elasticsearch.xpack.ml.datafeed.DatafeedNodeSelector;
+import org.elasticsearch.xpack.ml.datafeed.MlRemoteLicenseChecker;
 import org.elasticsearch.xpack.ml.datafeed.extractor.DataExtractorFactory;
 
 import java.util.List;
@@ -60,7 +61,7 @@ import java.util.function.Predicate;
  In case of instability persistent tasks checks may fail and that is ok, in that case all bets are off.
  The start datafeed api is a low through put api, so the fact that we redirect to elected master node shouldn't be an issue.
  */
-public class TransportStartDatafeedAction extends TransportMasterNodeAction<StartDatafeedAction.Request, StartDatafeedAction.Response> {
+public class TransportStartDatafeedAction extends TransportMasterNodeAction<StartDatafeedAction.Request, AcknowledgedResponse> {
 
     private final Client client;
     private final XPackLicenseState licenseState;
@@ -104,13 +105,13 @@ public class TransportStartDatafeedAction extends TransportMasterNodeAction<Star
     }
 
     @Override
-    protected StartDatafeedAction.Response newResponse() {
-        return new StartDatafeedAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(StartDatafeedAction.Request request, ClusterState state,
-                                   ActionListener<StartDatafeedAction.Response> listener) {
+                                   ActionListener<AcknowledgedResponse> listener) {
         StartDatafeedAction.DatafeedParams params = request.getParams();
         if (licenseState.isMachineLearningAllowed()) {
 
@@ -181,7 +182,7 @@ public class TransportStartDatafeedAction extends TransportMasterNodeAction<Star
     }
 
     private void waitForDatafeedStarted(String taskId, StartDatafeedAction.DatafeedParams params,
-                                        ActionListener<StartDatafeedAction.Response> listener) {
+                                        ActionListener<AcknowledgedResponse> listener) {
         DatafeedPredicate predicate = new DatafeedPredicate();
         persistentTasksService.waitForPersistentTaskCondition(taskId, predicate, params.getTimeout(),
                 new PersistentTasksService.WaitForPersistentTaskListener<StartDatafeedAction.DatafeedParams>() {
@@ -193,7 +194,7 @@ public class TransportStartDatafeedAction extends TransportMasterNodeAction<Star
                             // what would have happened if the error had been detected in the "fast fail" validation
                             cancelDatafeedStart(persistentTask, predicate.exception, listener);
                         } else {
-                            listener.onResponse(new StartDatafeedAction.Response(true));
+                            listener.onResponse(new AcknowledgedResponse(true));
                         }
                     }
 
@@ -211,7 +212,7 @@ public class TransportStartDatafeedAction extends TransportMasterNodeAction<Star
     }
 
     private void cancelDatafeedStart(PersistentTasksCustomMetaData.PersistentTask<StartDatafeedAction.DatafeedParams> persistentTask,
-                                     Exception exception, ActionListener<StartDatafeedAction.Response> listener) {
+                                     Exception exception, ActionListener<AcknowledgedResponse> listener) {
         persistentTasksService.sendRemoveRequest(persistentTask.getId(),
                 new ActionListener<PersistentTasksCustomMetaData.PersistentTask<?>>() {
                     @Override
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateDetectorAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateDetectorAction.java
index c2e89dc78c2..71b8ca5d6dc 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateDetectorAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateDetectorAction.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.ml.action;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.tasks.Task;
@@ -16,8 +17,7 @@ import org.elasticsearch.xpack.core.ml.action.ValidateDetectorAction;
 
 import java.util.function.Supplier;
 
-public class TransportValidateDetectorAction extends HandledTransportAction<ValidateDetectorAction.Request,
-        ValidateDetectorAction.Response> {
+public class TransportValidateDetectorAction extends HandledTransportAction<ValidateDetectorAction.Request, AcknowledgedResponse> {
 
     @Inject
     public TransportValidateDetectorAction(Settings settings, TransportService transportService, ActionFilters actionFilters) {
@@ -26,8 +26,8 @@ public class TransportValidateDetectorAction extends HandledTransportAction<Vali
     }
 
     @Override
-    protected void doExecute(Task task, ValidateDetectorAction.Request request, ActionListener<ValidateDetectorAction.Response> listener) {
-        listener.onResponse(new ValidateDetectorAction.Response(true));
+    protected void doExecute(Task task, ValidateDetectorAction.Request request, ActionListener<AcknowledgedResponse> listener) {
+        listener.onResponse(new AcknowledgedResponse(true));
     }
 
 }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateJobConfigAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateJobConfigAction.java
index b644bc1d470..c0347aa27d1 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateJobConfigAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportValidateJobConfigAction.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.ml.action;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.tasks.Task;
@@ -16,8 +17,7 @@ import org.elasticsearch.xpack.core.ml.action.ValidateJobConfigAction;
 
 import java.util.function.Supplier;
 
-public class TransportValidateJobConfigAction extends HandledTransportAction<ValidateJobConfigAction.Request,
-        ValidateJobConfigAction.Response> {
+public class TransportValidateJobConfigAction extends HandledTransportAction<ValidateJobConfigAction.Request, AcknowledgedResponse> {
 
     @Inject
     public TransportValidateJobConfigAction(Settings settings, TransportService transportService, ActionFilters actionFilters) {
@@ -27,8 +27,8 @@ public class TransportValidateJobConfigAction extends HandledTransportAction<Val
 
     @Override
     protected void doExecute(Task task, ValidateJobConfigAction.Request request,
-                             ActionListener<ValidateJobConfigAction.Response> listener) {
-        listener.onResponse(new ValidateJobConfigAction.Response(true));
+                             ActionListener<AcknowledgedResponse> listener) {
+        listener.onResponse(new AcknowledgedResponse(true));
     }
 
 }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java
index c18c2c940a4..d361bb21112 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/JobManager.java
@@ -9,6 +9,7 @@ import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.index.IndexResponse;
 import org.elasticsearch.action.support.WriteRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
 import org.elasticsearch.cluster.ClusterState;
@@ -52,8 +53,8 @@ import org.elasticsearch.xpack.core.ml.job.process.autodetect.state.ModelSnapsho
 import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 import org.elasticsearch.xpack.ml.MachineLearning;
 import org.elasticsearch.xpack.ml.job.categorization.CategorizationAnalyzer;
-import org.elasticsearch.xpack.ml.job.persistence.JobResultsProvider;
 import org.elasticsearch.xpack.ml.job.persistence.JobResultsPersister;
+import org.elasticsearch.xpack.ml.job.persistence.JobResultsProvider;
 import org.elasticsearch.xpack.ml.job.process.autodetect.UpdateParams;
 import org.elasticsearch.xpack.ml.notifications.Auditor;
 import org.elasticsearch.xpack.ml.utils.ChainTaskExecutor;
@@ -489,7 +490,7 @@ public class JobManager extends AbstractComponent {
     }
 
     public void deleteJob(DeleteJobAction.Request request, JobStorageDeletionTask task,
-                          ActionListener<DeleteJobAction.Response> actionListener) {
+                          ActionListener<AcknowledgedResponse> actionListener) {
 
         String jobId = request.getJobId();
         logger.debug("Deleting job '" + jobId + "'");
@@ -500,9 +501,9 @@ public class JobManager extends AbstractComponent {
             if (jobDeleted) {
                 logger.info("Job [" + jobId + "] deleted");
                 auditor.info(jobId, Messages.getMessage(Messages.JOB_AUDIT_DELETED));
-                actionListener.onResponse(new DeleteJobAction.Response(true));
+                actionListener.onResponse(new AcknowledgedResponse(true));
             } else {
-                actionListener.onResponse(new DeleteJobAction.Response(false));
+                actionListener.onResponse(new AcknowledgedResponse(false));
             }
         };
 
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProvider.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProvider.java
index e850d737d31..b9d7322b1ad 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProvider.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProvider.java
@@ -13,11 +13,9 @@ import org.elasticsearch.ResourceAlreadyExistsException;
 import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.bulk.BulkAction;
 import org.elasticsearch.action.bulk.BulkRequestBuilder;
 import org.elasticsearch.action.bulk.BulkResponse;
@@ -31,6 +29,7 @@ import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.ShardSearchFailure;
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.WriteRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.update.UpdateRequest;
 import org.elasticsearch.action.update.UpdateResponse;
 import org.elasticsearch.client.Client;
@@ -260,7 +259,7 @@ public class JobResultsProvider {
                     .addAlias(indexName, readAliasName, QueryBuilders.termQuery(Job.ID.getPreferredName(), job.getId()))
                     .addAlias(indexName, writeAliasName).request();
             executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, request,
-                    ActionListener.<IndicesAliasesResponse>wrap(r -> finalListener.onResponse(true), finalListener::onFailure),
+                    ActionListener.<AcknowledgedResponse>wrap(r -> finalListener.onResponse(true), finalListener::onFailure),
                     client.admin().indices()::aliases);
             }, finalListener::onFailure);
 
@@ -340,9 +339,9 @@ public class JobResultsProvider {
         try (XContentBuilder termFieldsMapping = ElasticsearchMappings.docMapping(termFields)) {
             final PutMappingRequest request = client.admin().indices().preparePutMapping(indexName).setType(ElasticsearchMappings.DOC_TYPE)
                     .setSource(termFieldsMapping).request();
-            executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, request, new ActionListener<PutMappingResponse>() {
+            executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, request, new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(PutMappingResponse putMappingResponse) {
+                public void onResponse(AcknowledgedResponse putMappingResponse) {
                     listener.onResponse(putMappingResponse.isAcknowledged());
                 }
 
@@ -1164,7 +1163,7 @@ public class JobResultsProvider {
                 }, errorHandler), client::search);
 
     }
-    
+
     public void updateCalendar(String calendarId, Set<String> jobIdsToAdd, Set<String> jobIdsToRemove,
                                Consumer<Calendar> handler, Consumer<Exception> errorHandler) {
 
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilder.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilder.java
index 200cb085125..0094eba97ce 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilder.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilder.java
@@ -61,7 +61,6 @@ public class AutodetectBuilder {
     public static final String LENGTH_ENCODED_INPUT_ARG = "--lengthEncodedInput";
     public static final String MODEL_CONFIG_ARG = "--modelconfig=";
     public static final String QUANTILES_STATE_PATH_ARG = "--quantilesState=";
-    public static final String PER_PARTITION_NORMALIZATION = "--perPartitionNormalization";
 
     private static final String CONF_EXTENSION = ".conf";
     static final String JOB_ID_ARG = "--jobid=";
@@ -207,10 +206,6 @@ public class AutodetectBuilder {
             if (Boolean.TRUE.equals(analysisConfig.getMultivariateByFields())) {
                 command.add(MULTIVARIATE_BY_FIELDS_ARG);
             }
-
-            if (analysisConfig.getUsePerPartitionNormalization()) {
-                command.add(PER_PARTITION_NORMALIZATION);
-            }
         }
 
         // Input is always length encoded
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java
index 063ab3b49d1..fa05c2e63ee 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java
@@ -499,7 +499,7 @@ public class AutodetectProcessManager extends AbstractComponent {
                 new JobRenormalizedResultsPersister(job.getId(), settings, client), normalizerFactory);
         ExecutorService renormalizerExecutorService = threadPool.executor(MachineLearning.UTILITY_THREAD_POOL_NAME);
         Renormalizer renormalizer = new ShortCircuitingRenormalizer(jobId, scoresUpdater,
-                renormalizerExecutorService, job.getAnalysisConfig().getUsePerPartitionNormalization());
+                renormalizerExecutorService);
 
         AutodetectProcess process = autodetectProcessFactory.createAutodetectProcess(job, autodetectParams, autoDetectExecutorService,
                 onProcessCrash(jobTask));
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizable.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizable.java
index 7ef23cb513b..9b54d01de5f 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizable.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizable.java
@@ -16,12 +16,10 @@ import java.util.Objects;
 import java.util.stream.Collectors;
 
 import static org.elasticsearch.xpack.ml.job.process.normalizer.Normalizable.ChildType.BUCKET_INFLUENCER;
-import static org.elasticsearch.xpack.ml.job.process.normalizer.Normalizable.ChildType.PARTITION_SCORE;
-
 
 public class BucketNormalizable extends Normalizable {
 
-    private static final List<ChildType> CHILD_TYPES = Arrays.asList(BUCKET_INFLUENCER, PARTITION_SCORE);
+    private static final List<ChildType> CHILD_TYPES = Arrays.asList(BUCKET_INFLUENCER);
 
     private final Bucket bucket;
 
@@ -117,11 +115,6 @@ public class BucketNormalizable extends Normalizable {
                         .map(bi -> new BucketInfluencerNormalizable(bi, getOriginatingIndex()))
                         .collect(Collectors.toList()));
                 break;
-            case PARTITION_SCORE:
-                children.addAll(bucket.getPartitionScores().stream()
-                        .map(ps -> new PartitionScoreNormalizable(ps, getOriginatingIndex()))
-                        .collect(Collectors.toList()));
-                break;
             default:
                 throw new IllegalArgumentException("Invalid type: " + type);
         }
@@ -135,8 +128,6 @@ public class BucketNormalizable extends Normalizable {
                 double oldScore = bucket.getAnomalyScore();
                 bucket.setAnomalyScore(maxScore);
                 return maxScore != oldScore;
-            case PARTITION_SCORE:
-                return false;
             default:
                 throw new IllegalArgumentException("Invalid type: " + childrenType);
         }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NativeNormalizerProcessFactory.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NativeNormalizerProcessFactory.java
index c96a3b48fe1..60f52d3f442 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NativeNormalizerProcessFactory.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NativeNormalizerProcessFactory.java
@@ -38,20 +38,19 @@ public class NativeNormalizerProcessFactory implements NormalizerProcessFactory
 
     @Override
     public NormalizerProcess createNormalizerProcess(String jobId, String quantilesState, Integer bucketSpan,
-                                                     boolean perPartitionNormalization, ExecutorService executorService) {
+                                                     ExecutorService executorService) {
         ProcessPipes processPipes = new ProcessPipes(env, NAMED_PIPE_HELPER, NormalizerBuilder.NORMALIZE, jobId,
                 true, false, true, true, false, false);
-        createNativeProcess(jobId, quantilesState, processPipes, bucketSpan, perPartitionNormalization);
+        createNativeProcess(jobId, quantilesState, processPipes, bucketSpan);
 
         return new NativeNormalizerProcess(jobId, settings, processPipes.getLogStream().get(),
                 processPipes.getProcessInStream().get(), processPipes.getProcessOutStream().get(), executorService);
     }
 
-    private void createNativeProcess(String jobId, String quantilesState, ProcessPipes processPipes, Integer bucketSpan,
-                                     boolean perPartitionNormalization) {
+    private void createNativeProcess(String jobId, String quantilesState, ProcessPipes processPipes, Integer bucketSpan) {
 
         try {
-            List<String> command = new NormalizerBuilder(env, jobId, quantilesState, bucketSpan, perPartitionNormalization).build();
+            List<String> command = new NormalizerBuilder(env, jobId, quantilesState, bucketSpan).build();
             processPipes.addArgs(command);
             nativeController.startProcess(command);
             processPipes.connectStreams(PROCESS_STARTUP_TIMEOUT);
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizable.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizable.java
index 7efadf29613..0d88372de17 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizable.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizable.java
@@ -11,7 +11,7 @@ import java.util.List;
 import java.util.Objects;
 
 public abstract class Normalizable implements ToXContentObject {
-    public enum ChildType {BUCKET_INFLUENCER, RECORD, PARTITION_SCORE};
+    public enum ChildType {BUCKET_INFLUENCER, RECORD};
 
     private final String indexName;
     private boolean hadBigNormalizedUpdate;
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizer.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizer.java
index 2d4e2135478..22e7d3ba995 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizer.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/Normalizer.java
@@ -46,15 +46,14 @@ public class Normalizer {
      * and normalizes the given results.
      *
      * @param bucketSpan                If <code>null</code> the default is used
-     * @param perPartitionNormalization Is normalization per partition (rather than per job)?
      * @param results                   Will be updated with the normalized results
      * @param quantilesState            The state to be used to seed the system change
      *                                  normalizer
      */
-    public void normalize(Integer bucketSpan, boolean perPartitionNormalization,
+    public void normalize(Integer bucketSpan,
                           List<? extends Normalizable> results, String quantilesState) {
         NormalizerProcess process = processFactory.createNormalizerProcess(jobId, quantilesState, bucketSpan,
-                perPartitionNormalization, executorService);
+                 executorService);
         NormalizerResultHandler resultsHandler = process.createNormalizedResultsHandler();
         Future<?> resultsHandlerFuture = executorService.submit(() -> {
             try {
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilder.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilder.java
index 5630a751275..37ffd92a3d7 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilder.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilder.java
@@ -29,15 +29,12 @@ public class NormalizerBuilder {
     private final String jobId;
     private final String quantilesState;
     private final Integer bucketSpan;
-    private final boolean perPartitionNormalization;
 
-    public NormalizerBuilder(Environment env, String jobId, String quantilesState, Integer bucketSpan,
-                             boolean perPartitionNormalization) {
+    public NormalizerBuilder(Environment env, String jobId, String quantilesState, Integer bucketSpan) {
         this.env = env;
         this.jobId = jobId;
         this.quantilesState = quantilesState;
         this.bucketSpan = bucketSpan;
-        this.perPartitionNormalization = perPartitionNormalization;
     }
 
     /**
@@ -49,9 +46,6 @@ public class NormalizerBuilder {
         command.add(NORMALIZE_PATH);
         addIfNotNull(bucketSpan, AutodetectBuilder.BUCKET_SPAN_ARG, command);
         command.add(AutodetectBuilder.LENGTH_ENCODED_INPUT_ARG);
-        if (perPartitionNormalization) {
-            command.add(AutodetectBuilder.PER_PARTITION_NORMALIZATION);
-        }
 
         if (quantilesState != null) {
             Path quantilesStateFilePath = AutodetectBuilder.writeNormalizerInitState(jobId, quantilesState, env);
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerProcessFactory.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerProcessFactory.java
index bdb63b77897..cf08190a993 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerProcessFactory.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerProcessFactory.java
@@ -17,6 +17,5 @@ public interface NormalizerProcessFactory {
      * @param executorService Executor service used to start the async tasks a job needs to operate the analytical process
      * @return The process
      */
-    NormalizerProcess createNormalizerProcess(String jobId, String quantilesState, Integer bucketSpan, boolean perPartitionNormalization,
-                                              ExecutorService executorService);
+    NormalizerProcess createNormalizerProcess(String jobId, String quantilesState, Integer bucketSpan, ExecutorService executorService);
 }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/PartitionScoreNormalizable.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/PartitionScoreNormalizable.java
deleted file mode 100644
index 91b2a7a505e..00000000000
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/PartitionScoreNormalizable.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.ml.job.process.normalizer;
-
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.xpack.core.ml.job.results.PartitionScore;
-
-import java.io.IOException;
-import java.util.Objects;
-
-
-public class PartitionScoreNormalizable extends AbstractLeafNormalizable {
-    private final PartitionScore score;
-
-    public PartitionScoreNormalizable(PartitionScore score, String indexName) {
-        super(indexName);
-        this.score = Objects.requireNonNull(score);
-    }
-
-    @Override
-    public String getId() {
-        throw new UnsupportedOperationException("PartitionScore has no ID as it should not be persisted outside of the owning bucket");
-    }
-
-    @Override
-    public Level getLevel() {
-        return Level.PARTITION;
-    }
-
-    @Override
-    public String getPartitionFieldName() {
-        return score.getPartitionFieldName();
-    }
-
-    @Override
-    public String getPartitionFieldValue() {
-        return score.getPartitionFieldValue();
-    }
-
-    @Override
-    public String getPersonFieldName() {
-        return null;
-    }
-
-    @Override
-    public String getPersonFieldValue() {
-        return null;
-    }
-
-    @Override
-    public String getFunctionName() {
-        return null;
-    }
-
-    @Override
-    public String getValueFieldName() {
-        return null;
-    }
-
-    @Override
-    public double getProbability() {
-        return score.getProbability();
-    }
-
-    @Override
-    public double getNormalizedScore() {
-        return score.getRecordScore();
-    }
-
-    @Override
-    public void setNormalizedScore(double normalizedScore) {
-        score.setRecordScore(normalizedScore);
-    }
-
-    @Override
-    public void setParentScore(double parentScore) {
-        // Do nothing as it is not holding the parent score.
-    }
-
-    @Override
-    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
-        return score.toXContent(builder, params);
-    }
-}
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdater.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdater.java
index cfb5660c911..c2ef2fab7f8 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdater.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdater.java
@@ -79,12 +79,12 @@ public class ScoresUpdater {
      * Update the anomaly score field on all previously persisted buckets
      * and all contained records
      */
-    public void update(String quantilesState, long endBucketEpochMs, long windowExtensionMs, boolean perPartitionNormalization) {
+    public void update(String quantilesState, long endBucketEpochMs, long windowExtensionMs) {
         Normalizer normalizer = normalizerFactory.create(jobId);
         int[] counts = {0, 0};
-        updateBuckets(normalizer, quantilesState, endBucketEpochMs, windowExtensionMs, counts, perPartitionNormalization);
-        updateRecords(normalizer, quantilesState, endBucketEpochMs, windowExtensionMs, counts, perPartitionNormalization);
-        updateInfluencers(normalizer, quantilesState, endBucketEpochMs, windowExtensionMs, counts, perPartitionNormalization);
+        updateBuckets(normalizer, quantilesState, endBucketEpochMs, windowExtensionMs, counts);
+        updateRecords(normalizer, quantilesState, endBucketEpochMs, windowExtensionMs, counts);
+        updateInfluencers(normalizer, quantilesState, endBucketEpochMs, windowExtensionMs, counts);
 
         // The updates will have been persisted in batches throughout the renormalization
         // process - this call just catches any leftovers
@@ -94,7 +94,7 @@ public class ScoresUpdater {
     }
 
     private void updateBuckets(Normalizer normalizer, String quantilesState, long endBucketEpochMs,
-                               long windowExtensionMs, int[] counts, boolean perPartitionNormalization) {
+                               long windowExtensionMs, int[] counts) {
         BatchedDocumentsIterator<Result<Bucket>> bucketsIterator =
                 jobResultsProvider.newBatchedBucketsIterator(jobId)
                         .timeRange(calcNormalizationWindowStart(endBucketEpochMs, windowExtensionMs), endBucketEpochMs)
@@ -114,14 +114,14 @@ public class ScoresUpdater {
                 if (current.result.isNormalizable()) {
                     bucketsToRenormalize.add(new BucketNormalizable(current.result, current.index));
                     if (bucketsToRenormalize.size() >= TARGET_BUCKETS_TO_RENORMALIZE) {
-                        normalizeBuckets(normalizer, bucketsToRenormalize, quantilesState, counts, perPartitionNormalization);
+                        normalizeBuckets(normalizer, bucketsToRenormalize, quantilesState, counts);
                         bucketsToRenormalize.clear();
                     }
                 }
             }
         }
         if (!bucketsToRenormalize.isEmpty()) {
-            normalizeBuckets(normalizer, bucketsToRenormalize, quantilesState, counts, perPartitionNormalization);
+            normalizeBuckets(normalizer, bucketsToRenormalize, quantilesState, counts);
         }
     }
 
@@ -130,8 +130,8 @@ public class ScoresUpdater {
     }
 
     private void normalizeBuckets(Normalizer normalizer, List<BucketNormalizable> normalizableBuckets,
-                                  String quantilesState, int[] counts, boolean perPartitionNormalization) {
-        normalizer.normalize(bucketSpan, perPartitionNormalization, normalizableBuckets, quantilesState);
+                                  String quantilesState, int[] counts) {
+        normalizer.normalize(bucketSpan, normalizableBuckets, quantilesState);
 
         for (BucketNormalizable bucketNormalizable : normalizableBuckets) {
             if (bucketNormalizable.hadBigNormalizedUpdate()) {
@@ -144,7 +144,7 @@ public class ScoresUpdater {
     }
 
     private void updateRecords(Normalizer normalizer, String quantilesState, long endBucketEpochMs,
-                               long windowExtensionMs, int[] counts, boolean perPartitionNormalization) {
+                               long windowExtensionMs, int[] counts) {
         BatchedDocumentsIterator<Result<AnomalyRecord>> recordsIterator = jobResultsProvider.newBatchedRecordsIterator(jobId)
                 .timeRange(calcNormalizationWindowStart(endBucketEpochMs, windowExtensionMs), endBucketEpochMs)
                 .includeInterim(false);
@@ -160,14 +160,14 @@ public class ScoresUpdater {
             List<Normalizable> asNormalizables = records.stream()
                     .map(recordResultIndex -> new RecordNormalizable(recordResultIndex.result, recordResultIndex.index))
                     .collect(Collectors.toList());
-            normalizer.normalize(bucketSpan, perPartitionNormalization, asNormalizables, quantilesState);
+            normalizer.normalize(bucketSpan, asNormalizables, quantilesState);
 
             persistChanged(counts, asNormalizables);
         }
     }
 
     private void updateInfluencers(Normalizer normalizer, String quantilesState, long endBucketEpochMs,
-                                   long windowExtensionMs, int[] counts, boolean perPartitionNormalization) {
+                                   long windowExtensionMs, int[] counts) {
         BatchedDocumentsIterator<Result<Influencer>> influencersIterator = jobResultsProvider.newBatchedInfluencersIterator(jobId)
                 .timeRange(calcNormalizationWindowStart(endBucketEpochMs, windowExtensionMs), endBucketEpochMs)
                 .includeInterim(false);
@@ -183,7 +183,7 @@ public class ScoresUpdater {
             List<Normalizable> asNormalizables = influencers.stream()
                     .map(influencerResultIndex -> new InfluencerNormalizable(influencerResultIndex.result, influencerResultIndex.index))
                     .collect(Collectors.toList());
-            normalizer.normalize(bucketSpan, perPartitionNormalization, asNormalizables, quantilesState);
+            normalizer.normalize(bucketSpan, asNormalizables, quantilesState);
 
             persistChanged(counts, asNormalizables);
         }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizer.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizer.java
index 057ed18cd69..7db66387db8 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizer.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizer.java
@@ -26,7 +26,6 @@ public class ShortCircuitingRenormalizer implements Renormalizer {
     private final String jobId;
     private final ScoresUpdater scoresUpdater;
     private final ExecutorService executorService;
-    private final boolean isPerPartitionNormalization;
     private final Deque<QuantilesWithLatch> quantilesDeque = new ConcurrentLinkedDeque<>();
     private final Deque<CountDownLatch> latchDeque = new ConcurrentLinkedDeque<>();
     /**
@@ -34,12 +33,10 @@ public class ShortCircuitingRenormalizer implements Renormalizer {
      */
     private final Semaphore semaphore = new Semaphore(1);
 
-    public ShortCircuitingRenormalizer(String jobId, ScoresUpdater scoresUpdater, ExecutorService executorService,
-                                       boolean isPerPartitionNormalization) {
+    public ShortCircuitingRenormalizer(String jobId, ScoresUpdater scoresUpdater, ExecutorService executorService) {
         this.jobId = jobId;
         this.scoresUpdater = scoresUpdater;
         this.executorService = executorService;
-        this.isPerPartitionNormalization = isPerPartitionNormalization;
     }
 
     @Override
@@ -161,8 +158,7 @@ public class ShortCircuitingRenormalizer implements Renormalizer {
                                 jobId, latestBucketTimeMs, earliestBucketTimeMs);
                         windowExtensionMs = 0;
                     }
-                    scoresUpdater.update(latestQuantiles.getQuantileState(), latestBucketTimeMs, windowExtensionMs,
-                            isPerPartitionNormalization);
+                    scoresUpdater.update(latestQuantiles.getQuantileState(), latestBucketTimeMs, windowExtensionMs);
                     latch.countDown();
                     latch = null;
                 }
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemover.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemover.java
index 0f1501c6689..47a10a8aea3 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemover.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemover.java
@@ -12,6 +12,7 @@ import org.elasticsearch.action.search.SearchAction;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.ThreadedActionListener;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.common.logging.Loggers;
@@ -123,9 +124,9 @@ public class ExpiredModelSnapshotsRemover extends AbstractExpiredJobDataRemover
         ModelSnapshot modelSnapshot = modelSnapshotIterator.next();
         DeleteModelSnapshotAction.Request deleteSnapshotRequest = new DeleteModelSnapshotAction.Request(
                 modelSnapshot.getJobId(), modelSnapshot.getSnapshotId());
-        client.execute(DeleteModelSnapshotAction.INSTANCE, deleteSnapshotRequest, new ActionListener<DeleteModelSnapshotAction.Response>() {
+        client.execute(DeleteModelSnapshotAction.INSTANCE, deleteSnapshotRequest, new ActionListener<AcknowledgedResponse>() {
                 @Override
-                public void onResponse(DeleteModelSnapshotAction.Response response) {
+                public void onResponse(AcknowledgedResponse response) {
                     try {
                         deleteModelSnapshots(modelSnapshotIterator, listener);
                     } catch (Exception e) {
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/datafeeds/RestStartDatafeedAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/datafeeds/RestStartDatafeedAction.java
index cb4cab14dda..07906a49c28 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/datafeeds/RestStartDatafeedAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/datafeeds/RestStartDatafeedAction.java
@@ -5,6 +5,7 @@
  */
 package org.elasticsearch.xpack.ml.rest.datafeeds;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.node.NodeClient;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
@@ -17,9 +18,9 @@ import org.elasticsearch.rest.RestRequest;
 import org.elasticsearch.rest.RestResponse;
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.rest.action.RestBuilderListener;
-import org.elasticsearch.xpack.ml.MachineLearning;
 import org.elasticsearch.xpack.core.ml.action.StartDatafeedAction;
 import org.elasticsearch.xpack.core.ml.datafeed.DatafeedConfig;
+import org.elasticsearch.xpack.ml.MachineLearning;
 
 import java.io.IOException;
 
@@ -60,10 +61,10 @@ public class RestStartDatafeedAction extends BaseRestHandler {
         }
         return channel -> {
             client.execute(StartDatafeedAction.INSTANCE, jobDatafeedRequest,
-                    new RestBuilderListener<StartDatafeedAction.Response>(channel) {
+                    new RestBuilderListener<AcknowledgedResponse>(channel) {
 
                         @Override
-                        public RestResponse buildResponse(StartDatafeedAction.Response r, XContentBuilder builder) throws Exception {
+                        public RestResponse buildResponse(AcknowledgedResponse r, XContentBuilder builder) throws Exception {
                             builder.startObject();
                             builder.field("started", r.isAcknowledged());
                             builder.endObject();
diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/job/RestOpenJobAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/job/RestOpenJobAction.java
index 80e00eb1a47..4da4e540307 100644
--- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/job/RestOpenJobAction.java
+++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/rest/job/RestOpenJobAction.java
@@ -5,6 +5,7 @@
  */
 package org.elasticsearch.xpack.ml.rest.job;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.node.NodeClient;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
@@ -16,9 +17,9 @@ import org.elasticsearch.rest.RestRequest;
 import org.elasticsearch.rest.RestResponse;
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.rest.action.RestBuilderListener;
-import org.elasticsearch.xpack.ml.MachineLearning;
 import org.elasticsearch.xpack.core.ml.action.OpenJobAction;
 import org.elasticsearch.xpack.core.ml.job.config.Job;
+import org.elasticsearch.xpack.ml.MachineLearning;
 
 import java.io.IOException;
 
@@ -50,9 +51,9 @@ public class RestOpenJobAction extends BaseRestHandler {
             request = new OpenJobAction.Request(jobParams);
         }
         return channel -> {
-            client.execute(OpenJobAction.INSTANCE, request, new RestBuilderListener<OpenJobAction.Response>(channel) {
+            client.execute(OpenJobAction.INSTANCE, request, new RestBuilderListener<AcknowledgedResponse>(channel) {
                 @Override
-                public RestResponse buildResponse(OpenJobAction.Response r, XContentBuilder builder) throws Exception {
+                public RestResponse buildResponse(AcknowledgedResponse r, XContentBuilder builder) throws Exception {
                     builder.startObject();
                     builder.field("opened", r.isAcknowledged());
                     builder.endObject();
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/license/MachineLearningLicensingTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/license/MachineLearningLicensingTests.java
index 57a97641791..e8ac4285b6b 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/license/MachineLearningLicensingTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/license/MachineLearningLicensingTests.java
@@ -7,12 +7,14 @@ package org.elasticsearch.license;
 
 import org.elasticsearch.ElasticsearchSecurityException;
 import org.elasticsearch.action.support.PlainActionFuture;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.transport.TransportClient;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.license.License.OperationMode;
+import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.test.junit.annotations.TestLogging;
 import org.elasticsearch.transport.Transport;
@@ -31,7 +33,6 @@ import org.elasticsearch.xpack.core.ml.action.StopDatafeedAction;
 import org.elasticsearch.xpack.core.ml.client.MachineLearningClient;
 import org.elasticsearch.xpack.core.ml.datafeed.DatafeedState;
 import org.elasticsearch.xpack.core.ml.job.config.JobState;
-import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
 import org.elasticsearch.xpack.ml.LocalStateMachineLearning;
 import org.elasticsearch.xpack.ml.support.BaseMlIntegTestCase;
 import org.junit.Before;
@@ -107,7 +108,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
         // test that license restricted apis do not work
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
-            PlainActionFuture<OpenJobAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), listener);
             listener.actionGet();
             fail("open job action should not be enabled!");
@@ -131,9 +132,9 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
         // test that license restricted apis do now work
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
-            PlainActionFuture<OpenJobAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), listener);
-            OpenJobAction.Response response = listener.actionGet();
+            AcknowledgedResponse response = listener.actionGet();
             assertNotNull(response);
         }
     }
@@ -208,12 +209,12 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
             PutDatafeedAction.Response putDatafeedResponse = putDatafeedListener.actionGet();
             assertNotNull(putDatafeedResponse);
             // open job
-            PlainActionFuture<OpenJobAction.Response> openJobListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> openJobListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), openJobListener);
-            OpenJobAction.Response openJobResponse = openJobListener.actionGet();
+            AcknowledgedResponse openJobResponse = openJobListener.actionGet();
             assertNotNull(openJobResponse);
             // start datafeed
-            PlainActionFuture<StartDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).startDatafeed(new StartDatafeedAction.Request(datafeedId, 0L), listener);
             listener.actionGet();
         }
@@ -244,12 +245,12 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
             // open job
-            PlainActionFuture<OpenJobAction.Response> openJobListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> openJobListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), openJobListener);
-            OpenJobAction.Response openJobResponse = openJobListener.actionGet();
+            AcknowledgedResponse openJobResponse = openJobListener.actionGet();
             assertNotNull(openJobResponse);
             // start datafeed
-            PlainActionFuture<StartDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).startDatafeed(new StartDatafeedAction.Request(datafeedId, 0L), listener);
             listener.actionGet();
         }
@@ -308,9 +309,9 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
                             Collections.singletonList(datafeedIndex))), putDatafeedListener);
             PutDatafeedAction.Response putDatafeedResponse = putDatafeedListener.actionGet();
             assertNotNull(putDatafeedResponse);
-            PlainActionFuture<OpenJobAction.Response> openJobListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> openJobListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), openJobListener);
-            OpenJobAction.Response openJobResponse = openJobListener.actionGet();
+            AcknowledgedResponse openJobResponse = openJobListener.actionGet();
             assertNotNull(openJobResponse);
         }
 
@@ -331,7 +332,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
         // test that license restricted apis do not work
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
-            PlainActionFuture<StartDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).startDatafeed(new StartDatafeedAction.Request(datafeedId, 0L), listener);
             listener.actionGet();
             fail("start datafeed action should not be enabled!");
@@ -349,14 +350,14 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
             // re-open job now that the license is valid again
-            PlainActionFuture<OpenJobAction.Response> openJobListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> openJobListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), openJobListener);
-            OpenJobAction.Response openJobResponse = openJobListener.actionGet();
+            AcknowledgedResponse openJobResponse = openJobListener.actionGet();
             assertNotNull(openJobResponse);
 
-            PlainActionFuture<StartDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).startDatafeed(new StartDatafeedAction.Request(datafeedId, 0L), listener);
-            StartDatafeedAction.Response response = listener.actionGet();
+            AcknowledgedResponse response = listener.actionGet();
             assertNotNull(response);
         }
     }
@@ -382,14 +383,14 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
                             Collections.singletonList(datafeedIndex))), putDatafeedListener);
             PutDatafeedAction.Response putDatafeedResponse = putDatafeedListener.actionGet();
             assertNotNull(putDatafeedResponse);
-            PlainActionFuture<OpenJobAction.Response> openJobListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> openJobListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), openJobListener);
-            OpenJobAction.Response openJobResponse = openJobListener.actionGet();
+            AcknowledgedResponse openJobResponse = openJobListener.actionGet();
             assertNotNull(openJobResponse);
-            PlainActionFuture<StartDatafeedAction.Response> startDatafeedListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> startDatafeedListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).startDatafeed(
                 new StartDatafeedAction.Request(datafeedId, 0L), startDatafeedListener);
-            StartDatafeedAction.Response startDatafeedResponse = startDatafeedListener.actionGet();
+            AcknowledgedResponse startDatafeedResponse = startDatafeedListener.actionGet();
             assertNotNull(startDatafeedResponse);
         }
 
@@ -438,9 +439,9 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
             new MachineLearningClient(client).putJob(new PutJobAction.Request(createJob(jobId)), putJobListener);
             PutJobAction.Response putJobResponse = putJobListener.actionGet();
             assertNotNull(putJobResponse);
-            PlainActionFuture<OpenJobAction.Response> openJobListener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> openJobListener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).openJob(new OpenJobAction.Request(jobId), openJobListener);
-            OpenJobAction.Response openJobResponse = openJobListener.actionGet();
+            AcknowledgedResponse openJobResponse = openJobListener.actionGet();
             assertNotNull(openJobResponse);
         }
 
@@ -489,7 +490,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
 
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
-            PlainActionFuture<DeleteJobAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).deleteJob(new DeleteJobAction.Request(jobId), listener);
             listener.actionGet();
         }
@@ -521,7 +522,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
 
         try (TransportClient client = new TestXPackTransportClient(settings, LocalStateMachineLearning.class)) {
             client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
-            PlainActionFuture<DeleteDatafeedAction.Response> listener = PlainActionFuture.newFuture();
+            PlainActionFuture<AcknowledgedResponse> listener = PlainActionFuture.newFuture();
             new MachineLearningClient(client).deleteDatafeed(new DeleteDatafeedAction.Request(datafeedId), listener);
             listener.actionGet();
         }
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/AutodetectResultProcessorIT.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/AutodetectResultProcessorIT.java
index 8f6005a2161..756eeb8626d 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/AutodetectResultProcessorIT.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/AutodetectResultProcessorIT.java
@@ -5,6 +5,7 @@
  */
 package org.elasticsearch.xpack.ml.integration;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.routing.UnassignedInfo;
 import org.elasticsearch.common.io.stream.Writeable;
@@ -36,8 +37,8 @@ import org.elasticsearch.xpack.ml.MachineLearning;
 import org.elasticsearch.xpack.ml.MlSingleNodeTestCase;
 import org.elasticsearch.xpack.ml.job.persistence.BucketsQueryBuilder;
 import org.elasticsearch.xpack.ml.job.persistence.InfluencersQueryBuilder;
-import org.elasticsearch.xpack.ml.job.persistence.JobResultsProvider;
 import org.elasticsearch.xpack.ml.job.persistence.JobResultsPersister;
+import org.elasticsearch.xpack.ml.job.persistence.JobResultsProvider;
 import org.elasticsearch.xpack.ml.job.persistence.RecordsQueryBuilder;
 import org.elasticsearch.xpack.ml.job.process.autodetect.AutodetectProcess;
 import org.elasticsearch.xpack.ml.job.process.autodetect.output.AutoDetectResultProcessor;
@@ -115,7 +116,7 @@ public class AutodetectResultProcessorIT extends MlSingleNodeTestCase {
     @After
     public void deleteJob() throws Exception {
         DeleteJobAction.Request request = new DeleteJobAction.Request(JOB_ID);
-        DeleteJobAction.Response response = client().execute(DeleteJobAction.INSTANCE, request).actionGet();
+        AcknowledgedResponse response = client().execute(DeleteJobAction.INSTANCE, request).actionGet();
         assertTrue(response.isAcknowledged());
     }
 
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/DeleteJobIT.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/DeleteJobIT.java
index f389bc4b749..ed23a5328ae 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/DeleteJobIT.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/DeleteJobIT.java
@@ -6,14 +6,15 @@
 package org.elasticsearch.xpack.ml.integration;
 
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.ClusterStateUpdateTask;
 import org.elasticsearch.cluster.metadata.MetaData;
+import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
 import org.elasticsearch.xpack.core.ml.MlMetadata;
 import org.elasticsearch.xpack.core.ml.action.DeleteJobAction;
 import org.elasticsearch.xpack.core.ml.action.PutJobAction;
 import org.elasticsearch.xpack.core.ml.job.config.Job;
-import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
 import org.elasticsearch.xpack.ml.support.BaseMlIntegTestCase;
 
 import java.util.concurrent.CountDownLatch;
@@ -56,9 +57,9 @@ public class DeleteJobIT extends BaseMlIntegTestCase {
         // Job is marked as deleting so now a delete request should wait for it.
         AtomicBoolean isDeleted = new AtomicBoolean(false);
         AtomicReference<Exception> deleteFailure = new AtomicReference<>();
-        ActionListener<DeleteJobAction.Response> deleteListener = new ActionListener<DeleteJobAction.Response>() {
+        ActionListener<AcknowledgedResponse> deleteListener = new ActionListener<AcknowledgedResponse>() {
             @Override
-            public void onResponse(DeleteJobAction.Response response) {
+            public void onResponse(AcknowledgedResponse response) {
                 isDeleted.compareAndSet(false, response.isAcknowledged());
             }
 
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/NetworkDisruptionIT.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/NetworkDisruptionIT.java
index 27a827992df..67138cde5bd 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/NetworkDisruptionIT.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/integration/NetworkDisruptionIT.java
@@ -7,6 +7,7 @@ package org.elasticsearch.xpack.ml.integration;
 
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.ByteSizeUnit;
 import org.elasticsearch.common.unit.ByteSizeValue;
@@ -62,7 +63,7 @@ public class NetworkDisruptionIT extends BaseMlIntegTestCase {
         ensureGreen();
 
         OpenJobAction.Request openJobRequest = new OpenJobAction.Request(job.getId());
-        OpenJobAction.Response openJobResponse = client().execute(OpenJobAction.INSTANCE, openJobRequest).actionGet();
+        AcknowledgedResponse openJobResponse = client().execute(OpenJobAction.INSTANCE, openJobRequest).actionGet();
         assertTrue(openJobResponse.isAcknowledged());
 
         // Record which node the job starts off on
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java
index 2c0681c33f2..929961a33fc 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/JobResultsProviderTests.java
@@ -10,12 +10,12 @@ import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.get.GetResponse;
 import org.elasticsearch.action.search.MultiSearchRequest;
 import org.elasticsearch.action.search.MultiSearchResponse;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
 import org.elasticsearch.cluster.ClusterName;
@@ -128,7 +128,7 @@ public class JobResultsProviderTests extends ESTestCase {
         MockClientBuilder clientBuilder = new MockClientBuilder(CLUSTER_NAME);
         clientBuilder.prepareAlias(AnomalyDetectorsIndex.jobResultsAliasedName("foo"),
                 AnomalyDetectorsIndex.jobResultsAliasedName("foo123"), jobFilter);
-        clientBuilder.preparePutMapping(mock(PutMappingResponse.class), Result.TYPE.getPreferredName());
+        clientBuilder.preparePutMapping(mock(AcknowledgedResponse.class), Result.TYPE.getPreferredName());
 
         GetMappingsResponse getMappingsResponse = mock(GetMappingsResponse.class);
         ImmutableOpenMap<String, MappingMetaData> typeMappings = ImmutableOpenMap.<String, MappingMetaData>of();
@@ -197,7 +197,7 @@ public class JobResultsProviderTests extends ESTestCase {
         clientBuilder.createIndexRequest(captor, indexName);
         clientBuilder.prepareAlias(indexName, readAliasName, jobFilter);
         clientBuilder.prepareAlias(indexName, writeAliasName);
-        clientBuilder.preparePutMapping(mock(PutMappingResponse.class), Result.TYPE.getPreferredName());
+        clientBuilder.preparePutMapping(mock(AcknowledgedResponse.class), Result.TYPE.getPreferredName());
 
         Job.Builder job = buildJobBuilder("foo");
         job.setResultsIndexName("bar");
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java
index 61fc73d1641..7dbe3bbf1ff 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/persistence/MockClientBuilder.java
@@ -11,21 +11,17 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequestBuilder
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
-import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequestBuilder;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.bulk.BulkRequest;
 import org.elasticsearch.action.bulk.BulkRequestBuilder;
 import org.elasticsearch.action.bulk.BulkResponse;
@@ -38,6 +34,7 @@ import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.SearchScrollRequestBuilder;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.AdminClient;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.ClusterAdminClient;
@@ -50,7 +47,6 @@ import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.search.sort.SortBuilder;
 import org.elasticsearch.search.sort.SortOrder;
 import org.elasticsearch.threadpool.ThreadPool;
-import org.elasticsearch.xpack.core.ml.action.DeleteJobAction;
 import org.mockito.ArgumentCaptor;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -138,8 +134,8 @@ public class MockClientBuilder {
 
     @SuppressWarnings({ "unchecked" })
     public MockClientBuilder addIndicesDeleteResponse(String index, boolean exists, boolean exception,
-            ActionListener<DeleteJobAction.Response> actionListener) throws InterruptedException, ExecutionException, IOException {
-        DeleteIndexResponse response = DeleteIndexAction.INSTANCE.newResponse();
+            ActionListener<AcknowledgedResponse> actionListener) throws InterruptedException, ExecutionException, IOException {
+        AcknowledgedResponse response = DeleteIndexAction.INSTANCE.newResponse();
         StreamInput si = mock(StreamInput.class);
         // this looks complicated but Mockito can't mock the final method
         // DeleteIndexResponse.isAcknowledged() and the only way to create
@@ -153,7 +149,7 @@ public class MockClientBuilder {
             if (exception) {
                 actionListener.onFailure(new InterruptedException());
             } else {
-                actionListener.onResponse(new DeleteJobAction.Response(true));
+                actionListener.onResponse(new AcknowledgedResponse(true));
             }
             return null;
         }).when(indicesAdminClient).delete(any(DeleteIndexRequest.class), any(ActionListener.class));
@@ -294,9 +290,9 @@ public class MockClientBuilder {
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
-                ActionListener<IndicesAliasesResponse> listener =
-                        (ActionListener<IndicesAliasesResponse>) invocationOnMock.getArguments()[0];
-                listener.onResponse(mock(IndicesAliasesResponse.class));
+                ActionListener<AcknowledgedResponse> listener =
+                        (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[0];
+                listener.onResponse(mock(AcknowledgedResponse.class));
                 return null;
             }
         }).when(aliasesRequestBuilder).execute(any());
@@ -310,9 +306,9 @@ public class MockClientBuilder {
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
-                ActionListener<IndicesAliasesResponse> listener =
-                        (ActionListener<IndicesAliasesResponse>) invocationOnMock.getArguments()[1];
-                listener.onResponse(mock(IndicesAliasesResponse.class));
+                ActionListener<AcknowledgedResponse> listener =
+                        (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
+                listener.onResponse(mock(AcknowledgedResponse.class));
                 return null;
             }
         }).when(indicesAdminClient).aliases(any(IndicesAliasesRequest.class), any(ActionListener.class));
@@ -337,15 +333,15 @@ public class MockClientBuilder {
         return this;
     }
 
-    public MockClientBuilder preparePutMapping(PutMappingResponse response, String type) {
+    public MockClientBuilder preparePutMapping(AcknowledgedResponse response, String type) {
         PutMappingRequestBuilder requestBuilder = mock(PutMappingRequestBuilder.class);
         when(requestBuilder.setType(eq(type))).thenReturn(requestBuilder);
         when(requestBuilder.setSource(any(XContentBuilder.class))).thenReturn(requestBuilder);
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
-                ActionListener<PutMappingResponse> listener =
-                        (ActionListener<PutMappingResponse>) invocationOnMock.getArguments()[0];
+                ActionListener<AcknowledgedResponse> listener =
+                        (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[0];
                 listener.onResponse(response);
                 return null;
             }
@@ -376,9 +372,9 @@ public class MockClientBuilder {
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
-                ActionListener<PutIndexTemplateResponse> listener =
-                        (ActionListener<PutIndexTemplateResponse>) invocationOnMock.getArguments()[1];
-                listener.onResponse(mock(PutIndexTemplateResponse.class));
+                ActionListener<AcknowledgedResponse> listener =
+                        (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
+                listener.onResponse(mock(AcknowledgedResponse.class));
                 return null;
             }
         }).when(indicesAdminClient).putTemplate(requestCaptor.capture(), any(ActionListener.class));
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilderTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilderTests.java
index 0f831064411..325ad52864b 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilderTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectBuilderTests.java
@@ -56,7 +56,6 @@ public class AutodetectBuilderTests extends ESTestCase {
         acBuilder.setSummaryCountFieldName("summaryField");
         acBuilder.setOverlappingBuckets(true);
         acBuilder.setMultivariateByFields(true);
-        acBuilder.setUsePerPartitionNormalization(true);
         job.setAnalysisConfig(acBuilder);
 
         DataDescription.Builder dd = new DataDescription.Builder();
@@ -66,7 +65,7 @@ public class AutodetectBuilderTests extends ESTestCase {
         job.setDataDescription(dd);
 
         List<String> command = autodetectBuilder(job.build()).buildAutodetectCommand();
-        assertEquals(13, command.size());
+        assertEquals(12, command.size());
         assertTrue(command.contains(AutodetectBuilder.AUTODETECT_PATH));
         assertTrue(command.contains(AutodetectBuilder.BUCKET_SPAN_ARG + "120"));
         assertTrue(command.contains(AutodetectBuilder.LATENCY_ARG + "360"));
@@ -80,8 +79,6 @@ public class AutodetectBuilderTests extends ESTestCase {
         assertTrue(command.contains(AutodetectBuilder.TIME_FIELD_ARG + "tf"));
         assertTrue(command.contains(AutodetectBuilder.JOB_ID_ARG + "unit-test-job"));
 
-        assertTrue(command.contains(AutodetectBuilder.PER_PARTITION_NORMALIZATION));
-
         int expectedPersistInterval = 10800 + AutodetectBuilder.calculateStaggeringInterval(job.getId());
         assertTrue(command.contains(AutodetectBuilder.PERSIST_INTERVAL_ARG + expectedPersistInterval));
         int expectedMaxQuantileInterval = 21600 + AutodetectBuilder.calculateStaggeringInterval(job.getId());
@@ -116,4 +113,4 @@ public class AutodetectBuilderTests extends ESTestCase {
     private AutodetectBuilder autodetectBuilder(Job job) {
         return new AutodetectBuilder(job, filesToDelete, logger, env, settings, nativeController, processPipes);
     }
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/output/AutoDetectResultProcessorTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/output/AutoDetectResultProcessorTests.java
index c5a459f70f3..05b6bc7209b 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/output/AutoDetectResultProcessorTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/output/AutoDetectResultProcessorTests.java
@@ -172,25 +172,6 @@ public class AutoDetectResultProcessorTests extends ESTestCase {
         verifyNoMoreInteractions(persister);
     }
 
-    public void testProcessResult_records_isPerPartitionNormalization() {
-        JobResultsPersister.Builder bulkBuilder = mock(JobResultsPersister.Builder.class);
-        when(persister.bulkPersisterBuilder(JOB_ID)).thenReturn(bulkBuilder);
-
-        AutoDetectResultProcessor.Context context = new AutoDetectResultProcessor.Context("foo", bulkBuilder);
-        context.deleteInterimRequired = false;
-        AutodetectResult result = mock(AutodetectResult.class);
-        AnomalyRecord record1 = new AnomalyRecord("foo", new Date(123), 123);
-        record1.setPartitionFieldValue("pValue");
-        AnomalyRecord record2 = new AnomalyRecord("foo", new Date(123), 123);
-        record2.setPartitionFieldValue("pValue");
-        List<AnomalyRecord> records = Arrays.asList(record1, record2);
-        when(result.getRecords()).thenReturn(records);
-        processorUnderTest.processResult(context, result);
-
-        verify(bulkBuilder, times(1)).persistRecords(records);
-        verify(bulkBuilder, never()).executeRequest();
-        verifyNoMoreInteractions(persister);
-    }
 
     public void testProcessResult_influencers() {
         JobResultsPersister.Builder bulkBuilder = mock(JobResultsPersister.Builder.class);
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizableTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizableTests.java
index 4436fcc7026..f2cd6572db6 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizableTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/BucketNormalizableTests.java
@@ -9,10 +9,8 @@ import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.xpack.core.ml.job.results.AnomalyRecord;
 import org.elasticsearch.xpack.core.ml.job.results.Bucket;
 import org.elasticsearch.xpack.core.ml.job.results.BucketInfluencer;
-import org.elasticsearch.xpack.core.ml.job.results.PartitionScore;
 import org.junit.Before;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -46,11 +44,6 @@ public class BucketNormalizableTests extends ESTestCase {
         AnomalyRecord record2 = new AnomalyRecord("foo", bucket.getTimestamp(), 600);
         record2.setRecordScore(2.0);
         bucket.setRecords(Arrays.asList(record1, record2));
-
-        List<PartitionScore> partitionScores = new ArrayList<>();
-        partitionScores.add(new PartitionScore("pf1", "pv1", 0.3, 0.2, 0.1));
-        partitionScores.add(new PartitionScore("pf1", "pv2", 0.5, 0.4, 0.01));
-        bucket.setPartitionScores(partitionScores);
     }
 
     public void testIsContainerOnly() {
@@ -106,15 +99,11 @@ public class BucketNormalizableTests extends ESTestCase {
         BucketNormalizable bn = new BucketNormalizable(bucket, INDEX_NAME);
 
         List<Normalizable> children = bn.getChildren();
-        assertEquals(4, children.size());
+        assertEquals(2, children.size());
         assertTrue(children.get(0) instanceof BucketInfluencerNormalizable);
         assertEquals(42.0, children.get(0).getNormalizedScore(), EPSILON);
         assertTrue(children.get(1) instanceof BucketInfluencerNormalizable);
         assertEquals(88.0, children.get(1).getNormalizedScore(), EPSILON);
-        assertTrue(children.get(2) instanceof PartitionScoreNormalizable);
-        assertEquals(0.2, children.get(2).getNormalizedScore(), EPSILON);
-        assertTrue(children.get(3) instanceof PartitionScoreNormalizable);
-        assertEquals(0.4, children.get(3).getNormalizedScore(), EPSILON);
     }
 
     public void testGetChildren_GivenTypeBucketInfluencer() {
@@ -132,7 +121,6 @@ public class BucketNormalizableTests extends ESTestCase {
         BucketNormalizable bucketNormalizable = new BucketNormalizable(bucket, INDEX_NAME);
 
         assertTrue(bucketNormalizable.setMaxChildrenScore(Normalizable.ChildType.BUCKET_INFLUENCER, 95.0));
-        assertFalse(bucketNormalizable.setMaxChildrenScore(Normalizable.ChildType.PARTITION_SCORE, 42.0));
 
         assertEquals(95.0, bucket.getAnomalyScore(), EPSILON);
     }
@@ -141,7 +129,6 @@ public class BucketNormalizableTests extends ESTestCase {
         BucketNormalizable bucketNormalizable = new BucketNormalizable(bucket, INDEX_NAME);
 
         assertFalse(bucketNormalizable.setMaxChildrenScore(Normalizable.ChildType.BUCKET_INFLUENCER, 88.0));
-        assertFalse(bucketNormalizable.setMaxChildrenScore(Normalizable.ChildType.PARTITION_SCORE, 2.0));
 
         assertEquals(88.0, bucket.getAnomalyScore(), EPSILON);
     }
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilderTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilderTests.java
index 64e595fd5a0..5d9c183c738 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilderTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerBuilderTests.java
@@ -21,11 +21,10 @@ public class NormalizerBuilderTests extends ESTestCase {
                 Settings.builder().put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()).build());
         String jobId = "unit-test-job";
 
-        List<String> command = new NormalizerBuilder(env, jobId, null, 300, true).build();
-        assertEquals(4, command.size());
+        List<String> command = new NormalizerBuilder(env, jobId, null, 300).build();
+        assertEquals(3, command.size());
         assertTrue(command.contains("./normalize"));
         assertTrue(command.contains(AutodetectBuilder.BUCKET_SPAN_ARG + "300"));
         assertTrue(command.contains(AutodetectBuilder.LENGTH_ENCODED_INPUT_ARG));
-        assertTrue(command.contains(AutodetectBuilder.PER_PARTITION_NORMALIZATION));
     }
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerTests.java
index 1b34226e336..d06146ad53f 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/NormalizerTests.java
@@ -49,7 +49,7 @@ public class NormalizerTests extends ESTestCase {
         ExecutorService threadpool = Executors.newScheduledThreadPool(1);
         try {
             NormalizerProcessFactory processFactory = mock(NormalizerProcessFactory.class);
-            when(processFactory.createNormalizerProcess(eq(JOB_ID), eq(QUANTILES_STATE), eq(BUCKET_SPAN), eq(false),
+            when(processFactory.createNormalizerProcess(eq(JOB_ID), eq(QUANTILES_STATE), eq(BUCKET_SPAN),
                     any())).thenReturn(new MultiplyingNormalizerProcess(Settings.EMPTY, FACTOR));
             Normalizer normalizer = new Normalizer(JOB_ID, processFactory, threadpool);
 
@@ -58,7 +58,7 @@ public class NormalizerTests extends ESTestCase {
             bucket.addBucketInfluencer(createTimeBucketInfluencer(bucket.getTimestamp(), 0.07, INITIAL_SCORE));
 
             List<Normalizable> asNormalizables = Arrays.asList(new BucketNormalizable(bucket, INDEX_NAME));
-            normalizer.normalize(BUCKET_SPAN, false, asNormalizables, QUANTILES_STATE);
+            normalizer.normalize(BUCKET_SPAN, asNormalizables, QUANTILES_STATE);
 
             assertEquals(1, asNormalizables.size());
             assertEquals(FACTOR * INITIAL_SCORE, asNormalizables.get(0).getNormalizedScore(), 0.0001);
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdaterTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdaterTests.java
index 2acaf973594..9836cf93718 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdaterTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ScoresUpdaterTests.java
@@ -33,7 +33,6 @@ import java.util.Deque;
 import java.util.List;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyList;
 import static org.mockito.Matchers.anyListOf;
@@ -95,7 +94,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         buckets.add(bucket);
         givenProviderReturnsBuckets(buckets);
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(0);
         verifyNothingWasUpdated();
@@ -113,7 +112,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsBuckets(buckets);
         givenProviderReturnsRecords(new ArrayDeque<>());
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(1);
         verify(jobRenormalizedResultsPersister, times(1)).updateBucket(any());
@@ -129,7 +128,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsBuckets(buckets);
         givenProviderReturnsRecords(new ArrayDeque<>());
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(1);
         verifyBucketWasUpdated(1);
@@ -150,7 +149,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsBuckets(buckets);
         givenProviderReturnsRecords(records);
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(2);
         verify(jobRenormalizedResultsPersister, times(1)).updateBucket(any());
@@ -176,7 +175,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsBuckets(batch1, batch2);
         givenProviderReturnsRecords(new ArrayDeque<>());
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(1);
 
@@ -212,7 +211,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         recordIter.requireIncludeInterim(false);
         when(jobResultsProvider.newBatchedRecordsIterator(JOB_ID)).thenReturn(recordIter);
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(2);
     }
@@ -224,7 +223,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         influencers.add(influencer);
         givenProviderReturnsInfluencers(influencers);
 
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(1);
         verify(jobRenormalizedResultsPersister, times(1)).updateResults(any());
@@ -253,7 +252,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsRecords(records);
 
         scoresUpdater.shutdown();
-        scoresUpdater.update(QUANTILES_STATE, 3600, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 3600, 0);
 
         verifyNormalizerWasInvoked(0);
         verify(jobRenormalizedResultsPersister, never()).updateBucket(any());
@@ -272,7 +271,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsRecords(new ArrayDeque<>());
         givenProviderReturnsNoInfluencers();
 
-        scoresUpdater.update(QUANTILES_STATE, 2595600000L, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 2595600000L, 0);
 
         verifyNormalizerWasInvoked(1);
         verifyBucketWasUpdated(1);
@@ -289,7 +288,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsRecords(new ArrayDeque<>());
         givenProviderReturnsNoInfluencers();
 
-        scoresUpdater.update(QUANTILES_STATE, 90000000L, 0, false);
+        scoresUpdater.update(QUANTILES_STATE, 90000000L, 0);
 
         verifyNormalizerWasInvoked(1);
         verifyBucketWasUpdated(1);
@@ -307,7 +306,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         givenProviderReturnsRecords(new ArrayDeque<>());
         givenProviderReturnsNoInfluencers();
 
-        scoresUpdater.update(QUANTILES_STATE, 90000000L, 900000, false);
+        scoresUpdater.update(QUANTILES_STATE, 90000000L, 900000);
 
         verifyNormalizerWasInvoked(1);
         verifyBucketWasUpdated(1);
@@ -339,7 +338,7 @@ public class ScoresUpdaterTests extends ESTestCase {
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
-                List<Normalizable> normalizables = (List<Normalizable>) invocationOnMock.getArguments()[2];
+                List<Normalizable> normalizables = (List<Normalizable>) invocationOnMock.getArguments()[1];
                 for (Normalizable normalizable : normalizables) {
                     normalizable.raiseBigChangeFlag();
                     for (Normalizable child : normalizable.getChildren()) {
@@ -348,7 +347,7 @@ public class ScoresUpdaterTests extends ESTestCase {
                 }
                 return null;
             }
-        }).when(normalizer).normalize(anyInt(), anyBoolean(), anyList(), anyString());
+        }).when(normalizer).normalize(anyInt(), anyList(), anyString());
     }
 
     private void givenProviderReturnsBuckets(Deque<Bucket> batch1, Deque<Bucket> batch2) {
@@ -416,7 +415,7 @@ public class ScoresUpdaterTests extends ESTestCase {
     private void verifyNormalizerWasInvoked(int times) throws IOException {
         int bucketSpan = job.getAnalysisConfig() == null ? 0 : ((Long) job.getAnalysisConfig().getBucketSpan().seconds()).intValue();
         verify(normalizer, times(times)).normalize(
-                eq(bucketSpan), eq(false), anyListOf(Normalizable.class),
+                eq(bucketSpan), anyListOf(Normalizable.class),
                 eq(QUANTILES_STATE));
     }
 
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizerTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizerTests.java
index 769d3657b04..e10d7191acc 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizerTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/process/normalizer/ShortCircuitingRenormalizerTests.java
@@ -18,7 +18,6 @@ import java.util.concurrent.TimeUnit;
 
 import static org.hamcrest.Matchers.is;
 import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -43,10 +42,7 @@ public class ShortCircuitingRenormalizerTests extends ESTestCase {
     public void testNormalize() throws InterruptedException {
         ExecutorService threadpool = Executors.newScheduledThreadPool(10);
         try {
-            boolean isPerPartitionNormalization = randomBoolean();
-
-            ShortCircuitingRenormalizer renormalizer = new ShortCircuitingRenormalizer(JOB_ID, scoresUpdater, threadpool,
-                    isPerPartitionNormalization);
+            ShortCircuitingRenormalizer renormalizer = new ShortCircuitingRenormalizer(JOB_ID, scoresUpdater, threadpool);
 
             // Blast through many sets of quantiles in quick succession, faster than the normalizer can process them
             for (int i = 1; i < TEST_SIZE / 2; ++i) {
@@ -61,7 +57,7 @@ public class ShortCircuitingRenormalizerTests extends ESTestCase {
             renormalizer.waitUntilIdle();
 
             ArgumentCaptor<String> stateCaptor = ArgumentCaptor.forClass(String.class);
-            verify(scoresUpdater, atLeastOnce()).update(stateCaptor.capture(), anyLong(), anyLong(), eq(isPerPartitionNormalization));
+            verify(scoresUpdater, atLeastOnce()).update(stateCaptor.capture(), anyLong(), anyLong());
 
             List<String> quantilesUsed = stateCaptor.getAllValues();
             assertFalse(quantilesUsed.isEmpty());
@@ -91,7 +87,7 @@ public class ShortCircuitingRenormalizerTests extends ESTestCase {
     public void testIsEnabled_GivenNormalizationWindowIsZero() {
         ScoresUpdater scoresUpdater = mock(ScoresUpdater.class);
         when(scoresUpdater.getNormalizationWindow()).thenReturn(0L);
-        ShortCircuitingRenormalizer renormalizer = new ShortCircuitingRenormalizer(JOB_ID, scoresUpdater, null, randomBoolean());
+        ShortCircuitingRenormalizer renormalizer = new ShortCircuitingRenormalizer(JOB_ID, scoresUpdater, null);
 
         assertThat(renormalizer.isEnabled(), is(false));
     }
@@ -99,7 +95,7 @@ public class ShortCircuitingRenormalizerTests extends ESTestCase {
     public void testIsEnabled_GivenNormalizationWindowGreaterThanZero() {
         ScoresUpdater scoresUpdater = mock(ScoresUpdater.class);
         when(scoresUpdater.getNormalizationWindow()).thenReturn(1L);
-        ShortCircuitingRenormalizer renormalizer = new ShortCircuitingRenormalizer(JOB_ID, scoresUpdater, null, randomBoolean());
+        ShortCircuitingRenormalizer renormalizer = new ShortCircuitingRenormalizer(JOB_ID, scoresUpdater, null);
 
         assertThat(renormalizer.isEnabled(), is(true));
     }
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/BucketTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/BucketTests.java
index 966501db43f..65343b0a068 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/BucketTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/BucketTests.java
@@ -13,7 +13,6 @@ import org.elasticsearch.xpack.core.ml.job.results.AnomalyRecord;
 import org.elasticsearch.xpack.core.ml.job.results.AnomalyRecordTests;
 import org.elasticsearch.xpack.core.ml.job.results.Bucket;
 import org.elasticsearch.xpack.core.ml.job.results.BucketInfluencer;
-import org.elasticsearch.xpack.core.ml.job.results.PartitionScore;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -61,15 +60,6 @@ public class BucketTests extends AbstractSerializingTestCase<Bucket> {
         if (randomBoolean()) {
             bucket.setInterim(randomBoolean());
         }
-        if (randomBoolean()) {
-            int size = randomInt(10);
-            List<PartitionScore> partitionScores = new ArrayList<>(size);
-            for (int i = 0; i < size; i++) {
-                partitionScores.add(new PartitionScore(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20), randomDouble(),
-                        randomDouble(), randomDouble()));
-            }
-            bucket.setPartitionScores(partitionScores);
-        }
         if (randomBoolean()) {
             bucket.setProcessingTimeMs(randomLong());
         }
@@ -235,15 +225,6 @@ public class BucketTests extends AbstractSerializingTestCase<Bucket> {
         assertFalse(bucket.isNormalizable());
     }
 
-    public void testIsNormalizable_GivenAnomalyScoreIsZeroAndPartitionsScoresAreNonZero() {
-        Bucket bucket = new Bucket("foo", new Date(123), 123);
-        bucket.addBucketInfluencer(new BucketInfluencer("foo", new Date(123), 123));
-        bucket.setAnomalyScore(0.0);
-        bucket.setPartitionScores(Collections.singletonList(new PartitionScore("n", "v", 50.0, 40.0, 0.01)));
-
-        assertTrue(bucket.isNormalizable());
-    }
-
     public void testIsNormalizable_GivenAnomalyScoreIsNonZeroAndRecordCountIsZero() {
         Bucket bucket = new Bucket("foo", new Date(123), 123);
         bucket.addBucketInfluencer(new BucketInfluencer("foo", new Date(123), 123));
@@ -260,35 +241,7 @@ public class BucketTests extends AbstractSerializingTestCase<Bucket> {
         assertTrue(bucket.isNormalizable());
     }
 
-    public void testPartitionAnomalyScore() {
-        List<PartitionScore> pScore = new ArrayList<>();
-        pScore.add(new PartitionScore("pf", "pv1", 11.0, 10.0, 0.1));
-        pScore.add(new PartitionScore("pf", "pv3", 51.0, 50.0, 0.1));
-        pScore.add(new PartitionScore("pf", "pv4", 61.0, 60.0, 0.1));
-        pScore.add(new PartitionScore("pf", "pv2", 41.0, 40.0, 0.1));
-
-        Bucket bucket = new Bucket("foo", new Date(123), 123);
-        bucket.setPartitionScores(pScore);
-
-        double initialAnomalyScore = bucket.partitionInitialAnomalyScore("pv1");
-        assertEquals(11.0, initialAnomalyScore, 0.001);
-        double anomalyScore = bucket.partitionAnomalyScore("pv1");
-        assertEquals(10.0, anomalyScore, 0.001);
-        initialAnomalyScore = bucket.partitionInitialAnomalyScore("pv2");
-        assertEquals(41.0, initialAnomalyScore, 0.001);
-        anomalyScore = bucket.partitionAnomalyScore("pv2");
-        assertEquals(40.0, anomalyScore, 0.001);
-        initialAnomalyScore = bucket.partitionInitialAnomalyScore("pv3");
-        assertEquals(51.0, initialAnomalyScore, 0.001);
-        anomalyScore = bucket.partitionAnomalyScore("pv3");
-        assertEquals(50.0, anomalyScore, 0.001);
-        initialAnomalyScore = bucket.partitionInitialAnomalyScore("pv4");
-        assertEquals(61.0, initialAnomalyScore, 0.001);
-        anomalyScore = bucket.partitionAnomalyScore("pv4");
-        assertEquals(60.0, anomalyScore, 0.001);
-    }
-
-    public void testId() {
+     public void testId() {
         Bucket bucket = new Bucket("foo", new Date(123), 60L);
         assertEquals("foo_bucket_123_60", bucket.getId());
     }
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/PartitionScoreTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/PartitionScoreTests.java
deleted file mode 100644
index 74c3934c532..00000000000
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/results/PartitionScoreTests.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.ml.job.results;
-
-import org.elasticsearch.common.io.stream.Writeable.Reader;
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.common.xcontent.json.JsonXContent;
-import org.elasticsearch.test.AbstractSerializingTestCase;
-import org.elasticsearch.xpack.core.ml.job.results.PartitionScore;
-
-import java.io.IOException;
-
-import static org.hamcrest.Matchers.containsString;
-
-public class PartitionScoreTests extends AbstractSerializingTestCase<PartitionScore> {
-
-    @Override
-    protected PartitionScore createTestInstance() {
-        return new PartitionScore(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20), randomDouble(), randomDouble(),
-                randomDouble());
-    }
-
-    @Override
-    protected Reader<PartitionScore> instanceReader() {
-        return PartitionScore::new;
-    }
-
-    @Override
-    protected PartitionScore doParseInstance(XContentParser parser) {
-        return PartitionScore.STRICT_PARSER.apply(parser, null);
-    }
-
-    public void testStrictParser() throws IOException {
-        String json = "{\"partition_field_name\":\"field_1\", \"partition_field_value\":\"x\", \"initial_record_score\": 3," +
-                " \"record_score\": 3, \"probability\": 0.001, \"foo\":\"bar\"}";
-        try (XContentParser parser = createParser(JsonXContent.jsonXContent, json)) {
-            IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
-                    () -> PartitionScore.STRICT_PARSER.apply(parser, null));
-
-            assertThat(e.getMessage(), containsString("unknown field [foo]"));
-        }
-    }
-
-    public void testLenientParser() throws IOException {
-        String json = "{\"partition_field_name\":\"field_1\", \"partition_field_value\":\"x\", \"initial_record_score\": 3," +
-                " \"record_score\": 3, \"probability\": 0.001, \"foo\":\"bar\"}";
-        try (XContentParser parser = createParser(JsonXContent.jsonXContent, json)) {
-            PartitionScore.LENIENT_PARSER.apply(parser, null);
-        }
-    }
-}
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemoverTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemoverTests.java
index 4195e93439d..9f056e91854 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemoverTests.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/job/retention/ExpiredModelSnapshotsRemoverTests.java
@@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.search.SearchAction;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.metadata.MetaData;
@@ -270,8 +271,8 @@ public class ExpiredModelSnapshotsRemoverTests extends ESTestCase {
             @Override
             public Void answer(InvocationOnMock invocationOnMock) {
                 capturedDeleteModelSnapshotRequests.add((DeleteModelSnapshotAction.Request) invocationOnMock.getArguments()[1]);
-                ActionListener<DeleteModelSnapshotAction.Response> listener =
-                        (ActionListener<DeleteModelSnapshotAction.Response>) invocationOnMock.getArguments()[2];
+                ActionListener<AcknowledgedResponse> listener =
+                        (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[2];
                 if (shouldDeleteSnapshotRequestsSucceed) {
                     listener.onResponse(null);
                 } else {
@@ -307,4 +308,4 @@ public class ExpiredModelSnapshotsRemoverTests extends ESTestCase {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/support/BaseMlIntegTestCase.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/support/BaseMlIntegTestCase.java
index 7a1ca6a00f4..3c07db3a9ab 100644
--- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/support/BaseMlIntegTestCase.java
+++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/support/BaseMlIntegTestCase.java
@@ -12,6 +12,7 @@ import org.elasticsearch.action.bulk.BulkRequestBuilder;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.support.WriteRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.analysis.common.CommonAnalysisPlugin;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
@@ -27,19 +28,17 @@ import org.elasticsearch.test.ESIntegTestCase;
 import org.elasticsearch.test.MockHttpTransport;
 import org.elasticsearch.test.discovery.TestZenDiscovery;
 import org.elasticsearch.xpack.core.XPackSettings;
-import org.elasticsearch.xpack.core.ml.action.GetDatafeedsAction;
-import org.elasticsearch.xpack.core.ml.action.GetJobsAction;
-import org.elasticsearch.xpack.core.ml.action.util.QueryPage;
-import org.elasticsearch.xpack.core.ml.client.MachineLearningClient;
-import org.elasticsearch.xpack.ml.LocalStateMachineLearning;
-import org.elasticsearch.xpack.ml.MachineLearning;
 import org.elasticsearch.xpack.core.ml.MachineLearningField;
 import org.elasticsearch.xpack.core.ml.action.CloseJobAction;
 import org.elasticsearch.xpack.core.ml.action.DeleteDatafeedAction;
 import org.elasticsearch.xpack.core.ml.action.DeleteJobAction;
+import org.elasticsearch.xpack.core.ml.action.GetDatafeedsAction;
 import org.elasticsearch.xpack.core.ml.action.GetDatafeedsStatsAction;
+import org.elasticsearch.xpack.core.ml.action.GetJobsAction;
 import org.elasticsearch.xpack.core.ml.action.GetJobsStatsAction;
 import org.elasticsearch.xpack.core.ml.action.StopDatafeedAction;
+import org.elasticsearch.xpack.core.ml.action.util.QueryPage;
+import org.elasticsearch.xpack.core.ml.client.MachineLearningClient;
 import org.elasticsearch.xpack.core.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.xpack.core.ml.datafeed.DatafeedState;
 import org.elasticsearch.xpack.core.ml.job.config.AnalysisConfig;
@@ -49,6 +48,8 @@ import org.elasticsearch.xpack.core.ml.job.config.Detector;
 import org.elasticsearch.xpack.core.ml.job.config.Job;
 import org.elasticsearch.xpack.core.ml.job.config.JobState;
 import org.elasticsearch.xpack.core.ml.job.process.autodetect.state.DataCounts;
+import org.elasticsearch.xpack.ml.LocalStateMachineLearning;
+import org.elasticsearch.xpack.ml.MachineLearning;
 import org.junit.After;
 import org.junit.Before;
 
@@ -306,7 +307,7 @@ public abstract class BaseMlIntegTestCase extends ESIntegTestCase {
                     throw new RuntimeException(e);
                 }
             });
-            DeleteDatafeedAction.Response deleteResponse =
+            AcknowledgedResponse deleteResponse =
                     client.execute(DeleteDatafeedAction.INSTANCE, new DeleteDatafeedAction.Request(datafeed.getId())).get();
             assertTrue(deleteResponse.isAcknowledged());
         }
@@ -344,7 +345,7 @@ public abstract class BaseMlIntegTestCase extends ESIntegTestCase {
                         client().execute(GetJobsStatsAction.INSTANCE, new GetJobsStatsAction.Request(job.getId())).actionGet();
                 assertEquals(JobState.CLOSED, statsResponse.getResponse().results().get(0).getState());
             });
-            DeleteJobAction.Response response =
+            AcknowledgedResponse response =
                     client.execute(DeleteJobAction.INSTANCE, new DeleteJobAction.Request(job.getId())).get();
             assertTrue(response.isAcknowledged());
         }
diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java
index d4375af4e55..6962d91c9be 100644
--- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java
+++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java
@@ -11,9 +11,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.apache.logging.log4j.util.Supplier;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
 import org.elasticsearch.action.ingest.PutPipelineRequest;
 import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
@@ -402,7 +400,7 @@ public class LocalExporter extends Exporter implements ClusterStateListener, Cle
     }
 
     // FIXME this should use the IndexTemplateMetaDataUpgrader
-    private void putTemplate(String template, String source, ActionListener<PutIndexTemplateResponse> listener) {
+    private void putTemplate(String template, String source, ActionListener<AcknowledgedResponse> listener) {
         logger.debug("installing template [{}]", template);
 
         PutIndexTemplateRequest request = new PutIndexTemplateRequest(template).source(source, XContentType.JSON);
@@ -547,9 +545,9 @@ public class LocalExporter extends Exporter implements ClusterStateListener, Cle
         logger.trace("deleting {} indices: [{}]", indices.size(), collectionToCommaDelimitedString(indices));
         final DeleteIndexRequest request = new DeleteIndexRequest(indices.toArray(new String[indices.size()]));
         executeAsyncWithOrigin(client.threadPool().getThreadContext(), MONITORING_ORIGIN, request,
-                new ActionListener<DeleteIndexResponse>() {
+                new ActionListener<AcknowledgedResponse>() {
                     @Override
-                    public void onResponse(DeleteIndexResponse response) {
+                    public void onResponse(AcknowledgedResponse response) {
                         if (response.isAcknowledged()) {
                             logger.debug("{} indices deleted", indices.size());
                         } else {
diff --git a/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportDeleteRollupJobAction.java b/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportDeleteRollupJobAction.java
index 03df531e737..97b4483b1ff 100644
--- a/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportDeleteRollupJobAction.java
+++ b/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportDeleteRollupJobAction.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.rollup.action;
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.block.ClusterBlockException;
@@ -28,7 +29,7 @@ import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 public class TransportDeleteRollupJobAction
-        extends TransportMasterNodeAction<DeleteRollupJobAction.Request, DeleteRollupJobAction.Response> {
+        extends TransportMasterNodeAction<DeleteRollupJobAction.Request, AcknowledgedResponse> {
 
     private final PersistentTasksService persistentTasksService;
 
@@ -47,13 +48,13 @@ public class TransportDeleteRollupJobAction
     }
 
     @Override
-    protected DeleteRollupJobAction.Response newResponse() {
-        return new DeleteRollupJobAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(DeleteRollupJobAction.Request request, ClusterState state,
-                                   ActionListener<DeleteRollupJobAction.Response> listener) throws Exception {
+                                   ActionListener<AcknowledgedResponse> listener) throws Exception {
 
         String jobId = request.getId();
         TimeValue timeout = new TimeValue(60, TimeUnit.SECONDS); // TODO make this a config option
@@ -70,7 +71,7 @@ public class TransportDeleteRollupJobAction
                             @Override
                             public void onResponse(PersistentTasksCustomMetaData.PersistentTask<RollupJob> task) {
                                 logger.debug("Task for Rollup job [" + jobId + "] successfully canceled.");
-                                listener.onResponse(new DeleteRollupJobAction.Response(true));
+                                listener.onResponse(new AcknowledgedResponse(true));
                             }
 
                             @Override
diff --git a/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportPutRollupJobAction.java b/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportPutRollupJobAction.java
index 889dfa3ac8e..9f20fba8e92 100644
--- a/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportPutRollupJobAction.java
+++ b/x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportPutRollupJobAction.java
@@ -21,6 +21,7 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
 import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse;
 import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterState;
@@ -53,7 +54,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
-public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRollupJobAction.Request, PutRollupJobAction.Response> {
+public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRollupJobAction.Request, AcknowledgedResponse> {
     private final XPackLicenseState licenseState;
     private final PersistentTasksService persistentTasksService;
     private final Client client;
@@ -76,13 +77,13 @@ public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRo
     }
 
     @Override
-    protected PutRollupJobAction.Response newResponse() {
-        return new PutRollupJobAction.Response();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(PutRollupJobAction.Request request, ClusterState clusterState,
-                                   ActionListener<PutRollupJobAction.Response> listener) {
+                                   ActionListener<AcknowledgedResponse> listener) {
 
         if (!licenseState.isRollupAllowed()) {
             listener.onFailure(LicenseUtils.newComplianceException(XPackField.ROLLUP));
@@ -123,7 +124,7 @@ public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRo
         return new RollupJob(config, filteredHeaders);
     }
 
-    static void createIndex(RollupJob job, ActionListener<PutRollupJobAction.Response> listener,
+    static void createIndex(RollupJob job, ActionListener<AcknowledgedResponse> listener,
                             PersistentTasksService persistentTasksService, Client client, Logger logger) {
 
         String jobMetadata = "\"" + job.getConfig().getId() + "\":" + job.getConfig().toJSONString();
@@ -148,7 +149,7 @@ public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRo
     }
 
     @SuppressWarnings("unchecked")
-    static void updateMapping(RollupJob job, ActionListener<PutRollupJobAction.Response> listener,
+    static void updateMapping(RollupJob job, ActionListener<AcknowledgedResponse> listener,
                               PersistentTasksService persistentTasksService, Client client, Logger logger) {
 
         final String indexName = job.getConfig().getRollupIndex();
@@ -210,7 +211,7 @@ public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRo
                 }));
     }
 
-    static void startPersistentTask(RollupJob job, ActionListener<PutRollupJobAction.Response> listener,
+    static void startPersistentTask(RollupJob job, ActionListener<AcknowledgedResponse> listener,
                                     PersistentTasksService persistentTasksService) {
 
         persistentTasksService.sendStartRequest(job.getConfig().getId(), RollupField.TASK_NAME, job,
@@ -226,13 +227,13 @@ public class TransportPutRollupJobAction extends TransportMasterNodeAction<PutRo
     }
 
 
-    private static void waitForRollupStarted(RollupJob job, ActionListener<PutRollupJobAction.Response> listener,
+    private static void waitForRollupStarted(RollupJob job, ActionListener<AcknowledgedResponse> listener,
                                              PersistentTasksService persistentTasksService) {
         persistentTasksService.waitForPersistentTaskCondition(job.getConfig().getId(), Objects::nonNull, job.getConfig().getTimeout(),
                 new PersistentTasksService.WaitForPersistentTaskListener<RollupJob>() {
                     @Override
                     public void onResponse(PersistentTasksCustomMetaData.PersistentTask<RollupJob> task) {
-                        listener.onResponse(new PutRollupJobAction.Response(true));
+                        listener.onResponse(new AcknowledgedResponse(true));
                     }
 
                     @Override
diff --git a/x-pack/plugin/rollup/src/test/java/org/elasticsearch/xpack/rollup/action/PutJobStateMachineTests.java b/x-pack/plugin/rollup/src/test/java/org/elasticsearch/xpack/rollup/action/PutJobStateMachineTests.java
index d9caad5147d..5599c50321c 100644
--- a/x-pack/plugin/rollup/src/test/java/org/elasticsearch/xpack/rollup/action/PutJobStateMachineTests.java
+++ b/x-pack/plugin/rollup/src/test/java/org/elasticsearch/xpack/rollup/action/PutJobStateMachineTests.java
@@ -17,17 +17,17 @@ import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.metadata.MappingMetaData;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
 import org.elasticsearch.persistent.PersistentTasksCustomMetaData;
 import org.elasticsearch.persistent.PersistentTasksService;
 import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.xpack.core.rollup.ConfigTestHelpers;
 import org.elasticsearch.xpack.core.rollup.RollupField;
-import org.elasticsearch.xpack.core.rollup.action.PutRollupJobAction;
 import org.elasticsearch.xpack.core.rollup.job.RollupJob;
 import org.elasticsearch.xpack.core.rollup.job.RollupJobConfig;
-import org.elasticsearch.xpack.core.rollup.ConfigTestHelpers;
 import org.elasticsearch.xpack.rollup.Rollup;
 import org.mockito.ArgumentCaptor;
 
@@ -52,7 +52,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testCreateIndexException() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random(), "foo"), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Could not create index for rollup job [foo]"));
@@ -78,7 +78,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testIndexAlreadyExists() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random()), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getCause().getMessage(), equalTo("Ending"));
@@ -110,7 +110,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testIndexMetaData() throws InterruptedException {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random()), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getCause().getMessage(), equalTo("Ending"));
@@ -153,7 +153,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testGetMappingFails() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random(), "foo"), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Could not update mappings for rollup job [foo]"));
@@ -177,7 +177,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testNoMetadataInMapping() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random()), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Expected to find _meta key in mapping of rollup index ["
@@ -210,7 +210,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testNoMappingVersion() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random()), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Could not determine version of existing rollup metadata for index ["
@@ -247,7 +247,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testJobAlreadyInMapping() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random(), "foo"), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Cannot create rollup job [foo] because job was previously created (existing metadata)."));
@@ -288,7 +288,7 @@ public class PutJobStateMachineTests extends ESTestCase {
         final RollupJobConfig config =
             ConfigTestHelpers.randomRollupJobConfig(random(), ESTestCase.randomAlphaOfLength(10), "foo", "rollup_index_foo");
         RollupJob job = new RollupJob(config, Collections.emptyMap());
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Ending"));
@@ -333,7 +333,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testTaskAlreadyExists() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random(), "foo"), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Cannot create job [foo] because it has already been created (task exists)"));
@@ -356,7 +356,7 @@ public class PutJobStateMachineTests extends ESTestCase {
     public void testStartTask() {
         RollupJob job = new RollupJob(ConfigTestHelpers.randomRollupJobConfig(random()), Collections.emptyMap());
 
-        ActionListener<PutRollupJobAction.Response> testListener = ActionListener.wrap(response -> {
+        ActionListener<AcknowledgedResponse> testListener = ActionListener.wrap(response -> {
             fail("Listener success should not have been triggered.");
         }, e -> {
             assertThat(e.getMessage(), equalTo("Ending"));
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PasswordHashingAlgorithmBootstrapCheck.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PasswordHashingAlgorithmBootstrapCheck.java
deleted file mode 100644
index c60c2ea18d0..00000000000
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PasswordHashingAlgorithmBootstrapCheck.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.security;
-
-import org.elasticsearch.bootstrap.BootstrapCheck;
-import org.elasticsearch.bootstrap.BootstrapContext;
-import org.elasticsearch.xpack.core.XPackSettings;
-
-import javax.crypto.SecretKeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.util.Locale;
-
-/**
- * Bootstrap check to ensure that one of the allowed password hashing algorithms is
- * selected and that it is available.
- */
-public class PasswordHashingAlgorithmBootstrapCheck implements BootstrapCheck {
-    @Override
-    public BootstrapCheckResult check(BootstrapContext context) {
-        final String selectedAlgorithm = XPackSettings.PASSWORD_HASHING_ALGORITHM.get(context.settings);
-        if (selectedAlgorithm.toLowerCase(Locale.ROOT).startsWith("pbkdf2")) {
-            try {
-                SecretKeyFactory.getInstance("PBKDF2withHMACSHA512");
-            } catch (NoSuchAlgorithmException e) {
-                final String errorMessage = String.format(Locale.ROOT,
-                    "Support for PBKDF2WithHMACSHA512 must be available in order to use any of the " +
-                        "PBKDF2 algorithms for the [%s] setting.", XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey());
-                return BootstrapCheckResult.failure(errorMessage);
-            }
-        }
-        return BootstrapCheckResult.success();
-    }
-
-    @Override
-    public boolean alwaysEnforce() {
-        return true;
-    }
-}
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
index 18bcfeb94a5..d31ffae13f2 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
@@ -300,7 +300,6 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
                 new TokenSSLBootstrapCheck(),
                 new PkiRealmBootstrapCheck(getSslService()),
                 new TLSLicenseBootstrapCheck(),
-                new PasswordHashingAlgorithmBootstrapCheck(),
                 new FIPS140SecureSettingsBootstrapCheck(settings, env),
                 new FIPS140JKSKeystoreBootstrapCheck(settings),
                 new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings)));
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportPutUserAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportPutUserAction.java
index ebc1612afca..a2715896da6 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportPutUserAction.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportPutUserAction.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.action.user;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.apache.logging.log4j.util.Supplier;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.HandledTransportAction;
 import org.elasticsearch.common.inject.Inject;
@@ -18,11 +19,15 @@ import org.elasticsearch.xpack.core.security.action.user.PutUserAction;
 import org.elasticsearch.xpack.core.security.action.user.PutUserRequest;
 import org.elasticsearch.xpack.core.security.action.user.PutUserResponse;
 import org.elasticsearch.xpack.core.security.authc.esnative.ClientReservedRealm;
+import org.elasticsearch.xpack.core.security.support.Validation;
 import org.elasticsearch.xpack.core.security.user.AnonymousUser;
 import org.elasticsearch.xpack.core.security.user.SystemUser;
+import org.elasticsearch.xpack.core.security.user.XPackSecurityUser;
 import org.elasticsearch.xpack.core.security.user.XPackUser;
 import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
 
+import static org.elasticsearch.action.ValidateActions.addValidationError;
+
 public class TransportPutUserAction extends HandledTransportAction<PutUserRequest, PutUserResponse> {
 
     private final NativeUsersStore usersStore;
@@ -36,37 +41,62 @@ public class TransportPutUserAction extends HandledTransportAction<PutUserReques
 
     @Override
     protected void doExecute(Task task, final PutUserRequest request, final ActionListener<PutUserResponse> listener) {
+        final ActionRequestValidationException validationException = validateRequest(request);
+        if (validationException != null) {
+            listener.onFailure(validationException);
+        } else {
+            usersStore.putUser(request, new ActionListener<Boolean>() {
+                @Override
+                public void onResponse(Boolean created) {
+                    if (created) {
+                        logger.info("added user [{}]", request.username());
+                    } else {
+                        logger.info("updated user [{}]", request.username());
+                    }
+                    listener.onResponse(new PutUserResponse(created));
+                }
+
+                @Override
+                public void onFailure(Exception e) {
+                    logger.error((Supplier<?>) () -> new ParameterizedMessage("failed to put user [{}]", request.username()), e);
+                    listener.onFailure(e);
+                }
+            });
+        }
+    }
+
+    private ActionRequestValidationException validateRequest(PutUserRequest request) {
+        ActionRequestValidationException validationException = null;
         final String username = request.username();
         if (ClientReservedRealm.isReserved(username, settings)) {
             if (AnonymousUser.isAnonymousUsername(username, settings)) {
-                listener.onFailure(new IllegalArgumentException("user [" + username + "] is anonymous and cannot be modified via the API"));
-                return;
+                validationException =
+                    addValidationError("user [" + username + "] is anonymous and cannot be modified via the API", validationException);
             } else {
-                listener.onFailure(new IllegalArgumentException("user [" + username + "] is reserved and only the " +
-                        "password can be changed"));
-                return;
+                validationException = addValidationError("user [" + username + "] is reserved and only the " +
+                    "password can be changed", validationException);
+            }
+        } else if (SystemUser.NAME.equals(username) || XPackUser.NAME.equals(username) || XPackSecurityUser.NAME.equals(username)) {
+            validationException = addValidationError("user [" + username + "] is internal", validationException);
+        } else {
+            Validation.Error usernameError = Validation.Users.validateUsername(username, true, settings);
+            if (usernameError != null) {
+                validationException = addValidationError(usernameError.toString(), validationException);
             }
-        } else if (SystemUser.NAME.equals(username) || XPackUser.NAME.equals(username)) {
-            listener.onFailure(new IllegalArgumentException("user [" + username + "] is internal"));
-            return;
         }
 
-        usersStore.putUser(request, new ActionListener<Boolean>() {
-            @Override
-            public void onResponse(Boolean created) {
-                if (created) {
-                    logger.info("added user [{}]", request.username());
-                } else {
-                    logger.info("updated user [{}]", request.username());
+        if (request.roles() != null) {
+            for (String role : request.roles()) {
+                Validation.Error roleNameError = Validation.Roles.validateRoleName(role, true);
+                if (roleNameError != null) {
+                    validationException = addValidationError(roleNameError.toString(), validationException);
                 }
-                listener.onResponse(new PutUserResponse(created));
             }
+        }
 
-            @Override
-            public void onFailure(Exception e) {
-                logger.error((Supplier<?>) () -> new ParameterizedMessage("failed to put user [{}]", request.username()), e);
-                listener.onFailure(e);
-            }
-        });
+        if (request.password() != null) {
+            validationException = addValidationError("password should never be passed to the transport action", validationException);
+        }
+        return validationException;
     }
 }
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java
index 45c55c633d9..d02b569a744 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java
@@ -17,9 +17,9 @@ import org.elasticsearch.action.admin.indices.alias.Alias;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
 import org.elasticsearch.action.support.ActiveShardCount;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterChangedEvent;
 import org.elasticsearch.cluster.ClusterState;
@@ -299,7 +299,7 @@ public class SecurityIndexManager extends AbstractComponent implements ClusterSt
                     .source(loadMappingAndSettingsSourceFromTemplate().v1(), XContentType.JSON)
                     .type("doc");
             executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
-                    ActionListener.<PutMappingResponse>wrap(putMappingResponse -> {
+                    ActionListener.<AcknowledgedResponse>wrap(putMappingResponse -> {
                         if (putMappingResponse.isAcknowledged()) {
                             andThen.run();
                         } else {
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/DateMathExpressionIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/DateMathExpressionIntegTests.java
index 5ec9f8fbe06..2238c12cfb4 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/DateMathExpressionIntegTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/DateMathExpressionIntegTests.java
@@ -7,12 +7,12 @@ package org.elasticsearch.integration;
 
 import org.elasticsearch.action.DocWriteResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
-import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
 import org.elasticsearch.action.get.GetResponse;
 import org.elasticsearch.action.get.MultiGetResponse;
 import org.elasticsearch.action.index.IndexResponse;
 import org.elasticsearch.action.search.MultiSearchResponse;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.update.UpdateResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.Requests;
@@ -111,7 +111,7 @@ public class DateMathExpressionIntegTests extends SecurityIntegTestCase {
         assertEquals(expectedIndexName, multiGetResponse.getResponses()[0].getResponse().getIndex());
 
 
-        DeleteIndexResponse deleteIndexResponse = client.admin().indices().prepareDelete(expression).get();
+        AcknowledgedResponse deleteIndexResponse = client.admin().indices().prepareDelete(expression).get();
         assertThat(deleteIndexResponse.isAcknowledged(), is(true));
     }
 
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java
index f3fea81e201..24ef13c0b07 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java
@@ -8,7 +8,7 @@ package org.elasticsearch.integration;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
 import org.elasticsearch.common.settings.SecureString;
@@ -87,7 +87,7 @@ public class PermissionPrecedenceTests extends SecurityIntegTestCase {
 
         // first lets try with "admin"... all should work
 
-        PutIndexTemplateResponse putResponse = client
+        AcknowledgedResponse putResponse = client
             .filterWithHeader(Collections.singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER,
                     basicAuthHeaderValue(transportClientUsername(), transportClientPassword())))
             .admin().indices().preparePutTemplate("template1")
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PasswordHashingAlgorithmBootstrapCheckTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PasswordHashingAlgorithmBootstrapCheckTests.java
deleted file mode 100644
index 8ca5c6c7216..00000000000
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PasswordHashingAlgorithmBootstrapCheckTests.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.security;
-
-import org.elasticsearch.bootstrap.BootstrapContext;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.xpack.core.XPackSettings;
-
-import javax.crypto.SecretKeyFactory;
-import java.security.NoSuchAlgorithmException;
-
-public class PasswordHashingAlgorithmBootstrapCheckTests extends ESTestCase {
-
-    public void testPasswordHashingAlgorithmBootstrapCheck() {
-        Settings settings = Settings.EMPTY;
-        assertFalse(new PasswordHashingAlgorithmBootstrapCheck().check(new BootstrapContext(settings, null)).isFailure());
-        // The following two will always pass because for now we only test in environments where PBKDF2WithHMACSHA512 is supported
-        assertTrue(isSecretkeyFactoryAlgoAvailable("PBKDF2WithHMACSHA512"));
-        settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "PBKDF2_10000").build();
-        assertFalse(new PasswordHashingAlgorithmBootstrapCheck().check(new BootstrapContext(settings, null)).isFailure());
-
-        settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "PBKDF2").build();
-        assertFalse(new PasswordHashingAlgorithmBootstrapCheck().check(new BootstrapContext(settings, null)).isFailure());
-
-        settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "BCRYPT").build();
-        assertFalse(new PasswordHashingAlgorithmBootstrapCheck().check(new BootstrapContext(settings, null)).isFailure());
-
-        settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "BCRYPT11").build();
-        assertFalse(new PasswordHashingAlgorithmBootstrapCheck().check(new BootstrapContext(settings, null)).isFailure());
-    }
-
-    private boolean isSecretkeyFactoryAlgoAvailable(String algorithmId) {
-        try {
-            SecretKeyFactory.getInstance(algorithmId);
-            return true;
-        } catch (NoSuchAlgorithmException e) {
-            return false;
-        }
-    }
-}
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java
index 7c254723868..2d891afea8c 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/TemplateUpgraderTests.java
@@ -6,7 +6,7 @@
 package org.elasticsearch.xpack.security;
 
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterChangedEvent;
 import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
@@ -48,7 +48,7 @@ public class TemplateUpgraderTests extends SecurityIntegTestCase {
             return map;
         };
 
-        PutIndexTemplateResponse putIndexTemplateResponse = client().admin().indices().preparePutTemplate("removed-template")
+        AcknowledgedResponse putIndexTemplateResponse = client().admin().indices().preparePutTemplate("removed-template")
                 .setOrder(1)
                 .setPatterns(Collections.singletonList(randomAlphaOfLength(10)))
                 .get();
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/PutUserRequestTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/PutUserRequestTests.java
index af3a89c77b6..952448db486 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/PutUserRequestTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/PutUserRequestTests.java
@@ -39,16 +39,6 @@ public class PutUserRequestTests extends ESTestCase {
         assertThat(validation.validationErrors().size(), is(1));
     }
 
-    public void testValidateRejectsUserNameThatHasInvalidCharacters() throws Exception {
-        final PutUserRequest request = new PutUserRequest();
-        request.username("fóóbár");
-        request.roles("bar");
-        final ActionRequestValidationException validation = request.validate();
-        assertThat(validation, is(notNullValue()));
-        assertThat(validation.validationErrors(), contains(containsString("must be")));
-        assertThat(validation.validationErrors().size(), is(1));
-    }
-
     public void testValidateRejectsMetaDataWithLeadingUnderscore() throws Exception {
         final PutUserRequest request = new PutUserRequest();
         request.username("foo");
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportPutUserActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportPutUserActionTests.java
index b7eeb78fad3..36ba3f46b5e 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportPutUserActionTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportPutUserActionTests.java
@@ -7,6 +7,7 @@ package org.elasticsearch.xpack.security.action.user;
 
 import org.elasticsearch.ElasticsearchSecurityException;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.common.ValidationException;
@@ -37,6 +38,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.atomic.AtomicReference;
 
+import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.instanceOf;
 import static org.hamcrest.Matchers.is;
@@ -194,12 +196,32 @@ public class TransportPutUserActionTests extends ESTestCase {
             }
         });
 
+        assertThat(throwableRef.get(), is(nullValue()));
         assertThat(responseRef.get(), is(notNullValue()));
         assertThat(responseRef.get().created(), is(created));
-        assertThat(throwableRef.get(), is(nullValue()));
         verify(usersStore, times(1)).putUser(eq(request), any(ActionListener.class));
     }
 
+    public void testInvalidUser() {
+        NativeUsersStore usersStore = mock(NativeUsersStore.class);
+        TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null,
+            TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
+        TransportPutUserAction action = new TransportPutUserAction(Settings.EMPTY, mock(ActionFilters.class),
+            usersStore, transportService);
+
+        final PutUserRequest request = new PutUserRequest();
+        request.username("fóóbár");
+        request.roles("bar");
+        ActionRequestValidationException validation = request.validate();
+        assertNull(validation);
+
+        PlainActionFuture<PutUserResponse> responsePlainActionFuture = new PlainActionFuture<>();
+        action.doExecute(mock(Task.class), request, responsePlainActionFuture);
+        validation = expectThrows(ActionRequestValidationException.class, responsePlainActionFuture::actionGet);
+        assertThat(validation.validationErrors(), contains(containsString("must be")));
+        assertThat(validation.validationErrors().size(), is(1));
+    }
+
     public void testException() {
         final Exception e = randomFrom(new ElasticsearchSecurityException(""), new IllegalStateException(), new ValidationException());
         final User user = new User("joe");
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java
index 7f9e25e77e6..6ebf6dca2cf 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java
@@ -13,7 +13,6 @@ import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.PlainActionFuture;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.ValidationException;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.collect.MapBuilder;
 import org.elasticsearch.common.settings.SecureString;
@@ -492,14 +491,14 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
             client.preparePutUser("joe", randomAlphaOfLengthBetween(0, 5).toCharArray(), hasher,
                 "admin_role").get();
             fail("cannot create a user without a password < 6 characters");
-        } catch (ValidationException v) {
+        } catch (IllegalArgumentException v) {
             assertThat(v.getMessage().contains("password"), is(true));
         }
     }
 
     public void testCannotCreateUserWithInvalidCharactersInName() throws Exception {
         SecurityClient client = securityClient();
-        ValidationException v = expectThrows(ValidationException.class,
+        IllegalArgumentException v = expectThrows(IllegalArgumentException.class,
             () -> client.preparePutUser("fóóbár", "my-am@zing-password".toCharArray(), hasher,
                 "admin_role").get()
         );
@@ -533,7 +532,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
         IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
                 () -> securityClient().preparePutUser(username, randomBoolean() ? SecuritySettingsSourceField.TEST_PASSWORD.toCharArray()
                     : null, hasher, "admin").get());
-        assertThat(exception.getMessage(), containsString("Username [" + username + "] is reserved"));
+        assertThat(exception.getMessage(), containsString("user [" + username + "] is reserved"));
 
         exception = expectThrows(IllegalArgumentException.class,
                 () -> securityClient().prepareDeleteUser(username).get());
@@ -551,7 +550,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
         exception = expectThrows(IllegalArgumentException.class,
             () -> securityClient().preparePutUser(AnonymousUser.DEFAULT_ANONYMOUS_USERNAME, "foobar".toCharArray(),
                 hasher).get());
-        assertThat(exception.getMessage(), containsString("Username [" + AnonymousUser.DEFAULT_ANONYMOUS_USERNAME + "] is reserved"));
+        assertThat(exception.getMessage(), containsString("user [" + AnonymousUser.DEFAULT_ANONYMOUS_USERNAME + "] is anonymous"));
 
         exception = expectThrows(IllegalArgumentException.class,
             () -> securityClient().preparePutUser(SystemUser.NAME, "foobar".toCharArray(), hasher).get());
diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java
index a03f30abc33..04e0afcf882 100644
--- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java
+++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java
@@ -83,7 +83,7 @@ public class ReservedRealmTests extends ESTestCase {
         IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new ReservedRealm(mock(Environment.class),
             invalidSettings, usersStore, new AnonymousUser(Settings.EMPTY), securityIndex, threadPool));
         assertThat(exception.getMessage(), containsString(invalidAlgoId));
-        assertThat(exception.getMessage(), containsString("Only pbkdf2 or bcrypt family algorithms can be used for password hashing"));
+        assertThat(exception.getMessage(), containsString("Invalid algorithm"));
     }
 
     public void testReservedUserEmptyPasswordAuthenticationFails() throws Throwable {
diff --git a/x-pack/plugin/upgrade/src/main/java/org/elasticsearch/xpack/upgrade/InternalIndexReindexer.java b/x-pack/plugin/upgrade/src/main/java/org/elasticsearch/xpack/upgrade/InternalIndexReindexer.java
index 7e1e31919b1..82208f1f5ce 100644
--- a/x-pack/plugin/upgrade/src/main/java/org/elasticsearch/xpack/upgrade/InternalIndexReindexer.java
+++ b/x-pack/plugin/upgrade/src/main/java/org/elasticsearch/xpack/upgrade/InternalIndexReindexer.java
@@ -6,9 +6,9 @@
 package org.elasticsearch.xpack.upgrade;
 
 import org.elasticsearch.action.ActionListener;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
 import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.ParentTaskAssigningClient;
 import org.elasticsearch.cluster.ClusterState;
@@ -109,7 +109,7 @@ public class InternalIndexReindexer<T> {
     }
 
     private void removeReadOnlyBlock(ParentTaskAssigningClient parentAwareClient, String index,
-                                     ActionListener<UpdateSettingsResponse> listener) {
+                                     ActionListener<AcknowledgedResponse> listener) {
         Settings settings = Settings.builder().put(IndexMetaData.INDEX_READ_ONLY_SETTING.getKey(), false).build();
         parentAwareClient.admin().indices().prepareUpdateSettings(index).setSettings(settings).execute(listener);
     }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java
index 78d1d37287f..96237b6e3de 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/Watcher.java
@@ -92,12 +92,7 @@ import org.elasticsearch.xpack.watcher.actions.slack.SlackActionFactory;
 import org.elasticsearch.xpack.watcher.actions.webhook.WebhookAction;
 import org.elasticsearch.xpack.watcher.actions.webhook.WebhookActionFactory;
 import org.elasticsearch.xpack.watcher.common.http.HttpClient;
-import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.HttpSettings;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthFactory;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.condition.ArrayCompareCondition;
 import org.elasticsearch.xpack.watcher.condition.CompareCondition;
@@ -264,12 +259,7 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
         new WatcherIndexTemplateRegistry(settings, clusterService, threadPool, client);
 
         // http client
-        Map<String, HttpAuthFactory> httpAuthFactories = new HashMap<>();
-        httpAuthFactories.put(BasicAuth.TYPE, new BasicAuthFactory(cryptoService));
-        // TODO: add more auth types, or remove this indirection
-        HttpAuthRegistry httpAuthRegistry = new HttpAuthRegistry(httpAuthFactories);
-        HttpRequestTemplate.Parser httpTemplateParser = new HttpRequestTemplate.Parser(httpAuthRegistry);
-        httpClient = new HttpClient(settings, httpAuthRegistry, getSslService());
+        httpClient = new HttpClient(settings, getSslService(), cryptoService);
 
         // notification
         EmailService emailService = new EmailService(settings, cryptoService, clusterService.getClusterSettings());
@@ -286,11 +276,9 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
 
         TextTemplateEngine templateEngine = new TextTemplateEngine(settings, scriptService);
         Map<String, EmailAttachmentParser> emailAttachmentParsers = new HashMap<>();
-        emailAttachmentParsers.put(HttpEmailAttachementParser.TYPE, new HttpEmailAttachementParser(httpClient, httpTemplateParser,
-                templateEngine));
+        emailAttachmentParsers.put(HttpEmailAttachementParser.TYPE, new HttpEmailAttachementParser(httpClient, templateEngine));
         emailAttachmentParsers.put(DataAttachmentParser.TYPE, new DataAttachmentParser());
-        emailAttachmentParsers.put(ReportingAttachmentParser.TYPE, new ReportingAttachmentParser(settings, httpClient, templateEngine,
-                httpAuthRegistry));
+        emailAttachmentParsers.put(ReportingAttachmentParser.TYPE, new ReportingAttachmentParser(settings, httpClient, templateEngine));
         EmailAttachmentsParser emailAttachmentsParser = new EmailAttachmentsParser(emailAttachmentParsers);
 
         // conditions
@@ -310,7 +298,7 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
         // actions
         final Map<String, ActionFactory> actionFactoryMap = new HashMap<>();
         actionFactoryMap.put(EmailAction.TYPE, new EmailActionFactory(settings, emailService, templateEngine, emailAttachmentsParser));
-        actionFactoryMap.put(WebhookAction.TYPE, new WebhookActionFactory(settings, httpClient, httpTemplateParser, templateEngine));
+        actionFactoryMap.put(WebhookAction.TYPE, new WebhookActionFactory(settings, httpClient, templateEngine));
         actionFactoryMap.put(IndexAction.TYPE, new IndexActionFactory(settings, client));
         actionFactoryMap.put(LoggingAction.TYPE, new LoggingActionFactory(settings, templateEngine));
         actionFactoryMap.put(HipChatAction.TYPE, new HipChatActionFactory(settings, templateEngine, hipChatService));
@@ -324,7 +312,7 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
         final Map<String, InputFactory> inputFactories = new HashMap<>();
         inputFactories.put(SearchInput.TYPE, new SearchInputFactory(settings, client, xContentRegistry, scriptService));
         inputFactories.put(SimpleInput.TYPE, new SimpleInputFactory(settings));
-        inputFactories.put(HttpInput.TYPE, new HttpInputFactory(settings, httpClient, templateEngine, httpTemplateParser));
+        inputFactories.put(HttpInput.TYPE, new HttpInputFactory(settings, httpClient, templateEngine));
         inputFactories.put(NoneInput.TYPE, new NoneInputFactory(settings));
         inputFactories.put(TransformInput.TYPE, new TransformInputFactory(settings, transformRegistry));
         final InputRegistry inputRegistry = new InputRegistry(settings, inputFactories);
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/pagerduty/ExecutablePagerDutyAction.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/pagerduty/ExecutablePagerDutyAction.java
index 224e72e1a3d..59381dc3336 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/pagerduty/ExecutablePagerDutyAction.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/pagerduty/ExecutablePagerDutyAction.java
@@ -47,7 +47,7 @@ public class ExecutablePagerDutyAction extends ExecutableAction<PagerDutyAction>
             return new PagerDutyAction.Result.Simulated(event);
         }
 
-        SentEvent sentEvent = account.send(event, payload);
+        SentEvent sentEvent = account.send(event, payload, ctx.id().watchId());
         return new PagerDutyAction.Result.Executed(account.getName(), sentEvent);
     }
 
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookAction.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookAction.java
index 8d20d91f4dc..febbae99d46 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookAction.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookAction.java
@@ -55,10 +55,9 @@ public class WebhookAction implements Action {
         return requestTemplate.toXContent(builder, params);
     }
 
-    public static WebhookAction parse(String watchId, String actionId, XContentParser parser,
-                                      HttpRequestTemplate.Parser requestParser) throws IOException {
+    public static WebhookAction parse(String watchId, String actionId, XContentParser parser) throws IOException {
         try {
-            HttpRequestTemplate request = requestParser.parse(parser);
+            HttpRequestTemplate request = HttpRequestTemplate.Parser.parse(parser);
             return new WebhookAction(request);
         } catch (ElasticsearchParseException pe) {
             throw new ElasticsearchParseException("could not parse [{}] action [{}/{}]. failed parsing http request template", pe, TYPE,
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionFactory.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionFactory.java
index 6de16006432..5a7a1069932 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionFactory.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionFactory.java
@@ -10,7 +10,6 @@ import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.xpack.core.watcher.actions.ActionFactory;
 import org.elasticsearch.xpack.watcher.common.http.HttpClient;
-import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 
 import java.io.IOException;
@@ -18,21 +17,18 @@ import java.io.IOException;
 public class WebhookActionFactory extends ActionFactory {
 
     private final HttpClient httpClient;
-    private final HttpRequestTemplate.Parser requestTemplateParser;
     private final TextTemplateEngine templateEngine;
 
-    public WebhookActionFactory(Settings settings, HttpClient httpClient, HttpRequestTemplate.Parser requestTemplateParser,
-                                TextTemplateEngine templateEngine) {
+    public WebhookActionFactory(Settings settings, HttpClient httpClient, TextTemplateEngine templateEngine) {
 
         super(Loggers.getLogger(ExecutableWebhookAction.class, settings));
         this.httpClient = httpClient;
-        this.requestTemplateParser = requestTemplateParser;
         this.templateEngine = templateEngine;
     }
 
     @Override
     public ExecutableWebhookAction parseExecutable(String watchId, String actionId, XContentParser parser) throws IOException {
-        return new ExecutableWebhookAction(WebhookAction.parse(watchId, actionId, parser, requestTemplateParser),
+        return new ExecutableWebhookAction(WebhookAction.parse(watchId, actionId, parser),
                 actionLogger, httpClient, templateEngine);
 
     }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/BasicAuth.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/BasicAuth.java
similarity index 84%
rename from x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/BasicAuth.java
rename to x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/BasicAuth.java
index 2d316735efd..0b40df4262f 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/BasicAuth.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/BasicAuth.java
@@ -3,22 +3,22 @@
  * or more contributor license agreements. Licensed under the Elastic License;
  * you may not use this file except in compliance with the Elastic License.
  */
-package org.elasticsearch.xpack.watcher.common.http.auth.basic;
+package org.elasticsearch.xpack.watcher.common.http;
 
 import org.elasticsearch.ElasticsearchParseException;
 import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ToXContentObject;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.xpack.core.watcher.common.secret.Secret;
 import org.elasticsearch.xpack.core.watcher.crypto.CryptoService;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherXContentParser;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
 
 import java.io.IOException;
 import java.util.Objects;
 
-public class BasicAuth implements HttpAuth {
+public class BasicAuth implements ToXContentObject {
 
     public static final String TYPE = "basic";
 
@@ -34,11 +34,6 @@ public class BasicAuth implements HttpAuth {
         this.password = password;
     }
 
-    @Override
-    public String type() {
-        return TYPE;
-    }
-
     public String getUsername() {
         return username;
     }
@@ -74,7 +69,7 @@ public class BasicAuth implements HttpAuth {
         return builder.endObject();
     }
 
-    public static BasicAuth parse(XContentParser parser) throws IOException {
+    public static BasicAuth parseInner(XContentParser parser) throws IOException {
         String username = null;
         Secret password = null;
 
@@ -103,6 +98,20 @@ public class BasicAuth implements HttpAuth {
         return new BasicAuth(username, password);
     }
 
+    public static BasicAuth parse(XContentParser parser) throws IOException {
+        String type = null;
+        XContentParser.Token token;
+        BasicAuth auth = null;
+        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+            if (token == XContentParser.Token.FIELD_NAME) {
+                type = parser.currentName();
+            } else if (token == XContentParser.Token.START_OBJECT && type != null) {
+                auth = BasicAuth.parseInner(parser);
+            }
+        }
+        return auth;
+    }
+
     interface Field {
         ParseField USERNAME = new ParseField("username");
         ParseField PASSWORD = new ParseField("password");
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java
index 97d7779346f..547e3b7197f 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java
@@ -10,6 +10,8 @@ import org.apache.http.HttpHeaders;
 import org.apache.http.HttpHost;
 import org.apache.http.NameValuePair;
 import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.AuthCache;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.config.RequestConfig;
@@ -42,8 +44,7 @@ import org.elasticsearch.core.internal.io.Streams;
 import org.elasticsearch.xpack.core.common.socket.SocketAccess;
 import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
 import org.elasticsearch.xpack.core.ssl.SSLService;
-import org.elasticsearch.xpack.watcher.common.http.auth.ApplicableHttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
+import org.elasticsearch.xpack.core.watcher.crypto.CryptoService;
 
 import javax.net.ssl.HostnameVerifier;
 import java.io.ByteArrayOutputStream;
@@ -66,20 +67,20 @@ public class HttpClient extends AbstractComponent implements Closeable {
     // you are querying a remote Elasticsearch cluster
     private static final int MAX_CONNECTIONS = 500;
 
-    private final HttpAuthRegistry httpAuthRegistry;
     private final CloseableHttpClient client;
     private final HttpProxy settingsProxy;
     private final TimeValue defaultConnectionTimeout;
     private final TimeValue defaultReadTimeout;
     private final ByteSizeValue maxResponseSize;
+    private final CryptoService cryptoService;
 
-    public HttpClient(Settings settings, HttpAuthRegistry httpAuthRegistry, SSLService sslService) {
+    public HttpClient(Settings settings, SSLService sslService, CryptoService cryptoService) {
         super(settings);
-        this.httpAuthRegistry = httpAuthRegistry;
         this.defaultConnectionTimeout = HttpSettings.CONNECTION_TIMEOUT.get(settings);
         this.defaultReadTimeout = HttpSettings.READ_TIMEOUT.get(settings);
         this.maxResponseSize = HttpSettings.MAX_HTTP_RESPONSE_SIZE.get(settings);
         this.settingsProxy = getProxyFromSettings();
+        this.cryptoService = cryptoService;
 
         HttpClientBuilder clientBuilder = HttpClientBuilder.create();
 
@@ -139,9 +140,10 @@ public class HttpClient extends AbstractComponent implements Closeable {
         HttpClientContext localContext = HttpClientContext.create();
         // auth
         if (request.auth() != null) {
-            ApplicableHttpAuth applicableAuth = httpAuthRegistry.createApplicable(request.auth);
             CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-            applicableAuth.apply(credentialsProvider, new AuthScope(request.host, request.port));
+            Credentials credentials = new UsernamePasswordCredentials(request.auth().username,
+                new String(request.auth().password.text(cryptoService)));
+            credentialsProvider.setCredentials(new AuthScope(request.host, request.port), credentials);
             localContext.setCredentialsProvider(credentialsProvider);
 
             // preemptive auth, no need to wait for a 401 first
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequest.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequest.java
index 3754cc440eb..6bcfc9e5e7d 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequest.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequest.java
@@ -21,8 +21,6 @@ import org.elasticsearch.xpack.core.watcher.support.WatcherDateTimeUtils;
 import org.elasticsearch.xpack.core.watcher.support.WatcherUtils;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherXContentParser;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -50,7 +48,7 @@ public class HttpRequest implements ToXContentObject {
     @Nullable final String path;
     final Map<String, String> params;
     final Map<String, String> headers;
-    @Nullable final HttpAuth auth;
+    @Nullable final BasicAuth auth;
     @Nullable final String body;
     @Nullable final TimeValue connectionTimeout;
     @Nullable final TimeValue readTimeout;
@@ -58,7 +56,7 @@ public class HttpRequest implements ToXContentObject {
 
     public HttpRequest(String host, int port, @Nullable Scheme scheme, @Nullable HttpMethod method, @Nullable String path,
                        @Nullable Map<String, String> params, @Nullable Map<String, String> headers,
-                       @Nullable HttpAuth auth, @Nullable String body, @Nullable TimeValue connectionTimeout,
+                       @Nullable BasicAuth auth, @Nullable String body, @Nullable TimeValue connectionTimeout,
                        @Nullable TimeValue readTimeout, @Nullable HttpProxy proxy) {
         this.host = host;
         this.port = port;
@@ -102,7 +100,7 @@ public class HttpRequest implements ToXContentObject {
         return headers;
     }
 
-    public HttpAuth auth() {
+    public BasicAuth auth() {
         return auth;
     }
 
@@ -166,7 +164,7 @@ public class HttpRequest implements ToXContentObject {
         }
         if (auth != null) {
             builder.startObject(Field.AUTH.getPreferredName())
-                        .field(auth.type(), auth, toXContentParams)
+                        .field(BasicAuth.TYPE, auth, toXContentParams)
                     .endObject();
         }
         if (body != null) {
@@ -234,7 +232,7 @@ public class HttpRequest implements ToXContentObject {
             sb.append("], ");
         }
         if (auth != null) {
-            sb.append("auth=[").append(auth.type()).append("], ");
+            sb.append("auth=[").append(BasicAuth.TYPE).append("], ");
         }
         sb.append("connection_timeout=[").append(connectionTimeout).append("], ");
         sb.append("read_timeout=[").append(readTimeout).append("], ");
@@ -254,14 +252,7 @@ public class HttpRequest implements ToXContentObject {
     }
 
     public static class Parser {
-
-        private final HttpAuthRegistry httpAuthRegistry;
-
-        public Parser(HttpAuthRegistry httpAuthRegistry) {
-            this.httpAuthRegistry = httpAuthRegistry;
-        }
-
-        public HttpRequest parse(XContentParser parser) throws IOException {
+        public static HttpRequest parse(XContentParser parser) throws IOException {
             Builder builder = new Builder();
             XContentParser.Token token;
             String currentFieldName = null;
@@ -275,7 +266,7 @@ public class HttpRequest implements ToXContentObject {
                         throw new ElasticsearchParseException("could not parse http request. could not parse [{}] field", currentFieldName);
                     }
                 } else if (Field.AUTH.match(currentFieldName, parser.getDeprecationHandler())) {
-                    builder.auth(httpAuthRegistry.parse(parser));
+                    builder.auth(BasicAuth.parse(parser));
                 } else if (HttpRequest.Field.CONNECTION_TIMEOUT.match(currentFieldName, parser.getDeprecationHandler())) {
                     builder.connectionTimeout(TimeValue.timeValueMillis(parser.longValue()));
                 } else if (HttpRequest.Field.CONNECTION_TIMEOUT_HUMAN.match(currentFieldName, parser.getDeprecationHandler())) {
@@ -302,7 +293,7 @@ public class HttpRequest implements ToXContentObject {
                         builder.setHeaders((Map) WatcherUtils.flattenModel(parser.map()));
                     } else if (Field.PARAMS.match(currentFieldName, parser.getDeprecationHandler())) {
                         builder.setParams((Map) WatcherUtils.flattenModel(parser.map()));
-                    }  else if (Field.BODY.match(currentFieldName, parser.getDeprecationHandler())) {
+                    } else if (Field.BODY.match(currentFieldName, parser.getDeprecationHandler())) {
                         builder.body(parser.text());
                     } else {
                         throw new ElasticsearchParseException("could not parse http request. unexpected object field [{}]",
@@ -360,7 +351,7 @@ public class HttpRequest implements ToXContentObject {
         private String path;
         private Map<String, String> params = new HashMap<>();
         private Map<String, String> headers = new HashMap<>();
-        private HttpAuth auth;
+        private BasicAuth auth;
         private String body;
         private TimeValue connectionTimeout;
         private TimeValue readTimeout;
@@ -421,7 +412,7 @@ public class HttpRequest implements ToXContentObject {
             return this;
         }
 
-        public Builder auth(HttpAuth auth) {
+        public Builder auth(BasicAuth auth) {
             this.auth = auth;
             return this;
         }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplate.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplate.java
index e511b30ef59..8ca87395248 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplate.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplate.java
@@ -18,8 +18,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.rest.RestUtils;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.xpack.core.watcher.support.WatcherDateTimeUtils;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 
@@ -42,14 +40,14 @@ public class HttpRequestTemplate implements ToXContentObject {
     private final TextTemplate path;
     private final Map<String, TextTemplate> params;
     private final Map<String, TextTemplate> headers;
-    private final HttpAuth auth;
+    private final BasicAuth auth;
     private final TextTemplate body;
     @Nullable private final TimeValue connectionTimeout;
     @Nullable private final TimeValue readTimeout;
     @Nullable private final HttpProxy proxy;
 
     public HttpRequestTemplate(String host, int port, @Nullable Scheme scheme, @Nullable HttpMethod method, @Nullable TextTemplate path,
-                               Map<String, TextTemplate> params, Map<String, TextTemplate> headers, HttpAuth auth,
+                               Map<String, TextTemplate> params, Map<String, TextTemplate> headers, BasicAuth auth,
                                TextTemplate body, @Nullable TimeValue connectionTimeout, @Nullable TimeValue readTimeout,
                                @Nullable HttpProxy proxy) {
         this.host = host;
@@ -94,7 +92,7 @@ public class HttpRequestTemplate implements ToXContentObject {
         return headers;
     }
 
-    public HttpAuth auth() {
+    public BasicAuth auth() {
         return auth;
     }
 
@@ -185,7 +183,7 @@ public class HttpRequestTemplate implements ToXContentObject {
         }
         if (auth != null) {
             builder.startObject(HttpRequest.Field.AUTH.getPreferredName())
-                    .field(auth.type(), auth, params)
+                    .field(BasicAuth.TYPE, auth, params)
                     .endObject();
         }
         if (body != null) {
@@ -261,14 +259,7 @@ public class HttpRequestTemplate implements ToXContentObject {
     }
 
     public static class Parser {
-
-        private final HttpAuthRegistry httpAuthRegistry;
-
-        public Parser(HttpAuthRegistry httpAuthRegistry) {
-            this.httpAuthRegistry = httpAuthRegistry;
-        }
-
-        public HttpRequestTemplate parse(XContentParser parser) throws IOException {
+        public static HttpRequestTemplate parse(XContentParser parser) throws IOException {
             assert parser.currentToken() == XContentParser.Token.START_OBJECT;
 
             Builder builder = new Builder();
@@ -312,8 +303,8 @@ public class HttpRequestTemplate implements ToXContentObject {
                     }
                 } else if (token == XContentParser.Token.START_OBJECT) {
                     if (HttpRequest.Field.AUTH.match(currentFieldName, parser.getDeprecationHandler())) {
-                        builder.auth(httpAuthRegistry.parse(parser));
-                    }  else {
+                        builder.auth(BasicAuth.parse(parser));
+                    } else {
                         throw new ElasticsearchParseException("could not parse http request template. unexpected object field [{}]",
                                 currentFieldName);
                     }
@@ -387,7 +378,7 @@ public class HttpRequestTemplate implements ToXContentObject {
         private TextTemplate path;
         private final Map<String, TextTemplate> params = new HashMap<>();
         private final Map<String, TextTemplate> headers = new HashMap<>();
-        private HttpAuth auth;
+        private BasicAuth auth;
         private TextTemplate body;
         private TimeValue connectionTimeout;
         private TimeValue readTimeout;
@@ -444,7 +435,7 @@ public class HttpRequestTemplate implements ToXContentObject {
             return this;
         }
 
-        public Builder auth(HttpAuth auth) {
+        public Builder auth(BasicAuth auth) {
             this.auth = auth;
             return this;
         }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/ApplicableHttpAuth.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/ApplicableHttpAuth.java
deleted file mode 100644
index cecc7bfda79..00000000000
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/ApplicableHttpAuth.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.watcher.common.http.auth;
-
-import org.apache.http.auth.AuthScope;
-import org.apache.http.client.CredentialsProvider;
-import org.elasticsearch.common.xcontent.ToXContentObject;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-
-import java.io.IOException;
-import java.net.HttpURLConnection;
-
-public abstract class ApplicableHttpAuth<Auth extends HttpAuth> implements ToXContentObject {
-
-    protected final Auth auth;
-
-    public ApplicableHttpAuth(Auth auth) {
-        this.auth = auth;
-    }
-
-    public final String type() {
-        return auth.type();
-    }
-
-    public abstract void apply(HttpURLConnection connection);
-
-    public abstract void apply(CredentialsProvider credsProvider, AuthScope authScope);
-
-    @Override
-    public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
-        return auth.toXContent(builder, params);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ApplicableHttpAuth<?> that = (ApplicableHttpAuth<?>) o;
-
-        return auth.equals(that.auth);
-    }
-
-    @Override
-    public int hashCode() {
-        return auth.hashCode();
-    }
-}
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuth.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuth.java
deleted file mode 100644
index 0909a33ab73..00000000000
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuth.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.watcher.common.http.auth;
-
-import org.elasticsearch.common.xcontent.ToXContentObject;
-
-public interface HttpAuth extends ToXContentObject {
-
-    String type();
-
-}
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuthFactory.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuthFactory.java
deleted file mode 100644
index 7667e568b0a..00000000000
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuthFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.watcher.common.http.auth;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-
-import java.io.IOException;
-
-public abstract class HttpAuthFactory<Auth extends HttpAuth, AAuth extends ApplicableHttpAuth<Auth>> {
-
-    public abstract String type();
-
-    public abstract Auth parse(XContentParser parser) throws IOException;
-
-    public abstract AAuth createApplicable(Auth auth);
-
-    public AAuth parseApplicable(XContentParser parser) throws IOException {
-        Auth auth = parse(parser);
-        return createApplicable(auth);
-    }
-
-}
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuthRegistry.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuthRegistry.java
deleted file mode 100644
index edf584231d6..00000000000
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/HttpAuthRegistry.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.watcher.common.http.auth;
-
-import org.elasticsearch.ElasticsearchParseException;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.Map;
-
-import static org.elasticsearch.xpack.core.watcher.support.Exceptions.illegalArgument;
-
-public class HttpAuthRegistry {
-
-    private final Map<String, HttpAuthFactory> factories;
-
-    public HttpAuthRegistry(Map<String, HttpAuthFactory> factories) {
-        this.factories = factories;
-    }
-
-    public HttpAuth parse(XContentParser parser) throws IOException {
-        String type = null;
-        XContentParser.Token token;
-        HttpAuth auth = null;
-        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
-            if (token == XContentParser.Token.FIELD_NAME) {
-                type = parser.currentName();
-            } else if (token == XContentParser.Token.START_OBJECT && type != null) {
-                HttpAuthFactory factory = factories.get(type);
-                if (factory == null) {
-                    throw new ElasticsearchParseException("unknown http auth type [{}]", type);
-                }
-                auth = factory.parse(parser);
-            }
-        }
-        return auth;
-    }
-
-    public <A extends HttpAuth, AA extends ApplicableHttpAuth<A>> AA createApplicable(A auth) {
-        HttpAuthFactory factory = factories.get(auth.type());
-        if (factory == null) {
-            throw illegalArgument("unknown http auth type [{}]", auth.type());
-        }
-        return (AA) factory.createApplicable(auth);
-    }
-
-}
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/ApplicableBasicAuth.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/ApplicableBasicAuth.java
deleted file mode 100644
index 86639a59a12..00000000000
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/ApplicableBasicAuth.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.watcher.common.http.auth.basic;
-
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.elasticsearch.xpack.core.watcher.crypto.CryptoService;
-import org.elasticsearch.xpack.watcher.common.http.auth.ApplicableHttpAuth;
-
-import java.net.HttpURLConnection;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-
-public class ApplicableBasicAuth extends ApplicableHttpAuth<BasicAuth> {
-
-    private final String basicAuth;
-    private final CryptoService cryptoService;
-
-    public ApplicableBasicAuth(BasicAuth auth, CryptoService service) {
-        super(auth);
-        basicAuth = headerValue(auth.username, auth.password.text(service));
-        this.cryptoService = service;
-    }
-
-    public static String headerValue(String username, char[] password) {
-        return "Basic " + Base64.getEncoder().encodeToString((username + ":" + new String(password)).getBytes(StandardCharsets.UTF_8));
-    }
-
-    public void apply(HttpURLConnection connection) {
-        connection.setRequestProperty("Authorization", basicAuth);
-    }
-
-    @Override
-    public void apply(CredentialsProvider credsProvider, AuthScope authScope) {
-        credsProvider.setCredentials(authScope,
-                new UsernamePasswordCredentials(auth.username, new String(auth.password.text(cryptoService))));
-    }
-
-}
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/BasicAuthFactory.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/BasicAuthFactory.java
deleted file mode 100644
index 838c53be7b1..00000000000
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/auth/basic/BasicAuthFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-package org.elasticsearch.xpack.watcher.common.http.auth.basic;
-
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.xpack.core.watcher.crypto.CryptoService;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthFactory;
-
-import java.io.IOException;
-
-public class BasicAuthFactory extends HttpAuthFactory<BasicAuth, ApplicableBasicAuth> {
-
-    private final CryptoService cryptoService;
-
-    public BasicAuthFactory(@Nullable CryptoService cryptoService) {
-        this.cryptoService = cryptoService;
-    }
-
-    public String type() {
-        return BasicAuth.TYPE;
-    }
-
-    public BasicAuth parse(XContentParser parser) throws IOException {
-        return BasicAuth.parse(parser);
-    }
-
-    @Override
-    public ApplicableBasicAuth createApplicable(BasicAuth auth) {
-        return new ApplicableBasicAuth(auth, cryptoService);
-    }
-}
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInput.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInput.java
index 3f3acdc0b32..4a0763f7d6b 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInput.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInput.java
@@ -70,7 +70,7 @@ public class HttpInput implements Input {
         return builder;
     }
 
-    public static HttpInput parse(String watchId, XContentParser parser, HttpRequestTemplate.Parser requestParser) throws IOException {
+    public static HttpInput parse(String watchId, XContentParser parser) throws IOException {
         Set<String> extract = null;
         HttpRequestTemplate request = null;
         HttpContentType expectedResponseBodyType = null;
@@ -82,7 +82,7 @@ public class HttpInput implements Input {
                 currentFieldName = parser.currentName();
             } else if (Field.REQUEST.match(currentFieldName, parser.getDeprecationHandler())) {
                 try {
-                    request = requestParser.parse(parser);
+                    request = HttpRequestTemplate.Parser.parse(parser);
                 } catch (ElasticsearchParseException pe) {
                     throw new ElasticsearchParseException("could not parse [{}] input for watch [{}]. failed to parse http request " +
                             "template", pe, TYPE, watchId);
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInputFactory.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInputFactory.java
index 2cb26ab1d67..7a68a77ddd2 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInputFactory.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/input/http/HttpInputFactory.java
@@ -9,7 +9,6 @@ import org.elasticsearch.common.logging.Loggers;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.xpack.watcher.common.http.HttpClient;
-import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.input.InputFactory;
 
@@ -19,14 +18,11 @@ public final class HttpInputFactory extends InputFactory<HttpInput, HttpInput.Re
 
     private final HttpClient httpClient;
     private final TextTemplateEngine templateEngine;
-    private final HttpRequestTemplate.Parser requestTemplateParser;
 
-    public HttpInputFactory(Settings settings, HttpClient httpClient, TextTemplateEngine templateEngine,
-                            HttpRequestTemplate.Parser requestTemplateParser) {
+    public HttpInputFactory(Settings settings, HttpClient httpClient, TextTemplateEngine templateEngine) {
         super(Loggers.getLogger(ExecutableHttpInput.class, settings));
         this.templateEngine = templateEngine;
         this.httpClient = httpClient;
-        this.requestTemplateParser = requestTemplateParser;
     }
 
     @Override
@@ -36,7 +32,7 @@ public final class HttpInputFactory extends InputFactory<HttpInput, HttpInput.Re
 
     @Override
     public HttpInput parseInput(String watchId, XContentParser parser) throws IOException {
-        return HttpInput.parse(watchId, parser, requestTemplateParser);
+        return HttpInput.parse(watchId, parser);
     }
 
     @Override
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParser.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParser.java
index a9f161a3fc8..7c5d68a126b 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParser.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParser.java
@@ -34,13 +34,10 @@ public class HttpEmailAttachementParser implements EmailAttachmentParser<HttpReq
 
     public static final String TYPE = "http";
     private final HttpClient httpClient;
-    private HttpRequestTemplate.Parser requestTemplateParser;
     private final TextTemplateEngine templateEngine;
 
-    public HttpEmailAttachementParser(HttpClient httpClient, HttpRequestTemplate.Parser requestTemplateParser,
-                                      TextTemplateEngine templateEngine) {
+    public HttpEmailAttachementParser(HttpClient httpClient, TextTemplateEngine templateEngine) {
         this.httpClient = httpClient;
-        this.requestTemplateParser = requestTemplateParser;
         this.templateEngine = templateEngine;
     }
 
@@ -65,7 +62,7 @@ public class HttpEmailAttachementParser implements EmailAttachmentParser<HttpReq
             } else if (Fields.INLINE.match(currentFieldName, parser.getDeprecationHandler())) {
                 inline = parser.booleanValue();
             } else if (Fields.REQUEST.match(currentFieldName, parser.getDeprecationHandler())) {
-                requestTemplate = requestTemplateParser.parse(parser);
+                requestTemplate = HttpRequestTemplate.Parser.parse(parser);
             } else {
                 String msg = "Unknown field name [" + currentFieldName + "] in http request attachment configuration";
                 throw new ElasticsearchParseException(msg);
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachment.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachment.java
index b4c0208ae2a..f5d330f5323 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachment.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachment.java
@@ -10,7 +10,7 @@ import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 
 import java.io.IOException;
 import java.util.Objects;
@@ -26,14 +26,14 @@ public class ReportingAttachment implements EmailAttachmentParser.EmailAttachmen
 
     private final boolean inline;
     private final String id;
-    private final HttpAuth auth;
+    private final BasicAuth auth;
     private final String url;
     private final TimeValue interval;
     private final Integer retries;
     private final HttpProxy proxy;
 
     ReportingAttachment(String id, String url, boolean inline, @Nullable TimeValue interval, @Nullable Integer retries,
-                        @Nullable HttpAuth auth, @Nullable HttpProxy proxy) {
+                        @Nullable BasicAuth auth, @Nullable HttpProxy proxy) {
         this.id = id;
         this.url = url;
         this.retries = retries;
@@ -61,7 +61,7 @@ public class ReportingAttachment implements EmailAttachmentParser.EmailAttachmen
         return inline;
     }
 
-    public HttpAuth auth() {
+    public BasicAuth auth() {
         return auth;
     }
 
@@ -100,7 +100,7 @@ public class ReportingAttachment implements EmailAttachmentParser.EmailAttachmen
 
         if (auth != null) {
             builder.startObject(AUTH.getPreferredName());
-            builder.field(auth.type(), auth, params);
+            builder.field(BasicAuth.TYPE, auth, params);
             builder.endObject();
         }
 
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java
index cb508766783..28a8c194b57 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java
@@ -28,8 +28,7 @@ import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.notification.email.Attachment;
@@ -69,15 +68,12 @@ public class ReportingAttachmentParser implements EmailAttachmentParser<Reportin
     private final int retries;
     private HttpClient httpClient;
     private final TextTemplateEngine templateEngine;
-    private HttpAuthRegistry authRegistry;
 
-    public ReportingAttachmentParser(Settings settings, HttpClient httpClient,
-                                     TextTemplateEngine templateEngine, HttpAuthRegistry authRegistry) {
+    public ReportingAttachmentParser(Settings settings, HttpClient httpClient, TextTemplateEngine templateEngine) {
         this.interval = INTERVAL_SETTING.get(settings);
         this.retries = RETRIES_SETTING.get(settings);
         this.httpClient = httpClient;
         this.templateEngine = templateEngine;
-        this.authRegistry = authRegistry;
         this.logger = Loggers.getLogger(getClass());
     }
 
@@ -89,7 +85,7 @@ public class ReportingAttachmentParser implements EmailAttachmentParser<Reportin
     @Override
     public ReportingAttachment parse(String id, XContentParser parser) throws IOException {
         Builder builder = new Builder(id);
-        PARSER.parse(parser, builder, new AuthParseContext(authRegistry));
+        PARSER.parse(parser, builder, new AuthParseContext());
         return builder.build();
     }
 
@@ -222,15 +218,9 @@ public class ReportingAttachmentParser implements EmailAttachmentParser<Reportin
      */
     private static class AuthParseContext {
 
-        private final HttpAuthRegistry authRegistry;
-
-        AuthParseContext(HttpAuthRegistry authRegistry) {
-            this.authRegistry = authRegistry;
-        }
-
-        HttpAuth parseAuth(XContentParser parser) {
+        BasicAuth parseAuth(XContentParser parser) {
             try {
-                return authRegistry.parse(parser);
+                return BasicAuth.parse(parser);
             } catch (IOException e) {
                 throw new UncheckedIOException(e);
             }
@@ -273,7 +263,7 @@ public class ReportingAttachmentParser implements EmailAttachmentParser<Reportin
         private String url;
         private TimeValue interval;
         private Integer retries;
-        private HttpAuth auth;
+        private BasicAuth auth;
         private HttpProxy proxy;
 
         Builder(String id) {
@@ -301,7 +291,7 @@ public class ReportingAttachmentParser implements EmailAttachmentParser<Reportin
             return this;
         }
 
-        Builder auth(HttpAuth auth) {
+        Builder auth(BasicAuth auth) {
             this.auth = auth;
             return this;
         }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatMessage.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatMessage.java
index ae08bb85e9d..10eaba535ed 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatMessage.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatMessage.java
@@ -13,14 +13,12 @@ import org.elasticsearch.common.xcontent.ToXContentObject;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
-import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Objects;
 
 public class HipChatMessage implements ToXContentObject {
@@ -181,26 +179,6 @@ public class HipChatMessage implements ToXContentObject {
             return Objects.hash(body, rooms, users, from, format, color, notify);
         }
 
-        public HipChatMessage render(TextTemplateEngine engine, Map<String, Object> model) {
-            String body = engine.render(this.body, model);
-            String[] rooms = null;
-            if (this.rooms != null) {
-                rooms = new String[this.rooms.length];
-                for (int i = 0; i < this.rooms.length; i++) {
-                    rooms[i] = engine.render(this.rooms[i], model);
-                }
-            }
-            String[] users = null;
-            if (this.users != null) {
-                users = new String[this.users.length];
-                for (int i = 0; i < this.users.length; i++) {
-                    users[i] = engine.render(this.users[i], model);
-                }
-            }
-            Color color = this.color == null ? null : Color.resolve(engine.render(this.color, model), null);
-            return new HipChatMessage(body, rooms, users, from, format, color, notify);
-        }
-
         @Override
         public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
             builder.startObject();
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/jira/JiraAccount.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/jira/JiraAccount.java
index 5efe09c5759..4221b405d29 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/jira/JiraAccount.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/jira/JiraAccount.java
@@ -26,7 +26,7 @@ import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
 import org.elasticsearch.xpack.watcher.common.http.Scheme;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEvent.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEvent.java
index 0fb1a52d286..c44fbf36e0b 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEvent.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEvent.java
@@ -24,22 +24,22 @@ import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * Official documentation for this can be found at
  *
- * https://developer.pagerduty.com/documentation/howto/manually-trigger-an-incident/
- * https://developer.pagerduty.com/documentation/integration/events/trigger
- * https://developer.pagerduty.com/documentation/integration/events/acknowledge
- * https://developer.pagerduty.com/documentation/integration/events/resolve
+ * https://v2.developer.pagerduty.com/docs/send-an-event-events-api-v2
  */
 public class IncidentEvent implements ToXContentObject {
 
     static final String HOST = "events.pagerduty.com";
-    static final String PATH = "/generic/2010-04-15/create_event.json";
+    static final String PATH = "/v2/enqueue";
+    static final String ACCEPT_HEADER = "application/vnd.pagerduty+json;version=2";
 
     final String description;
     @Nullable final HttpProxy proxy;
@@ -93,46 +93,81 @@ public class IncidentEvent implements ToXContentObject {
         return result;
     }
 
-    public HttpRequest createRequest(final String serviceKey, final Payload payload) throws IOException {
+    HttpRequest createRequest(final String serviceKey, final Payload payload, final String watchId) throws IOException {
         return HttpRequest.builder(HOST, -1)
                 .method(HttpMethod.POST)
                 .scheme(Scheme.HTTPS)
                 .path(PATH)
                 .proxy(proxy)
-                .jsonBody(new ToXContent() {
-                    @Override
-                    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
-                        builder.field(Fields.SERVICE_KEY.getPreferredName(), serviceKey);
-                        builder.field(Fields.EVENT_TYPE.getPreferredName(), eventType);
-                        builder.field(Fields.DESCRIPTION.getPreferredName(), description);
-                        if (incidentKey != null) {
-                            builder.field(Fields.INCIDENT_KEY.getPreferredName(), incidentKey);
-                        }
-                        if (client != null) {
-                            builder.field(Fields.CLIENT.getPreferredName(), client);
-                        }
-                        if (clientUrl != null) {
-                            builder.field(Fields.CLIENT_URL.getPreferredName(), clientUrl);
-                        }
-                        if (attachPayload) {
-                            builder.startObject(Fields.DETAILS.getPreferredName());
-                            builder.field(Fields.PAYLOAD.getPreferredName());
-                            payload.toXContent(builder, params);
-                            builder.endObject();
-                        }
-                        if (contexts != null && contexts.length > 0) {
-                            builder.startArray(Fields.CONTEXTS.getPreferredName());
-                            for (IncidentEventContext context : contexts) {
-                                context.toXContent(builder, params);
-                            }
-                            builder.endArray();
-                        }
-                        return builder;
-                    }
-                })
+                .setHeader("Accept", ACCEPT_HEADER)
+                .jsonBody((b, p) -> buildAPIXContent(b, p, serviceKey, payload, watchId))
                 .build();
     }
 
+    XContentBuilder buildAPIXContent(XContentBuilder builder, Params params, String serviceKey,
+                                            Payload payload, String watchId) throws IOException {
+        builder.field(Fields.ROUTING_KEY.getPreferredName(), serviceKey);
+        builder.field(Fields.EVENT_ACTION.getPreferredName(), eventType);
+        if (incidentKey != null) {
+            builder.field(Fields.DEDUP_KEY.getPreferredName(), incidentKey);
+        }
+
+        builder.startObject(Fields.PAYLOAD.getPreferredName());
+        {
+            builder.field(Fields.SUMMARY.getPreferredName(), description);
+
+            if (attachPayload && payload != null) {
+                builder.startObject(Fields.CUSTOM_DETAILS.getPreferredName());
+                {
+                    builder.field(Fields.PAYLOAD.getPreferredName(), payload, params);
+                }
+                builder.endObject();
+            }
+
+            if (watchId != null) {
+                builder.field(Fields.SOURCE.getPreferredName(), watchId);
+            } else {
+                builder.field(Fields.SOURCE.getPreferredName(), "watcher");
+            }
+            // TODO externalize this into something user editable
+            builder.field(Fields.SEVERITY.getPreferredName(), "critical");
+        }
+        builder.endObject();
+
+        if (client != null) {
+            builder.field(Fields.CLIENT.getPreferredName(), client);
+        }
+        if (clientUrl != null) {
+            builder.field(Fields.CLIENT_URL.getPreferredName(), clientUrl);
+        }
+
+        if (contexts != null && contexts.length > 0) {
+            toXContentV2Contexts(builder, params, contexts);
+        }
+
+        return builder;
+    }
+
+    /**
+     * Turns the V1 API contexts into 2 distinct lists, images and links. The V2 API has separated these out into 2 top level fields.
+     */
+    private void toXContentV2Contexts(XContentBuilder builder, ToXContent.Params params,
+                                      IncidentEventContext[] contexts) throws IOException {
+        // contexts can be either links or images, and the v2 api needs them separate
+        Map<IncidentEventContext.Type, List<IncidentEventContext>> groups = Arrays.stream(contexts)
+            .collect(Collectors.groupingBy(iec -> iec.type));
+
+        List<IncidentEventContext> links = groups.getOrDefault(IncidentEventContext.Type.LINK, Collections.emptyList());
+        if (links.isEmpty() == false) {
+            builder.array(Fields.LINKS.getPreferredName(), links.toArray());
+        }
+
+        List<IncidentEventContext> images = groups.getOrDefault(IncidentEventContext.Type.IMAGE, Collections.emptyList());
+        if (images.isEmpty() == false) {
+            builder.array(Fields.IMAGES.getPreferredName(), images.toArray());
+        }
+    }
+
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
         builder.startObject();
@@ -445,8 +480,15 @@ public class IncidentEvent implements ToXContentObject {
         // we need to keep this for BWC
         ParseField CONTEXT_DEPRECATED = new ParseField("context");
 
-        ParseField SERVICE_KEY = new ParseField("service_key");
         ParseField PAYLOAD = new ParseField("payload");
-        ParseField DETAILS = new ParseField("details");
+        ParseField ROUTING_KEY = new ParseField("routing_key");
+        ParseField EVENT_ACTION = new ParseField("event_action");
+        ParseField DEDUP_KEY = new ParseField("dedup_key");
+        ParseField SUMMARY = new ParseField("summary");
+        ParseField SOURCE = new ParseField("source");
+        ParseField SEVERITY = new ParseField("severity");
+        ParseField LINKS = new ParseField("links");
+        ParseField IMAGES = new ParseField("images");
+        ParseField CUSTOM_DETAILS = new ParseField("custom_details");
     }
 }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventContext.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventContext.java
index d43829346b6..cd9924ae9dc 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventContext.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventContext.java
@@ -92,6 +92,85 @@ public class IncidentEventContext implements ToXContentObject {
         return builder.endObject();
     }
 
+    public static IncidentEventContext parse(XContentParser parser) throws IOException {
+        Type type = null;
+        String href = null;
+        String text = null;
+        String src = null;
+        String alt = null;
+
+        String currentFieldName = null;
+        XContentParser.Token token;
+        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+            if (token == XContentParser.Token.FIELD_NAME) {
+                currentFieldName = parser.currentName();
+            } else if (Strings.hasLength(currentFieldName)) {
+                if (XField.TYPE.match(currentFieldName, parser.getDeprecationHandler())) {
+                    try {
+                        type = Type.valueOf(parser.text().toUpperCase(Locale.ROOT));
+                    } catch (IllegalArgumentException e) {
+                        String msg = "could not parse trigger incident event context. unknown context type [{}]";
+                        throw new ElasticsearchParseException(msg, parser.text());
+                    }
+                } else {
+                    if (XField.HREF.match(currentFieldName, parser.getDeprecationHandler())) {
+                        href = parser.text();
+                    } else if (XField.TEXT.match(currentFieldName, parser.getDeprecationHandler())) {
+                        text = parser.text();
+                    } else if (XField.SRC.match(currentFieldName, parser.getDeprecationHandler())) {
+                        src = parser.text();
+                    } else if (XField.ALT.match(currentFieldName, parser.getDeprecationHandler())) {
+                        alt = parser.text();
+                    } else {
+                        String msg = "could not parse trigger incident event context. unknown field [{}]";
+                        throw new ElasticsearchParseException(msg, currentFieldName);
+                    }
+                }
+            }
+        }
+
+        return createAndValidateTemplate(type, href, src, alt, text);
+    }
+
+    private static IncidentEventContext createAndValidateTemplate(Type type, String href, String src, String alt,
+                                                      String text) {
+        if (type == null) {
+            throw new ElasticsearchParseException("could not parse trigger incident event context. missing required field [{}]",
+                XField.TYPE.getPreferredName());
+        }
+
+        switch (type) {
+            case LINK:
+                if (href == null) {
+                    throw new ElasticsearchParseException("could not parse trigger incident event context. missing required field " +
+                        "[{}] for [{}] context", XField.HREF.getPreferredName(), Type.LINK.name().toLowerCase(Locale.ROOT));
+                }
+                if (src != null) {
+                    throw new ElasticsearchParseException("could not parse trigger incident event context. unexpected field [{}] for " +
+                        "[{}] context", XField.SRC.getPreferredName(), Type.LINK.name().toLowerCase(Locale.ROOT));
+                }
+                if (alt != null) {
+                    throw new ElasticsearchParseException("could not parse trigger incident event context. unexpected field [{}] for " +
+                        "[{}] context", XField.ALT.getPreferredName(), Type.LINK.name().toLowerCase(Locale.ROOT));
+                }
+                return link(href, text);
+            case IMAGE:
+                if (src == null) {
+                    throw new ElasticsearchParseException("could not parse trigger incident event context. missing required field " +
+                        "[{}] for [{}] context", XField.SRC.getPreferredName(), Type.IMAGE.name().toLowerCase(Locale.ROOT));
+                }
+                if (text != null) {
+                    throw new ElasticsearchParseException("could not parse trigger incident event context. unexpected field [{}] for " +
+                        "[{}] context", XField.TEXT.getPreferredName(), Type.IMAGE.name().toLowerCase(Locale.ROOT));
+                }
+                return image(src, href, alt);
+            default:
+                throw new ElasticsearchParseException("could not parse trigger incident event context. unknown context type [{}]",
+                    type);
+        }
+    }
+
+
     public static class Template implements ToXContentObject {
 
         final Type type;
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccount.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccount.java
index 5cf1a77f971..b2498a749d7 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccount.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccount.java
@@ -48,8 +48,8 @@ public class PagerDutyAccount {
         return eventDefaults;
     }
 
-    public SentEvent send(IncidentEvent event, Payload payload) throws IOException {
-        HttpRequest request = event.createRequest(serviceKey, payload);
+    public SentEvent send(IncidentEvent event, Payload payload, String watchId) throws IOException {
+        HttpRequest request = event.createRequest(serviceKey, payload, watchId);
         HttpResponse response = httpClient.execute(request);
         return SentEvent.responded(event, request, response);
     }
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java
index 6e1fb859284..36ec856bedd 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistry.java
@@ -8,7 +8,7 @@ package org.elasticsearch.xpack.watcher.support;
 import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterChangedEvent;
 import org.elasticsearch.cluster.ClusterState;
@@ -21,8 +21,8 @@ import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.gateway.GatewayService;
 import org.elasticsearch.threadpool.ThreadPool;
-import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
 import org.elasticsearch.xpack.core.template.TemplateUtils;
+import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
 
 import java.nio.charset.StandardCharsets;
 import java.util.concurrent.ConcurrentHashMap;
@@ -108,9 +108,9 @@ public class WatcherIndexTemplateRegistry extends AbstractComponent implements C
             PutIndexTemplateRequest request = new PutIndexTemplateRequest(templateName).source(config.load(), XContentType.JSON);
             request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
             executeAsyncWithOrigin(client.threadPool().getThreadContext(), WATCHER_ORIGIN, request,
-                    new ActionListener<PutIndexTemplateResponse>() {
+                    new ActionListener<AcknowledgedResponse>() {
                         @Override
-                        public void onResponse(PutIndexTemplateResponse response) {
+                        public void onResponse(AcknowledgedResponse response) {
                             creationCheck.set(false);
                             if (response.isAcknowledged() == false) {
                                 logger.error("Error adding watcher template [{}], request was not acknowledged", templateName);
diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/service/TransportWatcherServiceAction.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/service/TransportWatcherServiceAction.java
index 6b2bb26ef45..f4fd443abe1 100644
--- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/service/TransportWatcherServiceAction.java
+++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/service/TransportWatcherServiceAction.java
@@ -9,6 +9,7 @@ import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.ActionFilters;
 import org.elasticsearch.action.support.master.AcknowledgedRequest;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.action.support.master.TransportMasterNodeAction;
 import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
 import org.elasticsearch.cluster.ClusterState;
@@ -27,9 +28,8 @@ import org.elasticsearch.xpack.core.XPackPlugin;
 import org.elasticsearch.xpack.core.watcher.WatcherMetaData;
 import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceAction;
 import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceRequest;
-import org.elasticsearch.xpack.core.watcher.transport.actions.service.WatcherServiceResponse;
 
-public class TransportWatcherServiceAction extends TransportMasterNodeAction<WatcherServiceRequest, WatcherServiceResponse> {
+public class TransportWatcherServiceAction extends TransportMasterNodeAction<WatcherServiceRequest, AcknowledgedResponse> {
 
     private AckedRequest ackedRequest = new AckedRequest() {
         @Override
@@ -57,13 +57,13 @@ public class TransportWatcherServiceAction extends TransportMasterNodeAction<Wat
     }
 
     @Override
-    protected WatcherServiceResponse newResponse() {
-        return new WatcherServiceResponse();
+    protected AcknowledgedResponse newResponse() {
+        return new AcknowledgedResponse();
     }
 
     @Override
     protected void masterOperation(WatcherServiceRequest request, ClusterState state,
-                                   ActionListener<WatcherServiceResponse> listener) {
+                                   ActionListener<AcknowledgedResponse> listener) {
         switch (request.getCommand()) {
             case STOP:
                 setWatcherMetaDataAndWait(true, listener);
@@ -74,15 +74,15 @@ public class TransportWatcherServiceAction extends TransportMasterNodeAction<Wat
         }
     }
 
-    private void setWatcherMetaDataAndWait(boolean manuallyStopped, final ActionListener<WatcherServiceResponse> listener) {
+    private void setWatcherMetaDataAndWait(boolean manuallyStopped, final ActionListener<AcknowledgedResponse> listener) {
         String source = manuallyStopped ? "update_watcher_manually_stopped" : "update_watcher_manually_started";
 
         clusterService.submitStateUpdateTask(source,
-                new AckedClusterStateUpdateTask<WatcherServiceResponse>(ackedRequest, listener) {
+                new AckedClusterStateUpdateTask<AcknowledgedResponse>(ackedRequest, listener) {
 
                     @Override
-                    protected WatcherServiceResponse newResponse(boolean acknowledged) {
-                        return new WatcherServiceResponse(acknowledged);
+                    protected AcknowledgedResponse newResponse(boolean acknowledged) {
+                        return new AcknowledgedResponse(acknowledged);
                     }
 
                     @Override
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailActionTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailActionTests.java
index 83b48cb9f4f..d073d3e4dd1 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailActionTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailActionTests.java
@@ -27,8 +27,6 @@ import org.elasticsearch.xpack.watcher.common.http.HttpClient;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.notification.email.Attachment;
@@ -79,7 +77,6 @@ import static org.mockito.Mockito.when;
 
 public class EmailActionTests extends ESTestCase {
 
-    private HttpAuthRegistry registry = new HttpAuthRegistry(singletonMap("basic", new BasicAuthFactory(null)));
     private HttpClient httpClient = mock(HttpClient.class);
     private EmailAttachmentsParser emailAttachmentParser;
 
@@ -87,7 +84,7 @@ public class EmailActionTests extends ESTestCase {
     public void addEmailAttachmentParsers() {
         Map<String, EmailAttachmentParser> emailAttachmentParsers = new HashMap<>();
         emailAttachmentParsers.put(HttpEmailAttachementParser.TYPE, new HttpEmailAttachementParser(httpClient,
-                new HttpRequestTemplate.Parser(registry), new MockTextTemplateEngine()));
+            new MockTextTemplateEngine()));
         emailAttachmentParsers.put(DataAttachmentParser.TYPE, new DataAttachmentParser());
         emailAttachmentParser = new EmailAttachmentsParser(emailAttachmentParsers);
     }
@@ -511,10 +508,8 @@ public class EmailActionTests extends ESTestCase {
                 .thenReturn(new HttpResponse(403));
 
         // setup email attachment parsers
-        HttpRequestTemplate.Parser httpRequestTemplateParser = new HttpRequestTemplate.Parser(registry);
         Map<String, EmailAttachmentParser> attachmentParsers = new HashMap<>();
-        attachmentParsers.put(HttpEmailAttachementParser.TYPE, new HttpEmailAttachementParser(httpClient, httpRequestTemplateParser,
-                engine));
+        attachmentParsers.put(HttpEmailAttachementParser.TYPE, new HttpEmailAttachementParser(httpClient, engine));
         EmailAttachmentsParser emailAttachmentsParser = new EmailAttachmentsParser(attachmentParsers);
 
         XContentBuilder builder = jsonBuilder().startObject()
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/jira/ExecutableJiraActionTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/jira/ExecutableJiraActionTests.java
index cb434e62df5..aa03bf4545e 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/jira/ExecutableJiraActionTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/jira/ExecutableJiraActionTests.java
@@ -17,8 +17,7 @@ import org.elasticsearch.xpack.watcher.common.http.HttpClient;
 import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.notification.jira.JiraAccount;
@@ -93,11 +92,9 @@ public class ExecutableJiraActionTests extends ESTestCase {
         assertThat(request.port(), is(port));
         assertThat(request.path(), is(JiraAccount.DEFAULT_PATH));
 
-        HttpAuth httpAuth = request.auth();
-        assertThat(httpAuth.type(), is("basic"));
+        BasicAuth httpAuth = request.auth();
 
-        BasicAuth basicAuth = (BasicAuth) httpAuth;
-        assertThat(basicAuth.getUsername(), is(user));
+        assertThat(httpAuth.getUsername(), is(user));
     }
 
     public void testExecutionWithNoDefaults() throws Exception {
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/pagerduty/PagerDutyActionTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/pagerduty/PagerDutyActionTests.java
index 6f57ccd82d9..07a55c628ec 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/pagerduty/PagerDutyActionTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/pagerduty/PagerDutyActionTests.java
@@ -111,7 +111,7 @@ public class PagerDutyActionTests extends ESTestCase {
         when(response.status()).thenReturn(200);
         HttpRequest request = mock(HttpRequest.class);
         SentEvent sentEvent = SentEvent.responded(event, request, response);
-        when(account.send(event, payload)).thenReturn(sentEvent);
+        when(account.send(event, payload, wid.watchId())).thenReturn(sentEvent);
         when(service.getAccount(accountName)).thenReturn(account);
 
         Action.Result result = executable.execute("_id", ctx, payload);
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java
index 09ca57c1708..755e3dffe5c 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookActionTests.java
@@ -28,8 +28,6 @@ import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.execution.TriggeredExecutionContext;
@@ -47,7 +45,6 @@ import javax.mail.internet.AddressException;
 import java.io.IOException;
 import java.util.Map;
 
-import static java.util.Collections.singletonMap;
 import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -73,7 +70,6 @@ public class WebhookActionTests extends ESTestCase {
     private static final String TEST_PATH_STRING = "/testPath";
 
     private TextTemplateEngine templateEngine;
-    private HttpAuthRegistry authRegistry;
     private TextTemplate testBody;
     private TextTemplate testPath;
 
@@ -82,7 +78,6 @@ public class WebhookActionTests extends ESTestCase {
         templateEngine = new MockTextTemplateEngine();
         testBody = new TextTemplate(TEST_BODY_STRING);
         testPath = new TextTemplate(TEST_PATH_STRING);
-        authRegistry = new HttpAuthRegistry(singletonMap("basic", new BasicAuthFactory(null)));
     }
 
     public void testExecute() throws Exception {
@@ -213,14 +208,14 @@ public class WebhookActionTests extends ESTestCase {
     }
 
     private WebhookActionFactory webhookFactory(HttpClient client) {
-        return new WebhookActionFactory(Settings.EMPTY, client, new HttpRequestTemplate.Parser(authRegistry), templateEngine);
+        return new WebhookActionFactory(Settings.EMPTY, client, templateEngine);
     }
 
     public void testThatSelectingProxyWorks() throws Exception {
         Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
 
-        try (HttpClient httpClient = new HttpClient(Settings.EMPTY, authRegistry,
-            new SSLService(environment.settings(), environment)); MockWebServer proxyServer = new MockWebServer()) {
+        try (HttpClient httpClient = new HttpClient(Settings.EMPTY, new SSLService(environment.settings(), environment), null);
+             MockWebServer proxyServer = new MockWebServer()) {
             proxyServer.start();
             proxyServer.enqueue(new MockResponse().setResponseCode(200).setBody("fullProxiedContent"));
 
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java
index a69445386d0..0ba733ea4c5 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java
@@ -18,7 +18,7 @@ import org.elasticsearch.xpack.watcher.actions.ActionBuilders;
 import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.Scheme;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
 import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java
index 4fd162495f4..d26d07a8fbd 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java
@@ -19,7 +19,7 @@ import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource;
 import org.elasticsearch.xpack.watcher.actions.ActionBuilders;
 import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
 import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java
index 03dcd794715..882dc5389a4 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java
@@ -27,9 +27,6 @@ import org.elasticsearch.test.junit.annotations.Network;
 import org.elasticsearch.xpack.core.ssl.SSLService;
 import org.elasticsearch.xpack.core.ssl.TestsSSLService;
 import org.elasticsearch.xpack.core.ssl.VerificationMode;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.junit.After;
 import org.junit.Before;
 
@@ -48,7 +45,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicReference;
 
-import static java.util.Collections.singletonMap;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
@@ -64,14 +60,12 @@ public class HttpClientTests extends ESTestCase {
 
     private MockWebServer webServer = new MockWebServer();
     private HttpClient httpClient;
-    private HttpAuthRegistry authRegistry;
     private Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
 
     @Before
     public void init() throws Exception {
-        authRegistry = new HttpAuthRegistry(singletonMap(BasicAuth.TYPE, new BasicAuthFactory(null)));
         webServer.start();
-        httpClient = new HttpClient(Settings.EMPTY, authRegistry, new SSLService(environment.settings(), environment));
+        httpClient = new HttpClient(Settings.EMPTY, new SSLService(environment.settings(), environment), null);
     }
 
     @After
@@ -185,7 +179,7 @@ public class HttpClientTests extends ESTestCase {
                 .setSecureSettings(secureSettings)
                 .build();
         }
-        try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
+        try (HttpClient client = new HttpClient(settings, new SSLService(settings, environment), null)) {
             secureSettings = new MockSecureSettings();
             // We can't use the client created above for the server since it is only a truststore
             secureSettings.setString("xpack.ssl.secure_key_passphrase", "testnode");
@@ -226,7 +220,7 @@ public class HttpClientTests extends ESTestCase {
             }
             settings = builder.build();
         }
-        try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
+        try (HttpClient client = new HttpClient(settings, new SSLService(settings, environment), null)) {
             MockSecureSettings secureSettings = new MockSecureSettings();
             // We can't use the client created above for the server since it only defines a truststore
             secureSettings.setString("xpack.ssl.secure_key_passphrase", "testnode-no-subjaltname");
@@ -253,7 +247,7 @@ public class HttpClientTests extends ESTestCase {
             .build();
 
         TestsSSLService sslService = new TestsSSLService(settings, environment);
-        try (HttpClient client = new HttpClient(settings, authRegistry, sslService)) {
+        try (HttpClient client = new HttpClient(settings, sslService, null)) {
             testSslMockWebserver(client, sslService.sslContext(), true);
         }
     }
@@ -301,7 +295,7 @@ public class HttpClientTests extends ESTestCase {
 
     @Network
     public void testHttpsWithoutTruststore() throws Exception {
-        try (HttpClient client = new HttpClient(Settings.EMPTY, authRegistry, new SSLService(Settings.EMPTY, environment))) {
+        try (HttpClient client = new HttpClient(Settings.EMPTY, new SSLService(Settings.EMPTY, environment), null)) {
             // Known server with a valid cert from a commercial CA
             HttpRequest.Builder request = HttpRequest.builder("www.elastic.co", 443).scheme(Scheme.HTTPS);
             HttpResponse response = client.execute(request.build());
@@ -325,7 +319,7 @@ public class HttpClientTests extends ESTestCase {
                     .method(HttpMethod.GET)
                     .path("/");
 
-            try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
+            try (HttpClient client = new HttpClient(settings, new SSLService(settings, environment), null)) {
                 HttpResponse response = client.execute(requestBuilder.build());
                 assertThat(response.status(), equalTo(200));
                 assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
@@ -406,7 +400,7 @@ public class HttpClientTests extends ESTestCase {
                     .scheme(Scheme.HTTP)
                     .path("/");
 
-            try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
+            try (HttpClient client = new HttpClient(settings, new SSLService(settings, environment), null)) {
                 HttpResponse response = client.execute(requestBuilder.build());
                 assertThat(response.status(), equalTo(200));
                 assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
@@ -434,7 +428,7 @@ public class HttpClientTests extends ESTestCase {
                     .proxy(new HttpProxy("localhost", proxyServer.getPort(), Scheme.HTTP))
                     .path("/");
 
-            try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(settings, environment))) {
+            try (HttpClient client = new HttpClient(settings, new SSLService(settings, environment), null)) {
                 HttpResponse response = client.execute(requestBuilder.build());
                 assertThat(response.status(), equalTo(200));
                 assertThat(response.body().utf8ToString(), equalTo("fullProxiedContent"));
@@ -455,7 +449,7 @@ public class HttpClientTests extends ESTestCase {
         }
 
         IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
-                () -> new HttpClient(settings.build(), authRegistry, new SSLService(settings.build(), environment)));
+                () -> new HttpClient(settings.build(), new SSLService(settings.build(), environment), null));
         assertThat(e.getMessage(),
                 containsString("HTTP proxy requires both settings: [xpack.http.proxy.host] and [xpack.http.proxy.port]"));
     }
@@ -554,7 +548,7 @@ public class HttpClientTests extends ESTestCase {
 
         HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort()).method(HttpMethod.GET).path("/");
 
-        try (HttpClient client = new HttpClient(settings, authRegistry, new SSLService(environment.settings(), environment))) {
+        try (HttpClient client = new HttpClient(settings, new SSLService(environment.settings(), environment), null)) {
             IOException e = expectThrows(IOException.class, () -> client.execute(requestBuilder.build()));
             assertThat(e.getMessage(), startsWith("Maximum limit of"));
         }
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpConnectionTimeoutTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpConnectionTimeoutTests.java
index 8ac2bef16e8..21efe5b2b94 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpConnectionTimeoutTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpConnectionTimeoutTests.java
@@ -13,11 +13,9 @@ import org.elasticsearch.env.TestEnvironment;
 import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.test.junit.annotations.Network;
 import org.elasticsearch.xpack.core.ssl.SSLService;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
 
 import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.lessThan;
-import static org.mockito.Mockito.mock;
 
 public class HttpConnectionTimeoutTests extends ESTestCase {
     // setting an unroutable IP to simulate a connection timeout
@@ -26,8 +24,7 @@ public class HttpConnectionTimeoutTests extends ESTestCase {
     @Network
     public void testDefaultTimeout() throws Exception {
         Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
-        HttpClient httpClient = new HttpClient(Settings.EMPTY, mock(HttpAuthRegistry.class),
-                new SSLService(environment.settings(), environment));
+        HttpClient httpClient = new HttpClient(Settings.EMPTY, new SSLService(environment.settings(), environment), null);
 
         HttpRequest request = HttpRequest.builder(UNROUTABLE_IP, 12345)
                 .method(HttpMethod.POST)
@@ -52,8 +49,7 @@ public class HttpConnectionTimeoutTests extends ESTestCase {
     public void testDefaultTimeoutCustom() throws Exception {
         Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
         HttpClient httpClient = new HttpClient(Settings.builder()
-                .put("xpack.http.default_connection_timeout", "5s").build()
-                , mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment));
+                .put("xpack.http.default_connection_timeout", "5s").build(), new SSLService(environment.settings(), environment), null);
 
         HttpRequest request = HttpRequest.builder(UNROUTABLE_IP, 12345)
                 .method(HttpMethod.POST)
@@ -78,8 +74,7 @@ public class HttpConnectionTimeoutTests extends ESTestCase {
     public void testTimeoutCustomPerRequest() throws Exception {
         Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
         HttpClient httpClient = new HttpClient(Settings.builder()
-                .put("xpack.http.default_connection_timeout", "10s").build()
-                , mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment));
+                .put("xpack.http.default_connection_timeout", "10s").build(), new SSLService(environment.settings(), environment), null);
 
         HttpRequest request = HttpRequest.builder(UNROUTABLE_IP, 12345)
                 .connectionTimeout(TimeValue.timeValueSeconds(5))
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpReadTimeoutTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpReadTimeoutTests.java
index fa5a53f4e1d..bc328dc586e 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpReadTimeoutTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpReadTimeoutTests.java
@@ -13,7 +13,6 @@ import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.test.http.MockResponse;
 import org.elasticsearch.test.http.MockWebServer;
 import org.elasticsearch.xpack.core.ssl.SSLService;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
 import org.junit.After;
 import org.junit.Before;
 
@@ -21,7 +20,6 @@ import java.net.SocketTimeoutException;
 
 import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.lessThan;
-import static org.mockito.Mockito.mock;
 
 public class HttpReadTimeoutTests extends ESTestCase {
 
@@ -45,8 +43,7 @@ public class HttpReadTimeoutTests extends ESTestCase {
                 .path("/")
                 .build();
 
-        try (HttpClient httpClient = new HttpClient(Settings.EMPTY, mock(HttpAuthRegistry.class),
-            new SSLService(environment.settings(), environment))) {
+        try (HttpClient httpClient = new HttpClient(Settings.EMPTY, new SSLService(environment.settings(), environment), null)) {
             long start = System.nanoTime();
 
             expectThrows(SocketTimeoutException.class, () ->  httpClient.execute(request));
@@ -68,8 +65,7 @@ public class HttpReadTimeoutTests extends ESTestCase {
                 .build();
 
         try (HttpClient httpClient = new HttpClient(Settings.builder()
-            .put("xpack.http.default_read_timeout", "3s").build()
-            , mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment))) {
+            .put("xpack.http.default_read_timeout", "3s").build(), new SSLService(environment.settings(), environment), null)) {
 
             long start = System.nanoTime();
             expectThrows(SocketTimeoutException.class, () ->  httpClient.execute(request));
@@ -92,8 +88,7 @@ public class HttpReadTimeoutTests extends ESTestCase {
                 .build();
 
         try (HttpClient httpClient = new HttpClient(Settings.builder()
-            .put("xpack.http.default_read_timeout", "10s").build()
-            , mock(HttpAuthRegistry.class), new SSLService(environment.settings(), environment))) {
+            .put("xpack.http.default_read_timeout", "10s").build(), new SSLService(environment.settings(), environment), null)) {
 
             long start = System.nanoTime();
             expectThrows(SocketTimeoutException.class, () ->  httpClient.execute(request));
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplateTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplateTests.java
index 1f57c812ebb..dcbc19f4d50 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplateTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTemplateTests.java
@@ -14,22 +14,17 @@ import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
 
 import java.util.Collections;
 
 import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonMap;
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasEntry;
 import static org.hamcrest.Matchers.is;
-import static org.mockito.Mockito.mock;
 
 public class HttpRequestTemplateTests extends ESTestCase {
 
@@ -87,8 +82,7 @@ public class HttpRequestTemplateTests extends ESTestCase {
         XContentParser xContentParser = createParser(xContentBuilder);
         xContentParser.nextToken();
 
-        HttpRequestTemplate.Parser parser = new HttpRequestTemplate.Parser(mock(HttpAuthRegistry.class));
-        HttpRequestTemplate parsedTemplate = parser.parse(xContentParser);
+        HttpRequestTemplate parsedTemplate = HttpRequestTemplate.Parser.parse(xContentParser);
         assertThat(parsedTemplate.proxy().getPort(), is(proxyPort));
         assertThat(parsedTemplate.proxy().getHost(), is(proxyHost));
     }
@@ -134,14 +128,10 @@ public class HttpRequestTemplateTests extends ESTestCase {
 
         HttpRequestTemplate template = builder.build();
 
-        HttpAuthRegistry registry = new HttpAuthRegistry(singletonMap(BasicAuth.TYPE,
-                new BasicAuthFactory(null)));
-        HttpRequestTemplate.Parser parser = new HttpRequestTemplate.Parser(registry);
-
         XContentBuilder xContentBuilder = template.toXContent(jsonBuilder(), WatcherParams.builder().hideSecrets(false).build());
         XContentParser xContentParser = createParser(xContentBuilder);
         xContentParser.nextToken();
-        HttpRequestTemplate parsed = parser.parse(xContentParser);
+        HttpRequestTemplate parsed = HttpRequestTemplate.Parser.parse(xContentParser);
 
         assertEquals(template, parsed);
     }
@@ -194,13 +184,12 @@ public class HttpRequestTemplateTests extends ESTestCase {
         XContentParser urlContentParser = createParser(urlContentBuilder);
         urlContentParser.nextToken();
 
-        HttpRequestTemplate.Parser parser = new HttpRequestTemplate.Parser(mock(HttpAuthRegistry.class));
-        HttpRequestTemplate urlParsedTemplate = parser.parse(urlContentParser);
+        HttpRequestTemplate urlParsedTemplate = HttpRequestTemplate.Parser.parse(urlContentParser);
 
         XContentBuilder xContentBuilder = builder.build().toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS);
         XContentParser xContentParser = createParser(xContentBuilder);
         xContentParser.nextToken();
-        HttpRequestTemplate parsedTemplate = parser.parse(xContentParser);
+        HttpRequestTemplate parsedTemplate = HttpRequestTemplate.Parser.parse(xContentParser);
 
         assertThat(parsedTemplate, is(urlParsedTemplate));
     }
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTests.java
index 223735cad54..0d1541577a5 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpRequestTests.java
@@ -13,11 +13,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
 import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherXContentParser;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 
-import static java.util.Collections.singletonMap;
 import static org.elasticsearch.common.xcontent.XContentFactory.cborBuilder;
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 import static org.elasticsearch.common.xcontent.XContentFactory.smileBuilder;
@@ -25,7 +21,6 @@ import static org.elasticsearch.common.xcontent.XContentFactory.yamlBuilder;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
-import static org.mockito.Mockito.mock;
 
 public class HttpRequestTests extends ESTestCase {
 
@@ -129,14 +124,12 @@ public class HttpRequestTests extends ESTestCase {
         try (XContentBuilder xContentBuilder = randomFrom(jsonBuilder(), smileBuilder(), yamlBuilder(), cborBuilder())) {
             httpRequest.toXContent(xContentBuilder, WatcherParams.builder().hideSecrets(false).build());
 
-            HttpAuthRegistry registry = new HttpAuthRegistry(singletonMap(BasicAuth.TYPE, new BasicAuthFactory(null)));
-            HttpRequest.Parser httpRequestParser = new HttpRequest.Parser(registry);
-    
+
             try (XContentParser parser = createParser(xContentBuilder)) {
                 assertNull(parser.currentToken());
                 parser.nextToken();
-    
-                HttpRequest parsedRequest = httpRequestParser.parse(parser);
+
+                HttpRequest parsedRequest = HttpRequest.Parser.parse(parser);
                 assertEquals(httpRequest, parsedRequest);
             }
         }
@@ -161,14 +154,13 @@ public class HttpRequestTests extends ESTestCase {
         XContentParser urlContentParser = createParser(urlContentBuilder);
         urlContentParser.nextToken();
 
-        HttpRequest.Parser parser = new HttpRequest.Parser(mock(HttpAuthRegistry.class));
-        HttpRequest urlParsedRequest = parser.parse(urlContentParser);
+        HttpRequest urlParsedRequest = HttpRequest.Parser.parse(urlContentParser);
 
         WatcherParams params = WatcherParams.builder().hideSecrets(false).build();
         XContentBuilder xContentBuilder = builder.build().toXContent(jsonBuilder(), params);
         XContentParser xContentParser = createParser(xContentBuilder);
         xContentParser.nextToken();
-        HttpRequest parsedRequest = parser.parse(xContentParser);
+        HttpRequest parsedRequest = HttpRequest.Parser.parse(xContentParser);
 
         assertThat(parsedRequest, is(urlParsedRequest));
     }
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/chain/ChainInputTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/chain/ChainInputTests.java
index cc19cef7b47..2e1e7858f16 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/chain/ChainInputTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/chain/ChainInputTests.java
@@ -22,7 +22,7 @@ import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
 import org.elasticsearch.xpack.core.watcher.input.Input;
 import org.elasticsearch.xpack.core.watcher.watch.Payload;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.condition.ScriptCondition;
 import org.elasticsearch.xpack.watcher.input.InputFactory;
 import org.elasticsearch.xpack.watcher.input.InputRegistry;
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/http/HttpInputTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/http/HttpInputTests.java
index dd13fcb14a2..7d81ff2203d 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/http/HttpInputTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/input/http/HttpInputTests.java
@@ -28,10 +28,7 @@ import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
 import org.elasticsearch.xpack.watcher.common.http.Scheme;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.input.InputBuilders;
@@ -73,8 +70,7 @@ public class HttpInputTests extends ESTestCase {
     public void init() throws Exception {
         httpClient = mock(HttpClient.class);
         templateEngine = mock(TextTemplateEngine.class);
-        HttpAuthRegistry registry = new HttpAuthRegistry(singletonMap("basic", new BasicAuthFactory(null)));
-        httpParser = new HttpInputFactory(Settings.EMPTY, httpClient, templateEngine, new HttpRequestTemplate.Parser(registry));
+        httpParser = new HttpInputFactory(Settings.EMPTY, httpClient, templateEngine);
     }
 
     public void testExecute() throws Exception {
@@ -158,7 +154,7 @@ public class HttpInputTests extends ESTestCase {
                 randomBoolean() ? new MapBuilder<String, TextTemplate>().put("a", new TextTemplate("b")).map() : null;
         Map<String, TextTemplate> headers =
                 randomBoolean() ? new MapBuilder<String, TextTemplate>().put("c", new TextTemplate("d")).map() : null;
-        HttpAuth auth = randomBoolean() ? new BasicAuth("username", "password".toCharArray()) : null;
+        BasicAuth auth = randomBoolean() ? new BasicAuth("username", "password".toCharArray()) : null;
         HttpRequestTemplate.Builder requestBuilder = HttpRequestTemplate.builder(host, port)
                 .scheme(scheme)
                 .method(httpMethod)
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParserTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParserTests.java
index ef71a115743..2b0e632b0ca 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParserTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/HttpEmailAttachementParserTests.java
@@ -19,9 +19,6 @@ import org.elasticsearch.xpack.watcher.common.http.HttpClient;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
@@ -34,7 +31,6 @@ import java.util.List;
 import java.util.Map;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Collections.singletonMap;
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContextBuilder;
 import static org.hamcrest.Matchers.hasSize;
@@ -45,20 +41,17 @@ import static org.mockito.Mockito.when;
 
 public class HttpEmailAttachementParserTests extends ESTestCase {
 
-    private HttpRequestTemplate.Parser httpRequestTemplateParser;
     private HttpClient httpClient;
     private EmailAttachmentsParser emailAttachmentsParser;
     private Map<String, EmailAttachmentParser> attachmentParsers;
 
     @Before
     public void init() throws Exception {
-        HttpAuthRegistry authRegistry = new HttpAuthRegistry(singletonMap(BasicAuth.TYPE, new BasicAuthFactory(null)));
-        httpRequestTemplateParser = new HttpRequestTemplate.Parser(authRegistry);
         httpClient = mock(HttpClient.class);
 
         attachmentParsers = new HashMap<>();
         attachmentParsers.put(HttpEmailAttachementParser.TYPE,
-                new HttpEmailAttachementParser(httpClient, httpRequestTemplateParser, new MockTextTemplateEngine()));
+                new HttpEmailAttachementParser(httpClient, new MockTextTemplateEngine()));
         emailAttachmentsParser = new EmailAttachmentsParser(attachmentParsers);
     }
 
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java
index e8678f5c40e..97907bbef8a 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java
@@ -8,7 +8,6 @@ package org.elasticsearch.xpack.watcher.notification.email.attachment;
 import com.fasterxml.jackson.core.io.JsonEOFException;
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.collect.MapBuilder;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -24,11 +23,7 @@ import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
 import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthFactory;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.notification.email.Attachment;
@@ -69,19 +64,13 @@ public class ReportingAttachmentParserTests extends ESTestCase {
     private Map<String, EmailAttachmentParser> attachmentParsers = new HashMap<>();
     private EmailAttachmentsParser emailAttachmentsParser;
     private ReportingAttachmentParser reportingAttachmentParser;
-    private HttpAuthRegistry authRegistry;
     private MockTextTemplateEngine templateEngine = new MockTextTemplateEngine();
     private String dashboardUrl = "http://www.example.org/ovb/api/reporting/generate/dashboard/My-Dashboard";
 
     @Before
     public void init() throws Exception {
         httpClient = mock(HttpClient.class);
-
-        Map<String, HttpAuthFactory> factories = MapBuilder.<String, HttpAuthFactory>newMapBuilder()
-                .put("basic", new BasicAuthFactory(null))
-                .immutableMap();
-        authRegistry = new HttpAuthRegistry(factories);
-        reportingAttachmentParser = new ReportingAttachmentParser(Settings.EMPTY, httpClient, templateEngine, authRegistry);
+        reportingAttachmentParser = new ReportingAttachmentParser(Settings.EMPTY, httpClient, templateEngine);
 
         attachmentParsers.put(ReportingAttachmentParser.TYPE, reportingAttachmentParser);
         emailAttachmentsParser = new EmailAttachmentsParser(attachmentParsers);
@@ -113,7 +102,7 @@ public class ReportingAttachmentParserTests extends ESTestCase {
             builder.field("inline", true);
         }
 
-        HttpAuth auth = null;
+        BasicAuth auth = null;
         boolean withAuth = randomBoolean();
         boolean isPasswordEncrypted = randomBoolean();
         if (withAuth) {
@@ -318,9 +307,8 @@ public class ReportingAttachmentParserTests extends ESTestCase {
         assertThat(allRequests, hasSize(3));
         for (HttpRequest request : allRequests) {
             assertThat(request.auth(), is(notNullValue()));
-            assertThat(request.auth().type(), is("basic"));
             assertThat(request.auth(), instanceOf(BasicAuth.class));
-            BasicAuth basicAuth = (BasicAuth) request.auth();
+            BasicAuth basicAuth = request.auth();
             assertThat(basicAuth.getUsername(), is("foo"));
         }
     }
@@ -351,7 +339,7 @@ public class ReportingAttachmentParserTests extends ESTestCase {
                 .put(ReportingAttachmentParser.RETRIES_SETTING.getKey(), retries)
                 .build();
 
-        reportingAttachmentParser = new ReportingAttachmentParser(settings, httpClient, templateEngine, authRegistry);
+        reportingAttachmentParser = new ReportingAttachmentParser(settings, httpClient, templateEngine);
         expectThrows(ElasticsearchException.class, () ->
                 reportingAttachmentParser.toAttachment(createWatchExecutionContext(), Payload.EMPTY, attachment));
 
@@ -374,7 +362,7 @@ public class ReportingAttachmentParserTests extends ESTestCase {
         ReportingAttachment attachment = new ReportingAttachment("foo", "http://www.example.org/REPLACEME", randomBoolean(),
                 TimeValue.timeValueMillis(1), 10, new BasicAuth("foo", "bar".toCharArray()), null);
         reportingAttachmentParser = new ReportingAttachmentParser(Settings.EMPTY, httpClient,
-                replaceHttpWithHttpsTemplateEngine, authRegistry);
+                replaceHttpWithHttpsTemplateEngine);
         reportingAttachmentParser.toAttachment(createWatchExecutionContext(), Payload.EMPTY, attachment);
 
         ArgumentCaptor<HttpRequest> requestArgumentCaptor = ArgumentCaptor.forClass(HttpRequest.class);
@@ -391,7 +379,7 @@ public class ReportingAttachmentParserTests extends ESTestCase {
 
         Settings invalidSettings = Settings.builder().put("xpack.notification.reporting.retries", -10).build();
         e = expectThrows(IllegalArgumentException.class,
-                () -> new ReportingAttachmentParser(invalidSettings, httpClient, templateEngine, authRegistry));
+                () -> new ReportingAttachmentParser(invalidSettings, httpClient, templateEngine));
         assertThat(e.getMessage(), is("Failed to parse value [-10] for setting [xpack.notification.reporting.retries] must be >= 0"));
     }
 
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatAccountsTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatAccountsTests.java
index b793bf92023..795f5aaacc7 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatAccountsTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/hipchat/HipChatAccountsTests.java
@@ -12,12 +12,9 @@ import org.elasticsearch.xpack.watcher.common.http.HttpClient;
 import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
-import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
 import org.junit.Before;
 import org.mockito.ArgumentCaptor;
 
-import java.util.HashMap;
 import java.util.HashSet;
 
 import static org.hamcrest.Matchers.is;
@@ -40,11 +37,7 @@ public class HipChatAccountsTests extends ESTestCase {
                 new HashSet<>(HipChatService.getSettings())));
         HipChatAccount account = service.getAccount("account1");
 
-        HipChatMessage.Template template = new HipChatMessage.Template.Builder(new TextTemplate("foo"))
-                .addRooms(new TextTemplate("room"))
-                .setFrom("from")
-                .build();
-        HipChatMessage hipChatMessage = template.render(new MockTextTemplateEngine(), new HashMap<>());
+        HipChatMessage hipChatMessage = new HipChatMessage("body", new String[]{"rooms"}, null, "from", null, null, null);
 
         ArgumentCaptor<HttpRequest> argumentCaptor = ArgumentCaptor.forClass(HttpRequest.class);
         when(httpClient.execute(argumentCaptor.capture())).thenReturn(new HttpResponse(200));
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/jira/JiraIssueTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/jira/JiraIssueTests.java
index 8e615d76050..e3c4d79f6d0 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/jira/JiraIssueTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/jira/JiraIssueTests.java
@@ -14,14 +14,11 @@ import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
 import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
 import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import static java.util.Collections.singletonMap;
 import static org.elasticsearch.common.xcontent.XContentFactory.cborBuilder;
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 import static org.elasticsearch.common.xcontent.XContentFactory.smileBuilder;
@@ -43,19 +40,19 @@ public class JiraIssueTests extends ESTestCase {
 
             Map<String, Object> parsedFields = null;
             Map<String, Object> parsedResult = null;
-    
+
             HttpRequest parsedRequest = null;
             HttpResponse parsedResponse = null;
             String parsedAccount = null;
             String parsedReason = null;
-    
+
             try (XContentParser parser = createParser(builder)) {
                 assertNull(parser.currentToken());
                 parser.nextToken();
-    
+
                 XContentParser.Token token = parser.currentToken();
                 assertThat(token, is(XContentParser.Token.START_OBJECT));
-    
+
                 String currentFieldName = null;
                 while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
                     if (token == XContentParser.Token.FIELD_NAME) {
@@ -65,9 +62,7 @@ public class JiraIssueTests extends ESTestCase {
                     } else if ("result".equals(currentFieldName)) {
                         parsedResult = parser.map();
                     } else if ("request".equals(currentFieldName)) {
-                        HttpAuthRegistry registry = new HttpAuthRegistry(singletonMap(BasicAuth.TYPE, new BasicAuthFactory(null)));
-                        HttpRequest.Parser httpRequestParser = new HttpRequest.Parser(registry);
-                        parsedRequest = httpRequestParser.parse(parser);
+                        parsedRequest = HttpRequest.Parser.parse(parser);
                     } else if ("response".equals(currentFieldName)) {
                         parsedResponse = HttpResponse.parse(parser);
                     } else if ("fields".equals(currentFieldName)) {
@@ -79,7 +74,7 @@ public class JiraIssueTests extends ESTestCase {
                     }
                 }
             }
-            
+
             assertThat(parsedAccount, equalTo(issue.getAccount()));
             assertThat(parsedFields, equalTo(issue.getFields()));
             if (issue.successful()) {
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventTests.java
new file mode 100644
index 00000000000..3638d5f85d9
--- /dev/null
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/IncidentEventTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+package org.elasticsearch.xpack.watcher.notification.pagerduty;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.rest.yaml.ObjectPath;
+import org.elasticsearch.xpack.core.watcher.watch.Payload;
+import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.hamcrest.Matchers.equalTo;
+
+public class IncidentEventTests extends ESTestCase {
+
+    public void testPagerDutyXContent() throws IOException {
+
+        String serviceKey = randomAlphaOfLength(3);
+        boolean attachPayload = randomBoolean();
+        Payload payload = null;
+        if (attachPayload) {
+            payload = new Payload.Simple(Collections.singletonMap(randomAlphaOfLength(3), randomAlphaOfLength(3)));
+        }
+        String watchId = randomAlphaOfLength(3);
+        String description = randomAlphaOfLength(3);
+        String eventType = randomAlphaOfLength(3);
+        String incidentKey = rarely() ? null : randomAlphaOfLength(3);
+        String client = rarely() ? null : randomAlphaOfLength(3);
+        String clientUrl = rarely() ? null : randomAlphaOfLength(3);
+        String account = rarely() ? null : randomAlphaOfLength(3);
+
+        IncidentEventContext[] contexts = null;
+        List<IncidentEventContext> links = new ArrayList<>();
+        List<IncidentEventContext> images = new ArrayList<>();
+
+        if (randomBoolean()) {
+            int numContexts = randomIntBetween(0, 3);
+            contexts = new IncidentEventContext[numContexts];
+            for (int i = 0; i < numContexts; i++) {
+                if (randomBoolean()) {
+                    contexts[i] = IncidentEventContext.link("href", "text");
+                    links.add(contexts[i]);
+                } else {
+                    contexts[i] = IncidentEventContext.image("src", "href", "alt");
+                    images.add(contexts[i]);
+                }
+            }
+        }
+
+        HttpProxy proxy = rarely() ? null : HttpProxy.NO_PROXY;
+
+        IncidentEvent event = new IncidentEvent(description, eventType, incidentKey, client, clientUrl, account,
+            attachPayload, contexts, proxy);
+
+        XContentBuilder jsonBuilder = jsonBuilder();
+        jsonBuilder.startObject(); // since its a snippet
+        event.buildAPIXContent(jsonBuilder, ToXContent.EMPTY_PARAMS, serviceKey, payload, watchId);
+        jsonBuilder.endObject();
+        XContentParser parser = createParser(jsonBuilder);
+        parser.nextToken();
+
+        ObjectPath objectPath = ObjectPath.createFromXContent(jsonBuilder.contentType().xContent(), BytesReference.bytes(jsonBuilder));
+
+        String actualServiceKey = objectPath.evaluate(IncidentEvent.Fields.ROUTING_KEY.getPreferredName());
+        String actualWatchId = objectPath.evaluate(IncidentEvent.Fields.PAYLOAD.getPreferredName()
+            + "." + IncidentEvent.Fields.SOURCE.getPreferredName());
+        if (actualWatchId == null) {
+            actualWatchId = "watcher"; // hardcoded if the SOURCE is null
+        }
+        String actualDescription = objectPath.evaluate(IncidentEvent.Fields.PAYLOAD.getPreferredName()
+            + "." + IncidentEvent.Fields.SUMMARY.getPreferredName());
+        String actualEventType = objectPath.evaluate(IncidentEvent.Fields.EVENT_ACTION.getPreferredName());
+        String actualIncidentKey = objectPath.evaluate(IncidentEvent.Fields.DEDUP_KEY.getPreferredName());
+        String actualClient = objectPath.evaluate(IncidentEvent.Fields.CLIENT.getPreferredName());
+        String actualClientUrl = objectPath.evaluate(IncidentEvent.Fields.CLIENT_URL.getPreferredName());
+        String actualSeverity = objectPath.evaluate(IncidentEvent.Fields.PAYLOAD.getPreferredName()
+            + "." + IncidentEvent.Fields.SEVERITY.getPreferredName());
+        Map<String, Object> payloadDetails = objectPath.evaluate("payload.custom_details.payload");
+        Payload actualPayload = null;
+
+        if (payloadDetails != null) {
+            actualPayload = new Payload.Simple(payloadDetails);
+        }
+
+        List<IncidentEventContext> actualLinks = new ArrayList<>();
+        List<Map<String, String>> linkMap = (List<Map<String, String>>) objectPath.evaluate(IncidentEvent.Fields.LINKS.getPreferredName());
+        if (linkMap != null) {
+            for (Map<String, String> iecValue : linkMap) {
+                actualLinks.add(IncidentEventContext.link(iecValue.get("href"), iecValue.get("text")));
+            }
+        }
+
+        List<IncidentEventContext> actualImages = new ArrayList<>();
+        List<Map<String, String>> imgMap = (List<Map<String, String>>) objectPath.evaluate(IncidentEvent.Fields.IMAGES.getPreferredName());
+        if (imgMap != null) {
+            for (Map<String, String> iecValue : imgMap) {
+                actualImages.add(IncidentEventContext.image(iecValue.get("src"), iecValue.get("href"), iecValue.get("alt")));
+            }
+        }
+
+        // assert the actuals were the same as expected
+        assertThat(serviceKey, equalTo(actualServiceKey));
+        assertThat(eventType, equalTo(actualEventType));
+        assertThat(incidentKey, equalTo(actualIncidentKey));
+        assertThat(description, equalTo(actualDescription));
+        assertThat(watchId, equalTo(actualWatchId));
+        assertThat("critical", equalTo(actualSeverity));
+        assertThat(client, equalTo(actualClient));
+        assertThat(clientUrl, equalTo(actualClientUrl));
+        assertThat(links, equalTo(actualLinks));
+        assertThat(images, equalTo(actualImages));
+        assertThat(payload, equalTo(actualPayload));
+    }
+}
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccountsTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccountsTests.java
index d70badc4bec..1e88c696142 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccountsTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/pagerduty/PagerDutyAccountsTests.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -48,7 +49,7 @@ public class PagerDutyAccountsTests extends ESTestCase {
 
         HttpProxy proxy = new HttpProxy("localhost", 8080);
         IncidentEvent event = new IncidentEvent("foo", null, null, null, null, account.getName(), true, null, proxy);
-        account.send(event, Payload.EMPTY);
+        account.send(event, Payload.EMPTY, null);
 
         HttpRequest request = argumentCaptor.getValue();
         assertThat(request.proxy(), is(proxy));
@@ -72,11 +73,13 @@ public class PagerDutyAccountsTests extends ESTestCase {
                         "https://www.elastic.co/products/x-pack/alerting", "X-Pack-Alerting website link with log")
         };
         IncidentEvent event = new IncidentEvent("foo", null, null, null, null, account.getName(), true, contexts, HttpProxy.NO_PROXY);
-        account.send(event, Payload.EMPTY);
+        account.send(event, Payload.EMPTY, null);
 
         HttpRequest request = argumentCaptor.getValue();
         ObjectPath source = ObjectPath.createFromXContent(JsonXContent.jsonXContent, new BytesArray(request.body()));
-        assertThat(source.evaluate("contexts"), notNullValue());
+        assertThat(source.evaluate("contexts"), nullValue());
+        assertThat(source.evaluate("links"), notNullValue());
+        assertThat(source.evaluate("images"), notNullValue());
     }
 
     private void addAccountSettings(String name, Settings.Builder builder) {
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java
index 4388b20f520..3201a69b486 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/support/WatcherIndexTemplateRegistryTests.java
@@ -8,7 +8,7 @@ package org.elasticsearch.xpack.watcher.support;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
-import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.AdminClient;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.IndicesAdminClient;
@@ -65,8 +65,8 @@ public class WatcherIndexTemplateRegistryTests extends ESTestCase {
         when(adminClient.indices()).thenReturn(indicesAdminClient);
         when(client.admin()).thenReturn(adminClient);
         doAnswer(invocationOnMock -> {
-            ActionListener<PutIndexTemplateResponse> listener =
-                    (ActionListener<PutIndexTemplateResponse>) invocationOnMock.getArguments()[1];
+            ActionListener<AcknowledgedResponse> listener =
+                    (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
             listener.onResponse(new TestPutIndexTemplateResponse(true));
             return null;
         }).when(indicesAdminClient).putTemplate(any(PutIndexTemplateRequest.class), any(ActionListener.class));
@@ -173,7 +173,7 @@ public class WatcherIndexTemplateRegistryTests extends ESTestCase {
         return ClusterState.builder(new ClusterName("foo")).metaData(metaDataBuilder.build()).build();
     }
 
-    private static class TestPutIndexTemplateResponse extends PutIndexTemplateResponse {
+    private static class TestPutIndexTemplateResponse extends AcknowledgedResponse {
         TestPutIndexTemplateResponse(boolean acknowledged) {
             super(acknowledged);
         }
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java
index 07fb45936e9..0de8fc1ee4b 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java
@@ -22,9 +22,8 @@ import org.elasticsearch.xpack.core.watcher.transport.actions.execute.ExecuteWat
 import org.elasticsearch.xpack.core.watcher.transport.actions.get.GetWatchResponse;
 import org.elasticsearch.xpack.core.watcher.trigger.TriggerEvent;
 import org.elasticsearch.xpack.core.watcher.watch.Watch;
+import org.elasticsearch.xpack.watcher.common.http.BasicAuth;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.ApplicableBasicAuth;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
 import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
 import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
 import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent;
@@ -32,6 +31,8 @@ import org.joda.time.DateTime;
 import org.junit.After;
 import org.junit.Before;
 
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
 import java.util.Map;
 
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@@ -154,7 +155,7 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC
 
         assertThat(webServer.requests(), hasSize(1));
         assertThat(webServer.requests().get(0).getHeader("Authorization"),
-                is(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray())));
+                is(headerValue(USERNAME, PASSWORD.toCharArray())));
 
         // now trigger the by the scheduler and make sure that the password is also correctly transmitted
         webServer.enqueue(new MockResponse().setResponseCode(200).setBody(
@@ -162,7 +163,7 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC
         timeWarp().trigger("_id");
         assertThat(webServer.requests(), hasSize(2));
         assertThat(webServer.requests().get(1).getHeader("Authorization"),
-            is(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray())));
+            is(headerValue(USERNAME, PASSWORD.toCharArray())));
     }
 
     public void testWebhookAction() throws Exception {
@@ -251,6 +252,10 @@ public class HttpSecretsIntegrationTests extends AbstractWatcherIntegrationTestC
 
         assertThat(webServer.requests(), hasSize(1));
         assertThat(webServer.requests().get(0).getHeader("Authorization"),
-                is(ApplicableBasicAuth.headerValue(USERNAME, PASSWORD.toCharArray())));
+                is(headerValue(USERNAME, PASSWORD.toCharArray())));
+    }
+
+    private String headerValue(String username, char[] password) {
+        return "Basic " + Base64.getEncoder().encodeToString((username + ":" + new String(password)).getBytes(StandardCharsets.UTF_8));
     }
 }
diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java
index df96a802166..8029b1c7a49 100644
--- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java
+++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/watch/WatchTests.java
@@ -61,8 +61,6 @@ import org.elasticsearch.xpack.watcher.actions.webhook.WebhookActionFactory;
 import org.elasticsearch.xpack.watcher.common.http.HttpClient;
 import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
 import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
-import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
-import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
 import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
 import org.elasticsearch.xpack.watcher.condition.AlwaysConditionTests;
@@ -160,7 +158,6 @@ public class WatchTests extends ESTestCase {
     private EmailService emailService;
     private TextTemplateEngine templateEngine;
     private HtmlSanitizer htmlSanitizer;
-    private HttpAuthRegistry authRegistry;
     private XPackLicenseState licenseState;
     private Logger logger;
     private Settings settings = Settings.EMPTY;
@@ -175,7 +172,6 @@ public class WatchTests extends ESTestCase {
         templateEngine = mock(TextTemplateEngine.class);
         htmlSanitizer = mock(HtmlSanitizer.class);
         licenseState = mock(XPackLicenseState.class);
-        authRegistry = new HttpAuthRegistry(singletonMap("basic", new BasicAuthFactory(null)));
         logger = Loggers.getLogger(WatchTests.class);
         searchTemplateService = mock(WatcherSearchTemplateService.class);
     }
@@ -623,8 +619,7 @@ public class WatchTests extends ESTestCase {
                     parsers.put(IndexAction.TYPE, new IndexActionFactory(settings, client));
                     break;
                 case WebhookAction.TYPE:
-                    parsers.put(WebhookAction.TYPE, new WebhookActionFactory(settings,  httpClient,
-                            new HttpRequestTemplate.Parser(authRegistry), templateEngine));
+                    parsers.put(WebhookAction.TYPE, new WebhookActionFactory(settings, httpClient, templateEngine));
                     break;
                 case LoggingAction.TYPE:
                     parsers.put(LoggingAction.TYPE, new LoggingActionFactory(settings, new MockTextTemplateEngine()));
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/license/DeleteLicenseResponse.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/license/DeleteLicenseResponse.java
deleted file mode 100644
index 596af7f2f90..00000000000
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/license/DeleteLicenseResponse.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.protocol.xpack.license;
-
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.common.xcontent.XContentParser;
-
-public class DeleteLicenseResponse extends AcknowledgedResponse {
-
-    public DeleteLicenseResponse() {
-    }
-
-    public DeleteLicenseResponse(boolean acknowledged) {
-        super(acknowledged);
-    }
-
-    public static DeleteLicenseResponse fromXContent(XContentParser parser) {
-        return new DeleteLicenseResponse(parseAcknowledged(parser));
-    }
-}
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/AnalysisConfig.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/AnalysisConfig.java
index 1c106f78208..00fa1bdd47f 100644
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/AnalysisConfig.java
+++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/AnalysisConfig.java
@@ -333,7 +333,7 @@ public class AnalysisConfig implements ToXContentObject {
             this.multivariateByFields = analysisConfig.multivariateByFields;
         }
 
-        public void setDetectors(List<Detector> detectors) {
+        public Builder setDetectors(List<Detector> detectors) {
             Objects.requireNonNull(detectors,  "[" + DETECTORS.getPreferredName() + "] must not be null");
             // We always assign sequential IDs to the detectors that are correct for this analysis config
             int detectorIndex = 0;
@@ -344,50 +344,62 @@ public class AnalysisConfig implements ToXContentObject {
                 sequentialIndexDetectors.add(builder.build());
             }
             this.detectors = sequentialIndexDetectors;
+            return this;
         }
 
-        public void setDetector(int detectorIndex, Detector detector) {
+        public Builder setDetector(int detectorIndex, Detector detector) {
             detectors.set(detectorIndex, detector);
+            return this;
         }
 
-        public void setBucketSpan(TimeValue bucketSpan) {
+        public Builder setBucketSpan(TimeValue bucketSpan) {
             this.bucketSpan = bucketSpan;
+            return this;
         }
 
-        public void setLatency(TimeValue latency) {
+        public Builder setLatency(TimeValue latency) {
             this.latency = latency;
+            return this;
         }
 
-        public void setCategorizationFieldName(String categorizationFieldName) {
+        public Builder setCategorizationFieldName(String categorizationFieldName) {
             this.categorizationFieldName = categorizationFieldName;
+            return this;
         }
 
-        public void setCategorizationFilters(List<String> categorizationFilters) {
+        public Builder setCategorizationFilters(List<String> categorizationFilters) {
             this.categorizationFilters = categorizationFilters;
+            return this;
         }
 
-        public void setCategorizationAnalyzerConfig(CategorizationAnalyzerConfig categorizationAnalyzerConfig) {
+        public Builder setCategorizationAnalyzerConfig(CategorizationAnalyzerConfig categorizationAnalyzerConfig) {
             this.categorizationAnalyzerConfig = categorizationAnalyzerConfig;
+            return this;
         }
 
-        public void setSummaryCountFieldName(String summaryCountFieldName) {
+        public Builder setSummaryCountFieldName(String summaryCountFieldName) {
             this.summaryCountFieldName = summaryCountFieldName;
+            return this;
         }
 
-        public void setInfluencers(List<String> influencers) {
+        public Builder setInfluencers(List<String> influencers) {
             this.influencers = Objects.requireNonNull(influencers, INFLUENCERS.getPreferredName());
+            return this;
         }
 
-        public void setOverlappingBuckets(Boolean overlappingBuckets) {
+        public Builder setOverlappingBuckets(Boolean overlappingBuckets) {
             this.overlappingBuckets = overlappingBuckets;
+            return this;
         }
 
-        public void setResultFinalizationWindow(Long resultFinalizationWindow) {
+        public Builder setResultFinalizationWindow(Long resultFinalizationWindow) {
             this.resultFinalizationWindow = resultFinalizationWindow;
+            return this;
         }
 
-        public void setMultivariateByFields(Boolean multivariateByFields) {
+        public Builder setMultivariateByFields(Boolean multivariateByFields) {
             this.multivariateByFields = multivariateByFields;
+            return this;
         }
 
         public AnalysisConfig build() {
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/DataDescription.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/DataDescription.java
index f469512f649..a3f8c2563b2 100644
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/DataDescription.java
+++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/DataDescription.java
@@ -243,28 +243,34 @@ public class DataDescription implements ToXContentObject {
         private Character fieldDelimiter;
         private Character quoteCharacter;
 
-        public void setFormat(DataFormat format) {
+        public Builder setFormat(DataFormat format) {
             dataFormat = Objects.requireNonNull(format);
+            return this;
         }
 
-        private void setFormat(String format) {
+        private Builder setFormat(String format) {
             setFormat(DataFormat.forString(format));
+            return this;
         }
 
-        public void setTimeField(String fieldName) {
+        public Builder setTimeField(String fieldName) {
             timeFieldName = Objects.requireNonNull(fieldName);
+            return this;
         }
 
-        public void setTimeFormat(String format) {
+        public Builder setTimeFormat(String format) {
             timeFormat = Objects.requireNonNull(format);
+            return this;
         }
 
-        public void setFieldDelimiter(Character delimiter) {
+        public Builder setFieldDelimiter(Character delimiter) {
             fieldDelimiter = delimiter;
+            return this;
         }
 
-        public void setQuoteCharacter(Character value) {
+        public Builder setQuoteCharacter(Character value) {
             quoteCharacter = value;
+            return this;
         }
 
         public DataDescription build() {
diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/license/DeleteLicenseResponseTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/license/DeleteLicenseResponseTests.java
deleted file mode 100644
index f4caa1f4242..00000000000
--- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/license/DeleteLicenseResponseTests.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.protocol.xpack.license;
-
-import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractStreamableXContentTestCase;
-
-public class DeleteLicenseResponseTests extends AbstractStreamableXContentTestCase<DeleteLicenseResponse> {
-
-    @Override
-    protected boolean supportsUnknownFields() {
-        return true;
-    }
-
-    @Override
-    protected DeleteLicenseResponse createTestInstance() {
-        return new DeleteLicenseResponse(randomBoolean());
-    }
-
-    @Override
-    protected DeleteLicenseResponse doParseInstance(XContentParser parser) {
-        return DeleteLicenseResponse.fromXContent(parser);
-    }
-
-    @Override
-    protected DeleteLicenseResponse createBlankInstance() {
-        return new DeleteLicenseResponse();
-    }
-
-    @Override
-    protected DeleteLicenseResponse mutateInstance(DeleteLicenseResponse response) {
-        return new DeleteLicenseResponse(!response.isAcknowledged());
-    }
-}
diff --git a/x-pack/qa/audit-tests/src/test/java/org/elasticsearch/xpack/security/audit/IndexAuditIT.java b/x-pack/qa/audit-tests/src/test/java/org/elasticsearch/xpack/security/audit/IndexAuditIT.java
index a8155b785b3..c0111e57c74 100644
--- a/x-pack/qa/audit-tests/src/test/java/org/elasticsearch/xpack/security/audit/IndexAuditIT.java
+++ b/x-pack/qa/audit-tests/src/test/java/org/elasticsearch/xpack/security/audit/IndexAuditIT.java
@@ -7,9 +7,9 @@ package org.elasticsearch.xpack.security.audit;
 
 import com.carrotsearch.hppc.cursors.ObjectCursor;
 import org.apache.http.message.BasicHeader;
-import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
 import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.RequestOptions;
@@ -28,8 +28,8 @@ import org.elasticsearch.test.ESIntegTestCase;
 import org.elasticsearch.test.TestCluster;
 import org.elasticsearch.xpack.core.XPackClientPlugin;
 import org.elasticsearch.xpack.core.security.SecurityField;
-import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
 import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
+import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -132,7 +132,7 @@ public class IndexAuditIT extends ESIntegTestCase {
         awaitIndexTemplateCreation();
 
         // delete the template
-        DeleteIndexTemplateResponse deleteResponse = client().admin().indices()
+        AcknowledgedResponse deleteResponse = client().admin().indices()
                 .prepareDeleteTemplate(IndexAuditTrail.INDEX_TEMPLATE_NAME).execute().actionGet();
         assertThat(deleteResponse.isAcknowledged(), is(true));
         awaitIndexTemplateCreation();
diff --git a/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsIT.java b/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsIT.java
index 23bd9dc8495..ccef7c3f2e1 100644
--- a/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsIT.java
+++ b/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsIT.java
@@ -9,6 +9,7 @@ import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.admin.cluster.node.hotthreads.NodeHotThreads;
 import org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
 import org.elasticsearch.common.util.concurrent.ConcurrentMapLong;
@@ -186,7 +187,7 @@ public class DatafeedJobsIT extends MlNativeAutodetectIntegTestCase {
             try {
                 DeleteDatafeedAction.Request request = new DeleteDatafeedAction.Request(datafeedId);
                 request.setForce(true);
-                DeleteDatafeedAction.Response response = client().execute(DeleteDatafeedAction.INSTANCE, request).actionGet();
+                AcknowledgedResponse response = client().execute(DeleteDatafeedAction.INSTANCE, request).actionGet();
                 if (response.isAcknowledged()) {
                     GetDatafeedsStatsAction.Request statsRequest = new GetDatafeedsStatsAction.Request(datafeedId);
                     expectThrows(ResourceNotFoundException.class,
diff --git a/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java b/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java
index 74a026ed5ad..1fd0eddf41c 100644
--- a/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java
+++ b/x-pack/qa/ml-native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java
@@ -8,6 +8,7 @@ package org.elasticsearch.xpack.ml.integration;
 import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
 import org.elasticsearch.action.get.GetResponse;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.cluster.ClusterModule;
 import org.elasticsearch.cluster.ClusterState;
@@ -213,7 +214,7 @@ abstract class MlNativeAutodetectIntegTestCase extends ESIntegTestCase {
         return client().execute(PutJobAction.INSTANCE, request).actionGet();
     }
 
-    protected OpenJobAction.Response openJob(String jobId) {
+    protected AcknowledgedResponse openJob(String jobId) {
         OpenJobAction.Request request = new OpenJobAction.Request(jobId);
         return client().execute(OpenJobAction.INSTANCE, request).actionGet();
     }
@@ -234,7 +235,7 @@ abstract class MlNativeAutodetectIntegTestCase extends ESIntegTestCase {
         return client().execute(UpdateJobAction.INSTANCE, request).actionGet();
     }
 
-    protected DeleteJobAction.Response deleteJob(String jobId) {
+    protected AcknowledgedResponse deleteJob(String jobId) {
         DeleteJobAction.Request request = new DeleteJobAction.Request(jobId);
         return client().execute(DeleteJobAction.INSTANCE, request).actionGet();
     }
@@ -249,12 +250,12 @@ abstract class MlNativeAutodetectIntegTestCase extends ESIntegTestCase {
         return client().execute(StopDatafeedAction.INSTANCE, request).actionGet();
     }
 
-    protected DeleteDatafeedAction.Response deleteDatafeed(String datafeedId) {
+    protected AcknowledgedResponse deleteDatafeed(String datafeedId) {
         DeleteDatafeedAction.Request request = new DeleteDatafeedAction.Request(datafeedId);
         return client().execute(DeleteDatafeedAction.INSTANCE, request).actionGet();
     }
 
-    protected StartDatafeedAction.Response startDatafeed(String datafeedId, long start, Long end) {
+    protected AcknowledgedResponse startDatafeed(String datafeedId, long start, Long end) {
         StartDatafeedAction.Request request = new StartDatafeedAction.Request(datafeedId, start);
         request.getParams().setEndTime(end);
         return client().execute(StartDatafeedAction.INSTANCE, request).actionGet();
diff --git a/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/mixed_cluster/30_ml_jobs_crud.yml b/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/mixed_cluster/30_ml_jobs_crud.yml
index ba0f4d5091e..cb036b9d13a 100644
--- a/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/mixed_cluster/30_ml_jobs_crud.yml
+++ b/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/mixed_cluster/30_ml_jobs_crud.yml
@@ -1,3 +1,9 @@
+---
+setup:
+    - skip:
+        version: "all"
+        reason: "Temporarily disabled while backporting https://github.com/elastic/elasticsearch/pull/32816"
+
 ---
 "Test get old cluster job":
   - do:
diff --git a/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/old_cluster/30_ml_jobs_crud.yml b/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/old_cluster/30_ml_jobs_crud.yml
index 3a3334f6907..061a242a78d 100644
--- a/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/old_cluster/30_ml_jobs_crud.yml
+++ b/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/old_cluster/30_ml_jobs_crud.yml
@@ -1,3 +1,9 @@
+---
+setup:
+    - skip:
+        version: "all"
+        reason: "Temporarily disabled while backporting https://github.com/elastic/elasticsearch/pull/32816"
+
 ---
 "Put job on the old cluster and post some data":
 
diff --git a/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/upgraded_cluster/30_ml_jobs_crud.yml b/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/upgraded_cluster/30_ml_jobs_crud.yml
index bb47524b41d..1da16e79cbe 100644
--- a/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/upgraded_cluster/30_ml_jobs_crud.yml
+++ b/x-pack/qa/rolling-upgrade/src/test/resources/rest-api-spec/test/upgraded_cluster/30_ml_jobs_crud.yml
@@ -1,4 +1,8 @@
 setup:
+ - skip:
+     version: "all"
+     reason: "Temporarily disabled while backporting https://github.com/elastic/elasticsearch/pull/32816"
+
  - do:
      cluster.health:
         wait_for_status: green
diff --git a/x-pack/qa/transport-client-tests/src/test/java/org/elasticsearch/xpack/ml/client/MLTransportClientIT.java b/x-pack/qa/transport-client-tests/src/test/java/org/elasticsearch/xpack/ml/client/MLTransportClientIT.java
index 406b354e574..dceb2d1398a 100644
--- a/x-pack/qa/transport-client-tests/src/test/java/org/elasticsearch/xpack/ml/client/MLTransportClientIT.java
+++ b/x-pack/qa/transport-client-tests/src/test/java/org/elasticsearch/xpack/ml/client/MLTransportClientIT.java
@@ -5,6 +5,7 @@
  */
 package org.elasticsearch.xpack.ml.client;
 
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.unit.TimeValue;
@@ -62,7 +63,7 @@ public class MLTransportClientIT extends ESXPackSmokeClientTestCase {
         assertThat(getJobResponse.getResponse().count(), equalTo(1L));
 
         // Open job POST data, flush, close and check a result
-        OpenJobAction.Response openJobResponse = mlClient.openJob(new OpenJobAction.Request(jobId)).actionGet();
+        AcknowledgedResponse openJobResponse = mlClient.openJob(new OpenJobAction.Request(jobId)).actionGet();
         assertThat(openJobResponse.isAcknowledged(), equalTo(true));
 
         String content = "{\"time\":1000, \"msg\": \"some categorical message\"}\n" +
@@ -97,7 +98,7 @@ public class MLTransportClientIT extends ESXPackSmokeClientTestCase {
         assertThat(updateModelSnapshotResponse.getModel().getDescription(), equalTo("Changed description"));
 
         // and delete the job
-        DeleteJobAction.Response deleteJobResponse = mlClient.deleteJob(new DeleteJobAction.Request(jobId)).actionGet();
+        AcknowledgedResponse deleteJobResponse = mlClient.deleteJob(new DeleteJobAction.Request(jobId)).actionGet();
         assertThat(deleteJobResponse, notNullValue());
         assertThat(deleteJobResponse.isAcknowledged(), equalTo(true));
     }
@@ -110,12 +111,12 @@ public class MLTransportClientIT extends ESXPackSmokeClientTestCase {
         Detector.Builder detector = new Detector.Builder();
         detector.setFunction("count");
         ValidateDetectorAction.Request validateDetectorRequest = new ValidateDetectorAction.Request(detector.build());
-        ValidateDetectorAction.Response validateDetectorResponse = mlClient.validateDetector(validateDetectorRequest).actionGet();
+        AcknowledgedResponse validateDetectorResponse = mlClient.validateDetector(validateDetectorRequest).actionGet();
         assertThat(validateDetectorResponse.isAcknowledged(), equalTo(true));
 
         Job.Builder job = createJob("ml-transport-client-it-validate-job");
         ValidateJobConfigAction.Request validateJobRequest = new ValidateJobConfigAction.Request(job.build(new Date()));
-        ValidateJobConfigAction.Response validateJobResponse = mlClient.validateJobConfig(validateJobRequest).actionGet();
+        AcknowledgedResponse validateJobResponse = mlClient.validateJobConfig(validateJobRequest).actionGet();
         assertThat(validateJobResponse.isAcknowledged(), equalTo(true));
     }
 
@@ -144,7 +145,7 @@ public class MLTransportClientIT extends ESXPackSmokeClientTestCase {
         assertThat(getDatafeedResponse.getResponse(), notNullValue());
 
         // Open job before starting the datafeed
-        OpenJobAction.Response openJobResponse = mlClient.openJob(new OpenJobAction.Request(jobId)).actionGet();
+        AcknowledgedResponse openJobResponse = mlClient.openJob(new OpenJobAction.Request(jobId)).actionGet();
         assertThat(openJobResponse.isAcknowledged(), equalTo(true));
 
         // create the index for the data feed
@@ -154,7 +155,7 @@ public class MLTransportClientIT extends ESXPackSmokeClientTestCase {
         client.prepareIndex(datafeedIndex, datatype).setSource(source).get();
 
         StartDatafeedAction.Request startDatafeedRequest = new StartDatafeedAction.Request(datafeedId, new Date().getTime());
-        StartDatafeedAction.Response startDataFeedResponse = mlClient.startDatafeed(startDatafeedRequest).actionGet();
+        AcknowledgedResponse startDataFeedResponse = mlClient.startDatafeed(startDatafeedRequest).actionGet();
         assertThat(startDataFeedResponse.isAcknowledged(), equalTo(true));
 
         StopDatafeedAction.Response stopDataFeedResponse = mlClient.stopDatafeed(new StopDatafeedAction.Request(datafeedId)).actionGet();