{
  "Description": "Neptune Streams example",
  "Mappings": {
    "RegionMap": {
      "us-east-1": {
        "bucket": "aws-neptune-customer-samples-us-east-1"
      },
      "us-east-2": {
        "bucket": "aws-neptune-customer-samples-us-east-2"
      },
      "us-west-2": {
        "bucket": "aws-neptune-customer-samples-us-west-2"
      },
      "eu-west-1": {
        "bucket": "aws-neptune-customer-samples-eu-west-1"
      },
      "eu-west-2": {
        "bucket": "aws-neptune-customer-samples-eu-west-2"
      },
      "eu-central-1": {
        "bucket": "aws-neptune-customer-samples-eu-central-1"
      },
      "us-west-1": {
        "bucket": "aws-neptune-customer-samples-us-west-1"
      },
      "ap-southeast-2": {
        "bucket": "aws-neptune-customer-samples-ap-southeast-2"
      },
      "ap-southeast-1": {
        "bucket": "aws-neptune-customer-samples-ap-southeast-1"
      },
      "ap-south-1": {
        "bucket": "aws-neptune-customer-samples-ap-south-1"
      },
      "ap-northeast-1": {
        "bucket": "aws-neptune-customer-samples-ap-northeast-1"
      }
    },
    "CfnMap": {
      "config": {
        "cfnRoot": "https://s3.amazonaws.com/aws-neptune-customer-samples/neptune-sagemaker/cloudformation-templates",
        "notebookContent": "s3://aws-neptune-customer-samples/neptune-sagemaker/notebooks",
        "scripts": "s3://aws-neptune-customer-samples/neptune-sagemaker/scripts",
        "lambdaS3BucketPrefix": "aws-neptune-customer-samples",
        "lambdaS3KeyPrefix": "neptune-sagemaker/"
      }
    }
  },
  "Parameters": {
    "ApplicationID": {
      "Description": "Application ID",
      "Type": "String",
      "AllowedPattern": "[-a-z0-9]+",
      "MaxLength": 50
    }
  },
  "Resources": {
    "NetworkStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": [
            "${cfnRoot}/neptune-streams/network-stack.json",
            {
              "cfnRoot": {
                "Fn::FindInMap": [
                  "CfnMap",
                  "config",
                  "cfnRoot"
                ]
              }
            }
          ]
        },
        "Parameters": {
          "InfrastructureID": {
            "Ref": "AWS::StackName"
          }
        },
        "TimeoutInMinutes": "10",
        "Tags": [
          {
            "Key": "InfrastructureID",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "IAMStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": "NetworkStack",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": [
            "${cfnRoot}/neptune-streams/iam-stack.json",
            {
              "cfnRoot": {
                "Fn::FindInMap": [
                  "CfnMap",
                  "config",
                  "cfnRoot"
                ]
              }
            }
          ]
        },
        "Parameters": {
          "InfrastructureID": {
            "Ref": "AWS::StackName"
          },
          "LambdaS3BucketPrefix": {
            "Fn::FindInMap": [
              "RegionMap",
              {
                "Ref": "AWS::Region"
              },
              "bucket"
            ]
          }
        },
        "TimeoutInMinutes": "10",
        "Tags": [
          {
            "Key": "InfrastructureID",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "NeptuneStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": [
        "IAMStack"
      ],
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": [
            "${cfnRoot}/neptune-streams/services-neptune-stack.json",
            {
              "cfnRoot": {
                "Fn::FindInMap": [
                  "CfnMap",
                  "config",
                  "cfnRoot"
                ]
              }
            }
          ]
        },
        "Parameters": {
          "InfrastructureID": {
            "Ref": "AWS::StackName"
          },
          "ApplicationID": {
            "Ref": "ApplicationID"
          }
        },
        "TimeoutInMinutes": "20",
        "Tags": [
          {
            "Key": "InfrastructureID",
            "Value": {
              "Ref": "AWS::StackName"
            }
          },
          {
            "Key": "ApplicationID",
            "Value": {
              "Ref": "ApplicationID"
            }
          }
        ]
      }
    },
    "ElastiCacheStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": [
        "IAMStack"
      ],
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": [
            "${cfnRoot}/neptune-streams/services-elasticache-stack.json",
            {
              "cfnRoot": {
                "Fn::FindInMap": [
                  "CfnMap",
                  "config",
                  "cfnRoot"
                ]
              }
            }
          ]
        },
        "Parameters": {
          "InfrastructureID": {
            "Ref": "AWS::StackName"
          },
          "ApplicationID": {
            "Ref": "ApplicationID"
          }
        },
        "TimeoutInMinutes": "10",
        "Tags": [
          {
            "Key": "InfrastructureID",
            "Value": {
              "Ref": "AWS::StackName"
            }
          },
          {
            "Key": "ApplicationID",
            "Value": {
              "Ref": "ApplicationID"
            }
          }
        ]
      }
    },
    "NeptuneSagemakerNotebook": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": [
        "IAMStack",
        "NeptuneStack",
        "ElastiCacheStack"
      ],
      "Properties": {
        "TemplateURL": {
          "Fn::Join": [
            "",
            [
              "https://s3.amazonaws.com/aws-neptune-customer-samples/v2/cloudformation-templates/neptune-sagemaker-notebook-stack.json"
            ]
          ]
        },
        "TimeoutInMinutes": "30",
        "Parameters": {
          "Env": {
            "Fn::Join": [
              "",
              {
                "Fn::Split": [
                  "-",
                  {
                    "Ref": "ApplicationID"
                  }
                ]
              }
            ]
          },
          "NotebookInstanceType": "ml.t3.large",
          "NeptuneClusterEndpoint": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneDBClusterEndpoint"
            ]
          },
          "NeptuneClusterPort": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneDBClusterPort"
            ]
          },
          "NeptuneClusterVpc": {
            "Fn::GetAtt": [
              "NetworkStack",
              "Outputs.VPC"
            ]
          },
          "NeptuneClusterSubnetId": {
            "Fn::GetAtt": [
              "NetworkStack",
              "Outputs.PublicSubnet1"
            ]
          },
          "NeptuneClientSecurityGroup": {
            "Fn::GetAtt": [
              "NetworkStack",
              "Outputs.NeptuneAndElastiCacheClientSecurityGroup"
            ]
          },
          "NeptuneLoadFromS3RoleArn": {
            "Fn::GetAtt": [
              "IAMStack",
              "Outputs.NeptuneLoadFromS3RoleARN"
            ]
          },
          "StartupScript": {
            "Fn::Join": [
              "",
              [
                "/home/ec2-user/anaconda3/bin/python3 -m  pip install --target /home/ec2-user/anaconda3/envs/JupyterSystemEnv/lib/python3.7/site-packages/ ipython_unittest\n",
                "/home/ec2-user/anaconda3/bin/python3 -m  pip install --target /home/ec2-user/anaconda3/envs/JupyterSystemEnv/lib/python3.7/site-packages/ redis\n",
                "echo 'export ELASTICACHE_ENDPOINT=",
                {
                  "Fn::GetAtt": [
                    "ElastiCacheStack",
                    "Outputs.ElastiCacheEndpoint"
                  ]
                },
                "' >> /home/ec2-user/.bashrc\n",
                "aws s3 cp s3://",
                {
                  "Fn::FindInMap": [
                    "RegionMap",
                    {
                      "Ref": "AWS::Region"
                    },
                    "bucket"
                  ]
                },
                "/neptune-sagemaker/bin/neptune-python-utils-v2/neptune_python_utils.zip /home/ec2-user/anaconda3/envs/JupyterSystemEnv/lib/python3.7/site-packages/\n",
                "unzip -n /home/ec2-user/anaconda3/envs/JupyterSystemEnv/lib/python3.7/site-packages/neptune_python_utils.zip -d /home/ec2-user/anaconda3/envs/JupyterSystemEnv/lib/python3.7/site-packages/\n",
                "echo 'export NEPTUNE_CLUSTER_ENDPOINT=",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterEndpoint"
                  ]
                },
                "' >> ~/.bashrc\n",
                "echo 'export NEPTUNE_CLUSTER_PORT=",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterPort"
                  ]
                },
                "' >> ~/.bashrc\n",
                "echo 'export NEPTUNE_LOAD_FROM_S3_ROLE_ARN=",
                {
                  "Fn::GetAtt": [
                    "IAMStack",
                    "Outputs.NeptuneLoadFromS3RoleARN"
                  ]
                },
                "' >> ~/.bashrc\n",
                "echo 'export AWS_REGION=",
                {
                  "Ref": "AWS::Region"
                },
                "' >> ~/.bashrc\n",
                "sed -i '$d' /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "sed -i '$d' /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo ' \"language\": \"python\",' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo ' \"env\": {' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo '  \"NEPTUNE_CLUSTER_ENDPOINT\": \"",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterEndpoint"
                  ]
                },
                "\",' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo '  \"NEPTUNE_CLUSTER_PORT\": \"",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterPort"
                  ]
                },
                "\",' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo '  \"NEPTUNE_LOAD_FROM_S3_ROLE_ARN\": \"",
                {
                  "Fn::GetAtt": [
                    "IAMStack",
                    "Outputs.NeptuneLoadFromS3RoleARN"
                  ]
                },
                "\",' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo '  \"ELASTICACHE_ENDPOINT\": \"",
                {
                  "Fn::GetAtt": [
                    "ElastiCacheStack",
                    "Outputs.ElastiCacheEndpoint"
                  ]
                },
                "\",' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo '  \"AWS_REGION\": \"",
                {
                  "Ref": "AWS::Region"
                },
                "\"' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo ' }' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "echo '}' >> /home/ec2-user/anaconda3/envs/JupyterSystemEnv/share/jupyter/kernels/python3/kernel.json\n",
                "aws s3 cp ",
                {
                  "Fn::Sub": [
                    "${notebookContent}/neptune-streams/",
                    {
                      "notebookContent": {
                        "Fn::FindInMap": [
                          "CfnMap",
                          "config",
                          "notebookContent"
                        ]
                      }
                    }
                  ]
                },
                " /home/ec2-user/SageMaker/Neptune/neptune-streams/ --recursive\n"
              ]
            ]
          },
          "DBClusterId": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneDBClusterID"
            ]
          },
          "NeptuneClusterResourceId": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneDBClusterResourceID"
            ]
          },
          "EnableIamAuthOnNeptune": "false",
          "CustomPolicyArn": {
            "Fn::GetAtt": [
              "IAMStack",
              "Outputs.SageMakerCustomPolicyARN"
            ]
          }
        }
      }
    },
    "NeptuneWorkloadLambdaStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": [
        "NeptuneStack",
        "ElastiCacheStack",
        "IAMStack"
      ],
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": [
            "${cfnRoot}/neptune-streams/services-lambda-stack.json",
            {
              "cfnRoot": {
                "Fn::FindInMap": [
                  "CfnMap",
                  "config",
                  "cfnRoot"
                ]
              }
            }
          ]
        },
        "Parameters": {
          "InfrastructureID": {
            "Ref": "AWS::StackName"
          },
          "ApplicationID": {
            "Ref": "ApplicationID"
          },
          "LambdaS3BucketPrefix": {
            "Fn::FindInMap": [
              "RegionMap",
              {
                "Ref": "AWS::Region"
              },
              "bucket"
            ]
          },
          "LambdaS3KeyPrefix": {
            "Fn::FindInMap": [
              "CfnMap",
              "config",
              "lambdaS3KeyPrefix"
            ]
          }
        },
        "TimeoutInMinutes": "10",
        "Tags": [
          {
            "Key": "InfrastructureID",
            "Value": {
              "Ref": "AWS::StackName"
            }
          },
          {
            "Key": "ApplicationID",
            "Value": {
              "Ref": "ApplicationID"
            }
          }
        ]
      }
    },
    "NeptuneStreamsStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": [
        "NeptuneStack",
        "ElastiCacheStack"
      ],
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/aws-neptune-customer-samples/neptune-stream/neptune_stream_poller_nested_full_stack.json",
        "Parameters": {
          "ApplicationName": {
            "Ref": "ApplicationID"
          },
          "AdditionalParams": {
            "Fn::Join": [
              "",
              [
                "{\"elasticache_endpoint\":\"",
                {
                  "Fn::GetAtt": [
                    "ElastiCacheStack",
                    "Outputs.ElastiCacheEndpoint"
                  ]
                },
                "\", \"neptune_endpoint\":\"",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterEndpoint"
                  ]
                },
                "\"}"
              ]
            ]
          },
          "LambdaMemorySize": 2048,
          "StreamRecordsHandler": "neptune_stream_handler.NeptuneStreamHandler",
          "NeptuneStreamEndpoint": {
            "Fn::Join": [
              "",
              [
                "https://",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterEndpoint"
                  ]
                },
                ":",
                {
                  "Fn::GetAtt": [
                    "NeptuneStack",
                    "Outputs.NeptuneDBClusterPort"
                  ]
                },
                "/gremlin/stream"
              ]
            ]
          },
          "VPC": {
            "Fn::GetAtt": [
              "NetworkStack",
              "Outputs.VPC"
            ]
          },
          "SubnetIds": {
            "Fn::GetAtt": [
              "NetworkStack",
              "Outputs.PrivateSubnetIDs"
            ]
          },
          "SecurityGroupIds": {
            "Fn::Join": [
              ",",
              [
                {
                  "Fn::GetAtt": [
                    "NetworkStack",
                    "Outputs.DefaultSecurityGroup"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "NetworkStack",
                    "Outputs.NeptuneAndElastiCacheClientSecurityGroup"
                  ]
                }
              ]
            ]
          },
          "RouteTableIds": {
            "Fn::GetAtt": [
              "NetworkStack",
              "Outputs.PrivateRouteTableIDs"
            ]
          },
          "CreateCloudWatchAlarm": "false",
          "LambdaS3Bucket": {
            "Fn::Sub": [
              "${bucket_name}",
              {
                "bucket_name": {
                  "Fn::FindInMap": [
                    "RegionMap",
                    {
                      "Ref": "AWS::Region"
                    },
                    "bucket"
                  ]
                }
              }
            ]
          },
          "LambdaS3Key": {
            "Fn::Sub": [
              "${lambdaS3KeyPrefix}lambda/neptune-streams/neptune_streams_demo.zip",
              {
                "lambdaS3KeyPrefix": {
                  "Fn::FindInMap": [
                    "CfnMap",
                    "config",
                    "lambdaS3KeyPrefix"
                  ]
                }
              }
            ]
          },
          "MaxPollingWaitTime": 5,
          "StepFunctionFallbackPeriod": 1,
          "StepFunctionFallbackPeriodUnit": "minute"
        },
        "TimeoutInMinutes": "20",
        "Tags": [
          {
            "Key": "InfrastructureID",
            "Value": {
              "Ref": "AWS::StackName"
            }
          },
          {
            "Key": "ApplicationID",
            "Value": {
              "Ref": "ApplicationID"
            }
          }
        ]
      }
    }
  },
  "Outputs": {
    "SageMakerNotebook": {
      "Description": "SageMaker notebook",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneSagemakerNotebook",
          "Outputs.NeptuneSagemakerNotebook"
        ]
      }
    },
    "StartWorkload": {
      "Description": "Start workload CLI command",
      "Value": {
        "Fn::Join": [
          "",
          [
            "aws lambda invoke --function-name ",
            {
              "Fn::GetAtt": [
                "NeptuneWorkloadLambdaStack",
                "Outputs.NeptuneWorkloadManagerLambdaArn"
              ]
            },
            " --payload '{\"operation\": \"start\"}' --cli-binary-format raw-in-base64-out --region ",
            {
              "Ref": "AWS::Region"
            },
            " /dev/stdout 1>/dev/null"
          ]
        ]
      }
    },
    "StopWorkload": {
      "Description": "Start workload CLI command",
      "Value": {
        "Fn::Join": [
          "",
          [
            "aws lambda invoke --function-name ",
            {
              "Fn::GetAtt": [
                "NeptuneWorkloadLambdaStack",
                "Outputs.NeptuneWorkloadManagerLambdaArn"
              ]
            },
            " --payload '{\"operation\": \"stop\"}' --cli-binary-format raw-in-base64-out --region ",
            {
              "Ref": "AWS::Region"
            },
            " /dev/stdout 1>/dev/null"
          ]
        ]
      }
    }
  }
}