diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/README.asciidoc b/rest-api-spec/src/main/resources/rest-api-spec/test/README.asciidoc index c2259c7b55d14..51692fc593c44 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/README.asciidoc +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/README.asciidoc @@ -198,9 +198,7 @@ header. The warnings must match exactly. Using it looks like this: .... If the arguments to `do` include `node_selector` then the request is only -sent to nodes that match the `node_selector`. Currently only the `version` -selector is supported and it has the same logic as the `version` field in -`skip`. It looks like this: +sent to nodes that match the `node_selector`. It looks like this: .... "test id": @@ -216,6 +214,14 @@ selector is supported and it has the same logic as the `version` field in body: { foo: bar } .... +If you list multiple selectors then the request will only go to nodes that +match all of those selectors. The following selectors are supported: +* `version`: Only nodes who's version is within the range will receive the +request. The syntax for the pattern is the same as when `version` is within +`skip`. +* `name`: Only nodes who's name matches the name exactly will receive the +request. + === `set` For some tests, it is necessary to extract a value from the previous `response`, in diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java index 8cfbf11bd64b7..fd6e4e6fac32d 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java +++ b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java @@ -370,6 +370,27 @@ private String formatStatusCodeMessage(ClientYamlTestResponse restTestResponse, private static NodeSelector buildNodeSelector(XContentLocation location, String name, String value) { switch (name) { + case "name": + return new NodeSelector() { + @Override + public void select(Iterable nodes) { + for (Iterator itr = nodes.iterator(); itr.hasNext();) { + Node node = itr.next(); + if (node.getName() == null) { + throw new IllegalStateException("expected [name] metadata to be set but got " + + node); + } + if (false == value.equals(node.getName())) { + itr.remove(); + } + } + } + + @Override + public String toString() { + return "name is [" + value + "]"; + } + }; case "version": Version[] range = SkipSection.parseVersionRange(value); return new NodeSelector() { diff --git a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java index 719044cfc81c2..d88ad2cd842bf 100644 --- a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java +++ b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java @@ -511,7 +511,7 @@ public void testParseDoSectionExpectedWarnings() throws Exception { "just one entry this time"))); } - public void testNodeSelector() throws IOException { + public void testNodeSelectorByVersion() throws IOException { parser = createParser(YamlXContent.yamlXContent, "node_selector:\n" + " version: 5.2.0-6.0.0\n" + @@ -521,10 +521,10 @@ public void testNodeSelector() throws IOException { DoSection doSection = DoSection.parse(parser); assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector()); - Node v170 = nodeWithVersion("1.7.0"); - Node v521 = nodeWithVersion("5.2.1"); - Node v550 = nodeWithVersion("5.5.0"); - Node v612 = nodeWithVersion("6.1.2"); + Node v170 = new Node(new HttpHost("dummy"), null, null, "1.7.0", null); + Node v521 = new Node(new HttpHost("dummy"), null, null, "5.2.1", null); + Node v550 = new Node(new HttpHost("dummy"), null, null, "5.5.0", null); + Node v612 = new Node(new HttpHost("dummy"), null, null, "6.1.2", null); List nodes = new ArrayList<>(); nodes.add(v170); nodes.add(v521); @@ -541,8 +541,61 @@ public void testNodeSelector() throws IOException { emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector()); } - private Node nodeWithVersion(String version) { - return new Node(new HttpHost("dummy"), null, null, version, null); + public void testNodeSelectorByName() throws IOException { + parser = createParser(YamlXContent.yamlXContent, + "node_selector:\n" + + " name: cat\n" + + "indices.get_field_mapping:\n" + + " index: test_index" + ); + + DoSection doSection = DoSection.parse(parser); + assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector()); + Node cat = new Node(new HttpHost("dummy"), null, "cat", null, null); + Node dog = new Node(new HttpHost("dummy"), null, "dog", null, null); + Node pig = new Node(new HttpHost("dummy"), null, "pig", null, null); + List nodes = new ArrayList<>(); + nodes.add(cat); + nodes.add(dog); + nodes.add(pig); + doSection.getApiCallSection().getNodeSelector().select(nodes); + assertEquals(Arrays.asList(cat), nodes); + ClientYamlTestExecutionContext context = mock(ClientYamlTestExecutionContext.class); + ClientYamlTestResponse mockResponse = mock(ClientYamlTestResponse.class); + when(context.callApi("indices.get_field_mapping", singletonMap("index", "test_index"), + emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector())).thenReturn(mockResponse); + doSection.execute(context); + verify(context).callApi("indices.get_field_mapping", singletonMap("index", "test_index"), + emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector()); + } + + public void testNodeSelectorByTwoThings() throws IOException { + parser = createParser(YamlXContent.yamlXContent, + "node_selector:\n" + + " name: cat\n" + + " version: 5.2.0-6.0.0\n" + + "indices.get_field_mapping:\n" + + " index: test_index" + ); + + DoSection doSection = DoSection.parse(parser); + assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector()); + Node cat = new Node(new HttpHost("dummy"), null, "cat", "5.2.1", null); + Node badName = new Node(new HttpHost("dummy"), null, "dog", "5.2.1", null); + Node badVersion = new Node(new HttpHost("dummy"), null, "cat", "6.1.2", null); + List nodes = new ArrayList<>(); + nodes.add(cat); + nodes.add(badName); + nodes.add(badVersion); + doSection.getApiCallSection().getNodeSelector().select(nodes); + assertEquals(Arrays.asList(cat), nodes); + ClientYamlTestExecutionContext context = mock(ClientYamlTestExecutionContext.class); + ClientYamlTestResponse mockResponse = mock(ClientYamlTestResponse.class); + when(context.callApi("indices.get_field_mapping", singletonMap("index", "test_index"), + emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector())).thenReturn(mockResponse); + doSection.execute(context); + verify(context).callApi("indices.get_field_mapping", singletonMap("index", "test_index"), + emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector()); } private void assertJsonEquals(Map actual, String expected) throws IOException {