{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "A sample template to replicate data from source Neptune Cluster to target Elastic Search Cluster using Neptune Stream",
  "Metadata": {
    "AWS::CloudFormation::Interface": {
      "ParameterGroups": [
        {
          "Label": {
            "default": "Network Configuration"
          },
          "Parameters": [
            "VPC",
            "SubnetIds",
            "SecurityGroupIds",
            "RouteTableIds",
            "CreateDDBVPCEndPoint",
            "CreateMonitoringEndPoint"
          ]
        },
        {
          "Label": {
            "default": "Stream Poller"
          },
          "Parameters": [
            "ApplicationName",
            "LambdaMemorySize",
            "LambdaRuntime",
            "LambdaS3Bucket",
            "LambdaS3Key",
            "LambdaLoggingLevel",
            "ManagedPolicies",
            "StreamRecordsHandler",
            "StreamRecordsBatchSize",
            "MaxPollingWaitTime",
            "MaxPollingInterval",
            "StepFunctionFallbackPeriod",
            "StepFunctionFallbackPeriodUnit",
            "CreateExplicitMappings"
          ]
        },
        {
          "Label": {
            "default": "Neptune Stream"
          },
          "Parameters": [
            "NeptuneStreamEndpoint",
            "QueryEngine",
            "IAMAuthEnabledOnSourceStream",
            "StreamDBClusterResourceId"
          ]
        },
        {
          "Label": {
            "default": "Target Elastic Search Cluster"
          },
          "Parameters": [
            "ElasticSearchEndpoint",
            "NumberOfShards",
            "NumberOfReplica",
            "GeoLocationFields",
            "PropertiesToExclude",
            "DatatypesToExclude",
            "ReplicationScope",
            "IgnoreMissingDocument",
            "EnableNonStringIndexing"
          ]
        },
        {
          "Label": {
            "default": "Alarm"
          },
          "Parameters": [
            "CreateCloudWatchAlarm",
            "NotificationSNSTopicArn",
            "NotificationEmail"
          ]
        }
      ],
      "ParameterLabels": {
        "ApplicationName": {
          "default": "Application Name"
        },
        "LambdaMemorySize": {
          "default": "Memory size for Lambda Poller"
        },
        "LambdaRuntime": {
          "default": "Lambda Runtime"
        },
        "LambdaS3Bucket": {
          "default": "S3 Bucket having Lambda code artifacts"
        },
        "LambdaLoggingLevel": {
          "default": "Logging level for Lambda"
        },
        "LambdaS3Key": {
          "default": "S3 Key corresponding to Lambda Code artifacts"
        },
        "ManagedPolicies": {
          "default": "Managed Policies for Lambda Execution"
        },
        "StreamRecordsHandler": {
          "default": "Stream Records Handler"
        },
        "StreamRecordsBatchSize": {
          "default": "Maximum records Fetched from Stream"
        },
        "StepFunctionFallbackPeriod": {
          "default": "Step Function Fallback Period"
        },
        "StepFunctionFallbackPeriodUnit": {
          "default": "Step Function Fallback Period Unit"
        },
        "MaxPollingWaitTime": {
          "default": "Max wait time between two Polls (in Seconds)"
        },
        "NeptuneStreamEndpoint": {
          "default": "Endpoint of source Neptune Stream"
        },
        "QueryEngine": {
          "default": "Neptune Query Engine"
        },
        "IAMAuthEnabledOnSourceStream": {
          "default": "Is IAM Auth Enabled?"
        },
        "StreamDBClusterResourceId": {
          "default": "Neptune Cluster Resource Id"
        },
        "MaxPollingInterval": {
          "default": "Maximum Continuous polling period (in Seconds)"
        },
        "NotificationSNSTopicArn": {
          "default": "SNS Topic ARN for Alarm Notifications"
        },
        "NotificationEmail": {
          "default": "Email for Cloudwatch Alarm Notifications"
        },
        "VPC": {
          "default": "VPC"
        },
        "ElasticSearchEndpoint": {
          "default": "Endpoint for Elastic Search Service"
        },
        "NumberOfShards": {
          "default": "Number of Shards for Elastic Search Index"
        },
        "NumberOfReplica": {
          "default": "Number of Replicas for Elastic Search Index"
        },
        "GeoLocationFields": {
          "default": "Geo Location Fields for Mapping"
        },
        "PropertiesToExclude": {
          "default": "Properties to exclude from being inserted into Elastic Search Index"
        },
        "DatatypesToExclude": {
          "default": "Datatypes to exclude from being inserted into Elastic Search Index"
        },
        "EnableNonStringIndexing": {
          "default": "Enable/disable indexing non-string fields"
        },
        "CreateExplicitMappings": {
          "default": "Enable/disable creation of Elastic Search Mappings by Lambda"
        },
        "ReplicationScope": {
          "default": "Data replication scope"
        },
        "IgnoreMissingDocument": {
          "default": "Ignore Elastic Search missing document error"
        },
        "RouteTableIds": {
          "default": "List of Route Table Ids"
        },
        "CreateDDBVPCEndPoint": {
          "default": "Require to create Dynamo DB VPC Endpoint"
        },
        "CreateMonitoringEndPoint": {
          "default": "Require to create Monitoring VPC Endpoint"
        },
        "CreateCloudWatchAlarm": {
          "default": "Require to create Cloud watch Alarm"
        },
        "SubnetIds": {
          "default": "List of Subnet Ids"
        },
        "SecurityGroupIds": {
          "default": "List of Security Group Ids"
        }
      }
    }
  },
  "Parameters": {
    "ApplicationName": {
      "Type": "String",
      "Default": "NeptuneStream",
      "Description": "Application Name used as a reference to create resources"
    },
    "LambdaMemorySize": {
      "Type": "Number",
      "Default": 2048,
      "AllowedValues": [
        128,
        256,
        512,
        1024,
        2048,
        3008
      ],
      "Description": "Poller Lambda  memory size (in MB). Should be one of 128 MB, 256 MB, 512 MB, 1024 MB, 2048 MB."
    },
    "LambdaRuntime": {
      "Type": "String",
      "Description": "Lambda Runtime",
      "Default": "python3.12",
      "AllowedValues": [
        "python3.12"
      ]
    },
    "LambdaS3Bucket": {
      "Type": "String",
      "Default": "",
      "Description": "S3 bucket having Lambda Artifact. Optional Parameter - If left blank artifact will be picked from default Bucket."
    },
    "LambdaS3Key": {
      "Type": "String",
      "Default": "",
      "Description": "S3 key for Lambda Artifact. Optional Parameter - If left blank default Lambda Artifact is used."
    },
    "LambdaLoggingLevel": {
      "Type": "String",
      "Default": "INFO",
      "AllowedValues": [
        "DEBUG",
        "INFO",
        "WARN",
        "ERROR",
        "FATAL"
      ],
      "Description": "Poller Lambda logging level."
    },
    "ManagedPolicies": {
      "Type": "CommaDelimitedList",
      "Default": "",
      "Description": "Comma-delimited list of ARNs of managed policies to be attached to Lambda execution role. Optional Parameter - If left blank policy with required access is created. "
    },
    "StreamRecordsHandler": {
      "Type": "String",
      "Default": "",
      "Description": "Handler for processing stream records. Optional Parameter - If left blank default Handler for Elastic Search is used."
    },
    "StreamRecordsBatchSize": {
      "Type": "Number",
      "Default": 5000,
      "MaxValue": 50000,
      "MinValue": 1,
      "Description": "Number of records to be read from stream in each batch. Should be between 1 to 50000."
    },
    "MaxPollingWaitTime": {
      "Type": "Number",
      "Default": 60,
      "MaxValue": 3600,
      "MinValue": 0,
      "Description": "Maximum wait time in seconds between two successive polling from stream. Set value to 0 sec for continuous polling. Maximum value can be 3600 sec (1 hour)."
    },
    "MaxPollingInterval": {
      "Type": "Number",
      "Default": 600,
      "MaxValue": 900,
      "MinValue": 5,
      "Description": "Period for which we can continuously poll stream for records on one Lambda instance. Should be between 5 sec to 900 sec. This parameter is used to set Poller Lambda Timeout."
    },
    "NeptuneStreamEndpoint": {
      "Type": "String",
      "AllowedPattern": "^(.+)$",
      "ConstraintDescription": "Must be a valid stream endpoint",
      "Description": "Endpoint for source Neptune Stream. This is of the form https://<cluster>:<port>/propertygraph/stream or https://<cluster>:<port>/sparql/stream."
    },
    "QueryEngine": {
      "Type": "String",
      "Default": "Gremlin",
      "AllowedValues": [
        "Gremlin",
        "Sparql"
      ],
      "ConstraintDescription": "Must be a either Gremlin or Sparql",
      "Description": "Neptune Query Engine."
    },
    "IAMAuthEnabledOnSourceStream": {
      "Type": "String",
      "Default": "false",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be a either true or false",
      "Description": "Flag to determine if IAM Auth is Enabled for Source Neptune Cluster or not."
    },
    "StreamDBClusterResourceId": {
      "Type": "String",
      "Default": "",
      "Description": "Neptune DB Cluster Resource Id. Ex: cluster-5DSWZGISGVCHJPHOV5MK7QF2PY. Optional Parameter- Only needed when IAM Auth is Enabled."
    },
    "StepFunctionFallbackPeriod": {
      "Type": "Number",
      "Default": 5,
      "Description": "Period after which Step function is invoked using Cloud Watch Events to recover from failure. Unit for Step Function Fallback period is set separately."
    },
    "StepFunctionFallbackPeriodUnit": {
      "Type": "String",
      "Default": "minutes",
      "AllowedValues": [
        "minutes",
        "minute",
        "hours",
        "hour",
        "days",
        "day"
      ],
      "Description": "Step Function FallbackPeriod unit. Should be one of minutes, minute, hours, hour, days, day"
    },
    "NotificationSNSTopicArn": {
      "Type": "String",
      "Description": "SNS Topic ARN where CloudWatch Alarm Notifications would be sent. Eg. arn:aws:sns:<region>:<account-id>:<name>. Optional."
    },
    "NotificationEmail": {
      "Type": "String",
      "Description": "Email Address for CloudWatch Alarm Notification. Optional Parameter - Only needed when selecting option to create CloudWatch Alarm."
    },
    "VPC": {
      "Type": "AWS::EC2::VPC::Id",
      "Description": "The VPC in which Neptune Stream Instance is present",
      "ConstraintDescription": "Must be the id (for example, vpc-123a351e) of an existing VPC."
    },
    "SubnetIds": {
      "Type": "List<AWS::EC2::Subnet::Id>",
      "Description": "The subnets to which a network interface is established. Add subnets associated with both Neptune Stream Cluster & Neptune target Cluster.",
      "ConstraintDescription": "Must be the subnet id (for example, subnet-123a351e)."
    },
    "SecurityGroupIds": {
      "Type": "List<AWS::EC2::SecurityGroup::Id>",
      "Description": "The Security groups associated with the Neptune Stream Cluster and Neptune Target Cluster.",
      "ConstraintDescription": "Must be a security group ID (for example, sg-a123fd85)."
    },
    "RouteTableIds": {
      "Type": "String",
      "Default": "",
      "Description": "Comma Delimited list of Route table ids associated with the Subnets. For Example: rtb-a12345,rtba7863k1. Optional parameter - Only needed when creating DynamoDB VPC Endpoint."
    },
    "CreateDDBVPCEndPoint": {
      "Type": "String",
      "Default": "true",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be a either true or false",
      "Description": "Flag used to determine whether to create Dynamo DB VPC Endpoint or not. Select false only if Dynamo DB VPC endpoint already present."
    },
    "CreateMonitoringEndPoint": {
      "Type": "String",
      "Default": "true",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be a either true or false",
      "Description": "Flag used to determine whether to create Monitoring VPC Endpoint or not. Select false only if Monitoring VPC endpoint already present."
    },
    "CreateCloudWatchAlarm": {
      "Type": "String",
      "Default": "false",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be a either true or false",
      "Description": "Flag used to determine whether to create Cloud watch alarm or not."
    },
    "ElasticSearchEndpoint": {
      "Type": "String",
      "AllowedPattern": "^(.+)$",
      "ConstraintDescription": "Value cannot be blank. Must be a valid cluster Endpoint",
      "Description": "Elastic Search Cluster Endpoint. Ex : vpc-neptunestream.us-east-1.es.amazonaws.com"
    },
    "NumberOfShards": {
      "Type": "Number",
      "Default": 5,
      "Description": "Number of Shards for Elastic Search Index. Default value is 5."
    },
    "NumberOfReplica": {
      "Type": "Number",
      "Default": 1,
      "Description": "Number of replicas for Elastic Search Index. Default value is 1."
    },
    "GeoLocationFields": {
      "Type": "String",
      "Description": "Comma Delimited list of Property Keys to be mapped to Geo Point Type in Elastic Search. For Example: location,area. Currently, for a field to be mapped to Geo Point type, value should be in the format 'latitude,longitude' Ex: '41.33,-11.69'"
    },
    "PropertiesToExclude": {
      "Type": "String",
      "Description": "Comma delimited list of Property Keys to exclude from being indexed into Elastic Search. Optional Parameter - If left blank, all property keys will be indexed."
    },
    "DatatypesToExclude": {
      "Type": "String",
      "Description": "Comma delimited list of Property Value Data Types to exclude from being indexed into Elastic Search. Optional Parameter - If left blank, all valid property values will be indexed. Type inputs that are unsupported for the specified query language will be ignored. Valid inputs for Sparql/RDF data: [string, boolean, float, double, dateTime, byte, int, long, short, date, decimal, integer, nonNegativeInteger, nonPositiveInteger, negativeInteger, unsignedByte, unsignedInt, unsignedLong, unsignedShort, time]. Valid inputs for Gremlin data: [string, date, bool, byte, short, int, long, float, double]"
    },
    "EnableNonStringIndexing": {
      "Type": "String",
      "Default": "true",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be either true or false",
      "Description": "Flag to enable/disable indexing Non-String fields"
    },
    "CreateExplicitMappings": {
      "Type": "String",
      "Default": "true",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be either true or false",
      "Description": "Flag to enable/disable creation of Elastic Search Mappings by Lambda"
    },
    "ReplicationScope": {
      "Type": "String",
      "Default": "All",
      "AllowedValues": [
        "All",
        "Nodes"
      ],
      "ConstraintDescription": "Must be All or Only Nodes",
      "Description": "Determines whether to replicate both nodes and edges, or only nodes (Gremlin engine only)."
    },
    "IgnoreMissingDocument": {
      "Type": "String",
      "Default": "true",
      "AllowedValues": [
        "true",
        "false"
      ],
      "ConstraintDescription": "Must be a either true or false",
      "Description": "Flag to determine if missing document error in Elastic Search can be ignored. Missing document error can occur rarely but will need manual intervention if not ignored."
    },
    "StreamPollerInitialState": {
      "Type": "String",
      "Default": "ENABLED",
      "AllowedValues": [
        "DISABLED",
        "ENABLED"
      ],
      "ConstraintDescription": "Must be a either DISABLED or ENABLED",
      "Description": "Initial state of poller."
    },
    "StartingCheckpoint": {
      "Type": "String",
      "Default": "0:0",
      "Description": "Starting checkpoint for stream poller."
    }
  },
  "Conditions": {
    "CreateManagedPolicy": {
      "Fn::Equals": [
        {
          "Fn::Join": [
            ",",
            {
              "Ref": "ManagedPolicies"
            }
          ]
        },
        ""
      ]
    },
    "IsEmptyLambdaS3Bucket": {
      "Fn::Equals": [
        {
          "Ref": "LambdaS3Bucket"
        },
        ""
      ]
    },
    "IsEmptyLambdaS3Key": {
      "Fn::Equals": [
        {
          "Ref": "LambdaS3Key"
        },
        ""
      ]
    },
    "IsEmptyStreamRecordsHandler": {
      "Fn::Equals": [
        {
          "Ref": "StreamRecordsHandler"
        },
        ""
      ]
    },
    "CreateCloudWatchAlarmCondition": {
      "Fn::Equals": [
        {
          "Ref": "CreateCloudWatchAlarm"
        },
        "true"
      ]
    }
  },
  "Rules": {
    "ValidStreamClusterIdForIAMAuth": {
      "RuleCondition": {
        "Fn::Equals": [
          {
            "Ref": "IAMAuthEnabledOnSourceStream"
          },
          "true"
        ]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": [
              {
                "Fn::Equals": [
                  "",
                  {
                    "Ref": "StreamDBClusterResourceId"
                  }
                ]
              }
            ]
          },
          "AssertDescription": "Enter valid value for Cluster Resource Id to connect using IAMAuth."
        }
      ]
    },
    "DDBVPCEndpointRouteTableIdsCheck": {
      "RuleCondition": {
        "Fn::Equals": [
          {
            "Ref": "CreateDDBVPCEndPoint"
          },
          "true"
        ]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": [
              {
                "Fn::Equals": [
                  "",
                  {
                    "Ref": "RouteTableIds"
                  }
                ]
              }
            ]
          },
          "AssertDescription": "Enter valid Route Table Id when creating DynamoDB VPC Endpoint."
        }
      ]
    },
    "SubnetsInVPC": {
      "Assertions": [
        {
          "Assert": {
            "Fn::EachMemberIn": [
              {
                "Fn::ValueOfAll": [
                  "AWS::EC2::Subnet::Id",
                  "VpcId"
                ]
              },
              {
                "Fn::RefAll": "AWS::EC2::VPC::Id"
              }
            ]
          },
          "AssertDescription": "All subnets must in the VPC"
        }
      ]
    }
  },
  "Mappings": {
    "RuntimeMap": {
      "python3.12": {
        "keyname": "python312/release_2026_03_31"
      }
    },
    "Gremlin": {
      "python3.12" : {
        "true": "neptune_to_es.neptune_gremlin_es_handler.ElasticSearchGremlinHandler",
        "false": "neptune_to_es.neptune_gremlin_es_string_indexing_handler.ElasticSearchStringOnlyGremlinHandler"
      }
    },
    "Sparql": {
      "python3.12" : {
        "true": "neptune_to_es.neptune_sparql_es_handler.ElasticSearchSparqlHandler",
        "false": "neptune_to_es.neptune_sparql_es_string_indexing_handler.ElasticSearchStringOnlySparqlHandler"
      }
    },
    "ReplicationScopeMap": {
      "All": {
        "keyname": "all"
      },
      "Nodes": {
        "keyname": "nodes"
      }
    },
    "RegionalS3BucketMap": {
      "us-east-1": {
        "SamplesBucket": "aws-neptune-customer-samples-us-east-1"
      },
      "us-east-2": {
        "SamplesBucket": "aws-neptune-customer-samples-us-east-2"
      },
      "us-west-1": {
        "SamplesBucket": "aws-neptune-customer-samples-us-west-1"
      },
      "us-west-2": {
        "SamplesBucket": "aws-neptune-customer-samples-us-west-2"
      },
      "ca-central-1": {
        "SamplesBucket": "aws-neptune-customer-samples-ca-central-1"
      },
      "sa-east-1": {
        "SamplesBucket": "aws-neptune-customer-samples-sa-east-1"
      },
      "eu-north-1": {
        "SamplesBucket": "aws-neptune-customer-samples-eu-north-1"
      },
      "eu-west-1": {
        "SamplesBucket": "aws-neptune-customer-samples-eu-west-1"
      },
      "eu-west-2": {
        "SamplesBucket": "aws-neptune-customer-samples-eu-west-2"
      },
      "eu-west-3": {
        "SamplesBucket": "aws-neptune-customer-samples-eu-west-3"
      },
      "eu-central-1": {
        "SamplesBucket": "aws-neptune-customer-samples-eu-central-1"
      },
      "me-central-1": {
        "SamplesBucket": "aws-neptune-customer-samples-me-central-1"
      },
      "me-south-1": {
        "SamplesBucket": "aws-neptune-customer-samples-me-south-1"
      },
      "il-central-1": {
        "SamplesBucket": "aws-neptune-customer-samples-il-central-1"
      },
      "af-south-1": {
        "SamplesBucket": "aws-neptune-customer-samples-af-south-1"
      },
      "ap-east-1": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-east-1"
      },
      "ap-northeast-1": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-northeast-1"
      },
      "ap-northeast-2": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-northeast-2"
      },
      "ap-northeast-3": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-northeast-3"
      },
      "ap-southeast-1": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-southeast-1"
      },
      "ap-southeast-2": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-southeast-2"
      },
      "ap-southeast-3": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-southeast-3"
      },
      "ap-south-1": {
        "SamplesBucket": "aws-neptune-customer-samples-ap-south-1"
      },
      "cn-north-1": {
        "SamplesBucket": "aws-neptune-customer-samples-cn-north-1"
      },
      "cn-northwest-1": {
        "SamplesBucket": "aws-neptune-customer-samples-cn-northwest-1"
      },
      "us-gov-west-1": {
        "SamplesBucket": "aws-neptune-customer-samples-us-gov-west-1"
      },
      "us-gov-east-1": {
        "SamplesBucket": "aws-neptune-customer-samples-us-gov-east-1"
      }
    }
  },
  "Resources": {
    "ManagedPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Condition": "CreateManagedPolicy",
      "Properties": {
        "Description": "Policy for Elastic Search Access for Neptune Lambda Poller",
        "Path": "/",
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Action": [
                "es:ESHttpDelete",
                "es:ESHttpGet",
                "es:ESHttpHead",
                "es:ESHttpPost",
                "es:ESHttpPut"
              ],
              "Effect": "Allow",
              "Resource": [
                {
                  "Fn::Sub": "arn:${AWS::Partition}:es:${AWS::Region}:${AWS::AccountId}:domain/*"
                }
              ]
            },
            {
              "Action": [
                "aoss:APIAccessAll"
              ],
              "Effect": "Allow",
              "Resource": [
                {
                  "Fn::Sub": "arn:${AWS::Partition}:aoss:${AWS::Region}:${AWS::AccountId}:collection/*"
                }
              ]
            }
          ]
        }
      }
    },
    "NeptuneStreamPoller": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "Parameters": {
          "AdditionalParams": {
            "Fn::Sub": [
              "{ \"ElasticSearchEndpoint\": \"${ElasticSearchEndpoint}\", \"NumberOfShards\": \"${NumberOfShards}\", \"NumberOfReplica\": \"${NumberOfReplica}\", \"IgnoreMissingDocument\": \"${IgnoreMissingDocument}\", \"ReplicationScope\": \"${ReplicationScope}\", \"GeoLocationFields\": \"${GeoLocationFields}\", \"DatatypesToExclude\": \"${DatatypesToExclude}\", \"PropertiesToExclude\": \"${PropertiesToExclude}\", \"EnableNonStringIndexing\": \"${EnableNonStringIndexing}\", \"CreateExplicitMappings\": \"${CreateExplicitMappings}\"}",
              {
                "ElasticSearchEndpoint": {
                  "Ref": "ElasticSearchEndpoint"
                },
                "NumberOfShards": {
                  "Ref": "NumberOfShards"
                },
                "NumberOfReplica": {
                  "Ref": "NumberOfReplica"
                },
                "GeoLocationFields": {
                  "Ref": "GeoLocationFields"
                },
                "PropertiesToExclude": {
                  "Ref": "PropertiesToExclude"
                },
                "DatatypesToExclude": {
                  "Ref": "DatatypesToExclude"
                },
                "IgnoreMissingDocument": {
                  "Ref": "IgnoreMissingDocument"
                },
                "ReplicationScope": {
                  "Fn::FindInMap": [
                    "ReplicationScopeMap",
                    {
                      "Ref": "ReplicationScope"
                    },
                    "keyname"
                  ]
                },
                "EnableNonStringIndexing": {
                  "Ref": "EnableNonStringIndexing"
                },
                "CreateExplicitMappings": {
                  "Ref": "CreateExplicitMappings"
                }
              }
            ]
          },
          "ApplicationName": {
            "Ref": "ApplicationName"
          },
          "LambdaMemorySize": {
            "Ref": "LambdaMemorySize"
          },
          "LambdaRuntime": {
            "Ref": "LambdaRuntime"
          },
          "LambdaS3Bucket": {
            "Fn::If": [
              "IsEmptyLambdaS3Bucket",
              {
                "Fn::FindInMap": [
                  "RegionalS3BucketMap",
                  {
                    "Ref": "AWS::Region"
                  },
                  "SamplesBucket"
                ]
              },
              {
                "Ref": "LambdaS3Bucket"
              }
            ]
          },
          "LambdaS3Key": {
            "Fn::If": [
              "IsEmptyLambdaS3Key",
              {
                "Fn::Join": [
                  "/",
                  [
                    "neptune-stream",
                    "lambda",
                    {
                      "Fn::FindInMap": [
                        "RuntimeMap",
                        {
                          "Ref": "LambdaRuntime"
                        },
                        "keyname"
                      ]
                    },
                    "neptune-to-es.zip"
                  ]
                ]
              },
              {
                "Ref": "LambdaS3Key"
              }
            ]
          },
          "ManagedPolicies": {
            "Fn::If": [
              "CreateManagedPolicy",
              {
                "Ref": "ManagedPolicy"
              },
              {
                "Fn::Join": [
                  ",",
                  {
                    "Ref": "ManagedPolicies"
                  }
                ]
              }
            ]
          },
          "LambdaLoggingLevel": {
            "Ref": "LambdaLoggingLevel"
          },
          "StreamRecordsHandler": {
            "Fn::If": [
              "IsEmptyStreamRecordsHandler",
              {
                "Fn::FindInMap": [
                  {
                    "Ref": "QueryEngine"
                  },
                  {
                    "Ref": "LambdaRuntime"
                  },
                  {
                    "Ref": "EnableNonStringIndexing"
                  }
                ]
              },
              {
                "Ref": "StreamRecordsHandler"
              }
            ]
          },
          "StreamRecordsBatchSize": {
            "Ref": "StreamRecordsBatchSize"
          },
          "StepFunctionFallbackPeriod": {
            "Ref": "StepFunctionFallbackPeriod"
          },
          "StepFunctionFallbackPeriodUnit": {
            "Ref": "StepFunctionFallbackPeriodUnit"
          },
          "MaxPollingWaitTime": {
            "Ref": "MaxPollingWaitTime"
          },
          "NeptuneStreamEndpoint": {
            "Ref": "NeptuneStreamEndpoint"
          },
          "IAMAuthEnabledOnSourceStream": {
            "Ref": "IAMAuthEnabledOnSourceStream"
          },
          "StreamDBClusterResourceId": {
            "Ref": "StreamDBClusterResourceId"
          },
          "MaxPollingInterval": {
            "Ref": "MaxPollingInterval"
          },
          "VPC": {
            "Ref": "VPC"
          },
          "RouteTableIds": {
            "Ref": "RouteTableIds"
          },
          "CreateDDBVPCEndPoint": {
            "Ref": "CreateDDBVPCEndPoint"
          },
          "CreateMonitoringEndPoint": {
            "Ref": "CreateMonitoringEndPoint"
          },
          "CreateCloudWatchAlarm": {
            "Ref": "CreateCloudWatchAlarm"
          },
          "NotificationSNSTopicArn": {
            "Ref": "NotificationSNSTopicArn"
          },
          "NotificationEmail": {
            "Ref": "NotificationEmail"
          },
          "SubnetIds": {
            "Fn::Join": [
              ",",
              {
                "Ref": "SubnetIds"
              }
            ]
          },
          "SecurityGroupIds": {
            "Fn::Join": [
              ",",
              {
                "Ref": "SecurityGroupIds"
              }
            ]
          },
          "StreamPollerInitialState": {
            "Ref" : "StreamPollerInitialState"
	  },
          "StartingCheckpoint" : {
            "Ref" : "StartingCheckpoint" 
          }
        },
        "TemplateURL": "https://s3.amazonaws.com/aws-neptune-customer-samples/neptune-stream/neptune_stream_poller_nested_full_stack.json"
      }
    }
  },
  "Outputs": {
    "HTTPSAccessSG": {
      "Description": "HTTPS Access Security Group Arn",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.HTTPSAccessSG"
        ]
      }
    },
    "LeaseDynamoDBTable": {
      "Description": "Neptune Stream Poller Lease Table",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.LeaseDynamoDBTable"
        ]
      }
    },
    "StateMachineArn": {
      "Description": "Neptune Stream Poller State Machine Arn",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.StateMachineArn"
        ]
      }
    },
    "CronArn": {
      "Description": "Neptune Stream Poller Scheduler Cron Arn",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.CronArn"
        ]
      }
    },
    "StateMachineAlarmArn": {
      "Description": "Neptune Stream Poller State Machine Alarm Arn",
      "Condition" : "CreateCloudWatchAlarmCondition",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.StateMachineAlarmArn"
        ]
      }
    },
    "NeptuneStreamPollerLambdaArn": {
      "Description": "Neptune Stream Poller Lambda Arn",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.NeptuneStreamPollerLambdaArn"
        ]
      }
    },
    "CloudWatchMetricsDashboardURI": {
      "Description": "CloudWatch Metrics Dashboard URI",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStreamPoller",
          "Outputs.CloudWatchMetricsDashboardURI"
        ]
      }
    }
  }
}
