diff --git a/CHANGELOG.md b/CHANGELOG.md index 96e230a766..14c2542489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ This section is for maintaining a changelog for all breaking changes for the cli ### Added - Document HTTP/2 support ([#330](https://github.com/opensearch-project/opensearch-java/pull/330)) +- Added support for "withJson" in PutIndexTemplateRequest ([#657](https://github.com/opensearch-project/opensearch-java/pull/657)) + ### Dependencies diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/indices/PutIndexTemplateRequest.java b/java-client/src/main/java/org/opensearch/client/opensearch/indices/PutIndexTemplateRequest.java index 91b61e989d..d83f6ab4f8 100644 --- a/java-client/src/main/java/org/opensearch/client/opensearch/indices/PutIndexTemplateRequest.java +++ b/java-client/src/main/java/org/opensearch/client/opensearch/indices/PutIndexTemplateRequest.java @@ -53,6 +53,7 @@ import org.opensearch.client.util.ApiTypeHelper; import org.opensearch.client.util.ObjectBuilder; import org.opensearch.client.util.ObjectBuilderBase; +import org.opensearch.client.util.WithJsonBuilderBase; // typedef: indices.put_index_template.Request @@ -234,7 +235,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { * Builder for {@link PutIndexTemplateRequest}. */ - public static class Builder extends ObjectBuilderBase implements ObjectBuilder { + public static class Builder extends ObjectBuilderBase implements ObjectBuilder, WithJsonBuilderBase { @Nullable private Map meta; @@ -385,6 +386,11 @@ public PutIndexTemplateRequest build() { return new PutIndexTemplateRequest(this); } + + @Override + public Builder get() { + return this; + } } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/org/opensearch/client/util/WithJsonBuilderBase.java b/java-client/src/main/java/org/opensearch/client/util/WithJsonBuilderBase.java new file mode 100644 index 0000000000..74f0f3571c --- /dev/null +++ b/java-client/src/main/java/org/opensearch/client/util/WithJsonBuilderBase.java @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.client.util; + +import jakarta.json.stream.JsonParser; +import java.io.InputStream; +import org.opensearch.client.json.DelegatingDeserializer; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.JsonpMapperBase; +import org.opensearch.client.json.ObjectDeserializer; +import org.opensearch.client.json.jsonb.JsonbJsonpMapper; + +/** Base interface to set JSON properties **/ +public interface WithJsonBuilderBase { + + B get(); + + /** Updates object with newly provided JSON properties + @param parser the JsonParser parser + @param mapper the JsonpMapper mapper used to deserialize values + @return object + **/ + default B withJson(JsonParser parser, JsonpMapper mapper) { + var deserializer = JsonpMapperBase.findDeserializer(getClass().getEnclosingClass()); + @SuppressWarnings("unchecked") + ObjectDeserializer objectDeserializer = (ObjectDeserializer) DelegatingDeserializer.unwrap(deserializer); + assert objectDeserializer != null; + return objectDeserializer.deserialize(get(), parser, mapper, parser.next()); + } + + /** Updates object with newly provided JSON properties + @param inputStream the stream to read from + @return this object + * **/ + default B withJson(InputStream inputStream) { + JsonbJsonpMapper mapper = new JsonbJsonpMapper(); + JsonParser parser = mapper.jsonProvider().createParser(inputStream); + return withJson(parser, mapper); + } + +} diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractIndicesClientIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractIndicesClientIT.java index a3f360d245..fc41fe6c21 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractIndicesClientIT.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractIndicesClientIT.java @@ -8,25 +8,34 @@ package org.opensearch.client.opensearch.integTest; +import jakarta.json.stream.JsonParser; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.jsonb.JsonbJsonpMapper; import org.opensearch.client.opensearch.OpenSearchAsyncClient; import org.opensearch.client.opensearch._types.OpenSearchException; +import org.opensearch.client.opensearch._types.mapping.Property; import org.opensearch.client.opensearch.indices.CreateDataStreamResponse; import org.opensearch.client.opensearch.indices.CreateIndexResponse; import org.opensearch.client.opensearch.indices.DataStream; import org.opensearch.client.opensearch.indices.DataStreamsStatsResponse; import org.opensearch.client.opensearch.indices.DeleteDataStreamResponse; +import org.opensearch.client.opensearch.indices.DeleteIndexTemplateResponse; import org.opensearch.client.opensearch.indices.GetAliasRequest; import org.opensearch.client.opensearch.indices.GetAliasResponse; import org.opensearch.client.opensearch.indices.GetDataStreamResponse; import org.opensearch.client.opensearch.indices.GetIndexRequest; import org.opensearch.client.opensearch.indices.GetIndexResponse; +import org.opensearch.client.opensearch.indices.GetIndexTemplateResponse; import org.opensearch.client.opensearch.indices.GetIndicesSettingsRequest; import org.opensearch.client.opensearch.indices.IndexState; import org.opensearch.client.opensearch.indices.PutIndexTemplateResponse; +import org.opensearch.client.opensearch.indices.get_index_template.IndexTemplate; import org.opensearch.common.settings.Settings; public abstract class AbstractIndicesClientIT extends OpenSearchJavaClientTestCase { @@ -192,4 +201,87 @@ public void testGetNotExistingIndexAlias() throws Exception { assertEquals(ex.getMessage(), "Request failed: [string_error] " + "alias [alias_not_exists] missing"); } } + + public void testWithJsonPutIndexTemplateRequest() throws IOException { + + String jsonTemplate = "{ " + + " \"index_patterns\": [ " + + " \"logs-2023-01-*\"" + + " ], " + + " \"composed_of\":[], " + + " \"template\": { " + + " \"aliases\": { " + + " \"my_logs\": {} " + + " }, " + + " \"settings\": { " + + " \"number_of_shards\": 2, " + + " \"number_of_replicas\": 1 " + + " }, " + + " \"mappings\": { " + + " \"properties\": { " + + " \"timestamp\": { " + + " \"type\": \"date\"," + + " \"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\"" + + " },\n" + + " \"value\": { " + + " \"type\": \"double\" " + + " } " + + " } " + + " } " + + " } " + + "}"; + + final var pTemplateName = "daily_logs"; + InputStream pTemplateJson = new ByteArrayInputStream(jsonTemplate.getBytes()); + + // create an index template before creating data streams + PutIndexTemplateResponse putIndexTemplateResponse = javaClient().indices() + .putIndexTemplate(b -> b.name(pTemplateName).withJson(pTemplateJson)); + assertTrue(putIndexTemplateResponse.acknowledged()); + + // verify the settings + GetIndexTemplateResponse getIndexTemplateResponse = javaClient().indices().getIndexTemplate(b -> b.name(pTemplateName)); + assertEquals(1, getIndexTemplateResponse.indexTemplates().size()); + assertEquals("logs-2023-01-*", getIndexTemplateResponse.indexTemplates().get(0).indexTemplate().indexPatterns().get(0)); + + IndexTemplate responseIndexTemplate = getIndexTemplateResponse.indexTemplates().get(0).indexTemplate(); + + JsonpMapper mapper = new JsonbJsonpMapper(); + JsonParser parser = mapper.jsonProvider().createParser(new ByteArrayInputStream(jsonTemplate.getBytes())); + IndexTemplate indexTemplate = IndexTemplate._DESERIALIZER.deserialize(parser, mapper); + + assertEquals(indexTemplate.priority(), responseIndexTemplate.priority()); + assert indexTemplate.template() != null; + assert responseIndexTemplate.template() != null; + assertEquals(indexTemplate.template().aliases().size(), responseIndexTemplate.template().aliases().size()); + assert indexTemplate.template().mappings() != null; + assert responseIndexTemplate.template().mappings() != null; + assertEquals(indexTemplate.template().mappings().size(), responseIndexTemplate.template().mappings().size()); + + var mappings = indexTemplate.template().mappings().properties(); + var mappingValues = mappings.get("value"); + assertEquals(Property.Kind.Double, mappingValues._kind()); + + var timestampValues = mappings.get("timestamp"); + assertEquals("yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis", timestampValues.date().format()); + + var indicesSettings = responseIndexTemplate.template().settings().get("index").toJson().asJsonObject(); + assertEquals("\"2\"", indicesSettings.get("number_of_shards").toString()); + assertEquals("\"1\"", indicesSettings.get("number_of_replicas").toString()); + + // delete index template index + DeleteIndexTemplateResponse deleteIndexTemplateResponse = javaClient().indices().deleteIndexTemplate(b -> b.name(pTemplateName)); + assertTrue(deleteIndexTemplateResponse.acknowledged()); + + // verify index template is deleted + try { + javaClient().indices().getIndexTemplate(b -> b.name(pTemplateName)); + fail(); + } catch (OpenSearchException ex) { + assertNotNull(ex); + assertEquals(ex.status(), 404); + } + + } + }