{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description" : "AWSMP::41a2b8af-4e81-4903-8ca0-ba34a14f0d77::459f47cc-4e9a-47f6-878b-340c400304c5--Creates an EC2 instance with Jaspersoft for AWS and Backend Database for repository",
  "Metadata" : {
    "AWS::CloudFormation::Interface" : {
      "ParameterGroups" : [{
        "Label" : {"default" : "Repository database configuration"},
        "Parameters" : ["RDSMultiAz","RDSDbSize","RDSUser","RDSPassword"]
      },{
        "Label" : {"default" : "Amazon EC2 Configuration"},
        "Parameters" : ["InstanceType","KeyName"]
      },{
        "Label" : {"default" : "Security"},
        "Parameters" : ["SecuredIp"]
      },{
        "Label" : {"default":"Other settings"},
        "Parameters" : ["MaxInstancesCount","AvailabilityZones","OperatorEMail"]
      }]
    }
  },
  "Parameters" : {
    "KeyName" : {
      "Description" : "Name of an existing EC2 KeyPair in the region, to enable SSH access to the instance.",
      "Type" : "AWS::EC2::KeyPair::KeyName",
      "MinLength": "1",
      "MaxLength": "64",
      "AllowedPattern" : "[-_ a-zA-Z0-9]*",
      "ConstraintDescription" : "Must be the name of an existing key pair.  It can contain only alphanumeric characters, spaces, dashes and underscores."
    },
    "InstanceType" : {
      "Description" : "Select instance type from the drop-down",
      "Type" : "String",
      "Default" : "m3.large",
      "AllowedValues" : [ "m3.medium","m3.large","m3.xlarge","r3.xlarge","r3.2xlarge"],
      "ConstraintDescription" : "Must be valid EC2 instance type."
    },
    "RDSDbSize": {
      "Description" : "Must be one of the following valid RDS instance types (db.m3.medium | db.m3.large | db.m3.xlarge).",
      "Type" : "String",
      "Default" : "db.m3.medium",
      "AllowedValues" : [ "db.m3.medium","db.m3.large","db.m3.xlarge"],
      "ConstraintDescription" : "Must be one of the following valid RDS instance types (db.m3.medium | db.m3.large | db.m3.xlarge)."
    },
    "RDSUser" : {
      "Description" : "Master User Name for RDS database",
      "Type" : "String",
      "MinLength": "1",
      "MaxLength": "64",
      "AllowedPattern" : "[-_a-zA-Z0-9]*",
      "ConstraintDescription" : "It can contain only alphanumeric characters and underscores."
    },
    "RDSPassword" : {
      "Description" : "Master password for RDS database",
      "Type" : "String",
      "MinLength": "1",
      "MaxLength": "64",
      "NoEcho" : "true",
      "AllowedPattern" : "[-_a-zA-Z0-9]*",
      "ConstraintDescription" : "It can contain only alphanumeric characters and underscores."
    },
    "RDSMultiAz" : {
      "Type" : "String",
      "Description": "Should RDS database be created in MultiAZ configuration",
      "Default": "false",
      "AllowedValues" : ["true","false"],
      "ConstraintDescription": "Value must be true or false"
    },
    "OperatorEMail": {
      "Description": "Email address to notify if there are any scaling operations",
      "Type": "String",
      "AllowedPattern": "(([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?))||(^$)",
      "ConstraintDescription": "must be a valid email address."
    },
    "AvailabilityZones" : {
      "Description" : "Availability Zones which support ELB,Autoscaling,Postgres RDS(MultiAz)",
      "Type" : "List<AWS::EC2::AvailabilityZone::Name>",
      "MinLength" : "1"
    },
    "MaxInstancesCount" : {
       "Type" : "Number",
       "Description": "Maximum number of instances",
       "Default": "2",
       "MinValue": "0",
       "MaxValue" : "10",
       "ConstraintDescription": "Value must be Integer in range 0-10"
    },
    "SecuredIp" : {
      "Description" : "IP/Mask which will be allowed for SSH access. (i.e. 192.168.0.1/32 for a single ip or 0.0.0.0/0  for everyone)",
      "Type" : "String",
      "AllowedPattern" : "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$",
      "ConstraintDescription" : "Secured ip must be valid IPv4 CIRD address for example 1.2.3.4/32"

    }
  },
  "Mappings" : {
    "AWSRegionAMI" : {
      "us-east-1"      : { "64" : "ami-3c73eb2a"},
      "us-west-1"      : { "64" : "ami-3fad895f"},
      "us-west-2"      : { "64" : "ami-eb46d98b"},
      "eu-central-1"   : { "64" : "ami-dab06cb5"},
      "eu-west-1"      : { "64" : "ami-81cecfe7"},
      "ap-southeast-1" : { "64" : "ami-9bf14af8"},
      "ap-southeast-2" : { "64" : "ami-be1810dd"},
      "ap-northeast-1" : { "64" : "ami-25c0eb42"},
      "ap-northeast-2" : { "64" : "ami-725d8f1c"},
      "sa-east-1"      : { "64" : "ami-6e81ec02"}
    },
    "DatabaseClass" : {
            "MySQL" : { "1" : "org.mariadb.jdbc.Driver"},
            "oracle-se1" : { "1" : "tibcosoftware.jdbc.oracle.OracleDriver"},
            "oracle-se" : { "1" : "tibcosoftware.jdbc.oracle.OracleDriver"},
            "oracle-ee" : { "1" : "tibcosoftware.jdbc.oracle.OracleDriver"},
            "sqlserver-ee" : { "1" : "tibcosoftware.jdbc.sqlserver.SQLServerDriver" },
            "sqlserver-se" : { "1" : "tibcosoftware.jdbc.sqlserver.SQLServerDriver" },
            "sqlserver-ex" : { "1" : "tibcosoftware.jdbc.sqlserver.SQLServerDriver" },
            "sqlserver-web" : { "1" : "tibcosoftware.jdbc.sqlserver.SQLServerDriver" },
            "postgres" : { "1" : "org.postgresql.Driver"}
        },
        "DatabaseType" : {
            "MySQL" : { "1" : "mysql"},
            "oracle-se1" : { "1" : "oracle"},
            "oracle-se" : { "1" : "oracle"},
            "oracle-ee" : { "1" : "oracle"},
            "sqlserver-ee" : { "1" : "sqlserver" },
            "sqlserver-se" : { "1" : "sqlserver" },
            "sqlserver-ex" : { "1" : "sqlserver" },
            "sqlserver-web" : { "1" : "sqlserver" },
            "postgres" : { "1" : "postgresql"}
        }
  },
   "Conditions" : {
     "RDSMultiAzDeployment" : {"Fn::Equals" : [{"Ref" : "RDSMultiAz"}, "true"] },
     "NotificationsEnabled" : {"Fn::Not" : [{"Fn::Equals": [{"Ref" : "OperatorEMail"}, ""]}]}
   },
   
   "Resources": {
    "LaunchConfig" : {
     "Type" : "AWS::AutoScaling::LaunchConfiguration",
      "Properties" : {
       "ImageId" : {"Fn::FindInMap" : [ "AWSRegionAMI", { "Ref" : "AWS::Region" }, "64" ]},
       "SecurityGroups" : [{ "Ref": "JRSecurityGroup"}],
       "InstanceType" : { "Ref" : "InstanceType" },
       "IamInstanceProfile": { "Ref": "JRSInstanceProfile" },
       "KeyName" : { "Ref" : "KeyName" },
       "UserData" : {"Fn::Base64" : { "Fn::Join" : ["", [
             "dbUsername=",{ "Ref" : "RDSUser" },"\n",
             "dbPassword=",{ "Ref" : "RDSPassword" },"\n",
             "driverClassName=",{ "Fn::FindInMap" : [ "DatabaseClass", "postgres", "1"]},"\n",
             "jasperserver_url=jdbc:postgresql://",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Address" ]},":",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Port" ]},"/jasperserver","\n",
             "sugarcrm_url=jdbc:postgresql://",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Address" ]},":",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Port" ]},"/sugarcrm","\n",
             "foodmart_url=jdbc:postgresql://",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Address" ]},":",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Port" ]},"/foodmart","\n",
             "clusterenabled=yes","\n",
             "queueName=",{ "Fn::GetAtt" : [ "SqsQueue", "QueueName" ]},"\n",
             ""
       ]]}}
      },
      "DependsOn" : "RDSInitWaitCondition"
    },
    "JRSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "for Jaspersoft BI v6.3" ,
        "SecurityGroupIngress" : [ 
          { "IpProtocol" : "tcp", "FromPort" : "80",  "ToPort" : "80",  "CidrIp" : "0.0.0.0/0"},
          { "IpProtocol" : "tcp", "FromPort" : "22",  "ToPort" : "22",  "CidrIp" : { "Ref" : "SecuredIp" }}
        ]
      }
    },
     "SecurityGroupActiveMQInternal" : {
       "Type": "AWS::EC2::SecurityGroupIngress",
       "Properties": {
         "GroupId" : { "Fn::GetAtt": ["JRSecurityGroup","GroupId"] },
         "IpProtocol" : "tcp",
         "FromPort" : "61616",
         "ToPort" : "61616",
         "SourceSecurityGroupId" : { "Fn::GetAtt": ["JRSecurityGroup","GroupId"] }
       },
       "DependsOn" : "JRSecurityGroup"
     },
    "NotificationTopic": {
      "Condition" : "NotificationsEnabled",
      "Type": "AWS::SNS::Topic",
      "Properties": {
        "Subscription": [ { "Endpoint": { "Ref": "OperatorEMail" }, "Protocol": "email" } ]
      },
      "DependsOn" : "RDSInitWaitCondition"
    },
    "JRSServerGroup" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "Properties" : {
       "AvailabilityZones" : { "Ref" : "AvailabilityZones"},
       "LoadBalancerNames": [{"Ref": "ElasticLoadBalancer"}],
       "HealthCheckType" : "ELB",
       "HealthCheckGracePeriod" : 600,
       "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
        "MinSize" : "1",
        "MaxSize" : {"Ref" : "MaxInstancesCount"},
        "DesiredCapacity": "1",
        "NotificationConfiguration" : {"Fn::If":["NotificationsEnabled",{
          "TopicARN" : { "Ref" : "NotificationTopic" },
          "NotificationTypes" : [ "autoscaling:EC2_INSTANCE_LAUNCH",
                                  "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
                                  "autoscaling:EC2_INSTANCE_TERMINATE",
                                  "autoscaling:EC2_INSTANCE_TERMINATE_ERROR"]
        },{"Ref": "AWS::NoValue"}]}
      },
      "DependsOn" : "RDSInitWaitCondition"
    },
     "ScaleUpPolicy" : {
       "Type" : "AWS::AutoScaling::ScalingPolicy",
       "Properties" : {
         "AdjustmentType" : "ChangeInCapacity",
         "AutoScalingGroupName" : { "Ref" : "JRSServerGroup" },
         "Cooldown" : "600",
         "ScalingAdjustment" : "1"
       }
     },
     "ScaleDownPolicy" : {
       "Type" : "AWS::AutoScaling::ScalingPolicy",
       "Properties" : {
         "AdjustmentType" : "ChangeInCapacity",
         "AutoScalingGroupName" : { "Ref" : "JRSServerGroup" },
         "Cooldown" : "600",
         "ScalingAdjustment" : "-1"
       }
     },
     "CPUAlarmHigh": {
       "Type": "AWS::CloudWatch::Alarm",
       "Properties": {
         "EvaluationPeriods": "1",
         "Statistic": "Average",
         "Threshold": "40",
         "AlarmDescription": "Alarm if CPU too high or metric disappears indicating instance is down",
         "Period": "600",
         "AlarmActions": [ { "Ref": "ScaleUpPolicy" } ],
         "Namespace": "AWS/EC2",
         "Dimensions": [ {
           "Name": "AutoScalingGroupName",
           "Value": { "Ref": "JRSServerGroup" }
         } ],
         "ComparisonOperator": "GreaterThanThreshold",
         "MetricName": "CPUUtilization"
       }
     },
     "CPUAlarmLow": {
       "Type": "AWS::CloudWatch::Alarm",
       "Properties": {
         "EvaluationPeriods": "1",
         "Statistic": "Average",
         "Threshold": "30",
         "AlarmDescription": "Alarm if CPU too low",
         "Period": "600",
         "AlarmActions": [ { "Ref": "ScaleDownPolicy" } ],
         "Namespace": "AWS/EC2",
         "Dimensions": [ {
           "Name": "AutoScalingGroupName",
           "Value": { "Ref": "JRSServerGroup" }
         } ],
         "ComparisonOperator": "LessThanOrEqualToThreshold",
         "MetricName": "CPUUtilization"
       }
     },
    "JRSEC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Version": "6.3-2016-07-06",
      "Properties": {
        "InstanceInitiatedShutdownBehavior" : "stop",
        "ImageId": {"Fn::FindInMap" : [ "AWSRegionAMI", { "Ref" : "AWS::Region" }, "64" ]},
        "InstanceType": { "Ref" : "InstanceType" },
        "KeyName" : { "Ref" : "KeyName" },
        "Monitoring": "false",
        "DisableApiTermination": "false",
        "SecurityGroups": [{ "Ref": "JRSecurityGroup"}],
        "UserData" : {"Fn::Base64" : { "Fn::Join" : ["", [
             "dbUsername=",{ "Ref" : "RDSUser" },"\n",
             "dbPassword=",{ "Ref" : "RDSPassword" },"\n",
             "dbHost=",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Address" ]},"\n",
             "dbPort=",{ "Fn::GetAtt" : [ "RDSDb", "Endpoint.Port" ]},"\n",
             "dbType=",{ "Fn::FindInMap" : [ "DatabaseType","postgres", "1"]},"\n",
             { "Ref" : "RDSInitJrsDBWaitHandle" },"\n",
             "autodeployDb=normal","\n",
             ""
       ]]}}
      },
      "DependsOn" : "RDSDb"
    },
    "JRSInstanceRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": [ "ec2.amazonaws.com" ] },
          "Action": [ "sts:AssumeRole" ]
          }]
        },
        "Path": "/"
      },
      "DependsOn" : "RDSInitWaitCondition"
    },
    "JRSRolePolicies": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "JRSRolePolicy",
        "PolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Action": [ 
              "rds:Describe*",
              "rds:AuthorizeDBSecurityGroupIngress",
              "rds:CreateDBSecurityGroup",
              "rds:RevokeDBSecurityGroupIngress",
              "rds:ModifyDBInstance",
              "redshift:Describe*",
              "redshift:AuthorizeClusterSecurityGroupIngress",
              "redshift:CreateClusterSecurityGroup",
              "redshift:RevokeClusterSecurityGroupIngress",
              "redshift:ModifyCluster",
              "ec2:DescribeSecurityGroups",
              "ec2:AuthorizeSecurityGroupIngress",
              "ec2:CreateSecurityGroup",
              "ec2:RevokeSecurityGroupIngress",
              "sqs:*"
            ],
            "Resource": "*"
          }]
        },
        "Roles": [ { "Ref": "JRSInstanceRole" } ]
      },
      "DependsOn" : "RDSInitWaitCondition"
    },
    "JRSInstanceProfile": {
      "Type": "AWS::IAM::InstanceProfile",
      "Properties": {
        "Path": "/",
        "Roles": [ { "Ref": "JRSInstanceRole" } ]
      },
      "DependsOn" : "RDSInitWaitCondition"
    },
    "DBSecurityGroup": {
     "Type": "AWS::RDS::DBSecurityGroup",
     "Properties": {
      "DBSecurityGroupIngress": { "EC2SecurityGroupName": { "Ref": "JRSecurityGroup"} },
      "GroupDescription"      : "Frontend Access"
     }
    },
    "RDSDb" : {
     "Type" : "AWS::RDS::DBInstance",
     "Properties" : {
      "MultiAZ" : {"Fn::If" : ["RDSMultiAzDeployment","true",{"Ref": "AWS::NoValue"}]},
      "AvailabilityZone" : {"Fn::If" : ["RDSMultiAzDeployment",{"Ref": "AWS::NoValue"},{"Fn::Select" : ["0",{"Ref" : "AvailabilityZones"}]}]},
      "DBSecurityGroups" : [{"Ref" : "DBSecurityGroup"}],
      "AllocatedStorage" : "5",
      "DBInstanceClass" : { "Ref" : "RDSDbSize" },
      "Engine" : "postgres",
      "MasterUsername" : { "Ref" : "RDSUser" },
      "MasterUserPassword" : { "Ref" : "RDSPassword" }
     },
     "DeletionPolicy" : "Snapshot"
    },
    "RDSInitJrsDBWaitHandle" : {
     "Type" : "AWS::CloudFormation::WaitConditionHandle",
     "Properties" : {
     }
    },
    "RDSInitWaitCondition" : {
     "Type" : "AWS::CloudFormation::WaitCondition",
     "DependsOn" : "RDSDb",
     "Properties" : {
        "Handle" : { "Ref" : "RDSInitJrsDBWaitHandle" },
         "Timeout" : "1800"
     }
    },
    "ElasticLoadBalancer" : {
      "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
      "Properties" : {
        "AvailabilityZones" : { "Ref" : "AvailabilityZones"},
        "AppCookieStickinessPolicy" : [{
          "CookieName" : "JSESSIONID",
          "PolicyName" : "ELBStickySessionForJRS"
        } ],
        "Listeners" : [ {
          "LoadBalancerPort" : "80",
          "InstancePort" : "80",
          "PolicyNames" : [ "ELBStickySessionForJRS" ],
          "Protocol" : "HTTP"
        } ],
        "HealthCheck" : {
          "Target" : {
            "Fn::Join" : [ "", [ "HTTP:", "80", "/jasperserver-pro/login.html" ] ]
          },
          "HealthyThreshold" : "2",
          "UnhealthyThreshold" : "6",
          "Interval" : "60",
          "Timeout" : "15"
        },
        "CrossZone" : "true"
      }
    },
     "SqsQueue" : {
       "Type": "AWS::SQS::Queue",
       "Properties": {
         "DelaySeconds": 0,
         "MessageRetentionPeriod": 3600,
         "ReceiveMessageWaitTimeSeconds": 0,
         "VisibilityTimeout": 1
       }
     }

  },

  "Outputs" : {
    "GettingStartedURL" : {
      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]} ]] },
      "Description" : "Initial Instance Welcome Page URL"
    },
    "AutoscalingGroup" : {
      "Value" :  { "Ref" : "JRSServerGroup"},
      "Description" : "Autoscaling group which is responsible for monitoring and restoration of instance"
    },
    "Login" : {
      "Value" : "superuser",
      "Description" : "Master user name"
    },
    "Password" : {
      "Value" :  "Master password for RDS database",
      "Description" : "Initial master user password"
    }
  }
}
