LookupIndexModeIT.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. package org.elasticsearch.index;
  10. import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
  11. import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
  12. import org.elasticsearch.action.admin.indices.shrink.ResizeAction;
  13. import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
  14. import org.elasticsearch.action.admin.indices.shrink.ResizeType;
  15. import org.elasticsearch.action.fieldcaps.FieldCapabilitiesIndexResponse;
  16. import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
  17. import org.elasticsearch.action.search.SearchResponse;
  18. import org.elasticsearch.cluster.metadata.IndexMetadata;
  19. import org.elasticsearch.common.settings.Settings;
  20. import org.elasticsearch.index.query.MatchQueryBuilder;
  21. import org.elasticsearch.search.SearchHit;
  22. import org.elasticsearch.test.ESIntegTestCase;
  23. import java.util.Map;
  24. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
  25. import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
  26. import static org.hamcrest.Matchers.equalTo;
  27. import static org.hamcrest.Matchers.hasSize;
  28. public class LookupIndexModeIT extends ESIntegTestCase {
  29. @Override
  30. protected int numberOfShards() {
  31. return 1;
  32. }
  33. public void testBasic() {
  34. internalCluster().ensureAtLeastNumDataNodes(1);
  35. Settings.Builder lookupSettings = Settings.builder().put("index.mode", "lookup");
  36. if (randomBoolean()) {
  37. lookupSettings.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1);
  38. }
  39. CreateIndexRequest createRequest = new CreateIndexRequest("hosts");
  40. createRequest.settings(lookupSettings);
  41. createRequest.simpleMapping("ip", "type=ip", "os", "type=keyword");
  42. assertAcked(client().admin().indices().execute(TransportCreateIndexAction.TYPE, createRequest));
  43. Settings settings = client().admin().indices().prepareGetSettings("hosts").get().getIndexToSettings().get("hosts");
  44. assertThat(settings.get("index.mode"), equalTo("lookup"));
  45. assertNull(settings.get("index.auto_expand_replicas"));
  46. Map<String, String> allHosts = Map.of(
  47. "192.168.1.2",
  48. "Windows",
  49. "192.168.1.3",
  50. "MacOS",
  51. "192.168.1.4",
  52. "Linux",
  53. "192.168.1.5",
  54. "Android",
  55. "192.168.1.6",
  56. "iOS",
  57. "192.168.1.7",
  58. "Windows",
  59. "192.168.1.8",
  60. "MacOS",
  61. "192.168.1.9",
  62. "Linux",
  63. "192.168.1.10",
  64. "Linux",
  65. "192.168.1.11",
  66. "Windows"
  67. );
  68. for (Map.Entry<String, String> e : allHosts.entrySet()) {
  69. client().prepareIndex("hosts").setSource("ip", e.getKey(), "os", e.getValue()).get();
  70. }
  71. refresh("hosts");
  72. assertAcked(client().admin().indices().prepareCreate("events").setSettings(Settings.builder().put("index.mode", "logsdb")).get());
  73. int numDocs = between(1, 10);
  74. for (int i = 0; i < numDocs; i++) {
  75. String ip = randomFrom(allHosts.keySet());
  76. String message = randomFrom("login", "logout", "shutdown", "restart");
  77. client().prepareIndex("events").setSource("@timestamp", "2024-01-01", "ip", ip, "message", message).get();
  78. }
  79. refresh("events");
  80. // _search
  81. {
  82. SearchResponse resp = prepareSearch("events", "hosts").setQuery(new MatchQueryBuilder("_index_mode", "lookup"))
  83. .setSize(10000)
  84. .get();
  85. for (SearchHit hit : resp.getHits()) {
  86. assertThat(hit.getIndex(), equalTo("hosts"));
  87. }
  88. assertHitCount(resp, allHosts.size());
  89. resp.decRef();
  90. }
  91. // field_caps
  92. {
  93. FieldCapabilitiesRequest request = new FieldCapabilitiesRequest();
  94. request.indices("events", "hosts");
  95. request.fields("*");
  96. request.setMergeResults(false);
  97. request.indexFilter(new MatchQueryBuilder("_index_mode", "lookup"));
  98. var resp = client().fieldCaps(request).actionGet();
  99. assertThat(resp.getIndexResponses(), hasSize(1));
  100. FieldCapabilitiesIndexResponse indexResponse = resp.getIndexResponses().get(0);
  101. assertThat(indexResponse.getIndexMode(), equalTo(IndexMode.LOOKUP));
  102. assertThat(indexResponse.getIndexName(), equalTo("hosts"));
  103. }
  104. }
  105. public void testRejectMoreThanOneShard() {
  106. int numberOfShards = between(2, 5);
  107. IllegalArgumentException error = expectThrows(IllegalArgumentException.class, () -> {
  108. client().admin()
  109. .indices()
  110. .prepareCreate("hosts")
  111. .setSettings(Settings.builder().put("index.mode", "lookup").put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, numberOfShards))
  112. .setMapping("ip", "type=ip", "os", "type=keyword")
  113. .get();
  114. });
  115. assertThat(
  116. error.getMessage(),
  117. equalTo("index with [lookup] mode must have [index.number_of_shards] set to 1 or unset; provided " + numberOfShards)
  118. );
  119. }
  120. public void testResizeLookupIndex() {
  121. Settings.Builder createSettings = Settings.builder().put("index.mode", "lookup");
  122. if (randomBoolean()) {
  123. createSettings.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1);
  124. }
  125. CreateIndexRequest createIndexRequest = new CreateIndexRequest("lookup-1").settings(createSettings);
  126. assertAcked(client().admin().indices().execute(TransportCreateIndexAction.TYPE, createIndexRequest));
  127. client().admin().indices().prepareAddBlock(IndexMetadata.APIBlock.WRITE, "lookup-1").get();
  128. ResizeRequest clone = new ResizeRequest("lookup-2", "lookup-1");
  129. clone.setResizeType(ResizeType.CLONE);
  130. assertAcked(client().admin().indices().execute(ResizeAction.INSTANCE, clone).actionGet());
  131. Settings settings = client().admin().indices().prepareGetSettings("lookup-2").get().getIndexToSettings().get("lookup-2");
  132. assertThat(settings.get("index.mode"), equalTo("lookup"));
  133. assertThat(settings.get("index.number_of_shards"), equalTo("1"));
  134. ResizeRequest split = new ResizeRequest("lookup-3", "lookup-1");
  135. split.setResizeType(ResizeType.SPLIT);
  136. split.getTargetIndexRequest().settings(Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 3));
  137. IllegalArgumentException error = expectThrows(
  138. IllegalArgumentException.class,
  139. () -> client().admin().indices().execute(ResizeAction.INSTANCE, split).actionGet()
  140. );
  141. assertThat(
  142. error.getMessage(),
  143. equalTo("index with [lookup] mode must have [index.number_of_shards] set to 1 or unset; provided 3")
  144. );
  145. }
  146. public void testResizeRegularIndexToLookup() {
  147. String dataNode = internalCluster().startDataOnlyNode();
  148. assertAcked(
  149. client().admin()
  150. .indices()
  151. .prepareCreate("regular-1")
  152. .setSettings(
  153. Settings.builder()
  154. .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 2)
  155. .put("index.routing.allocation.require._name", dataNode)
  156. )
  157. .setMapping("ip", "type=ip", "os", "type=keyword")
  158. .get()
  159. );
  160. client().admin().indices().prepareAddBlock(IndexMetadata.APIBlock.WRITE, "regular-1").get();
  161. client().admin()
  162. .indices()
  163. .prepareUpdateSettings("regular-1")
  164. .setSettings(Settings.builder().put("index.number_of_replicas", 0))
  165. .get();
  166. ResizeRequest clone = new ResizeRequest("lookup-3", "regular-1");
  167. clone.setResizeType(ResizeType.CLONE);
  168. clone.getTargetIndexRequest().settings(Settings.builder().put("index.mode", "lookup"));
  169. IllegalArgumentException error = expectThrows(
  170. IllegalArgumentException.class,
  171. () -> client().admin().indices().execute(ResizeAction.INSTANCE, clone).actionGet()
  172. );
  173. assertThat(
  174. error.getMessage(),
  175. equalTo("index with [lookup] mode must have [index.number_of_shards] set to 1 or unset; provided 2")
  176. );
  177. ResizeRequest shrink = new ResizeRequest("lookup-4", "regular-1");
  178. shrink.setResizeType(ResizeType.SHRINK);
  179. shrink.getTargetIndexRequest()
  180. .settings(Settings.builder().put("index.mode", "lookup").put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1));
  181. error = expectThrows(
  182. IllegalArgumentException.class,
  183. () -> client().admin().indices().execute(ResizeAction.INSTANCE, shrink).actionGet()
  184. );
  185. assertThat(error.getMessage(), equalTo("can't change setting [index.mode] during resize"));
  186. }
  187. public void testDoNotOverrideAutoExpandReplicas() {
  188. internalCluster().ensureAtLeastNumDataNodes(1);
  189. Settings.Builder createSettings = Settings.builder().put("index.mode", "lookup");
  190. if (randomBoolean()) {
  191. createSettings.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1);
  192. }
  193. createSettings.put("index.auto_expand_replicas", "3-5");
  194. CreateIndexRequest createRequest = new CreateIndexRequest("hosts");
  195. createRequest.settings(createSettings);
  196. createRequest.simpleMapping("ip", "type=ip", "os", "type=keyword");
  197. assertAcked(client().admin().indices().execute(TransportCreateIndexAction.TYPE, createRequest));
  198. Settings settings = client().admin().indices().prepareGetSettings("hosts").get().getIndexToSettings().get("hosts");
  199. assertThat(settings.get("index.mode"), equalTo("lookup"));
  200. assertThat(settings.get("index.auto_expand_replicas"), equalTo("3-5"));
  201. }
  202. }