/* * 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. */ /* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ package org.opensearch.index.mapper; import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.IndexableField; import org.opensearch.common.CheckedConsumer; import org.opensearch.common.Strings; import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.common.compress.CompressedXContent; import org.opensearch.common.network.InetAddresses; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.common.xcontent.XContentType; import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.index.IndexService; import org.opensearch.index.termvectors.TermVectorsService; import org.opensearch.test.OpenSearchSingleNodeTestCase; import org.junit.Before; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.hamcrest.Matchers.containsString; public class IpRangeFieldMapperTests extends OpenSearchSingleNodeTestCase { private IndexService indexService; private DocumentMapperParser parser; @Before public void setup() { indexService = createIndex("test"); parser = indexService.mapperService().documentMapperParser(); } public void testStoreCidr() throws Exception { XContentBuilder mapping = XContentFactory.jsonBuilder() .startObject() .startObject("type") .startObject("properties") .startObject("field") .field("type", "ip_range") .field("store", true); mapping = mapping.endObject().endObject().endObject().endObject(); DocumentMapper mapper = parser.parse("type", new CompressedXContent(Strings.toString(mapping))); assertEquals(Strings.toString(mapping), mapper.mappingSource().toString()); final Map cases = new HashMap<>(); cases.put("192.168.0.0/15", "192.169.255.255"); cases.put("192.168.0.0/16", "192.168.255.255"); cases.put("192.168.0.0/17", "192.168.127.255"); for (final Map.Entry entry : cases.entrySet()) { ParsedDocument doc = mapper.parse(source(b -> b.field("field", entry.getKey()))); IndexableField[] fields = doc.rootDoc().getFields("field"); assertEquals(3, fields.length); IndexableField dvField = fields[0]; assertEquals(DocValuesType.BINARY, dvField.fieldType().docValuesType()); IndexableField pointField = fields[1]; assertEquals(2, pointField.fieldType().pointIndexDimensionCount()); IndexableField storedField = fields[2]; assertTrue(storedField.fieldType().stored()); String strVal = InetAddresses.toAddrString(InetAddresses.forString("192.168.0.0")) + " : " + InetAddresses.toAddrString(InetAddresses.forString(entry.getValue())); assertThat(storedField.stringValue(), containsString(strVal)); } // Use alternative form to populate the value: // // { // "field": { // "gte": "192.168.1.10", // "lte": "192.168.1.15" // } // } final Map params = new HashMap<>(); params.put("gte", "192.168.1.1"); params.put("lte", "192.168.1.15"); final ParsedDocument doc = mapper.parse(source(b -> b.field("field", params))); final IndexableField[] fields = doc.rootDoc().getFields("field"); assertEquals(3, fields.length); final IndexableField storedField = fields[2]; assertThat(storedField.stringValue(), containsString("192.168.1.1 : 192.168.1.15")); } public void testIgnoreMalformed() throws Exception { final DocumentMapper mapper = parser.parse( "type", new CompressedXContent( Strings.toString( XContentFactory.jsonBuilder() .startObject() .startObject("type") .startObject("properties") .startObject("field") .field("type", "ip_range") .endObject() .endObject() .endObject() .endObject() ) ) ); final ThrowingRunnable runnable = () -> mapper.parse(source(b -> b.field("field", ":1"))); final MapperParsingException e = expectThrows(MapperParsingException.class, runnable); assertThat(e.getCause().getMessage(), containsString("Expected [ip/prefix] but was [:1]")); final DocumentMapper mapper2 = parser.parse( "type", new CompressedXContent( Strings.toString( XContentFactory.jsonBuilder() .startObject() .startObject("type") .startObject("properties") .startObject("field") .field("type", "ip_range") .field("ignore_malformed", true) .endObject() .endObject() .endObject() .endObject() ) ) ); ParsedDocument doc = mapper2.parse(source(b -> b.field("field", ":1"))); IndexableField[] fields = doc.rootDoc().getFields("field"); assertEquals(0, fields.length); assertArrayEquals(new String[] { "field" }, TermVectorsService.getValues(doc.rootDoc().getFields("_ignored"))); final Map params = new HashMap<>(); params.put("gte", "x.x.x.x"); params.put("lte", "192.168.1.15"); doc = mapper2.parse(source(b -> b.field("field", params))); fields = doc.rootDoc().getFields("field"); assertEquals(0, fields.length); assertArrayEquals(new String[] { "field" }, TermVectorsService.getValues(doc.rootDoc().getFields("_ignored"))); } private final SourceToParse source(CheckedConsumer build) throws IOException { XContentBuilder builder = JsonXContent.contentBuilder().startObject(); build.accept(builder); builder.endObject(); return new SourceToParse("test", "1", BytesReference.bytes(builder), XContentType.JSON); } }