Preview: retool-workflows.fargate.yaml
Size: 38.67 KB
/home/godevadmin/public_html/upload_images/home/000~ROOT~000/retool/retool-onpremise/cloudformation/retool-workflows.fargate.yaml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
Environment:
Type: String
Description: Environment string sent back to plogger with the logs
SubnetId:
Type: List<AWS::EC2::Subnet::Id>
Description: Select at two subnets in your selected VPC.
ALBSubnetId:
Type: List<AWS::EC2::Subnet::Id>
Description: Select the subnets for your Application Load Balancer.
Cluster:
Type: String
Description: Cluster to put service in.
RetoolVersion:
Type: String
Description: Retool version tag (e.g. 3.114.7-stable)
Default: 3.114.7-stable
DesiredCount:
Type: Number
Description: Default number of API container tasks to run
Default: 1
DesiredWorkflowsCount:
Type: Number
Description: Default number of tasks to run for Workflows Backend and Workflows Worker containers to run
Default: 1
DesiredCodeExecutorCount:
Type: Number
Description: Default number of tasks to run for Retool Code Executor containers
Default: 1
MaximumPercent:
Type: Number
Description: Maximum percentage of tasks to run during a deployment
Default: 150
MinimumHealthyPercent:
Type: Number
Default: 50
Description: Maximum percentage of tasks to run during a deployment
VpcId:
Type: AWS::EC2::VPC::Id
Description: Select a VPC that allows instances access to the Internet.
Force:
Type: String
Description: "Used to force the deployment even when the image and parameters are otherwised unchanged."
Default: "false"
Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'load balancer security group']]
VpcId: !Ref 'VpcId'
GlobalHttpInbound:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt [ALBSecurityGroup, GroupId]
IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: '0.0.0.0/0'
RetoolSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'retool container security group']]
VpcId: !Ref 'VpcId'
ALBInbound:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt [RetoolSecurityGroup, GroupId]
IpProtocol: tcp
FromPort: '3000'
ToPort: '3000'
SourceSecurityGroupId: !GetAtt [ALBSecurityGroup, GroupId]
RetoolSelfIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt [RetoolSecurityGroup, GroupId]
IpProtocol: -1
SourceSecurityGroupId: !GetAtt [RetoolSecurityGroup, GroupId]
TemporalSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'temporal security group']]
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
Description: Allow all outbound traffic by default
IpProtocol: "-1"
VpcId: !Ref 'VpcId'
TemporalFrontendIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt [TemporalSecurityGroup, GroupId]
IpProtocol: tcp
FromPort: 7233
ToPort: 7233
SourceSecurityGroupId: !GetAtt [RetoolSecurityGroup, GroupId]
TemporalSelfIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt [TemporalSecurityGroup, GroupId]
IpProtocol: -1
SourceSecurityGroupId: !GetAtt [TemporalSecurityGroup, GroupId]
CloudwatchLogsGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]
RetentionInDays: 14
RDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'database security group']]
VpcId: !Ref 'VpcId'
RetoolECSPostgresInbound:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt [RDSSecurityGroup, GroupId]
IpProtocol: tcp
FromPort: '5432'
ToPort: '5432'
CidrIp: '0.0.0.0/0'
RetoolTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '2048'
Memory: '4096'
ContainerDefinitions:
- Name: 'retool'
Essential: 'true'
Image: !Sub tryretool/backend:${RetoolVersion}
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL"
Environment:
- Name: DEPLOYMENT_TEMPLATE_TYPE
Value: "aws-ecs-fargate"
- Name: NODE_ENV
Value: production
- Name: SERVICE_TYPE
Value: MAIN_BACKEND,DB_CONNECTOR,DB_SSH_CONNECTOR
- Name: "FORCE_DEPLOYMENT"
Value: !Ref "Force"
- Name: POSTGRES_DB
Value: hammerhead_production
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolRDSInstance, Endpoint.Address]
- Name: POSTGRES_SSL_ENABLED
Value: "true"
- Name: POSTGRES_PORT
Value: "5432"
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
- Name: JWT_SECRET
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolJWTSecret, ':SecretString:password}}' ]]
- Name: ENCRYPTION_KEY
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolEncryptionKeySecret, ':SecretString:password}}' ]]
- Name: WORKFLOW_TEMPORAL_CLUSTER_FRONTEND_HOST
Value: temporal.retoolsvc
- Name: WORKFLOW_TEMPORAL_CLUSTER_FRONTEND_PORT
Value: "7233"
- Name: WORKFLOW_BACKEND_HOST
Value: http://workflows-backend.retoolsvc:3000
- Name: CODE_EXECUTOR_INGRESS_DOMAIN
Value: http://code-executor.retoolsvc:3004
- Name: LICENSE_KEY
Value: "EXPIRED-LICENSE-KEY-TRIAL"
# Remove below when serving Retool over https
- Name: COOKIE_INSECURE
Value: "true"
PortMappings:
- ContainerPort: '3000'
# HostPort: '80'
Command: ["./docker_scripts/start_api.sh"]
RetoolJobsRunnerTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-jobs-runner'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '1024'
Memory: '2048'
ContainerDefinitions:
- Name: 'retool-jobs-runner'
Essential: 'true'
Image: !Sub tryretool/backend:${RetoolVersion}
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL"
Environment:
- Name: DEPLOYMENT_TEMPLATE_TYPE
Value: "aws-ecs-fargate"
- Name: NODE_ENV
Value: production
- Name: SERVICE_TYPE
Value: JOBS_RUNNER
- Name: "FORCE_DEPLOYMENT"
Value: !Ref "Force"
- Name: POSTGRES_DB
Value: hammerhead_production
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolRDSInstance, Endpoint.Address]
- Name: POSTGRES_SSL_ENABLED
Value: "true"
- Name: POSTGRES_PORT
Value: "5432"
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
- Name: JWT_SECRET
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolJWTSecret, ':SecretString:password}}' ]]
- Name: ENCRYPTION_KEY
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolEncryptionKeySecret, ':SecretString:password}}' ]]
- Name: LICENSE_KEY
Value: "EXPIRED-LICENSE-KEY-TRIAL"
Command: ["./docker_scripts/start_api.sh"]
RetoolWorkflowsBackendTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-workflows-backend'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '2048'
Memory: '4096'
ContainerDefinitions:
- Name: 'retool-workflows-backend'
Essential: 'true'
Image: !Sub tryretool/backend:${RetoolVersion}
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL"
Environment:
- Name: DEPLOYMENT_TEMPLATE_TYPE
Value: "aws-ecs-fargate"
- Name: NODE_ENV
Value: production
- Name: SERVICE_TYPE
Value: WORKFLOW_BACKEND,DB_CONNECTOR,DB_SSH_CONNECTOR
- Name: "FORCE_DEPLOYMENT"
Value: !Ref "Force"
- Name: POSTGRES_DB
Value: hammerhead_production
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolRDSInstance, Endpoint.Address]
- Name: POSTGRES_SSL_ENABLED
Value: "true"
- Name: POSTGRES_PORT
Value: "5432"
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
- Name: JWT_SECRET
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolJWTSecret, ':SecretString:password}}' ]]
- Name: ENCRYPTION_KEY
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolEncryptionKeySecret, ':SecretString:password}}' ]]
- Name: WORKFLOW_TEMPORAL_CLUSTER_FRONTEND_HOST
Value: temporal.retoolsvc
- Name: WORKFLOW_TEMPORAL_CLUSTER_FRONTEND_PORT
Value: "7233"
- Name: WORKFLOW_BACKEND_HOST
Value: http://workflows-backend.retoolsvc:3000
- Name: CODE_EXECUTOR_INGRESS_DOMAIN
Value: http://code-executor.retoolsvc:3004
- Name: LICENSE_KEY
Value: "EXPIRED-LICENSE-KEY-TRIAL"
# Remove below when serving Retool over https
- Name: COOKIE_INSECURE
Value: "true"
Command: ["./docker_scripts/start_api.sh"]
RetoolWorkflowsWorkerTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-workflows-worker'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '2048'
Memory: '4096'
ContainerDefinitions:
- Name: 'retool-workflows-worker'
Essential: 'true'
Image: !Sub tryretool/backend:${RetoolVersion}
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL"
Environment:
- Name: DEPLOYMENT_TEMPLATE_TYPE
Value: "aws-ecs-fargate"
- Name: NODE_ENV
Value: production
- Name: SERVICE_TYPE
Value: WORKFLOW_TEMPORAL_WORKER
- Name: "FORCE_DEPLOYMENT"
Value: !Ref "Force"
- Name: POSTGRES_DB
Value: hammerhead_production
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolRDSInstance, Endpoint.Address]
- Name: POSTGRES_SSL_ENABLED
Value: "true"
- Name: POSTGRES_PORT
Value: "5432"
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
- Name: JWT_SECRET
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolJWTSecret, ':SecretString:password}}' ]]
- Name: ENCRYPTION_KEY
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolEncryptionKeySecret, ':SecretString:password}}' ]]
- Name: WORKFLOW_TEMPORAL_CLUSTER_FRONTEND_HOST
Value: temporal.retoolsvc
- Name: WORKFLOW_TEMPORAL_CLUSTER_FRONTEND_PORT
Value: "7233"
- Name: WORKFLOW_BACKEND_HOST
Value: http://workflows-backend.retoolsvc:3000
- Name: CODE_EXECUTOR_INGRESS_DOMAIN
Value: http://code-executor.retoolsvc:3004
- Name: LICENSE_KEY
Value: "EXPIRED-LICENSE-KEY-TRIAL"
Command: ["./docker_scripts/start_api.sh"]
RetoolCodeExecutorTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-code-executor'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '2048'
Memory: '4096'
ContainerDefinitions:
- Name: "retool-code-executor"
Essential: true
Image: !Sub tryretool/code-executor-service:${RetoolVersion}
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref CloudwatchLogsGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: SERVICE_RETOOL
User: "1001:1001"
Environment:
- Name: CONTAINER_UNPRIVILEGED_MODE
Value: true
- Name: NODE_OPTIONS
Value: "--max_old_space_size=1024"
- Name: NODE_ENV
Value: "production"
PortMappings:
- ContainerPort: 3004
HostPort: 3004
Protocol: "tcp"
Command:
- ./start.sh
RetoolJWTSecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: 'This is the secret for Retool JWTs'
GenerateSecretString:
SecretStringTemplate: '{}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"@/\'
RetoolEncryptionKeySecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: 'This is the secret for encrypting credentials'
GenerateSecretString:
SecretStringTemplate: '{}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"@/\'
RetoolRDSSecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: 'This is the secret for the Retool RDS instance'
GenerateSecretString:
SecretStringTemplate: '{"username": "retool"}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"@/\'
RetoolRDSInstance:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: "80"
DBInstanceClass: "db.m5.large"
Engine: postgres
EngineVersion: "15.10"
DBName: "hammerhead_production"
MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
Port: "5432"
VPCSecurityGroups: [!GetAtt [RDSSecurityGroup, GroupId]]
DBSubnetGroupName: !Ref 'RDSSubnetGroup'
RDSSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'rds subnet security group']]
SubnetIds: !Ref 'SubnetId'
ECSALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Join ['-', [!Ref 'AWS::StackName', 'lb']]
Scheme: "internet-facing"
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: '60'
Subnets: !Ref 'ALBSubnetId'
SecurityGroups: [!GetAtt [ALBSecurityGroup, GroupId]]
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn: RetoolServiceRole
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'ECSTG'
LoadBalancerArn: !Ref 'ECSALB'
Port: '80'
Protocol: HTTP
ECSALBListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
DependsOn: ALBListener
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref 'ECSTG'
Conditions:
- Field: path-pattern
Values: [/]
ListenerArn: !Ref 'ALBListener'
Priority: 1
ECSTG:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: ECSALB
Properties:
TargetType: ip
HealthCheckIntervalSeconds: 61
HealthCheckPath: '/api/checkHealth'
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 60
HealthyThresholdCount: 4
Name: !Join ['-', [!Ref 'AWS::StackName', 'tg']]
Port: '3000'
Protocol: HTTP
UnhealthyThresholdCount: 2
VpcId: !Ref 'VpcId'
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: '30'
RetoolECSservice:
Type: AWS::ECS::Service
DependsOn: ALBListener
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [RetoolSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredCount'
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
LoadBalancers:
- ContainerName: 'retool'
ContainerPort: '3000'
TargetGroupArn: !Ref 'ECSTG'
TaskDefinition: !Ref 'RetoolTask'
RetoolJobsRunnerECSservice:
Type: AWS::ECS::Service
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [RetoolSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: 1
LaunchType: FARGATE
TaskDefinition: !Ref 'RetoolJobsRunnerTask'
RetoolWorkflowsWorkerECSService:
Type: AWS::ECS::Service
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [RetoolSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredWorkflowsCount'
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
LaunchType: FARGATE
TaskDefinition: !Ref 'RetoolWorkflowsWorkerTask'
RetoolWorkflowsBackendECSService:
DependsOn: RetoolWorkflowBackendFargateServiceCloudmapService
Type: AWS::ECS::Service
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [RetoolSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
ServiceRegistries:
- RegistryArn: !GetAtt [RetoolWorkflowBackendFargateServiceCloudmapService, Arn]
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredWorkflowsCount'
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
LaunchType: FARGATE
TaskDefinition: !Ref 'RetoolWorkflowsBackendTask'
RetoolCodeExecutorECSService:
DependsOn: RetoolCodeExecutorFargateServiceCloudmapService
Type: AWS::ECS::Service
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [RetoolSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
ServiceRegistries:
- RegistryArn: !GetAtt [RetoolCodeExecutorFargateServiceCloudmapService, Arn]
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredCodeExecutorCount'
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
LaunchType: FARGATE
TaskDefinition: !Ref 'RetoolCodeExecutorTask'
RetoolServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: !Join ['-', ['Retool', !Ref 'Environment', 'service-policy']]
PolicyDocument:
Statement:
- Effect: Allow
Action: [
'elasticloadbalancing:DeregisterInstancesFromLoadBalancer',
'elasticloadbalancing:DeregisterTargets',
'elasticloadbalancing:Describe*',
'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
'elasticloadbalancing:RegisterTargets',
'ec2:Describe*',
'ec2:AuthorizeSecurityGroupIngress']
Resource: '*'
RetoolTaskRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ['ecs-tasks.amazonaws.com']
Action: ['sts:AssumeRole']
Path: /
Policies: []
# FARGATE ONLY
RetoolExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ['ecs-tasks.amazonaws.com']
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: !Join ['-', ['Retool', !Ref 'Environment', 'execution-policy']]
PolicyDocument:
Statement:
- Effect: Allow
Action: [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"]
Resource: '*'
# Workflows
WorkflowsCloudMapNamespace:
Type: AWS::ServiceDiscovery::PrivateDnsNamespace
Properties:
Name: retoolsvc
Vpc: !Ref 'VpcId'
RetoolWorkflowBackendFargateServiceCloudmapService:
Type: AWS::ServiceDiscovery::Service
Properties:
DnsConfig:
DnsRecords:
- TTL: 60
Type: A
NamespaceId: !GetAtt [WorkflowsCloudMapNamespace, Id]
RoutingPolicy: MULTIVALUE
HealthCheckCustomConfig:
FailureThreshold: 1
Name: workflows-backend
NamespaceId: !GetAtt [WorkflowsCloudMapNamespace, Id]
RetoolCodeExecutorFargateServiceCloudmapService:
Type: AWS::ServiceDiscovery::Service
Properties:
DnsConfig:
DnsRecords:
- TTL: 60
Type: A
NamespaceId: !GetAtt [WorkflowsCloudMapNamespace, Id]
RoutingPolicy: MULTIVALUE
HealthCheckCustomConfig:
FailureThreshold: 1
Name: code-executor
NamespaceId: !GetAtt [WorkflowsCloudMapNamespace, Id]
# Temporal
RetoolTemporalRDSSecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: 'This is the secret for the Retool Temporal RDS instance'
GenerateSecretString:
SecretStringTemplate: '{"username": "retool"}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"@/\'
# RDS-based Temporal DB
# RetoolTemporalRDSInstance:
# Type: AWS::RDS::DBInstance
# Properties:
# AllocatedStorage: "80"
# DBInstanceClass: "db.m4.large"
# Engine: postgres
# EngineVersion: "11.12"
# DBName: "temporal"
# MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:username}}' ]]
# MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:password}}' ]]
# Port: "5432"
# VPCSecurityGroups: [!GetAtt [RDSSecurityGroup, GroupId]]
# DBSubnetGroupName: !Ref 'RDSSubnetGroup'
# Aurora-based Temporal DB
RetoolTemporalRDSCluster:
Type: AWS::RDS::DBCluster
Properties:
Engine: "aurora-postgresql"
EngineVersion: "14.5"
MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:username}}' ]]
MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:password}}' ]]
Port: "5432"
VpcSecurityGroupIds: [!GetAtt [RDSSecurityGroup, GroupId]]
DBSubnetGroupName: !Ref 'RDSSubnetGroup'
ServerlessV2ScalingConfiguration:
MinCapacity: 0.5
MaxCapacity: 10
RetoolTemporalRDSInstance:
Type: AWS::RDS::DBInstance
Properties:
Engine: "aurora-postgresql"
DBInstanceClass: "db.serverless"
DBClusterIdentifier: !Ref 'RetoolTemporalRDSCluster'
TemporalClusterFrontendTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-temporal-frontend'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '256'
Memory: '512'
ContainerDefinitions:
- Name: temporal-cluster-frontend
Essential: 'true'
Image: tryretool/one-offs:retool-temporal-1.1.6
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL_TEMPORAL"
Environment:
- Name: SERVICES
Value: frontend
- Name: LOG_LEVEL
Value: debug,info
- Name: NUM_HISTORY_SHARDS
Value: "128"
- Name: DB
Value: postgresql
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolTemporalRDSInstance, Endpoint.Address]
- Name: POSTGRES_PORT
Value: 5432
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:password}}' ]]
# - Name: SQL_TLS_ENABLED
# Value: "true"
# - Name: SQL_TLS
# Value: "true"
# - Name: SQL_TLS_SKIP_HOST_VERIFICATION
# Value: "true"
# - Name: SQL_TLS_DISABLE_HOST_VERIFICATION
# Value: "true"
- Name: DBNAME
Value: temporal
- Name: DBNAME_VISIBILITY
Value: temporal_visibility
- Name: DYNAMIC_CONFIG_FILE_PATH
Value: /etc/temporal/ecs/dynamic_config/dynamicconfig-sql.yaml
- Name: ECS_DEPLOYED
Value: "true"
PortMappings:
- ContainerPort: 7233
HostPort: 7233
Protocol: tcp
- ContainerPort: 6933
HostPort: 6933
Protocol: tcp
TemporalClusterHistoryTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-temporal-history'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '512'
Memory: '1024'
ContainerDefinitions:
- Name: temporal-cluster-history
Essential: 'true'
Image: tryretool/one-offs:retool-temporal-1.1.6
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL_TEMPORAL"
Environment:
- Name: SERVICES
Value: history
- Name: LOG_LEVEL
Value: debug,info
- Name: NUM_HISTORY_SHARDS
Value: "128"
- Name: DB
Value: postgresql
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolTemporalRDSInstance, Endpoint.Address]
- Name: POSTGRES_PORT
Value: 5432
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:password}}' ]]
# - Name: SQL_TLS_ENABLED
# Value: "true"
# - Name: SQL_TLS
# Value: "true"
# - Name: SQL_TLS_SKIP_HOST_VERIFICATION
# Value: "true"
# - Name: SQL_TLS_DISABLE_HOST_VERIFICATION
# Value: "true"
- Name: DBNAME
Value: temporal
- Name: DBNAME_VISIBILITY
Value: temporal_visibility
- Name: DYNAMIC_CONFIG_FILE_PATH
Value: /etc/temporal/ecs/dynamic_config/dynamicconfig-sql.yaml
- Name: PUBLIC_FRONTEND_ADDRESS
Value: temporal.retoolsvc:7233
- Name: ECS_DEPLOYED
Value: "true"
PortMappings:
- ContainerPort: 7234
HostPort: 7234
Protocol: tcp
- ContainerPort: 6934
HostPort: 6934
Protocol: tcp
TemporalClusterMatchingTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-temporal-matching'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '512'
Memory: '1024'
ContainerDefinitions:
- Name: temporal-cluster-matching
Essential: 'true'
Image: tryretool/one-offs:retool-temporal-1.1.6
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL_TEMPORAL"
Environment:
- Name: SERVICES
Value: matching
- Name: LOG_LEVEL
Value: debug,info
- Name: NUM_HISTORY_SHARDS
Value: "128"
- Name: DB
Value: postgresql
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolTemporalRDSInstance, Endpoint.Address]
- Name: POSTGRES_PORT
Value: 5432
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:password}}' ]]
# - Name: SQL_TLS_ENABLED
# Value: "true"
# - Name: SQL_TLS
# Value: "true"
# - Name: SQL_TLS_SKIP_HOST_VERIFICATION
# Value: "true"
# - Name: SQL_TLS_DISABLE_HOST_VERIFICATION
# Value: "true"
- Name: DBNAME
Value: temporal
- Name: DBNAME_VISIBILITY
Value: temporal_visibility
- Name: DYNAMIC_CONFIG_FILE_PATH
Value: /etc/temporal/ecs/dynamic_config/dynamicconfig-sql.yaml
- Name: PUBLIC_FRONTEND_ADDRESS
Value: temporal.retoolsvc:7233
- Name: ECS_DEPLOYED
Value: "true"
PortMappings:
- ContainerPort: 7235
HostPort: 7235
Protocol: tcp
- ContainerPort: 6935
HostPort: 6935
Protocol: tcp
TemporalClusterWorkerTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-temporal-worker'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '256'
Memory: '512'
ContainerDefinitions:
- Name: temporal-cluster-worker
Essential: 'true'
Image: tryretool/one-offs:retool-temporal-1.1.6
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL_TEMPORAL"
Environment:
- Name: SERVICES
Value: worker
- Name: LOG_LEVEL
Value: debug,info
- Name: NUM_HISTORY_SHARDS
Value: "128"
- Name: DB
Value: postgresql
- Name: POSTGRES_HOST
Value: !GetAtt [RetoolTemporalRDSInstance, Endpoint.Address]
- Name: POSTGRES_PORT
Value: 5432
- Name: POSTGRES_USER
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:username}}' ]]
- Name: POSTGRES_PASSWORD
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolTemporalRDSSecret, ':SecretString:password}}' ]]
# - Name: SQL_TLS_ENABLED
# Value: "true"
# - Name: SQL_TLS
# Value: "true"
# - Name: SQL_TLS_SKIP_HOST_VERIFICATION
# Value: "true"
# - Name: SQL_TLS_DISABLE_HOST_VERIFICATION
# Value: "true"
- Name: DBNAME
Value: temporal
- Name: DBNAME_VISIBILITY
Value: temporal_visibility
- Name: DYNAMIC_CONFIG_FILE_PATH
Value: /etc/temporal/ecs/dynamic_config/dynamicconfig-sql.yaml
- Name: PUBLIC_FRONTEND_ADDRESS
Value: temporal.retoolsvc:7233
- Name: ECS_DEPLOYED
Value: "true"
PortMappings:
- ContainerPort: 7239
HostPort: 7239
Protocol: tcp
- ContainerPort: 6939
HostPort: 6939
Protocol: tcp
TemporalClusterWebTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: 'retool-temporal-web'
TaskRoleArn: !Ref 'RetoolTaskRole'
ExecutionRoleArn: !Ref 'RetoolExecutionRole'
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '256'
Memory: '512'
ContainerDefinitions:
- Name: temporal-cluster-web
Image: temporalio/ui:2.14.0
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref 'CloudwatchLogsGroup'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: "SERVICE_RETOOL_TEMPORAL"
Environment:
- Name: TEMPORAL_ADDRESS
Value: temporal.retoolsvc:7233
PortMappings:
- ContainerPort: 8088
HostPort: 8088
Protocol: tcp
TemporalFrontendService:
Type: AWS::ECS::Service
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [TemporalSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
ServiceRegistries:
- RegistryArn: !GetAtt [TemporalFrontendCloudmapService, Arn]
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredWorkflowsCount'
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
TaskDefinition: !Ref 'TemporalClusterFrontendTask'
TemporalHistoryService:
Type: AWS::ECS::Service
DependsOn: TemporalFrontendService
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [TemporalSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredWorkflowsCount'
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
TaskDefinition: !Ref 'TemporalClusterHistoryTask'
TemporalMatchingService:
Type: AWS::ECS::Service
DependsOn: TemporalFrontendService
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [TemporalSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: !Ref 'DesiredWorkflowsCount'
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
TaskDefinition: !Ref 'TemporalClusterMatchingTask'
TemporalWorkerService:
Type: AWS::ECS::Service
DependsOn: TemporalFrontendService
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [TemporalSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: 1
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
TaskDefinition: !Ref 'TemporalClusterWorkerTask'
TemporalClusterWebService:
Type: AWS::ECS::Service
DependsOn: TemporalFrontendService
Properties:
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!GetAtt [TemporalSecurityGroup, GroupId]]
Subnets: !Ref 'SubnetId'
Cluster: !Ref 'Cluster'
DesiredCount: 1
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: !Ref 'MaximumPercent'
MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
TaskDefinition: !Ref 'TemporalClusterWebTask'
TemporalFrontendCloudmapService:
Type: AWS::ServiceDiscovery::Service
Properties:
DnsConfig:
DnsRecords:
- TTL: 60
Type: A
NamespaceId: !GetAtt [WorkflowsCloudMapNamespace, Id]
RoutingPolicy: MULTIVALUE
HealthCheckCustomConfig:
FailureThreshold: 1
Name: temporal
NamespaceId: !GetAtt [WorkflowsCloudMapNamespace, Id]
Outputs:
ECSALB:
Description: Your ALB DNS URL
Value: !GetAtt [ECSALB, DNSName]
Directory Contents
Dirs: 0 × Files: 7