blob: c2c8d856bcfcca38a9932b1753ad463d983e45d3 [file] [log] [blame]
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service into an ECS cluster behind a public load balancer.
Parameters:
GerritInstanceNumber:
Description: Whether this is master1 or master2
Type: Number
AllowedValues: [1,2]
ClusterStackName:
Description: Stack name of the ECS cluster to deply the serivces
Type: String
Default: gerrit-cluster
TemplateBucketName:
Description: S3 bucket containing cloudformation templates
Type: String
EnvironmentName:
Description: An environment name used to build the log stream names
Type: String
Default: test
DockerImage:
Description: Gerrit official Docker image
Type: String
Default: aws-gerrit/gerrit:latest
DockerRegistryUrl:
Description: Docker registry URL
Type: String
HTTPHostPort:
Description: Gerrit HTTP port
Type: Number
Default: 8080
SSHHostPort:
Description: Gerrit SSH port
Type: Number
Default: 29418
CertificateArn:
Description: SSL Certificates ARN
Type: String
HostedZoneName:
Description: The route53 HostedZoneName.
Type: String
Subdomain:
Description: The subdomain of the Gerrit cluster
Type: String
Default: gerrit-master-demo
SlaveSubdomain:
Description: The subdomain of the Gerrit slave
Type: String
LBSubdomain:
Description: The subdomain of the Gerrit load balancer
Type: String
LoadBalancerScheme:
Description: Load Balancer scheme, the nodes of an internet-facing load balancer have public IP addresses.
Type: String
Default: internet-facing
AllowedValues: [internal, internet-facing]
GerritKeyPrefix:
Description: Gerrit credentials keys prefix
Type: String
PeerSubdomain:
Description: The subdomain of the Gerrit cluster
Type: String
ReindexAtSartup:
Description: Force index reindexing at startup
Type: String
Default: false
GerritRAM:
Description: RAM to allocate to the Gerrit container
Type: Number
Default: 6000
GerritCPU:
Description: vCPU to allocate to the Gerrit container
Type: Number
Default: 1024
GerritHeapLimit:
Description: Gerrit Heap limit
Type: String
Default: 6g
FileDescriptorsSoftLimit:
Description: The soft limit for file descriptors allowed in the Gerrit container
Type: Number
Default: 1024
FileDescriptorsHardLimit:
Description: The hard limit for file descriptors allowed in the Gerrit container
Type: Number
Default: 1024
JgitCacheSize:
Description: JGit cache size
Type: String
Default: 3g
LDAPServer:
Description: LDAP server URL
Type: String
LDAPUsername:
Description: Username to bind to the LDAP server with
Type: String
LDAPAccountBase:
Description: Root of the tree containing all user accounts
Type: String
LDAPGroupBase:
Description: Root of the tree containing all group objects
Type: String
LDAPAccountPattern:
Description: Query pattern to use when searching for a user account
Type: String
Default: (&(objectClass=person)(uid=${username}))
SMTPServer:
Description: SMTP server URL
Type: String
SMTPServerPort:
Description: SMTP server port
Type: Number
Default: 465
SMTPUser:
Description: User name to authenticate with, if required for relay
Type: String
SMTPDomain:
Description: Domain to be used in the From field
Type: String
SMTPEncryption:
Description: Encryption to be used
Type: String
Default: ssl
AllowedValues: ['ssl', 'tls', 'none']
SMTPSslVerify:
Description: If false and SMTPEncryption is 'ssl' or 'tls', Gerrit will not verify the server certificate when it connects to send an email message.
Type: String
Default: true
AllowedValues: [true, false]
InstanceId:
Description: Optional identifier for the Gerrit instance
Type: String
Default: gerrit-dual-master-MASTER
MetricsCloudwatchEnabled:
Description: Whether gerrit metrics should be published to cloudwatch
Type: String
Default: false
AllowedValues: [true, false]
MetricsCloudwatchNamespace:
Description: The CloudWatch namespace for Gerrit metrics
Type: String
Default: gerrit
MetricsCloudwatchRate:
Description: The rate at which metrics should be fired to AWS
Type: String
Default: 60s
MetricsCloudwatchInitialDelay:
Description: The time to delay the first reporting execution
Type: String
Default: 0
MetricsCloudwatchJVMEnabled:
Description: Whether JVM metrics shoiuld be published to cloudwatch
Type: String
Default: false
AllowedValues: [true, false]
MetricsCloudwatchDryRun:
Description: The reporter will log.DEBUG the metrics, instead of doing a real POST to CloudWatch
Type: String
Default: false
AllowedValues: [true, false]
MetricsCloudwatchExcludeMetrics:
Description: Comma separated list of regex patterns to exclude metrics reported to CloudWatch
Type: CommaDelimitedList
Default: ''
RemoteReplicationTargetHost:
Description: The fully qualified domain name of a remote replication target
Type: String
Default: ''
MultiSiteGlobalProjects:
Description: The list of global project patterns
Type: CommaDelimitedList
Default: ''
MultiSiteEnabled:
Description: Whether this gerrit is part of a multi-site cluster deployment
Type: String
Default: false
MultiSiteKafkaBrokers:
Description: Comma separated list of Kafka broker hosts (host:port) to use for publishing events to the message broker
Type: CommaDelimitedList
Default: ''
MultiSiteZookeeperConnectString:
Description: Connection string to Zookeeper
Type: String
Default: ''
MultiSiteZookeeperRootNode:
Description: Root node to use in Zookeeper to store/retrieve information
Type: String
ConstraintDescription: Choose a slash-separated ('/') string not starting with a slash ('/')
AllowedPattern: '^[^\/].*'
Default: 'gerrit/multi-site'
Mappings:
Gerrit:
Volume:
Git: gerrit-git-master
Websessions: gerrit-ha-websessions-master
Data: gerrit-data-master
Index: gerrit-index-master
Cache: gerrit-cache-master
Db: gerrit-db-master
Logs: gerrit-logs-master
Service:
Name: gerrit-master
LoadBalancer:
HTTPPort: 8080
SSHPort: 29418
Container:
HTTPPort: 8080
SSHPort: 29418
Git:
Daemon:
Port: 9418
SSH:
Port: 1022
Resources:
Service:
Type: AWS::ECS::Service
DependsOn:
- HTTPListener
- SSHListener
Properties:
Cluster:
Fn::ImportValue:
!Join [':', [!Ref 'ClusterStackName', 'ClusterName']]
DesiredCount: 1
TaskDefinition: !Ref TaskDefinition
LoadBalancers:
- ContainerName: !FindInMap ['Gerrit', 'Service', 'Name']
ContainerPort: !FindInMap ['Gerrit', 'Container', 'HTTPPort']
TargetGroupArn: !Ref HTTPTargetGroup
- ContainerName: !FindInMap ['Gerrit', 'Service', 'Name']
ContainerPort: !FindInMap ['Gerrit', 'Container', 'SSHPort']
TargetGroupArn: !Ref SSHTargetGroup
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Join ['', [!FindInMap ['Gerrit', 'Service', 'Name'], TaskDefinition]]
TaskRoleArn: !GetAtt ECSTaskExecutionRoleStack.Outputs.TaskExecutionRoleRef
ExecutionRoleArn: !GetAtt ECSTaskExecutionRoleStack.Outputs.TaskExecutionRoleRef
NetworkMode: bridge
PlacementConstraints:
- Expression: !Sub 'attribute:target_group == master-${GerritInstanceNumber}'
Type: "memberOf"
ContainerDefinitions:
- Name: !FindInMap ['Gerrit', 'Service', 'Name']
Essential: true
Image: !Sub '${DockerRegistryUrl}/${DockerImage}'
Environment:
- Name: CANONICAL_WEB_URL
Value: !Sub 'https://${LBSubdomain}.${HostedZoneName}'
- Name: HTTPD_LISTEN_URL
Value: !Sub
- 'proxy-https://*:${HTTPContainerPort}/'
- { HTTPContainerPort: !FindInMap ['Gerrit', 'Container', 'HTTPPort'] }
- Name: AWS_REGION
Value: !Ref AWS::Region
- Name: SETUP_REPLICATION
Value: true
- Name: GERRIT_KEY_PREFIX
Value: !Ref GerritKeyPrefix
- Name: SETUP_HA
Value: true
- Name: HA_PEER_URL
Value: !Sub
- 'http://${PeerSubdomain}.${HostedZoneName}:${HTTPGerritLBPort}'
- { HTTPGerritLBPort: !FindInMap ['Gerrit', 'LoadBalancer', 'HTTPPort'] }
- Name: HOSTED_ZONE_NAME
Value: !Ref HostedZoneName
- Name: REINDEX_AT_STARTUP
Value: !Ref ReindexAtSartup
- Name: GERRIT_HEAP_LIMIT
Value: !Ref GerritHeapLimit
- Name: JGIT_CACHE_SIZE
Value: !Ref JgitCacheSize
- Name: LDAP_SERVER
Value: !Ref LDAPServer
- Name: LDAP_USERNAME
Value: !Ref LDAPUsername
- Name: LDAP_ACCOUNT_BASE
Value: !Ref LDAPAccountBase
- Name: LDAP_GROUP_BASE
Value: !Ref LDAPGroupBase
- Name: LDAP_ACCOUNT_PATTERN
Value: !Ref LDAPAccountPattern
- Name: SMTP_SERVER
Value: !Ref SMTPServer
- Name: SMTP_SERVER_PORT
Value: !Ref SMTPServerPort
- Name: SMTP_ENCRYPTION
Value: !Ref SMTPEncryption
- Name: SMTP_SSL_VERIFY
Value: !Ref SMTPSslVerify
- Name: SMTP_USER
Value: !Ref SMTPUser
- Name: SMTP_DOMAIN
Value: !Ref SMTPDomain
- Name: GIT_PORT
Value: !FindInMap ['Git', 'Daemon', 'Port']
- Name: GIT_SSH_PORT
Value: !FindInMap ['Git', 'SSH', 'Port']
- Name: SLAVE_SUBDOMAIN
Value: !Ref SlaveSubdomain
- Name: GERRIT_INSTANCE_ID
Value: !Ref InstanceId
- Name: METRICS_CLOUDWATCH_ENABLED
Value: !Ref MetricsCloudwatchEnabled
- Name: METRICS_CLOUDWATCH_NAMESPACE
Value: !Ref MetricsCloudwatchNamespace
- Name: METRICS_CLOUDWATCH_RATE
Value: !Ref MetricsCloudwatchRate
- Name: METRICS_CLOUDWATCH_INITIAL_DELAY
Value: !Ref MetricsCloudwatchInitialDelay
- Name: METRICS_CLOUDWATCH_JVM_ENABLED
Value: !Ref MetricsCloudwatchJVMEnabled
- Name: METRICS_CLOUDWATCH_DRY_RUN
Value: !Ref MetricsCloudwatchDryRun
- Name: METRICS_CLOUDWATCH_EXCLUDE_METRICS_LIST
Value: !Join [',', !Ref MetricsCloudwatchExcludeMetrics]
- Name: REMOTE_REPLICATION_TARGET_HOST
Value: !Ref RemoteReplicationTargetHost
- Name: MULTISITE_GLOBAL_PROJECTS
Value: !Join [',', !Ref MultiSiteGlobalProjects]
- Name: MULTISITE_ENABLED
Value: !Ref MultiSiteEnabled
- Name: MULTISITE_KAFKA_BROKERS
Value: !Join [',', !Ref MultiSiteKafkaBrokers]
- Name: MULTISITE_ZOOKEEPER_CONNECT_STRING
Value: !Ref MultiSiteZookeeperConnectString
- Name: MULTISITE_ZOOKEEPER_ROOT_NODE
Value: !Ref MultiSiteZookeeperRootNode
Ulimits:
- Name: nofile
HardLimit: !Ref FileDescriptorsHardLimit
SoftLimit: !Ref FileDescriptorsSoftLimit
MountPoints:
- SourceVolume: !FindInMap ['Gerrit', 'Volume', 'Git']
ContainerPath: /var/gerrit/git
- SourceVolume: !FindInMap ['Gerrit', 'Volume', 'Websessions']
ContainerPath: /var/gerrit/high-availability
- SourceVolume: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Data'], !Ref 'GerritInstanceNumber']]
ContainerPath: /var/gerrit/data
- SourceVolume: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Index'], !Ref 'GerritInstanceNumber']]
ContainerPath: /var/gerrit/index
- SourceVolume: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Cache'], !Ref 'GerritInstanceNumber']]
ContainerPath: /var/gerrit/cache
- SourceVolume: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Db'], !Ref 'GerritInstanceNumber']]
ContainerPath: /var/gerrit/db
- SourceVolume: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Logs'], !Ref 'GerritInstanceNumber']]
ContainerPath: /var/gerrit/logs
Cpu: !Ref GerritCPU
Memory: !Ref GerritRAM
PortMappings:
- ContainerPort: !FindInMap ['Gerrit', 'Container', 'HTTPPort']
HostPort: !Ref HTTPHostPort
Protocol: tcp
- ContainerPort: !FindInMap ['Gerrit', 'Container', 'SSHPort']
HostPort: !Ref SSHHostPort
Protocol: tcp
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref ClusterStackName
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: !Ref EnvironmentName
Volumes:
- Name: !FindInMap ['Gerrit', 'Volume', 'Git']
Host:
SourcePath: "/mnt/efs/gerrit-shared/git"
- Name: !FindInMap ['Gerrit', 'Volume', 'Websessions']
Host:
SourcePath: "/mnt/efs/gerrit-shared/high-availability"
- Name: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Db'], !Ref 'GerritInstanceNumber']]
DockerVolumeConfiguration:
Scope: shared
Autoprovision: true
Driver: local
Labels:
gerrit-db: !Join ['-', [!Ref EnvironmentName, !FindInMap ['Gerrit', 'Volume', 'Db'], !Ref 'GerritInstanceNumber']]
- Name: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Data'], !Ref 'GerritInstanceNumber']]
DockerVolumeConfiguration:
Scope: shared
Autoprovision: true
Driver: local
Labels:
gerrit-data: !Join ['-', [!Ref EnvironmentName, !FindInMap ['Gerrit', 'Volume', 'Data'], !Ref 'GerritInstanceNumber']]
- Name: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Cache'], !Ref 'GerritInstanceNumber']]
DockerVolumeConfiguration:
Scope: shared
Autoprovision: true
Driver: local
Labels:
gerrit-cache: !Join ['-', [!Ref EnvironmentName, !FindInMap ['Gerrit', 'Volume', 'Cache'], !Ref 'GerritInstanceNumber']]
- Name: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Index'], !Ref 'GerritInstanceNumber']]
DockerVolumeConfiguration:
Scope: shared
Autoprovision: true
Driver: local
Labels:
gerrit-index: !Join ['-', [!Ref EnvironmentName, !FindInMap ['Gerrit', 'Volume', 'Index'], !Ref 'GerritInstanceNumber']]
- Name: !Join ['-', [!FindInMap ['Gerrit', 'Volume', 'Logs'], !Ref 'GerritInstanceNumber']]
DockerVolumeConfiguration:
Scope: shared
Autoprovision: true
Driver: local
Labels:
gerrit-logs: !Join ['-', [!Ref EnvironmentName, !FindInMap ['Gerrit', 'Volume', 'Logs'], !Ref 'GerritInstanceNumber']]
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Type: network
Scheme: !Ref 'LoadBalancerScheme'
Subnets:
- Fn::ImportValue:
!Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
Tags:
- Key: Name
Value: !Join ['-', [!Ref 'EnvironmentName', !FindInMap ['Gerrit', 'Service', 'Name'], 'nlb']]
HTTPTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: LoadBalancer
Properties:
VpcId:
Fn::ImportValue:
!Join [':', [!Ref 'ClusterStackName', 'VPCId']]
Port: !Ref HTTPHostPort
Protocol: TCP
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn: LoadBalancer
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref HTTPTargetGroup
LoadBalancerArn: !Ref LoadBalancer
Port: !FindInMap ['Gerrit', 'LoadBalancer', 'HTTPPort']
Protocol: TCP
SSHTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: LoadBalancer
Properties:
VpcId:
Fn::ImportValue:
!Join [':', [!Ref 'ClusterStackName', 'VPCId']]
Port: !Ref SSHHostPort
Protocol: TCP
SSHListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn: LoadBalancer
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref SSHTargetGroup
LoadBalancerArn: !Ref LoadBalancer
Port: !FindInMap ['Gerrit', 'LoadBalancer', 'SSHPort']
Protocol: TCP
ECSTaskExecutionRoleStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Join [ '', ['https://', !Ref TemplateBucketName, '.s3.amazonaws.com/cf-gerrit-task-execution-role.yml'] ]
TimeoutInMinutes: '5'
Outputs:
PublicLoadBalancerDNSName:
Description: The DNS name of the external load balancer
Value: !GetAtt 'LoadBalancer.DNSName'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
CanonicalHostedZoneID:
Description: Canonical Hosted Zone ID
Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
PublicLoadBalancerUrl:
Description: The url of the external load balancer
Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
HostedZoneName:
Description: Route53 Hosted Zone name
Value: !Ref HostedZoneName
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
Subdomain:
Description: Service DNS subdomain
Value: !Ref Subdomain
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
CanonicalWebUrl:
Description: Canonical Web URL
Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]