Skip to content

Commit

Permalink
Add Insights stack
Browse files Browse the repository at this point in the history
  • Loading branch information
farski committed Jan 8, 2025
1 parent 262d548 commit c3d2954
Show file tree
Hide file tree
Showing 4 changed files with 317 additions and 0 deletions.
38 changes: 38 additions & 0 deletions spire/templates/apps-200A.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ Parameters:

FeederSharedAlbListenerRulePriorityPrefix: { Type: String }

InsightsSharedAlbListenerRulePriorityPrefix: { Type: String }

NetworksSharedAlbListenerRulePriorityPrefix: { Type: String }

RemixSharedAlbListenerRulePriorityPrefix: { Type: String }
Expand Down Expand Up @@ -299,6 +301,39 @@ Resources:
TemplateURL: !Sub ${TemplateUrlPrefix}/feeder.yml
TimeoutInMinutes: 20

InsightsStack:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
Parameters:
NestedChangeSetScrubbingResourcesState: !Ref NestedChangeSetScrubbingResourcesState
AlbFullName: !Ref AlbFullName
AlbHttpsListenerArn: !Ref AlbHttpsListenerArn
EcsClusterArn: !Ref EcsClusterArn
VpcId: !Ref VpcId
EcrImageTag: !Sub /prx/${EnvironmentTypeAbbreviation}/Spire/Dovetail-Insights/pkg/docker-image-tag
NewRelicApiKeyPrxLite: !Ref NewRelicApiKeyPrxLite
AlbListenerRulePriorityPrefix: !Ref InsightsSharedAlbListenerRulePriorityPrefix
EnvironmentType: !Ref EnvironmentType
EnvironmentTypeAbbreviation: !Ref EnvironmentTypeAbbreviation
EnvironmentTypeLowercase: !Ref EnvironmentTypeLowercase
RegionMode: !Ref RegionMode
RootStackName: !Ref RootStackName
RootStackId: !Ref RootStackId
IdHostname: !Ref IdHostname
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
TemplateURL: !Sub ${TemplateUrlPrefix}/dovetail-insights.yml
TimeoutInMinutes: 20

NetworksStack:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Delete
Expand Down Expand Up @@ -426,6 +461,9 @@ Outputs:
FeederWebTargetGroupFullName:
Value: !GetAtt FeederStack.Outputs.WebTargetGroupFullName

InsightsWebTargetGroupFullName:
Value: !GetAtt InsightsStack.Outputs.WebTargetGroupFullName

NetworksPublicWebTargetGroupFullName:
Value: !GetAtt NetworksStack.Outputs.PublicWebTargetGroupFullName

Expand Down
271 changes: 271 additions & 0 deletions spire/templates/apps/dovetail-insights.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# stacks/apps/dovetail-insights.yml
# 200A
#
# The names of the SQS queues created by this template are intended to
# implicitly match some configuration that exists within the CMS application.
# The only part of the queue names that is passed to the application is the
# prefix; if the stems change in other the template or the app config, things
# will not function as expected.
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Description: >-
Creates a dedicated load balancer and the ECS service for the public Insights
web server.
Parameters:
kWebContainerName:
Type: String
Default: insights-web
kWebApplicationPort:
Type: Number
Default: 3000
#######
NestedChangeSetScrubbingResourcesState: { Type: String }
AlbFullName: { Type: String }
AlbHttpsListenerArn: { Type: String }
EcsClusterArn: { Type: String }
EnvironmentType: { Type: String }
EnvironmentTypeAbbreviation: { Type: String }
EnvironmentTypeLowercase: { Type: String }
RegionMode: { Type: String }
RootStackName: { Type: String }
RootStackId: { Type: String }
VpcId: { Type: AWS::EC2::VPC::Id }
NewRelicApiKeyPrxLite: { Type: String }
EcrImageTag: { Type: AWS::SSM::Parameter::Value<String> }
AlbListenerRulePriorityPrefix: { Type: String }
IdHostname: { Type: String }

Conditions:
IsProduction: !Equals [!Ref EnvironmentType, Production]
IsPrimaryRegion: !Equals [!Ref RegionMode, Primary]
EnableNestedChangeSetScrubbingResources: !Equals [!Ref NestedChangeSetScrubbingResourcesState, Enabled]

Resources:
NestedChangeSetScrubber: { Type: AWS::SNS::Topic, Condition: EnableNestedChangeSetScrubbingResources }

HostHeaderListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref WebTargetGroup
Type: forward
Conditions:
- Field: host-header
Values:
- insights.dovetail.*
ListenerArn: !Ref AlbHttpsListenerArn
Priority: !Join ["", [!Ref AlbListenerRulePriorityPrefix, "01"]]

ExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyDocument:
Statement:
- Action: ssm:GetParameters
Effect: Allow
Resource: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/prx/${EnvironmentTypeAbbreviation}/Spire/Dovetail-Insights/*
Sid: AllowAppParameterRead
Version: "2012-10-17"
PolicyName: ContainerSecrets
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
TaskRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Version: "2012-10-17"
Policies:
- PolicyDocument:
Statement:
- Action: events:PutEvents
Effect: Allow
Resource: !Sub arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:event-bus/default
Sid: AllowDefaultEventBusPut
Version: "2012-10-17"
PolicyName: DefaultEventBus
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }

WebTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 15
HealthCheckPath: /api/v1
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 3
Port: 80
Protocol: HTTP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: "30"
Tags:
- { Key: Name, Value: !Sub "${RootStackName}_insights" }
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
UnhealthyThresholdCount: 3
VpcId: !Ref VpcId
WebTargetGroupHttp5xxAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProduction
Properties:
AlarmName: !Sub ERROR [Insights] Web server <${EnvironmentTypeAbbreviation}> RETURNING 5XX ERRORS (${RootStackName})
AlarmDescription: !Sub >-
${EnvironmentType} Insights' Rails server is returning 5XX errors from
the ECS service to the load balancer.
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: LoadBalancer
Value: !Ref AlbFullName
- Name: TargetGroup
Value: !GetAtt WebTargetGroup.TargetGroupFullName
EvaluationPeriods: 1
MetricName: HTTPCode_Target_5XX_Count
Namespace: AWS/ApplicationELB
Period: 60
Statistic: Sum
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:ops:cloudwatch-log-group-name, Value: !Ref WebTaskLogGroup }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
Threshold: 0
TreatMissingData: notBreaching

WebEcsService:
Type: AWS::ECS::Service
# Condition: HasAuroraEndpoint # See README
Properties:
Cluster: !Ref EcsClusterArn
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 50
DesiredCount: !If [IsPrimaryRegion, !If [IsProduction, 0, 0], 0]
EnableECSManagedTags: true
LoadBalancers:
- ContainerName: !Ref kWebContainerName
ContainerPort: !Ref kWebApplicationPort
TargetGroupArn: !Ref WebTargetGroup
PlacementConstraints:
- Type: memberOf
Expression: attribute:ecs.cpu-architecture == ARM64
PropagateTags: TASK_DEFINITION
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
TaskDefinition: !Ref WebTaskDefinition
WebTaskLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
RetentionInDays: 14
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
WebTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Command:
- web
Cpu: !If [IsProduction, 200, 128]
Environment:
- Name: ID_HOST
Value: !Ref IdHostname
- Name: NEW_RELIC_KEY
Value: !Ref NewRelicApiKeyPrxLite
- Name: NEW_RELIC_NAME
Value: !If [IsProduction, Insights Production, Insights Staging]
- Name: PORT
Value: !Ref kWebApplicationPort
- Name: RAILS_ENV
Value: !Ref EnvironmentTypeLowercase
Essential: true
Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${EcrImageTag}
LinuxParameters:
InitProcessEnabled: true
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref WebTaskLogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: ecs
Memory: !If [IsProduction, 2000, 1000]
MemoryReservation: !If [IsProduction, 1000, 500]
Name: !Ref kWebContainerName
PortMappings:
- ContainerPort: !Ref kWebApplicationPort
HostPort: 0
# Secrets:
# - Name: API_ADMIN_TOKENS
# ValueFrom: !Sub /prx/${EnvironmentTypeAbbreviation}/Spire/Dovetail-Feeder/api-admin-tokens
ExecutionRoleArn: !GetAtt ExecutionRole.Arn
NetworkMode: bridge
Tags:
- { Key: prx:meta:tagging-version, Value: "2021-04-07" }
- { Key: prx:cloudformation:stack-name, Value: !Ref AWS::StackName }
- { Key: prx:cloudformation:stack-id, Value: !Ref AWS::StackId }
- { Key: prx:cloudformation:root-stack-name, Value: !Ref RootStackName }
- { Key: prx:cloudformation:root-stack-id, Value: !Ref RootStackId }
- { Key: prx:ops:environment, Value: !Ref EnvironmentType }
- { Key: prx:dev:family, Value: Dovetail }
- { Key: prx:dev:application, Value: Insights }
TaskRoleArn: !GetAtt TaskRole.Arn

Outputs:
WebTargetGroupFullName:
Value: !GetAtt WebTargetGroup.TargetGroupFullName
3 changes: 3 additions & 0 deletions spire/templates/dashboards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Parameters:

IframelyTargetGroupFullName: { Type: String }

InsightsWebTargetGroupFullName: { Type: String }

MetricsTargetGroupFullName: { Type: String }

NetworksPublicWebTargetGroupFullName: { Type: String }
Expand Down Expand Up @@ -174,6 +176,7 @@ Resources:
[ "AWS/ApiGateway", "Count", "ApiId", "${FeederAuthProxyApiId}", { "label": "Feeder Auth Proxy" } ],
[ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${IdTargetGroupFullName}", "LoadBalancer", "${SharedAlbFullName}", { "label": "ID" } ],
[ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${IframelyTargetGroupFullName}", "LoadBalancer", "${SharedAlbFullName}", { "label": "Iframely" } ],
[ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${InsightsWebTargetGroupFullName}", "LoadBalancer", "${SharedAlbFullName}", { "label": "Dovetail Insights" } ],
[ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${MetricsTargetGroupFullName}", "LoadBalancer", "${SharedAlbFullName}", { "label": "Metrics" } ],
[ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${NetworksPublicWebTargetGroupFullName}", "LoadBalancer", "${SharedAlbFullName}", { "label": "Networks" } ],
[ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${PlayWebTargetGroupFullName}", "LoadBalancer", "${SharedAlbFullName}", { "label": "Play::Web" } ],
Expand Down
5 changes: 5 additions & 0 deletions spire/templates/root.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Mappings:
Networks: { prefix: 28 }
Remix: { prefix: 29 }
Metrics: { prefix: 36 }
Insights: { prefix: 37 }
TheCount: { prefix: 42 }
TheCastle: { prefix: 50 } # Legacy Castle
Styleguide: { prefix: 65 }
Expand Down Expand Up @@ -825,6 +826,8 @@ Resources:

FeederSharedAlbListenerRulePriorityPrefix: !FindInMap [SharedAlbListenerRulePriorityMap, Feeder, prefix]

InsightsSharedAlbListenerRulePriorityPrefix: !FindInMap [SharedAlbListenerRulePriorityMap, Insights, prefix]

NetworksSharedAlbListenerRulePriorityPrefix: !FindInMap [SharedAlbListenerRulePriorityMap, Networks, prefix]

RemixSharedAlbListenerRulePriorityPrefix: !FindInMap [SharedAlbListenerRulePriorityMap, Remix, prefix]
Expand Down Expand Up @@ -1084,6 +1087,8 @@ Resources:

IframelyTargetGroupFullName: !GetAtt Apps100AStack.Outputs.IframelyTargetGroupFullName

InsightsWebTargetGroupFullName: !GetAtt Apps200AStack.Outputs.InsightsWebTargetGroupFullName

MetricsTargetGroupFullName: !GetAtt Apps300AStack.Outputs.MetricsTargetGroupFullName

NetworksPublicWebTargetGroupFullName: !GetAtt Apps200AStack.Outputs.NetworksPublicWebTargetGroupFullName
Expand Down

0 comments on commit c3d2954

Please sign in to comment.