Main response should not have status 503 when okay (#29045)

The REST status 503 means "I can not handle the request that you sent
me." However today we respond to a main request with a 503 when there
are certain cluster blocks despite still responding with an actual main
response. This is broken, we should respond with a 200 status. This
commit removes this silliness.
This commit is contained in:
Jason Tedor 2018-03-14 06:36:37 -04:00 committed by GitHub
parent 647d0a1e95
commit 24d10adaab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 24 additions and 45 deletions

View File

@ -37,11 +37,6 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.main.MainRequest; import org.elasticsearch.action.main.MainRequest;
import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.action.main.MainResponse;
import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseListener;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
@ -162,7 +157,7 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
ProtocolVersion protocol = new ProtocolVersion("HTTP", 1, 1); ProtocolVersion protocol = new ProtocolVersion("HTTP", 1, 1);
when(mockResponse.getStatusLine()).thenReturn(new BasicStatusLine(protocol, 200, "OK")); when(mockResponse.getStatusLine()).thenReturn(new BasicStatusLine(protocol, 200, "OK"));
MainResponse response = new MainResponse(httpHeader.getValue(), Version.CURRENT, ClusterName.DEFAULT, "_na", Build.CURRENT, true); MainResponse response = new MainResponse(httpHeader.getValue(), Version.CURRENT, ClusterName.DEFAULT, "_na", Build.CURRENT);
BytesRef bytesRef = XContentHelper.toXContent(response, XContentType.JSON, false).toBytesRef(); BytesRef bytesRef = XContentHelper.toXContent(response, XContentType.JSON, false).toBytesRef();
when(mockResponse.getEntity()).thenReturn(new ByteArrayEntity(bytesRef.bytes, ContentType.APPLICATION_JSON)); when(mockResponse.getEntity()).thenReturn(new ByteArrayEntity(bytesRef.bytes, ContentType.APPLICATION_JSON));

View File

@ -163,7 +163,7 @@ public class RestHighLevelClientTests extends ESTestCase {
public void testInfo() throws IOException { public void testInfo() throws IOException {
Header[] headers = randomHeaders(random(), "Header"); Header[] headers = randomHeaders(random(), "Header");
MainResponse testInfo = new MainResponse("nodeName", Version.CURRENT, new ClusterName("clusterName"), "clusterUuid", MainResponse testInfo = new MainResponse("nodeName", Version.CURRENT, new ClusterName("clusterName"), "clusterUuid",
Build.CURRENT, true); Build.CURRENT);
mockResponse(testInfo); mockResponse(testInfo);
MainResponse receivedInfo = restHighLevelClient.info(headers); MainResponse receivedInfo = restHighLevelClient.info(headers);
assertEquals(testInfo, receivedInfo); assertEquals(testInfo, receivedInfo);

View File

@ -52,7 +52,6 @@ public class MainDocumentationIT extends ESRestHighLevelClientTestCase {
//tag::main-execute //tag::main-execute
MainResponse response = client.info(); MainResponse response = client.info();
//end::main-execute //end::main-execute
assertTrue(response.isAvailable());
//tag::main-response //tag::main-response
ClusterName clusterName = response.getClusterName(); // <1> ClusterName clusterName = response.getClusterName(); // <1>
String clusterUuid = response.getClusterUuid(); // <2> String clusterUuid = response.getClusterUuid(); // <2>

View File

@ -41,18 +41,16 @@ public class MainResponse extends ActionResponse implements ToXContentObject {
private ClusterName clusterName; private ClusterName clusterName;
private String clusterUuid; private String clusterUuid;
private Build build; private Build build;
boolean available;
MainResponse() { MainResponse() {
} }
public MainResponse(String nodeName, Version version, ClusterName clusterName, String clusterUuid, Build build, boolean available) { public MainResponse(String nodeName, Version version, ClusterName clusterName, String clusterUuid, Build build) {
this.nodeName = nodeName; this.nodeName = nodeName;
this.version = version; this.version = version;
this.clusterName = clusterName; this.clusterName = clusterName;
this.clusterUuid = clusterUuid; this.clusterUuid = clusterUuid;
this.build = build; this.build = build;
this.available = available;
} }
public String getNodeName() { public String getNodeName() {
@ -75,10 +73,6 @@ public class MainResponse extends ActionResponse implements ToXContentObject {
return build; return build;
} }
public boolean isAvailable() {
return available;
}
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
@ -87,7 +81,9 @@ public class MainResponse extends ActionResponse implements ToXContentObject {
clusterName.writeTo(out); clusterName.writeTo(out);
out.writeString(clusterUuid); out.writeString(clusterUuid);
Build.writeBuild(build, out); Build.writeBuild(build, out);
out.writeBoolean(available); if (out.getVersion().before(Version.V_7_0_0_alpha1)) {
out.writeBoolean(true);
}
} }
@Override @Override
@ -98,7 +94,9 @@ public class MainResponse extends ActionResponse implements ToXContentObject {
clusterName = new ClusterName(in); clusterName = new ClusterName(in);
clusterUuid = in.readString(); clusterUuid = in.readString();
build = Build.readBuild(in); build = Build.readBuild(in);
available = in.readBoolean(); if (in.getVersion().before(Version.V_7_0_0_alpha1)) {
in.readBoolean();
}
} }
@Override @Override
@ -133,7 +131,6 @@ public class MainResponse extends ActionResponse implements ToXContentObject {
response.build = new Build((String) value.get("build_hash"), (String) value.get("build_date"), response.build = new Build((String) value.get("build_hash"), (String) value.get("build_date"),
(boolean) value.get("build_snapshot")); (boolean) value.get("build_snapshot"));
response.version = Version.fromString((String) value.get("number")); response.version = Version.fromString((String) value.get("number"));
response.available = true;
}, (parser, context) -> parser.map(), new ParseField("version")); }, (parser, context) -> parser.map(), new ParseField("version"));
} }
@ -154,12 +151,11 @@ public class MainResponse extends ActionResponse implements ToXContentObject {
Objects.equals(version, other.version) && Objects.equals(version, other.version) &&
Objects.equals(clusterUuid, other.clusterUuid) && Objects.equals(clusterUuid, other.clusterUuid) &&
Objects.equals(build, other.build) && Objects.equals(build, other.build) &&
Objects.equals(available, other.available) &&
Objects.equals(clusterName, other.clusterName); Objects.equals(clusterName, other.clusterName);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(nodeName, version, clusterUuid, build, clusterName, available); return Objects.hash(nodeName, version, clusterUuid, build, clusterName);
} }
} }

View File

@ -53,6 +53,6 @@ public class TransportMainAction extends HandledTransportAction<MainRequest, Mai
final boolean available = clusterState.getBlocks().hasGlobalBlock(RestStatus.SERVICE_UNAVAILABLE) == false; final boolean available = clusterState.getBlocks().hasGlobalBlock(RestStatus.SERVICE_UNAVAILABLE) == false;
listener.onResponse( listener.onResponse(
new MainResponse(Node.NODE_NAME_SETTING.get(settings), Version.CURRENT, clusterState.getClusterName(), new MainResponse(Node.NODE_NAME_SETTING.get(settings), Version.CURRENT, clusterState.getClusterName(),
clusterState.metaData().clusterUUID(), Build.CURRENT, available)); clusterState.metaData().clusterUUID(), Build.CURRENT));
} }
} }

View File

@ -60,13 +60,11 @@ public class RestMainAction extends BaseRestHandler {
} }
static BytesRestResponse convertMainResponse(MainResponse response, RestRequest request, XContentBuilder builder) throws IOException { static BytesRestResponse convertMainResponse(MainResponse response, RestRequest request, XContentBuilder builder) throws IOException {
RestStatus status = response.isAvailable() ? RestStatus.OK : RestStatus.SERVICE_UNAVAILABLE;
// Default to pretty printing, but allow ?pretty=false to disable // Default to pretty printing, but allow ?pretty=false to disable
if (request.hasParam("pretty") == false) { if (request.hasParam("pretty") == false) {
builder.prettyPrint().lfAtEnd(); builder.prettyPrint().lfAtEnd();
} }
response.toXContent(builder, request); response.toXContent(builder, request);
return new BytesRestResponse(status, builder); return new BytesRestResponse(RestStatus.OK, builder);
} }
} }

View File

@ -48,9 +48,8 @@ public class MainActionTests extends ESTestCase {
final ClusterService clusterService = mock(ClusterService.class); final ClusterService clusterService = mock(ClusterService.class);
final ClusterName clusterName = new ClusterName("elasticsearch"); final ClusterName clusterName = new ClusterName("elasticsearch");
final Settings settings = Settings.builder().put("node.name", "my-node").build(); final Settings settings = Settings.builder().put("node.name", "my-node").build();
final boolean available = randomBoolean();
ClusterBlocks blocks; ClusterBlocks blocks;
if (available) { if (randomBoolean()) {
if (randomBoolean()) { if (randomBoolean()) {
blocks = ClusterBlocks.EMPTY_CLUSTER_BLOCK; blocks = ClusterBlocks.EMPTY_CLUSTER_BLOCK;
} else { } else {
@ -86,7 +85,6 @@ public class MainActionTests extends ESTestCase {
}); });
assertNotNull(responseRef.get()); assertNotNull(responseRef.get());
assertEquals(available, responseRef.get().isAvailable());
verify(clusterService, times(1)).state(); verify(clusterService, times(1)).state();
} }
} }

View File

@ -41,7 +41,7 @@ public class MainResponseTests extends AbstractStreamableXContentTestCase<MainRe
String nodeName = randomAlphaOfLength(10); String nodeName = randomAlphaOfLength(10);
Build build = new Build(randomAlphaOfLength(8), new Date(randomNonNegativeLong()).toString(), randomBoolean()); Build build = new Build(randomAlphaOfLength(8), new Date(randomNonNegativeLong()).toString(), randomBoolean());
Version version = VersionUtils.randomVersion(random()); Version version = VersionUtils.randomVersion(random());
return new MainResponse(nodeName, version, clusterName, clusterUuid , build, true); return new MainResponse(nodeName, version, clusterName, clusterUuid , build);
} }
@Override @Override
@ -58,7 +58,7 @@ public class MainResponseTests extends AbstractStreamableXContentTestCase<MainRe
String clusterUUID = randomAlphaOfLengthBetween(10, 20); String clusterUUID = randomAlphaOfLengthBetween(10, 20);
Build build = new Build(Build.CURRENT.shortHash(), Build.CURRENT.date(), Build.CURRENT.isSnapshot()); Build build = new Build(Build.CURRENT.shortHash(), Build.CURRENT.date(), Build.CURRENT.isSnapshot());
Version version = Version.CURRENT; Version version = Version.CURRENT;
MainResponse response = new MainResponse("nodeName", version, new ClusterName("clusterName"), clusterUUID, build, true); MainResponse response = new MainResponse("nodeName", version, new ClusterName("clusterName"), clusterUUID, build);
XContentBuilder builder = XContentFactory.jsonBuilder(); XContentBuilder builder = XContentFactory.jsonBuilder();
response.toXContent(builder, ToXContent.EMPTY_PARAMS); response.toXContent(builder, ToXContent.EMPTY_PARAMS);
assertEquals("{" assertEquals("{"
@ -80,12 +80,11 @@ public class MainResponseTests extends AbstractStreamableXContentTestCase<MainRe
@Override @Override
protected MainResponse mutateInstance(MainResponse mutateInstance) { protected MainResponse mutateInstance(MainResponse mutateInstance) {
String clusterUuid = mutateInstance.getClusterUuid(); String clusterUuid = mutateInstance.getClusterUuid();
boolean available = mutateInstance.isAvailable();
Build build = mutateInstance.getBuild(); Build build = mutateInstance.getBuild();
Version version = mutateInstance.getVersion(); Version version = mutateInstance.getVersion();
String nodeName = mutateInstance.getNodeName(); String nodeName = mutateInstance.getNodeName();
ClusterName clusterName = mutateInstance.getClusterName(); ClusterName clusterName = mutateInstance.getClusterName();
switch (randomIntBetween(0, 5)) { switch (randomIntBetween(0, 4)) {
case 0: case 0:
clusterUuid = clusterUuid + randomAlphaOfLength(5); clusterUuid = clusterUuid + randomAlphaOfLength(5);
break; break;
@ -93,19 +92,16 @@ public class MainResponseTests extends AbstractStreamableXContentTestCase<MainRe
nodeName = nodeName + randomAlphaOfLength(5); nodeName = nodeName + randomAlphaOfLength(5);
break; break;
case 2: case 2:
available = !available;
break;
case 3:
// toggle the snapshot flag of the original Build parameter // toggle the snapshot flag of the original Build parameter
build = new Build(build.shortHash(), build.date(), !build.isSnapshot()); build = new Build(build.shortHash(), build.date(), !build.isSnapshot());
break; break;
case 4: case 3:
version = randomValueOtherThan(version, () -> VersionUtils.randomVersion(random())); version = randomValueOtherThan(version, () -> VersionUtils.randomVersion(random()));
break; break;
case 5: case 4:
clusterName = new ClusterName(clusterName + randomAlphaOfLength(5)); clusterName = new ClusterName(clusterName + randomAlphaOfLength(5));
break; break;
} }
return new MainResponse(nodeName, version, clusterName, clusterUuid, build, available); return new MainResponse(nodeName, version, clusterName, clusterUuid, build);
} }
} }

View File

@ -36,6 +36,7 @@ import org.elasticsearch.test.rest.FakeRestRequest;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
public class RestMainActionTests extends ESTestCase { public class RestMainActionTests extends ESTestCase {
@ -44,12 +45,10 @@ public class RestMainActionTests extends ESTestCase {
final String nodeName = "node1"; final String nodeName = "node1";
final ClusterName clusterName = new ClusterName("cluster1"); final ClusterName clusterName = new ClusterName("cluster1");
final String clusterUUID = randomAlphaOfLengthBetween(10, 20); final String clusterUUID = randomAlphaOfLengthBetween(10, 20);
final boolean available = randomBoolean();
final RestStatus expectedStatus = available ? RestStatus.OK : RestStatus.SERVICE_UNAVAILABLE;
final Version version = Version.CURRENT; final Version version = Version.CURRENT;
final Build build = Build.CURRENT; final Build build = Build.CURRENT;
final MainResponse mainResponse = new MainResponse(nodeName, version, clusterName, clusterUUID, build, available); final MainResponse mainResponse = new MainResponse(nodeName, version, clusterName, clusterUUID, build);
XContentBuilder builder = JsonXContent.contentBuilder(); XContentBuilder builder = JsonXContent.contentBuilder();
RestRequest restRequest = new FakeRestRequest() { RestRequest restRequest = new FakeRestRequest() {
@Override @Override
@ -60,7 +59,7 @@ public class RestMainActionTests extends ESTestCase {
BytesRestResponse response = RestMainAction.convertMainResponse(mainResponse, restRequest, builder); BytesRestResponse response = RestMainAction.convertMainResponse(mainResponse, restRequest, builder);
assertNotNull(response); assertNotNull(response);
assertEquals(expectedStatus, response.status()); assertThat(response.status(), equalTo(RestStatus.OK));
// the empty responses are handled in the HTTP layer so we do // the empty responses are handled in the HTTP layer so we do
// not assert on them here // not assert on them here
@ -70,13 +69,11 @@ public class RestMainActionTests extends ESTestCase {
final String nodeName = "node1"; final String nodeName = "node1";
final ClusterName clusterName = new ClusterName("cluster1"); final ClusterName clusterName = new ClusterName("cluster1");
final String clusterUUID = randomAlphaOfLengthBetween(10, 20); final String clusterUUID = randomAlphaOfLengthBetween(10, 20);
final boolean available = randomBoolean();
final RestStatus expectedStatus = available ? RestStatus.OK : RestStatus.SERVICE_UNAVAILABLE;
final Version version = Version.CURRENT; final Version version = Version.CURRENT;
final Build build = Build.CURRENT; final Build build = Build.CURRENT;
final boolean prettyPrint = randomBoolean(); final boolean prettyPrint = randomBoolean();
final MainResponse mainResponse = new MainResponse(nodeName, version, clusterName, clusterUUID, build, available); final MainResponse mainResponse = new MainResponse(nodeName, version, clusterName, clusterUUID, build);
XContentBuilder builder = JsonXContent.contentBuilder(); XContentBuilder builder = JsonXContent.contentBuilder();
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
@ -87,7 +84,7 @@ public class RestMainActionTests extends ESTestCase {
BytesRestResponse response = RestMainAction.convertMainResponse(mainResponse, restRequest, builder); BytesRestResponse response = RestMainAction.convertMainResponse(mainResponse, restRequest, builder);
assertNotNull(response); assertNotNull(response);
assertEquals(expectedStatus, response.status()); assertThat(response.status(), equalTo(RestStatus.OK));
assertThat(response.content().length(), greaterThan(0)); assertThat(response.content().length(), greaterThan(0));
XContentBuilder responseBuilder = JsonXContent.contentBuilder(); XContentBuilder responseBuilder = JsonXContent.contentBuilder();