Skip to content

Commit ab832ac

Browse files
Add multi-project IT for indices stats API
This API already works correctly. This API just adds a test.
1 parent 7d06f81 commit ab832ac

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.action.admin.indices.stats;
11+
12+
import org.elasticsearch.client.Request;
13+
import org.elasticsearch.client.ResponseException;
14+
import org.elasticsearch.common.Strings;
15+
import org.elasticsearch.common.settings.SecureString;
16+
import org.elasticsearch.common.settings.Settings;
17+
import org.elasticsearch.common.util.concurrent.ThreadContext;
18+
import org.elasticsearch.multiproject.MultiProjectRestTestCase;
19+
import org.elasticsearch.test.cluster.ElasticsearchCluster;
20+
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
21+
import org.elasticsearch.test.rest.ObjectPath;
22+
import org.junit.ClassRule;
23+
24+
import java.io.IOException;
25+
import java.util.Map;
26+
27+
import static org.hamcrest.Matchers.containsInAnyOrder;
28+
import static org.hamcrest.Matchers.equalTo;
29+
30+
public class IndicesStatsMultiProjectIT extends MultiProjectRestTestCase {
31+
32+
private static final String PASSWORD = "hunter2";
33+
34+
@ClassRule
35+
public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
36+
.nodes(1)
37+
.distribution(DistributionType.INTEG_TEST)
38+
.module("test-multi-project")
39+
.setting("test.multi_project.enabled", "true")
40+
.setting("xpack.security.enabled", "true")
41+
.user("admin", PASSWORD)
42+
.build();
43+
44+
@Override
45+
protected String getTestRestCluster() {
46+
return cluster.getHttpAddresses();
47+
}
48+
49+
@Override
50+
protected Settings restClientSettings() {
51+
final String token = basicAuthHeaderValue("admin", new SecureString(PASSWORD.toCharArray()));
52+
return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build();
53+
}
54+
55+
public void testIndicesStats() throws IOException {
56+
// Create two projects. We will use the default project as the third project in this test.
57+
createProject("project-1");
58+
createProject("project-2");
59+
60+
// Create and write data into a number of indices.
61+
// Some of the index names are used only in one project, some in two projects, some in all three.
62+
int numDocs1Only = createPopulatedIndex("project-1", "my-index-project-1-only");
63+
int numDocs2Only = createPopulatedIndex("project-2", "my-index-project-2-only");
64+
int numDocsDefaultOnly = createPopulatedIndex("default", "my-index-default-project-only");
65+
int numDocs1Of1And2 = createPopulatedIndex("project-1", "my-index-projects-1-and-2");
66+
int numDocs2Of1And2 = createPopulatedIndex("project-2", "my-index-projects-1-and-2");
67+
int numDocs2Of2AndDefault = createPopulatedIndex("project-2", "my-index-projects-2-and-default");
68+
int numDocsDefaultOf2AndDefault = createPopulatedIndex("default", "my-index-projects-2-and-default");
69+
int numDocs1All = createPopulatedIndex("project-1", "my-index-all-projects");
70+
int numDocs2All = createPopulatedIndex("project-2", "my-index-all-projects");
71+
int numDocsDefaultAll = createPopulatedIndex("default", "my-index-all-projects");
72+
73+
// Check indices stats for project 1.
74+
Map<String, Object> statsForProject1 = getAsOrderedMapInProject("/_stats", "project-1");
75+
assertThat(ObjectPath.evaluate(statsForProject1, "_all.total.docs.count"), equalTo(numDocs1Only + numDocs1Of1And2 + numDocs1All));
76+
assertThat(
77+
ObjectPath.<Map<String, Object>>evaluate(statsForProject1, "indices").keySet(),
78+
containsInAnyOrder("my-index-project-1-only", "my-index-projects-1-and-2", "my-index-all-projects")
79+
);
80+
assertThat(ObjectPath.evaluate(statsForProject1, "indices.my-index-project-1-only.total.docs.count"), equalTo(numDocs1Only));
81+
assertThat(ObjectPath.evaluate(statsForProject1, "indices.my-index-projects-1-and-2.total.docs.count"), equalTo(numDocs1Of1And2));
82+
assertThat(ObjectPath.evaluate(statsForProject1, "indices.my-index-all-projects.total.docs.count"), equalTo(numDocs1All));
83+
84+
// Check indices stats for project 2.
85+
Map<String, Object> statsForProject2 = getAsOrderedMapInProject("/_stats", "project-2");
86+
assertThat(
87+
ObjectPath.evaluate(statsForProject2, "_all.total.docs.count"),
88+
equalTo(numDocs2Only + numDocs2Of1And2 + numDocs2Of2AndDefault + numDocs2All)
89+
);
90+
assertThat(
91+
ObjectPath.<Map<String, Object>>evaluate(statsForProject2, "indices").keySet(),
92+
containsInAnyOrder(
93+
"my-index-project-2-only",
94+
"my-index-projects-1-and-2",
95+
"my-index-projects-2-and-default",
96+
"my-index-all-projects"
97+
)
98+
);
99+
assertThat(ObjectPath.evaluate(statsForProject2, "indices.my-index-all-projects.total.docs.count"), equalTo(numDocs2All));
100+
101+
// Check indices stats for default project.
102+
Map<String, Object> statsForDefaultProject = getAsOrderedMap("/_stats");
103+
assertThat(
104+
ObjectPath.evaluate(statsForDefaultProject, "_all.total.docs.count"),
105+
equalTo(numDocsDefaultOnly + numDocsDefaultOf2AndDefault + numDocsDefaultAll)
106+
);
107+
assertThat(
108+
ObjectPath.<Map<String, Object>>evaluate(statsForDefaultProject, "indices").keySet(),
109+
containsInAnyOrder("my-index-default-project-only", "my-index-projects-2-and-default", "my-index-all-projects")
110+
);
111+
assertThat(
112+
ObjectPath.evaluate(statsForDefaultProject, "indices.my-index-all-projects.total.docs.count"),
113+
equalTo(numDocsDefaultAll)
114+
);
115+
116+
// Check single-index stats for each project.
117+
assertThat(
118+
ObjectPath.evaluate(getAsOrderedMapInProject("/my-index-all-projects/_stats", "project-1"), "_all.total.docs.count"),
119+
equalTo(numDocs1All)
120+
);
121+
assertThat(
122+
ObjectPath.evaluate(getAsOrderedMapInProject("/my-index-all-projects/_stats", "project-2"), "_all.total.docs.count"),
123+
equalTo(numDocs2All)
124+
);
125+
assertThat(
126+
ObjectPath.evaluate(getAsOrderedMap("/my-index-all-projects/_stats"), "_all.total.docs.count"),
127+
equalTo(numDocsDefaultAll)
128+
);
129+
130+
// Check that getting single-index stats for an index that does not exist in a project returns a 404.
131+
ResponseException exception = assertThrows(
132+
ResponseException.class,
133+
() -> client().performRequest(setRequestProjectId(new Request("GET", "/my-index-project-1-only/_stats"), "project-2"))
134+
);
135+
assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(404));
136+
137+
// Check using a wildcard gets the matching indices for that project.
138+
Map<String, Object> statsWithWildcardForProject1 = getAsOrderedMapInProject("/my-index-project*/_stats", "project-1");
139+
assertThat(ObjectPath.evaluate(statsWithWildcardForProject1, "_all.total.docs.count"), equalTo(numDocs1Only + numDocs1Of1And2));
140+
assertThat(
141+
ObjectPath.<Map<String, Object>>evaluate(statsWithWildcardForProject1, "indices").keySet(),
142+
containsInAnyOrder("my-index-project-1-only", "my-index-projects-1-and-2")
143+
);
144+
}
145+
146+
private int createPopulatedIndex(String projectId, String indexName) throws IOException {
147+
createIndex(req -> {
148+
setRequestProjectId(req, projectId);
149+
return client().performRequest(req);
150+
}, indexName, null, null, null);
151+
int numDocs = randomIntBetween(5, 10);
152+
for (int i = 0; i < numDocs; i++) {
153+
Request request = new Request("POST", "/" + indexName + "/_doc");
154+
request.setJsonEntity(Strings.format("{ \"num\": %d, \"str\": \"%s\" }", randomInt(), randomAlphaOfLengthBetween(5, 10)));
155+
setRequestProjectId(request, projectId);
156+
client().performRequest(request);
157+
}
158+
client().performRequest(setRequestProjectId(new Request("POST", "/" + indexName + "/_refresh"), projectId));
159+
return numDocs;
160+
}
161+
162+
private static Map<String, Object> getAsOrderedMapInProject(String endpoint, String projectId) throws IOException {
163+
return responseAsOrderedMap(client().performRequest(setRequestProjectId(new Request("GET", endpoint), projectId)));
164+
}
165+
}

0 commit comments

Comments
 (0)