{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Neptune full stack with gremlin and rd4j console",
  "Parameters": {
    "EC2SSHKeyPairName": {
      "Description": "OPTIONAL: Name of an existing EC2 KeyPair to enable SSH access to the instances. Required only if an EC2ClientInstanceType is specified",
      "Type": "String",
      "ConstraintDescription": "Must be the name of an existing EC2 KeyPair in same region.",
      "Default": ""
    },
    "Env": {
      "Description": "Environment tag, e.g. prod, nonprod.",
      "Default": "test",
      "Type": "String",
      "AllowedPattern": "[a-z0-9]+",
      "MaxLength": 15
    },
    "DbInstanceType": {
      "Description": "Neptune DB instance type",
      "Type": "String",
      "Default": "db.serverless",
      "AllowedValues": [
        "db.serverless",
        "db.t3.medium",
        "db.r6g.large",
        "db.r6g.xlarge",
        "db.r6g.2xlarge",
        "db.r6g.4xlarge",
        "db.r6g.8xlarge",
        "db.r5.large",
        "db.r5.xlarge",
        "db.r5.2xlarge",
        "db.r5.4xlarge",
        "db.r5.8xlarge",
        "db.r5.12xlarge"
      ],
      "ConstraintDescription": "Must be a valid Neptune instance type. Note that for Stockholm and OSU only R5 and T3 instances are available."
    },
    "MinNCUs": {
      "Description": "Min NCUs to be set on the Neptune cluster(Should be less than or equal to MaxNCUs). Required if DBInstance type is db.serverless",
      "Default": 2.5,
      "Type": "Number",
      "MinValue": 1,
      "MaxValue": 128,
      "ConstraintDescription": "Must be a valid value between 1 and 128."
    },
    "MaxNCUs": {
      "Description": "Max NCUs to be set on the Neptune cluster(Should be greater than or equal to MinNCUs). Required if DBInstance type is db.serverless",
      "Default": 128,
      "Type": "Number",
      "MinValue": 1,
      "MaxValue": 128,
      "ConstraintDescription": "Must be a valid value between 1 and 128."
    },
    "DBReplicaIdentifierSuffix": {
      "Description": "OPTIONAL: The ID for the Neptune Replica to use. Empty means no read replica. Maximum Length allowed is 32 characters.",
      "Type": "String",
      "Default": "",
      "MaxLength": 32
    },
    "DBClusterId": {
      "Description": "OPTIONAL: Enter the Cluster id of your Neptune cluster. Maximum Length allowed is 38 characters.",
      "Type": "String",
      "AllowedPattern": "^[a-zA-Z]{0}(?:-?[a-zA-Z0-9]){0,37}$",
      "MaxLength": 38
    },
    "DBClusterPort": {
      "Type": "String",
      "Default": "8182",
      "Description": "Enter the port of your Neptune cluster"
    },
    "EC2ClientInstanceType": {
      "Description": "OPTIONAL: EC2 client instance. Required only if EC2 client needs to setup. Please refer to https://aws.amazon.com/ec2/pricing/ for pricing.",
      "Type": "String",
      "Default": "none",
      "AllowedValues": [
        "none",
        "t3.micro",
        "t3.small",
        "t3.medium",
        "m5.large",
        "m5.xlarge",
        "m5.2xlarge",
        "m5.4xlarge",
        "m5.12xlarge",
        "r5.large",
        "r5.xlarge",
        "r5.2xlarge",
        "r5.4xlarge",
        "r5.12xlarge"
      ],
      "ConstraintDescription": "Must be a valid EC2 instance type. Note some regions support limited instance types only. Ex: Stockholm and OSU does not support R4 instances"
    },
    "NeptuneQueryTimeout": {
      "Type": "Number",
      "Default": 20000,
      "Description": "Neptune Query Time out (in milliseconds)"
    },
    "NeptuneEnableAuditLog": {
      "Type": "Number",
      "Default": 0,
      "AllowedValues": [
        0,
        1
      ],
      "Description": "Enable Audit Log. 0 means disable and 1 means enable."
    },
    "IamAuthEnabled": {
      "Type": "String",
      "Default": "false",
      "AllowedValues": [
        "true",
        "false"
      ],
      "Description": "Enable IAM Auth for Neptune."
    },
    "SetupGremlinConsole": {
      "Type": "String",
      "Default": "false",
      "AllowedValues": [
        "true",
        "false"
      ],
      "Description": "OPTIONAL: Setup Gremlin console on EC2 client. Used only if EC2ClientInstanceType is specified."
    },
    "SetupRDF4JConsole": {
      "Type": "String",
      "Default": "false",
      "AllowedValues": [
        "true",
        "false"
      ],
      "Description": "OPTIONAL: Setup RDF4J console on EC2 client. Used only if EC2ClientInstanceType is specified."
    },
    "AttachBulkloadIAMRoleToNeptuneCluster": {
      "Type": "String",
      "Default": "true",
      "AllowedValues": [
        "true",
        "false"
      ],
      "Description": "Attach Bulkload IAM role to cluster"
    },
    "NotebookInstanceType": {
      "Description": "SageMaker Notebook instance type. Please refer https://aws.amazon.com/sagemaker/pricing/ for uptodate allowed instance type in aws region and https://aws.amazon.com/neptune/pricing/ for pricing.",
      "Type": "String",
      "Default": "none",
      "AllowedValues": [
        "none",
        "ml.t2.medium",
        "ml.t2.large",
        "ml.t2.xlarge",
        "ml.t2.2xlarge",
        "ml.t3.medium",
        "ml.t3.large",
        "ml.t3.xlarge",
        "ml.t3.2xlarge",
        "ml.m4.xlarge",
        "ml.m4.2xlarge",
        "ml.m4.4xlarge",
        "ml.m4.10xlarge",
        "ml.m4.16xlarge",
        "ml.m5.xlarge",
        "ml.m5.2xlarge",
        "ml.m5.4xlarge",
        "ml.m5.12xlarge",
        "ml.m5.24xlarge",
        "ml.c4.large",
        "ml.c4.xlarge",
        "ml.c4.2xlarge",
        "ml.c4.4xlarge",
        "ml.c4.8xlarge",
        "ml.c5.xlarge",
        "ml.c5.2xlarge",
        "ml.c5.4xlarge",
        "ml.c5.9xlarge",
        "ml.c5.18xlarge",
        "ml.c5d.xlarge",
        "ml.c5d.2xlarge",
        "ml.c5d.4xlarge",
        "ml.c5d.9xlarge",
        "ml.c5d.18xlarge",
        "ml.p3.2xlarge",
        "ml.p3.8xlarge",
        "ml.p3.16xlarge",
        "ml.p2.2xlarge",
        "ml.p2.8xlarge",
        "ml.p2.16xlarge"
      ],
      "ConstraintDescription": "Must be a valid SageMaker instance type."
    },
    "NeptuneSagemakerNotebookStartupScript": {
      "Description": "OPTIONAL: Startup script additions for the notebook instance.",
      "Type": "String",
      "Default": ""
    }
  },
  "Rules": {
    "DBInstanceTypeVsRegion": {
      "RuleCondition": {
        "Fn::Or" : [
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "eu-north-1"
        ]}, 
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
            "us-gov-east-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "us-west-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "sa-east-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "ap-east-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "ca-central-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "me-south-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region" },
          "af-south-1"
        ]},
        { "Fn::Equals": [
          { "Ref": "AWS::Region"},
          "cn-northwest-1"
        ]}]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Contains": [
              [ "db.t3.medium", "db.r5.large", "db.r5.xlarge", "db.r5.2xlarge", "db.r5.4xlarge", "db.r5.12xlarge", "db.serverless" ],
              { "Ref": "DbInstanceType" }
            ]
          },
          "AssertDescription": "Only R5 and T3 Instances are available in eu-north-1 (ARN), us-gov-east-1 (OSU), ca-central-1 (YUL), us-west-1 (SFO), me-south-1 (BAH), ap-east-1 (HKG), sa-east-1 (GRU) af-south-1 (CPT) and cn-northwest-1 (ZHY)"
        }
      ]
    },
    "EC2ClientInstanceTypeVsRegion": {
      "RuleCondition": {
          "Fn::Or" : [
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "eu-north-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
              "us-gov-east-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
              "us-west-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
              "ap-east-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
              "sa-east-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "ca-central-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "me-south-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "af-south-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "cn-northwest-1"
          ]}]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": [
              {
                "Fn::Contains": [
                  [ "r4.large", "r4.xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge" ],
                  { "Ref": "EC2ClientInstanceType" }
                ]
              }
            ]
          },
          "AssertDescription": "R4 Instances are not available in eu-north-1 (ARN), us-gov-east-1 (OSU), ca-central-1 (YUL), us-west-1(SFO), me-south-1 (BAH), ap-east-1 (HKG), sa-east-1 (GRU) af-south-1 (CPT) and cn-northwest-1 (ZHY)"
        }
      ]
    },
    "SagemakerNotebookInstanceTypeVsRegion": {
      "RuleCondition": {
        "Fn::Or" : [
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "us-gov-east-1"
          ]},
          { "Fn::Equals": [
            { "Ref": "AWS::Region" },
            "us-gov-west-1"
          ]}
        ]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Contains": [
              [
                "none"
              ],
              {
                "Ref": "NotebookInstanceType"
              }
            ]
          },
          "AssertDescription": "Neptune Sagemaker notebooks are not available in us-gov-east-1 (OSU) and us-gov-west-1 (PDT)"
        }
      ]
    },
    "EC2SSHKeyPairNameRequiredIfEC2Instance": {
      "RuleCondition": {
		  "Fn::Not": [
			{
			  "Fn::Equals": [
				{
				  "Ref": "EC2ClientInstanceType"
				},
				"none"
			  ]
			}
		  ]
		},
      "Assertions": [
        {
          "Assert": {
			  "Fn::Not": [
				{
				  "Fn::Equals": [
					{
					  "Ref": "EC2SSHKeyPairName"
					},
					""
				  ]
				}
			  ]
			},
          "AssertDescription": "EC2SSHKeyPairName is required if an EC2 client instance is specified"
        }
      ]
    }
  },
  "Conditions": {
    "CreateDBReplicaInstance": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "DBReplicaIdentifierSuffix"
            },
            ""
          ]
        }
      ]
    },
    "AZ3NotPresent": {"Fn::Or": [{"Fn::Equals": [{"Ref": "AWS::Region"}, "ca-central-1"]}, {"Fn::Equals": [{"Ref": "AWS::Region"}, "us-west-1"]}]},
    "AZ3Present": { "Fn::Not": [{ "Condition": "AZ3NotPresent" }] },
    "CreateEC2Instance": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "EC2ClientInstanceType"
            },
            "none"
          ]
        }
      ]
    },
    "CreateSagemakerNotebook": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "NotebookInstanceType"
            },
            "none"
          ]
        }
      ]
    }
  },
  "Resources": {
    "NeptuneStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
          "TemplateURL": {
          "Fn::Join": [
            "",
            [
              "https://s3.amazonaws.com/aws-neptune-customer-samples/v2/cloudformation-templates/neptune-base-stack.json"
            ]
          ]
        },

        "TimeoutInMinutes": "60",
        "Parameters": {
          "Env": {
            "Ref": "Env"
          },
          "DBReplicaIdentifierSuffix": {
            "Ref": "DBReplicaIdentifierSuffix"
          },
          "DBClusterId": {
            "Ref": "DBClusterId"
          },
          "DBClusterPort": {
            "Ref": "DBClusterPort"
          },
          "DbInstanceType": {
            "Ref": "DbInstanceType"
          },
          "NeptuneQueryTimeout": {
            "Ref": "NeptuneQueryTimeout"
          },
          "NeptuneEnableAuditLog": {
            "Ref": "NeptuneEnableAuditLog"
          },
          "IamAuthEnabled": {
            "Ref": "IamAuthEnabled"
          },
          "AttachBulkloadIAMRoleToNeptuneCluster": {
            "Ref": "AttachBulkloadIAMRoleToNeptuneCluster"
          },
          "MinNCUs": {
            "Ref": "MinNCUs"
          },
          "MaxNCUs": {
            "Ref": "MaxNCUs"
          }
        }
      }
    },
    "NeptuneEC2Client": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "CreateEC2Instance",
      "Properties": {
        "TemplateURL": {
          "Fn::Join": [
            "",
            [
              "https://s3.amazonaws.com/aws-neptune-customer-samples/v2/cloudformation-templates/neptune-ec2-client.json"
            ]
          ]
        },
        "TimeoutInMinutes": "30",
        "Parameters": {
          "Env": {
            "Ref": "Env"
          },
          "EC2SSHKeyPairName": {
            "Ref": "EC2SSHKeyPairName"
          },
          "EC2ClientInstanceType": {
            "Ref": "EC2ClientInstanceType"
          },
          "SetupGremlinConsole": {
            "Ref": "SetupGremlinConsole"
          },
          "SetupRDF4JConsole": {
            "Ref": "SetupRDF4JConsole"
          },
          "VPC": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.VPC"
            ]
          },
          "Subnet": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.PublicSubnet1"
            ]
          },
          "NeptuneDBCluster": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterId"
            ]
          },
          "NeptuneDBClusterEndpoint": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterEndpoint"
            ]
          },
          "NeptuneDBClusterPort": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterPort"
            ]
          },
          "NeptuneClientRole": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneClientRole"
            ]
          }
        }
      }
    },
    "NeptuneSagemakerNotebook": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "CreateSagemakerNotebook",
      "Properties": {
        "TemplateURL": {
          "Fn::Join": [
            "",
            [
              "https://s3.amazonaws.com/aws-neptune-customer-samples/v2/cloudformation-templates/neptune-sagemaker-notebook-stack.json"
            ]
          ]
        },
        "TimeoutInMinutes": "30",
        "Parameters": {
          "Env": {
            "Ref": "Env"
          },
          "NotebookInstanceType": {
            "Ref": "NotebookInstanceType"
          },
          "NeptuneClusterEndpoint": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterEndpoint"
            ]
          },
          "NeptuneClusterPort": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterPort"
            ]
          },
          "NeptuneClusterVpc": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.VPC"
            ]
          },
          "NeptuneClusterSubnetId": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.PublicSubnet1"
            ]
          },
          "NeptuneClientSecurityGroup": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneSG"
            ]
          },
          "NeptuneLoadFromS3RoleArn": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.NeptuneLoadFromS3IAMRoleArn"
            ]
          },
          "StartupScript": {
            "Ref": "NeptuneSagemakerNotebookStartupScript"
          },
          "DBClusterId": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterId"
            ]
          },
          "NeptuneClusterResourceId": {
            "Fn::GetAtt": [
              "NeptuneStack",
              "Outputs.DBClusterResourceId"
            ]
          },
          "EnableIamAuthOnNeptune" : {
            "Ref": "IamAuthEnabled"
          }
        }
      }
    }
  },
  "Outputs": {
    "DBClusterId": {
      "Description": "Neptune Cluster Identifier",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBClusterId"
        ]
      }
    },
    "DBSubnetGroupId": {
      "Description": "Neptune DBSubnetGroup Identifier",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBSubnetGroupId"
        ]
      }
    },
    "DBClusterResourceId": {
      "Description": "Neptune Cluster Resource Identifier",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBClusterResourceId"
        ]
      }
    },
    "DBClusterEndpoint": {
      "Description": "Master Endpoint for Neptune Cluster",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBClusterEndpoint"
        ]
      }
    },
    "DBInstanceEndpoint": {
      "Description": "Master Instance Endpoint",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBInstanceEndpoint"
        ]
      }
    },
    "DBReplicaInstanceEndpoint": {
      "Description": "ReadReplica Instance Endpoint",
      "Condition": "CreateDBReplicaInstance",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBReplicaInstanceEndpoint"
        ]
      }
    },
    "SparqlEndpoint": {
      "Description": "Sparql Endpoint for Neptune",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.SparqlEndpoint"
        ]
      }
    },
    "GremlinEndpoint": {
      "Description": "Gremlin Endpoint for Neptune",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.GremlinEndpoint"
        ]
      }
    },
    "LoaderEndpoint": {
      "Description": "Loader Endpoint for Neptune",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.LoaderEndpoint"
        ]
      }
    },
    "DBClusterReadEndpoint": {
      "Description": "DB cluster Read Endpoint",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBClusterReadEndpoint"
        ]
      }
    },
    "DBClusterPort": {
      "Description": "Port for the Neptune Cluster",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.DBClusterPort"
        ]
      }
    },
    "NeptuneLoadFromS3IAMRoleArn": {
      "Description": "IAM Role for loading data in Neptune",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.NeptuneLoadFromS3IAMRoleArn"
        ]
      }
    },
    "NeptuneIamAuthUser": {
      "Description": "IAM User for IAM Auth",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.NeptuneIamAuthUser"
        ]
      }
    },
    "EC2Client": {
      "Condition": "CreateEC2Instance",
      "Description": "EC2 client Identifier",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneEC2Client",
          "Outputs.EC2Client"
        ]
      }
    },
    "SSHAccess": {
      "Condition": "CreateEC2Instance",
      "Description": "This is how you gain remote access to the EC2 client.",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneEC2Client",
          "Outputs.SSHAccess"
        ]
      }
    },
    "VPC": {
      "Description": "VPC",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.VPC"
        ]
      }
    },
    "Subnet1": {
      "Description": "Private Subnet1",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.PrivateSubnet1"
        ]
      }
    },
    "Subnet2": {
      "Description": "Private Subnet2",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.PrivateSubnet2"
        ]
      }
    },
    "Subnet3": {
      "Description": "Private Subnet3",
      "Condition": "AZ3Present",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.PrivateSubnet3"
        ]
      }
    },
    "Subnet4": {
      "Description": "Public Subnet1",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneStack",
          "Outputs.PublicSubnet1"
        ]
      }
    },
    "NeptuneSagemakerNotebook": {
      "Condition": "CreateSagemakerNotebook",
      "Description": "Neptune Sagemaker Notebook Name",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneSagemakerNotebook",
          "Outputs.NeptuneSagemakerNotebook"
        ]
      }
    },
    "NeptuneNotebookInstanceLifecycleConfigId": {
      "Condition": "CreateSagemakerNotebook",
      "Description": "Neptune Sagemaker Notebook Instance Lifecycle ConfigId",
      "Value": {
        "Fn::GetAtt": [
          "NeptuneSagemakerNotebook",
          "Outputs.NeptuneNotebookInstanceLifecycleConfigId"
        ]
      }
    }
  }
}
