constructor()

in cdk/lib/podcasts-rss.ts [16:124]


  constructor(scope: App, id: string, props: GuStackProps) {
    super(scope, id, props);

    const urgentAlarmTopicArn = aws_ssm.StringParameter.fromStringParameterName(this, "urgent-alarm-arn", "/account/content-api-common/alarms/urgent-alarm-topic");
    const nonUrgentAlarmTopicArn = aws_ssm.StringParameter.fromStringParameterName(this, "non-urgent-alarm-arn", "/account/content-api-common/alarms/non-urgent-alarm-topic");

    const vpcId = aws_ssm.StringParameter.valueForStringParameter(this, this.getVpcIdPath());
    const vpc = Vpc.fromVpcAttributes(this, "vpc", {
      vpcId: vpcId,
      availabilityZones: ["eu-west-1a","eu-west-1b" ,"eu-west-1c"]
    });

    const subnetsList = new GuParameter(this, "subnets", {
      description: "Subnets to deploy into",
      default: this.getDeploymentSubnetsPath(),
      fromSSM: true,
      type: "List<String>"
    });
    const deploymentSubnets = GuVpc.subnets(this, subnetsList.valueAsList);

    const hostedZone = aws_ssm.StringParameter.valueForStringParameter(this, `/account/services/content-aws.guardianapis/${this.stage}/hostedzoneid`);

    const app = new GuPlayApp(this, {
      access: {
        scope: AccessScope.PUBLIC,
      },
      app: "podcasts-rss",
      applicationLogging: {
        enabled: true,
      },
      certificateProps: {
        domainName: this.stage==="CODE" ? "podcast-feed.content.code.dev-guardianapis.com" : "podcast-feed.content-aws.guardianapis.com",
        hostedZoneId: hostedZone,
      },
      instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.SMALL),
      monitoringConfiguration: {
        snsTopicName: urgentAlarmTopicArn.stringValue,
        http5xxAlarm: {
          tolerated5xxPercentage: 20,
          numberOfMinutesAboveThresholdBeforeAlarm: 2,
        },
        unhealthyInstancesAlarm: true,
      },
      privateSubnets: deploymentSubnets,
      publicSubnets: deploymentSubnets,
      roleConfiguration: {
        additionalPolicies: [policies(this)],
      },
      scaling: {
        minimumInstances: 2,
        maximumInstances: 20,
      },
      userData: {
        distributable: {
          fileName: "podcasts-rss_1.0_all.deb",
          executionStatement: "dpkg -i /podcasts-rss/podcasts-rss_1.0_all.deb"
        }
      },
      vpc,
    });

    app.loadBalancer.addListener("HttpToHttps", {
      protocol: ApplicationProtocol.HTTP,
      port: 80,
      defaultAction: ListenerAction.forward([app.targetGroup])
    });

    const cpuHighAlarm = new Alarm(this, "HighCPU", {
      actionsEnabled: true,
      alarmDescription: "CPU utilization alarm for autoscaling",
      comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
      datapointsToAlarm: 5,
      evaluationPeriods: 5,
      metric: new Metric({
        dimensionsMap: {
          AutoScalingGroupName: app.autoScalingGroup.autoScalingGroupName,
        },
        metricName: "CPUUtilization",
        namespace: "AWS/EC2",
        period: Duration.minutes(1),
        statistic: "Average",
      }),
      threshold: 50,
      treatMissingData: TreatMissingData.MISSING,
    });

    const scaleUpStep = new StepScalingAction(this, "ScaleUp", {
      adjustmentType: AdjustmentType.PERCENT_CHANGE_IN_CAPACITY,
      autoScalingGroup: app.autoScalingGroup,
      cooldown: Duration.minutes(5),
    });
    scaleUpStep.addAdjustment({
      lowerBound: 0,
      adjustment: 100
    });
    cpuHighAlarm.addAlarmAction(new AutoScalingAction(scaleUpStep));

    const scaleDownStep = new StepScalingAction(this, "ScaleDown", {
      adjustmentType: AdjustmentType.CHANGE_IN_CAPACITY,
      autoScalingGroup: app.autoScalingGroup,
      cooldown: Duration.minutes(5),
    });
    scaleDownStep.addAdjustment({
      lowerBound: 0,
      adjustment: -1,
    });
    cpuHighAlarm.addOkAction(new AutoScalingAction(scaleDownStep));

  }