<commit_before># aws cloudformation --region us-east-2 create-stack --template-body file://IaC/PSJenkinsStack.yml --capabilities CAPABILITY_NAMED_IAM --stack-name jenkins-ps --tags Key=iit-billing-tag,Value=jenkins-ps --parameters ParameterKey=JHostName,ParameterValue=ps.cd.percona.com ParameterKey=JShortName,ParameterValue=jenkins-ps
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:

  JHostName:
    Default: ps.cd.percona.com
    Description: Fully Qualified Domain Name
    Type: String
    MinLength: 1
    MaxLength: 64
    AllowedPattern: '^[a-z][a-z0-9\.\-]*$'
    ConstraintDescription: must begin with a letter and must contain only lowercase letters, numbers, periods (.), and dashes (-).

  JShortName:
    Default: jenkins-ps
    Description: Short host name
    Type: String
    MinLength: 1
    MaxLength: 64
    AllowedPattern: '^[a-z][a-z0-9\.\-]*$'
    ConstraintDescription: must begin with a letter and must contain only lowercase letters, numbers, periods (.), and dashes (-).

  ZoneId:
    Default: Z1H0AFAU7N8IMC
    Description: Hosted Zone ID
    Type: AWS::Route53::HostedZone::Id

  MasterKeyName:
    Default: mykola
    Description: Key pair name
    Type: AWS::EC2::KeyPair::KeyName

Mappings:
  AmazonLinux1:
    us-east-2:
      x64: ami-922914f7
  AmazonLinux2:
    us-east-2:
      x64: ami-2a0f324f
  Docker:
    us-east-2:
      x64: ami-c3073ba6

Resources:

  JVPC: # separate virtual network for jenkins instances
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.177.0.0/22
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      Tags:
      - Key: Name
        Value: !Ref JShortName
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JInternetGateway: # Internet Gateway for jenkins VPC
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Name
        Value: !Ref JShortName
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JVPCGatewayAttachment: # Attach Gateway to VPC
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref JVPC
      InternetGatewayId: !Ref JInternetGateway

  JSubnetA: # create subnet in AZ
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref JVPC
      CidrBlock: 10.177.0.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select: [ 0, !GetAZs '' ]
      Tags:
      - Key: Name
        Value: !Join [ '-', [ !Ref JShortName, 'A' ]]
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JSubnetB: # create subnet in AZ
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref JVPC
      CidrBlock: 10.177.1.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select: [ 1, !GetAZs '' ]
      Tags:
      - Key: Name
        Value: !Join [ '-', [ !Ref JShortName, 'B' ]]
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JSubnetC: # create subnet in AZ
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref JVPC
      CidrBlock: 10.177.2.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select: [ 2, !GetAZs '' ]
      Tags:
      - Key: Name
        Value: !Join [ '-', [ !Ref JShortName, 'C' ]]
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JRouteTable: # create route table for VPC
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref JVPC
      Tags:
      - Key: Name
        Value: !Ref JShortName
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JInternetRoute: # add default route
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref JInternetGateway
      RouteTableId: !Ref JRouteTable

  SubnetARouteTable: # add subnet route
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref JRouteTable
      SubnetId: !Ref JSubnetA

  SubnetBRouteTable: # add subnet route
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref JRouteTable
      SubnetId: !Ref JSubnetB

  SubnetCRouteTable: # add subnet route
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref JRouteTable
      SubnetId: !Ref JSubnetC

  SSHSecurityGroup: # allow ssh access (assign when needed)
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: SSH
      GroupDescription: SSH traffic in
      VpcId: !Ref JVPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: 0.0.0.0/0
      Tags:
      - Key: iit-billing-tag
        Value: !Ref JShortName

  HTTPSecurityGroup: # allow http and https access to jenkins master
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: HTTP
      GroupDescription: HTTP and HTTPS traffic in
      VpcId: !Ref JVPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 443
        ToPort: 443
        CidrIp: 0.0.0.0/0
      Tags:
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JSlaveRole: # create Role for jenkins slaves (needed for assign tags)
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join [ '-', [ !Ref JShortName, 'slave' ]]
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Action: sts:AssumeRole
          Principal:
            Service: ec2.amazonaws.com
      Path: /
      Policies:
      - PolicyName: !Join [ '-', [ !Ref JShortName, 'slave' ]]
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource: '*'
            Action:
            - ec2:CreateTags
            - ec2:DeleteTags
            - ec2:DescribeInstances
            - ec2:DescribeSpotInstanceRequests

  JSlaveProfile: # create Profile for jenkins slaves (needed for assign tags)
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref JSlaveRole
      InstanceProfileName: !Join [ '-', [ !Ref JShortName, 'slave' ]]

  JMasterRole: # create Role for jenkins master (needed for run slaves)
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join [ '-', [ !Ref JShortName, 'master' ]]
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Action: sts:AssumeRole
          Principal:
            Service: ec2.amazonaws.com
      Path: /
      Policies:
      - PolicyName: StartInstances
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource: '*'
            Action:
            - ec2:ModifySpotFleetRequest
            - ec2:DescribeSpotFleetRequests
            - ec2:DescribeSpotFleetInstances
            - ec2:DescribeSpotInstanceRequests
            - ec2:CancelSpotInstanceRequests
            - ec2:GetConsoleOutput
            - ec2:RequestSpotInstances
            - ec2:RunInstances
            - ec2:StartInstances
            - ec2:StopInstances
            - ec2:TerminateInstances
            - ec2:CreateTags
            - ec2:DeleteTags
            - ec2:DescribeInstances
            - ec2:DescribeKeyPairs
            - ec2:DescribeRegions
            - ec2:DescribeImages
            - ec2:DescribeAvailabilityZones
            - ec2:DescribeSecurityGroups
            - ec2:DescribeSubnets
      - PolicyName: PassRole
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource:
            - !GetAtt JSlaveRole.Arn
            - !GetAtt JSlaveProfile.Arn
            Action:
            - iam:ListRoles
            - iam:PassRole
            - iam:ListInstanceProfiles
      - PolicyName: UserDataNeeds
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource: '*'
            Action:
            - ec2:AttachVolume
            - ec2:DetachVolume
            - ec2:DescribeVolumes
            - ec2:AssociateAddress
            - ec2:CreateTags
            - ec2:DescribeInstances

  JMasterProfile: # create Profile for jenkins master (needed for run slaves)
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref JMasterRole
      InstanceProfileName: !Ref JShortName

  SpotFleetRole: # create Role for run jenkins master as spot instance
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join [ '-', [ !Ref JShortName, 'SpotFleet' ]]
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole
      AssumeRolePolicyDocument:
        Version: 2008-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service: spotfleet.amazonaws.com
          Action: sts:AssumeRole

  MasterIP: # create public IP for jenkins master
    Type: AWS::EC2::EIP
    DependsOn: JVPC
    Properties:
      Domain: vpc

  JDNSRecord: # create DNS record for jenkins master
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref ZoneId
      Name: !Ref JHostName
      Type: A
      TTL: 300
      ResourceRecords:
      - !Ref MasterIP

  JDataVolume: # create volume for jenkins data directory
    Type: AWS::EC2::Volume
    DeletionPolicy: Snapshot
    Properties:
      AutoEnableIO: false
      AvailabilityZone:
        Fn::Select: [ 1, !GetAZs '' ]
      Encrypted: false
      Size: 100
      Tags:
      - Key: iit-billing-tag
        Value: !Ref JShortName
      - Key: Name
        Value: !Join [ ' ', [ !Ref JShortName, 'DATA, do not remove' ]]
      VolumeType: gp2

  JMasterInstance: # create jenkins master as spot instance
    Type: AWS::EC2::SpotFleet
    Properties:
      SpotFleetRequestConfigData:
        AllocationStrategy: lowestPrice
        ExcessCapacityTerminationPolicy: default
        IamFleetRole: !GetAtt SpotFleetRole.Arn
        ReplaceUnhealthyInstances: true
        SpotPrice: 0.10
        TargetCapacity: 1
        TerminateInstancesWithExpiration: false
        Type: maintain
        LaunchTemplateConfigs:
        - LaunchTemplateSpecification:
            LaunchTemplateId: !Ref JMasterTemplate
            Version: !GetAtt JMasterTemplate.LatestVersionNumber
          Overrides:
          - InstanceType: m4.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: c4.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: m5.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: c5.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: c5d.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB

  JMasterTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: PSMasterTemplate
      LaunchTemplateData:
        SecurityGroupIds:
        - !GetAtt JVPC.DefaultSecurityGroup
        - !GetAtt HTTPSecurityGroup.GroupId
        TagSpecifications:
        - ResourceType: instance
          Tags:
          - Key: Name
            Value: !Ref JShortName
          - Key: iit-billing-tag
            Value: !Ref JShortName
        - ResourceType: volume
          Tags:
          - Key: Name
            Value: !Ref JShortName
          - Key: iit-billing-tag
            Value: !Ref JShortName
        IamInstanceProfile:
            Arn: !GetAtt JMasterProfile.Arn
        EbsOptimized: true
        KeyName: !Ref MasterKeyName
        ImageId: !FindInMap [AmazonLinux1, !Ref 'AWS::Region', x64]
        Monitoring:
          Enabled: false
        UserData:
            Fn::Base64: !Sub |
              #!/bin/bash

              JENKINS_HOST=${JHostName}
              JENKINS_SHORT=${JShortName}
              JENKINS_EIP=${MasterIP.AllocationId}
              JENKINS_VOLUME_ID=${JDataVolume}
              INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
              INSTANCE_REGION=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/[a-z]$//')

              set -o xtrace
              set -o errexit

              setup_aws() {
                  aws ec2 associate-address \
                      --region $INSTANCE_REGION \
                      --instance-id $INSTANCE_ID \
                      --allocation-id $JENKINS_EIP \
                      --allow-reassociation

                  SPOT_REQUEST=$(
                      aws ec2 describe-instances \
                          --region $INSTANCE_REGION \
                          --instance-ids $INSTANCE_ID \
                          --query 'Reservations[].Instances[].SpotInstanceRequestId' \
                          --output text
                  )

                  VOLUMES=$(
                      aws ec2 describe-instances \
                          --region $INSTANCE_REGION \
                          --instance-ids $INSTANCE_ID \
                          --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId' \
                          --output text
                  )

                  aws ec2 create-tags  \
                      --resources $INSTANCE_ID $SPOT_REQUEST $VOLUMES \
                      --region $INSTANCE_REGION \
                      --tags Key=Name,Value=$JENKINS_SHORT \
                             Key=iit-billing-tag,Value=$JENKINS_SHORT
              }

              install_software() {
                  until yum makecache; do
                      sleep 1
                      echo try again
                  done

                  wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
                  rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
                  yum -y update --security
                  yum -y install java-1.8.0-openjdk jenkins nginx git yum-cron-daily aws-cli xfsprogs
                  yum -y remove java-1.7.0-openjdk

                  sed -i 's/apply_updates = no/apply_updates = yes/' /etc/yum/yum-cron.conf
                  chkconfig yum-cron on
                  service yum-cron start

                  wget https://dl.eff.org/certbot-auto -O /opt/certbot-auto
                  chmod 755 /opt/certbot-auto
              }

              volume_state() {
                  aws ec2 describe-volumes \
                      --volume-id $JENKINS_VOLUME_ID \
                      --region $INSTANCE_REGION \
                      --query 'Volumes[].State' \
                      --output text
              }

              mount_data_partition() {
                  aws ec2 detach-volume \
                      --region $INSTANCE_REGION \
                      --volume-id $JENKINS_VOLUME_ID \
                      || :
                  while true; do
                      [ "x$(volume_state)" = "xavailable" ] && break || sleep 1
                  done

                  aws ec2 attach-volume \
                      --region $INSTANCE_REGION \
                      --device /dev/xvdj \
                      --instance-id $INSTANCE_ID \
                      --volume-id $JENKINS_VOLUME_ID
                  while true; do
                      [ "x$(volume_state)" = "xin-use" ] && break || sleep 1
                  done
                  while true; do
                      [ -e /dev/xvdj ] && break || sleep 1
                  done

                  mkfs.xfs -L DATA /dev/xvdj || :
                  echo "/dev/xvdj /mnt xfs defaults,noatime,nofail 0 0" | tee -a /etc/fstab
                  mount /mnt
              }

              start_jenkins() {
                  ethtool -K eth0 sg off
                  cat <<-EOF | tee /etc/security/limits.d/jenkins.conf
              		jenkins    soft    core      unlimited
              		jenkins    hard    core      unlimited
              		jenkins    soft    fsize     unlimited
              		jenkins    hard    fsize     unlimited
              		jenkins    soft    nofile    4096
              		jenkins    hard    nofile    8192
              		jenkins    soft    nproc     30654
              		jenkins    hard    nproc     30654
              	EOF

                  install -o jenkins -g jenkins -d /mnt/$JENKINS_HOST
                  install -o jenkins -g jenkins -d /mnt/$JENKINS_HOST/init.groovy.d
                  if [ ! -f /mnt/$JENKINS_HOST/init.groovy.d/plugins.groovy ]; then
                      wget -O /mnt/$JENKINS_HOST/init.groovy.d/plugins.groovy \
                          https://raw.githubusercontent.com/Percona-Lab/jenkins-pipelines/master/IaC/init.groovy.d/plugins.groovy
                      sed -i 's/%LIST%/compress-buildlog copyartifact ec2-fleet google-login jobConfigHistory matrix-auth matrix-reloaded pipeline-model-definition pipeline-stage-view ssh-slaves warnings/' /mnt/$JENKINS_HOST/init.groovy.d/plugins.groovy
                  fi
                  printf "127.0.0.1 $(hostname) $(hostname -A)\n10.30.6.220 vbox-01.ci.percona.com\n10.30.6.9 repo.ci.percona.com\n" \
                      | tee -a /etc/hosts
                  sed -i 's^"-Djava.awt.headless=true"^"-Djava.awt.headless=true -Xms2048m -Xmx4096m -server -XX:+AlwaysPreTouch -verbose:gc -Xloggc:$JENKINS_HOME/gc-%t.log -XX:NumberOfGCLogFiles=5 -XX:+UseGCLogFileRotation -XX:GCLogFileSize=20m -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCCause -XX:+PrintTenuringDistribution -XX:+PrintReferenceGC -XX:+PrintAdaptiveSizePolicy -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -XX:+CMSParallelRemarkEnabled -XX:+ParallelRefProcEnabled -XX:+CMSClassUnloadingEnabled -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark -XX:NewSize=512m -XX:MaxNewSize=3g -XX:NewRatio=2"^' /etc/sysconfig/jenkins
                  echo JENKINS_HOME=/mnt/$JENKINS_HOST \
                      | tee -a /etc/sysconfig/jenkins
                  chkconfig jenkins on
                  service jenkins start

                  #echo "/usr/bin/aws s3 sync --sse-kms-key-id alias/jenkins-pmm-backup --sse aws:kms --exclude '*/caches/*' --exclude '*/config-history/nodes/*' --exclude '*/secretFiles/*' --delete /mnt/ s3://backup.cd.percona.com/" > /etc/cron.daily/jenkins-backup
                  #chmod 755 /etc/cron.daily/jenkins-backup

                  printf "* * * * * root bash -c 'curl -s http://169.254.169.254/latest/meta-data/spot/instance-action | grep action && sh -c \"service jenkins stop; umount /mnt\" || :'\n* * * * * root sleep 30; bash -c 'curl -s http://169.254.169.254/latest/meta-data/spot/instance-action | grep action && sh -c \"service jenkins stop; umount /mnt\" || :'\n" > /etc/cron.d/terminate-check
              }

              create_fake_ssl_cert() {
                  mkdir -p /etc/nginx/ssl<commit_msg>rollback Amazon EC2 Plugin<commit_after># aws cloudformation --region us-east-2 create-stack --template-body file://IaC/PSJenkinsStack.yml --capabilities CAPABILITY_NAMED_IAM --stack-name jenkins-ps --tags Key=iit-billing-tag,Value=jenkins-ps --parameters ParameterKey=JHostName,ParameterValue=ps.cd.percona.com ParameterKey=JShortName,ParameterValue=jenkins-ps
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:

  JHostName:
    Default: ps.cd.percona.com
    Description: Fully Qualified Domain Name
    Type: String
    MinLength: 1
    MaxLength: 64
    AllowedPattern: '^[a-z][a-z0-9\.\-]*$'
    ConstraintDescription: must begin with a letter and must contain only lowercase letters, numbers, periods (.), and dashes (-).

  JShortName:
    Default: jenkins-ps
    Description: Short host name
    Type: String
    MinLength: 1
    MaxLength: 64
    AllowedPattern: '^[a-z][a-z0-9\.\-]*$'
    ConstraintDescription: must begin with a letter and must contain only lowercase letters, numbers, periods (.), and dashes (-).

  ZoneId:
    Default: Z1H0AFAU7N8IMC
    Description: Hosted Zone ID
    Type: AWS::Route53::HostedZone::Id

  MasterKeyName:
    Default: mykola
    Description: Key pair name
    Type: AWS::EC2::KeyPair::KeyName

Mappings:
  AmazonLinux1:
    us-east-2:
      x64: ami-922914f7
  AmazonLinux2:
    us-east-2:
      x64: ami-2a0f324f
  Docker:
    us-east-2:
      x64: ami-c3073ba6

Resources:

  JVPC: # separate virtual network for jenkins instances
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.177.0.0/22
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      Tags:
      - Key: Name
        Value: !Ref JShortName
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JInternetGateway: # Internet Gateway for jenkins VPC
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Name
        Value: !Ref JShortName
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JVPCGatewayAttachment: # Attach Gateway to VPC
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref JVPC
      InternetGatewayId: !Ref JInternetGateway

  JSubnetA: # create subnet in AZ
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref JVPC
      CidrBlock: 10.177.0.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select: [ 0, !GetAZs '' ]
      Tags:
      - Key: Name
        Value: !Join [ '-', [ !Ref JShortName, 'A' ]]
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JSubnetB: # create subnet in AZ
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref JVPC
      CidrBlock: 10.177.1.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select: [ 1, !GetAZs '' ]
      Tags:
      - Key: Name
        Value: !Join [ '-', [ !Ref JShortName, 'B' ]]
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JSubnetC: # create subnet in AZ
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref JVPC
      CidrBlock: 10.177.2.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select: [ 2, !GetAZs '' ]
      Tags:
      - Key: Name
        Value: !Join [ '-', [ !Ref JShortName, 'C' ]]
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JRouteTable: # create route table for VPC
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref JVPC
      Tags:
      - Key: Name
        Value: !Ref JShortName
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JInternetRoute: # add default route
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref JInternetGateway
      RouteTableId: !Ref JRouteTable

  SubnetARouteTable: # add subnet route
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref JRouteTable
      SubnetId: !Ref JSubnetA

  SubnetBRouteTable: # add subnet route
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref JRouteTable
      SubnetId: !Ref JSubnetB

  SubnetCRouteTable: # add subnet route
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref JRouteTable
      SubnetId: !Ref JSubnetC

  SSHSecurityGroup: # allow ssh access (assign when needed)
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: SSH
      GroupDescription: SSH traffic in
      VpcId: !Ref JVPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: 0.0.0.0/0
      Tags:
      - Key: iit-billing-tag
        Value: !Ref JShortName

  HTTPSecurityGroup: # allow http and https access to jenkins master
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: HTTP
      GroupDescription: HTTP and HTTPS traffic in
      VpcId: !Ref JVPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 443
        ToPort: 443
        CidrIp: 0.0.0.0/0
      Tags:
      - Key: iit-billing-tag
        Value: !Ref JShortName

  JSlaveRole: # create Role for jenkins slaves (needed for assign tags)
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join [ '-', [ !Ref JShortName, 'slave' ]]
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Action: sts:AssumeRole
          Principal:
            Service: ec2.amazonaws.com
      Path: /
      Policies:
      - PolicyName: !Join [ '-', [ !Ref JShortName, 'slave' ]]
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource: '*'
            Action:
            - ec2:CreateTags
            - ec2:DeleteTags
            - ec2:DescribeInstances
            - ec2:DescribeSpotInstanceRequests

  JSlaveProfile: # create Profile for jenkins slaves (needed for assign tags)
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref JSlaveRole
      InstanceProfileName: !Join [ '-', [ !Ref JShortName, 'slave' ]]

  JMasterRole: # create Role for jenkins master (needed for run slaves)
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join [ '-', [ !Ref JShortName, 'master' ]]
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Action: sts:AssumeRole
          Principal:
            Service: ec2.amazonaws.com
      Path: /
      Policies:
      - PolicyName: StartInstances
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource: '*'
            Action:
            - ec2:ModifySpotFleetRequest
            - ec2:DescribeSpotFleetRequests
            - ec2:DescribeSpotFleetInstances
            - ec2:DescribeSpotInstanceRequests
            - ec2:CancelSpotInstanceRequests
            - ec2:GetConsoleOutput
            - ec2:RequestSpotInstances
            - ec2:RunInstances
            - ec2:StartInstances
            - ec2:StopInstances
            - ec2:TerminateInstances
            - ec2:CreateTags
            - ec2:DeleteTags
            - ec2:DescribeInstances
            - ec2:DescribeKeyPairs
            - ec2:DescribeRegions
            - ec2:DescribeImages
            - ec2:DescribeAvailabilityZones
            - ec2:DescribeSecurityGroups
            - ec2:DescribeSubnets
      - PolicyName: PassRole
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource:
            - !GetAtt JSlaveRole.Arn
            - !GetAtt JSlaveProfile.Arn
            Action:
            - iam:ListRoles
            - iam:PassRole
            - iam:ListInstanceProfiles
      - PolicyName: UserDataNeeds
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Resource: '*'
            Action:
            - ec2:AttachVolume
            - ec2:DetachVolume
            - ec2:DescribeVolumes
            - ec2:AssociateAddress
            - ec2:CreateTags
            - ec2:DescribeInstances

  JMasterProfile: # create Profile for jenkins master (needed for run slaves)
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref JMasterRole
      InstanceProfileName: !Ref JShortName

  SpotFleetRole: # create Role for run jenkins master as spot instance
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Join [ '-', [ !Ref JShortName, 'SpotFleet' ]]
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole
      AssumeRolePolicyDocument:
        Version: 2008-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service: spotfleet.amazonaws.com
          Action: sts:AssumeRole

  MasterIP: # create public IP for jenkins master
    Type: AWS::EC2::EIP
    DependsOn: JVPC
    Properties:
      Domain: vpc

  JDNSRecord: # create DNS record for jenkins master
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref ZoneId
      Name: !Ref JHostName
      Type: A
      TTL: 300
      ResourceRecords:
      - !Ref MasterIP

  JDataVolume: # create volume for jenkins data directory
    Type: AWS::EC2::Volume
    DeletionPolicy: Snapshot
    Properties:
      AutoEnableIO: false
      AvailabilityZone:
        Fn::Select: [ 1, !GetAZs '' ]
      Encrypted: false
      Size: 100
      Tags:
      - Key: iit-billing-tag
        Value: !Ref JShortName
      - Key: Name
        Value: !Join [ ' ', [ !Ref JShortName, 'DATA, do not remove' ]]
      VolumeType: gp2

  JMasterInstance: # create jenkins master as spot instance
    Type: AWS::EC2::SpotFleet
    Properties:
      SpotFleetRequestConfigData:
        AllocationStrategy: lowestPrice
        ExcessCapacityTerminationPolicy: default
        IamFleetRole: !GetAtt SpotFleetRole.Arn
        ReplaceUnhealthyInstances: true
        SpotPrice: 0.10
        TargetCapacity: 1
        TerminateInstancesWithExpiration: false
        Type: maintain
        LaunchTemplateConfigs:
        - LaunchTemplateSpecification:
            LaunchTemplateId: !Ref JMasterTemplate
            Version: !GetAtt JMasterTemplate.LatestVersionNumber
          Overrides:
          - InstanceType: m4.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: c4.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: m5.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: c5.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB
          - InstanceType: c5d.large
            AvailabilityZone:
              Fn::Select: [ 1, !GetAZs '' ]
            SubnetId: !Ref JSubnetB

  JMasterTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: PSMasterTemplate
      LaunchTemplateData:
        SecurityGroupIds:
        - !GetAtt JVPC.DefaultSecurityGroup
        - !GetAtt HTTPSecurityGroup.GroupId
        TagSpecifications:
        - ResourceType: instance
          Tags:
          - Key: Name
            Value: !Ref JShortName
          - Key: iit-billing-tag
            Value: !Ref JShortName
        - ResourceType: volume
          Tags:
          - Key: Name
            Value: !Ref JShortName
          - Key: iit-billing-tag
            Value: !Ref JShortName
        IamInstanceProfile:
            Arn: !GetAtt JMasterProfile.Arn
        EbsOptimized: true
        KeyName: !Ref MasterKeyName
        ImageId: !FindInMap [AmazonLinux1, !Ref 'AWS::Region', x64]
        Monitoring:
          Enabled: false
        UserData:
            Fn::Base64: !Sub |
              #!/bin/bash

              JENKINS_HOST=${JHostName}
              JENKINS_SHORT=${JShortName}
              JENKINS_EIP=${MasterIP.AllocationId}
              JENKINS_VOLUME_ID=${JDataVolume}
              INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
              INSTANCE_REGION=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/[a-z]$//')

              set -o xtrace
              set -o errexit

              setup_aws() {
                  aws ec2 associate-address \
                      --region $INSTANCE_REGION \
                      --instance-id $INSTANCE_ID \
                      --allocation-id $JENKINS_EIP \
                      --allow-reassociation

                  SPOT_REQUEST=$(
                      aws ec2 describe-instances \
                          --region $INSTANCE_REGION \
                          --instance-ids $INSTANCE_ID \
                          --query 'Reservations[].Instances[].SpotInstanceRequestId' \
                          --output text
                  )

                  VOLUMES=$(
                      aws ec2 describe-instances \
                          --region $INSTANCE_REGION \
                          --instance-ids $INSTANCE_ID \
                          --query 'Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId' \
                          --output text
                  )

                  aws ec2 create-tags  \
                      --resources $INSTANCE_ID $SPOT_REQUEST $VOLUMES \
                      --region $INSTANCE_REGION \
                      --tags Key=Name,Value=$JENKINS_SHORT \
                             Key=iit-billing-tag,Value=$JENKINS_SHORT
              }

              install_software() {
                  until yum makecache; do
                      sleep 1
                      echo try again
                  done

                  wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
                  rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
                  yum -y update --security
                  yum -y install java-1.8.0-openjdk jenkins nginx git yum-cron-daily aws-cli xfsprogs
                  yum -y remove java-1.7.0-openjdk

                  sed -i 's/apply_updates = no/apply_updates = yes/' /etc/yum/yum-cron.conf
                  chkconfig yum-cron on
                  service yum-cron start

                  wget https://dl.eff.org/certbot-auto -O /opt/certbot-auto
                  chmod 755 /opt/certbot-auto
              }

              volume_state() {
                  aws ec2 describe-volumes \
                      --volume-id $JENKINS_VOLUME_ID \
                      --region $INSTANCE_REGION \
                      --query 'Volumes[].State' \
                      --output text
              }

              mount_data_partition() {
                  aws ec2 detach-volume \
                      --region $INSTANCE_REGION \
                      --volume-id $JENKINS_VOLUME_ID \
                      || :
                  while true; do
                      [ "x$(volume_state)" = "xavailable" ] && break || sleep 1
                  done

                  aws ec2 attach-volume \
                      --region $INSTANCE_REGION \
                      --device /dev/xvdj \
                      --instance-id $INSTANCE_ID \
                      --volume-id $JENKINS_VOLUME_ID
                  while true; do
                      [ "x$(volume_state)" = "xin-use" ] && break || sleep 1
                  done
                  while true; do
                      [ -e /dev/xvdj ] && break || sleep 1
                  done

                  mkfs.xfs -L DATA /dev/xvdj || :
                  echo "/dev/xvdj /mnt xfs defaults,noatime,nofail 0 0" | tee -a /etc/fstab
                  mount /mnt
              }

              start_jenkins() {
                  ethtool -K eth0 sg off
                  cat <<-EOF | tee /etc/security/limits.d/jenkins.conf
              		jenkins    soft    core      unlimited
              		jenkins    hard    core      unlimited
              		jenkins    soft    fsize     unlimited
              		jenkins    hard    fsize     unlimited
              		jenkins    soft    nofile    4096
              		jenkins    hard    nofile    8192
              		jenkins    soft    nproc     30654
              		jenkins    hard    nproc     30654
              	EOF

                  install -o jenkins -g jenkins -d /mnt/$JENKINS_HOST
                  install -o jenkins -g jenkins -d /mnt/$JENKINS_HOST/init.groovy.d
                  if [ ! -f /mnt/$JENKINS_HOST/init.groovy.d/plugins.groovy ]; then
                      wget -O /mnt/$JENKINS_HOST/init.groovy.d/plugins.groovy \
                          https://raw.githubusercontent.com/Percona-Lab/jenkins-pipelines/master/IaC/init.groovy.d/plugins.groovy
                      sed -i 's/%LIST%/ec2 compress-buildlog copyartifact google-login jobConfigHistory matrix-auth matrix-reloaded pipeline-model-definition pipeline-stage-view ssh-slaves warnings/' /mnt/$JENKINS_HOST/init.groovy.d/plugins.groovy
                  fi
                  printf "127.0.0.1 $(hostname) $(hostname -A)\n10.30.6.220 vbox-01.ci.percona.com\n10.30.6.9 repo.ci.percona.com\n" \
                      | tee -a /etc/hosts
                  sed -i 's^"-Djava.awt.headless=true"^"-Djava.awt.headless=true -Xms2048m -Xmx4096m -server -XX:+AlwaysPreTouch -verbose:gc -Xloggc:$JENKINS_HOME/gc-%t.log -XX:NumberOfGCLogFiles=5 -XX:+UseGCLogFileRotation -XX:GCLogFileSize=20m -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCCause -XX:+PrintTenuringDistribution -XX:+PrintReferenceGC -XX:+PrintAdaptiveSizePolicy -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -XX:+CMSParallelRemarkEnabled -XX:+ParallelRefProcEnabled -XX:+CMSClassUnloadingEnabled -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark -XX:NewSize=512m -XX:MaxNewSize=3g -XX:NewRatio=2"^' /etc/sysconfig/jenkins
                  echo JENKINS_HOME=/mnt/$JENKINS_HOST \
                      | tee -a /etc/sysconfig/jenkins
                  chkconfig jenkins on
                  service jenkins start

                  #echo "/usr/bin/aws s3 sync --sse-kms-key-id alias/jenkins-pmm-backup --sse aws:kms --exclude '*/caches/*' --exclude '*/config-history/nodes/*' --exclude '*/secretFiles/*' --delete /mnt/ s3://backup.cd.percona.com/" > /etc/cron.daily/jenkins-backup
                  #chmod 755 /etc/cron.daily/jenkins-backup

                  printf "* * * * * root bash -c 'curl -s http://169.254.169.254/latest/meta-data/spot/instance-action | grep action && sh -c \"service jenkins stop; umount /mnt\" || :'\n* * * * * root sleep 30; bash -c 'curl -s http://169.254.169.254/latest/meta-data/spot/instance-action | grep action && sh -c \"service jenkins stop; umount /mnt\" || :'\n" > /etc/cron.d/terminate-check
              }

              create_fake_ssl_cert() {
                  mkdir -p /etc/nginx/ssl
{'fraction_non_alphanumeric': 0.0957756069454993, 'fraction_numerical': 0.020820784118586805, 'mean_word_length': 1.6748861646234676, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 30, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '198602', 'n_tokens_mistral': 12393, 'n_tokens_neox': 11558, 'n_words': 2510}