View a markdown version of this page

Getting started with Amazon Neptune - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Getting started with Amazon Neptune

The following code example shows how to:

  • Create a VPC for your Neptune database

  • Create subnets in multiple availability zones

  • Configure security for your Neptune database

  • Create a Neptune DB subnet group

  • Create a Neptune DB cluster and instance

  • Add data to your graph database

  • Query your graph database

Bash
AWS CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # Amazon Neptune Getting Started Script # This script creates an Amazon Neptune database cluster and demonstrates basic operations # Set up logging LOG_FILE="neptune-setup.log" echo "Starting Neptune setup at $(date)" > "$LOG_FILE" # Function to log commands and their output log_cmd() { echo "Running: $1" | tee -a "$LOG_FILE" eval "$1" 2>&1 | tee -a "$LOG_FILE" return ${PIPESTATUS[0]} } # Function to check for errors in command output check_error() { local cmd_output="$1" local cmd_status="$2" local error_msg="$3" if [[ $cmd_status -ne 0 || "$cmd_output" =~ [Ee][Rr][Rr][Oo][Rr] ]]; then echo "ERROR: $error_msg" | tee -a "$LOG_FILE" cleanup_on_error exit 1 fi } # Function to clean up resources on error cleanup_on_error() { echo "Error encountered. Cleaning up resources..." | tee -a "$LOG_FILE" # Only attempt to delete resources that were successfully created if [[ -n "$DB_INSTANCE_ID" ]]; then echo "Deleting DB instance $DB_INSTANCE_ID..." | tee -a "$LOG_FILE" log_cmd "aws neptune delete-db-instance --db-instance-identifier $DB_INSTANCE_ID --skip-final-snapshot" log_cmd "aws neptune wait db-instance-deleted --db-instance-identifier $DB_INSTANCE_ID" fi if [[ -n "$DB_CLUSTER_ID" ]]; then echo "Deleting DB cluster $DB_CLUSTER_ID..." | tee -a "$LOG_FILE" log_cmd "aws neptune delete-db-cluster --db-cluster-identifier $DB_CLUSTER_ID --skip-final-snapshot" fi if [[ -n "$DB_SUBNET_GROUP" ]]; then echo "Deleting DB subnet group $DB_SUBNET_GROUP..." | tee -a "$LOG_FILE" log_cmd "aws neptune delete-db-subnet-group --db-subnet-group-name $DB_SUBNET_GROUP" fi if [[ -n "$SECURITY_GROUP_ID" ]]; then echo "Deleting security group $SECURITY_GROUP_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-security-group --group-id $SECURITY_GROUP_ID" fi if [[ -n "$SUBNET_IDS" ]]; then for SUBNET_ID in $SUBNET_IDS; do echo "Deleting subnet $SUBNET_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-subnet --subnet-id $SUBNET_ID" done fi if [[ -n "$VPC_ID" ]]; then echo "Deleting VPC $VPC_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-vpc --vpc-id $VPC_ID" fi } # Generate random identifier for resource names RANDOM_ID=$(openssl rand -hex 4) VPC_NAME="neptune-vpc-$RANDOM_ID" DB_SUBNET_GROUP="neptune-subnet-group-$RANDOM_ID" DB_CLUSTER_ID="neptune-cluster-$RANDOM_ID" DB_INSTANCE_ID="neptune-instance-$RANDOM_ID" SG_NAME="neptune-sg-$RANDOM_ID" echo "Using random identifier: $RANDOM_ID" | tee -a "$LOG_FILE" echo "VPC Name: $VPC_NAME" | tee -a "$LOG_FILE" echo "DB Subnet Group: $DB_SUBNET_GROUP" | tee -a "$LOG_FILE" echo "DB Cluster ID: $DB_CLUSTER_ID" | tee -a "$LOG_FILE" echo "DB Instance ID: $DB_INSTANCE_ID" | tee -a "$LOG_FILE" echo "Security Group Name: $SG_NAME" | tee -a "$LOG_FILE" # Step 1: Create VPC echo "Creating VPC..." | tee -a "$LOG_FILE" VPC_OUTPUT=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications "ResourceType=vpc,Tags=[{Key=Name,Value=$VPC_NAME}]" --output json) check_error "$VPC_OUTPUT" $? "Failed to create VPC" VPC_ID=$(echo "$VPC_OUTPUT" | grep -o '"VpcId": "[^"]*' | cut -d'"' -f4) echo "VPC created with ID: $VPC_ID" | tee -a "$LOG_FILE" # Enable DNS support for the VPC log_cmd "aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-support" log_cmd "aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames" # Step 2: Create Internet Gateway and attach to VPC echo "Creating Internet Gateway..." | tee -a "$LOG_FILE" IGW_OUTPUT=$(aws ec2 create-internet-gateway --output json) check_error "$IGW_OUTPUT" $? "Failed to create Internet Gateway" IGW_ID=$(echo "$IGW_OUTPUT" | grep -o '"InternetGatewayId": "[^"]*' | cut -d'"' -f4) echo "Internet Gateway created with ID: $IGW_ID" | tee -a "$LOG_FILE" log_cmd "aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID" # Step 3: Create subnets in different AZs echo "Creating subnets..." | tee -a "$LOG_FILE" # Get available AZs AZ_OUTPUT=$(aws ec2 describe-availability-zones --output json) check_error "$AZ_OUTPUT" $? "Failed to get availability zones" # Extract first 3 AZ names AZ1=$(echo "$AZ_OUTPUT" | grep -o '"ZoneName": "[^"]*' | cut -d'"' -f4 | head -1) AZ2=$(echo "$AZ_OUTPUT" | grep -o '"ZoneName": "[^"]*' | cut -d'"' -f4 | head -2 | tail -1) AZ3=$(echo "$AZ_OUTPUT" | grep -o '"ZoneName": "[^"]*' | cut -d'"' -f4 | head -3 | tail -1) # Create 3 subnets in different AZs SUBNET1_OUTPUT=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.1.0/24 --availability-zone $AZ1 --output json) check_error "$SUBNET1_OUTPUT" $? "Failed to create subnet 1" SUBNET1_ID=$(echo "$SUBNET1_OUTPUT" | grep -o '"SubnetId": "[^"]*' | cut -d'"' -f4) SUBNET2_OUTPUT=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.2.0/24 --availability-zone $AZ2 --output json) check_error "$SUBNET2_OUTPUT" $? "Failed to create subnet 2" SUBNET2_ID=$(echo "$SUBNET2_OUTPUT" | grep -o '"SubnetId": "[^"]*' | cut -d'"' -f4) SUBNET3_OUTPUT=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.3.0/24 --availability-zone $AZ3 --output json) check_error "$SUBNET3_OUTPUT" $? "Failed to create subnet 3" SUBNET3_ID=$(echo "$SUBNET3_OUTPUT" | grep -o '"SubnetId": "[^"]*' | cut -d'"' -f4) SUBNET_IDS="$SUBNET1_ID $SUBNET2_ID $SUBNET3_ID" echo "Created subnets: $SUBNET1_ID, $SUBNET2_ID, $SUBNET3_ID" | tee -a "$LOG_FILE" # Step 4: Create route table and add route to Internet Gateway echo "Creating route table..." | tee -a "$LOG_FILE" ROUTE_TABLE_OUTPUT=$(aws ec2 create-route-table --vpc-id $VPC_ID --output json) check_error "$ROUTE_TABLE_OUTPUT" $? "Failed to create route table" ROUTE_TABLE_ID=$(echo "$ROUTE_TABLE_OUTPUT" | grep -o '"RouteTableId": "[^"]*' | cut -d'"' -f4) echo "Route table created with ID: $ROUTE_TABLE_ID" | tee -a "$LOG_FILE" # Add route to Internet Gateway log_cmd "aws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID" # Associate route table with subnets log_cmd "aws ec2 associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET1_ID" log_cmd "aws ec2 associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET2_ID" log_cmd "aws ec2 associate-route-table --route-table-id $ROUTE_TABLE_ID --subnet-id $SUBNET3_ID" # Step 5: Create security group echo "Creating security group..." | tee -a "$LOG_FILE" SG_OUTPUT=$(aws ec2 create-security-group --group-name $SG_NAME --description "Security group for Neptune" --vpc-id $VPC_ID --output json) check_error "$SG_OUTPUT" $? "Failed to create security group" SECURITY_GROUP_ID=$(echo "$SG_OUTPUT" | grep -o '"GroupId": "[^"]*' | cut -d'"' -f4) echo "Security group created with ID: $SECURITY_GROUP_ID" | tee -a "$LOG_FILE" # Add inbound rule for Neptune port (8182) # Note: In production, you should restrict this to specific IP ranges echo "Adding security group rule for Neptune port 8182..." | tee -a "$LOG_FILE" log_cmd "aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 8182 --cidr 10.0.0.0/16" # Step 6: Create DB subnet group echo "Creating DB subnet group..." | tee -a "$LOG_FILE" DB_SUBNET_GROUP_OUTPUT=$(aws neptune create-db-subnet-group --db-subnet-group-name $DB_SUBNET_GROUP --db-subnet-group-description "Subnet group for Neptune" --subnet-ids $SUBNET1_ID $SUBNET2_ID $SUBNET3_ID --output json) check_error "$DB_SUBNET_GROUP_OUTPUT" $? "Failed to create DB subnet group" echo "DB subnet group created: $DB_SUBNET_GROUP" | tee -a "$LOG_FILE" # Step 7: Create Neptune DB cluster echo "Creating Neptune DB cluster..." | tee -a "$LOG_FILE" DB_CLUSTER_OUTPUT=$(aws neptune create-db-cluster --db-cluster-identifier $DB_CLUSTER_ID --engine neptune --vpc-security-group-ids $SECURITY_GROUP_ID --db-subnet-group-name $DB_SUBNET_GROUP --output json) check_error "$DB_CLUSTER_OUTPUT" $? "Failed to create Neptune DB cluster" echo "Neptune DB cluster created: $DB_CLUSTER_ID" | tee -a "$LOG_FILE" # Step 8: Create Neptune DB instance echo "Creating Neptune DB instance..." | tee -a "$LOG_FILE" DB_INSTANCE_OUTPUT=$(aws neptune create-db-instance --db-instance-identifier $DB_INSTANCE_ID --db-instance-class db.r5.large --engine neptune --db-cluster-identifier $DB_CLUSTER_ID --output json) check_error "$DB_INSTANCE_OUTPUT" $? "Failed to create Neptune DB instance" echo "Neptune DB instance created: $DB_INSTANCE_ID" | tee -a "$LOG_FILE" # Step 9: Wait for the DB instance to become available echo "Waiting for Neptune DB instance to become available..." | tee -a "$LOG_FILE" log_cmd "aws neptune wait db-instance-available --db-instance-identifier $DB_INSTANCE_ID" # Step 10: Get the Neptune endpoint echo "Getting Neptune endpoint..." | tee -a "$LOG_FILE" ENDPOINT_OUTPUT=$(aws neptune describe-db-clusters --db-cluster-identifier $DB_CLUSTER_ID --output json) check_error "$ENDPOINT_OUTPUT" $? "Failed to get Neptune endpoint" NEPTUNE_ENDPOINT=$(echo "$ENDPOINT_OUTPUT" | grep -o '"Endpoint": "[^"]*' | cut -d'"' -f4) echo "Neptune endpoint: $NEPTUNE_ENDPOINT" | tee -a "$LOG_FILE" # Step 11: Display information about how to connect to Neptune echo "" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" echo "NEPTUNE SETUP COMPLETE" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" echo "Neptune Endpoint: $NEPTUNE_ENDPOINT" | tee -a "$LOG_FILE" echo "Port: 8182" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" echo "To query your Neptune database using Gremlin, you can use curl:" | tee -a "$LOG_FILE" echo "curl -X POST -d '{\"gremlin\":\"g.V().limit(1)\"}' https://$NEPTUNE_ENDPOINT:8182/gremlin" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" echo "To add data to your graph:" | tee -a "$LOG_FILE" echo "curl -X POST -d '{\"gremlin\":\"g.addV(\\\"person\\\").property(\\\"name\\\", \\\"Howard\\\")\"}' https://$NEPTUNE_ENDPOINT:8182/gremlin" | tee -a "$LOG_FILE" echo "" | tee -a "$LOG_FILE" echo "Note: You may need to configure your client machine to access the Neptune instance within the VPC." | tee -a "$LOG_FILE" echo "For production use, consider using an EC2 instance in the same VPC or setting up a bastion host." | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" # Step 12: List all created resources echo "" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" echo "RESOURCES CREATED" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" echo "VPC: $VPC_ID" | tee -a "$LOG_FILE" echo "Internet Gateway: $IGW_ID" | tee -a "$LOG_FILE" echo "Subnets: $SUBNET1_ID, $SUBNET2_ID, $SUBNET3_ID" | tee -a "$LOG_FILE" echo "Route Table: $ROUTE_TABLE_ID" | tee -a "$LOG_FILE" echo "Security Group: $SECURITY_GROUP_ID" | tee -a "$LOG_FILE" echo "DB Subnet Group: $DB_SUBNET_GROUP" | tee -a "$LOG_FILE" echo "Neptune DB Cluster: $DB_CLUSTER_ID" | tee -a "$LOG_FILE" echo "Neptune DB Instance: $DB_INSTANCE_ID" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" # Step 13: Ask if user wants to clean up resources echo "" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" echo "CLEANUP CONFIRMATION" | tee -a "$LOG_FILE" echo "=============================================" | tee -a "$LOG_FILE" echo "Do you want to clean up all created resources? (y/n): " | tee -a "$LOG_FILE" read -r CLEANUP_CHOICE if [[ "$CLEANUP_CHOICE" =~ ^[Yy]$ ]]; then echo "Starting cleanup process..." | tee -a "$LOG_FILE" # Delete DB instance echo "Deleting DB instance $DB_INSTANCE_ID..." | tee -a "$LOG_FILE" log_cmd "aws neptune delete-db-instance --db-instance-identifier $DB_INSTANCE_ID --skip-final-snapshot" # Wait for DB instance to be deleted echo "Waiting for DB instance to be deleted..." | tee -a "$LOG_FILE" log_cmd "aws neptune wait db-instance-deleted --db-instance-identifier $DB_INSTANCE_ID" # Delete DB cluster echo "Deleting DB cluster $DB_CLUSTER_ID..." | tee -a "$LOG_FILE" log_cmd "aws neptune delete-db-cluster --db-cluster-identifier $DB_CLUSTER_ID --skip-final-snapshot" # Wait for DB cluster to be deleted (no specific wait command for this, so we'll sleep) echo "Waiting for DB cluster to be deleted..." | tee -a "$LOG_FILE" sleep 60 # Delete DB subnet group echo "Deleting DB subnet group $DB_SUBNET_GROUP..." | tee -a "$LOG_FILE" log_cmd "aws neptune delete-db-subnet-group --db-subnet-group-name $DB_SUBNET_GROUP" # Delete security group echo "Deleting security group $SECURITY_GROUP_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-security-group --group-id $SECURITY_GROUP_ID" # Detach and delete internet gateway echo "Detaching and deleting internet gateway $IGW_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID" log_cmd "aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID" # Delete subnets echo "Deleting subnets..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-subnet --subnet-id $SUBNET1_ID" log_cmd "aws ec2 delete-subnet --subnet-id $SUBNET2_ID" log_cmd "aws ec2 delete-subnet --subnet-id $SUBNET3_ID" # Delete route table echo "Deleting route table $ROUTE_TABLE_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-route-table --route-table-id $ROUTE_TABLE_ID" # Delete VPC echo "Deleting VPC $VPC_ID..." | tee -a "$LOG_FILE" log_cmd "aws ec2 delete-vpc --vpc-id $VPC_ID" echo "Cleanup complete!" | tee -a "$LOG_FILE" else echo "Resources will not be cleaned up. You can delete them manually later." | tee -a "$LOG_FILE" echo "See the list of resources above for reference." | tee -a "$LOG_FILE" fi echo "Script completed. See $LOG_FILE for details." | tee -a "$LOG_FILE"