@guardian/cdk 48.5.1-beta.1 → 48.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/lib/bin/commands/new-project/index.d.ts +1 -1
  2. package/lib/bin/commands/new-project/index.d.ts.map +1 -1
  3. package/lib/constants/metadata-keys.d.ts +0 -1
  4. package/lib/constants/metadata-keys.d.ts.map +1 -1
  5. package/lib/constants/metadata-keys.js +0 -1
  6. package/lib/constants/metadata-keys.js.map +1 -1
  7. package/lib/constructs/acm/certificate.d.ts +1 -1
  8. package/lib/constructs/acm/certificate.d.ts.map +1 -1
  9. package/lib/constructs/autoscaling/user-data.d.ts +1 -1
  10. package/lib/constructs/autoscaling/user-data.d.ts.map +1 -1
  11. package/lib/constructs/autoscaling/user-data.js +8 -8
  12. package/lib/constructs/autoscaling/user-data.js.map +1 -1
  13. package/lib/constructs/core/parameters/base.d.ts +2 -2
  14. package/lib/constructs/core/parameters/base.d.ts.map +1 -1
  15. package/lib/constructs/core/stack.js +27 -27
  16. package/lib/constructs/core/stack.js.map +1 -1
  17. package/lib/constructs/ec2/vpc.d.ts +1 -1
  18. package/lib/constructs/ec2/vpc.d.ts.map +1 -1
  19. package/lib/constructs/ecs/ecs-task.d.ts +4 -4
  20. package/lib/constructs/ecs/ecs-task.d.ts.map +1 -1
  21. package/lib/constructs/iam/policies/base-policy.d.ts +3 -3
  22. package/lib/constructs/iam/policies/base-policy.d.ts.map +1 -1
  23. package/lib/constructs/iam/roles/instance-role.d.ts +1 -1
  24. package/lib/constructs/iam/roles/instance-role.d.ts.map +1 -1
  25. package/lib/constructs/iam/roles/roles.d.ts +1 -1
  26. package/lib/constructs/iam/roles/roles.d.ts.map +1 -1
  27. package/lib/constructs/kinesis/kinesis-stream.d.ts +1 -1
  28. package/lib/constructs/kinesis/kinesis-stream.d.ts.map +1 -1
  29. package/lib/constructs/sns/sns-topic.d.ts +1 -1
  30. package/lib/constructs/sns/sns-topic.d.ts.map +1 -1
  31. package/lib/constructs/vpc/vpc.d.ts +1 -1
  32. package/lib/constructs/vpc/vpc.d.ts.map +1 -1
  33. package/lib/experimental/constructs/error-budget-alarm.d.ts +2 -18
  34. package/lib/experimental/constructs/error-budget-alarm.d.ts.map +1 -1
  35. package/lib/experimental/constructs/error-budget-alarm.js +1 -81
  36. package/lib/experimental/constructs/error-budget-alarm.js.map +1 -1
  37. package/lib/experimental/riff-raff-yaml-file/index.js +48 -48
  38. package/lib/experimental/riff-raff-yaml-file/index.js.map +1 -1
  39. package/lib/experimental/riff-raff-yaml-file/types.d.ts +7 -7
  40. package/lib/experimental/riff-raff-yaml-file/types.d.ts.map +1 -1
  41. package/lib/patterns/api-multiple-lambdas.d.ts +1 -1
  42. package/lib/patterns/api-multiple-lambdas.d.ts.map +1 -1
  43. package/lib/patterns/ec2-app/base.d.ts.map +1 -1
  44. package/lib/patterns/ec2-app/base.js +0 -5
  45. package/lib/patterns/ec2-app/base.js.map +1 -1
  46. package/lib/patterns/ec2-app/framework.d.ts +1 -1
  47. package/lib/patterns/ec2-app/framework.d.ts.map +1 -1
  48. package/lib/types/access.d.ts +1 -1
  49. package/lib/types/access.d.ts.map +1 -1
  50. package/lib/types/cli.d.ts +1 -1
  51. package/lib/types/cli.d.ts.map +1 -1
  52. package/lib/utils/lambda/event-source.d.ts +4 -4
  53. package/lib/utils/lambda/event-source.d.ts.map +1 -1
  54. package/lib/utils/lambda/event-source.js +4 -4
  55. package/lib/utils/lambda/event-source.js.map +1 -1
  56. package/lib/utils/mixin/types.d.ts +1 -1
  57. package/lib/utils/mixin/types.d.ts.map +1 -1
  58. package/package.json +15 -15
@@ -1 +1 @@
1
- {"version":3,"file":"error-budget-alarm.js","sourceRoot":"","sources":["../../../src/experimental/constructs/error-budget-alarm.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport { CfnRuleGroupsNamespace } from \"aws-cdk-lib/aws-aps\";\nimport type { CfnCompositeAlarm, IMetric } from \"aws-cdk-lib/aws-cloudwatch\";\nimport {\n Alarm,\n AlarmRule,\n AlarmState,\n ComparisonOperator,\n CompositeAlarm,\n MathExpression,\n TreatMissingData,\n} from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { Construct } from \"constructs\";\nimport type { GuStack } from \"../../constructs/core\";\n\nexport interface CloudWatchErrorBudgetAlarmProps {\n /**\n * The name of the SLO. Assumed to be unique per stack.\n */\n sloName: string;\n /**\n * The percentange target for the SLO, expressed as a decimal floating point number. Must be between 0.95 and 0.995.\n */\n sloTarget: number;\n /**\n * The metric representing the bad events. Can be any IMetric type, like Metric or MathExpression.\n */\n badEvents: IMetric;\n /**\n * The metric representing the events to be considered. Can be any IMetric type, like Metric or MathExpression.\n */\n validEvents: IMetric;\n /**\n * The sns topic name (not the full arn) used by the alarm to send email alerts.\n */\n snsTopicNameForAlerts: string;\n}\n\nexport interface PrometheusErrorBudgetAlarmProps {\n /**\n * The name of the SLO. Assumed to be unique per stack.\n */\n sloName: string;\n /**\n * The percentage target for the SLO, expressed as a decimal floating point number. Must be between 0.95 and 0.995.\n */\n sloTarget: number;\n badEvents: string; // TODO: explain this once it is properly understood!\n validEvents: string; // TODO: explain this once it is properly understood!\n}\n\ninterface BurnRate {\n speed: \"Fast\" | \"Medium\" | \"Slow\";\n burnRate: number;\n}\n\ninterface CloudWatchBurnRateMonitoring extends BurnRate {\n longPeriod: Duration;\n shortPeriod: Duration;\n}\n\ninterface PrometheusBurnRateMonitoring extends BurnRate {\n longWindow: string;\n shortWindow: string;\n}\n\ninterface MonitorBurnRateForPeriodProps {\n alarmName: string;\n burnRateSpeed: BurnRate;\n period: Duration;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n}\n\ninterface CompositeBurnRateAlarmProps {\n sloName: string;\n burnRateMonitoring: CloudWatchBurnRateMonitoring;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n snsTopic: ITopic;\n suppressorAlarm?: CompositeBurnRateAlarm;\n}\n\n// If we use a single shared Prometheus instance in the Deploy Tools account, this construct would need to be deployed\n// into that account only.\nexport class GuPrometheusErrorBudgetAlarmExperimental extends CfnRuleGroupsNamespace {\n constructor(scope: GuStack, props: PrometheusErrorBudgetAlarmProps) {\n const lowestTargetAllowed = 0.95;\n const highestTargetAllowed = 0.9995;\n if (!(props.sloTarget >= lowestTargetAllowed && props.sloTarget <= highestTargetAllowed)) {\n throw new Error(\n `ErrorBudgetAlarm only works with SLO targets between ${lowestTargetAllowed} and ${highestTargetAllowed}`\n );\n }\n\n const errorBudget = 1 - props.sloTarget;\n\n const fastBurnRate: PrometheusBurnRateMonitoring = {\n speed: \"Fast\",\n burnRate: 14.4,\n longWindow: \"1h\",\n shortWindow: \"5m\",\n };\n\n const mediumBurnRate: PrometheusBurnRateMonitoring = {\n speed: \"Medium\",\n burnRate: 6,\n longWindow: \"6h\",\n shortWindow: \"30m\",\n };\n\n const slowBurnRate: PrometheusBurnRateMonitoring = {\n speed: \"Slow\",\n burnRate: 3,\n longWindow: \"1d\",\n shortWindow: \"2h\",\n };\n\n const recordingRulePrefix = `sli_for_${props.sloName}`;\n\n const fastBurnShortWindowRule = `${recordingRulePrefix}_${fastBurnRate.shortWindow}`;\n const fastBurnLongWindowRule = `${recordingRulePrefix}_${fastBurnRate.longWindow}`;\n const mediumBurnShortWindowRule = `${recordingRulePrefix}_${mediumBurnRate.shortWindow}`;\n const mediumBurnLongWindowRule = `${recordingRulePrefix}_${mediumBurnRate.longWindow}`;\n const slowBurnShortWindowRule = `${recordingRulePrefix}_${slowBurnRate.shortWindow}`;\n const slowBurnLongWindowRule = `${recordingRulePrefix}_${slowBurnRate.longWindow}`;\n\n const fastBurnThreshold: number = errorBudget * fastBurnRate.burnRate;\n const mediumBurnThreshold: number = errorBudget * mediumBurnRate.burnRate;\n const slowBurnThreshold: number = errorBudget * slowBurnRate.burnRate;\n\n // Currently we assume that the job label refers to a unique app. This works fine with our simple test data but will not scale out properly.\n // Perhaps we will need to sum by (${props.app}, ${scope.stack}, ${scope.stage}) in order to scale up?\n const prometheusRules = `groups:\n - name: multiwindow_recording_rules\n rules:\n - record: ${fastBurnShortWindowRule}\n expr: sum by (job) (rate(${props.badEvents}[${fastBurnRate.shortWindow}])) / sum by (job) (rate(${props.validEvents}[${fastBurnRate.shortWindow}]))\n - record: ${mediumBurnShortWindowRule}\n expr: sum by (job) (rate(${props.badEvents}[${mediumBurnRate.shortWindow}])) / sum by (job) (rate(${props.validEvents}[${mediumBurnRate.shortWindow}]))\n - record: ${fastBurnLongWindowRule}\n expr: sum by (job) (rate(${props.badEvents}[${fastBurnRate.longWindow}])) / sum by (job) (rate(${props.validEvents}[${fastBurnRate.longWindow}]))\n - record: ${slowBurnShortWindowRule}\n expr: sum by (job) (rate(${props.badEvents}[${slowBurnRate.shortWindow}])) / sum by (job) (rate(${props.validEvents}[${slowBurnRate.shortWindow}]))\n - record: ${mediumBurnLongWindowRule}\n expr: sum by (job) (rate(${props.badEvents}[${mediumBurnRate.longWindow}])) / sum by (job) (rate(${props.validEvents}[${mediumBurnRate.longWindow}]))\n - record: ${slowBurnLongWindowRule}\n expr: sum by (job) (rate(${props.badEvents}[${slowBurnRate.longWindow}])) / sum by (job) (rate(${props.validEvents}[${slowBurnRate.longWindow}]))\n - name: multiwindow_alerts\n rules:\n - alert: FastBurnAlarm\n expr: (${fastBurnShortWindowRule} > ${fastBurnThreshold}) and (${fastBurnLongWindowRule} > ${fastBurnThreshold})\n - alert: MediumBurnAlarm\n expr: (${mediumBurnShortWindowRule} > ${mediumBurnThreshold}) and (${mediumBurnLongWindowRule} > ${mediumBurnThreshold})\n - alert: SlowBurnAlarm\n expr: (${slowBurnShortWindowRule} > ${slowBurnThreshold}) and (${slowBurnLongWindowRule} > ${slowBurnThreshold})\n `;\n\n // TODO: figure out how to do alert silencing for lower priority alerts - presumably via a separate config file?\n\n super(scope, props.sloName, {\n // TODO: it would probably be better to get this ARN from parameter store\n workspace: `arn:aws:aps:${scope.region}:${scope.account}:workspace/ws-e4fe0f0b-2372-4309-901b-9aae06e4d9ba`,\n // N.B. there is an AWS quota limit for unique namespaces. For this simple test we are using a namespace for a\n // single SLO. This model will not scale. If AWS allow us to increase the namespace limit significantly we could\n // potentially use a namespace per service. However, it might be better to model this as one namespace per team.\n // In either case we'd need to generate the data section only (per SLO) and then combine the list of rules under a\n // single namespace.\n name: \"test-cdk-rules\",\n data: prometheusRules,\n });\n }\n}\n\n/**\n * Use this construct to create alarms that will notify you when you are at risk of missing your SLO targets.\n *\n * These alarms follow the recommendations in the [SRE Workbook](https://sre.google/workbook/alerting-on-slos/) to\n * implement Multiwindow, Multi-Burn-Rate Alerts.\n *\n * The CloudWatch implementation of this strategy creates nine separate CloudWatch alarms. The main alarms that users\n * need to care about are the three composite alarms. These track different burn rates of error budget consumption:\n * fast (e.g. complete outages), medium (e.g. moderate error percentage over hours, rather than minutes) and slow (e.g.\n * a small percentage of errors sustained over a much longer period). Multiple burn rates are used to ensure that\n * we are able to pick up all scenarios which could threaten the SLO, without interrupting developers with an\n * unnecessary level of urgency.\n *\n * Each composite alarm creates two child alarms; these are used to support multiple windows (or periods in CloudWatch\n * terminology). A composite alarm is configured to send notifications if both of its child alarms are in an alarm state.\n * The child alarms themselves have no actions/notifications configured and users should not need to interact with them\n * directly. Multiple windows are helpful for accuracy and reset time. The long window helps us to avoid sending an\n * alert in scenarios where no intervention is required, for example a very brief spike in errors that is resolved\n * automatically (e.g. when AWS replaces a 'bad' EC2 instance). The short window helps to ensure that the alert is reset\n * (or moved back into OK state, in CloudWatch terminology) promptly once a problem has been resolved.\n *\n * The composite alarms have an awareness of priority, meaning that low priority alarm notifications are suppressed if\n * a higher priority alarm is already firing. That is, if you receive an alert about fast error budget consumption, you\n * should not receive an alert from the medium or slow versions of the alarm.\n *\n * For how to instantiate an ErrorBudgetAlarm check the unit-test in error-budget-alarm.test.ts,\n * and for a description of the props that need to be passed see [[ErrorBudgetAlarmProps]]\n */\nexport class GuErrorBudgetAlarmExperimental extends Construct {\n constructor(scope: GuStack, props: CloudWatchErrorBudgetAlarmProps) {\n const lowestTargetAllowed = 0.95;\n const highestTargetAllowed = 0.9995;\n if (!(props.sloTarget >= lowestTargetAllowed && props.sloTarget <= highestTargetAllowed)) {\n throw new Error(\n `ErrorBudgetAlarm only works with SLO targets between ${lowestTargetAllowed} and ${highestTargetAllowed}`\n );\n }\n\n super(scope, props.sloName); // The assumption here is that `sloName` will be unique (per stack)\n\n const errorBudget = 1 - props.sloTarget;\n\n const snsTopic: ITopic = Topic.fromTopicArn(\n scope,\n `SnsSloAlarmsFor${props.sloName}`,\n `arn:aws:sns:${scope.region}:${scope.account}:${props.snsTopicNameForAlerts}`\n );\n\n const fastBurnRate: CloudWatchBurnRateMonitoring = {\n speed: \"Fast\",\n burnRate: 14.4,\n longPeriod: Duration.hours(1),\n shortPeriod: Duration.minutes(5),\n };\n\n const fastBurnAlarm = new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: fastBurnRate,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n });\n\n const mediumBurnRateMonitoring: CloudWatchBurnRateMonitoring = {\n speed: \"Medium\",\n burnRate: 6,\n longPeriod: Duration.hours(6),\n shortPeriod: Duration.minutes(30),\n };\n\n const mediumBurnRateAlarm = new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: mediumBurnRateMonitoring,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n suppressorAlarm: fastBurnAlarm,\n });\n\n const slowBurnRate: CloudWatchBurnRateMonitoring = {\n speed: \"Slow\",\n burnRate: 3,\n longPeriod: Duration.days(1),\n shortPeriod: Duration.hours(2),\n };\n\n new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: slowBurnRate,\n errorBudget,\n // TODO - use a different topic for tickets or figure out how to route notifications vs tickets using a single topic\n snsTopic,\n validEvents: props.validEvents,\n suppressorAlarm: mediumBurnRateAlarm,\n });\n }\n}\n\nclass MonitorBurnRateForPeriod extends Alarm {\n constructor(scope: GuStack, props: MonitorBurnRateForPeriodProps) {\n const undesirableErrorBudgetConsumption = props.errorBudget * props.burnRateSpeed.burnRate;\n super(scope, props.alarmName, {\n alarmName: props.alarmName,\n metric: new MathExpression({\n expression: \"badEvents/validEvents\",\n label: \"Observed failure rate\",\n usingMetrics: {\n badEvents: props.badEvents,\n validEvents: props.validEvents,\n },\n period: props.period,\n }),\n evaluationPeriods: 1,\n threshold: undesirableErrorBudgetConsumption,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n }\n}\n\nclass CompositeBurnRateAlarm extends CompositeAlarm {\n constructor(scope: GuStack, props: CompositeBurnRateAlarmProps) {\n const alarmName = `${props.sloName}${props.burnRateMonitoring.speed}BurnCompositeAlarm`;\n const sharedIndividualAlarmProps = {\n badEvents: props.badEvents,\n burnRateSpeed: {\n speed: props.burnRateMonitoring.speed,\n burnRate: props.burnRateMonitoring.burnRate,\n },\n errorBudget: props.errorBudget,\n validEvents: props.validEvents,\n };\n super(scope, alarmName, {\n alarmRule: AlarmRule.allOf(\n AlarmRule.fromAlarm(\n new MonitorBurnRateForPeriod(scope, {\n ...sharedIndividualAlarmProps,\n alarmName: `ChildAlarmLongPeriod${alarmName}`,\n period: props.burnRateMonitoring.longPeriod,\n }),\n AlarmState.ALARM\n ),\n AlarmRule.fromAlarm(\n new MonitorBurnRateForPeriod(scope, {\n ...sharedIndividualAlarmProps,\n alarmName: `ChildAlarmShortPeriod${alarmName}`,\n period: props.burnRateMonitoring.shortPeriod,\n }),\n AlarmState.ALARM\n )\n ),\n });\n this.addAlarmAction(new SnsAction(props.snsTopic));\n if (props.suppressorAlarm) {\n const cfnAlarm = this.node.defaultChild as CfnCompositeAlarm;\n cfnAlarm.actionsSuppressor = props.suppressorAlarm.alarmArn;\n cfnAlarm.actionsSuppressorWaitPeriod = 120;\n cfnAlarm.actionsSuppressorExtensionPeriod = props.burnRateMonitoring.shortPeriod.toSeconds();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"error-budget-alarm.js","sourceRoot":"","sources":["../../../src/experimental/constructs/error-budget-alarm.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration } from \"aws-cdk-lib\";\nimport type { CfnCompositeAlarm, IMetric } from \"aws-cdk-lib/aws-cloudwatch\";\nimport {\n Alarm,\n AlarmRule,\n AlarmState,\n ComparisonOperator,\n CompositeAlarm,\n MathExpression,\n TreatMissingData,\n} from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ITopic } from \"aws-cdk-lib/aws-sns\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { Construct } from \"constructs\";\nimport type { GuStack } from \"../../constructs/core\";\n\nexport interface ErrorBudgetAlarmProps {\n /**\n * The name of the SLO. Assumed to be unique per stack.\n */\n sloName: string;\n /**\n * The percentange target for the SLO, expressed as a decimal floating point number. Must be between 0.95 and 0.995.\n */\n sloTarget: number;\n /**\n * The metric representing the bad events. Can be any IMetric type, like Metric or MathExpression.\n */\n badEvents: IMetric;\n /**\n * The metric representing the events to be considered. Can be any IMetric type, like Metric or MathExpression.\n */\n validEvents: IMetric;\n /**\n * The sns topic name (not the full arn) used by the alarm to send email alerts.\n */\n snsTopicNameForAlerts: string;\n}\n\ninterface BurnRate {\n speed: \"Fast\" | \"Medium\" | \"Slow\";\n burnRate: number;\n}\n\ninterface BurnRateMonitoring extends BurnRate {\n longPeriod: Duration;\n shortPeriod: Duration;\n}\n\ninterface MonitorBurnRateForPeriodProps {\n alarmName: string;\n burnRateSpeed: BurnRate;\n period: Duration;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n}\n\ninterface CompositeBurnRateAlarmProps {\n sloName: string;\n burnRateMonitoring: BurnRateMonitoring;\n errorBudget: number;\n badEvents: IMetric;\n validEvents: IMetric;\n snsTopic: ITopic;\n suppressorAlarm?: CompositeBurnRateAlarm;\n}\n\n/**\n * Use this construct to create alarms that will notify you when you are at risk of missing your SLO targets.\n *\n * These alarms follow the recommendations in the [SRE Workbook](https://sre.google/workbook/alerting-on-slos/) to\n * implement Multiwindow, Multi-Burn-Rate Alerts.\n *\n * The CloudWatch implementation of this strategy creates nine separate CloudWatch alarms. The main alarms that users\n * need to care about are the three composite alarms. These track different burn rates of error budget consumption:\n * fast (e.g. complete outages), medium (e.g. moderate error percentage over hours, rather than minutes) and slow (e.g.\n * a small percentage of errors sustained over a much longer period). Multiple burn rates are used to ensure that\n * we are able to pick up all scenarios which could threaten the SLO, without interrupting developers with an\n * unnecessary level of urgency.\n *\n * Each composite alarm creates two child alarms; these are used to support multiple windows (or periods in CloudWatch\n * terminology). A composite alarm is configured to send notifications if both of its child alarms are in an alarm state.\n * The child alarms themselves have no actions/notifications configured and users should not need to interact with them\n * directly. Multiple windows are helpful for accuracy and reset time. The long window helps us to avoid sending an\n * alert in scenarios where no intervention is required, for example a very brief spike in errors that is resolved\n * automatically (e.g. when AWS replaces a 'bad' EC2 instance). The short window helps to ensure that the alert is reset\n * (or moved back into OK state, in CloudWatch terminology) promptly once a problem has been resolved.\n *\n * The composite alarms have an awareness of priority, meaning that low priority alarm notifications are suppressed if\n * a higher priority alarm is already firing. That is, if you receive an alert about fast error budget consumption, you\n * should not receive an alert from the medium or slow versions of the alarm.\n *\n * For how to instantiate an ErrorBudgetAlarm check the unit-test in error-budget-alarm.test.ts,\n * and for a description of the props that need to be passed see [[ErrorBudgetAlarmProps]]\n */\nexport class GuErrorBudgetAlarmExperimental extends Construct {\n constructor(scope: GuStack, props: ErrorBudgetAlarmProps) {\n const lowestTargetAllowed = 0.95;\n const highestTargetAllowed = 0.9995;\n if (!(props.sloTarget >= lowestTargetAllowed && props.sloTarget <= highestTargetAllowed)) {\n throw new Error(\n `ErrorBudgetAlarm only works with SLO targets between ${lowestTargetAllowed} and ${highestTargetAllowed}`\n );\n }\n\n super(scope, props.sloName); // The assumption here is that `sloName` will be unique (per stack)\n\n const errorBudget = 1 - props.sloTarget;\n\n const snsTopic: ITopic = Topic.fromTopicArn(\n scope,\n `SnsSloAlarmsFor${props.sloName}`,\n `arn:aws:sns:${scope.region}:${scope.account}:${props.snsTopicNameForAlerts}`\n );\n\n const fastBurnRate: BurnRateMonitoring = {\n speed: \"Fast\",\n burnRate: 14.4,\n longPeriod: Duration.hours(1),\n shortPeriod: Duration.minutes(5),\n };\n\n const fastBurnAlarm = new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: fastBurnRate,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n });\n\n const mediumBurnRateMonitoring: BurnRateMonitoring = {\n speed: \"Medium\",\n burnRate: 6,\n longPeriod: Duration.hours(6),\n shortPeriod: Duration.minutes(30),\n };\n\n const mediumBurnRateAlarm = new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: mediumBurnRateMonitoring,\n errorBudget,\n snsTopic,\n validEvents: props.validEvents,\n suppressorAlarm: fastBurnAlarm,\n });\n\n const slowBurnRate: BurnRateMonitoring = {\n speed: \"Slow\",\n burnRate: 3,\n longPeriod: Duration.days(1),\n shortPeriod: Duration.hours(2),\n };\n\n new CompositeBurnRateAlarm(scope, {\n sloName: props.sloName,\n badEvents: props.badEvents,\n burnRateMonitoring: slowBurnRate,\n errorBudget,\n // TODO - use a different topic for tickets or figure out how to route notifications vs tickets using a single topic\n snsTopic,\n validEvents: props.validEvents,\n suppressorAlarm: mediumBurnRateAlarm,\n });\n }\n}\n\nclass MonitorBurnRateForPeriod extends Alarm {\n constructor(scope: GuStack, props: MonitorBurnRateForPeriodProps) {\n const undesirableErrorBudgetConsumption = props.errorBudget * props.burnRateSpeed.burnRate;\n super(scope, props.alarmName, {\n alarmName: props.alarmName,\n metric: new MathExpression({\n expression: \"badEvents/validEvents\",\n label: \"Observed failure rate\",\n usingMetrics: {\n badEvents: props.badEvents,\n validEvents: props.validEvents,\n },\n period: props.period,\n }),\n evaluationPeriods: 1,\n threshold: undesirableErrorBudgetConsumption,\n comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n }\n}\n\nclass CompositeBurnRateAlarm extends CompositeAlarm {\n constructor(scope: GuStack, props: CompositeBurnRateAlarmProps) {\n const alarmName = `${props.sloName}${props.burnRateMonitoring.speed}BurnCompositeAlarm`;\n const sharedIndividualAlarmProps = {\n badEvents: props.badEvents,\n burnRateSpeed: {\n speed: props.burnRateMonitoring.speed,\n burnRate: props.burnRateMonitoring.burnRate,\n },\n errorBudget: props.errorBudget,\n validEvents: props.validEvents,\n };\n super(scope, alarmName, {\n alarmRule: AlarmRule.allOf(\n AlarmRule.fromAlarm(\n new MonitorBurnRateForPeriod(scope, {\n ...sharedIndividualAlarmProps,\n alarmName: `ChildAlarmLongPeriod${alarmName}`,\n period: props.burnRateMonitoring.longPeriod,\n }),\n AlarmState.ALARM\n ),\n AlarmRule.fromAlarm(\n new MonitorBurnRateForPeriod(scope, {\n ...sharedIndividualAlarmProps,\n alarmName: `ChildAlarmShortPeriod${alarmName}`,\n period: props.burnRateMonitoring.shortPeriod,\n }),\n AlarmState.ALARM\n )\n ),\n });\n this.addAlarmAction(new SnsAction(props.snsTopic));\n if (props.suppressorAlarm) {\n const cfnAlarm = this.node.defaultChild as CfnCompositeAlarm;\n cfnAlarm.actionsSuppressor = props.suppressorAlarm.alarmArn;\n cfnAlarm.actionsSuppressorWaitPeriod = 120;\n cfnAlarm.actionsSuppressorExtensionPeriod = props.burnRateMonitoring.shortPeriod.toSeconds();\n }\n }\n}\n"]}
@@ -60,54 +60,6 @@ const group_by_1 = require("./group-by");
60
60
  * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types
61
61
  */
62
62
  class RiffRaffYamlFileExperimental {
63
- // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree
64
- constructor(app) {
65
- this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof core_1.GuStack);
66
- const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));
67
- this.allStageTags = Array.from(allowedStages);
68
- this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));
69
- this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));
70
- this.validateStacksInApp();
71
- this.validateAllRegionsAreResolved();
72
- this.outdir = app.outdir;
73
- const deployments = new Map();
74
- const groupedStacks = (0, group_by_1.groupByClassNameStackRegionStage)(this.allCdkStacks);
75
- Object.values(groupedStacks).forEach((stackTagGroup) => {
76
- Object.values(stackTagGroup).forEach((regionGroup) => {
77
- Object.values(regionGroup).forEach((stageGroup) => {
78
- const stacks = Object.values(stageGroup).flat();
79
- if (stacks.length === 0) {
80
- throw new Error("Unable to produce a working riff-raff.yaml file; there are no stacks!");
81
- }
82
- // The items in `stacks` only differ by stage, so we can just use the first item in the list.
83
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above
84
- const stack = stacks[0];
85
- const lambdas = this.getLambdas(stack);
86
- const autoscalingGroups = this.getAutoScalingGroups(stack);
87
- const artifactUploads = [
88
- lambdas.map(lambda_2.uploadLambdaArtifact),
89
- autoscalingGroups.map(autoscaling_2.uploadAutoscalingArtifact),
90
- ].flat();
91
- artifactUploads.forEach(({ name, props }) => deployments.set(name, props));
92
- const cfnDeployment = (0, cloudformation_1.cloudFormationDeployment)(stacks, artifactUploads, this.outdir);
93
- deployments.set(cfnDeployment.name, cfnDeployment.props);
94
- lambdas.forEach((lambda) => {
95
- const lambdaDeployment = (0, lambda_2.updateLambdaDeployment)(lambda, cfnDeployment);
96
- deployments.set(lambdaDeployment.name, lambdaDeployment.props);
97
- });
98
- autoscalingGroups.forEach((asg) => {
99
- const asgDeployment = (0, autoscaling_2.autoscalingDeployment)(asg, cfnDeployment);
100
- deployments.set(asgDeployment.name, asgDeployment.props);
101
- deployments.set(cfnDeployment.name, (0, cloudformation_1.addAmiParametersToCloudFormationDeployment)(cfnDeployment, asg));
102
- });
103
- });
104
- });
105
- });
106
- this.riffRaffYaml = {
107
- allowedStages,
108
- deployments,
109
- };
110
- }
111
63
  isCdkStackPresent(expectedClassName, expectedStack, expectedRegion, expectedStage) {
112
64
  const matches = this.allCdkStacks.find((cdkStack) => {
113
65
  const { constructor: { name }, stack, stage, region, } = cdkStack;
@@ -223,6 +175,54 @@ class RiffRaffYamlFileExperimental {
223
175
  getAutoScalingGroups(cdkStack) {
224
176
  return cdkStack.node.findAll().filter((_) => _ instanceof autoscaling_1.GuAutoScalingGroup);
225
177
  }
178
+ // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree
179
+ constructor(app) {
180
+ this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof core_1.GuStack);
181
+ const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));
182
+ this.allStageTags = Array.from(allowedStages);
183
+ this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));
184
+ this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));
185
+ this.validateStacksInApp();
186
+ this.validateAllRegionsAreResolved();
187
+ this.outdir = app.outdir;
188
+ const deployments = new Map();
189
+ const groupedStacks = (0, group_by_1.groupByClassNameStackRegionStage)(this.allCdkStacks);
190
+ Object.values(groupedStacks).forEach((stackTagGroup) => {
191
+ Object.values(stackTagGroup).forEach((regionGroup) => {
192
+ Object.values(regionGroup).forEach((stageGroup) => {
193
+ const stacks = Object.values(stageGroup).flat();
194
+ if (stacks.length === 0) {
195
+ throw new Error("Unable to produce a working riff-raff.yaml file; there are no stacks!");
196
+ }
197
+ // The items in `stacks` only differ by stage, so we can just use the first item in the list.
198
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above
199
+ const stack = stacks[0];
200
+ const lambdas = this.getLambdas(stack);
201
+ const autoscalingGroups = this.getAutoScalingGroups(stack);
202
+ const artifactUploads = [
203
+ lambdas.map(lambda_2.uploadLambdaArtifact),
204
+ autoscalingGroups.map(autoscaling_2.uploadAutoscalingArtifact),
205
+ ].flat();
206
+ artifactUploads.forEach(({ name, props }) => deployments.set(name, props));
207
+ const cfnDeployment = (0, cloudformation_1.cloudFormationDeployment)(stacks, artifactUploads, this.outdir);
208
+ deployments.set(cfnDeployment.name, cfnDeployment.props);
209
+ lambdas.forEach((lambda) => {
210
+ const lambdaDeployment = (0, lambda_2.updateLambdaDeployment)(lambda, cfnDeployment);
211
+ deployments.set(lambdaDeployment.name, lambdaDeployment.props);
212
+ });
213
+ autoscalingGroups.forEach((asg) => {
214
+ const asgDeployment = (0, autoscaling_2.autoscalingDeployment)(asg, cfnDeployment);
215
+ deployments.set(asgDeployment.name, asgDeployment.props);
216
+ deployments.set(cfnDeployment.name, (0, cloudformation_1.addAmiParametersToCloudFormationDeployment)(cfnDeployment, asg));
217
+ });
218
+ });
219
+ });
220
+ });
221
+ this.riffRaffYaml = {
222
+ allowedStages,
223
+ deployments,
224
+ };
225
+ }
226
226
  /**
227
227
  * The `riff-raff.yaml` file as a string.
228
228
  * Useful for testing.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport chalk from \"chalk\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n ClassName,\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(\n expectedClassName: ClassName,\n expectedStack: StackTag,\n expectedRegion: Region,\n expectedStage: StageTag\n ): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const {\n constructor: { name },\n stack,\n stage,\n region,\n } = cdkStack;\n return (\n name === expectedClassName && stack === expectedStack && stage === expectedStage && region === expectedRegion\n );\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `GuStack`, `stack`, `region`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * For the class: MyApplicationStack\n *\n * ┌───────────────┬────────────────────────────┐\n * │ (index) │ eu-west-1 │\n * ├───────────────┼────────────────────────────┤\n * │ deploy │ { CODE: '✅', PROD: '✅' } │\n * │ media-service │ { CODE: '❌', PROD: '✅' } │\n * └───────────────┴────────────────────────────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<ClassName, Record<StackTag, Record<Region, Record<StageTag, Found | NotFound>>>>;\n\n const { allCdkStacks, allStackTags, allStageTags, allRegions } = this;\n\n const checks: AppValidation = allCdkStacks.reduce((accClassName, { constructor: { name } }) => {\n return {\n ...accClassName,\n [name]: allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allRegions.reduce((accRegion, region) => {\n return {\n ...accRegion,\n [region]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(name, stackTag, region, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {}),\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).flatMap((groupedByRegion) => {\n return Object.values(groupedByRegion).flatMap((groupedByStage) => {\n return Object.values(groupedByStage).filter((_) => _ === \"❌\");\n });\n });\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n Object.entries(checks).forEach(([className, detail]) => {\n console.log(`For the class: ${chalk.yellow(className)}`);\n console.table(detail);\n });\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n lambdas.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n\n deployments.set(cfnDeployment.name, addAmiParametersToCloudFormationDeployment(cfnDeployment, asg));\n });\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/index.ts"],"names":[],"mappings":";;;;;;AAAA,2BAAmC;AACnC,gDAAwB;AAExB,6CAAoC;AACpC,kDAA0B;AAC1B,qCAA+B;AAC/B,8DAAkE;AAClE,gDAAgD;AAChD,oDAA2D;AAC3D,2DAA6F;AAC7F,iEAAoH;AACpH,iDAAoF;AACpF,yCAA8D;AAa9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAa,4BAA4B;IAS/B,iBAAiB,CACvB,iBAA4B,EAC5B,aAAuB,EACvB,cAAsB,EACtB,aAAuB;QAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YAClD,MAAM,EACJ,WAAW,EAAE,EAAE,IAAI,EAAE,EACrB,KAAK,EACL,KAAK,EACL,MAAM,GACP,GAAG,QAAQ,CAAC;YACb,OAAO,CACL,IAAI,KAAK,iBAAiB,IAAI,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,aAAa,IAAI,MAAM,KAAK,cAAc,CAC9G,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,CAAC,OAAO,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuDG;IACK,mBAAmB;QAKzB,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAEtE,MAAM,MAAM,GAAkB,YAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;YAC5F,OAAO;gBACL,GAAG,YAAY;gBACf,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE;oBACpD,OAAO;wBACL,GAAG,WAAW;wBACd,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;4BAClD,OAAO;gCACL,GAAG,SAAS;gCACZ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE;oCACtD,OAAO;wCACL,GAAG,WAAW;wCACd,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;qCACjF,CAAC;gCACJ,CAAC,EAAE,EAAE,CAAC;6BACP,CAAC;wBACJ,CAAC,EAAE,EAAE,CAAC;qBACP,CAAC;gBACJ,CAAC,EAAE,EAAE,CAAC;aACP,CAAC;QACJ,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE;YAC7E,OAAO,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,EAAE;gBAClE,OAAO,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE;oBAC/D,OAAO,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;gBAChE,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE;YACjC,MAAM,OAAO,GAAG,4DAA4D,kBAAkB,CAAC,MAAM,cAAc,CAAC;YAEpH,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,kBAAkB,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE;gBACrD,OAAO,CAAC,GAAG,CAAC,kBAAkB,eAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBACzD,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACxB,CAAC,CAAC,CAAC;YAEH,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;SAC1B;IACH,CAAC;IAEO,6BAA6B;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,mBAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAElF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,8FAA8F,CAAC,CAAC;SACjH;IACH,CAAC;IAEO,UAAU,CAAC,QAAiB;QAClC,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,yBAAgB,CAAuB,CAAC;IACpG,CAAC;IAEO,oBAAoB,CAAC,QAAiB;QAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,gCAAkB,CAAyB,CAAC;IACxG,CAAC;IAED,8GAA8G;IAC9G,YAAY,GAAQ;QAClB,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,cAAO,CAAc,CAAC;QACxF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrF,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAErF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,6BAA6B,EAAE,CAAC;QAErC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAEzB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAmD,CAAC;QAE/E,MAAM,aAAa,GAAqB,IAAA,2CAAgC,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAE5F,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;YACrD,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;gBACnD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;oBAChD,MAAM,MAAM,GAAc,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;oBAE3D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;wBACvB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;qBAC1F;oBAED,6FAA6F;oBAC7F,2GAA2G;oBAC3G,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;oBAEzB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;oBACvC,MAAM,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;oBAE3D,MAAM,eAAe,GAAyB;wBAC5C,OAAO,CAAC,GAAG,CAAC,6BAAoB,CAAC;wBACjC,iBAAiB,CAAC,GAAG,CAAC,uCAAyB,CAAC;qBACjD,CAAC,IAAI,EAAE,CAAC;oBACT,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;oBAE3E,MAAM,aAAa,GAAG,IAAA,yCAAwB,EAAC,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;oBACrF,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;oBAEzD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;wBACzB,MAAM,gBAAgB,GAAG,IAAA,+BAAsB,EAAC,MAAM,EAAE,aAAa,CAAC,CAAC;wBACvE,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;oBACjE,CAAC,CAAC,CAAC;oBAEH,iBAAiB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;wBAChC,MAAM,aAAa,GAAG,IAAA,mCAAqB,EAAC,GAAG,EAAE,aAAa,CAAC,CAAC;wBAChE,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;wBAEzD,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,IAAA,2DAA0C,EAAC,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC;oBACtG,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,GAAG;YAClB,aAAa;YACb,WAAW;SACZ,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,qFAAqF;QACrF,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,KAAc,EAAE,EAAE;YAChD,IAAI,KAAK,YAAY,GAAG,EAAE;gBACxB,iGAAiG;gBACjG,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aAC1B;YACD,IAAI,KAAK,YAAY,GAAG,EAAE;gBACxB,iGAAiG;gBACjG,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;aAClC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,OAAO,IAAA,cAAI,EAAC,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACzD,IAAA,kBAAa,EAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;CACF;AApPD,oEAoPC","sourcesContent":["import { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport chalk from \"chalk\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport { GuStack } from \"../../constructs/core\";\nimport { GuLambdaFunction } from \"../../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n ClassName,\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFileExperimental {\n private readonly allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n\n private readonly riffRaffYaml: RiffRaffYaml;\n private readonly outdir: string;\n\n private isCdkStackPresent(\n expectedClassName: ClassName,\n expectedStack: StackTag,\n expectedRegion: Region,\n expectedStage: StageTag\n ): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const {\n constructor: { name },\n stack,\n stage,\n region,\n } = cdkStack;\n return (\n name === expectedClassName && stack === expectedStack && stage === expectedStage && region === expectedRegion\n );\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `GuStack`, `stack`, `region`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * For the class: MyApplicationStack\n *\n * ┌───────────────┬────────────────────────────┐\n * │ (index) │ eu-west-1 │\n * ├───────────────┼────────────────────────────┤\n * │ deploy │ { CODE: '✅', PROD: '✅' } │\n * │ media-service │ { CODE: '❌', PROD: '✅' } │\n * └───────────────┴────────────────────────────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<ClassName, Record<StackTag, Record<Region, Record<StageTag, Found | NotFound>>>>;\n\n const { allCdkStacks, allStackTags, allStageTags, allRegions } = this;\n\n const checks: AppValidation = allCdkStacks.reduce((accClassName, { constructor: { name } }) => {\n return {\n ...accClassName,\n [name]: allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allRegions.reduce((accRegion, region) => {\n return {\n ...accRegion,\n [region]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(name, stackTag, region, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {}),\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).flatMap((groupedByRegion) => {\n return Object.values(groupedByRegion).flatMap((groupedByStage) => {\n return Object.values(groupedByStage).filter((_) => _ === \"❌\");\n });\n });\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n Object.entries(checks).forEach(([className, detail]) => {\n console.log(`For the class: ${chalk.yellow(className)}`);\n console.table(detail);\n });\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n }\n\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const cfnDeployment = cloudFormationDeployment(stacks, artifactUploads, this.outdir);\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n lambdas.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n\n deployments.set(cfnDeployment.name, addAmiParametersToCloudFormationDeployment(cfnDeployment, asg));\n });\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}
@@ -1,14 +1,14 @@
1
1
  import type { GuStack } from "../../constructs/core";
2
- export declare type ClassName = string;
3
- export declare type StackTag = string;
4
- export declare type StageTag = string;
5
- export declare type Region = string;
6
- export declare type CdkStacksDifferingOnlyByStage = GuStack[];
2
+ export type ClassName = string;
3
+ export type StackTag = string;
4
+ export type StageTag = string;
5
+ export type Region = string;
6
+ export type CdkStacksDifferingOnlyByStage = GuStack[];
7
7
  export interface RiffRaffYaml {
8
8
  allowedStages: Set<StageTag>;
9
9
  deployments: Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>;
10
10
  }
11
- export declare type RiffRaffDeploymentName = string;
11
+ export type RiffRaffDeploymentName = string;
12
12
  export interface RiffRaffDeploymentProps {
13
13
  type: string;
14
14
  regions: Set<Region>;
@@ -23,5 +23,5 @@ export interface RiffRaffDeployment {
23
23
  name: RiffRaffDeploymentName;
24
24
  props: RiffRaffDeploymentProps;
25
25
  }
26
- export declare type GroupedCdkStacks = Record<ClassName, Record<StackTag, Record<Region, Record<StageTag, CdkStacksDifferingOnlyByStage>>>>;
26
+ export type GroupedCdkStacks = Record<ClassName, Record<StackTag, Record<Region, Record<StageTag, CdkStacksDifferingOnlyByStage>>>>;
27
27
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,oBAAY,SAAS,GAAG,MAAM,CAAC;AAC/B,oBAAY,QAAQ,GAAG,MAAM,CAAC;AAC9B,oBAAY,QAAQ,GAAG,MAAM,CAAC;AAC9B,oBAAY,MAAM,GAAG,MAAM,CAAC;AAC5B,oBAAY,6BAA6B,GAAG,OAAO,EAAE,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;CACnE;AAED,oBAAY,sBAAsB,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,YAAY,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,KAAK,EAAE,uBAAuB,CAAC;CAChC;AASD,oBAAY,gBAAgB,GAAG,MAAM,CACnC,SAAS,EACT,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAClF,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/experimental/riff-raff-yaml-file/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,MAAM,6BAA6B,GAAG,OAAO,EAAE,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;CACnE;AAED,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,YAAY,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,KAAK,EAAE,uBAAuB,CAAC;CAChC;AASD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CACnC,SAAS,EACT,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAClF,CAAC"}
@@ -4,7 +4,7 @@ import { Construct } from "constructs";
4
4
  import type { Http5xxAlarmProps, NoMonitoring } from "../constructs/cloudwatch";
5
5
  import type { AppIdentity, GuStack } from "../constructs/core";
6
6
  import type { GuLambdaFunction } from "../constructs/lambda";
7
- export declare type HttpMethod = "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE" | "PATCH";
7
+ export type HttpMethod = "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE" | "PATCH";
8
8
  export interface ApiTarget {
9
9
  /**
10
10
  * The path for the request (e.g. /test).
@@ -1 +1 @@
1
- {"version":3,"file":"api-multiple-lambdas.d.ts","sourceRoot":"","sources":["../../src/patterns/api-multiple-lambdas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAqB,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,oBAAY,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,iBAAiB,CAAC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,iCAAkC,SAAQ,YAAY,EAAE,WAAW;IAClF;;OAEG;IACH,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB;;;;;;;OAOG;IACH,uBAAuB,EAAE,YAAY,GAAG,gBAAgB,CAAC;CAC1D;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,4BAA6B,SAAQ,SAAS;IACzD,SAAgB,GAAG,EAAE,OAAO,CAAC;gBAEjB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iCAAiC;CAwBrE"}
1
+ {"version":3,"file":"api-multiple-lambdas.d.ts","sourceRoot":"","sources":["../../src/patterns/api-multiple-lambdas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAqB,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,iBAAiB,CAAC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,iCAAkC,SAAQ,YAAY,EAAE,WAAW;IAClF;;OAEG;IACH,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB;;;;;;;OAOG;IACH,uBAAuB,EAAE,YAAY,GAAG,gBAAgB,CAAC;CAC1D;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,4BAA6B,SAAQ,SAAS;IACzD,SAAgB,GAAG,EAAE,OAAO,CAAC;gBAEjB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iCAAiC;CAwBrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"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"}
@@ -234,11 +234,6 @@ class GuEc2App extends constructs_1.Construct {
234
234
  ...(blockDevices && { blockDevices }),
235
235
  imageRecipe,
236
236
  });
237
- // We are selectively tagging the ASG so that we can expose the number of stacks using this pattern
238
- // based on which autoscaling groups possess this tag. It may become useful or necessary to tag all resources in the future,
239
- // but we have decided that this is sufficient for now.
240
- // TODO: Do we need to tag all resources with this value? What would the use-cases be?
241
- aws_cdk_lib_1.Tags.of(autoScalingGroup).add(constants_1.MetadataKeys.PATTERN_NAME, this.constructor.name, { applyToLaunchedInstances: true });
242
237
  // This allows automatic shipping of instance Cloud Init logs when using the
243
238
  // `cdk-base` Amigo role on your AMI.
244
239
  aws_cdk_lib_1.Tags.of(autoScalingGroup).add(constants_1.MetadataKeys.LOG_KINESIS_STREAM_NAME, core_1.GuLoggingStreamNameParameter.getInstance(scope).valueAsString);
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration, Tags } from \"aws-cdk-lib\";\nimport type { BlockDevice } from \"aws-cdk-lib/aws-autoscaling\";\nimport { HealthCheck } from \"aws-cdk-lib/aws-autoscaling\";\nimport type { InstanceType, IPeer, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport { Port } from \"aws-cdk-lib/aws-ec2\";\nimport { ApplicationProtocol } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { Construct } from \"constructs\";\nimport { AccessScope, MetadataKeys, NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuCertificate } from \"../../constructs/acm\";\nimport type { GuUserDataProps } from \"../../constructs/autoscaling\";\nimport { GuAutoScalingGroup, GuUserData } from \"../../constructs/autoscaling\";\nimport type { Http5xxAlarmProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { GuAlb5xxPercentageAlarm, GuUnhealthyInstancesAlarm } from \"../../constructs/cloudwatch\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { AppIdentity, GuLoggingStreamNameParameter, GuStringParameter } from \"../../constructs/core\";\nimport { GuSecurityGroup, GuVpc, SubnetType } from \"../../constructs/ec2\";\nimport type { GuInstanceRoleProps } from \"../../constructs/iam\";\nimport { GuGetPrivateConfigPolicy, GuInstanceRole } from \"../../constructs/iam\";\nimport {\n GuApplicationLoadBalancer,\n GuApplicationTargetGroup,\n GuHttpsApplicationListener,\n} from \"../../constructs/loadbalancing\";\nimport { AppAccess } from \"../../types\";\nimport type { GuAsgCapacity, GuDomainName } from \"../../types\";\n\nexport interface AccessLoggingProps {\n enabled: boolean;\n prefix?: string;\n}\n\n/**\n * To ship your application logs to ELK automatically, you must:\n *\n * 1. Set the `enabled` flag to true\n * 2. Include the `cdk-base` Amigo role in your AMI\n * 3. Log to `journald`. We recommend doing this by logging to `stdout` and\n * using `systemd` to start your app\n * 4. Confirm that your [[`systemdUnitName`]] is configured properly.\n *\n * Unless you have explicitly opted-out, appropriate IAM permissions for logging\n * to Kinesis will be configured automatically via the [[`GuEc2App`]] pattern.\n */\nexport interface ApplicationLoggingProps {\n enabled: boolean;\n /**\n * Defaults to app name. That is, if your app runs as `<app>.service`\n * (e.g. `janus.service`), this will 'just work'.\n *\n * If it runs with a non-standard name, you will need to override the default\n * behavour. I.e. if your app is running as `some-different-name.service`, then\n * this prop should be set to `some-different-name`.\n */\n systemdUnitName?: string;\n}\n\nexport interface Alarms {\n snsTopicName: string;\n http5xxAlarm: false | Http5xxAlarmProps;\n unhealthyInstancesAlarm: boolean;\n noMonitoring?: false;\n}\n\n/**\n * Configuration options for the [[`GuEc2App`]] pattern.\n *\n * To grant EC2 instances additional IAM permissions, use the `roleConfiguration` prop. For example,\n * to allow your app to write to DynamoDB:\n *\n * ```typescript\n * // other props\n * roleConfiguration: {\n * additionalPolicies: [new GuDynamoDBWritePolicy(stack, \"DynamoTable\", { tableName: \"my-dynamo-table\" })],\n * }\n * ```\n *\n * To create alarms (recommended), use:\n * ```typescript\n * // other props\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * }\n * ```\n *\n * To opt out of creating alarms, use:\n *```typescript\n * // other props\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n *\n * To automatically ship application logs from `stdout` to ELK, use:\n *\n * ```typescript\n * {\n * // other props\n * applicationLogging: { enabled: true }\n * }\n * ```\n *\n * For more details on the requirements for application log shipping, see [[`ApplicationLoggingProps`]].\n *\n * To enable access logging for your load balancer, you can specify the prefix to write the logs to.\n * The S3 bucket used to hold these access logs must be specified in SSM at `/account/services/access-logging/bucket`\n * You must specify a region in your stack declaration if you are to use this prop, as specified here:\n * https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix\n * For example:\n * ```typescript\n * {\n * // other props\n * accessLogging: {\n * enabled: true,\n * prefix: \"my-application-logs\"\n * }\n * }\n *\n * If you would like to enable access logging at the root of the S3 bucket (ie without a prefix), you can omit the prefix\n * For example:\n * ```typescript\n * {\n * // other props\n * accessLogging: {\n * enabled: true,\n * }\n * }\n * ```\n */\nexport interface GuEc2AppProps extends AppIdentity {\n userData: GuUserDataProps | string;\n access: AppAccess;\n applicationPort: number;\n roleConfiguration?: GuInstanceRoleProps;\n monitoringConfiguration: Alarms | NoMonitoring;\n instanceType: InstanceType;\n applicationLogging?: ApplicationLoggingProps;\n accessLogging?: AccessLoggingProps;\n blockDevices?: BlockDevice[];\n scaling: GuAsgCapacity;\n certificateProps: GuDomainName;\n withoutImdsv2?: boolean;\n imageRecipe?: string;\n vpc?: IVpc;\n privateSubnets?: ISubnet[];\n publicSubnets?: ISubnet[];\n}\n\nfunction restrictedCidrRanges(ranges: IPeer[]) {\n return ranges.map((range) => ({\n range,\n port: Port.tcp(443),\n description: `Allow access on port 443 from ${range.uniqueId}`,\n }));\n}\n\n/**\n * Pattern which creates the resources needed to run an application on EC2 instances.\n * For convenience, you may wish to use [[`GuPlayApp`]] or [[`GuNodeApp`]], which extend this class.\n *\n * This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on\n * this, see [[`GuInstanceRole`]]. To add additional permissions to your EC2 instances, see [[`GuEc2AppProps`]].\n *\n * This pattern will automatically create security groups/rules which allow for:\n * 1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the\n * [[`AppAccess`]] specified).\n * 2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.\n * 3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).\n *\n * Example usage for a public facing app (open to the internet):\n * ```typescript\n * new GuEc2App(stack, {\n * applicationPort: 1234,\n * app: \"app-name\",\n * access: { scope: AccessScope.PUBLIC },\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),\n * certificateProps:{\n * domainName: \"prod-guardian.com\",\n * },\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * },\n * userData: {\n * distributable: {\n * fileName: \"app-name.deb\",\n * executionStatement: `dpkg -i /app-name/app-name.deb`,\n * }\n * },\n * });\n * ```\n *\n * Example usage for an app which is restricted to specific CIDR ranges:\n * ```typescript\n * new GuEc2App(stack, {\n * applicationPort: 1234,\n * app: \"app-name\",\n * access: {\n * scope: AccessScope.RESTRICTED,\n * cidrRanges: [Peer.ipv4(\"192.168.1.1/32\"), Peer.ipv4(\"8.8.8.8/32\")],\n * },\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),\n * certificateProps:{\n * domainName: \"prod-guardian.com\",\n * },\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * }\n * userData: {\n * distributable: {\n * fileName: \"app-name.deb\",\n * executionStatement: `dpkg -i /app-name/app-name.deb`,\n * }\n * },\n * });\n * ```\n *\n * ### Varying values by stage\n *\n * There are times when you want a resource's configuration to be stage aware,\n * for example the number of instances in an ASG.\n *\n * To do this, we can use a simple ternary:\n * ```typescript\n * new GuEc2App(this, {\n * // other required properties\n * scaling: this.stage === \"PROD\" ? { minimumInstances: 6 } : { minimumInstances: 1 }\n * });\n * ```\n *\n * If multiple properties need to be stage aware, consider encoding this into the `props` of the calling class:\n *\n * ```typescript\n * export interface MyAppProps extends GuStackProps {\n * domainName: string;\n * scaling: GuAsgCapacity;\n * monitoringConfiguration: Alarms | NoMonitoring;\n * }\n *\n * export class MyApp extends GuStack {\n * private static app = \"cdk-playground\";\n *\n * constructor(scope: App, id: string, props: MyAppProps) {\n * const { stage, domainName, scaling, monitoringConfiguration } = props;\n *\n * super(scope, id, props);\n *\n * new GuPlayApp(this, {\n * app: \"my-app\",\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),\n * access: { scope: AccessScope.PUBLIC },\n * userData: {\n * distributable: {\n * fileName: `my-app.deb`,\n * executionStatement: `dpkg -i /my-app/my-app.deb`,\n * },\n * },\n * certificateProps: {\n * domainName,\n * },\n * monitoringConfiguration,\n * scaling,\n * });\n * }\n * }\n *\n * new MyApp(app, \"MyApp-CODE\", {\n * stage: \"CODE\",\n * domainName: \"my-app.code.dev-gutools.co.uk\",\n * scaling: { minimumInstances: 1 },\n * monitoringConfiguration: { noMonitoring: true },\n * });\n *\n * new MyApp(app, \"MyApp-PROD\", {\n * stage: \"PROD\",\n * domainName: \"my-app.prod.gutools.co.uk\",\n * scaling: { minimumInstances: 6 },\n * monitoringConfiguration: {\n * // config to enable alarms in PROD\n * },\n * });\n * ```\n *\n * If you _must_ support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which\n * instances will be started. You need to set the three props below in order for this to work:\n * vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from `Vpc.fromVpcAttributes`)\n * privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually\n * obtained from `GuVpc.subnets`)\n * publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer\n * is intended for public access (usually obtained from `GuVpc.subnets`)\n * On the other hand, if the access is private, then an \"internal\" loadbalancer is used in the `privateSubnets` list.\n * Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as\n * an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting\n * Cloudformation will fail to deploy.\n *\n * ### Customising the infrastructure generated by this pattern\n *\n * Although we allow users to customise many aspects of their infrastructure via [[`GuEc2AppProps`]], it's possible\n * that there are less common use-cases which are currently unsupported via the API. In these circumstances escape\n * hatches can be used to override specific resources in the stack.\n *\n * In order to do this:\n *\n * 1. Create desired resource using Guardian or AWS constructs, for example:\n * ```typescript\n * const sg = new GuSecurityGroup(\n * // custom parameters\n * );\n * ```\n * 2. Access the CloudFormation version of the resource that you wish to customise, for example:\n * ```typescript\n * const pattern = new GuEc2App(\n * // all parameters\n * )\n * const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;\n * ```\n * 3. Replace the resource generated by the pattern with your bespoke resource, for example:\n * ```typescript\n * cfnLb.securityGroups = [sg.securityGroupId];\n * ```\n */\nexport class GuEc2App extends Construct {\n /*\n * These are public for now, as this allows users to\n * modify these constructs as desired to fit their\n * specific needs.\n * In the future, we might build functionality to better enable users\n * to access in-pattern constructs, but this would allow teams to be unblocked\n * in the short term.\n * */\n public readonly vpc: IVpc;\n public readonly certificate: GuCertificate;\n public readonly loadBalancer: GuApplicationLoadBalancer;\n public readonly autoScalingGroup: GuAutoScalingGroup;\n public readonly listener: GuHttpsApplicationListener;\n public readonly targetGroup: GuApplicationTargetGroup;\n\n constructor(scope: GuStack, props: GuEc2AppProps) {\n const {\n access,\n accessLogging = { enabled: false },\n app,\n // We should update this default once a significant number of apps have migrated to devx-logs\n applicationLogging = { enabled: false },\n applicationPort,\n blockDevices,\n certificateProps: { domainName, hostedZoneId },\n instanceType,\n monitoringConfiguration,\n roleConfiguration = { withoutLogShipping: false, additionalPolicies: [] },\n scaling: { minimumInstances, maximumInstances = minimumInstances * 2 },\n userData,\n withoutImdsv2,\n imageRecipe,\n vpc = GuVpc.fromIdParameter(scope, AppIdentity.suffixText({ app }, \"VPC\")),\n privateSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PRIVATE, app }),\n publicSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PUBLIC, app }),\n } = props;\n\n super(scope, app); // The assumption is `app` is unique\n\n // We should really prevent users from doing this via the type system,\n // but that requires a breaking change to the API\n if (applicationLogging.enabled && roleConfiguration.withoutLogShipping) {\n throw new Error(\n \"Application logging has been enabled (via the `applicationLogging` prop) but your `roleConfiguration` sets \" +\n \"`withoutLogShipping` to true. Please turn off application logging or remove `withoutLogShipping`\"\n );\n }\n\n AppAccess.validate(access);\n\n const certificate = new GuCertificate(scope, {\n app,\n domainName,\n hostedZoneId,\n });\n\n const maybePrivateConfigPolicy =\n typeof userData !== \"string\" && userData.configuration\n ? [new GuGetPrivateConfigPolicy(scope, \"GetPrivateConfigFromS3Policy\", userData.configuration)]\n : [];\n\n const mergedRoleConfiguration: GuInstanceRoleProps = {\n withoutLogShipping: roleConfiguration.withoutLogShipping,\n additionalPolicies: maybePrivateConfigPolicy.concat(roleConfiguration.additionalPolicies ?? []),\n };\n\n const autoScalingGroup = new GuAutoScalingGroup(scope, \"AutoScalingGroup\", {\n app,\n vpc,\n instanceType,\n minimumInstances,\n maximumInstances,\n withoutImdsv2,\n role: new GuInstanceRole(scope, { app, ...mergedRoleConfiguration }),\n healthCheck: HealthCheck.elb({ grace: Duration.minutes(2) }), // should this be defaulted at pattern or construct level?\n userData: typeof userData !== \"string\" ? new GuUserData(scope, { app, ...userData }).userData : userData,\n vpcSubnets: { subnets: privateSubnets },\n ...(blockDevices && { blockDevices }),\n imageRecipe,\n });\n\n // We are selectively tagging the ASG so that we can expose the number of stacks using this pattern\n // based on which autoscaling groups possess this tag. It may become useful or necessary to tag all resources in the future,\n // but we have decided that this is sufficient for now.\n // TODO: Do we need to tag all resources with this value? What would the use-cases be?\n Tags.of(autoScalingGroup).add(MetadataKeys.PATTERN_NAME, this.constructor.name, { applyToLaunchedInstances: true });\n\n // This allows automatic shipping of instance Cloud Init logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.LOG_KINESIS_STREAM_NAME,\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString\n );\n\n if (applicationLogging.enabled) {\n // This allows automatic shipping of application logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.SYSTEMD_UNIT,\n applicationLogging.systemdUnitName ? `${applicationLogging.systemdUnitName}.service` : `${app}.service`\n );\n }\n\n const loadBalancer = new GuApplicationLoadBalancer(scope, \"LoadBalancer\", {\n app,\n vpc,\n // Setting internetFacing to true does not necessarily allow public access to the load balancer itself. That is handled by the listener's `open` prop.\n internetFacing: access.scope !== AccessScope.INTERNAL,\n vpcSubnets: {\n subnets: access.scope === AccessScope.INTERNAL ? privateSubnets : publicSubnets,\n },\n });\n\n if (accessLogging.enabled) {\n const accessLoggingBucket = new GuStringParameter(scope, \"AccessLoggingBucket\", {\n description: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.path,\n fromSSM: true,\n });\n\n loadBalancer.logAccessLogs(\n Bucket.fromBucketName(\n scope,\n AppIdentity.suffixText(props, \"AccessLoggingBucket\"),\n accessLoggingBucket.valueAsString\n ),\n accessLogging.prefix\n );\n }\n\n const targetGroup = new GuApplicationTargetGroup(scope, \"TargetGroup\", {\n app,\n vpc,\n protocol: ApplicationProtocol.HTTP,\n targets: [autoScalingGroup],\n port: applicationPort,\n });\n\n const listener = new GuHttpsApplicationListener(scope, \"Listener\", {\n app,\n loadBalancer,\n certificate,\n targetGroup,\n // When open=true, AWS will create a security group which allows all inbound traffic over HTTPS\n open: access.scope === AccessScope.PUBLIC,\n });\n\n // Since AWS won't create a security group automatically when open=false, we need to add our own\n if (access.scope !== AccessScope.PUBLIC) {\n loadBalancer.addSecurityGroup(\n new GuSecurityGroup(scope, `${access.scope}IngressSecurityGroup`, {\n app,\n vpc,\n description: \"Allow restricted ingress from CIDR ranges\",\n allowAllOutbound: false,\n ingresses: restrictedCidrRanges(access.cidrRanges),\n })\n );\n }\n\n if (!monitoringConfiguration.noMonitoring) {\n const { http5xxAlarm, snsTopicName, unhealthyInstancesAlarm } = monitoringConfiguration;\n\n if (http5xxAlarm) {\n new GuAlb5xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http5xxAlarm,\n });\n }\n if (unhealthyInstancesAlarm) {\n new GuUnhealthyInstancesAlarm(scope, {\n app,\n targetGroup,\n snsTopicName,\n });\n }\n }\n\n this.vpc = vpc;\n this.certificate = certificate;\n this.loadBalancer = loadBalancer;\n this.autoScalingGroup = autoScalingGroup;\n this.listener = listener;\n this.targetGroup = targetGroup;\n }\n}\n"]}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/patterns/ec2-app/base.ts"],"names":[],"mappings":";;;AAAA,6CAA6C;AAE7C,iEAA0D;AAE1D,iDAA2C;AAC3C,uFAA6E;AAC7E,+CAA4C;AAC5C,2CAAuC;AACvC,+CAAuF;AACvF,8CAAqD;AAErD,8DAA8E;AAE9E,4DAAiG;AAEjG,gDAAqG;AACrG,8CAA0E;AAE1E,8CAAgF;AAChF,kEAIwC;AACxC,uCAAwC;AA8HxC,SAAS,oBAAoB,CAAC,MAAe;IAC3C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,KAAK;QACL,IAAI,EAAE,cAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACnB,WAAW,EAAE,iCAAiC,KAAK,CAAC,QAAQ,EAAE;KAC/D,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2KG;AACH,MAAa,QAAS,SAAQ,sBAAS;IAgBrC,YAAY,KAAc,EAAE,KAAoB;QAC9C,MAAM,EACJ,MAAM,EACN,aAAa,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAClC,GAAG;QACH,6FAA6F;QAC7F,kBAAkB,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EACvC,eAAe,EACf,YAAY,EACZ,gBAAgB,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,EAC9C,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,EAAE,EACzE,OAAO,EAAE,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,CAAC,EAAE,EACtE,QAAQ,EACR,aAAa,EACb,WAAW,EACX,GAAG,GAAG,WAAK,CAAC,eAAe,CAAC,KAAK,EAAE,kBAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,EAC1E,cAAc,GAAG,WAAK,CAAC,oBAAoB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAU,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,EACrF,aAAa,GAAG,WAAK,CAAC,oBAAoB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAU,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GACpF,GAAG,KAAK,CAAC;QAEV,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,oCAAoC;QAEvD,sEAAsE;QACtE,iDAAiD;QACjD,IAAI,kBAAkB,CAAC,OAAO,IAAI,iBAAiB,CAAC,kBAAkB,EAAE;YACtE,MAAM,IAAI,KAAK,CACb,6GAA6G;gBAC3G,kGAAkG,CACrG,CAAC;SACH;QAED,iBAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAE3B,MAAM,WAAW,GAAG,IAAI,mBAAa,CAAC,KAAK,EAAE;YAC3C,GAAG;YACH,UAAU;YACV,YAAY;SACb,CAAC,CAAC;QAEH,MAAM,wBAAwB,GAC5B,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,aAAa;YACpD,CAAC,CAAC,CAAC,IAAI,8BAAwB,CAAC,KAAK,EAAE,8BAA8B,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;YAC/F,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,uBAAuB,GAAwB;YACnD,kBAAkB,EAAE,iBAAiB,CAAC,kBAAkB;YACxD,kBAAkB,EAAE,wBAAwB,CAAC,MAAM,CAAC,iBAAiB,CAAC,kBAAkB,IAAI,EAAE,CAAC;SAChG,CAAC;QAEF,MAAM,gBAAgB,GAAG,IAAI,gCAAkB,CAAC,KAAK,EAAE,kBAAkB,EAAE;YACzE,GAAG;YACH,GAAG;YACH,YAAY;YACZ,gBAAgB;YAChB,gBAAgB;YAChB,aAAa;YACb,IAAI,EAAE,IAAI,oBAAc,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,uBAAuB,EAAE,CAAC;YACpE,WAAW,EAAE,6BAAW,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,sBAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,QAAQ,EAAE,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,wBAAU,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;YACxG,UAAU,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE;YACvC,GAAG,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,CAAC;YACrC,WAAW;SACZ,CAAC,CAAC;QAEH,4EAA4E;QAC5E,qCAAqC;QACrC,kBAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAC3B,wBAAY,CAAC,uBAAuB,EACpC,mCAA4B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAAa,CAC9D,CAAC;QAEF,IAAI,kBAAkB,CAAC,OAAO,EAAE;YAC9B,oEAAoE;YACpE,qCAAqC;YACrC,kBAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAC3B,wBAAY,CAAC,YAAY,EACzB,kBAAkB,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,eAAe,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU,CACxG,CAAC;SACH;QAED,MAAM,YAAY,GAAG,IAAI,yCAAyB,CAAC,KAAK,EAAE,cAAc,EAAE;YACxE,GAAG;YACH,GAAG;YACH,sJAAsJ;YACtJ,cAAc,EAAE,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,QAAQ;YACrD,UAAU,EAAE;gBACV,OAAO,EAAE,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa;aAChF;SACF,CAAC,CAAC;QAEH,IAAI,aAAa,CAAC,OAAO,EAAE;YACzB,MAAM,mBAAmB,GAAG,IAAI,wBAAiB,CAAC,KAAK,EAAE,qBAAqB,EAAE;gBAC9E,WAAW,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,WAAW;gBACtE,OAAO,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,IAAI;gBAC3D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YAEH,YAAY,CAAC,aAAa,CACxB,eAAM,CAAC,cAAc,CACnB,KAAK,EACL,kBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,qBAAqB,CAAC,EACpD,mBAAmB,CAAC,aAAa,CAClC,EACD,aAAa,CAAC,MAAM,CACrB,CAAC;SACH;QAED,MAAM,WAAW,GAAG,IAAI,wCAAwB,CAAC,KAAK,EAAE,aAAa,EAAE;YACrE,GAAG;YACH,GAAG;YACH,QAAQ,EAAE,gDAAmB,CAAC,IAAI;YAClC,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,IAAI,EAAE,eAAe;SACtB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,0CAA0B,CAAC,KAAK,EAAE,UAAU,EAAE;YACjE,GAAG;YACH,YAAY;YACZ,WAAW;YACX,WAAW;YACX,+FAA+F;YAC/F,IAAI,EAAE,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,MAAM;SAC1C,CAAC,CAAC;QAEH,gGAAgG;QAChG,IAAI,MAAM,CAAC,KAAK,KAAK,uBAAW,CAAC,MAAM,EAAE;YACvC,YAAY,CAAC,gBAAgB,CAC3B,IAAI,qBAAe,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,sBAAsB,EAAE;gBAChE,GAAG;gBACH,GAAG;gBACH,WAAW,EAAE,2CAA2C;gBACxD,gBAAgB,EAAE,KAAK;gBACvB,SAAS,EAAE,oBAAoB,CAAC,MAAM,CAAC,UAAU,CAAC;aACnD,CAAC,CACH,CAAC;SACH;QAED,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE;YACzC,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,uBAAuB,EAAE,GAAG,uBAAuB,CAAC;YAExF,IAAI,YAAY,EAAE;gBAChB,IAAI,oCAAuB,CAAC,KAAK,EAAE;oBACjC,GAAG;oBACH,YAAY;oBACZ,YAAY;oBACZ,GAAG,YAAY;iBAChB,CAAC,CAAC;aACJ;YACD,IAAI,uBAAuB,EAAE;gBAC3B,IAAI,sCAAyB,CAAC,KAAK,EAAE;oBACnC,GAAG;oBACH,WAAW;oBACX,YAAY;iBACb,CAAC,CAAC;aACJ;SACF;QAED,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAtLD,4BAsLC","sourcesContent":["import { Duration, Tags } from \"aws-cdk-lib\";\nimport type { BlockDevice } from \"aws-cdk-lib/aws-autoscaling\";\nimport { HealthCheck } from \"aws-cdk-lib/aws-autoscaling\";\nimport type { InstanceType, IPeer, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport { Port } from \"aws-cdk-lib/aws-ec2\";\nimport { ApplicationProtocol } from \"aws-cdk-lib/aws-elasticloadbalancingv2\";\nimport { Bucket } from \"aws-cdk-lib/aws-s3\";\nimport { Construct } from \"constructs\";\nimport { AccessScope, MetadataKeys, NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuCertificate } from \"../../constructs/acm\";\nimport type { GuUserDataProps } from \"../../constructs/autoscaling\";\nimport { GuAutoScalingGroup, GuUserData } from \"../../constructs/autoscaling\";\nimport type { Http5xxAlarmProps, NoMonitoring } from \"../../constructs/cloudwatch\";\nimport { GuAlb5xxPercentageAlarm, GuUnhealthyInstancesAlarm } from \"../../constructs/cloudwatch\";\nimport type { GuStack } from \"../../constructs/core\";\nimport { AppIdentity, GuLoggingStreamNameParameter, GuStringParameter } from \"../../constructs/core\";\nimport { GuSecurityGroup, GuVpc, SubnetType } from \"../../constructs/ec2\";\nimport type { GuInstanceRoleProps } from \"../../constructs/iam\";\nimport { GuGetPrivateConfigPolicy, GuInstanceRole } from \"../../constructs/iam\";\nimport {\n GuApplicationLoadBalancer,\n GuApplicationTargetGroup,\n GuHttpsApplicationListener,\n} from \"../../constructs/loadbalancing\";\nimport { AppAccess } from \"../../types\";\nimport type { GuAsgCapacity, GuDomainName } from \"../../types\";\n\nexport interface AccessLoggingProps {\n enabled: boolean;\n prefix?: string;\n}\n\n/**\n * To ship your application logs to ELK automatically, you must:\n *\n * 1. Set the `enabled` flag to true\n * 2. Include the `cdk-base` Amigo role in your AMI\n * 3. Log to `journald`. We recommend doing this by logging to `stdout` and\n * using `systemd` to start your app\n * 4. Confirm that your [[`systemdUnitName`]] is configured properly.\n *\n * Unless you have explicitly opted-out, appropriate IAM permissions for logging\n * to Kinesis will be configured automatically via the [[`GuEc2App`]] pattern.\n */\nexport interface ApplicationLoggingProps {\n enabled: boolean;\n /**\n * Defaults to app name. That is, if your app runs as `<app>.service`\n * (e.g. `janus.service`), this will 'just work'.\n *\n * If it runs with a non-standard name, you will need to override the default\n * behavour. I.e. if your app is running as `some-different-name.service`, then\n * this prop should be set to `some-different-name`.\n */\n systemdUnitName?: string;\n}\n\nexport interface Alarms {\n snsTopicName: string;\n http5xxAlarm: false | Http5xxAlarmProps;\n unhealthyInstancesAlarm: boolean;\n noMonitoring?: false;\n}\n\n/**\n * Configuration options for the [[`GuEc2App`]] pattern.\n *\n * To grant EC2 instances additional IAM permissions, use the `roleConfiguration` prop. For example,\n * to allow your app to write to DynamoDB:\n *\n * ```typescript\n * // other props\n * roleConfiguration: {\n * additionalPolicies: [new GuDynamoDBWritePolicy(stack, \"DynamoTable\", { tableName: \"my-dynamo-table\" })],\n * }\n * ```\n *\n * To create alarms (recommended), use:\n * ```typescript\n * // other props\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * }\n * ```\n *\n * To opt out of creating alarms, use:\n *```typescript\n * // other props\n * monitoringConfiguration: { noMonitoring: true }\n * ```\n *\n * To automatically ship application logs from `stdout` to ELK, use:\n *\n * ```typescript\n * {\n * // other props\n * applicationLogging: { enabled: true }\n * }\n * ```\n *\n * For more details on the requirements for application log shipping, see [[`ApplicationLoggingProps`]].\n *\n * To enable access logging for your load balancer, you can specify the prefix to write the logs to.\n * The S3 bucket used to hold these access logs must be specified in SSM at `/account/services/access-logging/bucket`\n * You must specify a region in your stack declaration if you are to use this prop, as specified here:\n * https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html#logwbraccesswbrlogsbucket-prefix\n * For example:\n * ```typescript\n * {\n * // other props\n * accessLogging: {\n * enabled: true,\n * prefix: \"my-application-logs\"\n * }\n * }\n *\n * If you would like to enable access logging at the root of the S3 bucket (ie without a prefix), you can omit the prefix\n * For example:\n * ```typescript\n * {\n * // other props\n * accessLogging: {\n * enabled: true,\n * }\n * }\n * ```\n */\nexport interface GuEc2AppProps extends AppIdentity {\n userData: GuUserDataProps | string;\n access: AppAccess;\n applicationPort: number;\n roleConfiguration?: GuInstanceRoleProps;\n monitoringConfiguration: Alarms | NoMonitoring;\n instanceType: InstanceType;\n applicationLogging?: ApplicationLoggingProps;\n accessLogging?: AccessLoggingProps;\n blockDevices?: BlockDevice[];\n scaling: GuAsgCapacity;\n certificateProps: GuDomainName;\n withoutImdsv2?: boolean;\n imageRecipe?: string;\n vpc?: IVpc;\n privateSubnets?: ISubnet[];\n publicSubnets?: ISubnet[];\n}\n\nfunction restrictedCidrRanges(ranges: IPeer[]) {\n return ranges.map((range) => ({\n range,\n port: Port.tcp(443),\n description: `Allow access on port 443 from ${range.uniqueId}`,\n }));\n}\n\n/**\n * Pattern which creates the resources needed to run an application on EC2 instances.\n * For convenience, you may wish to use [[`GuPlayApp`]] or [[`GuNodeApp`]], which extend this class.\n *\n * This pattern will grant your EC2 instances a number of commonly needed IAM permissions. For more information on\n * this, see [[`GuInstanceRole`]]. To add additional permissions to your EC2 instances, see [[`GuEc2AppProps`]].\n *\n * This pattern will automatically create security groups/rules which allow for:\n * 1. Incoming traffic over HTTPS (from the whole internet or from the specified CIDR ranges, depending on the\n * [[`AppAccess`]] specified).\n * 2. Communication between the load balancer and the EC2 instances over HTTP, via the specified application port.\n * 3. Outbound traffic from your EC2 instances over HTTPS (to enable communication with third-party APIs).\n *\n * Example usage for a public facing app (open to the internet):\n * ```typescript\n * new GuEc2App(stack, {\n * applicationPort: 1234,\n * app: \"app-name\",\n * access: { scope: AccessScope.PUBLIC },\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),\n * certificateProps:{\n * domainName: \"prod-guardian.com\",\n * },\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * },\n * userData: {\n * distributable: {\n * fileName: \"app-name.deb\",\n * executionStatement: `dpkg -i /app-name/app-name.deb`,\n * }\n * },\n * });\n * ```\n *\n * Example usage for an app which is restricted to specific CIDR ranges:\n * ```typescript\n * new GuEc2App(stack, {\n * applicationPort: 1234,\n * app: \"app-name\",\n * access: {\n * scope: AccessScope.RESTRICTED,\n * cidrRanges: [Peer.ipv4(\"192.168.1.1/32\"), Peer.ipv4(\"8.8.8.8/32\")],\n * },\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MEDIUM),\n * certificateProps:{\n * domainName: \"prod-guardian.com\",\n * },\n * monitoringConfiguration: {\n * snsTopicName: \"alerts-topic-for-my-team\",\n * http5xxAlarm: {\n * tolerated5xxPercentage: 1,\n * },\n * unhealthyInstancesAlarm: true,\n * }\n * userData: {\n * distributable: {\n * fileName: \"app-name.deb\",\n * executionStatement: `dpkg -i /app-name/app-name.deb`,\n * }\n * },\n * });\n * ```\n *\n * ### Varying values by stage\n *\n * There are times when you want a resource's configuration to be stage aware,\n * for example the number of instances in an ASG.\n *\n * To do this, we can use a simple ternary:\n * ```typescript\n * new GuEc2App(this, {\n * // other required properties\n * scaling: this.stage === \"PROD\" ? { minimumInstances: 6 } : { minimumInstances: 1 }\n * });\n * ```\n *\n * If multiple properties need to be stage aware, consider encoding this into the `props` of the calling class:\n *\n * ```typescript\n * export interface MyAppProps extends GuStackProps {\n * domainName: string;\n * scaling: GuAsgCapacity;\n * monitoringConfiguration: Alarms | NoMonitoring;\n * }\n *\n * export class MyApp extends GuStack {\n * private static app = \"cdk-playground\";\n *\n * constructor(scope: App, id: string, props: MyAppProps) {\n * const { stage, domainName, scaling, monitoringConfiguration } = props;\n *\n * super(scope, id, props);\n *\n * new GuPlayApp(this, {\n * app: \"my-app\",\n * instanceType: InstanceType.of(InstanceClass.T4G, InstanceSize.MICRO),\n * access: { scope: AccessScope.PUBLIC },\n * userData: {\n * distributable: {\n * fileName: `my-app.deb`,\n * executionStatement: `dpkg -i /my-app/my-app.deb`,\n * },\n * },\n * certificateProps: {\n * domainName,\n * },\n * monitoringConfiguration,\n * scaling,\n * });\n * }\n * }\n *\n * new MyApp(app, \"MyApp-CODE\", {\n * stage: \"CODE\",\n * domainName: \"my-app.code.dev-gutools.co.uk\",\n * scaling: { minimumInstances: 1 },\n * monitoringConfiguration: { noMonitoring: true },\n * });\n *\n * new MyApp(app, \"MyApp-PROD\", {\n * stage: \"PROD\",\n * domainName: \"my-app.prod.gutools.co.uk\",\n * scaling: { minimumInstances: 6 },\n * monitoringConfiguration: {\n * // config to enable alarms in PROD\n * },\n * });\n * ```\n *\n * If you _must_ support a non-standard VPC setup, it's possible to override the VPC and subnet selection into which\n * instances will be started. You need to set the three props below in order for this to work:\n * vpc: this must be an IVpc instance indicating the VPC to deploy into (usually obtained from `Vpc.fromVpcAttributes`)\n * privateSubnets: a list of ISubnet indicating the subnets for the autoscaling group to deploy instances into (usually\n * obtained from `GuVpc.subnets`)\n * publicSubnets: a list of ISubnet indicating the subnets for the loadbalancer to use, if the loadbalancer\n * is intended for public access (usually obtained from `GuVpc.subnets`)\n * On the other hand, if the access is private, then an \"internal\" loadbalancer is used in the `privateSubnets` list.\n * Please note that no checking is applied to the subnet lists to ensure that they correspond to the vpc given; as\n * an advanced feature it is assumed that the caller ensures this. If the subnets are mismatched then the resulting\n * Cloudformation will fail to deploy.\n *\n * ### Customising the infrastructure generated by this pattern\n *\n * Although we allow users to customise many aspects of their infrastructure via [[`GuEc2AppProps`]], it's possible\n * that there are less common use-cases which are currently unsupported via the API. In these circumstances escape\n * hatches can be used to override specific resources in the stack.\n *\n * In order to do this:\n *\n * 1. Create desired resource using Guardian or AWS constructs, for example:\n * ```typescript\n * const sg = new GuSecurityGroup(\n * // custom parameters\n * );\n * ```\n * 2. Access the CloudFormation version of the resource that you wish to customise, for example:\n * ```typescript\n * const pattern = new GuEc2App(\n * // all parameters\n * )\n * const cfnLb = pattern.loadBalancer.node.defaultChild as CfnLoadBalancer;\n * ```\n * 3. Replace the resource generated by the pattern with your bespoke resource, for example:\n * ```typescript\n * cfnLb.securityGroups = [sg.securityGroupId];\n * ```\n */\nexport class GuEc2App extends Construct {\n /*\n * These are public for now, as this allows users to\n * modify these constructs as desired to fit their\n * specific needs.\n * In the future, we might build functionality to better enable users\n * to access in-pattern constructs, but this would allow teams to be unblocked\n * in the short term.\n * */\n public readonly vpc: IVpc;\n public readonly certificate: GuCertificate;\n public readonly loadBalancer: GuApplicationLoadBalancer;\n public readonly autoScalingGroup: GuAutoScalingGroup;\n public readonly listener: GuHttpsApplicationListener;\n public readonly targetGroup: GuApplicationTargetGroup;\n\n constructor(scope: GuStack, props: GuEc2AppProps) {\n const {\n access,\n accessLogging = { enabled: false },\n app,\n // We should update this default once a significant number of apps have migrated to devx-logs\n applicationLogging = { enabled: false },\n applicationPort,\n blockDevices,\n certificateProps: { domainName, hostedZoneId },\n instanceType,\n monitoringConfiguration,\n roleConfiguration = { withoutLogShipping: false, additionalPolicies: [] },\n scaling: { minimumInstances, maximumInstances = minimumInstances * 2 },\n userData,\n withoutImdsv2,\n imageRecipe,\n vpc = GuVpc.fromIdParameter(scope, AppIdentity.suffixText({ app }, \"VPC\")),\n privateSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PRIVATE, app }),\n publicSubnets = GuVpc.subnetsFromParameter(scope, { type: SubnetType.PUBLIC, app }),\n } = props;\n\n super(scope, app); // The assumption is `app` is unique\n\n // We should really prevent users from doing this via the type system,\n // but that requires a breaking change to the API\n if (applicationLogging.enabled && roleConfiguration.withoutLogShipping) {\n throw new Error(\n \"Application logging has been enabled (via the `applicationLogging` prop) but your `roleConfiguration` sets \" +\n \"`withoutLogShipping` to true. Please turn off application logging or remove `withoutLogShipping`\"\n );\n }\n\n AppAccess.validate(access);\n\n const certificate = new GuCertificate(scope, {\n app,\n domainName,\n hostedZoneId,\n });\n\n const maybePrivateConfigPolicy =\n typeof userData !== \"string\" && userData.configuration\n ? [new GuGetPrivateConfigPolicy(scope, \"GetPrivateConfigFromS3Policy\", userData.configuration)]\n : [];\n\n const mergedRoleConfiguration: GuInstanceRoleProps = {\n withoutLogShipping: roleConfiguration.withoutLogShipping,\n additionalPolicies: maybePrivateConfigPolicy.concat(roleConfiguration.additionalPolicies ?? []),\n };\n\n const autoScalingGroup = new GuAutoScalingGroup(scope, \"AutoScalingGroup\", {\n app,\n vpc,\n instanceType,\n minimumInstances,\n maximumInstances,\n withoutImdsv2,\n role: new GuInstanceRole(scope, { app, ...mergedRoleConfiguration }),\n healthCheck: HealthCheck.elb({ grace: Duration.minutes(2) }), // should this be defaulted at pattern or construct level?\n userData: typeof userData !== \"string\" ? new GuUserData(scope, { app, ...userData }).userData : userData,\n vpcSubnets: { subnets: privateSubnets },\n ...(blockDevices && { blockDevices }),\n imageRecipe,\n });\n\n // This allows automatic shipping of instance Cloud Init logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.LOG_KINESIS_STREAM_NAME,\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString\n );\n\n if (applicationLogging.enabled) {\n // This allows automatic shipping of application logs when using the\n // `cdk-base` Amigo role on your AMI.\n Tags.of(autoScalingGroup).add(\n MetadataKeys.SYSTEMD_UNIT,\n applicationLogging.systemdUnitName ? `${applicationLogging.systemdUnitName}.service` : `${app}.service`\n );\n }\n\n const loadBalancer = new GuApplicationLoadBalancer(scope, \"LoadBalancer\", {\n app,\n vpc,\n // Setting internetFacing to true does not necessarily allow public access to the load balancer itself. That is handled by the listener's `open` prop.\n internetFacing: access.scope !== AccessScope.INTERNAL,\n vpcSubnets: {\n subnets: access.scope === AccessScope.INTERNAL ? privateSubnets : publicSubnets,\n },\n });\n\n if (accessLogging.enabled) {\n const accessLoggingBucket = new GuStringParameter(scope, \"AccessLoggingBucket\", {\n description: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.path,\n fromSSM: true,\n });\n\n loadBalancer.logAccessLogs(\n Bucket.fromBucketName(\n scope,\n AppIdentity.suffixText(props, \"AccessLoggingBucket\"),\n accessLoggingBucket.valueAsString\n ),\n accessLogging.prefix\n );\n }\n\n const targetGroup = new GuApplicationTargetGroup(scope, \"TargetGroup\", {\n app,\n vpc,\n protocol: ApplicationProtocol.HTTP,\n targets: [autoScalingGroup],\n port: applicationPort,\n });\n\n const listener = new GuHttpsApplicationListener(scope, \"Listener\", {\n app,\n loadBalancer,\n certificate,\n targetGroup,\n // When open=true, AWS will create a security group which allows all inbound traffic over HTTPS\n open: access.scope === AccessScope.PUBLIC,\n });\n\n // Since AWS won't create a security group automatically when open=false, we need to add our own\n if (access.scope !== AccessScope.PUBLIC) {\n loadBalancer.addSecurityGroup(\n new GuSecurityGroup(scope, `${access.scope}IngressSecurityGroup`, {\n app,\n vpc,\n description: \"Allow restricted ingress from CIDR ranges\",\n allowAllOutbound: false,\n ingresses: restrictedCidrRanges(access.cidrRanges),\n })\n );\n }\n\n if (!monitoringConfiguration.noMonitoring) {\n const { http5xxAlarm, snsTopicName, unhealthyInstancesAlarm } = monitoringConfiguration;\n\n if (http5xxAlarm) {\n new GuAlb5xxPercentageAlarm(scope, {\n app,\n loadBalancer,\n snsTopicName,\n ...http5xxAlarm,\n });\n }\n if (unhealthyInstancesAlarm) {\n new GuUnhealthyInstancesAlarm(scope, {\n app,\n targetGroup,\n snsTopicName,\n });\n }\n }\n\n this.vpc = vpc;\n this.certificate = certificate;\n this.loadBalancer = loadBalancer;\n this.autoScalingGroup = autoScalingGroup;\n this.listener = listener;\n this.targetGroup = targetGroup;\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { GuStack } from "../../constructs/core";
2
2
  import type { GuEc2AppProps } from "./base";
3
3
  import { GuEc2App } from "./base";
4
- declare type GuEc2FrameworkAppProps = Omit<GuEc2AppProps, "applicationPort">;
4
+ type GuEc2FrameworkAppProps = Omit<GuEc2AppProps, "applicationPort">;
5
5
  /**
6
6
  * Creates an instance of [[`GuEc2App`]], with an application port of 9000.
7
7
  */
@@ -1 +1 @@
1
- {"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/framework.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,aAAK,sBAAsB,GAAG,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;AAErE;;GAEG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAQ;gBAExB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB;CAG1D;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAQ;gBAExB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB;CAG1D"}
1
+ {"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../../src/patterns/ec2-app/framework.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,KAAK,sBAAsB,GAAG,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;AAErE;;GAEG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAQ;gBAExB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB;CAG1D;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,QAAQ;IACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAQ;gBAExB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB;CAG1D"}
@@ -50,7 +50,7 @@ export interface InternalAccess extends Access {
50
50
  scope: AccessScope.INTERNAL;
51
51
  cidrRanges: IPeer[];
52
52
  }
53
- export declare type AppAccess = PublicAccess | RestrictedAccess | InternalAccess;
53
+ export type AppAccess = PublicAccess | RestrictedAccess | InternalAccess;
54
54
  export declare const AppAccess: {
55
55
  /**
56
56
  * Validate the CIDR rules for AppAccess.
@@ -1 +1 @@
1
- {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/types/access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAiB,SAAQ,MAAM;IAC9C,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC;IAC9B,UAAU,EAAE,KAAK,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAe,SAAQ,MAAM;IAC5C,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;IAC5B,UAAU,EAAE,KAAK,EAAE,CAAC;CACrB;AAED,oBAAY,SAAS,GAAG,YAAY,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAEzE,eAAO,MAAM,SAAS;IACpB;;;;;;;;OAQG;uBACgB,SAAS;CA6B7B,CAAC"}
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/types/access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAiB,SAAQ,MAAM;IAC9C,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC;IAC9B,UAAU,EAAE,KAAK,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAe,SAAQ,MAAM;IAC5C,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;IAC5B,UAAU,EAAE,KAAK,EAAE,CAAC;CACrB;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAEzE,eAAO,MAAM,SAAS;IACpB;;;;;;;;OAQG;uBACgB,SAAS;CA6B7B,CAAC"}
@@ -4,7 +4,7 @@ export interface AwsConfig {
4
4
  credentialProvider: CredentialProviderChain;
5
5
  region: string;
6
6
  }
7
- export declare type CliCommandResponse = Promise<string | Record<string, unknown> | number>;
7
+ export type CliCommandResponse = Promise<string | Record<string, unknown> | number>;
8
8
  export interface VpcInDetail extends Vpc {
9
9
  subnets: SubnetList;
10
10
  isUsed: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/types/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,SAAS;IACxB,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,oBAAY,kBAAkB,GAAG,OAAO,CAEpC,MAAM,GAEN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAEvB,MAAM,CACT,CAAC;AAEF,MAAM,WAAW,WAAY,SAAQ,GAAG;IACtC,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/types/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,SAAS;IACxB,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAEpC,MAAM,GAEN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAEvB,MAAM,CACT,CAAC;AAEF,MAAM,WAAW,WAAY,SAAQ,GAAG;IACtC,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB"}
@@ -1,7 +1,7 @@
1
1
  import { Duration } from "aws-cdk-lib";
2
2
  import type { IEventSourceDlq } from "aws-cdk-lib/aws-lambda";
3
3
  import type { KinesisEventSourceProps } from "aws-cdk-lib/aws-lambda-event-sources";
4
- export declare type StreamProcessingProps = Omit<KinesisEventSourceProps, "bisectBatchOnError" | "maxRecordAge" | "onFailure" | "retryAttempts">;
4
+ export type StreamProcessingProps = Omit<KinesisEventSourceProps, "bisectBatchOnError" | "maxRecordAge" | "onFailure" | "retryAttempts">;
5
5
  /**
6
6
  * In order to prevent your lambda from continuously retrying if it encounters errors
7
7
  * whilst processing a batch, use `retryBehaviour` to give up on a record once it reaches a certain age,
@@ -26,10 +26,10 @@ export interface StreamErrorHandlingProps {
26
26
  deadLetterQueueForSkippedRecords?: IEventSourceDlq;
27
27
  blockProcessingAndRetryIndefinitely?: false;
28
28
  }
29
- declare type AwsErrorHandlingProps = Pick<KinesisEventSourceProps, "bisectBatchOnError" | "maxRecordAge" | "onFailure" | "retryAttempts">;
29
+ type AwsErrorHandlingProps = Pick<KinesisEventSourceProps, "bisectBatchOnError" | "maxRecordAge" | "onFailure" | "retryAttempts">;
30
30
  export declare function toAwsErrorHandlingProps(errorHandlingProps: StreamErrorHandlingProps): AwsErrorHandlingProps;
31
- declare type AwsRetryProp = Pick<AwsErrorHandlingProps, "maxRecordAge" | "retryAttempts">;
32
- declare type RetryType = "attempts" | "recordAge";
31
+ type AwsRetryProp = Pick<AwsErrorHandlingProps, "maxRecordAge" | "retryAttempts">;
32
+ type RetryType = "attempts" | "recordAge";
33
33
  /**
34
34
  * To retry based on number of attempts, use:
35
35
  * ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"event-source.d.ts","sourceRoot":"","sources":["../../../src/utils/lambda/event-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAEpF,oBAAY,qBAAqB,GAAG,IAAI,CACtC,uBAAuB,EACvB,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,eAAe,CACtE,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,WAAW,CAAC;IAC5B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gCAAgC,CAAC,EAAE,eAAe,CAAC;IACnD,mCAAmC,CAAC,EAAE,KAAK,CAAC;CAC7C;AAED,aAAK,qBAAqB,GAAG,IAAI,CAC/B,uBAAuB,EACvB,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,eAAe,CACtE,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,kBAAkB,EAAE,wBAAwB,GAAG,qBAAqB,CAM3G;AAED,aAAK,YAAY,GAAG,IAAI,CAAC,qBAAqB,EAAE,cAAc,GAAG,eAAe,CAAC,CAAC;AAClF,aAAK,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAE1C;;;;;;;;;GASG;AACH,qBAAa,WAAW;WACR,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;WAGxC,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW;IAG9C,SAAS,IAAI,YAAY;IAKhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,OAAO;CAIR"}
1
+ {"version":3,"file":"event-source.d.ts","sourceRoot":"","sources":["../../../src/utils/lambda/event-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAEpF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,uBAAuB,EACvB,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,eAAe,CACtE,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,WAAW,CAAC;IAC5B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gCAAgC,CAAC,EAAE,eAAe,CAAC;IACnD,mCAAmC,CAAC,EAAE,KAAK,CAAC;CAC7C;AAED,KAAK,qBAAqB,GAAG,IAAI,CAC/B,uBAAuB,EACvB,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,eAAe,CACtE,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,kBAAkB,EAAE,wBAAwB,GAAG,qBAAqB,CAM3G;AAED,KAAK,YAAY,GAAG,IAAI,CAAC,qBAAqB,EAAE,cAAc,GAAG,eAAe,CAAC,CAAC;AAClF,KAAK,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAE1C;;;;;;;;;GASG;AACH,qBAAa,WAAW;WACR,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;WAGxC,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW;IAG9C,SAAS,IAAI,YAAY;IAKhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,OAAO;CAIR"}
@@ -21,10 +21,6 @@ exports.toAwsErrorHandlingProps = toAwsErrorHandlingProps;
21
21
  * ```
22
22
  */
23
23
  class StreamRetry {
24
- constructor(amount, type) {
25
- this.amount = amount;
26
- this.retryType = type;
27
- }
28
24
  static maxAttempts(amount) {
29
25
  return new StreamRetry(amount, "attempts");
30
26
  }
@@ -36,6 +32,10 @@ class StreamRetry {
36
32
  ? { retryAttempts: this.amount }
37
33
  : { maxRecordAge: aws_cdk_lib_1.Duration.seconds(this.amount) };
38
34
  }
35
+ constructor(amount, type) {
36
+ this.amount = amount;
37
+ this.retryType = type;
38
+ }
39
39
  }
40
40
  exports.StreamRetry = StreamRetry;
41
41
  //# sourceMappingURL=event-source.js.map