├── NOTICE ├── src ├── test │ ├── resources │ │ └── ip2geo │ │ │ ├── sample_invalid_less_than_two_fields.csv │ │ │ ├── sample_valid.csv │ │ │ ├── sample_valid.zip │ │ │ ├── server │ │ │ ├── city │ │ │ │ ├── city.zip │ │ │ │ ├── manifest_local.json │ │ │ │ └── manifest.json │ │ │ └── country │ │ │ │ ├── country.zip │ │ │ │ ├── manifest_local.json │ │ │ │ └── manifest.json │ │ │ ├── manifest_template.json │ │ │ ├── manifest.json │ │ │ ├── another_manifest.json │ │ │ └── manifest_invalid_url.json │ └── java │ │ └── org │ │ └── opensearch │ │ └── geospatial │ │ ├── shared │ │ └── URLBuilderTests.java │ │ ├── plugin │ │ └── GeospatialPluginIT.java │ │ ├── TestGeospatialPlugin.java │ │ ├── ip2geo │ │ ├── common │ │ │ ├── DatasourceManifestTests.java │ │ │ └── Ip2GeoSettingsTests.java │ │ ├── action │ │ │ ├── IpEnrichmentTransportActionTests.java │ │ │ ├── RestDeleteDatasourceHandlerTests.java │ │ │ ├── GetDatasourceRequestTests.java │ │ │ └── DeleteDatasourceRequestTests.java │ │ └── jobscheduler │ │ │ └── DatasourceExtensionTests.java │ │ ├── stats │ │ └── upload │ │ │ ├── UploadStatsBuilder.java │ │ │ ├── UploadStatsNodeResponseTests.java │ │ │ ├── UploadStatsNodeResponseBuilder.java │ │ │ └── RestUploadStatsActionIT.java │ │ ├── exceptions │ │ ├── ResourceInUseExceptionTests.java │ │ ├── ConcurrentModificationExceptionTests.java │ │ └── IncompatibleDatasourceExceptionTests.java │ │ ├── action │ │ └── upload │ │ │ └── geojson │ │ │ ├── UploadGeoJSONRequestTests.java │ │ │ └── UploadGeoJSONResponseTests.java │ │ ├── index │ │ ├── query │ │ │ └── xypoint │ │ │ │ └── XYPointQueryIT.java │ │ └── mapper │ │ │ └── xypoint │ │ │ └── XYPointIndexerTests.java │ │ └── geojson │ │ └── FeatureCollectionTests.java ├── main │ ├── resources │ │ ├── plugin-additional-permissions.yml │ │ ├── mappings │ │ │ └── ip2geo_geoip.json │ │ └── META-INF │ │ │ └── services │ │ │ └── org.opensearch.jobscheduler.spi.JobSchedulerExtension │ ├── java │ │ └── org │ │ │ └── opensearch │ │ │ └── geospatial │ │ │ ├── annotation │ │ │ └── VisibleForTesting.java │ │ │ ├── ip2geo │ │ │ ├── jobscheduler │ │ │ │ ├── DatasourceTask.java │ │ │ │ └── DatasourceExtension.java │ │ │ ├── action │ │ │ │ ├── GetDatasourceAction.java │ │ │ │ ├── PutDatasourceAction.java │ │ │ │ ├── DeleteDatasourceAction.java │ │ │ │ ├── UpdateDatasourceAction.java │ │ │ │ ├── RestGetDatasourceHandler.java │ │ │ │ ├── RestDeleteDatasourceHandler.java │ │ │ │ ├── DeleteDatasourceRequest.java │ │ │ │ ├── GetDatasourceRequest.java │ │ │ │ └── RestUpdateDatasourceHandler.java │ │ │ ├── common │ │ │ │ ├── DatasourceState.java │ │ │ │ ├── Ip2GeoExecutor.java │ │ │ │ ├── HttpRedirectValidator.java │ │ │ │ ├── ParameterValidator.java │ │ │ │ └── URLDenyListChecker.java │ │ │ └── dao │ │ │ │ └── Ip2GeoProcessorDao.java │ │ │ ├── shared │ │ │ ├── Constants.java │ │ │ ├── URLBuilder.java │ │ │ └── PluginClient.java │ │ │ ├── stats │ │ │ └── upload │ │ │ │ ├── UploadStatsAction.java │ │ │ │ ├── UploadStatsRequest.java │ │ │ │ ├── UploadStatsNodeRequest.java │ │ │ │ ├── RestUploadStatsAction.java │ │ │ │ ├── UploadStatsNodeResponse.java │ │ │ │ ├── UploadStatsTransportAction.java │ │ │ │ ├── UploadStatsResponse.java │ │ │ │ └── TotalUploadStats.java │ │ │ ├── index │ │ │ ├── mapper │ │ │ │ ├── xyshape │ │ │ │ │ ├── XYShapeFieldTypeParser.java │ │ │ │ │ ├── XYShapeQueryable.java │ │ │ │ │ └── XYShapeIndexer.java │ │ │ │ └── xypoint │ │ │ │ │ └── XYPointFieldTypeParser.java │ │ │ └── query │ │ │ │ └── xypoint │ │ │ │ └── XYPointQueryProcessor.java │ │ │ ├── constants │ │ │ └── IndexSetting.java │ │ │ ├── action │ │ │ └── upload │ │ │ │ └── geojson │ │ │ │ ├── UploadGeoJSONAction.java │ │ │ │ └── UploadGeoJSONRequest.java │ │ │ ├── search │ │ │ └── aggregations │ │ │ │ └── bucket │ │ │ │ └── geogrid │ │ │ │ ├── ParsedGeoHexGridBucket.java │ │ │ │ ├── ParsedGeoHexGrid.java │ │ │ │ ├── GeoHexGridBucket.java │ │ │ │ ├── GeoHexGridAggregator.java │ │ │ │ ├── GeoHexGrid.java │ │ │ │ └── GeoHexHelper.java │ │ │ ├── exceptions │ │ │ ├── ResourceInUseException.java │ │ │ ├── ConcurrentModificationException.java │ │ │ └── IncompatibleDatasourceException.java │ │ │ ├── geojson │ │ │ ├── Feature.java │ │ │ └── FeatureFactory.java │ │ │ └── processor │ │ │ └── FeatureProcessor.java │ └── plugin-metadata │ │ └── plugin-security.policy └── yamlRestTest │ ├── resources │ └── rest-api-spec │ │ └── test │ │ ├── 10_basic.yml │ │ └── 20_geohex_grid.yml │ └── java │ └── org │ └── opensearch │ └── geospatial │ └── plugin │ └── GeospatialClientYamlTestSuiteIT.java ├── client ├── NOTICE.txt ├── lombok.config └── src │ ├── main │ └── java │ │ └── org │ │ └── opensearch │ │ └── geospatial │ │ └── action │ │ ├── IpEnrichmentAction.java │ │ └── IpEnrichmentActionClient.java │ └── test │ └── java │ └── org │ └── opensearch │ └── geospatial │ └── action │ ├── IpEnrichmentResponseTests.java │ ├── IpEnrichmentActionClientTests.java │ └── IpEnrichmentRequestTests.java ├── .idea └── copyright │ ├── profiles_settings.xml │ └── SPDX_ALv2.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── release-notes ├── opensearch-geospatial.release-notes-2.16.0.0.md ├── opensearch-geospatial.release-notes-2.17.0.0.md ├── opensearch-geospatial.release-notes-2.18.0.0.md ├── opensearch-geospatial.release-notes-2.14.0.0.md ├── opensearch-geospatial.release-notes-2.15.0.0.md ├── opensearch-geospatial.release-notes-2.3.0.0.md ├── opensearch-geospatial.release-notes-2.5.0.0.md ├── opensearch-geospatial.release-notes-2.13.0.0.md ├── opensearch-geospatial.release-notes-3.0.0.0-beta1.md ├── opensearch-geospatial.release-notes-3.4.0.0.md ├── opensearch-geospatial.release-notes-2.11.1.0.md ├── opensearch-geospatial.release-notes-2.9.0.0.md ├── opensearch-geospatial.release-notes-2.11.0.0.md ├── opensearch-geospatial.release-notes-3.0.0.0-alpha1.md ├── opensearch-geospatial.release-notes-2.7.0.0.md ├── opensearch-geospatial.release-notes-2.12.0.0.md ├── opensearch-geospatial.release-notes-2.8.0.0.md ├── opensearch-geospatial.release-notes-3.0.0.0.md ├── opensearch-geospatial.release-notes-3.3.0.0.md ├── opensearch-geospatial.release-notes-3.1.0.0.md ├── opensearch-geospatial.release-notes-3.2.0.0.md ├── opensearch-geospatial.release-notes-2.19.0.0.md ├── opensearch-geospatial.release-notes-2.6.0.0.md ├── opensearch-geospatial.release-notes-2.10.0.0.md ├── opensearch-geospatial.release-notes-2.2.0.0.md └── opensearch-geospatial.release-notes-2.4.0.0.md ├── .gitignore ├── libs ├── h3 │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── org │ │ │ │ └── opensearch │ │ │ │ └── geospatial │ │ │ │ └── h3 │ │ │ │ ├── res00ic.txt.gz │ │ │ │ ├── res01ic.txt.gz │ │ │ │ ├── res02ic.txt.gz │ │ │ │ ├── res03ic.txt.gz │ │ │ │ ├── res04ic.txt.gz │ │ │ │ ├── res00cells.txt.gz │ │ │ │ ├── res01cells.txt.gz │ │ │ │ ├── res02cells.txt.gz │ │ │ │ ├── res03cells.txt.gz │ │ │ │ ├── bc05r08cells.txt.gz │ │ │ │ ├── bc05r09cells.txt.gz │ │ │ │ ├── bc05r10cells.txt.gz │ │ │ │ ├── bc05r11cells.txt.gz │ │ │ │ ├── bc05r12cells.txt.gz │ │ │ │ ├── bc05r13cells.txt.gz │ │ │ │ ├── bc05r14cells.txt.gz │ │ │ │ ├── bc05r15cells.txt.gz │ │ │ │ ├── bc14r08cells.txt.gz │ │ │ │ ├── bc14r09cells.txt.gz │ │ │ │ ├── bc14r10cells.txt.gz │ │ │ │ ├── bc14r11cells.txt.gz │ │ │ │ ├── bc14r12cells.txt.gz │ │ │ │ ├── bc14r13cells.txt.gz │ │ │ │ ├── bc14r14cells.txt.gz │ │ │ │ ├── bc14r15cells.txt.gz │ │ │ │ ├── bc19r08cells.txt.gz │ │ │ │ ├── bc19r09cells.txt.gz │ │ │ │ ├── bc19r10cells.txt.gz │ │ │ │ ├── bc19r11cells.txt.gz │ │ │ │ ├── bc19r12cells.txt.gz │ │ │ │ ├── bc19r13cells.txt.gz │ │ │ │ ├── bc19r14cells.txt.gz │ │ │ │ ├── bc19r15cells.txt.gz │ │ │ │ ├── bc05r08centers.txt.gz │ │ │ │ ├── bc05r09centers.txt.gz │ │ │ │ ├── bc05r10centers.txt.gz │ │ │ │ ├── bc05r11centers.txt.gz │ │ │ │ ├── bc05r12centers.txt.gz │ │ │ │ ├── bc05r13centers.txt.gz │ │ │ │ ├── bc05r14centers.txt.gz │ │ │ │ ├── bc05r15centers.txt.gz │ │ │ │ ├── bc14r08centers.txt.gz │ │ │ │ ├── bc14r09centers.txt.gz │ │ │ │ ├── bc14r10centers.txt.gz │ │ │ │ ├── bc14r11centers.txt.gz │ │ │ │ ├── bc14r12centers.txt.gz │ │ │ │ ├── bc14r13centers.txt.gz │ │ │ │ ├── bc14r14centers.txt.gz │ │ │ │ ├── bc14r15centers.txt.gz │ │ │ │ ├── bc19r08centers.txt.gz │ │ │ │ ├── bc19r09centers.txt.gz │ │ │ │ ├── bc19r10centers.txt.gz │ │ │ │ ├── bc19r11centers.txt.gz │ │ │ │ ├── bc19r12centers.txt.gz │ │ │ │ ├── bc19r13centers.txt.gz │ │ │ │ ├── bc19r14centers.txt.gz │ │ │ │ ├── bc19r15centers.txt.gz │ │ │ │ └── NOTICE.txt │ │ └── main │ │ │ └── java │ │ │ └── org │ │ │ └── opensearch │ │ │ └── geospatial │ │ │ └── h3 │ │ │ └── CellBoundary.java │ └── NOTICE.txt └── build.gradle ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── documentation-issue.md │ ├── config.yml │ ├── FEATURE_REQUEST_TEMPLATE.md │ ├── BUG_TEMPLATE.md │ └── PROPOSAL_TEMPLATE.md ├── workflows │ ├── draft-release-notes-workflow.yml │ ├── add-untriaged.yml │ ├── changelog_verifier.yml │ ├── delete_backport_branch.yml │ ├── links.yml │ ├── backport.yml │ ├── auto-release.yml │ ├── create-documentation-issue.yml │ ├── maven-publish.yml │ └── CI.yml ├── PULL_REQUEST_TEMPLATE.md └── draft-release-notes-config.yml ├── lombok.config ├── .codecov.yml ├── SECURITY.md ├── gradle.properties ├── .whitesource ├── settings.gradle ├── CHANGELOG.md ├── MAINTAINERS.md ├── ADMINS.md ├── README.md ├── RELEASING.md └── CODE_OF_CONDUCT.md /NOTICE: -------------------------------------------------------------------------------- 1 | OpenSearch (https://opensearch.org) 2 | Copyright OpenSearch Contributors -------------------------------------------------------------------------------- /src/test/resources/ip2geo/sample_invalid_less_than_two_fields.csv: -------------------------------------------------------------------------------- 1 | network 2 | 1.0.0.0/24 -------------------------------------------------------------------------------- /client/NOTICE.txt: -------------------------------------------------------------------------------- 1 | OpenSearch (https://opensearch.org) 2 | Copyright OpenSearch Contributors -------------------------------------------------------------------------------- /src/test/resources/ip2geo/sample_valid.csv: -------------------------------------------------------------------------------- 1 | network,country_name 2 | 1.0.0.0/24,Australia 3 | 10.0.0.0/24,USA -------------------------------------------------------------------------------- /src/main/resources/plugin-additional-permissions.yml: -------------------------------------------------------------------------------- 1 | cluster_permissions: 2 | - "indices:data/read/mget" 3 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.16.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.16.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.16.0 -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.17.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.17.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.17.0 -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.18.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.18.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.18.0 4 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.14.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.14.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.14.0 4 | 5 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.15.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.15.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.15.0 4 | 5 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/sample_valid.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/src/test/resources/ip2geo/sample_valid.zip -------------------------------------------------------------------------------- /src/test/resources/ip2geo/server/city/city.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/src/test/resources/ip2geo/server/city/city.zip -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | build 3 | .idea/* 4 | !.idea/codeStyles/codeStyleConfig.xml 5 | !.idea/copyright 6 | .DS_Store 7 | *.log 8 | out/ 9 | oss/* 10 | *.iml -------------------------------------------------------------------------------- /src/test/resources/ip2geo/server/country/country.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/src/test/resources/ip2geo/server/country/country.zip -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res00ic.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res00ic.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res01ic.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res01ic.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res02ic.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res02ic.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res03ic.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res03ic.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res04ic.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res04ic.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res00cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res00cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res01cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res01cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res02cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res02cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/res03cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/res03cells.txt.gz -------------------------------------------------------------------------------- /src/main/resources/mappings/ip2geo_geoip.json: -------------------------------------------------------------------------------- 1 | { 2 | "dynamic": false, 3 | "properties": { 4 | "_cidr": { 5 | "type": "ip_range", 6 | "doc_values": false 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r08cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r08cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r09cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r09cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r10cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r10cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r11cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r11cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r12cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r12cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r13cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r13cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r14cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r14cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r15cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r15cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r08cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r08cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r09cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r09cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r10cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r10cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r11cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r11cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r12cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r12cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r13cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r13cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r14cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r14cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r15cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r15cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r08cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r08cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r09cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r09cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r10cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r10cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r11cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r11cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r12cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r12cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r13cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r13cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r14cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r14cells.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r15cells.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r15cells.txt.gz -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This should match the owning team set up in https://github.com/orgs/opensearch-project/teams 2 | * @heemin32 @navneet1v @VijayanB @vamshin @jmazanec15 @naveentatikonda @junqiu-lei @martin-gaievski 3 | -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r08centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r08centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r09centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r09centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r10centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r10centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r11centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r11centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r12centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r12centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r13centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r13centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r14centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r14centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r15centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc05r15centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r08centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r08centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r09centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r09centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r10centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r10centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r11centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r11centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r12centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r12centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r13centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r13centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r14centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r14centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r15centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc14r15centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r08centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r08centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r09centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r09centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r10centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r10centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r11centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r11centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r12centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r12centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r13centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r13centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r14centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r14centers.txt.gz -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r15centers.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/geospatial/HEAD/libs/h3/src/test/resources/org/opensearch/geospatial/h3/bc19r15centers.txt.gz -------------------------------------------------------------------------------- /libs/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | subprojects { 6 | apply plugin: 'opensearch.build' 7 | description 'OpenSearch Geospatial H3 library' 8 | } 9 | -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | # tell lombok this is your root directory 2 | config.stopBubbling = true 3 | # add @lombok.Generated annotations to all generated nodes where possible 4 | # to skip code coverage for auto generated code 5 | lombok.addLombokGeneratedAnnotation = true 6 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/manifest_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "URL", 3 | "db_name": "sample_valid.csv", 4 | "sha256_hash": "safasdfaskkkesadfasdf", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 3134012341236, 7 | "provider": "maxmind" 8 | } -------------------------------------------------------------------------------- /client/lombok.config: -------------------------------------------------------------------------------- 1 | # tell lombok this is your root directory 2 | config.stopBubbling = true 3 | # add @lombok.Generated annotations to all generated nodes where possible 4 | # to skip code coverage for auto generated code 5 | lombok.addLombokGeneratedAnnotation = true 6 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.3.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.3.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.3.0 4 | 5 | ### Maintenance 6 | * Increment version to 2.3.0-SNAPSHOT ([#137](https://github.com/opensearch-project/geospatial/pull/137)) 7 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.5.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.5.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.5.0 4 | 5 | ### Maintenance 6 | * Increment version to 2.5.0-SNAPSHOT ([#184](https://github.com/opensearch-project/geospatial/pull/184)) 7 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.13.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.13.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.13.0 4 | 5 | ### Bug Fixes 6 | * Adjusted dependency versions to address CVEs ([#635](https://github.com/opensearch-project/geospatial/pull/635)) -------------------------------------------------------------------------------- /.idea/copyright/SPDX_ALv2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://test.com/db.zip", 3 | "db_name": "sample_valid.csv", 4 | "sha256_hash": "safasdfaskkkesadfasdf", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 3134012341236, 7 | "provider": "sample_provider" 8 | } -------------------------------------------------------------------------------- /libs/h3/src/test/resources/org/opensearch/geospatial/h3/NOTICE.txt: -------------------------------------------------------------------------------- 1 | The files under this directory come from the input test files from Uber's h3 repository 2 | (https://github.com/uber/h3/tree/master/tests/inputfiles) and are made available here 3 | under the same Apache 2 license. 4 | 5 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/another_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://test.com/db.zip", 3 | "db_name": "sample_valid.csv", 4 | "sha256_hash": "safasdfaskkkesadfasdf", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 3134012341236, 7 | "provider": "sample_provider" 8 | } -------------------------------------------------------------------------------- /src/test/resources/ip2geo/manifest_invalid_url.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "invalid://test.com/db.zip", 3 | "db_name": "sample_valid.csv", 4 | "sha256_hash": "safasdfaskkkesadfasdf", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 3134012341236, 7 | "provider": "sample_provider" 8 | } -------------------------------------------------------------------------------- /src/yamlRestTest/resources/rest-api-spec/test/10_basic.yml: -------------------------------------------------------------------------------- 1 | "Test that geospatial and job scheduler plugins are loaded in OpenSearch": 2 | - do: 3 | cat.plugins: 4 | local: true 5 | h: component 6 | 7 | - match: 8 | $body: /^opensearch-geospatial\nopensearch-job-scheduler\n$/ 9 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.0.0.0-beta1.md: -------------------------------------------------------------------------------- 1 | ## Version 3.0.0.0-beta1 Release Notes 2 | 3 | Compatible with OpenSearch 2.19.0 4 | 5 | ### Maintenance 6 | * Persist necessary license and developer information in maven pom ([#732](https://github.com/opensearch-project/geospatial/pull/732)) 7 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | 4 | coverage: 5 | precision: 2 6 | round: down 7 | range: "70...100" 8 | status: 9 | project: 10 | default: 11 | target: 70% # the required coverage value 12 | threshold: 1% # the leniency in hitting the target 13 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/server/city/manifest_local.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "http://localhost:8001/city/city.zip", 3 | "db_name": "data.csv", 4 | "sha256_hash": "oDPgEv+9+kNov7bdQQiLrhr8jQeEPdLnuJ22Hz5npvk=", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 1683590400000, 7 | "provider": "opensearch" 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/server/country/manifest_local.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "http://localhost:8001/country/country.zip", 3 | "db_name": "data.csv", 4 | "sha256_hash": "oDPgEv+4+kNov7bdQQiLrhr8jQeEPdLnuJ11Hz5npvk=", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 1683590400000, 7 | "provider": "opensearch" 8 | } 9 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting a Vulnerability 2 | 3 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com. Please do **not** create a public GitHub issue. -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.4.0.0.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Version 3.4.0 Release Notes 4 | 5 | Compatible with OpenSearch and OpenSearch Dashboards version 3.4.0 6 | 7 | 8 | ### Maintenance 9 | - Update to Gradle 9.2 and run CI checks with JDK 25 ([#816](https://github.com/opensearch-project/geospatial/issues/816)) 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation-issue.md: -------------------------------------------------------------------------------- 1 | **Is your feature request related to a problem?** 2 | A new feature has been added. 3 | 4 | **What solution would you like?** 5 | Document the usage of the new feature. 6 | 7 | **What alternatives have you considered?** 8 | N/A 9 | 10 | **Do you have any additional context?** 11 | See please 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: OpenSearch Community Support 3 | url: https://discuss.opendistrocommunity.dev/ 4 | about: Please ask and answer questions here. 5 | - name: AWS/Amazon Security 6 | url: https://aws.amazon.com/security/vulnerability-reporting/ 7 | about: Please report security vulnerabilities here. -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.11.1.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.11.1.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.11.1 4 | 5 | ### Bug Fixes 6 | * Add default value in denylist ([#583](https://github.com/opensearch-project/geospatial/pull/583)) 7 | * Add denylist ip config for datasource endpoint ([#573](https://github.com/opensearch-project/geospatial/pull/573)) 8 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/server/city/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://raw.githubusercontent.com/opensearch-project/geospatial/main/src/test/resources/ip2geo/server/city/city.zip", 3 | "db_name": "data.csv", 4 | "sha256_hash": "oDPgEv+9+kNov7bdQQiLrhr8jQeEPdLnuJ22Hz5npvk=", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 1683590400000, 7 | "provider": "opensearch" 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=16f2b95838c1ddcf7242b1c39e7bbbb43c842f1f1a1a0dc4959b6d4d68abcac3 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-all.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.9.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.9.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.9.0 4 | 5 | ### Maintenance 6 | Increment version to 2.9.0-SNAPSHOT ([#329](https://github.com/opensearch-project/geospatial/pull/329)) 7 | 8 | ### Refactoring 9 | Change package for Strings.hasText ([#314](https://github.com/opensearch-project/geospatial/pull/314)) 10 | -------------------------------------------------------------------------------- /src/test/resources/ip2geo/server/country/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://raw.githubusercontent.com/opensearch-project/geospatial/main/src/test/resources/ip2geo/server/country/country.zip", 3 | "db_name": "data.csv", 4 | "sha256_hash": "oDPgEv+4+kNov7bdQQiLrhr8jQeEPdLnuJ11Hz5npvk=", 5 | "valid_for_in_days": 30, 6 | "updated_at_in_epoch_milli": 1683590400000, 7 | "provider": "opensearch" 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/annotation/VisibleForTesting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * The OpenSearch Contributors require contributions made to 5 | * this file be licensed under the Apache-2.0 license or a 6 | * compatible open source license. 7 | */ 8 | 9 | package org.opensearch.geospatial.annotation; 10 | 11 | public @interface VisibleForTesting { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/plugin-metadata/plugin-security.policy: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * The OpenSearch Contributors require contributions made to 5 | * this file be licensed under the Apache-2.0 license or a 6 | * compatible open source license. 7 | */ 8 | 9 | grant { 10 | // needed by Ip2Geo datasource to get GeoIP database 11 | permission java.net.SocketPermission "*", "connect,resolve"; 12 | }; 13 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.11.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.11.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.11.0 4 | 5 | ### Bug Fixes 6 | * Fix flaky test, testIndexingMultiPolygon ([#483](https://github.com/opensearch-project/geospatial/pull/483)) 7 | 8 | ### Infrastructure 9 | * Add integration test against security enabled cluster ([#513](https://github.com/opensearch-project/geospatial/pull/513)) 10 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.0.0.0-alpha1.md: -------------------------------------------------------------------------------- 1 | ## Version 3.0.0.0-alpha1 Release Notes 2 | 3 | Compatible with OpenSearch 3.0.0.0-alpha1 4 | 5 | ### Maintenance 6 | * Set geospatial plugin 3.0.0 baseline JDK version to JDK-21 ([#695](https://github.com/opensearch-project/geospatial/pull/695)) 7 | * Bump gradle 8.10.2 / JDK 23 / 3.0.0.0-alpha1 support on geospatial ([#723](https://github.com/opensearch-project/geospatial/pull/723)) 8 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.7.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.7.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.7.0 4 | 5 | ### Infrastructure 6 | * Publish snapshots to maven via GHA ([#233](https://github.com/opensearch-project/geospatial/pull/233)) 7 | * Update snapshot version and fix compilation issues ([#237](https://github.com/opensearch-project/geospatial/pull/237)) 8 | * Add CHANGELOG ([#238](https://github.com/opensearch-project/geospatial/pull/238)) 9 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright OpenSearch Contributors 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ 7 | --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ 8 | --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ 9 | --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ 10 | --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.12.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.12.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.12.0 4 | 5 | ### Features 6 | * Add denylist ip config for datasource endpoint ([#573](https://github.com/opensearch-project/geospatial/pull/573)) 7 | ### Maintenance 8 | * Upgrade gradle to 8.4 ([#596](https://github.com/opensearch-project/geospatial/pull/596)) 9 | * Update spotless and eclipse dependencies ([#620](https://github.com/opensearch-project/geospatial/pull/620)) -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "configMode": "AUTO", 4 | "configExternalURL": "", 5 | "projectToken": "", 6 | "baseBranches": [] 7 | }, 8 | "checkRunSettings": { 9 | "vulnerableCheckRunConclusionLevel": "failure", 10 | "displayMode": "diff" 11 | }, 12 | "issueSettings": { 13 | "minSeverityLevel": "LOW", 14 | "issueType": "DEPENDENCY" 15 | }, 16 | "remediateSettings": { 17 | "workflowRules": { 18 | "enabled": true 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/jobscheduler/DatasourceTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.jobscheduler; 7 | 8 | /** 9 | * Task that {@link DatasourceRunner} will run 10 | */ 11 | public enum DatasourceTask { 12 | /** 13 | * Do everything 14 | */ 15 | ALL, 16 | 17 | /** 18 | * Only delete unused indices 19 | */ 20 | DELETE_UNUSED_INDICES 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/shared/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.shared; 7 | 8 | import java.util.Locale; 9 | 10 | import org.opensearch.Version; 11 | 12 | public class Constants { 13 | public static final String USER_AGENT_KEY = "User-Agent"; 14 | public static final String USER_AGENT_VALUE = String.format(Locale.ROOT, "OpenSearch/%s vanilla", Version.CURRENT.toString()); 15 | } 16 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.8.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.8.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.8.0 4 | 5 | ### Infrastructure 6 | * Make jacoco report to be generated faster in local ([#267](https://github.com/opensearch-project/geospatial/pull/267)) 7 | * Exclude lombok generated code from jacoco coverage report ([#268](https://github.com/opensearch-project/geospatial/pull/268)) 8 | 9 | ### Maintenance 10 | * Change package for Strings.hasText ([#314](https://github.com/opensearch-project/geospatial/pull/314)) -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/6.5.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'geospatial' 11 | 12 | include ":libs" 13 | include ":libs:h3" 14 | 15 | include 'client' 16 | project(":client").name = rootProject.name + "-client" 17 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.0.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 3.0.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 3.0.0 4 | 5 | ### Maintenance 6 | * Set geospatial plugin 3.0.0 baseline JDK version to JDK-21 ([#695](https://github.com/opensearch-project/geospatial/pull/695)) 7 | * Bump gradle 8.10.2 / JDK 23 / 3.0.0.0-alpha1 support on geospatial ([#723](https://github.com/opensearch-project/geospatial/pull/723)) 8 | * Persist necessary license and developer information in maven pom ([#732](https://github.com/opensearch-project/geospatial/pull/732)) 9 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org.opensearch.jobscheduler.spi.JobSchedulerExtension: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # The OpenSearch Contributors require contributions made to 5 | # this file be licensed under the Apache-2.0 license or a 6 | # compatible open source license. 7 | # 8 | 9 | # This file is needed to register DatasourceExtension in job scheduler framework 10 | # See https://github.com/opensearch-project/job-scheduler/blob/main/README.md#getting-started 11 | org.opensearch.geospatial.ip2geo.jobscheduler.DatasourceExtension 12 | -------------------------------------------------------------------------------- /.github/workflows/draft-release-notes-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | update_release_draft: 10 | name: Update draft release notes 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Update draft release notes 14 | uses: release-drafter/release-drafter@v5 15 | with: 16 | config-name: draft-release-notes-config.yml 17 | name: Version (set here) 18 | tag: (None) 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.3.0.0.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Version 3.3.0 Release Notes 4 | 5 | Compatible with OpenSearch and OpenSearch Dashboards version 3.3.0 6 | 7 | ### Bug Fixes 8 | * fix: Update System.env syntax for Gradle 9 compatibility ([#791](https://github.com/opensearch-project/geospatial/pull/791)) 9 | 10 | ### Maintenance 11 | * Remove deprecated URL(String) usage ([#795](https://github.com/opensearch-project/geospatial/pull/795)) 12 | * Increment version to 3.3.0-SNAPSHOT ([#788](https://github.com/opensearch-project/geospatial/pull/788)) 13 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.1.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 3.1.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 3.1.0 4 | 5 | ### Bug Fixes 6 | * Reset datasource metadata when failed to update it in postIndex and postDelete to force refresh it from the primary index shard. ([#761](https://github.com/opensearch-project/geospatial/pull/761)) 7 | * Refresh the Ip2Geo cache and retry one more time when we run into an issue. ([#766](https://github.com/opensearch-project/geospatial/pull/766)) 8 | ### Maintenance 9 | * Fix a unit test and update github workflow to use actions/setup-java@v3. -------------------------------------------------------------------------------- /.github/workflows/add-untriaged.yml: -------------------------------------------------------------------------------- 1 | name: Apply 'untriaged' label during issue lifecycle 2 | 3 | on: 4 | issues: 5 | types: [opened, reopened, transferred] 6 | 7 | jobs: 8 | apply-label: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/github-script@v6 12 | with: 13 | script: | 14 | github.rest.issues.addLabels({ 15 | issue_number: context.issue.number, 16 | owner: context.repo.owner, 17 | repo: context.repo.repo, 18 | labels: ['untriaged'] 19 | }) 20 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/shared/URLBuilderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.shared; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 9 | 10 | import org.opensearch.test.OpenSearchTestCase; 11 | 12 | public class URLBuilderTests extends OpenSearchTestCase { 13 | 14 | public void testPluginPrefix() { 15 | String pluginPrefix = getPluginURLPrefix(); 16 | assertEquals("_plugins/geospatial", pluginPrefix); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | All notable changes to this project are documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 5 | See the [CONTRIBUTING guide](./CONTRIBUTING.md#Changelog) for instructions on how to add changelog entries. 6 | 7 | ## [Unreleased 3.x](https://github.com/opensearch-project/geospatial/compare/main...HEAD) 8 | ### Features 9 | ### Enhancements 10 | ### Bug Fixes 11 | ### Infrastructure 12 | ### Documentation 13 | ### Maintenance 14 | 15 | ### Refactoring 16 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/UploadStatsAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import org.opensearch.action.ActionType; 9 | 10 | public class UploadStatsAction extends ActionType { 11 | 12 | public static final UploadStatsAction INSTANCE = new UploadStatsAction(); 13 | public static final String NAME = "cluster:admin/geospatial/stats"; 14 | 15 | public UploadStatsAction() { 16 | super(NAME, UploadStatsResponse::new); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-3.2.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 3.2.0 Release Notes 2 | 3 | Compatible with OpenSearch and OpenSearch Dashboards version 3.2.0 4 | 5 | ### Bug Fixes 6 | * Block redirect in IP2Geo and move validation to transport action ([#782](https://github.com/opensearch-project/geospatial/pull/782)) 7 | 8 | ### Maintenance 9 | * Upgrade gradle to 8.14.3 and run CI checks with JDK24 ([#776](https://github.com/opensearch-project/geospatial/pull/776)) 10 | 11 | ### Refactoring 12 | * Replace usages of ThreadContext.stashContext with pluginSubject.runAs ([#715](https://github.com/opensearch-project/geospatial/pull/715)) -------------------------------------------------------------------------------- /.github/workflows/changelog_verifier.yml: -------------------------------------------------------------------------------- 1 | name: "Changelog Verifier" 2 | on: 3 | pull_request: 4 | types: [opened, edited, review_requested, synchronize, reopened, ready_for_review, labeled, unlabeled] 5 | 6 | jobs: 7 | # Enforces the update of a changelog file on every pull request 8 | verify-changelog: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | token: ${{ secrets.GITHUB_TOKEN }} 14 | ref: ${{ github.event.pull_request.head.sha }} 15 | 16 | - uses: dangoslen/changelog-enforcer@v3 17 | with: 18 | skipLabels: "autocut, skip-changelog" 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🎆 Feature request 3 | about: Request a feature in this project 4 | title: '[FEATURE]' 5 | labels: enhancement 6 | assignees: '' 7 | --- 8 | **Is your feature request related to a problem?** 9 | A clear and concise description of what the problem is, e.g. _I'm always frustrated when [...]_ 10 | 11 | **What solution would you like?** 12 | A clear and concise description of what you want to happen. 13 | 14 | **What alternatives have you considered?** 15 | A clear and concise description of any alternative solutions or features you've considered. 16 | 17 | **Do you have any additional context?** 18 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/workflows/delete_backport_branch.yml: -------------------------------------------------------------------------------- 1 | name: Delete merged branch of the backport PRs 2 | on: 3 | pull_request: 4 | types: 5 | - closed 6 | 7 | jobs: 8 | delete-branch: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: write 12 | if: startsWith(github.event.pull_request.head.ref,'backport/') || startsWith(github.event.pull_request.head.ref,'release-chores/') 13 | steps: 14 | - name: Delete merged branch 15 | uses: actions/github-script@v7 16 | with: 17 | script: | 18 | github.rest.git.deleteRef({ 19 | owner: context.repo.owner, 20 | repo: context.repo.repo, 21 | ref: `heads/${context.payload.pull_request.head.ref}`, 22 | }) -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.19.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.19.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.19.0 4 | 5 | ### Features 6 | * Introduce new Java artifact geospatial-client to facilitate cross plugin communication. ([#700](https://github.com/opensearch-project/geospatial/pull/700)) 7 | 8 | ### Infrastructure 9 | * Github ci-runner Node.js issue fix ([#701](https://github.com/opensearch-project/geospatial/pull/701)) 10 | * Github CI pipeline update to publish geospatial-client Jar ([#706](https://github.com/opensearch-project/geospatial/pull/706)) 11 | 12 | ### Refactoring 13 | * Use instance of LockService instantiated in JobScheduler through Guice ([#677](https://github.com/opensearch-project/geospatial/pull/677)) -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.6.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.6.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.6.0 4 | 5 | ### Maintenance 6 | * Upgrade snapshot version to 2.6 for 2.x ([#208](https://github.com/opensearch-project/geospatial/pull/208)) 7 | 8 | ### Features 9 | * Add limit to geojson upload API ([#218](https://github.com/opensearch-project/geospatial/pull/218)) 10 | * Allow API to accept any index name without suffix ([#182](https://github.com/opensearch-project/geospatial/pull/182)) 11 | 12 | ### Refactoring 13 | * Fix compilation error and test failure ([#210](https://github.com/opensearch-project/geospatial/pull/210)) 14 | * Replace Locale.getDefault() with Local.ROOT ([#214](https://github.com/opensearch-project/geospatial/pull/214)) -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/index/mapper/xyshape/XYShapeFieldTypeParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.mapper.xyshape; 7 | 8 | import java.util.Map; 9 | 10 | import org.opensearch.index.mapper.AbstractShapeGeometryFieldMapper; 11 | 12 | /** 13 | * XYShapeFieldTypeParser to parse and validate mapping parameters 14 | */ 15 | public final class XYShapeFieldTypeParser extends AbstractShapeGeometryFieldMapper.TypeParser { 16 | @Override 17 | protected AbstractShapeGeometryFieldMapper.Builder newBuilder(String name, Map params) { 18 | return new XYShapeFieldMapper.XYShapeFieldMapperBuilder(name); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/constants/IndexSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.constants; 7 | 8 | /** 9 | * Collection of keys for index setting 10 | */ 11 | public class IndexSetting { 12 | public static final String NUMBER_OF_SHARDS = "index.number_of_shards"; 13 | public static final String NUMBER_OF_REPLICAS = "index.number_of_replicas"; 14 | public static final String REFRESH_INTERVAL = "index.refresh_interval"; 15 | public static final String AUTO_EXPAND_REPLICAS = "index.auto_expand_replicas"; 16 | public static final String HIDDEN = "index.hidden"; 17 | public static final String BLOCKS_WRITE = "index.blocks.write"; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/UploadStatsRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.action.support.nodes.BaseNodesRequest; 11 | import org.opensearch.core.common.io.stream.StreamInput; 12 | 13 | public class UploadStatsRequest extends BaseNodesRequest { 14 | 15 | /** 16 | * Empty constructor needed for UploadStatsTransportAction 17 | */ 18 | public UploadStatsRequest() { 19 | super((String[]) null); 20 | } 21 | 22 | protected UploadStatsRequest(StreamInput in) throws IOException { 23 | super(in); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/links.yml: -------------------------------------------------------------------------------- 1 | name: Link Checker 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | 8 | jobs: 9 | linkchecker: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: lychee Link Checker 16 | id: lychee 17 | uses: lycheeverse/lychee-action@master 18 | with: 19 | args: --accept=200,403,429 **/*.html **/*.md **/*.txt **/*.json --exclude "https://test.com/db.zip" --exclude "http://localhost:8001/country/country.zip" --exclude "http://localhost:8001/city/city.zip" 20 | env: 21 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 22 | - name: Fail if there were link errors 23 | run: exit ${{ steps.lychee.outputs.exit_code }} -------------------------------------------------------------------------------- /.github/workflows/backport.yml: -------------------------------------------------------------------------------- 1 | name: Backport 2 | on: 3 | pull_request_target: 4 | types: 5 | - closed 6 | - labeled 7 | 8 | jobs: 9 | backport: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | name: Backport 15 | steps: 16 | - name: GitHub App token 17 | id: github_app_token 18 | uses: tibdex/github-app-token@v1.5.0 19 | with: 20 | app_id: ${{ secrets.APP_ID }} 21 | private_key: ${{ secrets.APP_PRIVATE_KEY }} 22 | installation_id: 22958780 23 | 24 | - name: Backport 25 | uses: VachaShah/backport@v1.1.4 26 | with: 27 | github_token: ${{ steps.github_app_token.outputs.token }} 28 | branch_name: backport/backport-${{ github.event.number }} 29 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/GetDatasourceAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import org.opensearch.action.ActionType; 9 | 10 | /** 11 | * Ip2Geo datasource get action 12 | */ 13 | public class GetDatasourceAction extends ActionType { 14 | /** 15 | * Get datasource action instance 16 | */ 17 | public static final GetDatasourceAction INSTANCE = new GetDatasourceAction(); 18 | /** 19 | * Get datasource action name 20 | */ 21 | public static final String NAME = "cluster:admin/geospatial/datasource/get"; 22 | 23 | private GetDatasourceAction() { 24 | super(NAME, GetDatasourceResponse::new); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /client/src/main/java/org/opensearch/geospatial/action/IpEnrichmentAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action; 7 | 8 | import org.opensearch.action.ActionType; 9 | import org.opensearch.core.action.ActionResponse; 10 | 11 | /** 12 | * An ActionType registered on OpenSearch registry, for inter-cluster transportAction call, 13 | * to resolve GeoLocation for IP String. 14 | */ 15 | public class IpEnrichmentAction extends ActionType { 16 | 17 | public static final IpEnrichmentAction INSTANCE = new IpEnrichmentAction(); 18 | 19 | public static final String NAME = "cluster:admin/geospatial/ipenrichment/get"; 20 | 21 | public IpEnrichmentAction() { 22 | super(NAME, IpEnrichmentResponse::new); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: Create a report to help us improve 4 | title: '[BUG]' 5 | labels: 'bug, untriaged' 6 | assignees: '' 7 | --- 8 | 9 | **What is the bug?** 10 | A clear and concise description of the bug. 11 | 12 | **How can one reproduce the bug?** 13 | Steps to reproduce the behavior: 14 | 1. Go to '...' 15 | 2. Click on '....' 16 | 3. Scroll down to '....' 17 | 4. See error 18 | 19 | **What is the expected behavior?** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **What is your host/environment?** 23 | - OS: [e.g. iOS] 24 | - Version [e.g. 22] 25 | - Plugins 26 | 27 | **Do you have any screenshots?** 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | **Do you have any additional context?** 31 | Add any other context about the problem. 32 | -------------------------------------------------------------------------------- /.github/workflows/auto-release.yml: -------------------------------------------------------------------------------- 1 | name: Releases 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - name: GitHub App token 15 | id: github_app_token 16 | uses: tibdex/github-app-token@v1.5.0 17 | with: 18 | app_id: ${{ secrets.APP_ID }} 19 | private_key: ${{ secrets.APP_PRIVATE_KEY }} 20 | installation_id: 22958780 21 | - name: Get tag 22 | id: tag 23 | uses: dawidd6/action-get-tag@v1 24 | - uses: actions/checkout@v2 25 | - uses: ncipollo/release-action@v1 26 | with: 27 | github_token: ${{ steps.github_app_token.outputs.token }} 28 | bodyFile: release-notes/opensearch-geospatial.release-notes-${{steps.tag.outputs.tag}}.md 29 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/shared/URLBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.shared; 7 | 8 | import lombok.AccessLevel; 9 | import lombok.NoArgsConstructor; 10 | 11 | /** 12 | * Helper to build url path for this plugin 13 | */ 14 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 15 | public final class URLBuilder { 16 | 17 | public static final String NAME = "geospatial"; 18 | public static final String PLUGIN_PREFIX = "_plugins"; 19 | public static final String URL_DELIMITER = "/"; 20 | 21 | /** 22 | * @return plugin URL prefix path for {@link org.opensearch.geospatial.plugin.GeospatialPlugin} 23 | */ 24 | public static String getPluginURLPrefix() { 25 | return String.join(URL_DELIMITER, PLUGIN_PREFIX, NAME); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/action/upload/geojson/UploadGeoJSONAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * The OpenSearch Contributors require contributions made to 5 | * this file be licensed under the Apache-2.0 license or a 6 | * compatible open source license. 7 | * 8 | * Modifications Copyright OpenSearch Contributors. See 9 | * GitHub history for details. 10 | */ 11 | 12 | package org.opensearch.geospatial.action.upload.geojson; 13 | 14 | import org.opensearch.action.ActionType; 15 | 16 | public class UploadGeoJSONAction extends ActionType { 17 | 18 | public static final UploadGeoJSONAction INSTANCE = new UploadGeoJSONAction(); 19 | public static final String NAME = "cluster:admin/upload_geojson_action"; 20 | 21 | private UploadGeoJSONAction() { 22 | super(NAME, UploadGeoJSONResponse::new); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/PutDatasourceAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import org.opensearch.action.ActionType; 9 | import org.opensearch.action.support.clustermanager.AcknowledgedResponse; 10 | 11 | /** 12 | * Ip2Geo datasource creation action 13 | */ 14 | public class PutDatasourceAction extends ActionType { 15 | /** 16 | * Put datasource action instance 17 | */ 18 | public static final PutDatasourceAction INSTANCE = new PutDatasourceAction(); 19 | /** 20 | * Put datasource action name 21 | */ 22 | public static final String NAME = "cluster:admin/geospatial/datasource/put"; 23 | 24 | private PutDatasourceAction() { 25 | super(NAME, AcknowledgedResponse::new); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/h3/NOTICE.txt: -------------------------------------------------------------------------------- 1 | OpenSearch (https://opensearch.org/) 2 | Copyright OpenSearch Contributors 3 | 4 | -- 5 | Elastic-hex 6 | 7 | Copyright 2022 Elasticsearch B.V. 8 | 9 | -- 10 | 11 | This project is based on a modification of https://github.com/uber/h3 which is licensed under the Apache 2.0 License. 12 | 13 | Copyright 2017-2021 Uber Technologies, Inc. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | Unless required by applicable law or agreed to in writing, software 22 | distributed under the License is distributed on an "AS IS" BASIS, 23 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 | See the License for the specific language governing permissions and 25 | limitations under the License. 26 | -------------------------------------------------------------------------------- /client/src/test/java/org/opensearch/geospatial/action/IpEnrichmentResponseTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action; 7 | 8 | import java.util.Map; 9 | 10 | import org.junit.Assert; 11 | import org.junit.Test; 12 | 13 | public class IpEnrichmentResponseTests { 14 | 15 | /** 16 | * To simulate when Response class being passed from one plugin to the other. 17 | */ 18 | @Test 19 | public void testFromActionResponseWithValidPayload() { 20 | 21 | Map payload = Map.of("k1", "v1"); 22 | IpEnrichmentResponse response = new IpEnrichmentResponse(payload); 23 | IpEnrichmentResponse castedResponse = IpEnrichmentResponse.fromActionResponse(response); 24 | Assert.assertEquals(response.getGeoLocationData(), castedResponse.getGeoLocationData()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/DeleteDatasourceAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import org.opensearch.action.ActionType; 9 | import org.opensearch.action.support.clustermanager.AcknowledgedResponse; 10 | 11 | /** 12 | * Ip2Geo datasource delete action 13 | */ 14 | public class DeleteDatasourceAction extends ActionType { 15 | /** 16 | * Delete datasource action instance 17 | */ 18 | public static final DeleteDatasourceAction INSTANCE = new DeleteDatasourceAction(); 19 | /** 20 | * Delete datasource action name 21 | */ 22 | public static final String NAME = "cluster:admin/geospatial/datasource/delete"; 23 | 24 | private DeleteDatasourceAction() { 25 | super(NAME, AcknowledgedResponse::new); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/UpdateDatasourceAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import org.opensearch.action.ActionType; 9 | import org.opensearch.action.support.clustermanager.AcknowledgedResponse; 10 | 11 | /** 12 | * Ip2Geo datasource update action 13 | */ 14 | public class UpdateDatasourceAction extends ActionType { 15 | /** 16 | * Update datasource action instance 17 | */ 18 | public static final UpdateDatasourceAction INSTANCE = new UpdateDatasourceAction(); 19 | /** 20 | * Update datasource action name 21 | */ 22 | public static final String NAME = "cluster:admin/geospatial/datasource/update"; 23 | 24 | private UpdateDatasourceAction() { 25 | super(NAME, AcknowledgedResponse::new); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/yamlRestTest/java/org/opensearch/geospatial/plugin/GeospatialClientYamlTestSuiteIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.plugin; 7 | 8 | import org.opensearch.test.rest.yaml.ClientYamlTestCandidate; 9 | import org.opensearch.test.rest.yaml.OpenSearchClientYamlSuiteTestCase; 10 | 11 | import com.carrotsearch.randomizedtesting.annotations.Name; 12 | import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; 13 | 14 | public class GeospatialClientYamlTestSuiteIT extends OpenSearchClientYamlSuiteTestCase { 15 | 16 | public GeospatialClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { 17 | super(testCandidate); 18 | } 19 | 20 | @ParametersFactory 21 | public static Iterable parameters() throws Exception { 22 | return OpenSearchClientYamlSuiteTestCase.createParameters(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | [Describe what this change achieves] 3 | 4 | ### Related Issues 5 | Resolves #[Issue number to be closed when this PR is merged] 6 | 7 | 8 | ### Check List 9 | - [ ] New functionality includes testing. 10 | - [ ] New functionality has been documented. 11 | - [ ] API changes companion pull request [created](https://github.com/opensearch-project/opensearch-api-specification/blob/main/DEVELOPER_GUIDE.md). 12 | - [ ] Commits are signed per the DCO using `--signoff`. 13 | - [ ] Public documentation issue/PR [created](https://github.com/opensearch-project/documentation-website/issues/new/choose). 14 | 15 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 16 | For more information on following Developer Certificate of Origin and signing off your commits, please check [here](https://github.com/opensearch-project/geospatial/blob/main/CONTRIBUTING.md#developer-certificate-of-origin). 17 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/UploadStatsNodeRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.core.common.io.stream.StreamInput; 11 | import org.opensearch.core.common.io.stream.StreamOutput; 12 | import org.opensearch.transport.TransportRequest; 13 | 14 | public class UploadStatsNodeRequest extends TransportRequest { 15 | 16 | private final UploadStatsRequest request; 17 | 18 | public UploadStatsNodeRequest(StreamInput in) throws IOException { 19 | super(in); 20 | request = new UploadStatsRequest(in); 21 | } 22 | 23 | public UploadStatsNodeRequest(UploadStatsRequest request) { 24 | this.request = request; 25 | } 26 | 27 | @Override 28 | public void writeTo(StreamOutput out) throws IOException { 29 | super.writeTo(out); 30 | request.writeTo(out); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/PROPOSAL_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💭 Proposal 3 | about: Suggest an idea for a specific feature you wish to propose to the community for comment 4 | title: '[PROPOSAL]' 5 | labels: proposal 6 | assignees: '' 7 | --- 8 | ## What kind of business use case are you trying to solve? What are your requirements? 9 | A clear and concise description of the business problem, e.g. _My customers are asking for [...]_ 10 | 11 | **What is the problem? What is preventing you from meeting the requirements?** 12 | Describe what impact this problem has for lack of a solution. 13 | 14 | **What are you proposing? What do you suggest we do to solve the problem or improve the existing situation?** 15 | Describe your proposed solution. It's OK if you don't have one. 16 | 17 | **What are your assumptions or prerequisites?** 18 | Describe any assumptions you may be making that would limit the scope of this proposal. 19 | 20 | **What are remaining open questions?** 21 | List questions that may need to be answered before proceeding with an implementation. -------------------------------------------------------------------------------- /.github/draft-release-notes-config.yml: -------------------------------------------------------------------------------- 1 | # The overall template of the release notes 2 | template: | 3 | Compatible with OpenSearch (**set version here**). 4 | $CHANGES 5 | 6 | # Setting the formatting and sorting for the release notes body 7 | name-template: Version (set version here) 8 | change-template: '* $TITLE (#$NUMBER)' 9 | sort-by: merged_at 10 | sort-direction: ascending 11 | replacers: 12 | - search: '##' 13 | replace: '###' 14 | 15 | # Organizing the tagged PRs into categories 16 | categories: 17 | - title: 'Breaking Changes' 18 | labels: 19 | - 'Breaking Changes' 20 | - title: 'Features' 21 | labels: 22 | - 'Features' 23 | - title: 'Enhancements' 24 | labels: 25 | - 'Enhancements' 26 | - title: 'Bug Fixes' 27 | labels: 28 | - 'Bug Fixes' 29 | - title: 'Infrastructure' 30 | labels: 31 | - 'Infrastructure' 32 | - title: 'Documentation' 33 | labels: 34 | - 'Documentation' 35 | - title: 'Maintenance' 36 | labels: 37 | - 'Maintenance' 38 | - title: 'Refactoring' 39 | labels: 40 | - 'Refactoring' -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/search/aggregations/bucket/geogrid/ParsedGeoHexGridBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.search.aggregations.bucket.geogrid; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.common.geo.GeoPoint; 11 | import org.opensearch.core.xcontent.XContentParser; 12 | import org.opensearch.geo.search.aggregations.bucket.geogrid.ParsedGeoGridBucket; 13 | 14 | import lombok.NoArgsConstructor; 15 | 16 | @NoArgsConstructor 17 | public class ParsedGeoHexGridBucket extends ParsedGeoGridBucket { 18 | 19 | public GeoPoint getKey() { 20 | return GeoHexHelper.h3ToGeoPoint(this.hashAsString); 21 | } 22 | 23 | public String getKeyAsString() { 24 | return this.hashAsString; 25 | } 26 | 27 | static ParsedGeoHexGridBucket fromXContent(XContentParser parser) throws IOException { 28 | return parseXContent(parser, false, ParsedGeoHexGridBucket::new, (p, bucket) -> { bucket.hashAsString = p.textOrNull(); }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/exceptions/ResourceInUseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.exceptions; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.OpenSearchException; 11 | import org.opensearch.core.common.io.stream.StreamInput; 12 | import org.opensearch.core.rest.RestStatus; 13 | 14 | /** 15 | * Generic ResourceInUseException corresponding to the {@link RestStatus#BAD_REQUEST} status code 16 | */ 17 | public class ResourceInUseException extends OpenSearchException { 18 | 19 | public ResourceInUseException(String msg, Object... args) { 20 | super(msg, args); 21 | } 22 | 23 | public ResourceInUseException(String msg, Throwable cause, Object... args) { 24 | super(msg, cause, args); 25 | } 26 | 27 | public ResourceInUseException(StreamInput in) throws IOException { 28 | super(in); 29 | } 30 | 31 | @Override 32 | public final RestStatus status() { 33 | return RestStatus.BAD_REQUEST; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/plugin/GeospatialPluginIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.plugin; 7 | 8 | import org.apache.hc.core5.http.io.entity.EntityUtils; 9 | import org.opensearch.client.Request; 10 | import org.opensearch.client.Response; 11 | import org.opensearch.core.rest.RestStatus; 12 | import org.opensearch.geospatial.GeospatialRestTestCase; 13 | 14 | public class GeospatialPluginIT extends GeospatialRestTestCase { 15 | 16 | /** 17 | * Tests whether plugin is installed or not 18 | */ 19 | public void testPluginInstalled() throws Exception { 20 | String restURI = String.join("/", "_cat", "plugins"); 21 | 22 | Request request = new Request("GET", restURI); 23 | Response response = client().performRequest(request); 24 | assertEquals(RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode())); 25 | 26 | String responseBody = EntityUtils.toString(response.getEntity()); 27 | assertNotNull(responseBody); 28 | assertTrue(responseBody.contains("opensearch-geospatial")); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/index/mapper/xyshape/XYShapeQueryable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.mapper.xyshape; 7 | 8 | import org.apache.lucene.search.Query; 9 | import org.opensearch.common.geo.ShapeRelation; 10 | import org.opensearch.geometry.Geometry; 11 | import org.opensearch.index.query.QueryShardContext; 12 | 13 | /** 14 | * Interface to build {@link Query} based on given {@link Geometry} 15 | */ 16 | public interface XYShapeQueryable { 17 | /** 18 | * Finds all previously indexed shapes that comply the given {@link ShapeRelation} with 19 | * the specified {@link Geometry}. 20 | * @param geometry query parameter to search indexed shapes 21 | * @param fieldName field name that contains indexed shapes 22 | * @param relation relation between search shape and indexed shape 23 | * @param context instance of {@link QueryShardContext} 24 | * @return Lucene {@link Query} to find indexed shapes based on given geometry 25 | */ 26 | Query shapeQuery(Geometry geometry, String fieldName, ShapeRelation relation, QueryShardContext context); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/search/aggregations/bucket/geogrid/ParsedGeoHexGrid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.search.aggregations.bucket.geogrid; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.core.xcontent.ObjectParser; 11 | import org.opensearch.core.xcontent.XContentParser; 12 | import org.opensearch.geo.search.aggregations.bucket.geogrid.ParsedGeoGrid; 13 | 14 | import lombok.NoArgsConstructor; 15 | 16 | @NoArgsConstructor 17 | public class ParsedGeoHexGrid extends ParsedGeoGrid { 18 | private static final ObjectParser PARSER = createParser( 19 | ParsedGeoHexGrid::new, 20 | ParsedGeoHexGridBucket::fromXContent, 21 | ParsedGeoHexGridBucket::fromXContent 22 | ); 23 | 24 | public static ParsedGeoGrid fromXContent(XContentParser parser, String name) throws IOException { 25 | final var parsedGeoGrid = PARSER.parse(parser, null); 26 | parsedGeoGrid.setName(name); 27 | return parsedGeoGrid; 28 | } 29 | 30 | public String getType() { 31 | return GeoHexGridAggregationBuilder.NAME; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/TestGeospatialPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collection; 10 | import java.util.List; 11 | 12 | import org.opensearch.common.lifecycle.LifecycleComponent; 13 | import org.opensearch.geospatial.ip2geo.listener.Ip2GeoListener; 14 | import org.opensearch.geospatial.plugin.GeospatialPlugin; 15 | 16 | /** 17 | * This class is needed for ClusterSettingsHelper.createMockNode to instantiate a test instance of the 18 | * GeospatialPlugin without the JobSchedulerPlugin installed. Without overriding this class, the 19 | * GeospatialPlugin would try to Inject JobScheduler's LockService in the GuiceHolder which will 20 | * fail because JobScheduler is not installed 21 | */ 22 | public class TestGeospatialPlugin extends GeospatialPlugin { 23 | @Override 24 | public Collection> getGuiceServiceClasses() { 25 | final List> services = new ArrayList<>(1); 26 | services.add(Ip2GeoListener.class); 27 | return services; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/common/DatasourceState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | /** 9 | * Ip2Geo datasource state 10 | * 11 | * When data source is created, it starts with CREATING state. Once the first GeoIP data is generated, the state changes to AVAILABLE. 12 | * Only when the first GeoIP data generation failed, the state changes to CREATE_FAILED. 13 | * Subsequent GeoIP data failure won't change data source state from AVAILABLE to CREATE_FAILED. 14 | * When delete request is received, the data source state changes to DELETING. 15 | * 16 | * State changed from left to right for the entire lifecycle of a datasource 17 | * (CREATING) to (CREATE_FAILED or AVAILABLE) to (DELETING) 18 | * 19 | */ 20 | public enum DatasourceState { 21 | /** 22 | * Data source is being created 23 | */ 24 | CREATING, 25 | /** 26 | * Data source is ready to be used 27 | */ 28 | AVAILABLE, 29 | /** 30 | * Data source creation failed 31 | */ 32 | CREATE_FAILED, 33 | /** 34 | * Data source is being deleted 35 | */ 36 | DELETING 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/exceptions/ConcurrentModificationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.exceptions; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.OpenSearchException; 11 | import org.opensearch.core.common.io.stream.StreamInput; 12 | import org.opensearch.core.rest.RestStatus; 13 | 14 | /** 15 | * General ConcurrentModificationException corresponding to the {@link RestStatus#BAD_REQUEST} status code 16 | * 17 | * The exception is thrown when multiple mutation API is called for a same resource at the same time 18 | */ 19 | public class ConcurrentModificationException extends OpenSearchException { 20 | 21 | public ConcurrentModificationException(String msg, Object... args) { 22 | super(msg, args); 23 | } 24 | 25 | public ConcurrentModificationException(String msg, Throwable cause, Object... args) { 26 | super(msg, cause, args); 27 | } 28 | 29 | public ConcurrentModificationException(StreamInput in) throws IOException { 30 | super(in); 31 | } 32 | 33 | @Override 34 | public final RestStatus status() { 35 | return RestStatus.BAD_REQUEST; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/exceptions/IncompatibleDatasourceException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.exceptions; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.OpenSearchException; 11 | import org.opensearch.core.common.io.stream.StreamInput; 12 | import org.opensearch.core.rest.RestStatus; 13 | 14 | /** 15 | * IncompatibleDatasourceException corresponding to the {@link RestStatus#BAD_REQUEST} status code 16 | * 17 | * The exception is thrown when a user tries to update datasource with new endpoint which is not compatible 18 | * with current datasource 19 | */ 20 | public class IncompatibleDatasourceException extends OpenSearchException { 21 | 22 | public IncompatibleDatasourceException(String msg, Object... args) { 23 | super(msg, args); 24 | } 25 | 26 | public IncompatibleDatasourceException(String msg, Throwable cause, Object... args) { 27 | super(msg, cause, args); 28 | } 29 | 30 | public IncompatibleDatasourceException(StreamInput in) throws IOException { 31 | super(in); 32 | } 33 | 34 | @Override 35 | public final RestStatus status() { 36 | return RestStatus.BAD_REQUEST; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.10.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.10.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.10.0 4 | 5 | ### Features 6 | * IP2Geo processor implementation ([#362](https://github.com/opensearch-project/geospatial/pull/362)) 7 | 8 | ### Bug Fixes 9 | * Revert datasource state when delete fails([#382](https://github.com/opensearch-project/geospatial/pull/382)) 10 | * Update ip2geo test data url([#389](https://github.com/opensearch-project/geospatial/pull/389)) 11 | 12 | ### Infrastructure 13 | * Make jacoco report to be generated faster in local ([#267](https://github.com/opensearch-project/geospatial/pull/267)) 14 | * Exclude lombok generated code from jacoco coverage report ([#268](https://github.com/opensearch-project/geospatial/pull/268)) 15 | 16 | ### Maintenance 17 | * Change package for Strings.hasText ([#314](https://github.com/opensearch-project/geospatial/pull/314)) 18 | * Fixed compilation errors after refactoring in core foundation classes ([#380](https://github.com/opensearch-project/geospatial/pull/380)) 19 | * Version bump for spotlss and apache commons([#400](https://github.com/opensearch-project/geospatial/pull/400)) 20 | ### Refactoring 21 | * Refactor LifecycleComponent package path ([#377](https://github.com/opensearch-project/geospatial/pull/377)) 22 | * Refactor Strings utility methods to core library ([#379](https://github.com/opensearch-project/geospatial/pull/379)) 23 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/search/aggregations/bucket/geogrid/GeoHexGridBucket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.search.aggregations.bucket.geogrid; 7 | 8 | import static org.opensearch.geospatial.search.aggregations.bucket.geogrid.GeoHexHelper.h3ToGeoPoint; 9 | 10 | import java.io.IOException; 11 | 12 | import org.opensearch.core.common.io.stream.StreamInput; 13 | import org.opensearch.geo.search.aggregations.bucket.geogrid.BaseGeoGridBucket; 14 | import org.opensearch.geospatial.h3.H3; 15 | import org.opensearch.search.aggregations.InternalAggregations; 16 | 17 | /** 18 | * Implementation of geohex grid bucket 19 | */ 20 | public class GeoHexGridBucket extends BaseGeoGridBucket { 21 | 22 | public GeoHexGridBucket(long hashAsLong, long docCount, InternalAggregations aggregations) { 23 | super(hashAsLong, docCount, aggregations); 24 | } 25 | 26 | /** 27 | * Read from a Stream 28 | * @param in {@link StreamInput} contains GridBucket 29 | * @throws IOException 30 | */ 31 | public GeoHexGridBucket(StreamInput in) throws IOException { 32 | super(in); 33 | } 34 | 35 | @Override 36 | public Object getKey() { 37 | return h3ToGeoPoint(hashAsLong); 38 | } 39 | 40 | @Override 41 | public String getKeyAsString() { 42 | return H3.h3ToString(hashAsLong); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | This document contains a list of maintainers in this repo. See [opensearch-project/.github/RESPONSIBILITIES.md](https://github.com/opensearch-project/.github/blob/main/RESPONSIBILITIES.md#maintainer-responsibilities) that explains what the role of maintainer means, what maintainers do in this and other repos, and how they should be doing it. If you're interested in contributing, and becoming a maintainer, see [CONTRIBUTING](CONTRIBUTING.md). 4 | 5 | ## Current Maintainers 6 | 7 | | Maintainer | GitHub ID | Affiliation | 8 | |-------------------------|-------------------------------------------------------|-------------| 9 | | Heemin Kim | [heemin32](https://github.com/heemin32) | Amazon | 10 | | Jack Mazanec | [jmazanec15](https://github.com/jmazanec15) | Amazon | 11 | | Junqiu Lei | [junqiu-lei](https://github.com/junqiu-lei) | Amazon | 12 | | Martin Gaievski | [martin-gaievski](https://github.com/martin-gaievski) | Amazon | 13 | | Naveen Tatikonda | [naveentatikonda](https://github.com/naveentatikonda) | Amazon | 14 | | Navneet Verma | [navneet1v](https://github.com/navneet1v) | Amazon | 15 | | Vamshi Vijay Nakkirtha | [vamshin](https://github.com/vamshin) | Amazon | 16 | | Vijayan Balasubramanian | [VijayanB](https://github.com/VijayanB) | Amazon | 17 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/common/DatasourceManifestTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | import static org.mockito.Mockito.mock; 9 | import static org.mockito.Mockito.verify; 10 | import static org.mockito.Mockito.when; 11 | 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.net.URLConnection; 15 | 16 | import org.opensearch.common.SuppressForbidden; 17 | import org.opensearch.geospatial.ip2geo.Ip2GeoTestCase; 18 | import org.opensearch.geospatial.shared.Constants; 19 | 20 | import lombok.SneakyThrows; 21 | 22 | @SuppressForbidden(reason = "unit test") 23 | public class DatasourceManifestTests extends Ip2GeoTestCase { 24 | 25 | @SneakyThrows 26 | public void testInternalBuild_whenCalled_thenCorrectUserAgentValueIsSet() { 27 | URLConnection connection = mock(URLConnection.class); 28 | File manifestFile = new File(this.getClass().getClassLoader().getResource("ip2geo/manifest.json").getFile()); 29 | when(connection.getInputStream()).thenReturn(new FileInputStream(manifestFile)); 30 | 31 | // Run 32 | DatasourceManifest manifest = DatasourceManifest.Builder.internalBuild(connection); 33 | 34 | // Verify 35 | verify(connection).addRequestProperty(Constants.USER_AGENT_KEY, Constants.USER_AGENT_VALUE); 36 | assertEquals("https://test.com/db.zip", manifest.getUrl()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/dao/Ip2GeoProcessorDao.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.dao; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | import org.opensearch.common.inject.Inject; 13 | import org.opensearch.geospatial.ip2geo.processor.Ip2GeoProcessor; 14 | import org.opensearch.ingest.IngestMetadata; 15 | import org.opensearch.ingest.IngestService; 16 | 17 | /** 18 | * Data access object for Ip2Geo processors 19 | */ 20 | public class Ip2GeoProcessorDao { 21 | private final IngestService ingestService; 22 | 23 | @Inject 24 | public Ip2GeoProcessorDao(final IngestService ingestService) { 25 | this.ingestService = ingestService; 26 | } 27 | 28 | public List getProcessors(final String datasourceName) { 29 | IngestMetadata ingestMetadata = ingestService.getClusterService().state().getMetadata().custom(IngestMetadata.TYPE); 30 | if (ingestMetadata == null) { 31 | return Collections.emptyList(); 32 | } 33 | return ingestMetadata.getPipelines() 34 | .keySet() 35 | .stream() 36 | .flatMap(pipelineId -> ingestService.getProcessorsInPipeline(pipelineId, Ip2GeoProcessor.class).stream()) 37 | .filter(ip2GeoProcessor -> ip2GeoProcessor.getDatasourceName().equals(datasourceName)) 38 | .collect(Collectors.toList()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/RestUploadStatsAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.URL_DELIMITER; 9 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 10 | import static org.opensearch.rest.RestRequest.Method.GET; 11 | 12 | import java.util.List; 13 | 14 | import org.opensearch.rest.BaseRestHandler; 15 | import org.opensearch.rest.RestRequest; 16 | import org.opensearch.rest.action.RestToXContentListener; 17 | import org.opensearch.transport.client.node.NodeClient; 18 | 19 | public class RestUploadStatsAction extends BaseRestHandler { 20 | 21 | private static final String NAME = "upload_stats"; 22 | public static final String ACTION_OBJECT = "_upload"; 23 | 24 | public static final String ACTION_STATS = "stats"; 25 | 26 | @Override 27 | public String getName() { 28 | return NAME; 29 | } 30 | 31 | @Override 32 | public List routes() { 33 | String path = String.join(URL_DELIMITER, getPluginURLPrefix(), ACTION_OBJECT, ACTION_STATS); 34 | return List.of(new Route(GET, path)); 35 | } 36 | 37 | @Override 38 | protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient nodeClient) { 39 | return channel -> nodeClient.execute(UploadStatsAction.INSTANCE, new UploadStatsRequest(), new RestToXContentListener<>(channel)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.github/workflows/create-documentation-issue.yml: -------------------------------------------------------------------------------- 1 | name: Create Documentation Issue 2 | on: 3 | pull_request: 4 | types: 5 | - labeled 6 | env: 7 | PR_NUMBER: ${{ github.event.number }} 8 | 9 | jobs: 10 | create-issue: 11 | if: ${{ github.event.label.name == 'needs-documentation' }} 12 | runs-on: ubuntu-latest 13 | name: Create Documentation Issue 14 | steps: 15 | - name: GitHub App token 16 | id: github_app_token 17 | uses: tibdex/github-app-token@v1.5.0 18 | with: 19 | app_id: ${{ secrets.APP_ID }} 20 | private_key: ${{ secrets.APP_PRIVATE_KEY }} 21 | installation_id: 22958780 22 | 23 | - name: Checkout code 24 | uses: actions/checkout@v2 25 | 26 | - name: Edit the issue template 27 | run: | 28 | echo "https://github.com/opensearch-project/geospatial/pull/${{ env.PR_NUMBER }}." >> ./.github/ISSUE_TEMPLATE/documentation-issue.md 29 | 30 | - name: Create Issue From File 31 | id: create-issue 32 | uses: peter-evans/create-issue-from-file@v4 33 | with: 34 | title: Add documentation related to new feature 35 | content-filepath: ./.github/ISSUE_TEMPLATE/documentation-issue.md 36 | labels: documentation 37 | repository: opensearch-project/documentation-website 38 | token: ${{ steps.github_app_token.outputs.token }} 39 | 40 | - name: Print Issue 41 | run: echo Created related documentation issue ${{ steps.create-issue.outputs.issue-number }} 42 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/action/IpEnrichmentTransportActionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import static org.mockito.ArgumentMatchers.any; 9 | import static org.mockito.Mockito.times; 10 | import static org.mockito.Mockito.verify; 11 | 12 | import org.junit.Before; 13 | import org.mockito.Mock; 14 | import org.opensearch.core.action.ActionListener; 15 | import org.opensearch.core.action.ActionResponse; 16 | import org.opensearch.geospatial.action.IpEnrichmentRequest; 17 | import org.opensearch.geospatial.action.IpEnrichmentResponse; 18 | import org.opensearch.geospatial.ip2geo.Ip2GeoTestCase; 19 | import org.opensearch.tasks.Task; 20 | 21 | public class IpEnrichmentTransportActionTests extends Ip2GeoTestCase { 22 | 23 | private IpEnrichmentTransportAction action; 24 | 25 | @Mock 26 | Task task; 27 | 28 | @Mock 29 | ActionListener listener; 30 | 31 | @Before 32 | public void init() { 33 | action = new IpEnrichmentTransportAction(transportService, actionFilters, ip2GeoCachedDao); 34 | } 35 | 36 | /** 37 | * When dataSource is provided. 38 | */ 39 | public void testDoExecuteAllSucceed() { 40 | IpEnrichmentRequest request = new IpEnrichmentRequest("192.168.1.1", "testSource"); 41 | action.doExecute(task, request, listener); 42 | 43 | verify(listener, times(1)).onResponse(any(IpEnrichmentResponse.class)); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/stats/upload/UploadStatsBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import static org.opensearch.test.OpenSearchTestCase.randomBoolean; 9 | import static org.opensearch.test.OpenSearchTestCase.randomIntBetween; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.stream.IntStream; 14 | 15 | import org.opensearch.geospatial.GeospatialTestHelper; 16 | 17 | public class UploadStatsBuilder { 18 | private static final int MAX_METRIC_COUNT = 10; 19 | private static final int MIN_METRIC_COUNT = 2; 20 | 21 | public static UploadStats randomUploadStats() { 22 | int randomMetricCount = randomIntBetween(MIN_METRIC_COUNT, MAX_METRIC_COUNT); 23 | UploadStats stats = new UploadStats(); 24 | IntStream.range(0, randomMetricCount).forEach(unUsed -> { 25 | stats.addMetric(GeospatialTestHelper.generateRandomUploadMetric()); 26 | stats.incrementAPICount(); 27 | }); 28 | // simulate failed upload by randomly increasing the api count 29 | if (randomBoolean()) { 30 | stats.incrementAPICount(); 31 | } 32 | return stats; 33 | } 34 | 35 | public static List randomUploadStats(int max) { 36 | List stats = new ArrayList<>(); 37 | IntStream.range(0, max).forEach(unUsed -> stats.add(randomUploadStats())); 38 | return stats; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish snapshots to maven 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - 'main' 8 | - '[0-9]+.[0-9]+' 9 | - '[0-9]+.x' 10 | 11 | jobs: 12 | build-and-publish-snapshots: 13 | runs-on: ubuntu-latest 14 | 15 | permissions: 16 | id-token: write 17 | contents: write 18 | 19 | steps: 20 | - uses: actions/setup-java@v3 21 | with: 22 | distribution: temurin # Temurin is a distribution of adoptium 23 | java-version: 21 24 | - uses: actions/checkout@v3 25 | 26 | - name: Load secret 27 | uses: 1password/load-secrets-action@v2 28 | with: 29 | # Export loaded secrets as environment variables 30 | export-env: true 31 | env: 32 | OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} 33 | MAVEN_SNAPSHOTS_S3_REPO: op://opensearch-infra-secrets/maven-snapshots-s3/repo 34 | MAVEN_SNAPSHOTS_S3_ROLE: op://opensearch-infra-secrets/maven-snapshots-s3/role 35 | 36 | - name: Configure AWS credentials 37 | uses: aws-actions/configure-aws-credentials@v5 38 | with: 39 | role-to-assume: ${{ env.MAVEN_SNAPSHOTS_S3_ROLE }} 40 | aws-region: us-east-1 41 | 42 | - name: publish snapshots zip to maven 43 | run: | 44 | ./gradlew publishPluginZipPublicationToSnapshotsRepository 45 | 46 | - name: publish snapshots jar to maven 47 | run: | 48 | ./gradlew :geospatial-client:publishNebulaPublicationToSnapshotsRepository 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/common/Ip2GeoExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | import org.opensearch.common.settings.Settings; 11 | import org.opensearch.threadpool.ExecutorBuilder; 12 | import org.opensearch.threadpool.FixedExecutorBuilder; 13 | import org.opensearch.threadpool.ThreadPool; 14 | 15 | /** 16 | * Provide a list of static methods related with executors for Ip2Geo 17 | */ 18 | public class Ip2GeoExecutor { 19 | private static final String THREAD_POOL_NAME = "_plugin_geospatial_ip2geo_datasource_update"; 20 | private final ThreadPool threadPool; 21 | 22 | public Ip2GeoExecutor(final ThreadPool threadPool) { 23 | this.threadPool = threadPool; 24 | } 25 | 26 | /** 27 | * We use fixed thread count of 1 for updating datasource as updating datasource is running background 28 | * once a day at most and no need to expedite the task. 29 | * 30 | * @param settings the settings 31 | * @return the executor builder 32 | */ 33 | public static ExecutorBuilder executorBuilder(final Settings settings) { 34 | return new FixedExecutorBuilder(settings, THREAD_POOL_NAME, 1, 1000, THREAD_POOL_NAME, false); 35 | } 36 | 37 | /** 38 | * Return an executor service for datasource update task 39 | * 40 | * @return the executor service 41 | */ 42 | public ExecutorService forDatasourceUpdate() { 43 | return threadPool.executor(THREAD_POOL_NAME); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/stats/upload/UploadStatsNodeResponseTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.common.io.stream.BytesStreamOutput; 11 | import org.opensearch.core.common.io.stream.StreamInput; 12 | import org.opensearch.geospatial.GeospatialTestHelper; 13 | import org.opensearch.test.OpenSearchTestCase; 14 | 15 | public class UploadStatsNodeResponseTests extends OpenSearchTestCase { 16 | 17 | public void testStream() throws IOException { 18 | UploadStatsNodeResponse nodeResponse = UploadStatsNodeResponseBuilder.randomStatsNodeResponse( 19 | GeospatialTestHelper.randomLowerCaseString() 20 | ); 21 | BytesStreamOutput output = new BytesStreamOutput(); 22 | nodeResponse.writeTo(output); 23 | StreamInput in = StreamInput.wrap(output.bytes().toBytesRef().bytes); 24 | 25 | UploadStatsNodeResponse serializedNodeResponse = new UploadStatsNodeResponse(in); 26 | assertNotNull("serialized node response cannot be null", serializedNodeResponse); 27 | assertArrayEquals( 28 | "mismatch metrics during serialization", 29 | nodeResponse.getUploadStats().getMetrics().toArray(), 30 | serializedNodeResponse.getUploadStats().getMetrics().toArray() 31 | ); 32 | assertEquals( 33 | "mismatch api count", 34 | nodeResponse.getUploadStats().getTotalAPICount(), 35 | serializedNodeResponse.getUploadStats().getTotalAPICount() 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ADMINS.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | This document explains who the admins are (see below), what they do in this repo, and how they should be doing it. If you're interested in becoming a maintainer, see [MAINTAINERS](MAINTAINERS.md). If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). 4 | 5 | ## Current Admins 6 | 7 | | Admin | GitHub ID | Affiliation | 8 | | --------------- | --------------------------------------- | ----------- | 9 | | Charlotte | [CEHENKLE](https://github.com/CEHENKLE) | Amazon | 10 | | Henri Yandell | [hyandell](https://github.com/hyandell) | Amazon | 11 | 12 | ## Admin Responsibilities 13 | 14 | As an admin you own stewartship of the repository and its settings. Admins have [admin-level permissions on a repository](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization). Use those privileges to serve the community and protect the repository as follows. 15 | 16 | ### Prioritize Security 17 | 18 | Security is your number one priority. Manage security keys and safeguard access to the repository. 19 | 20 | Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](SECURITY.md) for details. 21 | 22 | ### Enforce Code of Conduct 23 | 24 | Act on [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) violations by revoking access, and blocking malicious actors. 25 | 26 | ### Adopt Organizational Best Practices 27 | 28 | Adopt organizational best practices, work in the open, and collaborate with other admins by opening issues before making process changes. Prefer consistency, and avoid diverging from practices in the opensearch-project organization. -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/index/mapper/xypoint/XYPointFieldTypeParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.mapper.xypoint; 7 | 8 | import java.util.Map; 9 | 10 | import org.opensearch.index.mapper.AbstractPointGeometryFieldMapper; 11 | 12 | /** 13 | * XYPointFieldTypeParser is used to parse and validate mapping parameters 14 | */ 15 | public class XYPointFieldTypeParser extends AbstractPointGeometryFieldMapper.TypeParser { 16 | /** 17 | * Invoke XYPointFieldMapperBuilder constructor and return object. 18 | * 19 | * @param name field name 20 | * @param params parameters 21 | * @return invoked XYPointFieldMapperBuilder object 22 | */ 23 | @Override 24 | protected AbstractPointGeometryFieldMapper.Builder newBuilder(String name, Map params) { 25 | return new XYPointFieldMapper.XYPointFieldMapperBuilder(name); 26 | } 27 | 28 | /** 29 | * Parse nullValue and reset XYPoint. 30 | * 31 | * @param nullValue null_value parameter value used as a substitute for any explicit null values 32 | * @param ignoreZValue if true (default), third dimension is ignored. If false, points containing more than two dimension throw an exception 33 | * @param ignoreMalformed if true, malformed points are ignored else. If false(default) malformed points throw an exception 34 | * @return XYPoint after parsing null_value and resetting coordinates 35 | */ 36 | @Override 37 | protected XYPoint parseNullValue(Object nullValue, boolean ignoreZValue, boolean ignoreMalformed) { 38 | return XYPointParser.parseXYPoint(nullValue, ignoreZValue); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/exceptions/ResourceInUseExceptionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.exceptions; 7 | 8 | import org.opensearch.common.io.stream.BytesStreamOutput; 9 | import org.opensearch.core.common.io.stream.BytesStreamInput; 10 | import org.opensearch.core.rest.RestStatus; 11 | import org.opensearch.test.OpenSearchTestCase; 12 | 13 | import lombok.SneakyThrows; 14 | 15 | public class ResourceInUseExceptionTests extends OpenSearchTestCase { 16 | public void testConstructor_whenCreated_thenSucceed() { 17 | ResourceInUseException exception = new ResourceInUseException("Resource is in use"); 18 | assertEquals(RestStatus.BAD_REQUEST, exception.status()); 19 | } 20 | 21 | public void testConstructor_whenCreatedWithRootCause_thenSucceed() { 22 | ResourceInUseException exception = new ResourceInUseException("Resource is in use", new RuntimeException()); 23 | assertEquals(RestStatus.BAD_REQUEST, exception.status()); 24 | } 25 | 26 | @SneakyThrows 27 | public void testConstructor_whenCreatedWithStream_thenSucceed() { 28 | ResourceInUseException exception = new ResourceInUseException("New datasource is not compatible with existing datasource"); 29 | 30 | BytesStreamOutput output = new BytesStreamOutput(); 31 | exception.writeTo(output); 32 | BytesStreamInput input = new BytesStreamInput(output.bytes().toBytesRef().bytes); 33 | ResourceInUseException copiedException = new ResourceInUseException(input); 34 | assertEquals(exception.getMessage(), copiedException.getMessage()); 35 | assertEquals(exception.status(), copiedException.status()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/UploadStatsNodeResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | import java.util.Objects; 10 | 11 | import org.opensearch.action.support.nodes.BaseNodeResponse; 12 | import org.opensearch.cluster.node.DiscoveryNode; 13 | import org.opensearch.core.common.io.stream.StreamInput; 14 | import org.opensearch.core.common.io.stream.StreamOutput; 15 | import org.opensearch.core.xcontent.ToXContentObject; 16 | import org.opensearch.core.xcontent.XContentBuilder; 17 | 18 | public class UploadStatsNodeResponse extends BaseNodeResponse implements ToXContentObject { 19 | 20 | private static final String UPLOADS = "uploads"; 21 | private final UploadStats uploadStats; 22 | 23 | public UploadStatsNodeResponse(DiscoveryNode node, UploadStats uploadStats) { 24 | super(node); 25 | this.uploadStats = Objects.requireNonNull(uploadStats, "upload stats cannot be null"); 26 | } 27 | 28 | public UploadStatsNodeResponse(StreamInput in) throws IOException { 29 | super(in); 30 | uploadStats = UploadStats.fromStreamInput(in); 31 | } 32 | 33 | public UploadStats getUploadStats() { 34 | return uploadStats; 35 | } 36 | 37 | @Override 38 | public void writeTo(StreamOutput out) throws IOException { 39 | super.writeTo(out); 40 | uploadStats.writeTo(out); 41 | } 42 | 43 | @Override 44 | public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { 45 | builder.startObject(UPLOADS); 46 | uploadStats.toXContent(builder, params); 47 | return builder.endObject(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/RestGetDatasourceHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.URL_DELIMITER; 9 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 10 | import static org.opensearch.rest.RestRequest.Method.GET; 11 | 12 | import java.util.List; 13 | 14 | import org.opensearch.core.common.Strings; 15 | import org.opensearch.rest.BaseRestHandler; 16 | import org.opensearch.rest.RestRequest; 17 | import org.opensearch.rest.action.RestToXContentListener; 18 | import org.opensearch.transport.client.node.NodeClient; 19 | 20 | /** 21 | * Rest handler for Ip2Geo datasource get request 22 | */ 23 | public class RestGetDatasourceHandler extends BaseRestHandler { 24 | private static final String ACTION_NAME = "ip2geo_datasource_get"; 25 | 26 | @Override 27 | public String getName() { 28 | return ACTION_NAME; 29 | } 30 | 31 | @Override 32 | protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) { 33 | final String[] names = request.paramAsStringArray("name", Strings.EMPTY_ARRAY); 34 | final GetDatasourceRequest getDatasourceRequest = new GetDatasourceRequest(names); 35 | 36 | return channel -> client.executeLocally(GetDatasourceAction.INSTANCE, getDatasourceRequest, new RestToXContentListener<>(channel)); 37 | } 38 | 39 | @Override 40 | public List routes() { 41 | return List.of( 42 | new Route(GET, String.join(URL_DELIMITER, getPluginURLPrefix(), "ip2geo/datasource")), 43 | new Route(GET, String.join(URL_DELIMITER, getPluginURLPrefix(), "ip2geo/datasource/{name}")) 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /client/src/main/java/org/opensearch/geospatial/action/IpEnrichmentActionClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action; 7 | 8 | import java.util.Map; 9 | import java.util.concurrent.ExecutionException; 10 | 11 | import org.opensearch.common.action.ActionFuture; 12 | import org.opensearch.core.action.ActionResponse; 13 | import org.opensearch.transport.client.node.NodeClient; 14 | 15 | import lombok.AllArgsConstructor; 16 | import lombok.extern.log4j.Log4j2; 17 | 18 | /** 19 | * Facade to provide GeoLocation enrichment for other plugins. 20 | */ 21 | @Log4j2 22 | @AllArgsConstructor 23 | public class IpEnrichmentActionClient { 24 | 25 | final private NodeClient nodeClient; 26 | 27 | /** 28 | * Client facing method, which read an IP in String form and return a map instance which contain the associated GeoLocation data. 29 | * @param ipString IP v4 || v6 address in String form. 30 | * @param datasourceName datasourceName in String form. 31 | * @return A map instance which contain GeoLocation data for the given Ip address. 32 | */ 33 | public Map getGeoLocationData(String ipString, String datasourceName) throws ExecutionException, InterruptedException { 34 | // Composite the request object. 35 | ActionFuture responseActionFuture = nodeClient.execute( 36 | IpEnrichmentAction.INSTANCE, 37 | new IpEnrichmentRequest(ipString, datasourceName) 38 | ); 39 | // Send out the request and process the response. 40 | ActionResponse genericActionResponse = responseActionFuture.get(); 41 | IpEnrichmentResponse enrichmentResponse = IpEnrichmentResponse.fromActionResponse(genericActionResponse); 42 | return enrichmentResponse.getGeoLocationData(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/yamlRestTest/resources/rest-api-spec/test/20_geohex_grid.yml: -------------------------------------------------------------------------------- 1 | setup: 2 | - do: 3 | indices.create: 4 | index: cities 5 | body: 6 | settings: 7 | number_of_replicas: 0 8 | mappings: 9 | properties: 10 | location: 11 | type: geo_point 12 | 13 | --- 14 | "Basic test": 15 | - do: 16 | bulk: 17 | refresh: true 18 | body: 19 | - index: 20 | _index: cities 21 | _id: 1 22 | - location: "52.374081,4.912350" 23 | - index: 24 | _index: cities 25 | _id: 2 26 | - location: "52.369219,4.901618" 27 | - index: 28 | _index: cities 29 | _id: 3 30 | - location: "52.371667,4.914722" 31 | - index: 32 | _index: cities 33 | _id: 4 34 | - location: "51.222900,4.405200" 35 | - index: 36 | _index: cities 37 | _id: 5 38 | - location: "48.861111,2.336389" 39 | - index: 40 | _index: cities 41 | _id: 6 42 | - location: "48.860000,2.327000" 43 | 44 | - do: 45 | search: 46 | rest_total_hits_as_int: true 47 | body: 48 | aggregations: 49 | grid: 50 | geohex_grid: 51 | field: location 52 | precision: 4 53 | 54 | 55 | - match: { hits.total: 6 } 56 | - match: { aggregations.grid.buckets.0.key: 841969dffffffff } 57 | - match: { aggregations.grid.buckets.0.doc_count: 3 } 58 | - match: { aggregations.grid.buckets.1.key: 841fb47ffffffff } 59 | - match: { aggregations.grid.buckets.1.doc_count: 2 } 60 | - match: { aggregations.grid.buckets.2.key: 841fa4dffffffff } 61 | - match: { aggregations.grid.buckets.2.doc_count: 1 } 62 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/RestDeleteDatasourceHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.URL_DELIMITER; 9 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 10 | import static org.opensearch.rest.RestRequest.Method.DELETE; 11 | 12 | import java.util.List; 13 | import java.util.Locale; 14 | 15 | import org.opensearch.rest.BaseRestHandler; 16 | import org.opensearch.rest.RestRequest; 17 | import org.opensearch.rest.action.RestToXContentListener; 18 | import org.opensearch.transport.client.node.NodeClient; 19 | 20 | /** 21 | * Rest handler for Ip2Geo datasource delete request 22 | */ 23 | public class RestDeleteDatasourceHandler extends BaseRestHandler { 24 | private static final String ACTION_NAME = "ip2geo_datasource_delete"; 25 | private static final String PARAMS_NAME = "name"; 26 | 27 | @Override 28 | public String getName() { 29 | return ACTION_NAME; 30 | } 31 | 32 | @Override 33 | protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) { 34 | final String name = request.param(PARAMS_NAME); 35 | final DeleteDatasourceRequest deleteDatasourceRequest = new DeleteDatasourceRequest(name); 36 | 37 | return channel -> client.executeLocally( 38 | DeleteDatasourceAction.INSTANCE, 39 | deleteDatasourceRequest, 40 | new RestToXContentListener<>(channel) 41 | ); 42 | } 43 | 44 | @Override 45 | public List routes() { 46 | String path = String.join(URL_DELIMITER, getPluginURLPrefix(), String.format(Locale.ROOT, "ip2geo/datasource/{%s}", PARAMS_NAME)); 47 | return List.of(new Route(DELETE, path)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/search/aggregations/bucket/geogrid/GeoHexGridAggregator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.search.aggregations.bucket.geogrid; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import org.opensearch.geo.search.aggregations.bucket.geogrid.BaseGeoGridBucket; 13 | import org.opensearch.geo.search.aggregations.bucket.geogrid.GeoGridAggregator; 14 | import org.opensearch.search.aggregations.Aggregator; 15 | import org.opensearch.search.aggregations.AggregatorFactories; 16 | import org.opensearch.search.aggregations.CardinalityUpperBound; 17 | import org.opensearch.search.aggregations.support.ValuesSource; 18 | import org.opensearch.search.internal.SearchContext; 19 | 20 | /** 21 | * Aggregates data expressed as H3 Cell ID. 22 | */ 23 | public class GeoHexGridAggregator extends GeoGridAggregator { 24 | 25 | public GeoHexGridAggregator( 26 | String name, 27 | AggregatorFactories factories, 28 | ValuesSource.Numeric valuesSource, 29 | int requiredSize, 30 | int shardSize, 31 | SearchContext aggregationContext, 32 | Aggregator parent, 33 | CardinalityUpperBound cardinality, 34 | Map metadata 35 | ) throws IOException { 36 | super(name, factories, valuesSource, requiredSize, shardSize, aggregationContext, parent, cardinality, metadata); 37 | } 38 | 39 | @Override 40 | protected GeoHexGrid buildAggregation(String name, int requiredSize, List buckets, Map metadata) { 41 | return new GeoHexGrid(name, requiredSize, buckets, metadata); 42 | } 43 | 44 | @Override 45 | protected BaseGeoGridBucket newEmptyBucket() { 46 | return new GeoHexGridBucket(0, 0, null); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build and Test plugin](https://github.com/opensearch-project/geospatial/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/opensearch-project/geospatial/actions/workflows/CI.yml) 2 | [![codecov](https://codecov.io/gh/opensearch-project/geospatial/branch/main/graph/badge.svg?token=1eHsSeBjxh)](https://codecov.io/gh/opensearch-project/geospatial) 3 | ![PRs welcome!](https://img.shields.io/badge/PRs-welcome!-success) 4 | 5 | 6 | 7 | - [OpenSearch Geospatial](#opensearch-geospatial) 8 | - [Project Resources](#project-resources) 9 | - [Code of Conduct](#code-of-conduct) 10 | - [License](#license) 11 | - [Copyright](#copyright) 12 | 13 | ## OpenSearch Geospatial 14 | **OpenSearch geospatial** is an OpenSearch plugin that contains geospatial specific features. 15 | 16 | ## Project Resources 17 | 18 | * [Project Website](https://opensearch.org/) 19 | * [Downloads](https://opensearch.org/downloads.html). 20 | * [Documentation](https://opensearch.org/docs/) 21 | * Need help? Try [Forums](https://discuss.opendistrocommunity.dev/) 22 | * [Project Principles](https://opensearch.org/#principles) 23 | * [Contributing to OpenSearch](CONTRIBUTING.md) 24 | * [Maintainer Responsibilities](MAINTAINERS.md) 25 | * [Release Management](RELEASING.md) 26 | * [Admin Responsibilities](ADMINS.md) 27 | * [Security](SECURITY.md) 28 | 29 | ## Code of Conduct 30 | 31 | This project has adopted the [Amazon Open Source Code of Conduct](CODE_OF_CONDUCT.md). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq), or contact [opensource-codeofconduct@amazon.com](mailto:opensource-codeofconduct@amazon.com) with any additional questions or comments. 32 | 33 | ## License 34 | 35 | This project is licensed under the [Apache v2.0 License](LICENSE). 36 | 37 | ## Copyright 38 | 39 | Copyright OpenSearch Contributors. See [NOTICE](NOTICE) for details. -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/DeleteDatasourceRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.action.ActionRequest; 11 | import org.opensearch.action.ActionRequestValidationException; 12 | import org.opensearch.core.common.io.stream.StreamInput; 13 | import org.opensearch.core.common.io.stream.StreamOutput; 14 | import org.opensearch.geospatial.ip2geo.common.ParameterValidator; 15 | 16 | import lombok.AllArgsConstructor; 17 | import lombok.Getter; 18 | import lombok.Setter; 19 | 20 | /** 21 | * GeoIP datasource delete request 22 | */ 23 | @Getter 24 | @Setter 25 | @AllArgsConstructor 26 | public class DeleteDatasourceRequest extends ActionRequest { 27 | private static final ParameterValidator VALIDATOR = new ParameterValidator(); 28 | /** 29 | * @param name the datasource name 30 | * @return the datasource name 31 | */ 32 | private String name; 33 | 34 | /** 35 | * Constructor 36 | * 37 | * @param in the stream input 38 | * @throws IOException IOException 39 | */ 40 | public DeleteDatasourceRequest(final StreamInput in) throws IOException { 41 | super(in); 42 | this.name = in.readString(); 43 | } 44 | 45 | @Override 46 | public ActionRequestValidationException validate() { 47 | ActionRequestValidationException errors = null; 48 | if (VALIDATOR.validateDatasourceName(name).isEmpty() == false) { 49 | errors = new ActionRequestValidationException(); 50 | errors.addValidationError("no such datasource exist"); 51 | } 52 | return errors; 53 | } 54 | 55 | @Override 56 | public void writeTo(final StreamOutput out) throws IOException { 57 | super.writeTo(out); 58 | out.writeString(name); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | - [Overview](#overview) 2 | - [Branching](#branching) 3 | - [Release Branching](#release-branching) 4 | - [Feature Branches](#feature-branches) 5 | - [Release Labels](#release-labels) 6 | - [Releasing](#releasing) 7 | 8 | ## Overview 9 | 10 | This document explains the release strategy for artifacts in this organization. 11 | 12 | ## Branching 13 | 14 | ### Release Branching 15 | 16 | Given the current major release of 1.0, projects in this organization maintain the following active branches. 17 | 18 | * **main**: The next _major_ release. This is the branch where all merges take place and code moves fast. 19 | * **1.x**: The next _minor_ release. Once a change is merged into `main`, decide whether to backport it to `1.x`. 20 | * **1.0**: The _current_ release. In between minor releases, only hotfixes (e.g. security) are backported to `1.0`. 21 | 22 | Label PRs with the next major version label (e.g. `2.0.0`) and merge changes into `main`. Label PRs that you believe need to be backported as `1.x` and `1.0`. Backport PRs by checking out the versioned branch, cherry-pick changes and open a PR against each target backport branch. 23 | 24 | ### Feature Branches 25 | 26 | Do not creating branches in the upstream repo, use your fork, for the exception of long lasting feature branches that require active collaboration from multiple developers. Name feature branches `feature/`. Once the work is merged to `main`, please make sure to delete the feature branch. 27 | 28 | ## Release Labels 29 | 30 | Repositories create consistent release labels, such as `v1.0.0`, `v1.1.0` and `v2.0.0`, as well as `patch` and `backport`. Use release labels to target an issue or a PR for a given release. See [MAINTAINERS](MAINTAINERS.md#triage-open-issues) for more information on triaging issues. 31 | 32 | ## Releasing 33 | 34 | The release process is standard across repositories in this org and is run by a release manager volunteering from amongst [MAINTAINERS](MAINTAINERS.md). 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/geojson/Feature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.geojson; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import lombok.Value; 12 | 13 | /** 14 | * Feature object represents GEOJSON of type Feature. 15 | */ 16 | @Value 17 | public class Feature { 18 | public static final String TYPE = "Feature"; 19 | public static final String GEOMETRY_KEY = "geometry"; 20 | public static final String PROPERTIES_KEY = "properties"; 21 | public static final String TYPE_KEY = "type"; 22 | private final Map geometry; 23 | private final Map properties; 24 | 25 | private Feature(Map geometry) { 26 | this.geometry = new HashMap<>(); 27 | this.geometry.putAll(geometry); 28 | this.properties = new HashMap<>(); 29 | } 30 | 31 | /** 32 | * FeatureBuilder represents the Builder Object to build Feature instance 33 | */ 34 | static class FeatureBuilder { 35 | 36 | private final Feature feature; 37 | 38 | public FeatureBuilder(Map geometry) { 39 | this.feature = new Feature(geometry); 40 | } 41 | 42 | /** 43 | * Returns Feature instance based on FeatureBuilder values. 44 | * 45 | * @return Feature, which is a GeoJSON Object of type Feature 46 | */ 47 | public Feature build() { 48 | return feature; 49 | } 50 | 51 | /** 52 | * Adds given properties to existing properties 53 | * 54 | * @param properties to be included in Feature 55 | * @return FeatureBuilder instance 56 | */ 57 | public FeatureBuilder properties(Map properties) { 58 | this.feature.properties.putAll(properties); 59 | return this; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/common/Ip2GeoSettingsTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | import org.opensearch.common.settings.Settings; 12 | import org.opensearch.test.OpenSearchTestCase; 13 | 14 | public class Ip2GeoSettingsTests extends OpenSearchTestCase { 15 | public void testValidateInvalidUrl() { 16 | Ip2GeoSettings.DatasourceEndpointValidator validator = new Ip2GeoSettings.DatasourceEndpointValidator(); 17 | Exception e = expectThrows(IllegalArgumentException.class, () -> validator.validate("InvalidUrl")); 18 | assertEquals("Invalid URL format is provided", e.getMessage()); 19 | } 20 | 21 | public void testValidateValidUrl() { 22 | Ip2GeoSettings.DatasourceEndpointValidator validator = new Ip2GeoSettings.DatasourceEndpointValidator(); 23 | validator.validate("https://test.com"); 24 | } 25 | 26 | public void testDenyListDefaultValue() { 27 | List privateNetworks = Arrays.asList( 28 | "127.0.0.0/8", 29 | "169.254.0.0/16", 30 | "10.0.0.0/8", 31 | "172.16.0.0/12", 32 | "192.168.0.0/16", 33 | "0.0.0.0/8", 34 | "100.64.0.0/10", 35 | "192.0.0.0/24", 36 | "192.0.2.0/24", 37 | "198.18.0.0/15", 38 | "192.88.99.0/24", 39 | "198.51.100.0/24", 40 | "203.0.113.0/24", 41 | "224.0.0.0/4", 42 | "240.0.0.0/4", 43 | "255.255.255.255/32", 44 | "::1/128", 45 | "fe80::/10", 46 | "fc00::/7", 47 | "::/128", 48 | "2001:db8::/32", 49 | "ff00::/8" 50 | ); 51 | assertEquals(privateNetworks, Ip2GeoSettings.DATASOURCE_ENDPOINT_DENYLIST.get(Settings.EMPTY)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/exceptions/ConcurrentModificationExceptionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.exceptions; 7 | 8 | import org.opensearch.common.io.stream.BytesStreamOutput; 9 | import org.opensearch.core.common.io.stream.BytesStreamInput; 10 | import org.opensearch.core.rest.RestStatus; 11 | import org.opensearch.test.OpenSearchTestCase; 12 | 13 | import lombok.SneakyThrows; 14 | 15 | public class ConcurrentModificationExceptionTests extends OpenSearchTestCase { 16 | public void testConstructor_whenCreated_thenSucceed() { 17 | ConcurrentModificationException exception = new ConcurrentModificationException("Resource is being modified by another processor"); 18 | assertEquals(RestStatus.BAD_REQUEST, exception.status()); 19 | } 20 | 21 | public void testConstructor_whenCreatedWithRootCause_thenSucceed() { 22 | ConcurrentModificationException exception = new ConcurrentModificationException( 23 | "Resource is being modified by another processor", 24 | new RuntimeException() 25 | ); 26 | assertEquals(RestStatus.BAD_REQUEST, exception.status()); 27 | } 28 | 29 | @SneakyThrows 30 | public void testConstructor_whenCreatedWithStream_thenSucceed() { 31 | ConcurrentModificationException exception = new ConcurrentModificationException( 32 | "New datasource is not compatible with existing datasource" 33 | ); 34 | 35 | BytesStreamOutput output = new BytesStreamOutput(); 36 | exception.writeTo(output); 37 | BytesStreamInput input = new BytesStreamInput(output.bytes().toBytesRef().bytes); 38 | ConcurrentModificationException copiedException = new ConcurrentModificationException(input); 39 | assertEquals(exception.getMessage(), copiedException.getMessage()); 40 | assertEquals(exception.status(), copiedException.status()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/action/upload/geojson/UploadGeoJSONRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * The OpenSearch Contributors require contributions made to 5 | * this file be licensed under the Apache-2.0 license or a 6 | * compatible open source license. 7 | * 8 | * Modifications Copyright OpenSearch Contributors. See 9 | * GitHub history for details. 10 | */ 11 | 12 | package org.opensearch.geospatial.action.upload.geojson; 13 | 14 | import java.io.IOException; 15 | import java.util.Objects; 16 | 17 | import org.opensearch.action.ActionRequest; 18 | import org.opensearch.action.ActionRequestValidationException; 19 | import org.opensearch.core.common.bytes.BytesReference; 20 | import org.opensearch.core.common.io.stream.StreamInput; 21 | import org.opensearch.core.common.io.stream.StreamOutput; 22 | import org.opensearch.rest.RestRequest; 23 | 24 | import lombok.AllArgsConstructor; 25 | import lombok.Getter; 26 | import lombok.NonNull; 27 | 28 | @AllArgsConstructor 29 | @Getter 30 | public class UploadGeoJSONRequest extends ActionRequest { 31 | 32 | /** 33 | * Request method type. This will be useful to decide whether new index should 34 | * be created for upload request or not. 35 | */ 36 | @NonNull 37 | private final RestRequest.Method method; 38 | @NonNull 39 | private final BytesReference content; 40 | 41 | public UploadGeoJSONRequest(StreamInput in) throws IOException { 42 | super(in); 43 | this.content = Objects.requireNonNull(in.readBytesReference(), "data is missing"); 44 | this.method = Objects.requireNonNull(in.readEnum(RestRequest.Method.class), "RestRequest Method is missing"); 45 | } 46 | 47 | @Override 48 | public ActionRequestValidationException validate() { 49 | return null; 50 | } 51 | 52 | @Override 53 | public void writeTo(StreamOutput out) throws IOException { 54 | super.writeTo(out); 55 | out.writeBytesReference(content); 56 | out.writeEnum(method); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/exceptions/IncompatibleDatasourceExceptionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.exceptions; 7 | 8 | import org.opensearch.common.io.stream.BytesStreamOutput; 9 | import org.opensearch.core.common.io.stream.BytesStreamInput; 10 | import org.opensearch.core.rest.RestStatus; 11 | import org.opensearch.test.OpenSearchTestCase; 12 | 13 | import lombok.SneakyThrows; 14 | 15 | public class IncompatibleDatasourceExceptionTests extends OpenSearchTestCase { 16 | public void testConstructor_whenCreated_thenSucceed() { 17 | IncompatibleDatasourceException exception = new IncompatibleDatasourceException( 18 | "New datasource is not compatible with existing datasource" 19 | ); 20 | assertEquals(RestStatus.BAD_REQUEST, exception.status()); 21 | } 22 | 23 | public void testConstructor_whenCreatedWithRootCause_thenSucceed() { 24 | IncompatibleDatasourceException exception = new IncompatibleDatasourceException( 25 | "New datasource is not compatible with existing datasource", 26 | new RuntimeException() 27 | ); 28 | assertEquals(RestStatus.BAD_REQUEST, exception.status()); 29 | } 30 | 31 | @SneakyThrows 32 | public void testConstructor_whenCreatedWithStream_thenSucceed() { 33 | IncompatibleDatasourceException exception = new IncompatibleDatasourceException( 34 | "New datasource is not compatible with existing datasource" 35 | ); 36 | 37 | BytesStreamOutput output = new BytesStreamOutput(); 38 | exception.writeTo(output); 39 | BytesStreamInput input = new BytesStreamInput(output.bytes().toBytesRef().bytes); 40 | IncompatibleDatasourceException copiedException = new IncompatibleDatasourceException(input); 41 | assertEquals(exception.getMessage(), copiedException.getMessage()); 42 | assertEquals(exception.status(), copiedException.status()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/common/HttpRedirectValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | import java.io.IOException; 9 | import java.net.HttpURLConnection; 10 | import java.util.Locale; 11 | 12 | import lombok.extern.log4j.Log4j2; 13 | 14 | /** 15 | * Utility class for validating HTTP connections no redirects 16 | */ 17 | @Log4j2 18 | public class HttpRedirectValidator { 19 | private static final int HTTP_REDIRECT_STATUS_MIN = 300; 20 | private static final int HTTP_REDIRECT_STATUS_MAX = 400; 21 | private static final String LOCATION_HEADER = "Location"; 22 | 23 | // Private constructor to prevent instantiation 24 | private HttpRedirectValidator() {} 25 | 26 | /** 27 | * Validates that an HTTP connection does not attempt to redirect 28 | * 29 | * @param httpConnection the HTTP connection to validate 30 | * @throws IOException if an I/O error occurs 31 | * @throws IllegalArgumentException if a redirect attempt is detected 32 | */ 33 | public static void validateNoRedirects(final HttpURLConnection httpConnection) throws IOException { 34 | httpConnection.setInstanceFollowRedirects(false); 35 | 36 | final int responseCode = httpConnection.getResponseCode(); 37 | if (responseCode >= HTTP_REDIRECT_STATUS_MIN && responseCode < HTTP_REDIRECT_STATUS_MAX) { 38 | final String redirectLocation = httpConnection.getHeaderField(LOCATION_HEADER); 39 | throw new IllegalArgumentException( 40 | String.format( 41 | Locale.ROOT, 42 | "HTTP redirects are not allowed. URL [%s] attempted to redirect to [%s] with status code [%d]", 43 | httpConnection.getURL().toString(), 44 | redirectLocation != null ? redirectLocation : "unknown", 45 | responseCode 46 | ) 47 | ); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/index/mapper/xyshape/XYShapeIndexer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.mapper.xyshape; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | import java.util.Objects; 11 | 12 | import org.apache.lucene.index.IndexableField; 13 | import org.opensearch.geometry.Geometry; 14 | import org.opensearch.geometry.GeometryVisitor; 15 | import org.opensearch.index.mapper.AbstractGeometryFieldMapper; 16 | import org.opensearch.index.mapper.ParseContext; 17 | 18 | /** 19 | * Converts geometries into Lucene-compatible form for indexing in a shape field. 20 | */ 21 | public class XYShapeIndexer implements AbstractGeometryFieldMapper.Indexer { 22 | 23 | private final GeometryVisitor indexableFieldsVisitor; 24 | private final GeometryVisitor supportVisitor; 25 | 26 | public XYShapeIndexer( 27 | GeometryVisitor supportVisitor, 28 | GeometryVisitor indexableFieldsVisitor 29 | ) { 30 | this.supportVisitor = Objects.requireNonNull(supportVisitor, "support visitor param cannot be null"); 31 | this.indexableFieldsVisitor = Objects.requireNonNull(indexableFieldsVisitor, "indexable field visitor param cannot be null"); 32 | } 33 | 34 | @Override 35 | public Geometry prepareForIndexing(Geometry geometry) { 36 | Objects.requireNonNull(geometry, "Geometry cannot be null"); 37 | return geometry.visit(supportVisitor); 38 | } 39 | 40 | @Override 41 | public Class processedClass() { 42 | return Geometry.class; 43 | } 44 | 45 | @Override 46 | public List indexShape(ParseContext parseContext, Geometry geometry) { 47 | Objects.requireNonNull(geometry, "geometry cannot be null"); 48 | return Arrays.asList(geometry.visit(indexableFieldsVisitor)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/stats/upload/UploadStatsNodeResponseBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import static java.util.Collections.emptyMap; 9 | import static java.util.Collections.emptySet; 10 | import static org.opensearch.geospatial.GeospatialTestHelper.randomLowerCaseString; 11 | import static org.opensearch.geospatial.stats.upload.UploadStatsBuilder.randomUploadStats; 12 | import static org.opensearch.test.OpenSearchTestCase.buildNewFakeTransportAddress; 13 | import static org.opensearch.test.OpenSearchTestCase.randomIntBetween; 14 | 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | import java.util.stream.IntStream; 18 | 19 | import org.opensearch.Version; 20 | import org.opensearch.cluster.node.DiscoveryNode; 21 | 22 | public class UploadStatsNodeResponseBuilder { 23 | private static final int MIN_STATS_NODE_RESPONSE = 2; 24 | private static final int MAX_STATS_NODE_RESPONSE = 5; 25 | 26 | public static UploadStatsNodeResponse randomStatsNodeResponse(String nodeID) { 27 | DiscoveryNode node = new DiscoveryNode( 28 | randomLowerCaseString(), 29 | nodeID, 30 | buildNewFakeTransportAddress(), 31 | emptyMap(), 32 | emptySet(), 33 | Version.CURRENT 34 | ); 35 | return new UploadStatsNodeResponse(node, randomUploadStats()); 36 | } 37 | 38 | public static Map randomStatsNodeResponse() { 39 | int randomResponseCount = randomIntBetween(MIN_STATS_NODE_RESPONSE, MAX_STATS_NODE_RESPONSE); 40 | Map nodesResponseMap = new HashMap<>(randomResponseCount); 41 | IntStream.range(0, randomResponseCount).forEach(unused -> { 42 | String nodeID = randomLowerCaseString(); 43 | nodesResponseMap.put(nodeID, randomStatsNodeResponse(nodeID)); 44 | }); 45 | return nodesResponseMap; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/jobscheduler/DatasourceExtensionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.jobscheduler; 7 | 8 | import static org.opensearch.geospatial.ip2geo.jobscheduler.DatasourceExtension.JOB_INDEX_NAME; 9 | 10 | import java.time.Instant; 11 | import java.time.temporal.ChronoUnit; 12 | 13 | import org.opensearch.common.xcontent.XContentFactory; 14 | import org.opensearch.geospatial.GeospatialTestHelper; 15 | import org.opensearch.geospatial.ip2geo.Ip2GeoTestCase; 16 | import org.opensearch.jobscheduler.spi.JobDocVersion; 17 | import org.opensearch.jobscheduler.spi.schedule.IntervalSchedule; 18 | 19 | public class DatasourceExtensionTests extends Ip2GeoTestCase { 20 | public void testBasic() { 21 | DatasourceExtension extension = new DatasourceExtension(); 22 | assertEquals("scheduler_geospatial_ip2geo_datasource", extension.getJobType()); 23 | assertEquals(JOB_INDEX_NAME, extension.getJobIndex()); 24 | assertEquals(DatasourceRunner.getJobRunnerInstance(), extension.getJobRunner()); 25 | } 26 | 27 | public void testParser() throws Exception { 28 | DatasourceExtension extension = new DatasourceExtension(); 29 | String id = GeospatialTestHelper.randomLowerCaseString(); 30 | IntervalSchedule schedule = new IntervalSchedule(Instant.now().truncatedTo(ChronoUnit.MILLIS), 1, ChronoUnit.DAYS); 31 | String endpoint = GeospatialTestHelper.randomLowerCaseString(); 32 | Datasource datasource = new Datasource(id, schedule, endpoint); 33 | 34 | Datasource anotherDatasource = (Datasource) extension.getJobParser() 35 | .parse( 36 | createParser(datasource.toXContent(XContentFactory.jsonBuilder(), null)), 37 | GeospatialTestHelper.randomLowerCaseString(), 38 | new JobDocVersion(randomPositiveLong(), randomPositiveLong(), randomPositiveLong()) 39 | ); 40 | 41 | assertTrue(datasource.equals(anotherDatasource)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.2.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.2.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.2.0 4 | 5 | ### Features 6 | 7 | * Add feature processor to convert geo-json feature to geo-shape field ([#15](https://github.com/opensearch-project/geospatial/pull/15)) 8 | * Add rest handler for geo-json upload ([#25](https://github.com/opensearch-project/geospatial/pull/25)) 9 | * Create UploadGeoJSONRequest content as an object ([#32](https://github.com/opensearch-project/geospatial/pull/32)) 10 | * Add GeoJSON object of type FeatureCollection ([#33](https://github.com/opensearch-project/geospatial/pull/33)) 11 | * Include new route to support update index while upload ([#34](https://github.com/opensearch-project/geospatial/pull/34)) 12 | * Add uploader to upload user input ([#35](https://github.com/opensearch-project/geospatial/pull/35)) 13 | * Make field name as optional ([#37](https://github.com/opensearch-project/geospatial/pull/37)) 14 | * Use BulkResponse build error message ([#46](https://github.com/opensearch-project/geospatial/pull/46)) 15 | * Update upload API response structure ([#51](https://github.com/opensearch-project/geospatial/pull/51)) 16 | * Add metric and stat entity ([#54](https://github.com/opensearch-project/geospatial/pull/54)) 17 | * Create Upload Stats Service to build response for stats API ([#62](https://github.com/opensearch-project/geospatial/pull/62)) 18 | * Include stats api to provide upload metrics ([#64](https://github.com/opensearch-project/geospatial/pull/64)) 19 | 20 | ### Infrastructure 21 | * Create plugin using plugin template ([#3](https://github.com/opensearch-project/geospatial/pull/3)) 22 | * Add formatter config from OpenSearch ([#21](https://github.com/opensearch-project/geospatial/pull/21)) 23 | * Adding JDK 11 to CI matrix ([#31](https://github.com/opensearch-project/geospatial/pull/31)) 24 | * Add support to run integration tests with multiple nodes ([#57](https://github.com/opensearch-project/geospatial/pull/57)) 25 | 26 | ### Maintenance 27 | * Update OpenSearch upstream version to 2.2.0([#87](https://github.com/opensearch-project/geospatial/pull/87)) -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/GetDatasourceRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import java.io.IOException; 9 | 10 | import org.opensearch.action.ActionRequest; 11 | import org.opensearch.action.ActionRequestValidationException; 12 | import org.opensearch.core.common.io.stream.StreamInput; 13 | import org.opensearch.core.common.io.stream.StreamOutput; 14 | 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | 18 | /** 19 | * Ip2Geo datasource get request 20 | */ 21 | @Getter 22 | @Setter 23 | public class GetDatasourceRequest extends ActionRequest { 24 | /** 25 | * @param names the datasource names 26 | * @return the datasource names 27 | */ 28 | private String[] names; 29 | 30 | /** 31 | * Constructs a new get datasource request with a list of datasources. 32 | * 33 | * If the list of datasources is empty or it contains a single element "_all", all registered datasources 34 | * are returned. 35 | * 36 | * @param names list of datasource names 37 | */ 38 | public GetDatasourceRequest(final String[] names) { 39 | this.names = names; 40 | } 41 | 42 | /** 43 | * Constructor with stream input 44 | * @param in the stream input 45 | * @throws IOException IOException 46 | */ 47 | public GetDatasourceRequest(final StreamInput in) throws IOException { 48 | super(in); 49 | this.names = in.readStringArray(); 50 | } 51 | 52 | @Override 53 | public ActionRequestValidationException validate() { 54 | ActionRequestValidationException errors = null; 55 | if (names == null) { 56 | errors = new ActionRequestValidationException(); 57 | errors.addValidationError("names should not be null"); 58 | } 59 | return errors; 60 | } 61 | 62 | @Override 63 | public void writeTo(final StreamOutput out) throws IOException { 64 | super.writeTo(out); 65 | out.writeStringArray(names); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/action/RestDeleteDatasourceHandlerTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.URL_DELIMITER; 9 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 10 | 11 | import java.util.Locale; 12 | import java.util.concurrent.atomic.AtomicBoolean; 13 | 14 | import org.junit.Before; 15 | import org.opensearch.geospatial.GeospatialTestHelper; 16 | import org.opensearch.rest.RestRequest; 17 | import org.opensearch.test.rest.FakeRestRequest; 18 | import org.opensearch.test.rest.RestActionTestCase; 19 | 20 | public class RestDeleteDatasourceHandlerTests extends RestActionTestCase { 21 | private String path; 22 | private RestDeleteDatasourceHandler action; 23 | 24 | @Before 25 | public void setupAction() { 26 | action = new RestDeleteDatasourceHandler(); 27 | controller().registerHandler(action); 28 | path = String.join(URL_DELIMITER, getPluginURLPrefix(), "ip2geo/datasource/%s"); 29 | } 30 | 31 | public void testPrepareRequest_whenValidInput_thenSucceed() { 32 | String datasourceName = GeospatialTestHelper.randomLowerCaseString(); 33 | RestRequest request = new FakeRestRequest.Builder(xContentRegistry()).withMethod(RestRequest.Method.DELETE) 34 | .withPath(String.format(Locale.ROOT, path, datasourceName)) 35 | .build(); 36 | AtomicBoolean isExecuted = new AtomicBoolean(false); 37 | 38 | verifyingClient.setExecuteLocallyVerifier((actionResponse, actionRequest) -> { 39 | assertTrue(actionRequest instanceof DeleteDatasourceRequest); 40 | DeleteDatasourceRequest deleteDatasourceRequest = (DeleteDatasourceRequest) actionRequest; 41 | assertEquals(datasourceName, deleteDatasourceRequest.getName()); 42 | isExecuted.set(true); 43 | return null; 44 | }); 45 | 46 | dispatchRequest(request); 47 | assertTrue(isExecuted.get()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/action/upload/geojson/UploadGeoJSONRequestTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action.upload.geojson; 7 | 8 | import static org.opensearch.geospatial.GeospatialTestHelper.randomLowerCaseString; 9 | import static org.opensearch.rest.RestRequest.Method.POST; 10 | import static org.opensearch.rest.RestRequest.Method.PUT; 11 | 12 | import java.io.IOException; 13 | import java.nio.charset.StandardCharsets; 14 | 15 | import org.json.JSONObject; 16 | import org.opensearch.common.io.stream.BytesStreamOutput; 17 | import org.opensearch.core.common.bytes.BytesArray; 18 | import org.opensearch.core.common.io.stream.StreamInput; 19 | import org.opensearch.rest.RestRequest; 20 | import org.opensearch.test.OpenSearchTestCase; 21 | 22 | public class UploadGeoJSONRequestTests extends OpenSearchTestCase { 23 | 24 | private String getRandomRequestBody() { 25 | JSONObject json = new JSONObject(); 26 | json.put(randomLowerCaseString(), randomLowerCaseString()); 27 | return json.toString(); 28 | } 29 | 30 | public void testStreams() throws IOException { 31 | String requestBody = getRandomRequestBody(); 32 | RestRequest.Method method = PUT; 33 | UploadGeoJSONRequest request = new UploadGeoJSONRequest(method, new BytesArray(requestBody.getBytes(StandardCharsets.UTF_8))); 34 | BytesStreamOutput output = new BytesStreamOutput(); 35 | request.writeTo(output); 36 | StreamInput in = StreamInput.wrap(output.bytes().toBytesRef().bytes); 37 | 38 | UploadGeoJSONRequest serialized = new UploadGeoJSONRequest(in); 39 | assertEquals(requestBody, serialized.getContent().utf8ToString()); 40 | assertEquals(method, serialized.getMethod()); 41 | } 42 | 43 | public void testRequestValidation() { 44 | UploadGeoJSONRequest request = new UploadGeoJSONRequest( 45 | POST, 46 | new BytesArray(getRandomRequestBody().getBytes(StandardCharsets.UTF_8)) 47 | ); 48 | assertNull(request.validate()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /release-notes/opensearch-geospatial.release-notes-2.4.0.0.md: -------------------------------------------------------------------------------- 1 | ## Version 2.4.0.0 Release Notes 2 | 3 | Compatible with OpenSearch 2.4.0 4 | 5 | ### Features 6 | * Support Uber's H3 geospatial indexing system as geohex_grid ([#179](https://github.com/opensearch-project/geospatial/pull/179)) 7 | * Add geojson support for XYPoint ([#162](https://github.com/opensearch-project/geospatial/pull/162)) 8 | * Add XYPoint Field Type to index and query documents that contains cartesian points ([#130](https://github.com/opensearch-project/geospatial/pull/130)) 9 | * Add XYShapeQueryBuilder ([#82](https://github.com/opensearch-project/geospatial/pull/82)) 10 | * Add parameter to randomly include z coordinates to geometry ([#79](https://github.com/opensearch-project/geospatial/pull/79)) 11 | * Add shape processor ([#74](https://github.com/opensearch-project/geospatial/pull/74)) 12 | * Add shape field mapper ([#70](https://github.com/opensearch-project/geospatial/pull/70)) 13 | * Add ShapeIndexer to create indexable fields ([#68](https://github.com/opensearch-project/geospatial/pull/68)) 14 | 15 | ### Enhancements 16 | * add groupId to pluginzip publication ([#167](https://github.com/opensearch-project/geospatial/pull/167)) 17 | * Flip X and Y coordinates for WKT and array formats in XYPoint ([#156](https://github.com/opensearch-project/geospatial/pull/156)) 18 | 19 | ### Infrastructure 20 | * Add window and mac platform in CI ([#173](https://github.com/opensearch-project/geospatial/pull/173)) 21 | * Fix integration test failure with security enabled cluster ([#138](https://github.com/opensearch-project/geospatial/pull/138)) 22 | * Remove explicit dco check ([#126](https://github.com/opensearch-project/geospatial/pull/126)) 23 | * Include feature branch in workflow to trigger CI ([#102](https://github.com/opensearch-project/geospatial/pull/102)) 24 | 25 | ### Maintenance 26 | * Increment version to 2.4.0-SNAPSHOT ([#139](https://github.com/opensearch-project/geospatial/pull/139)) 27 | * Update to Gradle 7.5.1 ([#134](https://github.com/opensearch-project/geospatial/pull/134)) 28 | 29 | ### Refactoring 30 | * Remove optional to get features ([#177](https://github.com/opensearch-project/geospatial/pull/177)) -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/jobscheduler/DatasourceExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.jobscheduler; 7 | 8 | import static org.opensearch.geospatial.constants.IndexSetting.AUTO_EXPAND_REPLICAS; 9 | import static org.opensearch.geospatial.constants.IndexSetting.HIDDEN; 10 | import static org.opensearch.geospatial.constants.IndexSetting.NUMBER_OF_SHARDS; 11 | 12 | import java.util.Map; 13 | 14 | import org.opensearch.jobscheduler.spi.JobSchedulerExtension; 15 | import org.opensearch.jobscheduler.spi.ScheduledJobParser; 16 | import org.opensearch.jobscheduler.spi.ScheduledJobRunner; 17 | 18 | /** 19 | * Datasource job scheduler extension 20 | * 21 | * This extension is responsible for scheduling GeoIp data update task 22 | * 23 | * See https://github.com/opensearch-project/job-scheduler/blob/main/README.md#getting-started 24 | */ 25 | public class DatasourceExtension implements JobSchedulerExtension { 26 | /** 27 | * Job index name for a datasource 28 | */ 29 | public static final String JOB_INDEX_NAME = ".scheduler-geospatial-ip2geo-datasource"; 30 | /** 31 | * Job index setting 32 | * 33 | * We want it to be single shard so that job can be run only in a single node by job scheduler. 34 | * We want it to expand to all replicas so that querying to this index can be done locally to reduce latency. 35 | */ 36 | public static final Map INDEX_SETTING = Map.of(NUMBER_OF_SHARDS, 1, AUTO_EXPAND_REPLICAS, "0-all", HIDDEN, true); 37 | 38 | @Override 39 | public String getJobType() { 40 | return "scheduler_geospatial_ip2geo_datasource"; 41 | } 42 | 43 | @Override 44 | public String getJobIndex() { 45 | return JOB_INDEX_NAME; 46 | } 47 | 48 | @Override 49 | public ScheduledJobRunner getJobRunner() { 50 | return DatasourceRunner.getJobRunnerInstance(); 51 | } 52 | 53 | @Override 54 | public ScheduledJobParser getJobParser() { 55 | return (parser, id, jobDocVersion) -> Datasource.PARSER.parse(parser, null); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /libs/h3/src/main/java/org/opensearch/geospatial/h3/CellBoundary.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /* 6 | * Licensed to Elasticsearch B.V. under one or more contributor 7 | * license agreements. See the NOTICE file distributed with 8 | * this work for additional information regarding copyright 9 | * ownership. Elasticsearch B.V. licenses this file to you under 10 | * the Apache License, Version 2.0 (the "License"); you may 11 | * not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, 17 | * software distributed under the License is distributed on an 18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 | * KIND, either express or implied. See the License for the 20 | * specific language governing permissions and limitations 21 | * under the License. 22 | * 23 | * This project is based on a modification of https://github.com/uber/h3 which is licensed under the Apache 2.0 License. 24 | * 25 | * Copyright 2016-2021 Uber Technologies, Inc. 26 | */ 27 | package org.opensearch.geospatial.h3; 28 | 29 | /** 30 | * cell boundary points as {@link LatLng} 31 | */ 32 | public final class CellBoundary { 33 | 34 | /** Maximum number of cell boundary vertices; worst case is pentagon: 35 | * 5 original verts + 5 edge crossings 36 | */ 37 | private static final int MAX_CELL_BNDRY_VERTS = 10; 38 | /** How many points it holds */ 39 | private int numVertext; 40 | /** The actual points */ 41 | private final LatLng[] points = new LatLng[MAX_CELL_BNDRY_VERTS]; 42 | 43 | CellBoundary() {} 44 | 45 | void add(LatLng point) { 46 | points[numVertext++] = point; 47 | } 48 | 49 | /** Number of points in this boundary */ 50 | public int numPoints() { 51 | return numVertext; 52 | } 53 | 54 | /** Return the point at the given position*/ 55 | public LatLng getLatLon(int i) { 56 | if (i >= numVertext) { 57 | throw new IndexOutOfBoundsException(); 58 | } 59 | return points[i]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/index/query/xypoint/XYPointQueryIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.query.xypoint; 7 | 8 | import static org.opensearch.geospatial.GeospatialTestHelper.randomLowerCaseString; 9 | 10 | import java.util.Map; 11 | 12 | import org.opensearch.client.ResponseException; 13 | import org.opensearch.common.geo.ShapeRelation; 14 | import org.opensearch.common.settings.Settings; 15 | import org.opensearch.geometry.Rectangle; 16 | import org.opensearch.geospatial.index.mapper.xypoint.XYPointFieldMapper; 17 | import org.opensearch.geospatial.index.query.AbstractXYShapeQueryTestCase; 18 | 19 | public class XYPointQueryIT extends AbstractXYShapeQueryTestCase { 20 | private String indexName; 21 | private String xyPointFieldName; 22 | 23 | @Override 24 | public void setUp() throws Exception { 25 | super.setUp(); 26 | indexName = randomLowerCaseString(); 27 | xyPointFieldName = randomLowerCaseString(); 28 | } 29 | 30 | @Override 31 | public String getIndexName() { 32 | return indexName; 33 | } 34 | 35 | @Override 36 | public String getFieldName() { 37 | return xyPointFieldName; 38 | } 39 | 40 | @Override 41 | public String getContentType() { 42 | return XYPointFieldMapper.CONTENT_TYPE; 43 | } 44 | 45 | public void testIndexPointsFilterRectangleWithUnsupportedRelation() throws Exception { 46 | createIndex(indexName, Settings.EMPTY, Map.of(xyPointFieldName, XYPointFieldMapper.CONTENT_TYPE)); 47 | 48 | final String firstDocument = buildDocumentWithWKT(xyPointFieldName, "POINT(-30 -30)"); 49 | indexDocument(indexName, firstDocument); 50 | 51 | Rectangle rectangle = new Rectangle(-45, 45, 45, -45); 52 | 53 | ResponseException exception = expectThrows( 54 | ResponseException.class, 55 | () -> searchUsingShapeRelation(indexName, xyPointFieldName, rectangle, ShapeRelation.CONTAINS) 56 | ); 57 | assertTrue(exception.getMessage().contains("[CONTAINS] query relation not supported")); 58 | 59 | deleteIndex(indexName); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /client/src/test/java/org/opensearch/geospatial/action/IpEnrichmentActionClientTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action; 7 | 8 | import static org.mockito.ArgumentMatchers.any; 9 | import static org.mockito.ArgumentMatchers.eq; 10 | import static org.mockito.Mockito.when; 11 | 12 | import java.util.Map; 13 | import java.util.concurrent.ExecutionException; 14 | 15 | import org.junit.Assert; 16 | import org.junit.Test; 17 | import org.junit.runner.RunWith; 18 | import org.mockito.Mock; 19 | import org.mockito.junit.MockitoJUnitRunner; 20 | import org.opensearch.common.action.ActionFuture; 21 | import org.opensearch.core.action.ActionResponse; 22 | import org.opensearch.transport.client.node.NodeClient; 23 | 24 | import lombok.SneakyThrows; 25 | 26 | @RunWith(MockitoJUnitRunner.class) 27 | public class IpEnrichmentActionClientTests { 28 | 29 | @Mock 30 | private NodeClient mockNodeClient; 31 | 32 | @Mock 33 | private ActionFuture mockResult; 34 | 35 | String dummyIpString = "192.168.1.1"; 36 | 37 | String dummyDataSourceName = "testDataSource"; 38 | 39 | Map dummyPayload = Map.of("k1", "v1"); 40 | 41 | @SneakyThrows 42 | @Test 43 | public void testWithValidResponse() { 44 | when(mockResult.get()).thenReturn(new IpEnrichmentResponse(dummyPayload)); 45 | when(mockNodeClient.execute(eq(IpEnrichmentAction.INSTANCE), any())).thenReturn(mockResult); 46 | IpEnrichmentActionClient ipClient = new IpEnrichmentActionClient(mockNodeClient); 47 | Map actualPayload = ipClient.getGeoLocationData(dummyIpString, dummyDataSourceName); 48 | Assert.assertEquals(dummyPayload, actualPayload); 49 | } 50 | 51 | @SneakyThrows 52 | @Test(expected = ExecutionException.class) 53 | public void testWithException() { 54 | when(mockResult.get()).thenThrow(new ExecutionException(new Throwable())); 55 | when(mockNodeClient.execute(eq(IpEnrichmentAction.INSTANCE), any())).thenReturn(mockResult); 56 | IpEnrichmentActionClient ipClient = new IpEnrichmentActionClient(mockNodeClient); 57 | ipClient.getGeoLocationData(dummyIpString, dummyDataSourceName); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/shared/PluginClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * The OpenSearch Contributors require contributions made to 6 | * this file be licensed under the Apache-2.0 license or a 7 | * compatible open source license. 8 | */ 9 | package org.opensearch.geospatial.shared; 10 | 11 | import org.apache.logging.log4j.LogManager; 12 | import org.apache.logging.log4j.Logger; 13 | import org.opensearch.action.ActionRequest; 14 | import org.opensearch.action.ActionType; 15 | import org.opensearch.common.util.concurrent.ThreadContext; 16 | import org.opensearch.core.action.ActionListener; 17 | import org.opensearch.core.action.ActionResponse; 18 | import org.opensearch.identity.Subject; 19 | import org.opensearch.transport.client.Client; 20 | import org.opensearch.transport.client.FilterClient; 21 | 22 | /** 23 | * A special client for executing transport actions as this plugin's system subject. 24 | */ 25 | public class PluginClient extends FilterClient { 26 | 27 | private static final Logger logger = LogManager.getLogger(PluginClient.class); 28 | 29 | private Subject subject; 30 | 31 | public PluginClient(Client delegate) { 32 | super(delegate); 33 | } 34 | 35 | public PluginClient(Client delegate, Subject subject) { 36 | super(delegate); 37 | this.subject = subject; 38 | } 39 | 40 | public void setSubject(Subject subject) { 41 | this.subject = subject; 42 | } 43 | 44 | @Override 45 | protected void doExecute( 46 | ActionType action, 47 | Request request, 48 | ActionListener listener 49 | ) { 50 | if (subject == null) { 51 | throw new IllegalStateException("PluginClient is not initialized."); 52 | } 53 | try (ThreadContext.StoredContext ctx = threadPool().getThreadContext().newStoredContext(false)) { 54 | subject.runAs(() -> { 55 | logger.info("Running transport action with subject: {}", subject.getPrincipal().getName()); 56 | super.doExecute(action, request, ActionListener.runBefore(listener, ctx::restore)); 57 | }); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/index/mapper/xypoint/XYPointIndexerTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.mapper.xypoint; 7 | 8 | import static org.mockito.Mockito.mock; 9 | import static org.opensearch.geospatial.index.common.xyshape.ShapeObjectBuilder.getRandomXYPoints; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | import org.apache.lucene.geo.XYPoint; 15 | import org.apache.lucene.index.IndexableField; 16 | import org.opensearch.index.mapper.ParseContext; 17 | import org.opensearch.test.OpenSearchTestCase; 18 | 19 | public class XYPointIndexerTests extends OpenSearchTestCase { 20 | private XYPointIndexer indexer; 21 | private ParseContext parseContext; 22 | private final static String fieldName = "geometry"; 23 | private final static Integer MIN_NUM_POINTS = 1; 24 | private final static Integer MAX_NUM_POINTS = 10; 25 | 26 | @Override 27 | public void setUp() throws Exception { 28 | super.setUp(); 29 | indexer = new XYPointIndexer(fieldName); 30 | parseContext = mock(ParseContext.class); 31 | } 32 | 33 | public void testIndexingNullGeometry() { 34 | expectThrows(NullPointerException.class, () -> indexer.prepareForIndexing(null)); 35 | } 36 | 37 | public void testIndexingEmptyList() { 38 | expectThrows(IllegalArgumentException.class, () -> indexer.prepareForIndexing(Collections.emptyList())); 39 | } 40 | 41 | public void testPrepareIndexing() { 42 | var point = mock(org.opensearch.geospatial.index.mapper.xypoint.XYPoint.class); 43 | List points = List.of(point); 44 | assertNotNull("failed to convert xypoints from opensearch to lucene type", indexer.prepareForIndexing(points)); 45 | } 46 | 47 | public void testIndexShape() { 48 | int numOfPoints = randomIntBetween(MIN_NUM_POINTS, MAX_NUM_POINTS); 49 | List xyPoints = getRandomXYPoints(numOfPoints, randomBoolean()); 50 | List indexableFields = indexer.indexShape(parseContext, xyPoints); 51 | assertEquals("failed to index xypoints", numOfPoints, indexableFields.size()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | This code of conduct applies to all spaces provided by the OpenSource project including in code, documentation, issue trackers, mailing lists, chat channels, wikis, blogs, social media and any other communication channels used by the project. 3 | 4 | 5 | **Our open source communities endeavor to:** 6 | 7 | * Be Inclusive: We are committed to being a community where everyone can join and contribute. This means using inclusive and welcoming language. 8 | * Be Welcoming: We are committed to maintaining a safe space for everyone to be able to contribute. 9 | * Be Respectful: We are committed to encouraging differing viewpoints, accepting constructive criticism and work collaboratively towards decisions that help the project grow. Disrespectful and unacceptable behavior will not be tolerated. 10 | * Be Collaborative: We are committed to supporting what is best for our community and users. When we build anything for the benefit of the project, we should document the work we do and communicate to others on how this affects their work. 11 | 12 | 13 | **Our Responsibility. As contributors, members, or bystanders we each individually have the responsibility to behave professionally and respectfully at all times. Disrespectful and unacceptable behaviors include, but are not limited to:** 14 | 15 | * The use of violent threats, abusive, discriminatory, or derogatory language; 16 | * Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, race, political or religious affiliation; 17 | * Posting of sexually explicit or violent content; 18 | * The use of sexualized language and unwelcome sexual attention or advances; 19 | * Public or private harassment of any kind; 20 | * Publishing private information, such as physical or electronic address, without permission; 21 | * Other conduct which could reasonably be considered inappropriate in a professional setting; 22 | * Advocating for or encouraging any of the above behaviors. 23 | * Enforcement and Reporting Code of Conduct Issues: 24 | 25 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported. [Contact us](mailto:opensource-codeofconduct@amazon.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. 26 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/action/upload/geojson/UploadGeoJSONResponseTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action.upload.geojson; 7 | 8 | import org.opensearch.action.bulk.BulkResponse; 9 | import org.opensearch.common.xcontent.XContentType; 10 | import org.opensearch.core.common.Strings; 11 | import org.opensearch.geospatial.GeospatialTestHelper; 12 | import org.opensearch.test.OpenSearchTestCase; 13 | 14 | public class UploadGeoJSONResponseTests extends OpenSearchTestCase { 15 | 16 | private static final int MAX_SUCCESS_ITEM_COUNT = 5; 17 | private static final int MIN_SUCCESS_ITEM_COUNT = 5; 18 | private static final int FAILURE_ITEM_COUNT = 1; 19 | 20 | public void testToXContentHasNoFailure() { 21 | int successActionCount = randomIntBetween(MIN_SUCCESS_ITEM_COUNT, MAX_SUCCESS_ITEM_COUNT); 22 | final BulkResponse bulkItemResponses = GeospatialTestHelper.generateRandomBulkResponse(successActionCount, false); 23 | UploadGeoJSONResponse getResponse = new UploadGeoJSONResponse(bulkItemResponses); 24 | String responseBody = Strings.toString(XContentType.JSON, getResponse); 25 | assertTrue(responseBody.contains("\"errors\":false")); 26 | assertTrue(responseBody.contains("\"failure\":0")); 27 | assertTrue(responseBody.contains("\"total\":" + successActionCount)); 28 | assertTrue(responseBody.contains("\"success\":" + successActionCount)); 29 | 30 | } 31 | 32 | public void testToXContentHasFailure() { 33 | int successActionCount = randomIntBetween(MIN_SUCCESS_ITEM_COUNT, MAX_SUCCESS_ITEM_COUNT); 34 | int totalActionCount = successActionCount + FAILURE_ITEM_COUNT; 35 | final BulkResponse bulkItemResponses = GeospatialTestHelper.generateRandomBulkResponse(successActionCount, true); 36 | UploadGeoJSONResponse getResponse = new UploadGeoJSONResponse(bulkItemResponses); 37 | String responseBody = Strings.toString(XContentType.JSON, getResponse); 38 | assertTrue(responseBody.contains("\"errors\":true")); 39 | assertTrue(responseBody.contains("\"total\":" + totalActionCount)); 40 | assertTrue(responseBody.contains("\"success\":" + successActionCount)); 41 | assertTrue(responseBody.contains("\"failure\":" + FAILURE_ITEM_COUNT)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test plugin 2 | on: 3 | push: 4 | branches: 5 | - "*" 6 | - "feature/**" 7 | pull_request: 8 | branches: 9 | - "*" 10 | - "feature/**" 11 | jobs: 12 | Get-CI-Image-Tag: 13 | uses: opensearch-project/opensearch-build/.github/workflows/get-ci-image-tag.yml@main 14 | with: 15 | product: opensearch 16 | 17 | Build-linux: 18 | needs: Get-CI-Image-Tag 19 | strategy: 20 | matrix: 21 | java: [21, 25] 22 | 23 | name: Build and Test geospatial Plugin 24 | runs-on: ubuntu-latest 25 | container: 26 | # using the same image which is used by opensearch-build team to build the OpenSearch Distribution 27 | # this image tag is subject to change as more dependencies and updates will arrive over time 28 | image: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-version-linux }} 29 | options: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-start-options }} 30 | 31 | steps: 32 | - name: Run start commands 33 | run: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-start-command }} 34 | 35 | - name: Checkout geospatial 36 | uses: actions/checkout@v4 37 | 38 | - name: Setup Java ${{ matrix.java }} 39 | uses: actions/setup-java@v4 40 | with: 41 | distribution: 'corretto' 42 | java-version: ${{ matrix.java }} 43 | 44 | - name: Run build 45 | run: | 46 | chown -R 1000:1000 `pwd` 47 | su `id -un 1000` -c "./gradlew build" 48 | 49 | - name: Upload Coverage Report 50 | uses: codecov/codecov-action@v4 51 | with: 52 | token: ${{ secrets.CODECOV_TOKEN }} 53 | 54 | Build-windows-macos: 55 | strategy: 56 | matrix: 57 | java: [21, 25] 58 | os: [windows-latest, macos-latest] 59 | 60 | name: Build and Test geospatial Plugin 61 | runs-on: ${{ matrix.os }} 62 | 63 | steps: 64 | - name: Checkout geospatial 65 | uses: actions/checkout@v4 66 | 67 | - name: Setup Java ${{ matrix.java }} 68 | uses: actions/setup-java@v1 69 | with: 70 | java-version: ${{ matrix.java }} 71 | 72 | - name: Run build 73 | run: | 74 | ./gradlew build 75 | 76 | - name: Upload Coverage Report 77 | uses: codecov/codecov-action@v1 78 | with: 79 | token: ${{ secrets.CODECOV_TOKEN }} 80 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/action/GetDatasourceRequestTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import org.opensearch.action.ActionRequestValidationException; 9 | import org.opensearch.common.io.stream.BytesStreamOutput; 10 | import org.opensearch.core.common.io.stream.BytesStreamInput; 11 | import org.opensearch.geospatial.GeospatialTestHelper; 12 | import org.opensearch.geospatial.ip2geo.Ip2GeoTestCase; 13 | 14 | public class GetDatasourceRequestTests extends Ip2GeoTestCase { 15 | public void testStreamInOut_whenEmptyNames_thenSucceed() throws Exception { 16 | String[] names = new String[0]; 17 | GetDatasourceRequest request = new GetDatasourceRequest(names); 18 | assertNull(request.validate()); 19 | 20 | // Run 21 | BytesStreamOutput output = new BytesStreamOutput(); 22 | request.writeTo(output); 23 | BytesStreamInput input = new BytesStreamInput(output.bytes().toBytesRef().bytes); 24 | GetDatasourceRequest copiedRequest = new GetDatasourceRequest(input); 25 | 26 | // Verify 27 | assertArrayEquals(request.getNames(), copiedRequest.getNames()); 28 | } 29 | 30 | public void testStreamInOut_whenNames_thenSucceed() throws Exception { 31 | String[] names = { GeospatialTestHelper.randomLowerCaseString(), GeospatialTestHelper.randomLowerCaseString() }; 32 | GetDatasourceRequest request = new GetDatasourceRequest(names); 33 | assertNull(request.validate()); 34 | 35 | // Run 36 | BytesStreamOutput output = new BytesStreamOutput(); 37 | request.writeTo(output); 38 | BytesStreamInput input = new BytesStreamInput(output.bytes().toBytesRef().bytes); 39 | GetDatasourceRequest copiedRequest = new GetDatasourceRequest(input); 40 | 41 | // Verify 42 | assertArrayEquals(request.getNames(), copiedRequest.getNames()); 43 | } 44 | 45 | public void testValidate_whenNull_thenError() { 46 | GetDatasourceRequest request = new GetDatasourceRequest((String[]) null); 47 | 48 | // Run 49 | ActionRequestValidationException error = request.validate(); 50 | 51 | // Verify 52 | assertNotNull(error.validationErrors()); 53 | assertFalse(error.validationErrors().isEmpty()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/common/ParameterValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Locale; 12 | 13 | import org.apache.commons.lang3.StringUtils; 14 | import org.opensearch.core.common.Strings; 15 | 16 | /** 17 | * Parameter validator for IP2Geo APIs 18 | */ 19 | public class ParameterValidator { 20 | private static final int MAX_DATASOURCE_NAME_BYTES = 127; 21 | 22 | /** 23 | * Validate datasource name and return list of error messages 24 | * 25 | * @param datasourceName datasource name 26 | * @return Error messages. Empty list if there is no violation. 27 | */ 28 | public List validateDatasourceName(final String datasourceName) { 29 | List errorMsgs = new ArrayList<>(); 30 | if (StringUtils.isBlank(datasourceName)) { 31 | errorMsgs.add("datasource name must not be empty"); 32 | return errorMsgs; 33 | } 34 | 35 | if (!Strings.validFileName(datasourceName)) { 36 | errorMsgs.add( 37 | String.format(Locale.ROOT, "datasource name must not contain the following characters %s", Strings.INVALID_FILENAME_CHARS) 38 | ); 39 | } 40 | if (datasourceName.contains("#")) { 41 | errorMsgs.add("datasource name must not contain '#'"); 42 | } 43 | if (datasourceName.contains(":")) { 44 | errorMsgs.add("datasource name must not contain ':'"); 45 | } 46 | if (datasourceName.charAt(0) == '_' || datasourceName.charAt(0) == '-' || datasourceName.charAt(0) == '+') { 47 | errorMsgs.add("datasource name must not start with '_', '-', or '+'"); 48 | } 49 | int byteCount = datasourceName.getBytes(StandardCharsets.UTF_8).length; 50 | if (byteCount > MAX_DATASOURCE_NAME_BYTES) { 51 | errorMsgs.add(String.format(Locale.ROOT, "datasource name is too long, (%d > %d)", byteCount, MAX_DATASOURCE_NAME_BYTES)); 52 | } 53 | if (datasourceName.equals(".") || datasourceName.equals("..")) { 54 | errorMsgs.add("datasource name must not be '.' or '..'"); 55 | } 56 | return errorMsgs; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/stats/upload/RestUploadStatsActionIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 9 | import static org.opensearch.geospatial.stats.upload.RestUploadStatsAction.ACTION_OBJECT; 10 | import static org.opensearch.geospatial.stats.upload.RestUploadStatsAction.ACTION_STATS; 11 | 12 | import org.apache.hc.core5.http.io.entity.EntityUtils; 13 | import org.opensearch.client.Request; 14 | import org.opensearch.client.Response; 15 | import org.opensearch.core.rest.RestStatus; 16 | import org.opensearch.geospatial.GeospatialRestTestCase; 17 | 18 | public class RestUploadStatsActionIT extends GeospatialRestTestCase { 19 | 20 | private static final int NUMBER_OF_FEATURES_TO_ADD = 3; 21 | 22 | private String getUploadStatsPath() { 23 | return String.join(URL_DELIMITER, getPluginURLPrefix(), ACTION_OBJECT, ACTION_STATS); 24 | } 25 | 26 | private String getStatsResponseAsString() throws Exception { 27 | Request statsRequest = new Request("GET", getUploadStatsPath()); 28 | Response statsResponse = client().performRequest(statsRequest); 29 | return EntityUtils.toString(statsResponse.getEntity()); 30 | } 31 | 32 | public void testStatsAPISuccess() throws Exception { 33 | 34 | Request request = new Request("GET", getUploadStatsPath()); 35 | Response response = client().performRequest(request); 36 | assertEquals("Failed to retrieve stats", RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode())); 37 | } 38 | 39 | public void testStatsAreUpdatedAfterUpload() throws Exception { 40 | // get current stats response 41 | final String currentUploadStats = getStatsResponseAsString(); 42 | assertNotNull(currentUploadStats); 43 | 44 | Response response = uploadGeoJSONFeatures(NUMBER_OF_FEATURES_TO_ADD, null, null); 45 | assertEquals(RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode())); 46 | 47 | // get stats response after an upload 48 | final String newUploadStats = getStatsResponseAsString(); 49 | assertNotNull(newUploadStats); 50 | assertTrue("New metrics are not added", newUploadStats.length() > currentUploadStats.length()); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/search/aggregations/bucket/geogrid/GeoHexGrid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.search.aggregations.bucket.geogrid; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import org.opensearch.core.common.io.stream.StreamInput; 13 | import org.opensearch.geo.search.aggregations.bucket.geogrid.BaseGeoGrid; 14 | import org.opensearch.geo.search.aggregations.bucket.geogrid.BaseGeoGridBucket; 15 | import org.opensearch.search.aggregations.InternalAggregations; 16 | 17 | /** 18 | * Represents a grid of cells where each cell's location is determined by a h3 cell address. 19 | * All h3CellAddress in a grid are of the same precision 20 | */ 21 | public final class GeoHexGrid extends BaseGeoGrid { 22 | 23 | public GeoHexGrid(StreamInput in) throws IOException { 24 | super(in); 25 | } 26 | 27 | @Override 28 | public BaseGeoGrid create(List list) { 29 | return new GeoHexGrid(name, requiredSize, buckets, metadata); 30 | } 31 | 32 | @Override 33 | public BaseGeoGridBucket createBucket(InternalAggregations internalAggregations, BaseGeoGridBucket baseGeoGridBucket) { 34 | return new GeoHexGridBucket(baseGeoGridBucket.hashAsLong(), baseGeoGridBucket.getDocCount(), internalAggregations); 35 | } 36 | 37 | @Override 38 | public String getWriteableName() { 39 | return GeoHexGridAggregationBuilder.NAME; 40 | } 41 | 42 | protected GeoHexGrid(String name, int requiredSize, List buckets, Map metadata) { 43 | super(name, requiredSize, buckets, metadata); 44 | } 45 | 46 | @Override 47 | protected Reader getBucketReader() { 48 | return GeoHexGridBucket::new; 49 | } 50 | 51 | @Override 52 | protected BaseGeoGrid create(String name, int requiredSize, List buckets, Map metadata) { 53 | return new GeoHexGrid(name, requiredSize, buckets, metadata); 54 | } 55 | 56 | @Override 57 | protected GeoHexGridBucket createBucket(long address, long docCount, InternalAggregations internalAggregations) { 58 | return new GeoHexGridBucket(address, docCount, internalAggregations); 59 | } 60 | 61 | int getRequiredSize() { 62 | return requiredSize; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /client/src/test/java/org/opensearch/geospatial/action/IpEnrichmentRequestTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.action; 7 | 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | /** 12 | * Test cases for IpEnrichmentRequest. 13 | */ 14 | public class IpEnrichmentRequestTests { 15 | 16 | /** 17 | * Test validate() against a valid record. 18 | */ 19 | @Test 20 | public void testValidateValidRequest() { 21 | System.out.println("Test"); 22 | IpEnrichmentRequest request = new IpEnrichmentRequest("192.168.1.1", "ValidDataSourceName"); 23 | Assert.assertNull(request.validate()); 24 | } 25 | 26 | /** 27 | * Test validate() against an invalid record, 28 | * Expecting an error being thrown as dataSource being null. 29 | */ 30 | @Test 31 | public void testValidateNullDataSourceName() { 32 | IpEnrichmentRequest request = new IpEnrichmentRequest("192.168.1.1", null); 33 | Assert.assertEquals(1, request.validate().validationErrors().size()); 34 | } 35 | 36 | /** 37 | * Test validate() against an invalid record, 38 | * Expecting an error being thrown as ipString being null. 39 | */ 40 | @Test 41 | public void testValidateNullIpString() { 42 | IpEnrichmentRequest request = new IpEnrichmentRequest(null, "dataSource"); 43 | Assert.assertEquals(1, request.validate().validationErrors().size()); 44 | } 45 | 46 | /** 47 | * Test validate() against an invalid record, 48 | * Expecting an error with size in 2, because both fields are null. 49 | */ 50 | @Test 51 | public void testValidateNullIpStringAndDataSourceName() { 52 | IpEnrichmentRequest request = new IpEnrichmentRequest(null, null); 53 | Assert.assertEquals(2, request.validate().validationErrors().size()); 54 | } 55 | 56 | /** 57 | * Test fromActionRequest( ) to make sure the serialisation works. 58 | */ 59 | @Test 60 | public void testFromActionRequestOnValidRecord() { 61 | String ipString = "192.168.1.1"; 62 | String dsName = "demo"; 63 | IpEnrichmentRequest request = new IpEnrichmentRequest(ipString, dsName); 64 | 65 | IpEnrichmentRequest requestAfterStream = IpEnrichmentRequest.fromActionRequest(request); 66 | 67 | Assert.assertEquals(request.getIpString(), requestAfterStream.getIpString()); 68 | Assert.assertEquals(request.getDatasourceName(), requestAfterStream.getDatasourceName()); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/action/RestUpdateDatasourceHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import static org.opensearch.geospatial.shared.URLBuilder.URL_DELIMITER; 9 | import static org.opensearch.geospatial.shared.URLBuilder.getPluginURLPrefix; 10 | import static org.opensearch.rest.RestRequest.Method.PUT; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | import org.opensearch.core.xcontent.XContentParser; 16 | import org.opensearch.geospatial.ip2geo.common.URLDenyListChecker; 17 | import org.opensearch.rest.BaseRestHandler; 18 | import org.opensearch.rest.RestRequest; 19 | import org.opensearch.rest.action.RestToXContentListener; 20 | import org.opensearch.transport.client.node.NodeClient; 21 | 22 | /** 23 | * Rest handler for Ip2Geo datasource update request 24 | */ 25 | public class RestUpdateDatasourceHandler extends BaseRestHandler { 26 | private static final String ACTION_NAME = "ip2geo_datasource_update"; 27 | 28 | private final URLDenyListChecker urlDenyListChecker; 29 | 30 | public RestUpdateDatasourceHandler(final URLDenyListChecker urlDenyListChecker) { 31 | this.urlDenyListChecker = urlDenyListChecker; 32 | } 33 | 34 | @Override 35 | public String getName() { 36 | return ACTION_NAME; 37 | } 38 | 39 | @Override 40 | protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { 41 | final UpdateDatasourceRequest updateDatasourceRequest = new UpdateDatasourceRequest(request.param("name")); 42 | if (request.hasContentOrSourceParam()) { 43 | try (XContentParser parser = request.contentOrSourceParamParser()) { 44 | UpdateDatasourceRequest.PARSER.parse(parser, updateDatasourceRequest, null); 45 | } 46 | } 47 | if (updateDatasourceRequest.getEndpoint() != null) { 48 | // Call to validate if URL is in a deny-list or not. 49 | urlDenyListChecker.toUrlIfNotInDenyList(updateDatasourceRequest.getEndpoint()); 50 | } 51 | return channel -> client.executeLocally( 52 | UpdateDatasourceAction.INSTANCE, 53 | updateDatasourceRequest, 54 | new RestToXContentListener<>(channel) 55 | ); 56 | } 57 | 58 | @Override 59 | public List routes() { 60 | String path = String.join(URL_DELIMITER, getPluginURLPrefix(), "ip2geo/datasource/{name}/_settings"); 61 | return List.of(new Route(PUT, path)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/ip2geo/action/DeleteDatasourceRequestTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.action; 7 | 8 | import org.opensearch.action.ActionRequestValidationException; 9 | import org.opensearch.common.io.stream.BytesStreamOutput; 10 | import org.opensearch.core.common.io.stream.BytesStreamInput; 11 | import org.opensearch.geospatial.GeospatialTestHelper; 12 | import org.opensearch.geospatial.ip2geo.Ip2GeoTestCase; 13 | 14 | import lombok.SneakyThrows; 15 | 16 | public class DeleteDatasourceRequestTests extends Ip2GeoTestCase { 17 | @SneakyThrows 18 | public void testStreamInOut_whenValidInput_thenSucceed() { 19 | String datasourceName = GeospatialTestHelper.randomLowerCaseString(); 20 | DeleteDatasourceRequest request = new DeleteDatasourceRequest(datasourceName); 21 | 22 | // Run 23 | BytesStreamOutput output = new BytesStreamOutput(); 24 | request.writeTo(output); 25 | BytesStreamInput input = new BytesStreamInput(output.bytes().toBytesRef().bytes); 26 | DeleteDatasourceRequest copiedRequest = new DeleteDatasourceRequest(input); 27 | 28 | // Verify 29 | assertEquals(request.getName(), copiedRequest.getName()); 30 | } 31 | 32 | public void testValidate_whenNull_thenError() { 33 | DeleteDatasourceRequest request = new DeleteDatasourceRequest((String) null); 34 | 35 | // Run 36 | ActionRequestValidationException error = request.validate(); 37 | 38 | // Verify 39 | assertNotNull(error.validationErrors()); 40 | assertFalse(error.validationErrors().isEmpty()); 41 | } 42 | 43 | public void testValidate_whenBlank_thenError() { 44 | DeleteDatasourceRequest request = new DeleteDatasourceRequest(" "); 45 | 46 | // Run 47 | ActionRequestValidationException error = request.validate(); 48 | 49 | // Verify 50 | assertNotNull(error.validationErrors()); 51 | assertFalse(error.validationErrors().isEmpty()); 52 | } 53 | 54 | public void testValidate_whenInvalidDatasourceName_thenFails() { 55 | String invalidName = "_" + GeospatialTestHelper.randomLowerCaseString(); 56 | DeleteDatasourceRequest request = new DeleteDatasourceRequest(invalidName); 57 | 58 | // Run 59 | ActionRequestValidationException exception = request.validate(); 60 | 61 | // Verify 62 | assertEquals(1, exception.validationErrors().size()); 63 | assertTrue(exception.validationErrors().get(0).contains("no such datasource")); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/ip2geo/common/URLDenyListChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.ip2geo.common; 7 | 8 | import java.net.InetAddress; 9 | import java.net.MalformedURLException; 10 | import java.net.URI; 11 | import java.net.URL; 12 | import java.net.UnknownHostException; 13 | import java.util.List; 14 | 15 | import org.opensearch.common.SuppressForbidden; 16 | import org.opensearch.common.settings.ClusterSettings; 17 | 18 | import inet.ipaddr.IPAddressString; 19 | import lombok.extern.log4j.Log4j2; 20 | 21 | /** 22 | * A class to check url against a deny-list 23 | */ 24 | @Log4j2 25 | public class URLDenyListChecker { 26 | private final ClusterSettings clusterSettings; 27 | 28 | public URLDenyListChecker(final ClusterSettings clusterSettings) { 29 | this.clusterSettings = clusterSettings; 30 | } 31 | 32 | /** 33 | * Convert String to URL after verifying the url is not on a deny-list 34 | * 35 | * @param url value to validate and convert to URL 36 | * @return value in URL type 37 | */ 38 | public URL toUrlIfNotInDenyList(final String url) { 39 | try { 40 | return toUrlIfNotInDenyList(url, clusterSettings.get(Ip2GeoSettings.DATASOURCE_ENDPOINT_DENYLIST)); 41 | } catch (UnknownHostException e) { 42 | log.error("Unknown host", e); 43 | throw new IllegalArgumentException("host provided in the datasource endpoint is unknown"); 44 | } catch (MalformedURLException e) { 45 | log.error("Malformed URL", e); 46 | throw new IllegalArgumentException("URL provided in the datasource endpoint is malformed"); 47 | } 48 | } 49 | 50 | @SuppressForbidden(reason = "Need to connect to http endpoint to read GeoIP database file") 51 | private URL toUrlIfNotInDenyList(final String url, final List denyList) throws UnknownHostException, MalformedURLException { 52 | URL urlToReturn = URI.create(url).toURL(); 53 | if (isInDenyList(new IPAddressString(InetAddress.getByName(urlToReturn.getHost()).getHostAddress()), denyList)) { 54 | throw new IllegalArgumentException( 55 | "given endpoint is blocked by deny list in cluster setting " + Ip2GeoSettings.DATASOURCE_ENDPOINT_DENYLIST.getKey() 56 | ); 57 | } 58 | return urlToReturn; 59 | } 60 | 61 | private boolean isInDenyList(final IPAddressString url, final List denyList) { 62 | return denyList.stream().map(cidr -> new IPAddressString(cidr)).anyMatch(cidr -> cidr.contains(url)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/UploadStatsTransportAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | 11 | import org.opensearch.action.FailedNodeException; 12 | import org.opensearch.action.support.ActionFilters; 13 | import org.opensearch.action.support.nodes.TransportNodesAction; 14 | import org.opensearch.cluster.service.ClusterService; 15 | import org.opensearch.common.inject.Inject; 16 | import org.opensearch.core.common.io.stream.StreamInput; 17 | import org.opensearch.threadpool.ThreadPool; 18 | import org.opensearch.transport.TransportService; 19 | 20 | public class UploadStatsTransportAction extends TransportNodesAction< 21 | UploadStatsRequest, 22 | UploadStatsResponse, 23 | UploadStatsNodeRequest, 24 | UploadStatsNodeResponse> { 25 | 26 | private final TransportService transportService; 27 | private final UploadStats uploadStats; 28 | 29 | @Inject 30 | public UploadStatsTransportAction( 31 | TransportService transportService, 32 | ClusterService clusterService, 33 | ThreadPool threadPool, 34 | ActionFilters actionFilters, 35 | UploadStats uploadStats 36 | ) { 37 | super( 38 | UploadStatsAction.NAME, 39 | threadPool, 40 | clusterService, 41 | transportService, 42 | actionFilters, 43 | UploadStatsRequest::new, 44 | UploadStatsNodeRequest::new, 45 | ThreadPool.Names.MANAGEMENT, 46 | UploadStatsNodeResponse.class 47 | ); 48 | this.transportService = transportService; 49 | this.uploadStats = uploadStats; 50 | } 51 | 52 | @Override 53 | protected UploadStatsResponse newResponse( 54 | UploadStatsRequest nodesRequest, 55 | List nodeResponses, 56 | List failures 57 | ) { 58 | return new UploadStatsResponse(clusterService.getClusterName(), nodeResponses, failures); 59 | } 60 | 61 | @Override 62 | protected UploadStatsNodeRequest newNodeRequest(UploadStatsRequest nodesRequest) { 63 | return new UploadStatsNodeRequest(nodesRequest); 64 | } 65 | 66 | @Override 67 | protected UploadStatsNodeResponse newNodeResponse(StreamInput streamInput) throws IOException { 68 | return new UploadStatsNodeResponse(streamInput); 69 | } 70 | 71 | @Override 72 | protected UploadStatsNodeResponse nodeOperation(UploadStatsNodeRequest nodeRequest) { 73 | return new UploadStatsNodeResponse(transportService.getLocalNode(), uploadStats); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/geojson/FeatureFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.geojson; 7 | 8 | import static org.opensearch.geospatial.GeospatialParser.toStringObjectMap; 9 | import static org.opensearch.geospatial.geojson.Feature.TYPE; 10 | 11 | import java.util.Map; 12 | 13 | import org.opensearch.geospatial.geojson.Feature.FeatureBuilder; 14 | 15 | import lombok.NonNull; 16 | 17 | /** 18 | * FeatureFactory helps to create {@link Feature} instance based on user input 19 | */ 20 | public class FeatureFactory { 21 | 22 | /** 23 | * The factory method to create an instance of Feature from input. 24 | * 25 | * @param input the object from where {@link Feature} will be extracted 26 | * @return Feature Instance from input 27 | * @throws NullPointerException if input is null 28 | * @throws IllegalArgumentException if input doesn't have valid arguments 29 | */ 30 | public static Feature create(@NonNull Map input) { 31 | var geoJSONType = input.get(Feature.TYPE_KEY); 32 | if (geoJSONType == null) { 33 | throw new IllegalArgumentException(Feature.TYPE_KEY + " cannot be null"); 34 | } 35 | if (!TYPE.equalsIgnoreCase(geoJSONType.toString())) { 36 | throw new IllegalArgumentException("Unknown type [ " + geoJSONType + " ], expected type [ " + TYPE + " ]"); 37 | } 38 | return extractFeature(input).build(); 39 | } 40 | 41 | private static FeatureBuilder extractFeature(Map input) { 42 | Object geometry = input.get(Feature.GEOMETRY_KEY); 43 | if (geometry == null) { 44 | throw new IllegalArgumentException("key: " + Feature.GEOMETRY_KEY + " cannot be null"); 45 | } 46 | if (!(geometry instanceof Map)) { 47 | throw new IllegalArgumentException( 48 | "key: " + Feature.GEOMETRY_KEY + " is not an instance of type Map but of type [ " + geometry.getClass().getName() + " ]" 49 | ); 50 | } 51 | Map geometryMap = toStringObjectMap(geometry); 52 | var featureBuilder = new FeatureBuilder(geometryMap); 53 | Object properties = input.get(Feature.PROPERTIES_KEY); 54 | if (properties == null) { 55 | return featureBuilder; 56 | } 57 | if (!(properties instanceof Map)) { 58 | throw new IllegalArgumentException( 59 | "key: " + Feature.PROPERTIES_KEY + " is not an instance of type Map but of type [ " + properties.getClass().getName() + " ]" 60 | ); 61 | } 62 | return featureBuilder.properties(toStringObjectMap(properties)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/UploadStatsResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Objects; 12 | import java.util.stream.Collectors; 13 | 14 | import org.opensearch.action.FailedNodeException; 15 | import org.opensearch.action.support.nodes.BaseNodesResponse; 16 | import org.opensearch.cluster.ClusterName; 17 | import org.opensearch.core.common.io.stream.StreamInput; 18 | import org.opensearch.core.common.io.stream.StreamOutput; 19 | import org.opensearch.core.common.io.stream.Writeable; 20 | import org.opensearch.core.xcontent.ToXContentObject; 21 | import org.opensearch.core.xcontent.XContentBuilder; 22 | 23 | public class UploadStatsResponse extends BaseNodesResponse implements Writeable, ToXContentObject { 24 | 25 | public UploadStatsResponse(StreamInput in) throws IOException { 26 | super(new ClusterName(in), in.readList(UploadStatsNodeResponse::new), in.readList(FailedNodeException::new)); 27 | } 28 | 29 | public UploadStatsResponse(ClusterName clusterName, List nodes, List failures) { 30 | super(clusterName, nodes, failures); 31 | } 32 | 33 | @Override 34 | protected List readNodesFrom(StreamInput in) throws IOException { 35 | return in.readList(UploadStatsNodeResponse::new); 36 | } 37 | 38 | @Override 39 | protected void writeNodesTo(StreamOutput out, List nodeResponses) throws IOException { 40 | out.writeList(nodeResponses); 41 | } 42 | 43 | @Override 44 | public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { 45 | 46 | final Map nodeIDStatsMap = getNodes().stream() 47 | .collect(Collectors.toMap(response -> response.getNode().getId(), UploadStatsNodeResponse::getUploadStats)); 48 | UploadStatsService uploadStatsService = new UploadStatsService(nodeIDStatsMap); 49 | return uploadStatsService.toXContent(builder, params); 50 | } 51 | 52 | @Override 53 | public boolean equals(Object o) { 54 | if (this == o) return true; 55 | if (o == null || getClass() != o.getClass()) return false; 56 | UploadStatsResponse otherResponse = (UploadStatsResponse) o; 57 | return Objects.equals(getNodes(), otherResponse.getNodes()) && Objects.equals(failures(), otherResponse.failures()); 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | return Objects.hash(getNodes(), failures()); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/org/opensearch/geospatial/geojson/FeatureCollectionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.geojson; 7 | 8 | import static org.opensearch.geospatial.GeospatialObjectBuilder.buildGeoJSONFeatureCollection; 9 | import static org.opensearch.geospatial.GeospatialObjectBuilder.randomGeoJSONFeature; 10 | import static org.opensearch.geospatial.geojson.FeatureCollection.FEATURES_KEY; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | import org.json.JSONArray; 16 | import org.json.JSONObject; 17 | import org.opensearch.test.OpenSearchTestCase; 18 | 19 | public class FeatureCollectionTests extends OpenSearchTestCase { 20 | 21 | public void testCreateFeatureCollection() { 22 | JSONArray features = new JSONArray(); 23 | features.put(randomGeoJSONFeature(new JSONObject())); 24 | features.put(randomGeoJSONFeature(new JSONObject())); 25 | features.put(randomGeoJSONFeature(new JSONObject())); 26 | 27 | Map featureCollectionAsMap = buildGeoJSONFeatureCollection(features).toMap(); 28 | FeatureCollection collection = FeatureCollection.create(featureCollectionAsMap); 29 | assertNotNull(collection); 30 | assertEquals(features.toList().size(), collection.getFeatures().size()); 31 | } 32 | 33 | public void testCreateFeatureCollectionInvalidType() { 34 | Map featureCollectionAsMap = new HashMap<>(); 35 | featureCollectionAsMap.put(FeatureCollection.TYPE_KEY, Feature.TYPE); 36 | IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> FeatureCollection.create(featureCollectionAsMap)); 37 | assertTrue(ex.getMessage().contains("expected type [ FeatureCollection ]")); 38 | } 39 | 40 | public void testCreateFeatureCollectionInvalidInput() { 41 | assertThrows(NullPointerException.class, () -> FeatureCollection.create(null)); 42 | } 43 | 44 | public void testCreateFeatureCollectionTypeMissing() { 45 | IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> FeatureCollection.create(new HashMap<>())); 46 | assertTrue(ex.getMessage().contains("type cannot be null")); 47 | } 48 | 49 | public void testCreateFeatureCollectionInvalidFeature() { 50 | Map featureCollectionAsMap = new HashMap<>(); 51 | featureCollectionAsMap.put(FeatureCollection.TYPE_KEY, FeatureCollection.TYPE); 52 | featureCollectionAsMap.put(FEATURES_KEY, "invalid"); 53 | IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> FeatureCollection.create(featureCollectionAsMap)); 54 | assertTrue(ex.getMessage().contains(FEATURES_KEY + " is not an instance of type List")); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/index/query/xypoint/XYPointQueryProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.index.query.xypoint; 7 | 8 | import java.util.Locale; 9 | 10 | import org.apache.lucene.search.Query; 11 | import org.opensearch.common.geo.ShapeRelation; 12 | import org.opensearch.geometry.Geometry; 13 | import org.opensearch.geospatial.index.mapper.xypoint.XYPointFieldMapper; 14 | import org.opensearch.index.query.QueryShardContext; 15 | import org.opensearch.index.query.QueryShardException; 16 | 17 | /** 18 | * Query Processor to convert given Geometry into Lucene query 19 | */ 20 | public class XYPointQueryProcessor { 21 | /** 22 | * Creates a {@link Query} that matches all indexed shapes to the provided {@link Geometry} based on {@link ShapeRelation} 23 | * 24 | * @param shape OpenSearch {@link Geometry} as an input 25 | * @param fieldName field name that contains indexed points 26 | * @param relation Relation to be used to get all points from given Geometry 27 | * @param context QueryShardContext instance 28 | * @return {@link Query} instance from XYPointField.XYPointInGeometryQuery 29 | */ 30 | public Query shapeQuery(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context) { 31 | validateIsXYPointFieldType(fieldName, context); 32 | // XYPoint only support "intersects" spatial relation which returns points that are on the edge and inside the given geometry 33 | if (relation != ShapeRelation.INTERSECTS) { 34 | throw new QueryShardException( 35 | context, 36 | String.format(Locale.ROOT, "[%s] query relation not supported for Field [%s]", relation, fieldName) 37 | ); 38 | } 39 | 40 | return getVectorQueryFromShape(shape, fieldName, context); 41 | } 42 | 43 | private void validateIsXYPointFieldType(String fieldName, QueryShardContext context) { 44 | var fieldType = context.fieldMapper(fieldName); 45 | if (fieldType instanceof XYPointFieldMapper.XYPointFieldType) { 46 | return; 47 | } 48 | 49 | throw new QueryShardException( 50 | context, 51 | String.format( 52 | Locale.ROOT, 53 | "Expected [%s] field type for Field [%s] but found [%s]", 54 | XYPointFieldMapper.CONTENT_TYPE, 55 | fieldName, 56 | fieldType.typeName() 57 | ) 58 | ); 59 | } 60 | 61 | protected Query getVectorQueryFromShape(Geometry queryShape, String fieldName, QueryShardContext context) { 62 | var xyPointQueryVisitor = new XYPointQueryVisitor(fieldName, context.fieldMapper(fieldName), context); 63 | return queryShape.visit(xyPointQueryVisitor); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/processor/FeatureProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.processor; 7 | 8 | import static org.opensearch.ingest.ConfigurationUtils.readStringProperty; 9 | 10 | import java.util.Map; 11 | 12 | import org.opensearch.geospatial.geojson.Feature; 13 | import org.opensearch.geospatial.geojson.FeatureFactory; 14 | import org.opensearch.ingest.AbstractProcessor; 15 | import org.opensearch.ingest.IngestDocument; 16 | import org.opensearch.ingest.Processor; 17 | 18 | /** 19 | * {@link FeatureProcessor} converts GeoJSON Feature into a document by extracting properties as its own field, 20 | * move GeoJSON Geometry object into OpenSearch geo_shape field, and, remove fields like "type" 21 | */ 22 | public class FeatureProcessor extends AbstractProcessor { 23 | 24 | public static final String FIELD_KEY = "field"; 25 | public static final String TYPE = "geojson-feature"; 26 | private final String geoShapeField; 27 | 28 | public FeatureProcessor(String tag, String description, String geoShapeField) { 29 | super(tag, description); 30 | this.geoShapeField = geoShapeField; 31 | } 32 | 33 | @Override 34 | public IngestDocument execute(IngestDocument ingestDocument) { 35 | // 1. Create Feature from ingesting document 36 | // 2. Remove field "type", since, we are not storing as geo-json 37 | // 3. Move properties.* as document's fields, since, we don't have to group it inside "properties" 38 | // 5. Move geojson's geometry object to geoshape field. 39 | final Feature feature = FeatureFactory.create(ingestDocument.getSourceAndMetadata()); 40 | ingestDocument.removeField(Feature.TYPE_KEY); 41 | feature.getProperties().forEach(ingestDocument::setFieldValue); 42 | if (ingestDocument.hasField(Feature.PROPERTIES_KEY)) { // properties are optional in Feature 43 | ingestDocument.removeField(Feature.PROPERTIES_KEY); 44 | } 45 | ingestDocument.setFieldValue(this.geoShapeField, feature.getGeometry()); 46 | ingestDocument.removeField(Feature.GEOMETRY_KEY); 47 | return ingestDocument; 48 | } 49 | 50 | @Override 51 | public String getType() { 52 | return TYPE; 53 | } 54 | 55 | public static final class Factory implements org.opensearch.ingest.Processor.Factory { 56 | @Override 57 | public FeatureProcessor create( 58 | Map registry, 59 | String processorTag, 60 | String description, 61 | Map config 62 | ) { 63 | String geoShapeField = readStringProperty(TYPE, processorTag, config, FIELD_KEY); 64 | return new FeatureProcessor(processorTag, description, geoShapeField); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/stats/upload/TotalUploadStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.stats.upload; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | import java.util.Locale; 11 | import java.util.Objects; 12 | import java.util.function.Function; 13 | 14 | import org.opensearch.core.xcontent.ToXContentObject; 15 | import org.opensearch.core.xcontent.XContentBuilder; 16 | 17 | // Holder to construct summary of Upload API Stats across all Nodes 18 | public final class TotalUploadStats implements ToXContentObject { 19 | 20 | // XContent field names 21 | public enum FIELDS { 22 | DURATION, 23 | FAILED, 24 | REQUEST_COUNT, 25 | SUCCESS, 26 | TOTAL, 27 | UPLOAD; 28 | 29 | @Override 30 | public String toString() { 31 | return name().toLowerCase(Locale.ROOT); 32 | } 33 | } 34 | 35 | private final List uploadStatsList; 36 | 37 | public TotalUploadStats(final List uploadStatsList) { 38 | this.uploadStatsList = Objects.requireNonNull(uploadStatsList, "Upload stats list cannot be null"); 39 | } 40 | 41 | @Override 42 | public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { 43 | builder.startObject(FIELDS.TOTAL.toString()); 44 | if (isUploadStatsEmpty()) { 45 | return builder.endObject(); 46 | } 47 | long totalRequestCount = uploadStatsList.stream().mapToLong(UploadStats::getTotalAPICount).sum(); 48 | builder.field(FIELDS.REQUEST_COUNT.toString(), totalRequestCount); 49 | 50 | long totalUpload = sumMetricField(uploadStatsList, UploadMetric::getUploadCount); 51 | builder.field(FIELDS.UPLOAD.toString(), totalUpload); 52 | 53 | long totalSuccess = sumMetricField(uploadStatsList, UploadMetric::getSuccessCount); 54 | builder.field(FIELDS.SUCCESS.toString(), totalSuccess); 55 | 56 | long totalFailed = sumMetricField(uploadStatsList, UploadMetric::getFailedCount); 57 | builder.field(FIELDS.FAILED.toString(), totalFailed); 58 | 59 | long totalDuration = sumMetricField(uploadStatsList, UploadMetric::getDuration); 60 | builder.field(FIELDS.DURATION.toString(), totalDuration); 61 | return builder.endObject(); 62 | } 63 | 64 | private long sumMetricField(List stats, Function mapper) { 65 | return stats.stream().map(UploadStats::getMetrics).flatMap(List::stream).mapToLong(mapper::apply).sum(); 66 | } 67 | 68 | /** 69 | * Return whether any upload metrics are available or not 70 | * @return true if no stats are available 71 | */ 72 | public boolean isUploadStatsEmpty() { 73 | return uploadStatsList.isEmpty(); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/opensearch/geospatial/search/aggregations/bucket/geogrid/GeoHexHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright OpenSearch Contributors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package org.opensearch.geospatial.search.aggregations.bucket.geogrid; 7 | 8 | import static org.opensearch.geospatial.h3.H3.MAX_H3_RES; 9 | import static org.opensearch.geospatial.h3.H3.MIN_H3_RES; 10 | import static org.opensearch.geospatial.h3.H3.geoToH3; 11 | import static org.opensearch.geospatial.h3.H3.h3IsValid; 12 | import static org.opensearch.geospatial.h3.H3.h3ToLatLng; 13 | import static org.opensearch.geospatial.h3.H3.stringToH3; 14 | 15 | import java.util.Locale; 16 | 17 | import org.opensearch.common.geo.GeoPoint; 18 | 19 | import lombok.NonNull; 20 | 21 | /** 22 | * Helper class for H3 library 23 | */ 24 | public class GeoHexHelper { 25 | 26 | /** 27 | * Checks whether given precision is within H3 Precision range 28 | * @param precision H3 index precision 29 | */ 30 | public static void checkPrecisionRange(int precision) { 31 | if ((precision < MIN_H3_RES) || (precision > MAX_H3_RES)) { 32 | throw new IllegalArgumentException( 33 | String.format(Locale.ROOT, "Invalid precision of %d . Must be between %d and %d.", precision, MIN_H3_RES, MAX_H3_RES) 34 | ); 35 | } 36 | } 37 | 38 | /** 39 | * Converts from long representation of an index to {@link GeoPoint} representation. 40 | * @param h3CellID H3 Cell Id 41 | * @throws IllegalArgumentException if invalid h3CellID is provided 42 | */ 43 | public static GeoPoint h3ToGeoPoint(long h3CellID) { 44 | if (h3IsValid(h3CellID) == false) { 45 | throw new IllegalArgumentException(String.format(Locale.ROOT, "Invalid H3 Cell address: %d", h3CellID)); 46 | } 47 | final var position = h3ToLatLng(h3CellID); 48 | return new GeoPoint(position.getLatDeg(), position.getLonDeg()); 49 | } 50 | 51 | /** 52 | * Converts from {@link String} representation of an index to {@link GeoPoint} representation. 53 | * @param h3CellID H3 Cell Id 54 | * @throws IllegalArgumentException if invalid h3CellID is provided 55 | */ 56 | public static GeoPoint h3ToGeoPoint(@NonNull String h3CellID) { 57 | return h3ToGeoPoint(stringToH3(h3CellID)); 58 | } 59 | 60 | /** 61 | * Encodes longitude/latitude into H3 Cell Address for given precision 62 | * 63 | * @param latitude Latitude in degrees. 64 | * @param longitude Longitude in degrees. 65 | * @param precision Precision, 0 <= res <= 15 66 | * @return The H3 index. 67 | * @throws IllegalArgumentException latitude, longitude, or precision are out of range. 68 | */ 69 | public static long longEncode(double longitude, double latitude, int precision) { 70 | return geoToH3(latitude, longitude, precision); 71 | } 72 | } 73 | --------------------------------------------------------------------------------