| AWSTemplateFormatVersion: '2010-09-09' |
| Description: Gerrit primary launch configuration and autoscaling group |
| Parameters: |
| TemplateBucketName: |
| Description: S3 bucket containing cloudformation templates |
| Type: String |
| EC2AMI: |
| Description: AMI ID for the EC2 instance hosting gerrit primaries |
| Type: String |
| InstanceType: |
| Description: EC2 instance type |
| Type: String |
| AllowedValues: [t2.micro, t2.small, t2.medium, t2.large, m3.medium, m3.large, |
| m3.xlarge, m3.2xlarge, m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge, |
| c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge, c3.large, c3.xlarge, |
| c3.2xlarge, c3.4xlarge, c3.8xlarge, r3.large, r3.xlarge, r3.2xlarge, r3.4xlarge, |
| r3.8xlarge, i2.xlarge, i2.2xlarge, i2.4xlarge, i2.8xlarge] |
| ConstraintDescription: Please choose a valid instance type. |
| ECSKeyName: |
| Type: String |
| Description: EC2 key pair name the cluter's instances |
| EnvironmentName: |
| Description: An environment name used to build the log stream names |
| Type: String |
| ECSCluster: |
| Description: The ECSCluster reference name to register gerrit primaries to |
| Type: String |
| EC2SecurityGroup: |
| Description: security groups to assign to the instances in the Auto Scaling group hosting gerrit primaries |
| Type: String |
| EC2InstanceProfile: |
| Description: The Amazon Resource Name (ARN) of the instance profile associated with the IAM role for the EC2 instances running gerrit primaries |
| Type: String |
| GerritInstanceNumber: |
| Description: Whether this is primary1 or primary2 |
| Type: Number |
| AllowedValues: [1,2] |
| FileSystem: |
| Description: The ID of the filesystem to share git data between gerrit primary instances |
| Type: String |
| SubnetId: |
| Description: The subnet ID where gerrit primary in the Auto Scaling group can be created |
| Type: String |
| AvailabilityZone: |
| Description: The Availability Zone in which to create the volume from a snapshot |
| Type: String |
| LogGroupName: |
| Description: The log group name |
| Type: String |
| PrimaryMaxCount: |
| Description: The maximum number of EC2 instances in the primary autoscaling group |
| Type: Number |
| GerritVolumeSnapshotId: |
| Description: Id of the EBS snapshot for Gerrit volume |
| Type: String |
| GerritVolumeAttachMaxRetries: |
| Description: Maximum number of retries when attaching Gerrit Volume |
| Type: Number |
| GerritVolumeAttachRetryDelay: |
| Description: The delay in seconds between Gerrit Volume attach attempts |
| Type: Number |
| GerritVolumeSizeInGiB: |
| Description: Gerrit volume size in GiB |
| Type: Number |
| |
| Resources: |
| PrimaryECSAutoScalingGroup: |
| Type: AWS::AutoScaling::AutoScalingGroup |
| Properties: |
| VPCZoneIdentifier: |
| - !Ref SubnetId |
| LaunchConfigurationName: !Ref 'PrimaryLaunchConfiguration' |
| MinSize: '1' |
| MaxSize: !Ref PrimaryMaxCount |
| DesiredCapacity: '1' |
| CreationPolicy: |
| ResourceSignal: |
| Timeout: PT15M |
| UpdatePolicy: |
| AutoScalingReplacingUpdate: |
| WillReplace: 'true' |
| |
| PrimaryLaunchConfiguration: |
| Type: AWS::AutoScaling::LaunchConfiguration |
| Properties: |
| ImageId: !Ref 'EC2AMI' |
| SecurityGroups: [!Ref 'EC2SecurityGroup'] |
| InstanceType: !Ref 'InstanceType' |
| IamInstanceProfile: !Ref 'EC2InstanceProfile' |
| KeyName: !Ref ECSKeyName |
| UserData: |
| Fn::Base64: !Sub | |
| #!/bin/bash -xe |
| export PRIMARY_ID=primary-${GerritInstanceNumber} |
| echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config |
| echo ECS_INSTANCE_ATTRIBUTES={\"target_group\":\"$PRIMARY_ID\"} >> /etc/ecs/ecs.config |
| |
| yum install -y aws-cfn-bootstrap nfs-utils wget aws-cli xfsprogs |
| |
| EC2_INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id` |
| VOLUME_ID=${GerritVolumeStack.Outputs.GerritVolumeRef} |
| echo "Volume Id: $VOLUME_ID" |
| |
| aws ec2 attach-volume --region ${AWS::Region} --volume-id $VOLUME_ID --instance-id $EC2_INSTANCE_ID --device /dev/xvdg |
| |
| for i in $(seq 1 ${GerritVolumeAttachMaxRetries}); do |
| echo "Waiting for volume $VOLUME_ID to be attached to the instace $EC2_INSTANCE_ID ($i/${GerritVolumeAttachMaxRetries})" |
| volumeStatus=`aws ec2 describe-volumes --region ${AWS::Region} --volume-ids $VOLUME_ID` |
| if [[ $volumeStatus =~ "\"State\": \"attached\"" ]]; then |
| echo "Volume $VOLUME_ID attached to the instace $EC2_INSTANCE_ID" |
| break |
| elif [[ "$i" -eq "${GerritVolumeAttachMaxRetries}" ]]; then |
| echo "Could not attach the volume $VOLUME_ID to the instace $EC2_INSTANCE_ID after ${GerritVolumeAttachMaxRetries} attempts" |
| exit 1 |
| fi |
| sleep ${GerritVolumeAttachRetryDelay} |
| done |
| |
| if [[ "${GerritVolumeSnapshotId}" = "" ]]; then |
| echo "Create file system for Gerrit volume" |
| mkfs -t xfs /dev/xvdg |
| fi |
| |
| mkdir /gerrit-mount-point |
| mount /dev/xvdg /gerrit-mount-point |
| |
| if [[ "${GerritVolumeSnapshotId}" = "" ]]; then |
| echo "Create Gerrit directories" |
| mkdir -p /gerrit-mount-point/gerrit-logs \ |
| /gerrit-mount-point/gerrit-cache \ |
| /gerrit-mount-point/gerrit-data \ |
| /gerrit-mount-point/gerrit-git \ |
| /gerrit-mount-point/gerrit-index \ |
| /gerrit-mount-point/gerrit-db |
| fi |
| |
| chown 1000:1000 -R /gerrit-mount-point |
| |
| # EFS setting |
| DIR_TGT=/mnt/efs/gerrit-shared |
| mkdir -p $DIR_TGT |
| EC2_REGION=${AWS::Region} |
| # 169.254.169.254 link-local address, valid only from the instance, to retrieve meta-data information. |
| EC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone` |
| EFS_FILE_SYSTEM_ID=${FileSystem} |
| DIR_SRC=$EC2_AVAIL_ZONE.$EFS_FILE_SYSTEM_ID.efs.$EC2_REGION.amazonaws.com |
| |
| touch /home/ec2-user/echo.res |
| echo $PRIMARY_ID >> /home/ec2-user/echo.res |
| echo $EFS_FILE_SYSTEM_ID >> /home/ec2-user/echo.res |
| echo $EC2_AVAIL_ZONE >> /home/ec2-user/echo.res |
| echo $EC2_REGION >> /home/ec2-user/echo.res |
| echo $DIR_SRC >> /home/ec2-user/echo.res |
| echo $DIR_TGT >> /home/ec2-user/echo.res |
| MAX_RETRIES=20 |
| for i in $(seq 1 $MAX_RETRIES); do |
| echo "Mounting EFS volume ($i/$MAX_RETRIES)..." |
| `mount -t nfs4 -o nfsvers=4.1,hard,timeo=600,retrans=2 $DIR_SRC:/ $DIR_TGT >> /home/ec2-user/echo.res` \ |
| && s=0 && break || s=$? && sleep 5; |
| done; (exit $s) |
| mkdir -p $DIR_TGT/git |
| mkdir -p $DIR_TGT/high-availability |
| chown -R 1000:1000 $DIR_TGT |
| cp -p /etc/fstab /etc/fstab.back-$(date +%F) |
| echo -e "$DIR_SRC:/ \t\t $DIR_TGT \t\t nfs \t\t defaults \t\t 0 \t\t 0" | tee -a /etc/fstab |
| # Get the CloudWatch Logs agent |
| echo -e " |
| {\"logs\": |
| {\"logs_collected\": |
| {\"files\": |
| {\"collect_list\": |
| [ |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/replication_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/replication_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/httpd_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/httpd_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/error_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/error_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/sshd_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/sshd_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/gc_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/gc_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/sharedref_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/sharedref_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/message_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/message_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/websession_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/websession_log\", |
| \"timezone\": \"UTC\" |
| }, |
| {\"file_path\": \"/gerrit-mount-point/gerrit-logs/audit_log\", |
| \"log_group_name\": \"${LogGroupName}\", |
| \"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/audit_log\", |
| \"timezone\": \"UTC\" |
| } |
| ] |
| } |
| } |
| } |
| }" >> /home/ec2-user/gerritlogsaccess.json |
| |
| # Install the CloudWatch Logs agent |
| wget https://s3.amazonaws.com/amazoncloudwatch-agent/centos/amd64/latest/amazon-cloudwatch-agent.rpm |
| rpm -U ./amazon-cloudwatch-agent.rpm |
| /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ec2-user/gerritlogsaccess.json -s |
| |
| # Signal to CloudFormation aws-cfn-bootstrap has been correctly updated |
| /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource PrimaryECSAutoScalingGroup --region ${AWS::Region} |
| |
| GerritVolumeStack: |
| Type: AWS::CloudFormation::Stack |
| Properties: |
| TemplateURL: !Join [ '', ['https://', !Ref TemplateBucketName, '.s3.amazonaws.com/cf-gerrit-volume.yml'] ] |
| TimeoutInMinutes: '25' |
| Parameters: |
| GerritVolumeId: "" |
| GerritVolumeSnapshotId: !Ref GerritVolumeSnapshotId |
| GerritVolumeSizeInGiB: !Ref GerritVolumeSizeInGiB |
| AvailabilityZone: !Ref AvailabilityZone |
| |
| Outputs: |
| PrimaryLaunchConfiguration: |
| Value: !Ref PrimaryLaunchConfiguration |
| Export: |
| Name: !Join [ '-', [ !Ref 'AWS::StackName', 'PrimaryLaunchConfiguration', !Ref GerritInstanceNumber ] ] |
| |
| PrimaryECSAutoScalingGroup: |
| Value: !Ref PrimaryECSAutoScalingGroup |
| Export: |
| Name: !Join [ '-', [ !Ref 'AWS::StackName', 'PrimaryECSAutoScalingGroup', !Ref GerritInstanceNumber ] ] |
| |