Skip to content

Commit 97f7ba9

Browse files
authored
Add Neptune Analytics support (#541)
* Add Neptune Analytics support
1 parent 1cbf15a commit 97f7ba9

File tree

127 files changed

+4384
-279
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+4384
-279
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
Starting with v1.31.6, this file will contain a record of major features and updates made in each release of graph-notebook.
44

55
## Upcoming
6+
7+
## Release 4.0.0 (Nov 29, 2023)
8+
- Added support for Neptune Analytics ([Link to PR](https://github.com/aws/graph-notebook/pull/541))
69
- Added Air-Routes and EPL sample seed datasets for openCypher ([Link to PR](https://github.com/aws/graph-notebook/pull/540))
710

811
## Release 3.9.0 (Oct 9, 2023)

README.md

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Instructions for connecting to the following graph databases:
2222
| :-----------------------------: | :---------------------: | :-----------------: |
2323
|[Gremlin Server](#gremlin-server)| property graph | Gremlin |
2424
| [Blazegraph](#blazegraph) | RDF | SPARQL |
25-
|[Amazon Neptune](#amazon-neptune)| property graph or RDF | Gremlin or SPARQL |
25+
|[Amazon Neptune](#amazon-neptune)| property graph or RDF | Gremlin, openCypher, or SPARQL |
2626
| [Neo4J](#neo4j) | property graph | Cypher |
2727

2828
We encourage others to contribute configurations they find useful. There is an [`additional-databases`](https://github.com/aws/graph-notebook/blob/main/additional-databases) folder where more information can be found.
@@ -184,6 +184,7 @@ Configuration options can be set using the `%graph_notebook_config` magic comman
184184
| aws_region | The AWS region to use for Amazon Neptune connections | your-region-1 | string |
185185
| host | The host url to form a connection with | localhost | string |
186186
| load_from_s3_arn | The ARN of the S3 bucket to load data from [Amazon Neptune only] | | string |
187+
| neptune_service | The name of the Neptune service for the host url [Amazon Neptune only] | neptune-db | string |
187188
| port | The port to use when creating a connection | 8182 | number |
188189
| proxy_host | The proxy host url to route a connection through [Amazon Neptune only]| | string |
189190
| proxy_port | The proxy port to use when creating proxy connection [Amazon Neptune only] | 8182 | number |
@@ -251,12 +252,15 @@ To setup a new local Blazegraph database for use with the graph notebook, check
251252

252253
### Amazon Neptune
253254

254-
Change the configuration using `%%graph_notebook_config` and modify the defaults as they apply to your Neptune cluster:
255+
Change the configuration using `%%graph_notebook_config` and modify the defaults as they apply to your Neptune instance.
256+
257+
#### Neptune DB
255258

256259
``` python
257260
%%graph_notebook_config
258261
{
259262
"host": "your-neptune-endpoint",
263+
"neptune_service": "neptune-db",
260264
"port": 8182,
261265
"auth_mode": "DEFAULT",
262266
"load_from_s3_arn": "",
@@ -266,9 +270,45 @@ Change the configuration using `%%graph_notebook_config` and modify the defaults
266270
}
267271
```
268272

273+
#### Neptune Analytics
274+
275+
``` python
276+
%%graph_notebook_config
277+
{
278+
"host": "your-neptune-endpoint",
279+
"neptune_service": "neptune-graph",
280+
"port": 443,
281+
"auth_mode": "IAM",
282+
"ssl": true,
283+
"ssl_verify": true,
284+
"aws_region": "your-neptune-region"
285+
}
286+
```
287+
269288
To setup a new Amazon Neptune cluster, check out the [Amazon Web Services documentation](https://docs.aws.amazon.com/neptune/latest/userguide/manage-console-launch.html).
270289

271-
When connecting the graph notebook to Neptune, make sure you have a network setup to communicate to the VPC that Neptune runs on. If not, you can follow [this guide](https://github.com/aws/graph-notebook/tree/main/additional-databases/neptune).
290+
When connecting the graph notebook to Neptune via a private endpoint, make sure you have a network setup to communicate to the VPC that Neptune runs on. If not, you can follow [this guide](https://github.com/aws/graph-notebook/tree/main/additional-databases/neptune).
291+
292+
In addition to the above configuration options, you can also specify the following options:
293+
294+
### Amazon Neptune Proxy Connection
295+
296+
``` python
297+
%%graph_notebook_config
298+
{
299+
"host": "clustername.cluster-ididididid.us-east-1.neptune.amazonaws.com",
300+
"neptune_service": "neptune-db",
301+
"port": 8182,
302+
"ssl": true,
303+
"proxy_port": 8182,
304+
"proxy_host": "host.proxy.com",
305+
"auth_mode": "IAM",
306+
"aws_region": "us-east-1",
307+
"load_from_s3_arn": ""
308+
}
309+
```
310+
311+
Connecting to Amazon Neptune from clients outside the Neptune VPC using AWS Network [Load Balancer](https://aws-samples.github.io/aws-dbs-refarch-graph/src/connecting-using-a-load-balancer/#connecting-to-amazon-neptune-from-clients-outside-the-neptune-vpc-using-aws-network-load-balancer)
272312

273313
in addition to the above configuration options, you can also specify the following options:
274314

@@ -298,6 +338,7 @@ If you are running a SigV4 authenticated endpoint, ensure that your configuratio
298338
%%graph_notebook_config
299339
{
300340
"host": "your-neptune-endpoint",
341+
"neptune_service": "neptune-db",
301342
"port": 8182,
302343
"auth_mode": "IAM",
303344
"load_from_s3_arn": "",
@@ -376,7 +417,7 @@ python3 setup.py bdist_wheel
376417

377418
You should now be able to find the built distribution at
378419

379-
`./dist/graph_notebook-3.9.0-py3-none-any.whl`
420+
`./dist/graph_notebook-4.0.0-py3-none-any.whl`
380421

381422
And use it by following the [installation](https://github.com/aws/graph-notebook#installation) steps, replacing
382423

@@ -387,8 +428,7 @@ pip install graph-notebook
387428
with
388429

389430
``` python
390-
pip install ./dist/graph_notebook-3.9.0-py3-none-any.whl
391-
431+
pip install ./dist/graph_notebook-4.0.0-py3-none-any.whl
392432
```
393433

394434
## Contributing Guidelines

additional-databases/sagemaker/sagemaker-notebook-lifecycle/install-graph-notebook-lc-cn.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
sudo -u ec2-user -i <<'EOF'
44
55
echo "export GRAPH_NOTEBOOK_AUTH_MODE=DEFAULT" >> ~/.bashrc # set to IAM instead of DEFAULT if cluster is IAM enabled
6+
echo "export GRAPH_NOTEBOOK_SERVICE=neptune-db" >> ~/.bashrc
67
echo "export GRAPH_NOTEBOOK_HOST=CHANGE-ME" >> ~/.bashrc
78
echo "export GRAPH_NOTEBOOK_PORT=8182" >> ~/.bashrc
89
echo "export NEPTUNE_LOAD_FROM_S3_ROLE_ARN=" >> ~/.bashrc
@@ -28,8 +29,15 @@ python3 -m ipykernel install --sys-prefix --name python3 --display-name "Python
2829
echo "installing python dependencies..."
2930
pip uninstall NeptuneGraphNotebook -y # legacy uninstall when we used to install from source in s3
3031
32+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "jupyter_core<=5.3.2"
33+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "jupyter_server<=2.7.3"
3134
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "jupyter-console<=6.4.0"
3235
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "jupyter-client<=6.1.12"
36+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "ipywidgets==7.7.2"
37+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "jupyterlab_widgets==1.1.1"
38+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "notebook==6.4.12"
39+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "nbclient<=0.7.0"
40+
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "itables<=1.4.2"
3341
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn "awswrangler"
3442
3543
if [[ ${VERSION} == "" ]]; then
@@ -58,6 +66,7 @@ chmod -R a+rw ~/SageMaker/Neptune/*
5866
source ~/.bashrc || exit
5967
HOST=${GRAPH_NOTEBOOK_HOST}
6068
PORT=${GRAPH_NOTEBOOK_PORT}
69+
SERVICE=${GRAPH_NOTEBOOK_SERVICE}
6170
AUTH_MODE=${GRAPH_NOTEBOOK_AUTH_MODE}
6271
SSL=${GRAPH_NOTEBOOK_SSL}
6372
LOAD_FROM_S3_ARN=${NEPTUNE_LOAD_FROM_S3_ROLE_ARN}
@@ -69,13 +78,15 @@ fi
6978
echo "Creating config with
7079
HOST: ${HOST}
7180
PORT: ${PORT}
81+
SERVICE: ${SERVICE}
7282
AUTH_MODE: ${AUTH_MODE}
7383
SSL: ${SSL}
7484
AWS_REGION: ${AWS_REGION}"
7585
7686
/home/ec2-user/anaconda3/envs/JupyterSystemEnv/bin/python -m graph_notebook.configuration.generate_config \
7787
--host "${HOST}" \
7888
--port "${PORT}" \
89+
--neptune_service "${SERVICE}" \
7990
--auth_mode "${AUTH_MODE}" \
8091
--ssl "${SSL}" \
8192
--load_from_s3_arn "${LOAD_FROM_S3_ARN}" \

additional-databases/sagemaker/sagemaker-notebook-lifecycle/install-graph-notebook-lc.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
sudo -u ec2-user -i <<'EOF'
44
55
echo "export GRAPH_NOTEBOOK_AUTH_MODE=DEFAULT" >> ~/.bashrc # set to IAM instead of DEFAULT if cluster is IAM enabled
6+
echo "export GRAPH_NOTEBOOK_SERVICE=neptune-db" >> ~/.bashrc # set to neptune-graph for Neptune Analytics host
67
echo "export GRAPH_NOTEBOOK_HOST=CHANGE-ME" >> ~/.bashrc
78
echo "export GRAPH_NOTEBOOK_PORT=8182" >> ~/.bashrc
89
echo "export NEPTUNE_LOAD_FROM_S3_ROLE_ARN=" >> ~/.bashrc
@@ -28,8 +29,15 @@ python3 -m ipykernel install --sys-prefix --name python3 --display-name "Python
2829
echo "installing python dependencies..."
2930
pip uninstall NeptuneGraphNotebook -y # legacy uninstall when we used to install from source in s3
3031
32+
pip install "jupyter_core<=5.3.2"
33+
pip install "jupyter_server<=2.7.3"
3134
pip install "jupyter-console<=6.4.0"
3235
pip install "jupyter-client<=6.1.12"
36+
pip install "ipywidgets==7.7.2"
37+
pip install "jupyterlab_widgets==1.1.1"
38+
pip install "notebook==6.4.12"
39+
pip install "nbclient<=0.7.0"
40+
pip install "itables<=1.4.2"
3341
pip install awswrangler
3442
3543
if [[ ${VERSION} == "" ]]; then
@@ -58,6 +66,7 @@ chmod -R a+rw ~/SageMaker/Neptune/*
5866
source ~/.bashrc || exit
5967
HOST=${GRAPH_NOTEBOOK_HOST}
6068
PORT=${GRAPH_NOTEBOOK_PORT}
69+
SERVICE=${GRAPH_NOTEBOOK_SERVICE}
6170
AUTH_MODE=${GRAPH_NOTEBOOK_AUTH_MODE}
6271
SSL=${GRAPH_NOTEBOOK_SSL}
6372
LOAD_FROM_S3_ARN=${NEPTUNE_LOAD_FROM_S3_ROLE_ARN}
@@ -69,13 +78,15 @@ fi
6978
echo "Creating config with
7079
HOST: ${HOST}
7180
PORT: ${PORT}
81+
SERVICE: ${SERVICE}
7282
AUTH_MODE: ${AUTH_MODE}
7383
SSL: ${SSL}
7484
AWS_REGION: ${AWS_REGION}"
7585
7686
/home/ec2-user/anaconda3/envs/JupyterSystemEnv/bin/python -m graph_notebook.configuration.generate_config \
7787
--host "${HOST}" \
7888
--port "${PORT}" \
89+
--neptune_service "${SERVICE}" \
7990
--auth_mode "${AUTH_MODE}" \
8091
--ssl "${SSL}" \
8192
--load_from_s3_arn "${LOAD_FROM_S3_ARN}" \

src/graph_notebook/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
SPDX-License-Identifier: Apache-2.0
44
"""
55

6-
__version__ = '3.9.0'
6+
__version__ = '4.0.0'

src/graph_notebook/configuration/generate_config.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
from graph_notebook.neptune.client import SPARQL_ACTION, DEFAULT_PORT, DEFAULT_REGION, DEFAULT_GREMLIN_SERIALIZER, \
1212
DEFAULT_GREMLIN_TRAVERSAL_SOURCE, DEFAULT_NEO4J_USERNAME, DEFAULT_NEO4J_PASSWORD, DEFAULT_NEO4J_DATABASE, \
1313
NEPTUNE_CONFIG_HOST_IDENTIFIERS, is_allowed_neptune_host, false_str_variants, \
14-
GRAPHSONV3_VARIANTS, GRAPHSONV2_VARIANTS, GRAPHBINARYV1_VARIANTS
14+
GRAPHSONV3_VARIANTS, GRAPHSONV2_VARIANTS, GRAPHBINARYV1_VARIANTS, \
15+
NEPTUNE_DB_SERVICE_NAME, normalize_service_name
1516

1617
DEFAULT_CONFIG_LOCATION = os.path.expanduser('~/graph_notebook_config.json')
1718

@@ -117,6 +118,7 @@ def to_dict(self):
117118

118119
class Configuration(object):
119120
def __init__(self, host: str, port: int,
121+
neptune_service: str = NEPTUNE_DB_SERVICE_NAME,
120122
auth_mode: AuthModeEnum = DEFAULT_AUTH_MODE,
121123
load_from_s3_arn='', ssl: bool = True, ssl_verify: bool = True, aws_region: str = DEFAULT_REGION,
122124
proxy_host: str = '', proxy_port: int = DEFAULT_PORT,
@@ -135,6 +137,7 @@ def __init__(self, host: str, port: int,
135137
or is_allowed_neptune_host(hostname=self.proxy_host, host_allowlist=neptune_hosts)
136138
if is_neptune_host:
137139
self.is_neptune_config = True
140+
self.neptune_service = normalize_service_name(neptune_service)
138141
self.auth_mode = auth_mode
139142
self.load_from_s3_arn = load_from_s3_arn
140143
self.aws_region = aws_region
@@ -165,6 +168,7 @@ def to_dict(self) -> dict:
165168
if self.is_neptune_config:
166169
return {
167170
'host': self.host,
171+
'neptune_service': self.neptune_service,
168172
'port': self.port,
169173
'proxy_host': self.proxy_host,
170174
'proxy_port': self.proxy_port,
@@ -199,26 +203,30 @@ def write_to_file(self, file_path=DEFAULT_CONFIG_LOCATION):
199203

200204

201205
def generate_config(host, port, auth_mode: AuthModeEnum = AuthModeEnum.DEFAULT, ssl: bool = True,
202-
ssl_verify: bool = True, load_from_s3_arn='',
206+
ssl_verify: bool = True, neptune_service: str = NEPTUNE_DB_SERVICE_NAME, load_from_s3_arn='',
203207
aws_region: str = DEFAULT_REGION, proxy_host: str = '', proxy_port: int = DEFAULT_PORT,
204208
sparql_section: SparqlSection = SparqlSection(), gremlin_section: GremlinSection = GremlinSection(),
205209
neo4j_section=Neo4JSection(), neptune_hosts: list = NEPTUNE_CONFIG_HOST_IDENTIFIERS):
206210
use_ssl = False if ssl in false_str_variants else True
207211
verify_ssl = False if ssl_verify in false_str_variants else True
208-
c = Configuration(host, port, auth_mode, load_from_s3_arn, use_ssl, verify_ssl, aws_region, proxy_host, proxy_port,
209-
sparql_section, gremlin_section, neo4j_section, neptune_hosts)
212+
c = Configuration(host, port, neptune_service, auth_mode, load_from_s3_arn, use_ssl, verify_ssl, aws_region,
213+
proxy_host, proxy_port, sparql_section, gremlin_section, neo4j_section, neptune_hosts)
210214
return c
211215

212216

213217
def generate_default_config():
214-
c = generate_config('change-me', 8182, AuthModeEnum.DEFAULT, True, True, '', DEFAULT_REGION)
218+
c = generate_config('change-me', 8182, AuthModeEnum.DEFAULT, True, True, NEPTUNE_DB_SERVICE_NAME, '', DEFAULT_REGION)
215219
return c
216220

217221

218222
if __name__ == "__main__":
219223
parser = argparse.ArgumentParser()
220224
parser.add_argument("--host", help="the host url to form a connection with", required=True)
221225
parser.add_argument("--port", help="the port to use when creating a connection", default=8182)
226+
parser.add_argument("--neptune_service",
227+
default=NEPTUNE_DB_SERVICE_NAME,
228+
help="The neptune service name to use for signing requests. "
229+
"Use 'neptune-db' for Neptune DB, and 'neptune-graph' for Neptune Analytics.")
222230
parser.add_argument("--auth_mode", default=AuthModeEnum.DEFAULT.value,
223231
help="type of authentication the cluster being connected to is using. Can be DEFAULT or IAM")
224232
parser.add_argument("--ssl",
@@ -259,7 +267,10 @@ def generate_default_config():
259267
args = parser.parse_args()
260268

261269
auth_mode_arg = args.auth_mode if args.auth_mode != '' else AuthModeEnum.DEFAULT.value
262-
config = generate_config(args.host, int(args.port), AuthModeEnum(auth_mode_arg), args.ssl, args.ssl_verify,
270+
config = generate_config(args.host, int(args.port),
271+
AuthModeEnum(auth_mode_arg),
272+
args.ssl, args.ssl_verify,
273+
args.neptune_service,
263274
args.load_from_s3_arn, args.aws_region, args.proxy_host, int(args.proxy_port),
264275
SparqlSection(args.sparql_path, ''),
265276
GremlinSection(args.gremlin_traversal_source, args.gremlin_username,

src/graph_notebook/configuration/get_config.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
from graph_notebook.configuration.generate_config import DEFAULT_CONFIG_LOCATION, Configuration, AuthModeEnum, \
99
SparqlSection, GremlinSection, Neo4JSection
1010
from graph_notebook.neptune.client import NEPTUNE_CONFIG_HOST_IDENTIFIERS, is_allowed_neptune_host, false_str_variants, \
11-
DEFAULT_NEO4J_USERNAME, DEFAULT_NEO4J_PASSWORD, DEFAULT_NEO4J_DATABASE
11+
DEFAULT_NEO4J_USERNAME, DEFAULT_NEO4J_PASSWORD, DEFAULT_NEO4J_DATABASE, \
12+
NEPTUNE_DB_SERVICE_NAME, NEPTUNE_ANALYTICS_SERVICE_NAME, NEPTUNE_DB_CONFIG_NAMES, NEPTUNE_ANALYTICS_CONFIG_NAMES
13+
14+
neptune_params = ['neptune_service', 'auth_mode', 'load_from_s3_arn', 'aws_region']
1215

1316
neptune_params = ['auth_mode', 'load_from_s3_arn', 'aws_region']
1417

@@ -27,14 +30,17 @@ def get_config_from_dict(data: dict, neptune_hosts: list = NEPTUNE_CONFIG_HOST_I
2730
is_neptune_host = is_allowed_neptune_host(hostname=data["host"], host_allowlist=neptune_hosts)
2831

2932
if is_neptune_host:
33+
neptune_service = data['neptune_service'] if 'neptune_service' in data else NEPTUNE_DB_SERVICE_NAME
3034
if gremlin_section.to_dict()['traversal_source'] != 'g':
3135
print('Ignoring custom traversal source, Amazon Neptune does not support this functionality.\n')
3236
if neo4j_section.to_dict()['username'] != DEFAULT_NEO4J_USERNAME \
3337
or neo4j_section.to_dict()['password'] != DEFAULT_NEO4J_PASSWORD:
3438
print('Ignoring Neo4J custom authentication, Amazon Neptune does not support this functionality.\n')
3539
if neo4j_section.to_dict()['database'] != DEFAULT_NEO4J_DATABASE:
3640
print('Ignoring Neo4J custom database, Amazon Neptune does not support multiple databases.\n')
37-
config = Configuration(host=data['host'], port=data['port'], auth_mode=AuthModeEnum(data['auth_mode']),
41+
config = Configuration(host=data['host'], port=data['port'],
42+
neptune_service=neptune_service,
43+
auth_mode=AuthModeEnum(data['auth_mode']),
3844
ssl=data['ssl'], ssl_verify=ssl_verify, load_from_s3_arn=data['load_from_s3_arn'],
3945
aws_region=data['aws_region'], sparql_section=sparql_section,
4046
gremlin_section=gremlin_section, neo4j_section=neo4j_section,

src/graph_notebook/decorators/decorators.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import ipywidgets as widgets
1414
from graph_notebook.visualization.template_retriever import retrieve_template
15+
from graph_notebook.neptune.client import NEPTUNE_ANALYTICS_SERVICE_NAME
1516
from gremlin_python.driver.protocol import GremlinServerError
1617
from requests import HTTPError
1718

@@ -133,6 +134,22 @@ def use_magic_variables(*args, **kwargs):
133134
return use_magic_variables
134135

135136

137+
def neptune_db_only(func):
138+
@functools.wraps(func)
139+
def check_neptune_db(self, *args, **kwargs):
140+
if not hasattr(self.graph_notebook_config, 'neptune_service'):
141+
return func(*args, **kwargs)
142+
else:
143+
service_type = self.graph_notebook_config.neptune_service
144+
if service_type == NEPTUNE_ANALYTICS_SERVICE_NAME:
145+
print(f'This magic is unavailable for Neptune Analytics.')
146+
return
147+
else:
148+
return func(*args, **kwargs)
149+
150+
return check_neptune_db
151+
152+
136153
def http_ex_to_html(http_ex: HTTPError):
137154
try:
138155
error = json.loads(http_ex.response.content.decode('utf-8'))

0 commit comments

Comments
 (0)