diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c81666a2457..f101e1e316f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -72,13 +72,6 @@ jobs: rm -r facia-rendering/* mv facia-rendering.tar.gz facia-rendering/ - - name: Compress tag-page-rendering app server files - working-directory: dotcom-rendering/target - run: | - tar -zcf tag-page-rendering.tar.gz tag-page-rendering - rm -r tag-page-rendering/* - mv tag-page-rendering.tar.gz tag-page-rendering/ - - name: Compress interactive-rendering app server files working-directory: dotcom-rendering/target run: | @@ -105,8 +98,6 @@ jobs: - dotcom-rendering/target/facia-rendering tag-page-rendering-cfn: - dotcom-rendering/target/tag-page-rendering-cfn - tag-page-rendering: - - dotcom-rendering/target/tag-page-rendering interactive-rendering-cfn: - dotcom-rendering/target/interactive-rendering-cfn interactive-rendering: diff --git a/dotcom-rendering/cdk/bin/cdk.ts b/dotcom-rendering/cdk/bin/cdk.ts index 0eb589ffdea..87be989429a 100644 --- a/dotcom-rendering/cdk/bin/cdk.ts +++ b/dotcom-rendering/cdk/bin/cdk.ts @@ -29,39 +29,43 @@ new RenderingCDKStack(cdkApp, 'ArticleRendering-CODE', { guApp: 'article-rendering', stage: 'CODE', domainName: 'article-rendering.code.dev-guardianapis.com', - scaling: { minimumInstances: 1, maximumInstances: 3 }, - instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.SMALL), + ec2Props: { + scaling: { minimumInstances: 1, maximumInstances: 3 }, + instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.SMALL), + }, }); new RenderingCDKStack(cdkApp, 'ArticleRendering-PROD', { guApp: 'article-rendering', stage: 'PROD', domainName: 'article-rendering.guardianapis.com', - scaling: { - minimumInstances: 42, - maximumInstances: 240, - policies: { - step: { - cpu: cpuScalingSteps, - latency: { - scalingStepsOut: [ - // When latency is lower than 0.2s no scaling up - { lower: 0, upper: 0.2, change: 0 }, - // When latency is higher than 0.2s we scale up by 50% - { lower: 0.2, change: 50 }, - // When latency is higher than 0.3s we scale up by 80% - { lower: 0.3, change: 80 }, - ], - scalingStepsIn: [ - // When latency is higher than 0.12s no scaling down - { lower: 0.12, change: 0 }, - // When latency is lower than 0.12s we scale down by 1 - { upper: 0.12, lower: 0, change: -1 }, - ], + ec2Props: { + scaling: { + minimumInstances: 42, + maximumInstances: 240, + policies: { + step: { + cpu: cpuScalingSteps, + latency: { + scalingStepsOut: [ + // When latency is lower than 0.2s no scaling up + { lower: 0, upper: 0.2, change: 0 }, + // When latency is higher than 0.2s we scale up by 50% + { lower: 0.2, change: 50 }, + // When latency is higher than 0.3s we scale up by 80% + { lower: 0.3, change: 80 }, + ], + scalingStepsIn: [ + // When latency is higher than 0.12s no scaling down + { lower: 0.12, change: 0 }, + // When latency is lower than 0.12s we scale down by 1 + { upper: 0.12, lower: 0, change: -1 }, + ], + }, }, }, }, + instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), }, - instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), }); /** Facia */ @@ -69,39 +73,43 @@ new RenderingCDKStack(cdkApp, 'FaciaRendering-CODE', { guApp: 'facia-rendering', stage: 'CODE', domainName: 'facia-rendering.code.dev-guardianapis.com', - scaling: { minimumInstances: 1, maximumInstances: 3 }, - instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.SMALL), + ec2Props: { + scaling: { minimumInstances: 1, maximumInstances: 3 }, + instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.SMALL), + }, }); new RenderingCDKStack(cdkApp, 'FaciaRendering-PROD', { guApp: 'facia-rendering', stage: 'PROD', domainName: 'facia-rendering.guardianapis.com', - scaling: { - minimumInstances: 21, - maximumInstances: 210, - policies: { - step: { - cpu: cpuScalingSteps, - latency: { - scalingStepsOut: [ - // When latency is lower than 0.4s no scaling up - { lower: 0, upper: 0.4, change: 0 }, - // When latency is higher than 0.4s we scale up by 50% - { lower: 0.4, change: 50 }, - // When latency is higher than 0.5s we scale up by 80% - { lower: 0.5, change: 80 }, - ], - scalingStepsIn: [ - // When latency is higher than 0.35s no scaling down - { lower: 0.35, change: 0 }, - // When latency is lower than 0.35s we scale down by 1 - { upper: 0.35, lower: 0, change: -1 }, - ], + ec2Props: { + scaling: { + minimumInstances: 21, + maximumInstances: 210, + policies: { + step: { + cpu: cpuScalingSteps, + latency: { + scalingStepsOut: [ + // When latency is lower than 0.4s no scaling up + { lower: 0, upper: 0.4, change: 0 }, + // When latency is higher than 0.4s we scale up by 50% + { lower: 0.4, change: 50 }, + // When latency is higher than 0.5s we scale up by 80% + { lower: 0.5, change: 80 }, + ], + scalingStepsIn: [ + // When latency is higher than 0.35s no scaling down + { lower: 0.35, change: 0 }, + // When latency is lower than 0.35s we scale down by 1 + { upper: 0.35, lower: 0, change: -1 }, + ], + }, }, }, }, + instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), }, - instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), }); /** Tag pages */ @@ -109,8 +117,6 @@ export const TagPageRenderingPropsCODE: RenderingCDKStackProps = { guApp: 'tag-page-rendering', stage: 'CODE', domainName: 'tag-page-rendering.code.dev-guardianapis.com', - scaling: { minimumInstances: 0, maximumInstances: 0 }, - instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.SMALL), ecsProps: { imageIdentifier: getImageIdentifier(), taskCpu: 1024, @@ -143,32 +149,6 @@ export const TagPageRenderingPropsPROD: RenderingCDKStackProps = { guApp: 'tag-page-rendering', stage: 'PROD', domainName: 'tag-page-rendering.guardianapis.com', - scaling: { - minimumInstances: 0, - maximumInstances: 0, - policies: { - step: { - cpu: cpuScalingSteps, - latency: { - scalingStepsOut: [ - // When latency is lower than 0.4s no scaling up - { lower: 0, upper: 0.4, change: 0 }, - // When latency is higher than 0.4s we scale up by 50% - { lower: 0.4, change: 50 }, - // When latency is higher than 0.5s we scale up by 80% - { lower: 0.5, change: 80 }, - ], - scalingStepsIn: [ - // When latency is higher than 0.35s no scaling down - { lower: 0.35, change: 0 }, - // When latency is lower than 0.35s we scale down by 1 - { upper: 0.35, lower: 0, change: -1 }, - ], - }, - }, - }, - }, - instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), ecsProps: { imageIdentifier: getImageIdentifier(), taskCpu: 1024, @@ -203,8 +183,10 @@ export const InteractiveRenderingPropsCODE: RenderingCDKStackProps = { guApp: 'interactive-rendering', stage: 'CODE', domainName: 'interactive-rendering.code.dev-guardianapis.com', - scaling: { minimumInstances: 1, maximumInstances: 3 }, - instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO), + ec2Props: { + scaling: { minimumInstances: 1, maximumInstances: 3 }, + instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO), + }, ecsProps: { imageIdentifier: getImageIdentifier(), taskCpu: 1024, @@ -239,32 +221,34 @@ export const InteractiveRenderingPropsPROD: RenderingCDKStackProps = { guApp: 'interactive-rendering', stage: 'PROD', domainName: 'interactive-rendering.guardianapis.com', - scaling: { - minimumInstances: 3, - maximumInstances: 30, - policies: { - step: { - cpu: cpuScalingSteps, - latency: { - scalingStepsOut: [ - // When latency is lower than 0.2s no scaling up - { lower: 0, upper: 0.2, change: 0 }, - // When latency is higher than 0.2s we scale up by 50% - { lower: 0.2, change: 50 }, - // When latency is higher than 0.3s we scale up by 80% - { lower: 0.3, change: 80 }, - ], - scalingStepsIn: [ - // When latency is higher than 0.15s no scaling down - { lower: 0.15, change: 0 }, - // When latency is lower than 0.15s we scale down by 1 - { upper: 0.15, lower: 0, change: -1 }, - ], + ec2Props: { + scaling: { + minimumInstances: 3, + maximumInstances: 30, + policies: { + step: { + cpu: cpuScalingSteps, + latency: { + scalingStepsOut: [ + // When latency is lower than 0.2s no scaling up + { lower: 0, upper: 0.2, change: 0 }, + // When latency is higher than 0.2s we scale up by 50% + { lower: 0.2, change: 50 }, + // When latency is higher than 0.3s we scale up by 80% + { lower: 0.3, change: 80 }, + ], + scalingStepsIn: [ + // When latency is higher than 0.15s no scaling down + { lower: 0.15, change: 0 }, + // When latency is lower than 0.15s we scale down by 1 + { upper: 0.15, lower: 0, change: -1 }, + ], + }, }, }, }, + instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), }, - instanceType: InstanceType.of(InstanceClass.C8G, InstanceSize.MEDIUM), }; new RenderingCDKStack( cdkApp, diff --git a/dotcom-rendering/cdk/lib/__snapshots__/renderingStack.test.ts.snap b/dotcom-rendering/cdk/lib/__snapshots__/renderingStack.test.ts.snap index 9ecd4709371..b2bd3abd366 100644 --- a/dotcom-rendering/cdk/lib/__snapshots__/renderingStack.test.ts.snap +++ b/dotcom-rendering/cdk/lib/__snapshots__/renderingStack.test.ts.snap @@ -5410,7 +5410,7 @@ systemctl start interactive-rendering", } `; -exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE (uses ECS) 1`] = ` +exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE 1`] = ` { "Metadata": { "gu:cdk:constructs": [ @@ -5422,18 +5422,10 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE "GuSubnetListParameter", "GuSubnetListParameter", "GuLoadBalancedAppExperimental", - "GuInstanceRole", - "GuSsmSshPolicy", - "GuDescribeEC2Policy", "GuLoggingStreamNameParameter", + "GuRiffRaffDeploymentIdParameterExperimental", "GuLogShippingPolicy", - "GuGetDistributablePolicy", "GuParameterStoreReadPolicy", - "GuAmiParameter", - "GuHttpsEgressSecurityGroup", - "GuAutoScalingGroup", - "GuApplicationTargetGroup", - "GuRiffRaffDeploymentIdParameterExperimental", "GuHttpsEgressSecurityGroup", "GuApplicationTargetGroup", "GuCertificate", @@ -5457,10 +5449,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, }, "Parameters": { - "AMITagpagerendering": { - "Description": "Amazon Machine Image ID for the app tag-page-rendering. Use this in conjunction with AMIgo to keep AMIs up to date.", - "Type": "AWS::EC2::Image::Id", - }, "AccessLoggingBucket": { "Default": "/account/services/access-logging/bucket", "Description": "S3 bucket to store your access logs", @@ -5518,9 +5506,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "PolicyName": "AllowPolicyCloudwatchLogsA783E5B4", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -5556,9 +5541,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "PolicyName": "AllowPolicyDescribeDecryptKmsE91286F3", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -5608,9 +5590,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "PolicyName": "AllowPolicyGetSsmParamsByPathB54B2DE8", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -5618,78 +5597,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::IAM::Policy", }, - "AutoScalingGroupTagpagerenderingASG7F7E0748": { - "Properties": { - "HealthCheckGracePeriod": 120, - "HealthCheckType": "ELB", - "LaunchTemplate": { - "LaunchTemplateId": { - "Ref": "frontendCODEtagpagerendering3C218821", - }, - "Version": { - "Fn::GetAtt": [ - "frontendCODEtagpagerendering3C218821", - "LatestVersionNumber", - ], - }, - }, - "MaxSize": "0", - "MetricsCollection": [ - { - "Granularity": "1Minute", - }, - ], - "MinSize": "0", - "Tags": [ - { - "Key": "App", - "PropagateAtLaunch": true, - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "PropagateAtLaunch": true, - "Value": "TEST", - }, - { - "Key": "gu:repo", - "PropagateAtLaunch": true, - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "LogKinesisStreamName", - "PropagateAtLaunch": true, - "Value": { - "Ref": "LoggingStreamName", - }, - }, - { - "Key": "Stack", - "PropagateAtLaunch": true, - "Value": "frontend", - }, - { - "Key": "Stage", - "PropagateAtLaunch": true, - "Value": "CODE", - }, - { - "Key": "SystemdUnit", - "PropagateAtLaunch": true, - "Value": "tag-page-rendering.service", - }, - ], - "TargetGroupARNs": [ - { - "Ref": "TargetGroupTagpagerendering42E428EE", - }, - ], - "VPCZoneIdentifier": { - "Ref": "tagpagerenderingPrivateSubnets", - }, - }, - "Type": "AWS::AutoScaling::AutoScalingGroup", - }, "CertificateTagpagerendering5182FE63": { "DeletionPolicy": "Retain", "Properties": { @@ -5725,38 +5632,10 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE "Type": "AWS::CertificateManager::Certificate", "UpdateReplacePolicy": "Retain", }, - "DescribeEC2PolicyFF5F9295": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "autoscaling:DescribeAutoScalingInstances", - "autoscaling:DescribeAutoScalingGroups", - "ec2:DescribeTags", - "ec2:DescribeInstances", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "describe-ec2-policy", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "EcsService81FC6EF6": { "DependsOn": [ "EcsTaskDefinitionTaskRoleDefaultPolicy1FD2F057", "EcsTaskDefinitionTaskRoleB7B6D8DD", - "ListenerTagpagerenderingDeterministicRouteToEc2Rule1C5C95A4", - "ListenerTagpagerenderingDeterministicRouteToEcsRuleAB05C756", "ListenerTagpagerendering92E57078", ], "Properties": { @@ -6356,78 +6235,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::IAM::Policy", }, - "GetDistributablePolicyTagpagerendering346128E3": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "s3:GetObject", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "DistributionBucketName", - }, - "/frontend/CODE/tag-page-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GetDistributablePolicyTagpagerendering346128E3", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE": { - "Properties": { - "GroupDescription": "Allow all outbound HTTPS traffic", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound HTTPS traffic", - "FromPort": 443, - "IpProtocol": "tcp", - "ToPort": 443, - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, "GuHttpsEgressSecurityGroupTagpagerenderingecsF0505C36": { "Properties": { "GroupDescription": "Allow all outbound HTTPS traffic", @@ -6510,48 +6317,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::EC2::SecurityGroupIngress", }, - "GuHttpsEgressSecurityGroupTagpagerenderingfromTagPageRenderingCODEInternalIngressSecurityGroupTagpagerendering0B98E4F9900035DE48AC": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupTagpagerendering38FD16DB", - "GroupId", - ], - }, - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuHttpsEgressSecurityGroupTagpagerenderingfromTagPageRenderingCODELoadBalancerTagpagerenderingSecurityGroup301E895290002304A373": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingSecurityGroup4D481A16", - "GroupId", - ], - }, - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, "GuLogShippingPolicy981BFE5A": { "Properties": { "PolicyDocument": { @@ -6583,9 +6348,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "PolicyName": "GuLogShippingPolicy981BFE5A", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -6593,46 +6355,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::IAM::Policy", }, - "InstanceRoleTagpagerendering171BC2F9": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "ec2.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "Path": "/", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - "Type": "AWS::IAM::Role", - }, "InternalIngressSecurityGroupTagpagerendering38FD16DB": { "Properties": { "GroupDescription": "Allow restricted ingress from CIDR ranges", @@ -6673,33 +6395,12 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::EC2::SecurityGroup", }, - "InternalIngressSecurityGroupTagpagerenderingtoTagPageRenderingCODEGuHttpsEgressSecurityGroupTagpagerendering51E7AF3890004F95C890": { + "InternalIngressSecurityGroupTagpagerenderingtoTagPageRenderingCODEGuHttpsEgressSecurityGroupTagpagerenderingecsBADC1D1E900094544771": { "Properties": { "Description": "Load balancer to target", "DestinationSecurityGroupId": { "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupTagpagerendering38FD16DB", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "InternalIngressSecurityGroupTagpagerenderingtoTagPageRenderingCODEGuHttpsEgressSecurityGroupTagpagerenderingecsBADC1D1E900094544771": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingecsF0505C36", + "GuHttpsEgressSecurityGroupTagpagerenderingecsF0505C36", "GroupId", ], }, @@ -6726,21 +6427,8 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE ], "DefaultActions": [ { - "ForwardConfig": { - "TargetGroups": [ - { - "TargetGroupArn": { - "Ref": "TargetGroupTagpagerendering42E428EE", - }, - "Weight": 0, - }, - { - "TargetGroupArn": { - "Ref": "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5", - }, - "Weight": 1, - }, - ], + "TargetGroupArn": { + "Ref": "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5", }, "Type": "forward", }, @@ -6776,106 +6464,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::ElasticLoadBalancingV2::Listener", }, - "ListenerTagpagerenderingDeterministicRouteToEc2Rule1C5C95A4": { - "Properties": { - "Actions": [ - { - "TargetGroupArn": { - "Ref": "TargetGroupTagpagerendering42E428EE", - }, - "Type": "forward", - }, - ], - "Conditions": [ - { - "Field": "http-header", - "HttpHeaderConfig": { - "HttpHeaderName": "X-Gu-Target-Group", - "Values": [ - "ec2", - ], - }, - }, - ], - "ListenerArn": { - "Ref": "ListenerTagpagerendering92E57078", - }, - "Priority": 10, - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - }, - "ListenerTagpagerenderingDeterministicRouteToEcsRuleAB05C756": { - "Properties": { - "Actions": [ - { - "TargetGroupArn": { - "Ref": "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5", - }, - "Type": "forward", - }, - ], - "Conditions": [ - { - "Field": "http-header", - "HttpHeaderConfig": { - "HttpHeaderName": "X-Gu-Target-Group", - "Values": [ - "ecs", - ], - }, - }, - ], - "ListenerArn": { - "Ref": "ListenerTagpagerendering92E57078", - }, - "Priority": 11, - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - }, "LoadBalancerDNS": { "Properties": { "Name": "tag-page-rendering.code.dev-guardianapis.com", @@ -7002,27 +6590,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::EC2::SecurityGroup", }, - "LoadBalancerTagpagerenderingSecurityGrouptoTagPageRenderingCODEGuHttpsEgressSecurityGroupTagpagerendering51E7AF38900020A4AE4F": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingSecurityGroup4D481A16", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, "LoadBalancerTagpagerenderingSecurityGrouptoTagPageRenderingCODEGuHttpsEgressSecurityGroupTagpagerenderingecsBADC1D1E900047DE752F": { "Properties": { "Description": "Load balancer to target", @@ -7088,9 +6655,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "PolicyName": "parameter-store-read-policy", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -7114,42 +6678,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::SSM::Parameter", }, - "SsmSshPolicy4CFC977E": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ec2messages:AcknowledgeMessage", - "ec2messages:DeleteMessage", - "ec2messages:FailMessage", - "ec2messages:GetEndpoint", - "ec2messages:GetMessages", - "ec2messages:SendReply", - "ssm:UpdateInstanceInformation", - "ssm:ListInstanceAssociations", - "ssm:DescribeInstanceProperties", - "ssm:DescribeDocumentParameters", - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "ssm-ssh-policy", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5": { "Properties": { "HealthCheckIntervalSeconds": 10, @@ -7199,15 +6727,32 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE }, "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", }, - "TargetGroupTagpagerendering42E428EE": { + "tagpagerenderingCpuScaling1742C101": { "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckPath": "/_healthcheck", - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 5, - "Port": 9000, - "Protocol": "HTTP", + "PolicyName": "TagPageRenderingCODEtagpagerenderingCpuScalingAFEBC723", + "PolicyType": "TargetTrackingScaling", + "ScalingTargetId": { + "Ref": "EcsServiceTaskCountTarget02FCCE22", + }, + "TargetTrackingScalingPolicyConfiguration": { + "PredefinedMetricSpecification": { + "PredefinedMetricType": "ECSServiceAverageCPUUtilizationHighResolution", + }, + "ScaleInCooldown": 60, + "ScaleOutCooldown": 60, + "TargetValue": 20, + }, + }, + "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", + }, + "tagpagerenderingEcsClusterE7696595": { + "Properties": { + "ClusterSettings": [ + { + "Name": "containerInsights", + "Value": "enhanced", + }, + ], "Tags": [ { "Key": "App", @@ -7230,265 +6775,14 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering CODE "Value": "CODE", }, ], - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "30", - }, - { - "Key": "stickiness.enabled", - "Value": "false", - }, - ], - "TargetType": "instance", - "UnhealthyThresholdCount": 2, - "VpcId": { - "Ref": "VpcId", - }, }, - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - }, - "frontendCODEtagpagerendering3C218821": { - "DependsOn": [ - "InstanceRoleTagpagerendering171BC2F9", - ], - "Properties": { - "LaunchTemplateData": { - "IamInstanceProfile": { - "Arn": { - "Fn::GetAtt": [ - "frontendCODEtagpagerenderingProfile70961F87", - "Arn", - ], - }, - }, - "ImageId": { - "Ref": "AMITagpagerendering", - }, - "InstanceType": "t4g.small", - "MetadataOptions": { - "HttpTokens": "required", - "InstanceMetadataTags": "enabled", - }, - "Monitoring": { - "Enabled": true, - }, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - ], - "TagSpecifications": [ - { - "ResourceType": "instance", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-CODE/frontend-CODE-tag-page-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - { - "ResourceType": "volume", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-CODE/frontend-CODE-tag-page-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - ], - "UserData": { - "Fn::Base64": { - "Fn::Join": [ - "", - [ - "#!/bin/bash -set -ev -groupadd frontend -useradd -r -m -s /usr/bin/nologin -g frontend dotcom-rendering -cd /home/dotcom-rendering -aws --region eu-west-1 s3 cp s3://", - { - "Ref": "DistributionBucketName", - }, - "/frontend/CODE/tag-page-rendering/tag-page-rendering.tar.gz ./ -tar -zxf tag-page-rendering.tar.gz tag-page-rendering -chown -R dotcom-rendering:frontend tag-page-rendering -cd tag-page-rendering -mkdir /var/log/dotcom-rendering -chown -R dotcom-rendering:frontend /var/log/dotcom-rendering -cat > /etc/systemd/system/tag-page-rendering.service << EOF -[Unit] -Description=tag-page-rendering -After=network.target -[Service] -WorkingDirectory=/home/dotcom-rendering/tag-page-rendering -Type=simple -User=dotcom-rendering -Group=frontend -StandardError=journal -StandardOutput=journal -Environment=TERM=xterm-256color -Environment=NODE_ENV=production -Environment=GU_STAGE=CODE -Environment=GU_APP=tag-page-rendering -Environment=GU_STACK=frontend -ExecStart=make prod -Restart=on-failure -[Install] -WantedBy=multi-user.target -EOF -systemctl enable tag-page-rendering -systemctl start tag-page-rendering", - ], - ], - }, - }, - }, - "TagSpecifications": [ - { - "ResourceType": "launch-template", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-CODE/frontend-CODE-tag-page-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - ], - }, - "Type": "AWS::EC2::LaunchTemplate", - }, - "frontendCODEtagpagerenderingProfile70961F87": { - "Properties": { - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::InstanceProfile", - }, - "tagpagerenderingCpuScaling1742C101": { - "Properties": { - "PolicyName": "TagPageRenderingCODEtagpagerenderingCpuScalingAFEBC723", - "PolicyType": "TargetTrackingScaling", - "ScalingTargetId": { - "Ref": "EcsServiceTaskCountTarget02FCCE22", - }, - "TargetTrackingScalingPolicyConfiguration": { - "PredefinedMetricSpecification": { - "PredefinedMetricType": "ECSServiceAverageCPUUtilizationHighResolution", - }, - "ScaleInCooldown": 60, - "ScaleOutCooldown": 60, - "TargetValue": 20, - }, - }, - "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", - }, - "tagpagerenderingEcsClusterE7696595": { - "Properties": { - "ClusterSettings": [ - { - "Name": "containerInsights", - "Value": "enhanced", - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "CODE", - }, - ], - }, - "Type": "AWS::ECS::Cluster", + "Type": "AWS::ECS::Cluster", }, }, } `; -exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD (now using ECS) 1`] = ` +exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD 1`] = ` { "Metadata": { "gu:cdk:constructs": [ @@ -7500,18 +6794,10 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD "GuSubnetListParameter", "GuSubnetListParameter", "GuLoadBalancedAppExperimental", - "GuInstanceRole", - "GuSsmSshPolicy", - "GuDescribeEC2Policy", "GuLoggingStreamNameParameter", + "GuRiffRaffDeploymentIdParameterExperimental", "GuLogShippingPolicy", - "GuGetDistributablePolicy", "GuParameterStoreReadPolicy", - "GuAmiParameter", - "GuHttpsEgressSecurityGroup", - "GuAutoScalingGroup", - "GuApplicationTargetGroup", - "GuRiffRaffDeploymentIdParameterExperimental", "GuHttpsEgressSecurityGroup", "GuApplicationTargetGroup", "GuCertificate", @@ -7520,7 +6806,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD "GuHttpsApplicationListener", "GuSecurityGroup", "GuAlb5xxPercentageAlarm", - "GuUnhealthyInstancesAlarm", "GuCname", ], "gu:cdk:version": "TEST", @@ -7537,10 +6822,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, }, "Parameters": { - "AMITagpagerendering": { - "Description": "Amazon Machine Image ID for the app tag-page-rendering. Use this in conjunction with AMIgo to keep AMIs up to date.", - "Type": "AWS::EC2::Image::Id", - }, "AccessLoggingBucket": { "Default": "/account/services/access-logging/bucket", "Description": "S3 bucket to store your access logs", @@ -7598,9 +6879,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "PolicyName": "AllowPolicyCloudwatchLogsA783E5B4", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -7636,9 +6914,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "PolicyName": "AllowPolicyDescribeDecryptKmsE91286F3", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -7688,9 +6963,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "PolicyName": "AllowPolicyGetSsmParamsByPathB54B2DE8", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -7698,256 +6970,45 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::IAM::Policy", }, - "AutoScalingGroupTagpagerenderingASG7F7E0748": { + "CertificateTagpagerendering5182FE63": { + "DeletionPolicy": "Retain", "Properties": { - "HealthCheckGracePeriod": 120, - "HealthCheckType": "ELB", - "LaunchTemplate": { - "LaunchTemplateId": { - "Ref": "frontendPRODtagpagerenderingA0B91C45", - }, - "Version": { - "Fn::GetAtt": [ - "frontendPRODtagpagerenderingA0B91C45", - "LatestVersionNumber", - ], - }, - }, - "MaxSize": "0", - "MetricsCollection": [ - { - "Granularity": "1Minute", - }, - ], - "MinSize": "0", + "DomainName": "tag-page-rendering.guardianapis.com", "Tags": [ { "Key": "App", - "PropagateAtLaunch": true, "Value": "tag-page-rendering", }, { "Key": "gu:cdk:version", - "PropagateAtLaunch": true, "Value": "TEST", }, { "Key": "gu:repo", - "PropagateAtLaunch": true, "Value": "guardian/dotcom-rendering", }, { - "Key": "LogKinesisStreamName", - "PropagateAtLaunch": true, - "Value": { - "Ref": "LoggingStreamName", - }, + "Key": "Name", + "Value": "TagPageRendering-PROD/CertificateTagpagerendering", }, { "Key": "Stack", - "PropagateAtLaunch": true, "Value": "frontend", }, { "Key": "Stage", - "PropagateAtLaunch": true, "Value": "PROD", }, - { - "Key": "SystemdUnit", - "PropagateAtLaunch": true, - "Value": "tag-page-rendering.service", - }, - ], - "TargetGroupARNs": [ - { - "Ref": "TargetGroupTagpagerendering42E428EE", - }, ], - "VPCZoneIdentifier": { - "Ref": "tagpagerenderingPrivateSubnets", - }, - }, - "Type": "AWS::AutoScaling::AutoScalingGroup", - }, - "CPUScaleUpPolicyUpperAlarm7E15DD91": { - "Properties": { - "AlarmActions": [ - { - "Ref": "CPUScaleUpPolicyUpperPolicyDEE5DA77", - }, - { - "Ref": "CPUScalingAlertsTopic9D0083F7", - }, - ], - "AlarmDescription": "Upper threshold scaling alarm", - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "Dimensions": [ - { - "Name": "AutoScalingGroupName", - "Value": { - "Ref": "AutoScalingGroupTagpagerenderingASG7F7E0748", - }, - }, - ], - "EvaluationPeriods": 2, - "ExtendedStatistic": "p90", - "MetricName": "CPUUtilization", - "Namespace": "AWS/EC2", - "Period": 30, - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "Threshold": 60, - "Unit": "Percent", - }, - "Type": "AWS::CloudWatch::Alarm", - }, - "CPUScaleUpPolicyUpperPolicyDEE5DA77": { - "Properties": { - "AdjustmentType": "PercentChangeInCapacity", - "AutoScalingGroupName": { - "Ref": "AutoScalingGroupTagpagerenderingASG7F7E0748", - }, - "MetricAggregationType": "Average", - "PolicyType": "StepScaling", - "StepAdjustments": [ - { - "MetricIntervalLowerBound": 0, - "MetricIntervalUpperBound": 20, - "ScalingAdjustment": 50, - }, - { - "MetricIntervalLowerBound": 20, - "ScalingAdjustment": 80, - }, - ], - }, - "Type": "AWS::AutoScaling::ScalingPolicy", - }, - "CPUScalingAlertsSubscriptionEmail170D6D82": { - "Properties": { - "Endpoint": "dotcom.platform@theguardian.com", - "Protocol": "email", - "TopicArn": { - "Ref": "CPUScalingAlertsTopic9D0083F7", - }, - }, - "Type": "AWS::SNS::Subscription", - }, - "CPUScalingAlertsTopic9D0083F7": { - "Properties": { - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - }, - "Type": "AWS::SNS::Topic", - }, - "CertificateTagpagerendering5182FE63": { - "DeletionPolicy": "Retain", - "Properties": { - "DomainName": "tag-page-rendering.guardianapis.com", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-PROD/CertificateTagpagerendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "ValidationMethod": "DNS", + "ValidationMethod": "DNS", }, "Type": "AWS::CertificateManager::Certificate", "UpdateReplacePolicy": "Retain", }, - "DescribeEC2PolicyFF5F9295": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "autoscaling:DescribeAutoScalingInstances", - "autoscaling:DescribeAutoScalingGroups", - "ec2:DescribeTags", - "ec2:DescribeInstances", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "describe-ec2-policy", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "EcsService81FC6EF6": { "DependsOn": [ "EcsTaskDefinitionTaskRoleDefaultPolicy1FD2F057", "EcsTaskDefinitionTaskRoleB7B6D8DD", - "ListenerTagpagerenderingDeterministicRouteToEc2Rule1C5C95A4", - "ListenerTagpagerenderingDeterministicRouteToEcsRuleAB05C756", "ListenerTagpagerendering92E57078", ], "Properties": { @@ -8547,78 +7608,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::IAM::Policy", }, - "GetDistributablePolicyTagpagerendering346128E3": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "s3:GetObject", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "DistributionBucketName", - }, - "/frontend/PROD/tag-page-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GetDistributablePolicyTagpagerendering346128E3", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE": { - "Properties": { - "GroupDescription": "Allow all outbound HTTPS traffic", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound HTTPS traffic", - "FromPort": 443, - "IpProtocol": "tcp", - "ToPort": 443, - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, "GuHttpsEgressSecurityGroupTagpagerenderingecsF0505C36": { "Properties": { "GroupDescription": "Allow all outbound HTTPS traffic", @@ -8701,49 +7690,7 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::EC2::SecurityGroupIngress", }, - "GuHttpsEgressSecurityGroupTagpagerenderingfromTagPageRenderingPRODInternalIngressSecurityGroupTagpagerendering1CF134899000DECEA4B2": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupTagpagerendering38FD16DB", - "GroupId", - ], - }, - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuHttpsEgressSecurityGroupTagpagerenderingfromTagPageRenderingPRODLoadBalancerTagpagerenderingSecurityGroup55D2582D90005A0A2694": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingSecurityGroup4D481A16", - "GroupId", - ], - }, - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuLogShippingPolicy981BFE5A": { + "GuLogShippingPolicy981BFE5A": { "Properties": { "PolicyDocument": { "Statement": [ @@ -8774,9 +7721,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "PolicyName": "GuLogShippingPolicy981BFE5A", "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, { "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, @@ -8909,46 +7853,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::CloudWatch::Alarm", }, - "InstanceRoleTagpagerendering171BC2F9": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "ec2.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "Path": "/", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - }, - "Type": "AWS::IAM::Role", - }, "InternalIngressSecurityGroupTagpagerendering38FD16DB": { "Properties": { "GroupDescription": "Allow restricted ingress from CIDR ranges", @@ -8989,27 +7893,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::EC2::SecurityGroup", }, - "InternalIngressSecurityGroupTagpagerenderingtoTagPageRenderingPRODGuHttpsEgressSecurityGroupTagpagerendering55A86AD190001055A384": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupTagpagerendering38FD16DB", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, "InternalIngressSecurityGroupTagpagerenderingtoTagPageRenderingPRODGuHttpsEgressSecurityGroupTagpagerenderingecs7BD0DC4E9000C0C61B8C": { "Properties": { "Description": "Load balancer to target", @@ -9031,40 +7914,29 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::EC2::SecurityGroupEgress", }, - "LatencyScaleDownPolicyLowerAlarm3AAA79CF": { + "ListenerTagpagerendering92E57078": { "Properties": { - "AlarmActions": [ - { - "Ref": "LatencyScaleDownPolicyLowerPolicy5B8C5A01", - }, - ], - "AlarmDescription": "Lower threshold scaling alarm", - "ComparisonOperator": "LessThanOrEqualToThreshold", - "Dimensions": [ + "Certificates": [ { - "Name": "LoadBalancer", - "Value": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingB0B7AC4E", - "LoadBalancerFullName", - ], + "CertificateArn": { + "Ref": "CertificateTagpagerendering5182FE63", }, }, + ], + "DefaultActions": [ { - "Name": "TargetGroup", - "Value": { - "Fn::GetAtt": [ - "TargetGroupTagpagerendering42E428EE", - "TargetGroupFullName", - ], + "TargetGroupArn": { + "Ref": "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5", }, + "Type": "forward", }, ], - "EvaluationPeriods": 10, - "MetricName": "TargetResponseTime", - "Namespace": "AWS/ApplicationELB", - "Period": 30, - "Statistic": "Average", + "LoadBalancerArn": { + "Ref": "LoadBalancerTagpagerenderingB0B7AC4E", + }, + "Port": 443, + "Protocol": "HTTPS", + "SslPolicy": "ELBSecurityPolicy-TLS13-1-2-2021-06", "Tags": [ { "Key": "App", @@ -9087,64 +7959,78 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD "Value": "PROD", }, ], - "Threshold": 0.35, }, - "Type": "AWS::CloudWatch::Alarm", + "Type": "AWS::ElasticLoadBalancingV2::Listener", }, - "LatencyScaleDownPolicyLowerPolicy5B8C5A01": { + "LoadBalancerDNS": { "Properties": { - "AdjustmentType": "ChangeInCapacity", - "AutoScalingGroupName": { - "Ref": "AutoScalingGroupTagpagerenderingASG7F7E0748", - }, - "MetricAggregationType": "Average", - "PolicyType": "StepScaling", - "StepAdjustments": [ + "Name": "tag-page-rendering.guardianapis.com", + "RecordType": "CNAME", + "ResourceRecords": [ { - "MetricIntervalUpperBound": 0, - "ScalingAdjustment": -1, + "Fn::GetAtt": [ + "LoadBalancerTagpagerenderingB0B7AC4E", + "DNSName", + ], }, ], + "Stage": "PROD", + "TTL": 3600, }, - "Type": "AWS::AutoScaling::ScalingPolicy", + "Type": "Guardian::DNS::RecordSet", }, - "LatencyScaleUpPolicyUpperAlarmB2CCE62D": { + "LoadBalancerTagpagerenderingB0B7AC4E": { "Properties": { - "AlarmActions": [ + "LoadBalancerAttributes": [ { - "Ref": "LatencyScaleUpPolicyUpperPolicy4A22B34C", + "Key": "deletion_protection.enabled", + "Value": "true", }, { - "Ref": "LatencyScalingAlertsTopic1A322157", + "Key": "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", + "Value": "true", }, - ], - "AlarmDescription": "Upper threshold scaling alarm", - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "Dimensions": [ { - "Name": "LoadBalancer", - "Value": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingB0B7AC4E", - "LoadBalancerFullName", - ], - }, + "Key": "routing.http.drop_invalid_header_fields.enabled", + "Value": "true", }, { - "Name": "TargetGroup", + "Key": "access_logs.s3.enabled", + "Value": "true", + }, + { + "Key": "access_logs.s3.bucket", "Value": { - "Fn::GetAtt": [ - "TargetGroupTagpagerendering42E428EE", - "TargetGroupFullName", - ], + "Ref": "AccessLoggingBucket", }, }, + { + "Key": "access_logs.s3.prefix", + "Value": "application-load-balancer/PROD/frontend/tag-page-rendering", + }, + { + "Key": "idle_timeout.timeout_seconds", + "Value": "4", + }, ], - "EvaluationPeriods": 2, - "MetricName": "TargetResponseTime", - "Namespace": "AWS/ApplicationELB", - "Period": 30, - "Statistic": "Average", + "Scheme": "internal", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "LoadBalancerTagpagerenderingSecurityGroup4D481A16", + "GroupId", + ], + }, + { + "Fn::GetAtt": [ + "InternalIngressSecurityGroupTagpagerendering38FD16DB", + "GroupId", + ], + }, + ], + "Subnets": { + "Ref": "tagpagerenderingPrivateSubnets", + }, "Tags": [ { "Key": "App", @@ -9167,44 +8053,13 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD "Value": "PROD", }, ], - "Threshold": 0.4, - }, - "Type": "AWS::CloudWatch::Alarm", - }, - "LatencyScaleUpPolicyUpperPolicy4A22B34C": { - "Properties": { - "AdjustmentType": "PercentChangeInCapacity", - "AutoScalingGroupName": { - "Ref": "AutoScalingGroupTagpagerenderingASG7F7E0748", - }, - "MetricAggregationType": "Average", - "PolicyType": "StepScaling", - "StepAdjustments": [ - { - "MetricIntervalLowerBound": 0, - "MetricIntervalUpperBound": 0.09999999999999998, - "ScalingAdjustment": 50, - }, - { - "MetricIntervalLowerBound": 0.09999999999999998, - "ScalingAdjustment": 80, - }, - ], - }, - "Type": "AWS::AutoScaling::ScalingPolicy", - }, - "LatencyScalingAlertsSubscriptionEmailF1826DAB": { - "Properties": { - "Endpoint": "dotcom.platform@theguardian.com", - "Protocol": "email", - "TopicArn": { - "Ref": "LatencyScalingAlertsTopic1A322157", - }, + "Type": "application", }, - "Type": "AWS::SNS::Subscription", + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", }, - "LatencyScalingAlertsTopic1A322157": { + "LoadBalancerTagpagerenderingSecurityGroup4D481A16": { "Properties": { + "GroupDescription": "Automatically created Security Group for ELB TagPageRenderingPRODLoadBalancerTagpagerenderingF63F513E", "Tags": [ { "Key": "App", @@ -9227,145 +8082,109 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD "Value": "PROD", }, ], + "VpcId": { + "Ref": "VpcId", + }, }, - "Type": "AWS::SNS::Topic", + "Type": "AWS::EC2::SecurityGroup", }, - "ListenerTagpagerendering92E57078": { + "LoadBalancerTagpagerenderingSecurityGrouptoTagPageRenderingPRODGuHttpsEgressSecurityGroupTagpagerenderingecs7BD0DC4E9000E1B35F77": { "Properties": { - "Certificates": [ - { - "CertificateArn": { - "Ref": "CertificateTagpagerendering5182FE63", - }, - }, - ], - "DefaultActions": [ - { - "ForwardConfig": { - "TargetGroups": [ - { - "TargetGroupArn": { - "Ref": "TargetGroupTagpagerendering42E428EE", - }, - "Weight": 0, - }, - { - "TargetGroupArn": { - "Ref": "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5", - }, - "Weight": 1, - }, - ], - }, - "Type": "forward", - }, - ], - "LoadBalancerArn": { - "Ref": "LoadBalancerTagpagerenderingB0B7AC4E", + "Description": "Load balancer to target", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "GuHttpsEgressSecurityGroupTagpagerenderingecsF0505C36", + "GroupId", + ], }, - "Port": 443, - "Protocol": "HTTPS", - "SslPolicy": "ELBSecurityPolicy-TLS13-1-2-2021-06", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], + "FromPort": 9000, + "GroupId": { + "Fn::GetAtt": [ + "LoadBalancerTagpagerenderingSecurityGroup4D481A16", + "GroupId", + ], + }, + "IpProtocol": "tcp", + "ToPort": 9000, }, - "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Type": "AWS::EC2::SecurityGroupEgress", }, - "ListenerTagpagerenderingDeterministicRouteToEc2Rule1C5C95A4": { + "ParameterStoreReadTagpagerendering4CA7B6E3": { "Properties": { - "Actions": [ - { - "TargetGroupArn": { - "Ref": "TargetGroupTagpagerendering42E428EE", + "PolicyDocument": { + "Statement": [ + { + "Action": "ssm:GetParametersByPath", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:ssm:eu-west-1:", + { + "Ref": "AWS::AccountId", + }, + ":parameter/PROD/frontend/tag-page-rendering", + ], + ], + }, }, - "Type": "forward", - }, - ], - "Conditions": [ - { - "Field": "http-header", - "HttpHeaderConfig": { - "HttpHeaderName": "X-Gu-Target-Group", - "Values": [ - "ec2", + { + "Action": [ + "ssm:GetParameters", + "ssm:GetParameter", ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:ssm:eu-west-1:", + { + "Ref": "AWS::AccountId", + }, + ":parameter/PROD/frontend/tag-page-rendering/*", + ], + ], + }, }, - }, - ], - "ListenerArn": { - "Ref": "ListenerTagpagerendering92E57078", + ], + "Version": "2012-10-17", }, - "Priority": 10, - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, + "PolicyName": "parameter-store-read-policy", + "Roles": [ { - "Key": "Stage", - "Value": "PROD", + "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", }, ], }, - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", + "Type": "AWS::IAM::Policy", }, - "ListenerTagpagerenderingDeterministicRouteToEcsRuleAB05C756": { + "RenderingBaseURLParamAE11E777": { "Properties": { - "Actions": [ - { - "TargetGroupArn": { - "Ref": "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5", - }, - "Type": "forward", - }, - ], - "Conditions": [ - { - "Field": "http-header", - "HttpHeaderConfig": { - "HttpHeaderName": "X-Gu-Target-Group", - "Values": [ - "ecs", - ], - }, - }, - ], - "ListenerArn": { - "Ref": "ListenerTagpagerendering92E57078", + "Description": "The rendering base URL for frontend to call the tag-page-rendering app in the PROD environment", + "Name": "/frontend/prod/tag-page-rendering.baseURL", + "Tags": { + "App": "tag-page-rendering", + "Stack": "frontend", + "Stage": "PROD", + "gu:cdk:version": "TEST", + "gu:repo": "guardian/dotcom-rendering", }, - "Priority": 11, + "Type": "String", + "Value": "https://tag-page-rendering.guardianapis.com", + }, + "Type": "AWS::SSM::Parameter", + }, + "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5": { + "Properties": { + "HealthCheckIntervalSeconds": 10, + "HealthCheckPath": "/_healthcheck", + "HealthCheckProtocol": "HTTP", + "HealthCheckTimeoutSeconds": 5, + "HealthyThresholdCount": 5, + "Port": 9000, + "Protocol": "HTTP", "Tags": [ { "Key": "App", @@ -9388,322 +8207,14 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD "Value": "PROD", }, ], - }, - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - }, - "LoadBalancerDNS": { - "Properties": { - "Name": "tag-page-rendering.guardianapis.com", - "RecordType": "CNAME", - "ResourceRecords": [ - { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingB0B7AC4E", - "DNSName", - ], - }, - ], - "Stage": "PROD", - "TTL": 3600, - }, - "Type": "Guardian::DNS::RecordSet", - }, - "LoadBalancerTagpagerenderingB0B7AC4E": { - "Properties": { - "LoadBalancerAttributes": [ - { - "Key": "deletion_protection.enabled", - "Value": "true", - }, - { - "Key": "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", - "Value": "true", - }, - { - "Key": "routing.http.drop_invalid_header_fields.enabled", - "Value": "true", - }, - { - "Key": "access_logs.s3.enabled", - "Value": "true", - }, - { - "Key": "access_logs.s3.bucket", - "Value": { - "Ref": "AccessLoggingBucket", - }, - }, - { - "Key": "access_logs.s3.prefix", - "Value": "application-load-balancer/PROD/frontend/tag-page-rendering", - }, - { - "Key": "idle_timeout.timeout_seconds", - "Value": "4", - }, - ], - "Scheme": "internal", - "SecurityGroups": [ + "TargetGroupAttributes": [ { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingSecurityGroup4D481A16", - "GroupId", - ], + "Key": "deregistration_delay.timeout_seconds", + "Value": "30", }, { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupTagpagerendering38FD16DB", - "GroupId", - ], - }, - ], - "Subnets": { - "Ref": "tagpagerenderingPrivateSubnets", - }, - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "Type": "application", - }, - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - }, - "LoadBalancerTagpagerenderingSecurityGroup4D481A16": { - "Properties": { - "GroupDescription": "Automatically created Security Group for ELB TagPageRenderingPRODLoadBalancerTagpagerenderingF63F513E", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "LoadBalancerTagpagerenderingSecurityGrouptoTagPageRenderingPRODGuHttpsEgressSecurityGroupTagpagerendering55A86AD190007FB7F7E9": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingSecurityGroup4D481A16", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "LoadBalancerTagpagerenderingSecurityGrouptoTagPageRenderingPRODGuHttpsEgressSecurityGroupTagpagerenderingecs7BD0DC4E9000E1B35F77": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingecsF0505C36", - "GroupId", - ], - }, - "FromPort": 9000, - "GroupId": { - "Fn::GetAtt": [ - "LoadBalancerTagpagerenderingSecurityGroup4D481A16", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 9000, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "ParameterStoreReadTagpagerendering4CA7B6E3": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "ssm:GetParametersByPath", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:ssm:eu-west-1:", - { - "Ref": "AWS::AccountId", - }, - ":parameter/PROD/frontend/tag-page-rendering", - ], - ], - }, - }, - { - "Action": [ - "ssm:GetParameters", - "ssm:GetParameter", - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:ssm:eu-west-1:", - { - "Ref": "AWS::AccountId", - }, - ":parameter/PROD/frontend/tag-page-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "parameter-store-read-policy", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - { - "Ref": "EcsTaskDefinitionTaskRoleB7B6D8DD", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "RenderingBaseURLParamAE11E777": { - "Properties": { - "Description": "The rendering base URL for frontend to call the tag-page-rendering app in the PROD environment", - "Name": "/frontend/prod/tag-page-rendering.baseURL", - "Tags": { - "App": "tag-page-rendering", - "Stack": "frontend", - "Stage": "PROD", - "gu:cdk:version": "TEST", - "gu:repo": "guardian/dotcom-rendering", - }, - "Type": "String", - "Value": "https://tag-page-rendering.guardianapis.com", - }, - "Type": "AWS::SSM::Parameter", - }, - "SsmSshPolicy4CFC977E": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ec2messages:AcknowledgeMessage", - "ec2messages:DeleteMessage", - "ec2messages:FailMessage", - "ec2messages:GetEndpoint", - "ec2messages:GetMessages", - "ec2messages:SendReply", - "ssm:UpdateInstanceInformation", - "ssm:ListInstanceAssociations", - "ssm:DescribeInstanceProperties", - "ssm:DescribeDocumentParameters", - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "ssm-ssh-policy", - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "TagpagerenderingEcsTargetGroupTagpagerendering0976D2E5": { - "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckPath": "/_healthcheck", - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 5, - "Port": 9000, - "Protocol": "HTTP", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "30", - }, - { - "Key": "stickiness.enabled", - "Value": "false", + "Key": "stickiness.enabled", + "Value": "false", }, ], "TargetType": "ip", @@ -9714,359 +8225,6 @@ exports[`The RenderingCDKStack matches the snapshot for Tag Page Rendering PROD }, "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", }, - "TargetGroupTagpagerendering42E428EE": { - "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckPath": "/_healthcheck", - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 5, - "Port": 9000, - "Protocol": "HTTP", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "30", - }, - { - "Key": "stickiness.enabled", - "Value": "false", - }, - ], - "TargetType": "instance", - "UnhealthyThresholdCount": 2, - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - }, - "UnhealthyInstancesAlarmTagpagerenderingED314507": { - "Properties": { - "ActionsEnabled": true, - "AlarmActions": [ - { - "Fn::Join": [ - "", - [ - "arn:aws:sns:eu-west-1:", - { - "Ref": "AWS::AccountId", - }, - ":Frontend-PROD-CriticalAlerts", - ], - ], - }, - ], - "AlarmDescription": "tag-page-rendering's instances have failed healthchecks several times over the last 1 hour. - This typically results in the AutoScaling Group cycling instances and can lead to problems with deployment, - scaling or handling traffic spikes. - - Check tag-page-rendering's application logs or ssh onto an unhealthy instance in order to debug these problems.", - "AlarmName": "Unhealthy instances for tag-page-rendering in PROD", - "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "DatapointsToAlarm": 30, - "Dimensions": [ - { - "Name": "LoadBalancer", - "Value": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "/", - { - "Ref": "ListenerTagpagerendering92E57078", - }, - ], - }, - ], - }, - "/", - { - "Fn::Select": [ - 2, - { - "Fn::Split": [ - "/", - { - "Ref": "ListenerTagpagerendering92E57078", - }, - ], - }, - ], - }, - "/", - { - "Fn::Select": [ - 3, - { - "Fn::Split": [ - "/", - { - "Ref": "ListenerTagpagerendering92E57078", - }, - ], - }, - ], - }, - ], - ], - }, - }, - { - "Name": "TargetGroup", - "Value": { - "Fn::GetAtt": [ - "TargetGroupTagpagerendering42E428EE", - "TargetGroupFullName", - ], - }, - }, - ], - "EvaluationPeriods": 60, - "MetricName": "UnHealthyHostCount", - "Namespace": "AWS/ApplicationELB", - "Period": 60, - "Statistic": "Maximum", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - "Threshold": 1, - "TreatMissingData": "notBreaching", - }, - "Type": "AWS::CloudWatch::Alarm", - }, - "frontendPRODtagpagerenderingA0B91C45": { - "DependsOn": [ - "InstanceRoleTagpagerendering171BC2F9", - ], - "Properties": { - "LaunchTemplateData": { - "IamInstanceProfile": { - "Arn": { - "Fn::GetAtt": [ - "frontendPRODtagpagerenderingProfile0369CEFE", - "Arn", - ], - }, - }, - "ImageId": { - "Ref": "AMITagpagerendering", - }, - "InstanceType": "c8g.medium", - "MetadataOptions": { - "HttpTokens": "required", - "InstanceMetadataTags": "enabled", - }, - "Monitoring": { - "Enabled": true, - }, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupTagpagerenderingDC233ADE", - "GroupId", - ], - }, - ], - "TagSpecifications": [ - { - "ResourceType": "instance", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-PROD/frontend-PROD-tag-page-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - }, - { - "ResourceType": "volume", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-PROD/frontend-PROD-tag-page-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - }, - ], - "UserData": { - "Fn::Base64": { - "Fn::Join": [ - "", - [ - "#!/bin/bash -set -ev -groupadd frontend -useradd -r -m -s /usr/bin/nologin -g frontend dotcom-rendering -cd /home/dotcom-rendering -aws --region eu-west-1 s3 cp s3://", - { - "Ref": "DistributionBucketName", - }, - "/frontend/PROD/tag-page-rendering/tag-page-rendering.tar.gz ./ -tar -zxf tag-page-rendering.tar.gz tag-page-rendering -chown -R dotcom-rendering:frontend tag-page-rendering -cd tag-page-rendering -mkdir /var/log/dotcom-rendering -chown -R dotcom-rendering:frontend /var/log/dotcom-rendering -cat > /etc/systemd/system/tag-page-rendering.service << EOF -[Unit] -Description=tag-page-rendering -After=network.target -[Service] -WorkingDirectory=/home/dotcom-rendering/tag-page-rendering -Type=simple -User=dotcom-rendering -Group=frontend -StandardError=journal -StandardOutput=journal -Environment=TERM=xterm-256color -Environment=NODE_ENV=production -Environment=GU_STAGE=PROD -Environment=GU_APP=tag-page-rendering -Environment=GU_STACK=frontend -ExecStart=make prod -Restart=on-failure -[Install] -WantedBy=multi-user.target -EOF -systemctl enable tag-page-rendering -systemctl start tag-page-rendering", - ], - ], - }, - }, - }, - "TagSpecifications": [ - { - "ResourceType": "launch-template", - "Tags": [ - { - "Key": "App", - "Value": "tag-page-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "TagPageRendering-PROD/frontend-PROD-tag-page-rendering", - }, - { - "Key": "Stack", - "Value": "frontend", - }, - { - "Key": "Stage", - "Value": "PROD", - }, - ], - }, - ], - }, - "Type": "AWS::EC2::LaunchTemplate", - }, - "frontendPRODtagpagerenderingProfile0369CEFE": { - "Properties": { - "Roles": [ - { - "Ref": "InstanceRoleTagpagerendering171BC2F9", - }, - ], - }, - "Type": "AWS::IAM::InstanceProfile", - }, "tagpagerenderingCpuScaling1742C101": { "Properties": { "PolicyName": "TagPageRenderingPRODtagpagerenderingCpuScaling4582D272", diff --git a/dotcom-rendering/cdk/lib/renderingStack.test.ts b/dotcom-rendering/cdk/lib/renderingStack.test.ts index d6c39cfc3a0..b58ef4a1527 100644 --- a/dotcom-rendering/cdk/lib/renderingStack.test.ts +++ b/dotcom-rendering/cdk/lib/renderingStack.test.ts @@ -20,45 +20,61 @@ describe('The RenderingCDKStack', () => { stage: 'PROD', guApp: 'article-rendering', domainName: 'article-rendering.test.dev-guardianapis.com', - scaling: { - minimumInstances: 1, - maximumInstances: 4, - policies: { - step: { - cpu: { - scalingStepsOut: [ - // No scaling up effect when p90 CPU is lower than 70% - { lower: 0, upper: 70, change: 0 }, - // When p90 CPU is higher than 70% we scale up by 50% - { lower: 70, change: 50 }, - // When p90 CPU is higher than 90% we scale up by 80% - { lower: 90, change: 80 }, - ], - }, - latency: { - scalingStepsOut: [ - { lower: 0, upper: 0.2, change: 0 }, - { lower: 0.2, change: 50 }, - { lower: 0.3, change: 80 }, - ], - scalingStepsIn: [ - { lower: 0.15, change: 0 }, - { upper: 0.15, lower: 0, change: -1 }, - ], + ec2Props: { + scaling: { + minimumInstances: 1, + maximumInstances: 4, + policies: { + step: { + cpu: { + scalingStepsOut: [ + // No scaling up effect when p90 CPU is lower than 70% + { lower: 0, upper: 70, change: 0 }, + // When p90 CPU is higher than 70% we scale up by 50% + { lower: 70, change: 50 }, + // When p90 CPU is higher than 90% we scale up by 80% + { lower: 90, change: 80 }, + ], + }, + latency: { + scalingStepsOut: [ + { lower: 0, upper: 0.2, change: 0 }, + { lower: 0.2, change: 50 }, + { lower: 0.3, change: 80 }, + ], + scalingStepsIn: [ + { lower: 0.15, change: 0 }, + { upper: 0.15, lower: 0, change: -1 }, + ], + }, }, }, }, + instanceType: InstanceType.of( + InstanceClass.T4G, + InstanceSize.MICRO, + ), }, - instanceType: InstanceType.of( - InstanceClass.T4G, - InstanceSize.MICRO, - ), }); const template = Template.fromStack(stack); expect(template.toJSON()).toMatchSnapshot(); }); - it('matches the snapshot for Tag Page Rendering PROD (now using ECS)', () => { + // Note: this is handled at the GuCDK library level + it('should not be possible to provision a stack without any compute', () => { + expect(() => { + const app = new App(); + new RenderingCDKStack(app, 'ArticleRendering', { + domainName: 'tag-page-rendering.guardianapis.com', + guApp: 'tag-page-rendering', + stage: 'PROD', + }); + }).toThrow( + "At least one of 'ec2Props' or 'ecsProps' must be specified", + ); + }); + + it('matches the snapshot for Tag Page Rendering PROD', () => { const app = new App(); const stack = new RenderingCDKStack( app, @@ -69,7 +85,7 @@ describe('The RenderingCDKStack', () => { expect(template.toJSON()).toMatchSnapshot(); }); - it('matches the snapshot for Tag Page Rendering CODE (uses ECS)', () => { + it('matches the snapshot for Tag Page Rendering CODE', () => { const app = new App(); const stack = new RenderingCDKStack( diff --git a/dotcom-rendering/cdk/lib/renderingStack.ts b/dotcom-rendering/cdk/lib/renderingStack.ts index fb23103832a..09c8e175d28 100644 --- a/dotcom-rendering/cdk/lib/renderingStack.ts +++ b/dotcom-rendering/cdk/lib/renderingStack.ts @@ -27,22 +27,27 @@ import { Subscription, SubscriptionProtocol, Topic } from 'aws-cdk-lib/aws-sns'; import { StringParameter } from 'aws-cdk-lib/aws-ssm'; import { getUserData } from './userData'; +interface RenderingEc2ScalingProps extends GuAsgCapacity { + policies?: { + step?: { + cpu?: { + scalingStepsOut: ScalingInterval[]; + }; + latency?: { + scalingStepsOut: ScalingInterval[]; + scalingStepsIn: ScalingInterval[]; + }; + }; + }; +} + export interface RenderingCDKStackProps extends Omit { guApp: `${'article' | 'facia' | 'interactive' | 'tag-page'}-rendering`; domainName: string; - instanceType: InstanceType; - scaling: GuAsgCapacity & { - policies?: { - step?: { - cpu?: { - scalingStepsOut: ScalingInterval[]; - }; - latency?: { - scalingStepsOut: ScalingInterval[]; - scalingStepsIn: ScalingInterval[]; - }; - }; - }; + + ec2Props?: { + instanceType: InstanceType; + scaling: RenderingEc2ScalingProps; }; /** @@ -50,23 +55,17 @@ export interface RenderingCDKStackProps extends Omit { * Optional to control which services run in an EC2-ECS hybrid mode, or EC2-only. */ ecsProps?: { - /** - * Which image to run. - * This should be the image digest (e.g. 'sha256:abc123') to ensure immutable deployments. - * - * @see https://docs.docker.com/dhi/core-concepts/digests - */ - imageIdentifier: string; + imageIdentifier: NonNullable< + GuLoadBalancedAppExperimentalProps['ecsProps'] + >['imageIdentifier']; - /** - * vCPU units for the ECS task - */ - taskCpu: number; + taskCpu: NonNullable< + GuLoadBalancedAppExperimentalProps['ecsProps'] + >['cpu']; - /** - * Memory in MB for ECS task - */ - taskMemoryLimitMiB: number; + taskMemoryLimitMiB: NonNullable< + GuLoadBalancedAppExperimentalProps['ecsProps'] + >['memoryLimitMiB']; scaling: NonNullable< GuLoadBalancedAppExperimentalProps['ecsProps'] @@ -81,10 +80,10 @@ export interface RenderingCDKStackProps extends Omit { const addCPUStepScalingPolicy = ( context: RenderingCDKStack, app: GuLoadBalancedAppExperimental, - props: RenderingCDKStackProps, + props: RenderingEc2ScalingProps, stage: string, ) => { - if (stage === 'PROD' && props.scaling.policies?.step?.cpu) { + if (stage === 'PROD' && props.policies?.step?.cpu) { const cpuMetric = new Metric({ namespace: 'AWS/EC2', metricName: 'CPUUtilization', @@ -119,7 +118,7 @@ const addCPUStepScalingPolicy = ( { autoScalingGroup: app.autoScalingGroup!, metric: cpuMetric, - scalingSteps: props.scaling.policies.step.cpu.scalingStepsOut, + scalingSteps: props.policies.step.cpu.scalingStepsOut, adjustmentType: AdjustmentType.PERCENT_CHANGE_IN_CAPACITY, evaluationPeriods: 2, // 1 minute = 2 × 30 seconds }, @@ -141,10 +140,10 @@ const addCPUStepScalingPolicy = ( const addLatencyStepScalingPolicy = ( context: RenderingCDKStack, app: GuLoadBalancedAppExperimental, - props: RenderingCDKStackProps, + props: RenderingEc2ScalingProps, stage: string, ) => { - if (stage === 'PROD' && props.scaling.policies?.step?.latency) { + if (stage === 'PROD' && props.policies?.step?.latency) { const latencyMetric = new Metric({ dimensionsMap: { LoadBalancer: app.loadBalancer.loadBalancerFullName, @@ -178,8 +177,7 @@ const addLatencyStepScalingPolicy = ( { autoScalingGroup: app.autoScalingGroup!, metric: latencyMetric, - scalingSteps: - props.scaling.policies.step.latency.scalingStepsOut, + scalingSteps: props.policies.step.latency.scalingStepsOut, adjustmentType: AdjustmentType.PERCENT_CHANGE_IN_CAPACITY, evaluationPeriods: 2, // 1 minute = 2 × 30 seconds }, @@ -203,7 +201,7 @@ const addLatencyStepScalingPolicy = ( new StepScalingPolicy(context, 'LatencyScaleDownPolicy', { autoScalingGroup: app.autoScalingGroup!, metric: latencyMetric, - scalingSteps: props.scaling.policies.step.latency.scalingStepsIn, + scalingSteps: props.policies.step.latency.scalingStepsIn, adjustmentType: AdjustmentType.CHANGE_IN_CAPACITY, evaluationPeriods: 10, }); @@ -213,8 +211,7 @@ const addLatencyStepScalingPolicy = ( /** DCR infrastructure provisioning via CDK */ export class RenderingCDKStack extends CDKStack { constructor(scope: CDKApp, id: string, props: RenderingCDKStackProps) { - const { guApp, stage, instanceType, scaling, domainName, ecsProps } = - props; + const { guApp, stage, domainName, ec2Props, ecsProps } = props; super(scope, id, { // Any version of this app should run in the eu-west-1 region @@ -278,21 +275,25 @@ export class RenderingCDKStack extends CDKStack { ], }), ], - ec2Props: { - instanceMetricGranularity: '1Minute', - applicationLogging: { - enabled: true, - systemdUnitName: guApp, - }, - instanceType, - scaling, - userData: getUserData({ - guApp, - guStack, - stage, - artifactsBucket, - }), - }, + ...(ec2Props == null + ? {} + : { + ec2Props: { + instanceMetricGranularity: '1Minute', + applicationLogging: { + enabled: true, + systemdUnitName: guApp, + }, + instanceType: ec2Props.instanceType, + scaling: ec2Props.scaling, + userData: getUserData({ + guApp, + guStack, + stage, + artifactsBucket, + }), + }, + }), // Provision ECS resources only when `ecsProps` has been provided ...(ecsProps == null @@ -414,11 +415,13 @@ export class RenderingCDKStack extends CDKStack { ttl: Duration.hours(1), }); - /** Add CPU utilisation based STEP scaling policy for PROD only if a policy is defined */ - addCPUStepScalingPolicy(this, app, props, stage); + if (ec2Props) { + /** Add CPU utilisation based STEP scaling policy for PROD only if a policy is defined */ + addCPUStepScalingPolicy(this, app, ec2Props.scaling, stage); - /** Add latency-based STEP scaling policy for PROD only if a policy is defined */ - addLatencyStepScalingPolicy(this, app, props, stage); + /** Add latency-based STEP scaling policy for PROD only if a policy is defined */ + addLatencyStepScalingPolicy(this, app, ec2Props.scaling, stage); + } // Saves the value of the rendering base URL to SSM for frontend apps to use new StringParameter(this, 'RenderingBaseURLParam', { diff --git a/dotcom-rendering/scripts/deploy/riff-raff.yaml b/dotcom-rendering/scripts/deploy/riff-raff.yaml index 6e34f12f268..abfc37e6ee6 100755 --- a/dotcom-rendering/scripts/deploy/riff-raff.yaml +++ b/dotcom-rendering/scripts/deploy/riff-raff.yaml @@ -68,24 +68,15 @@ deployments: - facia-rendering-cfn # tag-page-rendering cloudformation tag-page-rendering-cfn: - template: cloudformation + type: cloud-formation parameters: templateStagePaths: CODE: TagPageRendering-CODE.template.json PROD: TagPageRendering-PROD.template.json cloudFormationStackByTags: false cloudFormationStackName: tag-page-rendering - amiParameter: AMITagpagerendering - # tag-page-rendering autoscaling - tag-page-rendering: - type: autoscaling - parameters: - bucketSsmKey: /account/services/dotcom-artifact.bucket - # Default is 900 (15 mins), this is 25 mins - secondsToWait: 1500 dependencies: - frontend-static - - tag-page-rendering-cfn # interactive-rendering cloudformation interactive-rendering-cfn: template: cloudformation