-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PPL command expression implementation for geoip
#3228
base: main
Are you sure you want to change the base?
Changes from all commits
1196e14
2296c85
30cb69e
83b2853
71f246c
c061765
e0c23a8
781caf5
8a46b14
4a486c5
6cf166b
7dc34ca
51e6a7f
36bb4b7
f4a3e91
727362f
559e4ed
91d7540
2f119a3
b424a64
2e0accf
264cee5
d9bc40a
0e3bbad
643c8a5
f2ec4ff
ed9f965
fcf2003
8f1d8b7
71c1bc7
65aa555
ae56c1a
3aaf656
0ba723b
efe9e47
c26806f
086ed12
12905e3
73082e8
59060d3
8682abb
b7acfe1
302ed85
da7af99
c302b13
e95e2b0
52be18b
af264c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,89 @@ | ||||||
name: GeoSpatial Plugin IT | ||||||
|
||||||
on: | ||||||
pull_request: | ||||||
push: | ||||||
branches-ignore: | ||||||
- 'dependabot/**' | ||||||
paths: | ||||||
- 'integ-test/**' | ||||||
- '.github/workflows/integ-tests-with-geo.yml' | ||||||
|
||||||
jobs: | ||||||
Get-CI-Image-Tag: | ||||||
uses: opensearch-project/opensearch-build/.github/workflows/get-ci-image-tag.yml@main | ||||||
with: | ||||||
product: opensearch | ||||||
|
||||||
security-it-linux: | ||||||
needs: Get-CI-Image-Tag | ||||||
strategy: | ||||||
fail-fast: false | ||||||
matrix: | ||||||
java: [21] | ||||||
runs-on: ubuntu-latest | ||||||
container: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems like |
||||||
# using the same image which is used by opensearch-build team to build the OpenSearch Distribution | ||||||
# this image tag is subject to change as more dependencies and updates will arrive over time | ||||||
image: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-version-linux }} | ||||||
options: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-start-options }} | ||||||
|
||||||
steps: | ||||||
- name: Run start commands | ||||||
run: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-start-command }} | ||||||
|
||||||
- uses: actions/checkout@v4 | ||||||
|
||||||
- name: Set up JDK ${{ matrix.java }} | ||||||
uses: actions/setup-java@v4 | ||||||
with: | ||||||
distribution: 'temurin' | ||||||
java-version: ${{ matrix.java }} | ||||||
|
||||||
- name: Build with Gradle | ||||||
run: | | ||||||
chown -R 1000:1000 `pwd` | ||||||
su `id -un 1000` -c "./gradlew integTestWithGeo" | ||||||
|
||||||
- name: Upload test reports | ||||||
if: ${{ always() }} | ||||||
uses: actions/upload-artifact@v4 | ||||||
continue-on-error: true | ||||||
with: | ||||||
name: test-reports-${{ matrix.os }}-${{ matrix.java }} | ||||||
path: | | ||||||
integ-test/build/reports/** | ||||||
integ-test/build/testclusters/*/logs/* | ||||||
integ-test/build/testclusters/*/config/* | ||||||
|
||||||
security-it-windows-macos: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
strategy: | ||||||
fail-fast: false | ||||||
matrix: | ||||||
os: [ windows-latest, macos-13 ] | ||||||
java: [21] | ||||||
|
||||||
runs-on: ${{ matrix.os }} | ||||||
|
||||||
steps: | ||||||
- uses: actions/checkout@v4 | ||||||
|
||||||
- name: Set up JDK ${{ matrix.java }} | ||||||
uses: actions/setup-java@v4 | ||||||
with: | ||||||
distribution: 'temurin' | ||||||
java-version: ${{ matrix.java }} | ||||||
|
||||||
- name: Build with Gradle | ||||||
run: ./gradlew integTestWithGeo | ||||||
|
||||||
- name: Upload test reports | ||||||
if: ${{ always() }} | ||||||
uses: actions/upload-artifact@v4 | ||||||
continue-on-error: true | ||||||
with: | ||||||
name: test-reports-${{ matrix.os }}-${{ matrix.java }} | ||||||
path: | | ||||||
integ-test/build/reports/** | ||||||
integ-test/build/testclusters/*/logs/* | ||||||
integ-test/build/testclusters/*/config/* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.sql.expression.ip; | ||
|
||
import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; | ||
import static org.opensearch.sql.data.type.ExprCoreType.STRING; | ||
import static org.opensearch.sql.expression.function.FunctionDSL.define; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import lombok.experimental.UtilityClass; | ||
import org.apache.commons.lang3.tuple.Pair; | ||
import org.opensearch.sql.data.type.ExprType; | ||
import org.opensearch.sql.expression.function.BuiltinFunctionName; | ||
import org.opensearch.sql.expression.function.BuiltinFunctionRepository; | ||
import org.opensearch.sql.expression.function.DefaultFunctionResolver; | ||
import org.opensearch.sql.expression.function.FunctionBuilder; | ||
import org.opensearch.sql.expression.function.FunctionName; | ||
import org.opensearch.sql.expression.function.FunctionSignature; | ||
import org.opensearch.sql.expression.function.SerializableFunction; | ||
|
||
/** | ||
* Utility class to register the method signature for geoip( ) expression, concreted reallocated to | ||
* `opensearch` module, as this Ip location require GeoSpatial Plugin runtime support. | ||
*/ | ||
@UtilityClass | ||
public class GeoIPFunctions { | ||
|
||
public void register(BuiltinFunctionRepository repository) { | ||
repository.register(geoIp()); | ||
} | ||
|
||
/** | ||
* To register all method signatures related to geoip( ) expression under eval. | ||
* | ||
* @return Resolver for geoip( ) expression. | ||
*/ | ||
private DefaultFunctionResolver geoIp() { | ||
return define( | ||
BuiltinFunctionName.GEOIP.getName(), | ||
openSearchImpl(BOOLEAN, Arrays.asList(STRING, STRING)), | ||
openSearchImpl(BOOLEAN, Arrays.asList(STRING, STRING, STRING))); | ||
} | ||
|
||
/** | ||
* Util method to generate probe implementation with given list of argument types, with marker | ||
* class `OpenSearchFunctionExpression` to annotate this is an OpenSearch specific expression. | ||
* | ||
* @param returnType return type. | ||
* @return Binary Function Implementation. | ||
*/ | ||
public static SerializableFunction<FunctionName, Pair<FunctionSignature, FunctionBuilder>> | ||
openSearchImpl(ExprType returnType, List<ExprType> args) { | ||
return functionName -> { | ||
FunctionSignature functionSignature = new FunctionSignature(functionName, args); | ||
FunctionBuilder functionBuilder = | ||
(functionProperties, arguments) -> | ||
new OpenSearchFunctionExpression(functionName, arguments, returnType); | ||
return Pair.of(functionSignature, functionBuilder); | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
*/ | ||
|
||
package org.opensearch.sql.expression.ip; | ||
|
||
import java.util.List; | ||
import org.opensearch.sql.data.model.ExprValue; | ||
import org.opensearch.sql.data.type.ExprType; | ||
import org.opensearch.sql.expression.Expression; | ||
import org.opensearch.sql.expression.FunctionExpression; | ||
import org.opensearch.sql.expression.env.Environment; | ||
import org.opensearch.sql.expression.function.FunctionName; | ||
|
||
/** | ||
* Marker class to identify functions only compatible with OpenSearch storage engine. Any attempt to | ||
* invoke the method different from OpenSearch will result in UnsupportedOperationException. | ||
*/ | ||
public class OpenSearchFunctionExpression extends FunctionExpression { | ||
|
||
private final ExprType returnType; | ||
|
||
public OpenSearchFunctionExpression( | ||
FunctionName functionName, List<Expression> arguments, ExprType returnType) { | ||
super(functionName, arguments); | ||
this.returnType = returnType; | ||
} | ||
|
||
@Override | ||
public ExprValue valueOf() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) { | ||
throw new UnsupportedOperationException( | ||
"OpenSearch runtime specific function, no default implementation available"); | ||
} | ||
|
||
@Override | ||
public ExprType type() { | ||
return returnType; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.sql.expression.ip; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNull; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN; | ||
import static org.opensearch.sql.data.type.ExprCoreType.STRING; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.opensearch.sql.data.model.ExprValue; | ||
import org.opensearch.sql.expression.DSL; | ||
import org.opensearch.sql.expression.Expression; | ||
import org.opensearch.sql.expression.env.Environment; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
public class GeoIPFunctionTest { | ||
|
||
// Mock value environment for testing. | ||
@Mock private Environment<Expression, ExprValue> env; | ||
|
||
@Test | ||
public void geoIpDefaultImplementation() { | ||
UnsupportedOperationException exception = | ||
assertThrows( | ||
UnsupportedOperationException.class, | ||
() -> | ||
DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING)) | ||
.valueOf(env)); | ||
assertTrue(exception.getMessage().matches(".*no default implementation available")); | ||
} | ||
|
||
@Test | ||
public void testGeoipFnctionSignature() { | ||
var geoip = DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING)); | ||
assertEquals(BOOLEAN, geoip.type()); | ||
} | ||
|
||
/** To make sure no logic being evaluated when no environment being passed. */ | ||
@Test | ||
public void testDefaultValueOf() { | ||
var geoip = DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING)); | ||
assertNull(geoip.valueOf()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
==================== | ||
Geo IP Address Functions | ||
==================== | ||
|
||
.. rubric:: Table of contents | ||
|
||
.. contents:: | ||
:local: | ||
:depth: 1 | ||
|
||
GEOIP | ||
--------- | ||
|
||
Description | ||
>>>>>>>>>>> | ||
|
||
Usage: `geoip(dataSourceName, ipAddress, options)` to lookup location information from given IP addresses via OpenSearch GeoSpatial plugin API. | ||
|
||
Argument type: STRING, STRING, STRING | ||
|
||
Return type: Tuple | ||
|
||
Example: | ||
|
||
os> source=weblogs | eval LookupResult = geoip("dataSourceName", "50.68.18.229", "country_iso_code,city_name") | ||
fetched rows / total rows = 1/1 | ||
+-------------------------------------------------------------+ | ||
| LookupResult | | ||
|-------------------------------------------------------------| | ||
| {'city_name': 'Vancouver', 'country_iso_code': 'CA'} | | ||
+-------------------------------------------------------------+ | ||
|
||
|
||
Note: | ||
- `dataSourceName` must be an established dataSource on OpenSearch GeoSpatial plugin, detail of configuration can be found: https://opensearch.org/docs/latest/ingest-pipelines/processors/ip2geo/ | ||
- `ip` can be an IPv4 or an IPv6 address | ||
- `options` is a comma separated String for user to specify fields to output, the selection of fields subject to dataSourceProvider's schema, the list of geolite2-city dataset provide fields: "country_iso_code", "country_name", "continent_name", "region_iso_code", "region_name", "city_name", "time_zone", "location" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.