diff --git a/packages/aws-cdk-lib/.eslintrc.js b/packages/aws-cdk-lib/.eslintrc.js index bd396867c73d3..283ad93834c89 100644 --- a/packages/aws-cdk-lib/.eslintrc.js +++ b/packages/aws-cdk-lib/.eslintrc.js @@ -47,6 +47,7 @@ const enableNoThrowDefaultErrorIn = [ 'aws-elasticloadbalancingv2-actions', 'aws-elasticloadbalancingv2-targets', 'aws-lambda', + 'aws-logs', 'aws-rds', 'aws-s3', 'aws-sns', diff --git a/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts b/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts index f00fcc1ea11e1..1d7674b34113a 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/data-protection-policy.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { ILogGroup } from './log-group'; import { IBucket } from '../../aws-s3'; -import { Stack } from '../../core'; +import { Stack, UnscopedValidationError } from '../../core'; /** * Creates a data protection policy for CloudWatch Logs log groups. */ @@ -10,7 +10,7 @@ export class DataProtectionPolicy { constructor(props: DataProtectionPolicyProps) { if (props.identifiers.length == 0) { - throw new Error('DataIdentifier cannot be empty'); + throw new UnscopedValidationError('DataIdentifier cannot be empty'); } this.dataProtectionPolicyProps = props; } diff --git a/packages/aws-cdk-lib/aws-logs/lib/field-index-policy.ts b/packages/aws-cdk-lib/aws-logs/lib/field-index-policy.ts index 2df85826a866c..7874f9591d073 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/field-index-policy.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/field-index-policy.ts @@ -1,4 +1,5 @@ import { Construct } from 'constructs'; +import { UnscopedValidationError } from '../../core'; /** * Creates a field index policy for CloudWatch Logs log groups. @@ -8,7 +9,7 @@ export class FieldIndexPolicy { constructor(props: FieldIndexPolicyProps) { if (props.fields.length > 20) { - throw new Error('A maximum of 20 fields can be indexed per log group'); + throw new UnscopedValidationError('A maximum of 20 fields can be indexed per log group'); } this.fieldIndexPolicyProps = props; } diff --git a/packages/aws-cdk-lib/aws-logs/lib/log-group.ts b/packages/aws-cdk-lib/aws-logs/lib/log-group.ts index ef1c71b477a01..f7367d248ada6 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/log-group.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/log-group.ts @@ -10,7 +10,7 @@ import { ILogSubscriptionDestination, SubscriptionFilter } from './subscription- import * as cloudwatch from '../../aws-cloudwatch'; import * as iam from '../../aws-iam'; import * as kms from '../../aws-kms'; -import { Annotations, Arn, ArnFormat, RemovalPolicy, Resource, Stack, Token } from '../../core'; +import { Annotations, Arn, ArnFormat, RemovalPolicy, Resource, Stack, Token, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; export interface ILogGroup extends iam.IResourceWithPolicy { @@ -623,7 +623,7 @@ export class LogGroup extends LogGroupBase { if (retentionInDays === Infinity || retentionInDays === RetentionDays.INFINITE) { retentionInDays = undefined; } if (retentionInDays !== undefined && !Token.isUnresolved(retentionInDays) && retentionInDays <= 0) { - throw new Error(`retentionInDays must be positive, got ${retentionInDays}`); + throw new ValidationError(`retentionInDays must be positive, got ${retentionInDays}`, this); } let logGroupClass = props.logGroupClass; diff --git a/packages/aws-cdk-lib/aws-logs/lib/metric-filter.ts b/packages/aws-cdk-lib/aws-logs/lib/metric-filter.ts index c87f273e87bb8..10f3dcaa1c2ec 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/metric-filter.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/metric-filter.ts @@ -2,7 +2,7 @@ import { Construct } from 'constructs'; import { ILogGroup, MetricFilterOptions } from './log-group'; import { CfnMetricFilter } from './logs.generated'; import { Metric, MetricOptions } from '../../aws-cloudwatch'; -import { Resource } from '../../core'; +import { Resource, ValidationError } from '../../core'; import { addConstructMetadata, MethodMetadata } from '../../core/lib/metadata-resource'; /** @@ -34,7 +34,7 @@ export class MetricFilter extends Resource { const numberOfDimensions = Object.keys(props.dimensions ?? {}).length; if (numberOfDimensions > 3) { - throw new Error(`MetricFilter only supports a maximum of 3 dimensions but received ${numberOfDimensions}.`); + throw new ValidationError(`MetricFilter only supports a maximum of 3 dimensions but received ${numberOfDimensions}.`, this); } // It looks odd to map this object to a singleton list, but that's how diff --git a/packages/aws-cdk-lib/aws-logs/lib/pattern.ts b/packages/aws-cdk-lib/aws-logs/lib/pattern.ts index 44caabb6fec35..7894343c844a7 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/pattern.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/pattern.ts @@ -1,3 +1,5 @@ +import { UnscopedValidationError } from '../../core'; + // Implementation of metric patterns /** @@ -180,7 +182,7 @@ export class FilterPattern { * A JSON log pattern that matches if all given JSON log patterns match */ public static all(...patterns: JsonPattern[]): JsonPattern { - if (patterns.length === 0) { throw new Error('Must supply at least one pattern, or use allEvents() to match all events.'); } + if (patterns.length === 0) { throw new UnscopedValidationError('Must supply at least one pattern, or use allEvents() to match all events.'); } if (patterns.length === 1) { return patterns[0]; } return new JSONAggregatePattern('&&', patterns); } @@ -189,7 +191,7 @@ export class FilterPattern { * A JSON log pattern that matches if any of the given JSON log patterns match */ public static any(...patterns: JsonPattern[]): JsonPattern { - if (patterns.length === 0) { throw new Error('Must supply at least one pattern'); } + if (patterns.length === 0) { throw new UnscopedValidationError('Must supply at least one pattern'); } if (patterns.length === 1) { return patterns[0]; } return new JSONAggregatePattern('||', patterns); } @@ -282,7 +284,7 @@ class JSONPostfixPattern extends JsonPattern { class JSONAggregatePattern extends JsonPattern { public constructor(operator: string, patterns: JsonPattern[]) { if (operator !== '&&' && operator !== '||') { - throw new Error('Operator must be one of && or ||'); + throw new UnscopedValidationError('Operator must be one of && or ||'); } const clauses = patterns.map(p => '(' + p.jsonPatternString + ')'); @@ -313,12 +315,12 @@ export class SpaceDelimitedTextPattern implements IFilterPattern { // going through the factory for (const column of columns) { if (!validColumnName(column)) { - throw new Error(`Invalid column name: ${column}`); + throw new UnscopedValidationError(`Invalid column name: ${column}`); } } if (sum(columns.map(c => c === COL_ELLIPSIS ? 1 : 0)) > 1) { - throw new Error("Can use at most one '...' column"); + throw new UnscopedValidationError("Can use at most one '...' column"); } return new SpaceDelimitedTextPattern(columns, {}); @@ -335,10 +337,10 @@ export class SpaceDelimitedTextPattern implements IFilterPattern { */ public whereString(columnName: string, comparison: string, value: string): SpaceDelimitedTextPattern { if (columnName === COL_ELLIPSIS) { - throw new Error("Can't use '...' in a restriction"); + throw new UnscopedValidationError("Can't use '...' in a restriction"); } if (this.columns.indexOf(columnName) === -1) { - throw new Error(`Column in restrictions that is not in columns: ${columnName}`); + throw new UnscopedValidationError(`Column in restrictions that is not in columns: ${columnName}`); } comparison = validateStringOperator(comparison); @@ -354,10 +356,10 @@ export class SpaceDelimitedTextPattern implements IFilterPattern { */ public whereNumber(columnName: string, comparison: string, value: number): SpaceDelimitedTextPattern { if (columnName === COL_ELLIPSIS) { - throw new Error("Can't use '...' in a restriction"); + throw new UnscopedValidationError("Can't use '...' in a restriction"); } if (this.columns.indexOf(columnName) === -1) { - throw new Error(`Column in restrictions that is not in columns: ${columnName}`); + throw new UnscopedValidationError(`Column in restrictions that is not in columns: ${columnName}`); } comparison = validateNumericalOperator(comparison); @@ -445,7 +447,7 @@ function validateStringOperator(operator: string) { if (operator === '==') { operator = '='; } if (operator !== '=' && operator !== '!=') { - throw new Error(`Invalid comparison operator ('${operator}'), must be either '=' or '!='`); + throw new UnscopedValidationError(`Invalid comparison operator ('${operator}'), must be either '=' or '!='`); } return operator; @@ -463,7 +465,7 @@ function validateNumericalOperator(operator: string) { if (operator === '==') { operator = '='; } if (VALID_OPERATORS.indexOf(operator) === -1) { - throw new Error(`Invalid comparison operator ('${operator}'), must be one of ${VALID_OPERATORS.join(', ')}`); + throw new UnscopedValidationError(`Invalid comparison operator ('${operator}'), must be one of ${VALID_OPERATORS.join(', ')}`); } return operator; @@ -478,7 +480,7 @@ function renderRestriction(column: string, restriction: ColumnRestriction) { } else if (restriction.stringValue) { return `${column} ${restriction.comparison} ${quoteTerm(restriction.stringValue)}`; } else { - throw new Error('Invalid restriction'); + throw new UnscopedValidationError('Invalid restriction'); } } diff --git a/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts b/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts index 5c3907ffde784..516d4c040e74e 100644 --- a/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts +++ b/packages/aws-cdk-lib/aws-logs/lib/subscription-filter.ts @@ -3,7 +3,7 @@ import { ILogGroup, SubscriptionFilterOptions } from './log-group'; import { CfnSubscriptionFilter } from './logs.generated'; import * as iam from '../../aws-iam'; import { KinesisDestination } from '../../aws-logs-destinations'; -import { Resource, Token } from '../../core'; +import { Resource, Token, ValidationError } from '../../core'; import { addConstructMetadata } from '../../core/lib/metadata-resource'; /** @@ -67,7 +67,7 @@ export class SubscriptionFilter extends Resource { !Token.isUnresolved(props.destination) && !(props.destination instanceof KinesisDestination) ) { - throw new Error('distribution property can only be used with KinesisDestination.'); + throw new ValidationError('distribution property can only be used with KinesisDestination.', this); } const destProps = props.destination.bind(this, props.logGroup);