diff --git a/common/build.gradle b/common/build.gradle index 979752bc05..81673663ef 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -36,6 +36,9 @@ dependencies { exclude group: 'com.google.guava', module: 'listenablefuture' } compileOnly 'com.jayway.jsonpath:json-path:2.9.0' + compileOnly("com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}") + compileOnly("com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}") + compileOnly group: 'com.networknt' , name: 'json-schema-validator', version: '1.4.0' } lombok { diff --git a/common/src/main/java/org/opensearch/ml/common/CommonValue.java b/common/src/main/java/org/opensearch/ml/common/CommonValue.java index e06e552536..60d4dbad0e 100644 --- a/common/src/main/java/org/opensearch/ml/common/CommonValue.java +++ b/common/src/main/java/org/opensearch/ml/common/CommonValue.java @@ -44,15 +44,15 @@ public class CommonValue { public static final Set stopWordsIndices = ImmutableSet.of(".plugins-ml-stop-words"); // Index mapping paths - public static final String ML_MODEL_GROUP_INDEX_MAPPING_PATH = "index-mappings/ml-model-group.json"; - public static final String ML_MODEL_INDEX_MAPPING_PATH = "index-mappings/ml-model.json"; - public static final String ML_TASK_INDEX_MAPPING_PATH = "index-mappings/ml-task.json"; - public static final String ML_CONNECTOR_INDEX_MAPPING_PATH = "index-mappings/ml-connector.json"; - public static final String ML_CONFIG_INDEX_MAPPING_PATH = "index-mappings/ml-config.json"; - public static final String ML_CONTROLLER_INDEX_MAPPING_PATH = "index-mappings/ml-controller.json"; - public static final String ML_AGENT_INDEX_MAPPING_PATH = "index-mappings/ml-agent.json"; - public static final String ML_MEMORY_META_INDEX_MAPPING_PATH = "index-mappings/ml-memory-meta.json"; - public static final String ML_MEMORY_MESSAGE_INDEX_MAPPING_PATH = "index-mappings/ml-memory-message.json"; + public static final String ML_MODEL_GROUP_INDEX_MAPPING_PATH = "index-mappings/ml_model_group.json"; + public static final String ML_MODEL_INDEX_MAPPING_PATH = "index-mappings/ml_model.json"; + public static final String ML_TASK_INDEX_MAPPING_PATH = "index-mappings/ml_task.json"; + public static final String ML_CONNECTOR_INDEX_MAPPING_PATH = "index-mappings/ml_connector.json"; + public static final String ML_CONFIG_INDEX_MAPPING_PATH = "index-mappings/ml_config.json"; + public static final String ML_CONTROLLER_INDEX_MAPPING_PATH = "index-mappings/ml_controller.json"; + public static final String ML_AGENT_INDEX_MAPPING_PATH = "index-mappings/ml_agent.json"; + public static final String ML_MEMORY_META_INDEX_MAPPING_PATH = "index-mappings/ml_memory_meta.json"; + public static final String ML_MEMORY_MESSAGE_INDEX_MAPPING_PATH = "index-mappings/ml_memory_message.json"; // Calculate Versions independently of OpenSearch core version public static final Version VERSION_2_11_0 = Version.fromString("2.11.0"); diff --git a/common/src/main/java/org/opensearch/ml/common/utils/IndexUtils.java b/common/src/main/java/org/opensearch/ml/common/utils/IndexUtils.java index 92ccb07bf9..dbb27940d0 100644 --- a/common/src/main/java/org/opensearch/ml/common/utils/IndexUtils.java +++ b/common/src/main/java/org/opensearch/ml/common/utils/IndexUtils.java @@ -5,8 +5,11 @@ package org.opensearch.ml.common.utils; +import static org.opensearch.ml.common.utils.StringUtils.validateSchema; + import java.io.IOException; import java.net.URL; +import java.util.HashMap; import java.util.Map; import com.google.common.base.Charsets; @@ -40,6 +43,15 @@ public class IndexUtils { public static final Map UPDATED_DEFAULT_INDEX_SETTINGS = Map.of("index.auto_expand_replicas", "0-1"); public static final Map UPDATED_ALL_NODES_REPLICA_INDEX_SETTINGS = Map.of("index.auto_expand_replicas", "0-all"); + // Schema that validates system index mappings + public static final String MAPPING_SCHEMA_PATH = "index-mappings/schema.json"; + + // Placeholders to use within the json mapping files + private static final String USER_PLACEHOLDER = "USER_MAPPING_PLACEHOLDER"; + private static final String CONNECTOR_PLACEHOLDER = "CONNECTOR_MAPPING_PLACEHOLDER"; + public static final Map MAPPING_PLACEHOLDERS = Map + .of(USER_PLACEHOLDER, "index-mappings/placeholders/user.json", CONNECTOR_PLACEHOLDER, "index-mappings/placeholders/connector.json"); + public static String getMappingFromFile(String path) throws IOException { URL url = IndexUtils.class.getClassLoader().getResource(path); if (url == null) { @@ -47,13 +59,83 @@ public static String getMappingFromFile(String path) throws IOException { } String mapping = Resources.toString(url, Charsets.UTF_8).trim(); - if (mapping.isEmpty() || !StringUtils.isJson(mapping)) { - throw new IllegalArgumentException("Invalid or non-JSON mapping at: " + path); + if (mapping.isEmpty()) { + throw new IllegalArgumentException("Empty mapping found at: " + path); } + mapping = replacePlaceholders(mapping); + validateMapping(mapping); + return mapping; } + public static String replacePlaceholders(String mapping) throws IOException { + if (mapping == null || mapping.isBlank()) { + throw new IllegalArgumentException("Mapping cannot be null or empty"); + } + + // Preload resources into memory to avoid redundant I/O + Map loadedPlaceholders = new HashMap<>(); + for (Map.Entry placeholder : MAPPING_PLACEHOLDERS.entrySet()) { + URL url = IndexUtils.class.getClassLoader().getResource(placeholder.getValue()); + if (url == null) { + throw new IOException("Resource not found: " + placeholder.getValue()); + } + + loadedPlaceholders.put(placeholder.getKey(), Resources.toString(url, Charsets.UTF_8)); + } + + StringBuilder result = new StringBuilder(mapping); + for (Map.Entry entry : loadedPlaceholders.entrySet()) { + String placeholder = entry.getKey(); + String replacement = entry.getValue(); + + // Replace all occurrences of the placeholder + int index; + while ((index = result.indexOf(placeholder)) != -1) { + result.replace(index, index + placeholder.length(), replacement); + } + } + + return result.toString(); + } + + /** + * Checks if the provided mapping is a valid JSON and validates it against a schema. + * + *

The schema is located at mappings/schema.json and enforces the following validations:

+ * + *
    + *
  • Mandatory fields: + *
      + *
    • _meta
    • + *
    • _meta.schema_version
    • + *
    • properties
    • + *
    + *
  • + *
  • No additional fields are allowed at the root level.
  • + *
  • No additional fields are allowed in the _meta object.
  • + *
  • properties must be an object type.
  • + *
  • _meta must be an object type.
  • + *
  • _meta.schema_version must be an integer.
  • + *
+ * + *

Note: Validation can be made stricter if a specific schema is defined for each index.

+ */ + public static void validateMapping(String mapping) throws IOException { + if (mapping.isBlank() || !StringUtils.isJson(mapping)) { + throw new IllegalArgumentException("Invalid or non-JSON mapping found: " + mapping); + } + + URL url = IndexUtils.class.getClassLoader().getResource(MAPPING_SCHEMA_PATH); + if (url == null) { + throw new IOException("Resource not found: " + MAPPING_SCHEMA_PATH); + } + + String schema = Resources.toString(url, Charsets.UTF_8); + validateSchema(schema, mapping); + } + public static Integer getVersionFromMapping(String mapping) { if (mapping == null || mapping.isBlank()) { throw new IllegalArgumentException("Mapping cannot be null or empty"); diff --git a/common/src/main/java/org/opensearch/ml/common/utils/StringUtils.java b/common/src/main/java/org/opensearch/ml/common/utils/StringUtils.java index fcc0c4c3c9..8879306773 100644 --- a/common/src/main/java/org/opensearch/ml/common/utils/StringUtils.java +++ b/common/src/main/java/org/opensearch/ml/common/utils/StringUtils.java @@ -18,18 +18,27 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.apache.commons.lang3.BooleanUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.opensearch.OpenSearchParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.jayway.jsonpath.JsonPath; +import com.networknt.schema.JsonSchema; +import com.networknt.schema.JsonSchemaFactory; +import com.networknt.schema.SpecVersion; +import com.networknt.schema.ValidationMessage; import lombok.extern.log4j.Log4j2; @@ -54,6 +63,8 @@ public class StringUtils { } public static final String TO_STRING_FUNCTION_NAME = ".toString()"; + private static final ObjectMapper MAPPER = new ObjectMapper(); + public static boolean isValidJsonString(String json) { if (json == null || json.isBlank()) { return false; @@ -336,4 +347,28 @@ public static JsonObject getJsonObjectFromString(String jsonString) { return JsonParser.parseString(jsonString).getAsJsonObject(); } + public static void validateSchema(String schemaString, String instanceString) { + try { + // parse the schema JSON as string + JsonNode schemaNode = MAPPER.readTree(schemaString); + JsonSchema schema = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012).getSchema(schemaNode); + + // JSON data to validate + JsonNode jsonNode = MAPPER.readTree(instanceString); + + // Validate JSON node against the schema + Set errors = schema.validate(jsonNode); + if (!errors.isEmpty()) { + String errorMessage = errors.stream().map(ValidationMessage::getMessage).collect(Collectors.joining(", ")); + + throw new OpenSearchParseException( + "Validation failed: " + errorMessage + " for instance: " + instanceString + " with schema: " + schemaString + ); + } + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("Invalid JSON format: " + e.getMessage(), e); + } catch (Exception e) { + throw new OpenSearchParseException("Schema validation failed: " + e.getMessage(), e); + } + } } diff --git a/common/src/main/resources/index-mappings/ml-agent.json b/common/src/main/resources/index-mappings/ml_agent.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-agent.json rename to common/src/main/resources/index-mappings/ml_agent.json diff --git a/common/src/main/resources/index-mappings/ml-config.json b/common/src/main/resources/index-mappings/ml_config.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-config.json rename to common/src/main/resources/index-mappings/ml_config.json diff --git a/common/src/main/resources/index-mappings/ml-connector.json b/common/src/main/resources/index-mappings/ml_connector.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-connector.json rename to common/src/main/resources/index-mappings/ml_connector.json diff --git a/common/src/main/resources/index-mappings/ml-controller.json b/common/src/main/resources/index-mappings/ml_controller.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-controller.json rename to common/src/main/resources/index-mappings/ml_controller.json diff --git a/common/src/main/resources/index-mappings/ml-memory-message.json b/common/src/main/resources/index-mappings/ml_memory_message.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-memory-message.json rename to common/src/main/resources/index-mappings/ml_memory_message.json diff --git a/common/src/main/resources/index-mappings/ml-memory-meta.json b/common/src/main/resources/index-mappings/ml_memory_meta.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-memory-meta.json rename to common/src/main/resources/index-mappings/ml_memory_meta.json diff --git a/common/src/main/resources/index-mappings/ml-model.json b/common/src/main/resources/index-mappings/ml_model.json similarity index 70% rename from common/src/main/resources/index-mappings/ml-model.json rename to common/src/main/resources/index-mappings/ml_model.json index b996e463cd..e9b6c4fba4 100644 --- a/common/src/main/resources/index-mappings/ml-model.json +++ b/common/src/main/resources/index-mappings/ml_model.json @@ -167,77 +167,7 @@ } } }, - "connector": { - "properties": { - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "version": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "protocol": { - "type": "keyword" - }, - "parameters": { - "type": "flat_object" - }, - "credential": { - "type": "flat_object" - }, - "client_config": { - "type": "flat_object" - }, - "actions": { - "type": "flat_object" - } - } - }, - "user": { - "type": "nested", - "properties": { - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "backend_roles": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - }, - "roles": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - }, - "custom_attribute_names": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - } - } - } + "connector": CONNECTOR_MAPPING_PLACEHOLDER, + "user": USER_MAPPING_PLACEHOLDER } } diff --git a/common/src/main/resources/index-mappings/ml-model-group.json b/common/src/main/resources/index-mappings/ml_model_group.json similarity index 100% rename from common/src/main/resources/index-mappings/ml-model-group.json rename to common/src/main/resources/index-mappings/ml_model_group.json diff --git a/common/src/main/resources/index-mappings/ml-task.json b/common/src/main/resources/index-mappings/ml_task.json similarity index 51% rename from common/src/main/resources/index-mappings/ml-task.json rename to common/src/main/resources/index-mappings/ml_task.json index ad428724bf..87ff73763a 100644 --- a/common/src/main/resources/index-mappings/ml-task.json +++ b/common/src/main/resources/index-mappings/ml_task.json @@ -44,43 +44,6 @@ "remote_job": { "type": "flat_object" }, - "user": { - "type": "nested", - "properties": { - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "backend_roles": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - }, - "roles": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - }, - "custom_attribute_names": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - } - } - } + "user": USER_MAPPING_PLACEHOLDER } } diff --git a/common/src/main/resources/index-mappings/placeholders/connector.json b/common/src/main/resources/index-mappings/placeholders/connector.json new file mode 100644 index 0000000000..3955e886e5 --- /dev/null +++ b/common/src/main/resources/index-mappings/placeholders/connector.json @@ -0,0 +1,34 @@ +{ + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "version": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "protocol": { + "type": "keyword" + }, + "parameters": { + "type": "flat_object" + }, + "credential": { + "type": "flat_object" + }, + "client_config": { + "type": "flat_object" + }, + "actions": { + "type": "flat_object" + } + } +} diff --git a/common/src/main/resources/index-mappings/placeholders/user.json b/common/src/main/resources/index-mappings/placeholders/user.json new file mode 100644 index 0000000000..b3d2ed68a5 --- /dev/null +++ b/common/src/main/resources/index-mappings/placeholders/user.json @@ -0,0 +1,38 @@ +{ + "type": "nested", + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "backend_roles": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + }, + "roles": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + }, + "custom_attribute_names": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + } + } +} diff --git a/common/src/main/resources/index-mappings/schema.json b/common/src/main/resources/index-mappings/schema.json new file mode 100644 index 0000000000..b8e326bb38 --- /dev/null +++ b/common/src/main/resources/index-mappings/schema.json @@ -0,0 +1,25 @@ +{ + "type": "object", + "properties": { + "_meta": { + "type": "object", + "properties": { + "schema_version": { + "type": "integer" + } + }, + "required": [ + "schema_version" + ], + "additionalProperties": false + }, + "properties": { + "type": "object" + } + }, + "required": [ + "_meta", + "properties" + ], + "additionalProperties": false +} diff --git a/common/src/test/java/org/opensearch/ml/common/MLIndexTest.java b/common/src/test/java/org/opensearch/ml/common/MLIndexTest.java new file mode 100644 index 0000000000..74d9d44d14 --- /dev/null +++ b/common/src/test/java/org/opensearch/ml/common/MLIndexTest.java @@ -0,0 +1,43 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.ml.common; + +import static org.opensearch.ml.common.CommonValue.ML_CONFIG_INDEX_MAPPING_PATH; +import static org.opensearch.ml.common.CommonValue.ML_CONNECTOR_INDEX_MAPPING_PATH; +import static org.opensearch.ml.common.CommonValue.ML_MODEL_INDEX_MAPPING_PATH; + +import java.io.IOException; + +import org.junit.Test; +import org.opensearch.ml.common.utils.IndexUtils; + +public class MLIndexTest { + + /** + * Mappings are initialised during runtime when the MLIndex enum is referenced. + * We want to catch any failure in mapping assignment before runtime. + * This test simply references the enums to fetch the mapping. It will fail in case the enum is not initialized. + **/ + @Test + public void testValidateMappingsForSystemIndices() { + for (MLIndex index : MLIndex.values()) { + String mapping = index.getMapping(); + } + } + + // adding an explicit check for critical indices + @Test + public void testMappings() throws IOException { + String model_mapping = IndexUtils.getMappingFromFile(ML_MODEL_INDEX_MAPPING_PATH); + IndexUtils.validateMapping(model_mapping); + + String connector_mapping = IndexUtils.getMappingFromFile(ML_CONNECTOR_INDEX_MAPPING_PATH); + IndexUtils.validateMapping(connector_mapping); + + String config_mapping = IndexUtils.getMappingFromFile(ML_CONFIG_INDEX_MAPPING_PATH); + IndexUtils.validateMapping(config_mapping); + } +} diff --git a/common/src/test/java/org/opensearch/ml/common/utils/IndexUtilsTest.java b/common/src/test/java/org/opensearch/ml/common/utils/IndexUtilsTest.java index a4b3badacf..d55ac37fc1 100644 --- a/common/src/test/java/org/opensearch/ml/common/utils/IndexUtilsTest.java +++ b/common/src/test/java/org/opensearch/ml/common/utils/IndexUtilsTest.java @@ -12,6 +12,7 @@ import java.util.Map; import org.junit.Test; +import org.opensearch.OpenSearchParseException; import com.google.gson.JsonParseException; @@ -51,7 +52,7 @@ public void testUpdatedAllNodesReplicaIndexSettingsContainsExpectedValues() { public void testGetMappingFromFile() { String expectedMapping = "{\n" + " \"_meta\": {\n" - + " \"schema_version\": \"1\"\n" + + " \"schema_version\": 1\n" + " },\n" + " \"properties\": {\n" + " \"test_field_1\": {\n" @@ -66,26 +67,24 @@ public void testGetMappingFromFile() { + " }\n" + "}\n"; try { - String actualMapping = IndexUtils.getMappingFromFile("index-mappings/test-mapping.json"); + String actualMapping = IndexUtils.getMappingFromFile("index-mappings/test_mapping.json"); // comparing JsonObjects to avoid issues caused by eol character in different OS assertEquals(StringUtils.getJsonObjectFromString(expectedMapping), StringUtils.getJsonObjectFromString(actualMapping)); } catch (IOException e) { - throw new RuntimeException("Failed to read file at path: index-mappings/test-mapping.json"); + throw new RuntimeException("Failed to read file at path: index-mappings/test_mapping.json"); } } @Test public void testGetMappingFromFileFileNotFound() { - String path = "index-mappings/test-mapping-not-found.json"; + String path = "index-mappings/test_mapping_not_found.json"; IOException e = assertThrows(IOException.class, () -> IndexUtils.getMappingFromFile(path)); - assertEquals("Resource not found: " + path, e.getMessage()); } @Test public void testGetMappingFromFilesMalformedJson() { - String path = "index-mappings/test-mapping-malformed.json"; + String path = "index-mappings/test_mapping_malformed.json"; IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> IndexUtils.getMappingFromFile(path)); - assertEquals("Invalid or non-JSON mapping at: " + path, e.getMessage()); } @Test @@ -152,4 +151,16 @@ public void testGetVersionFromMappingNoSchemaVersion() { JsonParseException e = assertThrows(JsonParseException.class, () -> IndexUtils.getVersionFromMapping(mapping)); assertEquals("Failed to find \"schema_version\" in \"_meta\" object for mapping: " + mapping, e.getMessage()); } + + @Test + public void testValidateMapping() { + String empty_mapping = ""; + assertThrows(IllegalArgumentException.class, () -> IndexUtils.validateMapping(empty_mapping)); + + String non_json_mapping = "not a json"; + assertThrows(IllegalArgumentException.class, () -> IndexUtils.validateMapping(non_json_mapping)); + + String illegal_schema_mapping = "{\"key1\": \"foo\"}"; + assertThrows(OpenSearchParseException.class, () -> IndexUtils.validateMapping(illegal_schema_mapping)); + } } diff --git a/common/src/test/java/org/opensearch/ml/common/utils/StringUtilsTest.java b/common/src/test/java/org/opensearch/ml/common/utils/StringUtilsTest.java index ef5307ae46..d440c44faf 100644 --- a/common/src/test/java/org/opensearch/ml/common/utils/StringUtilsTest.java +++ b/common/src/test/java/org/opensearch/ml/common/utils/StringUtilsTest.java @@ -6,6 +6,7 @@ package org.opensearch.ml.common.utils; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.opensearch.ml.common.utils.StringUtils.TO_STRING_FUNCTION_NAME; import static org.opensearch.ml.common.utils.StringUtils.collectToStringPrefixes; import static org.opensearch.ml.common.utils.StringUtils.getJsonPath; @@ -14,6 +15,7 @@ import static org.opensearch.ml.common.utils.StringUtils.parseParameters; import static org.opensearch.ml.common.utils.StringUtils.toJson; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -25,6 +27,7 @@ import org.apache.commons.text.StringSubstitutor; import org.junit.Assert; import org.junit.Test; +import org.opensearch.OpenSearchParseException; public class StringUtilsTest { @@ -507,4 +510,21 @@ public void testisValidJSONPath_WithFilter() { Assert.assertTrue(isValidJSONPath("$['store','warehouse']")); Assert.assertTrue(isValidJSONPath("$..book[?(@.price > 20)].title")); } + + @Test + public void testValidateSchema() throws IOException { + String schema = "{" + + "\"type\": \"object\"," + + "\"properties\": {" + + " \"key1\": {\"type\": \"string\"}," + + " \"key2\": {\"type\": \"integer\"}" + + "}," + + "\"required\": [\"key1\", \"key2\"]" + + "}"; + String json = "{\"key1\": \"foo\", \"key2\": 123}"; + StringUtils.validateSchema(schema, json); + + String json2 = "{\"key1\": \"foo\"}"; + assertThrows(OpenSearchParseException.class, () -> StringUtils.validateSchema(schema, json2)); + } } diff --git a/common/src/test/resources/index-mappings/test-mapping.json b/common/src/test/resources/index-mappings/test_mapping.json similarity index 89% rename from common/src/test/resources/index-mappings/test-mapping.json rename to common/src/test/resources/index-mappings/test_mapping.json index 6114de4687..9f96c6a0a7 100644 --- a/common/src/test/resources/index-mappings/test-mapping.json +++ b/common/src/test/resources/index-mappings/test_mapping.json @@ -1,6 +1,6 @@ { "_meta": { - "schema_version": "1" + "schema_version": 1 }, "properties": { "test_field_1": { diff --git a/common/src/test/resources/index-mappings/test-mapping-malformed.json b/common/src/test/resources/index-mappings/test_mapping_malformed.json similarity index 100% rename from common/src/test/resources/index-mappings/test-mapping-malformed.json rename to common/src/test/resources/index-mappings/test_mapping_malformed.json diff --git a/memory/build.gradle b/memory/build.gradle index 8251303158..0453912db1 100644 --- a/memory/build.gradle +++ b/memory/build.gradle @@ -38,6 +38,9 @@ dependencies { testImplementation "org.opensearch.client:opensearch-rest-client:${opensearch_version}" testImplementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1' testImplementation group: 'org.json', name: 'json', version: '20231013' + testImplementation("com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}") + testImplementation("com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}") + testImplementation group: 'com.networknt' , name: 'json-schema-validator', version: '1.4.0' } test { diff --git a/ml-algorithms/build.gradle b/ml-algorithms/build.gradle index 2559341fa1..d55bd07d9d 100644 --- a/ml-algorithms/build.gradle +++ b/ml-algorithms/build.gradle @@ -75,6 +75,9 @@ dependencies { implementation 'com.jayway.jsonpath:json-path:2.9.0' implementation group: 'org.json', name: 'json', version: '20231013' implementation group: 'software.amazon.awssdk', name: 'netty-nio-client', version: '2.25.40' + testImplementation("com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}") + testImplementation("com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}") + testImplementation group: 'com.networknt' , name: 'json-schema-validator', version: '1.4.0' } lombok {