diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplate.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplate.java new file mode 100644 index 0000000000..f7a42d278b --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplate.java @@ -0,0 +1,49 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class ComposableIndexTemplate implements IndexTemplate { + + private final Map indexTemplateMap; + private String name; + + public ComposableIndexTemplate(final Map indexTemplateMap) { + this.indexTemplateMap = new HashMap<>(indexTemplateMap); + } + + @Override + public void setTemplateName(final String name) { + this.name = name; + + } + + @Override + public void setIndexPatterns(final List indexPatterns) { + indexTemplateMap.put("index_patterns", indexPatterns); + } + + @Override + public void putCustomSetting(final String name, final Object value) { + + } + + @Override + public Optional getVersion() { + if(!indexTemplateMap.containsKey("version")) + return Optional.empty(); + final Number version = (Number) indexTemplateMap.get("version"); + return Optional.of(version.longValue()); + } + + public Map getIndexTemplateMap() { + return Collections.unmodifiableMap(indexTemplateMap); + } + + public String getName() { + return name; + } +} diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableTemplateAPIWrapper.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableTemplateAPIWrapper.java new file mode 100644 index 0000000000..1dc4e4604f --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableTemplateAPIWrapper.java @@ -0,0 +1,100 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.stream.JsonParser; +import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.ObjectBuilderDeserializer; +import org.opensearch.client.json.ObjectDeserializer; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.indices.ExistsIndexTemplateRequest; +import org.opensearch.client.opensearch.indices.GetIndexTemplateRequest; +import org.opensearch.client.opensearch.indices.GetIndexTemplateResponse; +import org.opensearch.client.opensearch.indices.PutIndexTemplateRequest; +import org.opensearch.client.opensearch.indices.get_index_template.IndexTemplateItem; +import org.opensearch.client.opensearch.indices.put_index_template.IndexTemplateMapping; +import org.opensearch.client.transport.endpoints.BooleanResponse; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Optional; + +public class ComposableTemplateAPIWrapper implements IndexTemplateAPIWrapper { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private final OpenSearchClient openSearchClient; + + public ComposableTemplateAPIWrapper(final OpenSearchClient openSearchClient) { + this.openSearchClient = openSearchClient; + } + + @Override + public void putTemplate(final IndexTemplate indexTemplate) throws IOException { + if(!(indexTemplate instanceof ComposableIndexTemplate)) { + throw new IllegalArgumentException("Unexpected indexTemplate provided to createTemplate."); + } + + final ComposableIndexTemplate composableIndexTemplate = (ComposableIndexTemplate) indexTemplate; + final String indexTemplateString = OBJECT_MAPPER.writeValueAsString( + composableIndexTemplate.getIndexTemplateMap()); + + final ByteArrayInputStream byteIn = new ByteArrayInputStream( + indexTemplateString.getBytes(StandardCharsets.UTF_8)); + final JsonpMapper mapper = openSearchClient._transport().jsonpMapper(); + final JsonParser parser = mapper.jsonProvider().createParser(byteIn); + + final PutIndexTemplateRequest putIndexTemplateRequest = PutIndexTemplateRequestDeserializer + .getJsonpDeserializer(composableIndexTemplate.getName()) + .deserialize(parser, mapper); + + openSearchClient.indices().putIndexTemplate(putIndexTemplateRequest); + } + + @Override + public Optional getTemplate(final String indexTemplateName) throws IOException { + final ExistsIndexTemplateRequest existsRequest = new ExistsIndexTemplateRequest.Builder() + .name(indexTemplateName) + .build(); + final BooleanResponse existsResponse = openSearchClient.indices().existsIndexTemplate(existsRequest); + + if (!existsResponse.value()) { + return Optional.empty(); + } + + final GetIndexTemplateRequest getRequest = new GetIndexTemplateRequest.Builder() + .name(indexTemplateName) + .build(); + final GetIndexTemplateResponse indexTemplateResponse = openSearchClient.indices().getIndexTemplate(getRequest); + + final List indexTemplateItems = indexTemplateResponse.indexTemplates(); + if (indexTemplateItems.size() == 1) { + return indexTemplateItems.stream().findFirst(); + } else { + throw new RuntimeException(String.format("Found zero or multiple index templates result when querying for %s", + indexTemplateName)); + } + } + + private static class PutIndexTemplateRequestDeserializer { + private static void setupPutIndexTemplateRequestDeserializer(final ObjectDeserializer objectDeserializer) { + + objectDeserializer.add(PutIndexTemplateRequest.Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + objectDeserializer.add(PutIndexTemplateRequest.Builder::indexPatterns, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), + "index_patterns"); + objectDeserializer.add(PutIndexTemplateRequest.Builder::version, JsonpDeserializer.longDeserializer(), "version"); + objectDeserializer.add(PutIndexTemplateRequest.Builder::priority, JsonpDeserializer.integerDeserializer(), "priority"); + objectDeserializer.add(PutIndexTemplateRequest.Builder::composedOf, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), + "composed_of"); + objectDeserializer.add(PutIndexTemplateRequest.Builder::template, IndexTemplateMapping._DESERIALIZER, "template"); + } + + static JsonpDeserializer getJsonpDeserializer(final String name) { + return ObjectBuilderDeserializer + .lazy( + () -> new PutIndexTemplateRequest.Builder().name(name), + PutIndexTemplateRequestDeserializer::setupPutIndexTemplateRequestDeserializer); + } + } +} diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/Es6IndexTemplateAPIWrapper.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/Es6IndexTemplateAPIWrapper.java new file mode 100644 index 0000000000..9ebb9dbc22 --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/Es6IndexTemplateAPIWrapper.java @@ -0,0 +1,134 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.stream.JsonParser; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch._types.ErrorResponse; +import org.opensearch.client.opensearch.indices.ExistsTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateResponse; +import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; +import org.opensearch.client.opensearch.indices.PutTemplateRequest; +import org.opensearch.client.opensearch.indices.PutTemplateResponse; +import org.opensearch.client.opensearch.indices.TemplateMapping; +import org.opensearch.client.transport.JsonEndpoint; +import org.opensearch.client.transport.endpoints.BooleanResponse; +import org.opensearch.client.transport.endpoints.SimpleEndpoint; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class Es6IndexTemplateAPIWrapper implements IndexTemplateAPIWrapper { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private final OpenSearchClient openSearchClient; + + public Es6IndexTemplateAPIWrapper(final OpenSearchClient openSearchClient) { + this.openSearchClient = openSearchClient; + } + + @Override + public void putTemplate(final IndexTemplate indexTemplate) throws IOException { + if(!(indexTemplate instanceof LegacyIndexTemplate)) { + throw new IllegalArgumentException("Unexpected indexTemplate provided to createTemplate."); + } + + final Map templateMapping = ((LegacyIndexTemplate) indexTemplate).getTemplateMap(); + final String indexTemplateString = OBJECT_MAPPER.writeValueAsString(templateMapping); + + // Parse byte array to Map + final ByteArrayInputStream byteIn = new ByteArrayInputStream( + indexTemplateString.getBytes(StandardCharsets.UTF_8)); + final JsonpMapper mapper = openSearchClient._transport().jsonpMapper(); + final JsonParser parser = mapper.jsonProvider().createParser(byteIn); + + final PutTemplateRequest putTemplateRequest = PutTemplateRequestDeserializer.getJsonpDeserializer() + .deserialize(parser, mapper); + + final OpenSearchIndicesClient openSearchIndicesClient = openSearchClient.indices(); + final JsonEndpoint endpoint = es6PutTemplateEndpoint(putTemplateRequest); + openSearchIndicesClient._transport().performRequest(putTemplateRequest, endpoint, openSearchIndicesClient._transportOptions()); + } + + @Override + public Optional getTemplate(final String templateName) throws IOException { + final ExistsTemplateRequest existsTemplateRequest = new ExistsTemplateRequest.Builder() + .name(templateName) + .build(); + final BooleanResponse booleanResponse = openSearchClient.indices().existsTemplate( + existsTemplateRequest); + if (!booleanResponse.value()) { + return Optional.empty(); + } + + final GetTemplateRequest getTemplateRequest = new GetTemplateRequest.Builder() + .name(templateName) + .build(); + final GetTemplateResponse response = openSearchClient.indices().getTemplate(getTemplateRequest); + + if (response.result().size() == 1) { + return response.result().values().stream().findFirst(); + } else { + throw new RuntimeException(String.format("Found zero or multiple index templates result when querying for %s", + templateName)); + } + } + + private JsonEndpoint es6PutTemplateEndpoint( + final PutTemplateRequest putTemplateRequest) { + return new SimpleEndpoint<>( + + // Request method + request -> { + return "PUT"; + + }, + + // Request path + request -> { + final int _name = 1 << 0; + + int propsSet = 0; + + propsSet |= _name; + + if (propsSet == (_name)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_template"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.name(), buf); + buf.append("?include_type_name=false"); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Request parameters + request -> { + Map params = new HashMap<>(); + if (request.masterTimeout() != null) { + params.put("master_timeout", request.masterTimeout()._toJsonString()); + } + if (request.clusterManagerTimeout() != null) { + params.put("cluster_manager_timeout", request.clusterManagerTimeout()._toJsonString()); + } + if (request.flatSettings() != null) { + params.put("flat_settings", String.valueOf(request.flatSettings())); + } + if (request.create() != null) { + params.put("create", String.valueOf(request.create())); + } + if (request.timeout() != null) { + params.put("timeout", request.timeout()._toJsonString()); + } + return params; + + }, SimpleEndpoint.emptyMap(), true, PutTemplateResponse._DESERIALIZER); + } +} diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapper.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapper.java new file mode 100644 index 0000000000..79a269f430 --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapper.java @@ -0,0 +1,10 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import java.io.IOException; +import java.util.Optional; + +public interface IndexTemplateAPIWrapper { + void putTemplate(IndexTemplate indexTemplate) throws IOException; + + Optional getTemplate(String name) throws IOException; +} diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapperFactory.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapperFactory.java new file mode 100644 index 0000000000..0d3333c788 --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapperFactory.java @@ -0,0 +1,17 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.dataprepper.plugins.sink.opensearch.DistributionVersion; + +public class IndexTemplateAPIWrapperFactory { + public static IndexTemplateAPIWrapper getWrapper(final IndexConfiguration indexConfiguration, + final OpenSearchClient openSearchClient) { + if (DistributionVersion.ES6.equals(indexConfiguration.getDistributionVersion())) { + return new Es6IndexTemplateAPIWrapper(openSearchClient); + } else if (TemplateType.V1.equals(indexConfiguration.getTemplateType())) { + return new OpenSearchLegacyTemplateAPIWrapper(openSearchClient); + } else { + return new ComposableTemplateAPIWrapper(openSearchClient); + } + } +} diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/LegacyIndexTemplate.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/LegacyIndexTemplate.java new file mode 100644 index 0000000000..1d6e6be00e --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/LegacyIndexTemplate.java @@ -0,0 +1,48 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class LegacyIndexTemplate implements IndexTemplate { + + public static final String SETTINGS_KEY = "settings"; + private final Map templateMap; + + public LegacyIndexTemplate(final Map templateMap) { + this.templateMap = new HashMap<>(templateMap); + if(this.templateMap.containsKey(SETTINGS_KEY)) { + final HashMap copiedSettings = new HashMap<>((Map) this.templateMap.get(SETTINGS_KEY)); + this.templateMap.put(SETTINGS_KEY, copiedSettings); + } + } + + @Override + public void setTemplateName(final String name) { + templateMap.put("name", name); + } + + @Override + public void setIndexPatterns(final List indexPatterns) { + templateMap.put("index_patterns", indexPatterns); + } + + @Override + public void putCustomSetting(final String name, final Object value) { + Map settings = (Map) this.templateMap.computeIfAbsent(SETTINGS_KEY, x -> new HashMap<>()); + settings.put(name, value); + } + + @Override + public Optional getVersion() { + if(!templateMap.containsKey("version")) + return Optional.empty(); + final Number version = (Number) templateMap.get("version"); + return Optional.of(version.longValue()); + } + + Map getTemplateMap() { + return this.templateMap; + } +} diff --git a/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/OpenSearchLegacyTemplateAPIWrapper.java b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/OpenSearchLegacyTemplateAPIWrapper.java new file mode 100644 index 0000000000..366a3e6e0d --- /dev/null +++ b/data-prepper-plugins/opensearch/src/main/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/OpenSearchLegacyTemplateAPIWrapper.java @@ -0,0 +1,75 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.stream.JsonParser; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.indices.ExistsTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateResponse; +import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; +import org.opensearch.client.opensearch.indices.PutTemplateRequest; +import org.opensearch.client.opensearch.indices.TemplateMapping; +import org.opensearch.client.transport.endpoints.BooleanResponse; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Optional; + +public class OpenSearchLegacyTemplateAPIWrapper implements IndexTemplateAPIWrapper { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private final OpenSearchClient openSearchClient; + + public OpenSearchLegacyTemplateAPIWrapper(final OpenSearchClient openSearchClient) { + this.openSearchClient = openSearchClient; + } + + @Override + public void putTemplate(IndexTemplate indexTemplate) throws IOException { + if(!(indexTemplate instanceof LegacyIndexTemplate)) { + throw new IllegalArgumentException("Unexpected indexTemplate provided to createTemplate."); + } + + final Map templateMapping = ((LegacyIndexTemplate) indexTemplate).getTemplateMap(); + final String indexTemplateString = OBJECT_MAPPER.writeValueAsString(templateMapping); + + // Parse byte array to Map + final ByteArrayInputStream byteIn = new ByteArrayInputStream( + indexTemplateString.getBytes(StandardCharsets.UTF_8)); + final JsonpMapper mapper = openSearchClient._transport().jsonpMapper(); + final JsonParser parser = mapper.jsonProvider().createParser(byteIn); + + final PutTemplateRequest putTemplateRequest = PutTemplateRequestDeserializer.getJsonpDeserializer() + .deserialize(parser, mapper); + + final OpenSearchIndicesClient openSearchIndicesClient = openSearchClient.indices(); + openSearchIndicesClient.putTemplate(putTemplateRequest); + } + + @Override + public Optional getTemplate(final String templateName) throws IOException { + final ExistsTemplateRequest existsTemplateRequest = new ExistsTemplateRequest.Builder() + .name(templateName) + .build(); + final BooleanResponse booleanResponse = openSearchClient.indices().existsTemplate( + existsTemplateRequest); + if (!booleanResponse.value()) { + return Optional.empty(); + } + + final GetTemplateRequest getTemplateRequest = new GetTemplateRequest.Builder() + .name(templateName) + .build(); + final GetTemplateResponse response = openSearchClient.indices().getTemplate(getTemplateRequest); + + if (response.result().size() == 1) { + return response.result().values().stream().findFirst(); + } else { + throw new RuntimeException(String.format("Found zero or multiple index templates result when querying for %s", + templateName)); + } + } +} diff --git a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplateStrategyTest.java b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplateStrategyTest.java index fe30c4b236..00bfba3abe 100644 --- a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplateStrategyTest.java +++ b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableIndexTemplateStrategyTest.java @@ -21,6 +21,7 @@ import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; import org.opensearch.client.opensearch.indices.PutIndexTemplateRequest; import org.opensearch.client.opensearch.indices.TemplateMapping; +import org.opensearch.client.opensearch.indices.get_index_template.IndexTemplate; import org.opensearch.client.opensearch.indices.get_index_template.IndexTemplateItem; import org.opensearch.client.transport.OpenSearchTransport; import org.opensearch.client.transport.endpoints.BooleanResponse; @@ -38,15 +39,13 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -55,11 +54,8 @@ class ComposableIndexTemplateStrategyTest { private IndexTemplateAPIWrapper indexTemplateAPIWrapper; @Mock private IndexTemplateItem indexTemplateItem; -// @Mock -// private OpenSearchClient openSearchClient; -// -// @Mock -// private OpenSearchIndicesClient openSearchIndicesClient; + @Mock + private IndexTemplate indexTemplate; private Random random; private String indexTemplateName; @@ -89,229 +85,97 @@ void getExistingTemplateVersion_should_return_empty_if_no_template_exists() thro @Nested class WithExistingIndexTemplate { -// @BeforeEach -// void setUp() throws IOException { -// final BooleanResponse booleanResponse = mock(BooleanResponse.class); -// when(booleanResponse.value()).thenReturn(true); -// when(openSearchIndicesClient.existsIndexTemplate(any(ExistsIndexTemplateRequest.class))) -// .thenReturn(booleanResponse); -// } -// -// @Test -// void getExistingTemplateVersion_should_return_empty_if_index_template_exists_without_version() throws IOException { -// final GetIndexTemplateResponse getIndexTemplateResponse = mock(GetIndexTemplateResponse.class); -// final IndexTemplateItem indexTemplateItem = mock(IndexTemplateItem.class); -// org.opensearch.client.opensearch.indices.get_index_template.IndexTemplate indexTemplate = mock(org.opensearch.client.opensearch.indices.get_index_template.IndexTemplate.class); -// when(indexTemplate.version()).thenReturn(null); -// when(indexTemplateItem.indexTemplate()).thenReturn(indexTemplate); -// when(getIndexTemplateResponse.indexTemplates()).thenReturn(Collections.singletonList(indexTemplateItem)); -// when(openSearchIndicesClient.getIndexTemplate(any(GetIndexTemplateRequest.class))) -// .thenReturn(getIndexTemplateResponse); -// -// final Optional optionalVersion = createObjectUnderTest().getExistingTemplateVersion(indexTemplateName); -// -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(false)); -// } -// -// @Test -// void getExistingTemplateVersion_should_return_template_version_if_template_exists() throws IOException { -// final Long version = (long) (random.nextInt(10_000) + 100); -// final GetIndexTemplateResponse getIndexTemplateResponse = mock(GetIndexTemplateResponse.class); -// final IndexTemplateItem indexTemplateItem = mock(IndexTemplateItem.class); -// org.opensearch.client.opensearch.indices.get_index_template.IndexTemplate indexTemplate = mock(org.opensearch.client.opensearch.indices.get_index_template.IndexTemplate.class); -// when(indexTemplate.version()).thenReturn(version); -// when(indexTemplateItem.indexTemplate()).thenReturn(indexTemplate); -// when(getIndexTemplateResponse.indexTemplates()).thenReturn(Collections.singletonList(indexTemplateItem)); -// when(openSearchIndicesClient.getIndexTemplate(any(GetIndexTemplateRequest.class))) -// .thenReturn(getIndexTemplateResponse); -// -// final Optional optionalVersion = createObjectUnderTest().getExistingTemplateVersion(indexTemplateName); -// -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(true)); -// assertThat(optionalVersion.get(), equalTo(version)); -// } -// -// @ParameterizedTest -// @ValueSource(ints = {0, 2}) -// void getExistingTemplateVersion_should_throw_if_get_template_returns_unexpected_number_of_templates(final int numberOfTemplatesReturned) throws IOException { -// final GetIndexTemplateResponse getIndexTemplateResponse = mock(GetIndexTemplateResponse.class); -// final List templateResult = mock(List.class); -// when(templateResult.size()).thenReturn(numberOfTemplatesReturned); -// when(getIndexTemplateResponse.indexTemplates()).thenReturn(templateResult); -// when(openSearchIndicesClient.getIndexTemplate(any(GetIndexTemplateRequest.class))) -// .thenReturn(getIndexTemplateResponse); -// -// -// final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); -// assertThrows(RuntimeException.class, () -> objectUnderTest.getExistingTemplateVersion(indexTemplateName)); -// -// verify(openSearchIndicesClient).getIndexTemplate(any(GetIndexTemplateRequest.class)); -// } + @Test + void getExistingTemplateVersion_should_return_empty_if_index_template_exists_without_version() throws IOException { + when(indexTemplateAPIWrapper.getTemplate(any())).thenReturn(Optional.of(indexTemplateItem)); + when(indexTemplateItem.indexTemplate()).thenReturn(indexTemplate); + when(indexTemplate.version()).thenReturn(null); + + final Optional optionalVersion = createObjectUnderTest().getExistingTemplateVersion(indexTemplateName); + + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(false)); + } + + @Test + void getExistingTemplateVersion_should_return_template_version_if_template_exists() throws IOException { + final Long version = (long) (random.nextInt(10_000) + 100); + when(indexTemplateAPIWrapper.getTemplate(any())).thenReturn(Optional.of(indexTemplateItem)); + when(indexTemplateItem.indexTemplate()).thenReturn(indexTemplate); + when(indexTemplate.version()).thenReturn(version); + + final Optional optionalVersion = createObjectUnderTest().getExistingTemplateVersion(indexTemplateName); + + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(true)); + assertThat(optionalVersion.get(), equalTo(version)); + } + } + + @Test + void createTemplate_throws_if_putTemplate_throws() throws IOException { + doThrow(IOException.class).when(indexTemplateAPIWrapper).putTemplate(any()); + final org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate indexTemplate = mock( + org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate.class); + final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); + + assertThrows(IOException.class, () -> objectUnderTest.createTemplate(indexTemplate)); + } + + @Test + void createTemplate_performs_putTemplate_request() throws IOException { + final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); + final org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate indexTemplate = mock(org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate.class); + + objectUnderTest.createTemplate(indexTemplate); + verify(indexTemplateAPIWrapper).putTemplate(indexTemplate); + } + + @Nested + class IndexTemplateTests { + private Map providedTemplateMap; + + @BeforeEach + void setUp() { + providedTemplateMap = new HashMap<>(); + } + + @Test + void getVersion_returns_empty_if_no_version() { + final org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate indexTemplate = + createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + final Optional optionalVersion = indexTemplate.getVersion(); + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(false)); + } + + @Test + void getVersion_returns_version_from_root_map() { + final Long version = (long) (random.nextInt(10_000) + 100); + providedTemplateMap.put("version", version); + + final org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate indexTemplate = + createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + final Optional optionalVersion = indexTemplate.getVersion(); + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(true)); + assertThat(optionalVersion.get(), equalTo(version)); + } + + @Test + void getVersion_returns_version_from_root_map_when_provided_as_int() { + final Integer version = random.nextInt(10_000) + 100; + providedTemplateMap.put("version", version); + + final org.opensearch.dataprepper.plugins.sink.opensearch.index.IndexTemplate indexTemplate = + createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + final Optional optionalVersion = indexTemplate.getVersion(); + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(true)); + assertThat(optionalVersion.get(), equalTo((long) version)); + } } -// -// @Test -// void createTemplate_throws_if_template_is_not_ComposableIndexTemplate() { -// final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); -// final IndexTemplate indexTemplate = mock(IndexTemplate.class); -// -// final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); -// -// assertThrows(IllegalArgumentException.class, () -> objectUnderTest.createTemplate( -// indexConfiguration, indexTemplate)); -// } -// -// @Nested -// class IndexTemplateWithCreateTemplateTests { -// private ArgumentCaptor putIndexTemplateRequestArgumentCaptor; -// private List indexPatterns; -// -// @BeforeEach -// void setUp() { -// final OpenSearchTransport openSearchTransport = mock(OpenSearchTransport.class); -// when(openSearchClient._transport()).thenReturn(openSearchTransport); -// when(openSearchTransport.jsonpMapper()).thenReturn(new PreSerializedJsonpMapper()); -// -// putIndexTemplateRequestArgumentCaptor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class); -// -// indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); -// } -// -// @Test -// void createTemplate_with_setTemplateName_performs_putIndexTemplate_request() throws IOException { -// final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); -// -// final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); -// final IndexTemplate indexTemplate = objectUnderTest.createIndexTemplate(new HashMap<>()); -// indexTemplate.setTemplateName(indexTemplateName); -// objectUnderTest.createTemplate(indexConfiguration, indexTemplate); -// -// verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); -// -// final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); -// -// assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); -// -// assertThat(actualPutRequest.version(), nullValue()); -// assertThat(actualPutRequest.indexPatterns(), notNullValue()); -// assertThat(actualPutRequest.indexPatterns(), equalTo(Collections.emptyList())); -// assertThat(actualPutRequest.template(), nullValue()); -// assertThat(actualPutRequest.priority(), nullValue()); -// assertThat(actualPutRequest.composedOf(), notNullValue()); -// assertThat(actualPutRequest.composedOf(), equalTo(Collections.emptyList())); -// } -// -// @Test -// void createTemplate_with_setIndexPatterns_performs_putIndexTemplate_request() throws IOException { -// final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); -// -// final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); -// -// final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); -// final IndexTemplate indexTemplate = objectUnderTest.createIndexTemplate(new HashMap<>()); -// indexTemplate.setTemplateName(indexTemplateName); -// indexTemplate.setIndexPatterns(indexPatterns); -// objectUnderTest.createTemplate(indexConfiguration, indexTemplate); -// -// verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); -// -// final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); -// -// assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); -// assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); -// -// assertThat(actualPutRequest.version(), nullValue()); -// assertThat(actualPutRequest.template(), nullValue()); -// assertThat(actualPutRequest.priority(), nullValue()); -// assertThat(actualPutRequest.composedOf(), notNullValue()); -// assertThat(actualPutRequest.composedOf(), equalTo(Collections.emptyList())); -// } -// -// @Test -// void createTemplate_with_defined_template_values_performs_putIndexTemplate_request() throws IOException { -// final ComposableIndexTemplateStrategy objectUnderTest = createObjectUnderTest(); -// -// final Long version = (long) (random.nextInt(10_000) + 100); -// final int priority = random.nextInt(1000) + 100; -// final String numberOfShards = Integer.toString(random.nextInt(1000) + 100); -// final List composedOf = Collections.singletonList(UUID.randomUUID().toString()); -// -// final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); -// final IndexTemplate indexTemplate = objectUnderTest.createIndexTemplate( -// Map.of("version", version, -// "priority", priority, -// "composed_of", composedOf, -// "template", Map.of( -// "settings", Map.of( -// "index", Map.of("number_of_shards", numberOfShards)), -// "mappings", Map.of("date_detection", true) -// ) -// )); -// indexTemplate.setTemplateName(indexTemplateName); -// indexTemplate.setIndexPatterns(indexPatterns); -// objectUnderTest.createTemplate(indexConfiguration, indexTemplate); -// -// verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); -// -// final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); -// -// assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); -// assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); -// assertThat(actualPutRequest.version(), equalTo(version)); -// assertThat(actualPutRequest.priority(), equalTo(priority)); -// assertThat(actualPutRequest.composedOf(), equalTo(composedOf)); -// assertThat(actualPutRequest.template(), notNullValue()); -// assertThat(actualPutRequest.template().mappings(), notNullValue()); -// assertThat(actualPutRequest.template().mappings().dateDetection(), equalTo(true)); -// assertThat(actualPutRequest.template().settings(), notNullValue()); -// assertThat(actualPutRequest.template().settings().index(), notNullValue()); -// assertThat(actualPutRequest.template().settings().index().numberOfShards(), equalTo(numberOfShards)); -// } -// } -// -// @Nested -// class IndexTemplateTests { -// private Map providedTemplateMap; -// -// @BeforeEach -// void setUp() { -// providedTemplateMap = new HashMap<>(); -// } -// -// @Test -// void getVersion_returns_empty_if_no_version() { -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// final Optional optionalVersion = indexTemplate.getVersion(); -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(false)); -// } -// -// @Test -// void getVersion_returns_version_from_root_map() { -// final Long version = (long) (random.nextInt(10_000) + 100); -// providedTemplateMap.put("version", version); -// -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// final Optional optionalVersion = indexTemplate.getVersion(); -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(true)); -// assertThat(optionalVersion.get(), equalTo(version)); -// } -// -// @Test -// void getVersion_returns_version_from_root_map_when_provided_as_int() { -// final Integer version = random.nextInt(10_000) + 100; -// providedTemplateMap.put("version", version); -// -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// final Optional optionalVersion = indexTemplate.getVersion(); -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(true)); -// assertThat(optionalVersion.get(), equalTo((long) version)); -// } -// } } \ No newline at end of file diff --git a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableTemplateAPIWrapperTest.java b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableTemplateAPIWrapperTest.java new file mode 100644 index 0000000000..0ca4066922 --- /dev/null +++ b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/ComposableTemplateAPIWrapperTest.java @@ -0,0 +1,260 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.indices.ExistsIndexTemplateRequest; +import org.opensearch.client.opensearch.indices.GetIndexTemplateRequest; +import org.opensearch.client.opensearch.indices.GetIndexTemplateResponse; +import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; +import org.opensearch.client.opensearch.indices.PutIndexTemplateRequest; +import org.opensearch.client.opensearch.indices.get_index_template.IndexTemplateItem; +import org.opensearch.client.transport.OpenSearchTransport; +import org.opensearch.client.transport.endpoints.BooleanResponse; +import org.opensearch.dataprepper.plugins.sink.opensearch.bulk.PreSerializedJsonpMapper; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.UUID; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ComposableTemplateAPIWrapperTest { + @Mock + private OpenSearchClient openSearchClient; + @Mock + private OpenSearchIndicesClient openSearchIndicesClient; + @Mock + private OpenSearchTransport openSearchTransport; + @Mock + private GetIndexTemplateResponse getIndexTemplateResponse; + @Mock + private BooleanResponse booleanResponse; + @Captor + private ArgumentCaptor putIndexTemplateRequestArgumentCaptor; + @Captor + private ArgumentCaptor existsIndexTemplateRequestArgumentCaptor; + + private String indexTemplateName; + private ComposableTemplateAPIWrapper objectUnderTest; + private Random random; + + @BeforeEach + void setUp() { + random = new Random(); + objectUnderTest = new ComposableTemplateAPIWrapper(openSearchClient); + lenient().when(openSearchClient.indices()).thenReturn(openSearchIndicesClient); + indexTemplateName = UUID.randomUUID().toString(); + } + + @Test + void putTemplate_throws_if_template_is_not_ComposableIndexTemplate() { + final IndexTemplate indexTemplate = mock(IndexTemplate.class); + assertThrows(IllegalArgumentException.class, () -> objectUnderTest.putTemplate(indexTemplate)); + } + + @Test + void putTemplate_performs_putIndexTemplate_request() throws IOException { + when(openSearchClient._transport()).thenReturn(openSearchTransport); + when(openSearchTransport.jsonpMapper()).thenReturn(new PreSerializedJsonpMapper()); + + final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); + final IndexTemplate indexTemplate = new ComposableIndexTemplate(new HashMap<>()); + indexTemplate.setTemplateName(indexTemplateName); + indexTemplate.setIndexPatterns(indexPatterns); + objectUnderTest.putTemplate(indexTemplate); + + verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); + + final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); + + assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); + assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); + } + + @Test + void getExistingTemplate_should_calls_existIndexTemplate_with_templateName() throws IOException { + when(booleanResponse.value()).thenReturn(false); + when(openSearchIndicesClient.existsIndexTemplate(any(ExistsIndexTemplateRequest.class))) + .thenReturn(booleanResponse); + + objectUnderTest.getTemplate(indexTemplateName); + + verify(openSearchIndicesClient).existsIndexTemplate(existsIndexTemplateRequestArgumentCaptor.capture()); + + final ExistsIndexTemplateRequest actualRequest = existsIndexTemplateRequestArgumentCaptor.getValue(); + assertThat(actualRequest.name(), notNullValue()); + assertThat(actualRequest.name(), equalTo(indexTemplateName)); + } + + @Test + void getExistingTemplate_should_return_empty_if_no_index_template_exists() throws IOException { + when(booleanResponse.value()).thenReturn(false); + when(openSearchIndicesClient.existsIndexTemplate(any(ExistsIndexTemplateRequest.class))) + .thenReturn(booleanResponse); + + final Optional optionalIndexTemplateItem = objectUnderTest.getTemplate(indexTemplateName); + + assertThat(optionalIndexTemplateItem, notNullValue()); + assertThat(optionalIndexTemplateItem.isPresent(), equalTo(false)); + } + + @ParameterizedTest + @ValueSource(ints = {0, 2}) + void getExistingTemplate_should_throw_if_get_template_returns_unexpected_number_of_templates(final int numberOfTemplatesReturned) throws IOException { + when(booleanResponse.value()).thenReturn(true); + when(openSearchIndicesClient.existsIndexTemplate(any(ExistsIndexTemplateRequest.class))) + .thenReturn(booleanResponse); + final List indexTemplateItems = mock(List.class); + when(indexTemplateItems.size()).thenReturn(numberOfTemplatesReturned); + when(getIndexTemplateResponse.indexTemplates()).thenReturn(indexTemplateItems); + when(openSearchIndicesClient.getIndexTemplate(any(GetIndexTemplateRequest.class))) + .thenReturn(getIndexTemplateResponse); + + assertThrows(RuntimeException.class, () -> objectUnderTest.getTemplate(indexTemplateName)); + + verify(openSearchIndicesClient).getIndexTemplate(any(GetIndexTemplateRequest.class)); + } + + @Test + void getExistingTemplate_should_return_template_if_template_exists() throws IOException { + when(booleanResponse.value()).thenReturn(true); + when(openSearchIndicesClient.existsIndexTemplate(any(ExistsIndexTemplateRequest.class))) + .thenReturn(booleanResponse); + final IndexTemplateItem indexTemplateItem = mock(IndexTemplateItem.class); + when(getIndexTemplateResponse.indexTemplates()).thenReturn(Collections.singletonList(indexTemplateItem)); + when(openSearchIndicesClient.getIndexTemplate(any(GetIndexTemplateRequest.class))) + .thenReturn(getIndexTemplateResponse); + + final Optional optionalIndexTemplateItem = objectUnderTest.getTemplate(indexTemplateName); + + assertThat(optionalIndexTemplateItem, notNullValue()); + assertThat(optionalIndexTemplateItem.isPresent(), equalTo(true)); + assertThat(optionalIndexTemplateItem.get(), equalTo(indexTemplateItem)); + } + + + @Nested + class IndexTemplateWithCreateTemplateTests { + private ArgumentCaptor putIndexTemplateRequestArgumentCaptor; + private List indexPatterns; + + @BeforeEach + void setUp() { + final OpenSearchTransport openSearchTransport = mock(OpenSearchTransport.class); + when(openSearchClient._transport()).thenReturn(openSearchTransport); + when(openSearchTransport.jsonpMapper()).thenReturn(new PreSerializedJsonpMapper()); + + putIndexTemplateRequestArgumentCaptor = ArgumentCaptor.forClass(PutIndexTemplateRequest.class); + + indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); + } + + @Test + void putTemplate_with_setTemplateName_performs_putIndexTemplate_request() throws IOException { + final IndexTemplate indexTemplate = new ComposableIndexTemplate(new HashMap<>()); + indexTemplate.setTemplateName(indexTemplateName); + objectUnderTest.putTemplate(indexTemplate); + + verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); + + final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); + + assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); + + assertThat(actualPutRequest.version(), nullValue()); + assertThat(actualPutRequest.indexPatterns(), notNullValue()); + assertThat(actualPutRequest.indexPatterns(), equalTo(Collections.emptyList())); + assertThat(actualPutRequest.template(), nullValue()); + assertThat(actualPutRequest.priority(), nullValue()); + assertThat(actualPutRequest.composedOf(), notNullValue()); + assertThat(actualPutRequest.composedOf(), equalTo(Collections.emptyList())); + } + + @Test + void putTemplate_with_setIndexPatterns_performs_putIndexTemplate_request() throws IOException { + final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); + + final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); + final IndexTemplate indexTemplate = new ComposableIndexTemplate(new HashMap<>()); + indexTemplate.setTemplateName(indexTemplateName); + indexTemplate.setIndexPatterns(indexPatterns); + objectUnderTest.putTemplate(indexTemplate); + + verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); + + final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); + + assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); + assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); + + assertThat(actualPutRequest.version(), nullValue()); + assertThat(actualPutRequest.template(), nullValue()); + assertThat(actualPutRequest.priority(), nullValue()); + assertThat(actualPutRequest.composedOf(), notNullValue()); + assertThat(actualPutRequest.composedOf(), equalTo(Collections.emptyList())); + } + + @Test + void putTemplate_with_defined_template_values_performs_putIndexTemplate_request() throws IOException { + final Long version = (long) (random.nextInt(10_000) + 100); + final int priority = random.nextInt(1000) + 100; + final String numberOfShards = Integer.toString(random.nextInt(1000) + 100); + final List composedOf = Collections.singletonList(UUID.randomUUID().toString()); + + final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); + final IndexTemplate indexTemplate = new ComposableIndexTemplate( + Map.of("version", version, + "priority", priority, + "composed_of", composedOf, + "template", Map.of( + "settings", Map.of( + "index", Map.of("number_of_shards", numberOfShards)), + "mappings", Map.of("date_detection", true) + ) + )); + indexTemplate.setTemplateName(indexTemplateName); + indexTemplate.setIndexPatterns(indexPatterns); + objectUnderTest.putTemplate(indexTemplate); + + verify(openSearchIndicesClient).putIndexTemplate(putIndexTemplateRequestArgumentCaptor.capture()); + + final PutIndexTemplateRequest actualPutRequest = putIndexTemplateRequestArgumentCaptor.getValue(); + + assertThat(actualPutRequest.name(), equalTo(indexTemplateName)); + assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); + assertThat(actualPutRequest.version(), equalTo(version)); + assertThat(actualPutRequest.priority(), equalTo(priority)); + assertThat(actualPutRequest.composedOf(), equalTo(composedOf)); + assertThat(actualPutRequest.template(), notNullValue()); + assertThat(actualPutRequest.template().mappings(), notNullValue()); + assertThat(actualPutRequest.template().mappings().dateDetection(), equalTo(true)); + assertThat(actualPutRequest.template().settings(), notNullValue()); + assertThat(actualPutRequest.template().settings().index(), notNullValue()); + assertThat(actualPutRequest.template().settings().index().numberOfShards(), equalTo(numberOfShards)); + } + } +} \ No newline at end of file diff --git a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/Es6IndexTemplateAPIWrapperTest.java b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/Es6IndexTemplateAPIWrapperTest.java new file mode 100644 index 0000000000..f53794675e --- /dev/null +++ b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/Es6IndexTemplateAPIWrapperTest.java @@ -0,0 +1,175 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch._types.ErrorResponse; +import org.opensearch.client.opensearch.indices.ExistsTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateResponse; +import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; +import org.opensearch.client.opensearch.indices.PutTemplateRequest; +import org.opensearch.client.opensearch.indices.PutTemplateResponse; +import org.opensearch.client.opensearch.indices.TemplateMapping; +import org.opensearch.client.transport.JsonEndpoint; +import org.opensearch.client.transport.OpenSearchTransport; +import org.opensearch.client.transport.TransportOptions; +import org.opensearch.client.transport.endpoints.BooleanResponse; +import org.opensearch.dataprepper.plugins.sink.opensearch.bulk.PreSerializedJsonpMapper; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.UUID; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class Es6IndexTemplateAPIWrapperTest { + @Mock + private OpenSearchClient openSearchClient; + @Mock + private OpenSearchIndicesClient openSearchIndicesClient; + @Mock + private OpenSearchTransport openSearchTransport; + @Mock + private GetTemplateResponse getTemplateResponse; + @Mock + private BooleanResponse booleanResponse; + @Mock + private TransportOptions transportOptions; + @Captor + private ArgumentCaptor putTemplateRequestArgumentCaptor; + @Captor + private ArgumentCaptor> jsonEndpointArgumentCaptor; + @Captor + private ArgumentCaptor existsTemplateRequestArgumentCaptor; + + private String templateName; + private Es6IndexTemplateAPIWrapper objectUnderTest; + + @BeforeEach + void setUp() { + objectUnderTest = new Es6IndexTemplateAPIWrapper(openSearchClient); + lenient().when(openSearchClient.indices()).thenReturn(openSearchIndicesClient); + templateName = UUID.randomUUID().toString(); + } + + @Test + void putTemplate_throws_if_template_is_not_LegacyIndexTemplate() { + final IndexTemplate indexTemplate = mock(IndexTemplate.class); + assertThrows(IllegalArgumentException.class, () -> objectUnderTest.putTemplate( + indexTemplate)); + } + + @Test + void putTemplate_performs_perform_request() throws IOException { + when(openSearchClient._transport()).thenReturn(openSearchTransport); + when(openSearchIndicesClient._transport()).thenReturn(openSearchTransport); + when(openSearchIndicesClient._transportOptions()).thenReturn(transportOptions); + when(openSearchTransport.jsonpMapper()).thenReturn(new PreSerializedJsonpMapper()); + + final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); + final IndexTemplate indexTemplate = new LegacyIndexTemplate(new HashMap<>()); + indexTemplate.setTemplateName(templateName); + indexTemplate.setIndexPatterns(indexPatterns); + objectUnderTest.putTemplate(indexTemplate); + + verify(openSearchTransport).performRequest( + putTemplateRequestArgumentCaptor.capture(), jsonEndpointArgumentCaptor.capture(), eq(transportOptions)); + + final PutTemplateRequest actualPutRequest = putTemplateRequestArgumentCaptor.getValue(); + + assertThat(actualPutRequest.name(), equalTo(templateName)); + assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); + final JsonEndpoint endpoint = jsonEndpointArgumentCaptor.getValue(); + assertThat(endpoint.requestUrl(actualPutRequest), equalTo( + String.format("/_template/%s?include_type_name=false", templateName))); + } + + @Test + void getExistingTemplate_should_calls_existTemplate_with_templateName() throws IOException { + when(booleanResponse.value()).thenReturn(false); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + + objectUnderTest.getTemplate(templateName); + + verify(openSearchIndicesClient).existsTemplate(existsTemplateRequestArgumentCaptor.capture()); + + final ExistsTemplateRequest actualRequest = existsTemplateRequestArgumentCaptor.getValue(); + assertThat(actualRequest.name(), notNullValue()); + assertAll( + () -> assertThat(actualRequest.name().size(), equalTo(1)), + () -> assertThat(actualRequest.name(), hasItem(templateName)) + ); + } + + @Test + void getExistingTemplate_should_return_empty_if_no_template_exists() throws IOException { + when(booleanResponse.value()).thenReturn(false); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + + final Optional optionalTemplateMapping = objectUnderTest.getTemplate(templateName); + + assertThat(optionalTemplateMapping, notNullValue()); + assertThat(optionalTemplateMapping.isPresent(), equalTo(false)); + } + + @ParameterizedTest + @ValueSource(ints = {0, 2}) + void getExistingTemplate_should_throw_if_get_template_returns_unexpected_number_of_templates(final int numberOfTemplatesReturned) throws IOException { + when(booleanResponse.value()).thenReturn(true); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + final Map templateResult = mock(Map.class); + when(templateResult.size()).thenReturn(numberOfTemplatesReturned); + when(getTemplateResponse.result()).thenReturn(templateResult); + when(openSearchIndicesClient.getTemplate(any(GetTemplateRequest.class))) + .thenReturn(getTemplateResponse); + + assertThrows(RuntimeException.class, () -> objectUnderTest.getTemplate(templateName)); + + verify(openSearchIndicesClient).getTemplate(any(GetTemplateRequest.class)); + } + + @Test + void getExistingTemplate_should_return_template_if_template_exists() throws IOException { + when(booleanResponse.value()).thenReturn(true); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + final TemplateMapping templateMapping = mock(TemplateMapping.class); + when(getTemplateResponse.result()).thenReturn(Collections.singletonMap(templateName, templateMapping)); + when(openSearchIndicesClient.getTemplate(any(GetTemplateRequest.class))) + .thenReturn(getTemplateResponse); + + final Optional optionalTemplateMapping = objectUnderTest.getTemplate(templateName); + + assertThat(optionalTemplateMapping, notNullValue()); + assertThat(optionalTemplateMapping.isPresent(), equalTo(true)); + assertThat(optionalTemplateMapping.get(), equalTo(templateMapping)); + } +} \ No newline at end of file diff --git a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapperFactoryTest.java b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapperFactoryTest.java new file mode 100644 index 0000000000..7f5f4ef4d7 --- /dev/null +++ b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/IndexTemplateAPIWrapperFactoryTest.java @@ -0,0 +1,44 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.dataprepper.plugins.sink.opensearch.DistributionVersion; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class IndexTemplateAPIWrapperFactoryTest { + @Mock + private IndexConfiguration indexConfiguration; + + @Mock + private OpenSearchClient openSearchClient; + + @Test + void testGetEs6IndexTemplateAPIWrapper() { + when(indexConfiguration.getDistributionVersion()).thenReturn(DistributionVersion.ES6); + assertThat(IndexTemplateAPIWrapperFactory.getWrapper(indexConfiguration, openSearchClient), + instanceOf(Es6IndexTemplateAPIWrapper.class)); + } + + @Test + void testGetOpenSearchLegacyTemplateAPIWrapper() { + when(indexConfiguration.getDistributionVersion()).thenReturn(DistributionVersion.DEFAULT); + when(indexConfiguration.getTemplateType()).thenReturn(TemplateType.V1); + assertThat(IndexTemplateAPIWrapperFactory.getWrapper(indexConfiguration, openSearchClient), + instanceOf(OpenSearchLegacyTemplateAPIWrapper.class)); + } + + @Test + void testGetComposableTemplateAPIWrapper() { + when(indexConfiguration.getDistributionVersion()).thenReturn(DistributionVersion.DEFAULT); + when(indexConfiguration.getTemplateType()).thenReturn(TemplateType.INDEX_TEMPLATE); + assertThat(IndexTemplateAPIWrapperFactory.getWrapper(indexConfiguration, openSearchClient), + instanceOf(ComposableTemplateAPIWrapper.class)); + } +} \ No newline at end of file diff --git a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/OpenSearchLegacyTemplateAPIWrapperTest.java b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/OpenSearchLegacyTemplateAPIWrapperTest.java new file mode 100644 index 0000000000..bb3c883952 --- /dev/null +++ b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/OpenSearchLegacyTemplateAPIWrapperTest.java @@ -0,0 +1,162 @@ +package org.opensearch.dataprepper.plugins.sink.opensearch.index; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.indices.ExistsTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateRequest; +import org.opensearch.client.opensearch.indices.GetTemplateResponse; +import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; +import org.opensearch.client.opensearch.indices.PutTemplateRequest; +import org.opensearch.client.opensearch.indices.TemplateMapping; +import org.opensearch.client.transport.OpenSearchTransport; +import org.opensearch.client.transport.endpoints.BooleanResponse; +import org.opensearch.dataprepper.plugins.sink.opensearch.bulk.PreSerializedJsonpMapper; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.UUID; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class OpenSearchLegacyTemplateAPIWrapperTest { + @Mock + private OpenSearchClient openSearchClient; + @Mock + private OpenSearchIndicesClient openSearchIndicesClient; + @Mock + private OpenSearchTransport openSearchTransport; + @Mock + private GetTemplateResponse getTemplateResponse; + @Mock + private BooleanResponse booleanResponse; + @Captor + private ArgumentCaptor putTemplateRequestArgumentCaptor; + @Captor + private ArgumentCaptor existsTemplateRequestArgumentCaptor; + + private String templateName; + private OpenSearchLegacyTemplateAPIWrapper objectUnderTest; + private Random random; + + @BeforeEach + void setUp() { + random = new Random(); + objectUnderTest = new OpenSearchLegacyTemplateAPIWrapper(openSearchClient); + lenient().when(openSearchClient.indices()).thenReturn(openSearchIndicesClient); + templateName = UUID.randomUUID().toString(); + } + + @Test + void putTemplate_throws_if_template_is_not_LegacyIndexTemplate() { + final IndexTemplate indexTemplate = mock(IndexTemplate.class); + assertThrows(IllegalArgumentException.class, () -> objectUnderTest.putTemplate( + indexTemplate)); + } + + @Test + void putTemplate_performs_putTemplate_request() throws IOException { + when(openSearchClient._transport()).thenReturn(openSearchTransport); + when(openSearchTransport.jsonpMapper()).thenReturn(new PreSerializedJsonpMapper()); + + final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); + final IndexTemplate indexTemplate = new LegacyIndexTemplate(new HashMap<>()); + indexTemplate.setTemplateName(templateName); + indexTemplate.setIndexPatterns(indexPatterns); + objectUnderTest.putTemplate(indexTemplate); + + verify(openSearchIndicesClient).putTemplate(putTemplateRequestArgumentCaptor.capture()); + + final PutTemplateRequest actualPutRequest = putTemplateRequestArgumentCaptor.getValue(); + + assertThat(actualPutRequest.name(), equalTo(templateName)); + assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); + } + + @Test + void getExistingTemplate_should_calls_existTemplate_with_templateName() throws IOException { + when(booleanResponse.value()).thenReturn(false); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + + objectUnderTest.getTemplate(templateName); + + verify(openSearchIndicesClient).existsTemplate(existsTemplateRequestArgumentCaptor.capture()); + + final ExistsTemplateRequest actualRequest = existsTemplateRequestArgumentCaptor.getValue(); + assertThat(actualRequest.name(), notNullValue()); + assertAll( + () -> assertThat(actualRequest.name().size(), equalTo(1)), + () -> assertThat(actualRequest.name(), hasItem(templateName)) + ); + } + + @Test + void getExistingTemplate_should_return_empty_if_no_template_exists() throws IOException { + when(booleanResponse.value()).thenReturn(false); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + + final Optional optionalTemplateMapping = objectUnderTest.getTemplate(templateName); + + assertThat(optionalTemplateMapping, notNullValue()); + assertThat(optionalTemplateMapping.isPresent(), equalTo(false)); + } + + @ParameterizedTest + @ValueSource(ints = {0, 2}) + void getExistingTemplate_should_throw_if_get_template_returns_unexpected_number_of_templates(final int numberOfTemplatesReturned) throws IOException { + when(booleanResponse.value()).thenReturn(true); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + final Map templateResult = mock(Map.class); + when(templateResult.size()).thenReturn(numberOfTemplatesReturned); + when(getTemplateResponse.result()).thenReturn(templateResult); + when(openSearchIndicesClient.getTemplate(any(GetTemplateRequest.class))) + .thenReturn(getTemplateResponse); + + assertThrows(RuntimeException.class, () -> objectUnderTest.getTemplate(templateName)); + + verify(openSearchIndicesClient).getTemplate(any(GetTemplateRequest.class)); + } + + @Test + void getExistingTemplate_should_return_template_if_template_exists() throws IOException { + when(booleanResponse.value()).thenReturn(true); + when(openSearchIndicesClient.existsTemplate(any(ExistsTemplateRequest.class))) + .thenReturn(booleanResponse); + final TemplateMapping templateMapping = mock(TemplateMapping.class); + when(getTemplateResponse.result()).thenReturn(Collections.singletonMap(templateName, templateMapping)); + when(openSearchIndicesClient.getTemplate(any(GetTemplateRequest.class))) + .thenReturn(getTemplateResponse); + + final Optional optionalTemplateMapping = objectUnderTest.getTemplate(templateName); + + assertThat(optionalTemplateMapping, notNullValue()); + assertThat(optionalTemplateMapping.isPresent(), equalTo(true)); + assertThat(optionalTemplateMapping.get(), equalTo(templateMapping)); + } +} \ No newline at end of file diff --git a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/V1TemplateStrategyTest.java b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/V1TemplateStrategyTest.java index 93ea637ec4..93b2885fe8 100644 --- a/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/V1TemplateStrategyTest.java +++ b/data-prepper-plugins/opensearch/src/test/java/org/opensearch/dataprepper/plugins/sink/opensearch/index/V1TemplateStrategyTest.java @@ -9,29 +9,9 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.opensearch.client.opensearch.OpenSearchClient; -import org.opensearch.client.opensearch._types.ErrorResponse; -import org.opensearch.client.opensearch.core.BulkRequest; -import org.opensearch.client.opensearch.core.BulkResponse; -import org.opensearch.client.opensearch.indices.ExistsTemplateRequest; -import org.opensearch.client.opensearch.indices.GetTemplateRequest; -import org.opensearch.client.opensearch.indices.GetTemplateResponse; -import org.opensearch.client.opensearch.indices.OpenSearchIndicesClient; -import org.opensearch.client.opensearch.indices.PutTemplateRequest; -import org.opensearch.client.opensearch.indices.PutTemplateResponse; import org.opensearch.client.opensearch.indices.TemplateMapping; -import org.opensearch.client.transport.JsonEndpoint; -import org.opensearch.client.transport.OpenSearchTransport; -import org.opensearch.client.transport.TransportOptions; -import org.opensearch.client.transport.endpoints.BooleanResponse; -import org.opensearch.dataprepper.plugins.sink.opensearch.DistributionVersion; -import org.opensearch.dataprepper.plugins.sink.opensearch.bulk.PreSerializedJsonpMapper; import java.io.IOException; import java.util.Collections; @@ -43,19 +23,16 @@ import java.util.UUID; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasKey; -import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -66,14 +43,6 @@ class V1TemplateStrategyTest { private IndexTemplateAPIWrapper indexTemplateAPIWrapper; @Mock private TemplateMapping templateMapping; -// @Mock -// private OpenSearchClient openSearchClient; -// -// @Mock -// private OpenSearchIndicesClient openSearchIndicesClient; -// -// @Captor -// private ArgumentCaptor> jsonEndpointArgumentCaptor; private Random random; private String templateName; @@ -145,159 +114,127 @@ void createTemplate_performs_putTemplate_request() throws IOException { objectUnderTest.createTemplate(indexTemplate); verify(indexTemplateAPIWrapper).putTemplate(indexTemplate); } -// -// @Test -// void createTemplate_es6() throws IOException { -// final OpenSearchTransport openSearchTransport = mock(OpenSearchTransport.class); -// when(openSearchClient._transport()).thenReturn(openSearchTransport); -// when(openSearchTransport.jsonpMapper()).thenReturn(new PreSerializedJsonpMapper()); -// final OpenSearchTransport openSearchTransport1 = mock(OpenSearchTransport.class); -// when(openSearchIndicesClient._transport()).thenReturn(openSearchTransport1); -// final TransportOptions transportOptions = mock(TransportOptions.class); -// when(openSearchIndicesClient._transportOptions()).thenReturn(transportOptions); -// final V1TemplateStrategy objectUnderTest = createObjectUnderTest(); -// -// final IndexConfiguration indexConfiguration = mock(IndexConfiguration.class); -// when(indexConfiguration.getDistributionVersion()).thenReturn(DistributionVersion.ES6); -// final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); -// final IndexTemplate indexTemplate = objectUnderTest.createIndexTemplate(new HashMap<>()); -// indexTemplate.setTemplateName(templateName); -// indexTemplate.setIndexPatterns(indexPatterns); -// objectUnderTest.createTemplate(indexConfiguration, indexTemplate); -// -// final ArgumentCaptor putTemplateRequestArgumentCaptor = ArgumentCaptor.forClass(PutTemplateRequest.class); -// verify(openSearchTransport1).performRequest( -// putTemplateRequestArgumentCaptor.capture(), jsonEndpointArgumentCaptor.capture(), eq(transportOptions)); -// -// final PutTemplateRequest actualPutRequest = putTemplateRequestArgumentCaptor.getValue(); -// -// assertThat(actualPutRequest.name(), equalTo(templateName)); -// assertThat(actualPutRequest.indexPatterns(), equalTo(indexPatterns)); -// final JsonEndpoint endpoint = jsonEndpointArgumentCaptor.getValue(); -// assertThat(endpoint.requestUrl(actualPutRequest), equalTo( -// String.format("/_template/%s?include_type_name=false", templateName))); -// } -// -// @Nested -// class IndexTemplateTests { -// private Map providedTemplateMap; -// -// @BeforeEach -// void setUp() { -// providedTemplateMap = new HashMap<>(); -// } -// -// @Test -// void createIndexTemplate_setTemplateName_sets_the_name() { -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// assertThat(indexTemplate, instanceOf(V1TemplateStrategy.LegacyIndexTemplate.class)); -// -// indexTemplate.setTemplateName(templateName); -// -// final Map returnedTemplateMap = ((V1TemplateStrategy.LegacyIndexTemplate) indexTemplate).getTemplateMap(); -// assertThat(returnedTemplateMap, hasKey("name")); -// assertThat(returnedTemplateMap.get("name"), equalTo(templateName)); -// -// assertThat(providedTemplateMap, not(hasKey("name"))); -// } -// -// @Test -// void createIndexTemplate_setIndexPatterns_sets_the_indexPatterns() { -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// assertThat(indexTemplate, instanceOf(V1TemplateStrategy.LegacyIndexTemplate.class)); -// -// final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); -// indexTemplate.setIndexPatterns(indexPatterns); -// -// final Map returnedTemplateMap = ((V1TemplateStrategy.LegacyIndexTemplate) indexTemplate).getTemplateMap(); -// assertThat(returnedTemplateMap, hasKey("index_patterns")); -// assertThat(returnedTemplateMap.get("index_patterns"), equalTo(indexPatterns)); -// -// assertThat(providedTemplateMap, not(hasKey("index_patterns"))); -// } -// -// @Test -// void putCustomSetting_setIndexPatterns_sets_existing_settings() { -// final String existingKey = UUID.randomUUID().toString(); -// final String existingValue = UUID.randomUUID().toString(); -// final Map providedSettings = Collections.singletonMap(existingKey, existingValue); -// providedTemplateMap.put("settings", providedSettings); -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// assertThat(indexTemplate, instanceOf(V1TemplateStrategy.LegacyIndexTemplate.class)); -// -// final String customKey = UUID.randomUUID().toString(); -// final String customValue = UUID.randomUUID().toString(); -// -// indexTemplate.putCustomSetting(customKey, customValue); -// -// final Map returnedTemplateMap = ((V1TemplateStrategy.LegacyIndexTemplate) indexTemplate).getTemplateMap(); -// assertThat(returnedTemplateMap, hasKey("settings")); -// assertThat(returnedTemplateMap.get("settings"), instanceOf(Map.class)); -// final Map settings = (Map) returnedTemplateMap.get("settings"); -// assertThat(settings, hasKey(customKey)); -// assertThat(settings.get(customKey), equalTo(customValue)); -// assertThat(settings, hasKey(existingKey)); -// assertThat(settings.get(existingKey), equalTo(existingValue)); -// -// assertThat(providedSettings, not(hasKey(customKey))); -// } -// -// @Test -// void putCustomSetting_setIndexPatterns_sets_new_settings() { -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// assertThat(indexTemplate, instanceOf(V1TemplateStrategy.LegacyIndexTemplate.class)); -// -// final String customKey = UUID.randomUUID().toString(); -// final String customValue = UUID.randomUUID().toString(); -// indexTemplate.putCustomSetting(customKey, customValue); -// -// final Map returnedTemplateMap = ((V1TemplateStrategy.LegacyIndexTemplate) indexTemplate).getTemplateMap(); -// assertThat(returnedTemplateMap, hasKey("settings")); -// assertThat(returnedTemplateMap.get("settings"), instanceOf(Map.class)); -// final Map settings = (Map) returnedTemplateMap.get("settings"); -// assertThat(settings, hasKey(customKey)); -// assertThat(settings.get(customKey), equalTo(customValue)); -// -// assertThat(providedTemplateMap, not(hasKey("settings"))); -// } -// -// @Test -// void getVersion_returns_empty_if_no_version() { -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// final Optional optionalVersion = indexTemplate.getVersion(); -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(false)); -// } -// -// @Test -// void getVersion_returns_version_from_root_map() { -// final Long version = (long) (random.nextInt(10_000) + 100); -// providedTemplateMap.put("version", version); -// -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// final Optional optionalVersion = indexTemplate.getVersion(); -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(true)); -// assertThat(optionalVersion.get(), equalTo(version)); -// } -// -// @Test -// void getVersion_returns_version_from_root_map_when_provided_as_int() { -// final Integer version = random.nextInt(10_000) + 100; -// providedTemplateMap.put("version", version); -// -// final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); -// -// final Optional optionalVersion = indexTemplate.getVersion(); -// assertThat(optionalVersion, notNullValue()); -// assertThat(optionalVersion.isPresent(), equalTo(true)); -// assertThat(optionalVersion.get(), equalTo((long) version)); -// } -// } + + @Nested + class IndexTemplateTests { + private Map providedTemplateMap; + + @BeforeEach + void setUp() { + providedTemplateMap = new HashMap<>(); + } + + @Test + void createIndexTemplate_setTemplateName_sets_the_name() { + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + assertThat(indexTemplate, instanceOf(LegacyIndexTemplate.class)); + + indexTemplate.setTemplateName(templateName); + + final Map returnedTemplateMap = ((LegacyIndexTemplate) indexTemplate).getTemplateMap(); + assertThat(returnedTemplateMap, hasKey("name")); + assertThat(returnedTemplateMap.get("name"), equalTo(templateName)); + + assertThat(providedTemplateMap, not(hasKey("name"))); + } + + @Test + void createIndexTemplate_setIndexPatterns_sets_the_indexPatterns() { + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + assertThat(indexTemplate, instanceOf(LegacyIndexTemplate.class)); + + final List indexPatterns = Collections.singletonList(UUID.randomUUID().toString()); + indexTemplate.setIndexPatterns(indexPatterns); + + final Map returnedTemplateMap = ((LegacyIndexTemplate) indexTemplate).getTemplateMap(); + assertThat(returnedTemplateMap, hasKey("index_patterns")); + assertThat(returnedTemplateMap.get("index_patterns"), equalTo(indexPatterns)); + + assertThat(providedTemplateMap, not(hasKey("index_patterns"))); + } + + @Test + void putCustomSetting_setIndexPatterns_sets_existing_settings() { + final String existingKey = UUID.randomUUID().toString(); + final String existingValue = UUID.randomUUID().toString(); + final Map providedSettings = Collections.singletonMap(existingKey, existingValue); + providedTemplateMap.put("settings", providedSettings); + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + assertThat(indexTemplate, instanceOf(LegacyIndexTemplate.class)); + + final String customKey = UUID.randomUUID().toString(); + final String customValue = UUID.randomUUID().toString(); + + indexTemplate.putCustomSetting(customKey, customValue); + + final Map returnedTemplateMap = ((LegacyIndexTemplate) indexTemplate).getTemplateMap(); + assertThat(returnedTemplateMap, hasKey("settings")); + assertThat(returnedTemplateMap.get("settings"), instanceOf(Map.class)); + final Map settings = (Map) returnedTemplateMap.get("settings"); + assertThat(settings, hasKey(customKey)); + assertThat(settings.get(customKey), equalTo(customValue)); + assertThat(settings, hasKey(existingKey)); + assertThat(settings.get(existingKey), equalTo(existingValue)); + + assertThat(providedSettings, not(hasKey(customKey))); + } + + @Test + void putCustomSetting_setIndexPatterns_sets_new_settings() { + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + assertThat(indexTemplate, instanceOf(LegacyIndexTemplate.class)); + + final String customKey = UUID.randomUUID().toString(); + final String customValue = UUID.randomUUID().toString(); + indexTemplate.putCustomSetting(customKey, customValue); + + final Map returnedTemplateMap = ((LegacyIndexTemplate) indexTemplate).getTemplateMap(); + assertThat(returnedTemplateMap, hasKey("settings")); + assertThat(returnedTemplateMap.get("settings"), instanceOf(Map.class)); + final Map settings = (Map) returnedTemplateMap.get("settings"); + assertThat(settings, hasKey(customKey)); + assertThat(settings.get(customKey), equalTo(customValue)); + + assertThat(providedTemplateMap, not(hasKey("settings"))); + } + + @Test + void getVersion_returns_empty_if_no_version() { + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + final Optional optionalVersion = indexTemplate.getVersion(); + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(false)); + } + + @Test + void getVersion_returns_version_from_root_map() { + final Long version = (long) (random.nextInt(10_000) + 100); + providedTemplateMap.put("version", version); + + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + final Optional optionalVersion = indexTemplate.getVersion(); + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(true)); + assertThat(optionalVersion.get(), equalTo(version)); + } + + @Test + void getVersion_returns_version_from_root_map_when_provided_as_int() { + final Integer version = random.nextInt(10_000) + 100; + providedTemplateMap.put("version", version); + + final IndexTemplate indexTemplate = createObjectUnderTest().createIndexTemplate(providedTemplateMap); + + final Optional optionalVersion = indexTemplate.getVersion(); + assertThat(optionalVersion, notNullValue()); + assertThat(optionalVersion.isPresent(), equalTo(true)); + assertThat(optionalVersion.get(), equalTo((long) version)); + } + } } \ No newline at end of file