Skip to content

Commit db28485

Browse files
authored
fix(core): undeployable due to invalid mapping (#18922)
In #17984, mappings were altered so that non-alphanumeric values were replaced with `_`. However, the names in the name-value pairs must be fully alphanumeric according to the [docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html). The result was potentially invalid mappings generated at `cdk synth` that would fail at `cdk deploy`. One such example is the mappings generated for `lambda-insights` in #18789. In this PR, the replacement value is updated from `_` to `x`. The mapping is not surfaced anywhere other than the template, so we just need a value that satisfies cloudformation. Thus we're okay with the slight loss of readability. In addition, `CfnMapping` is updated to validate the names in the name-value pair and ensure that it is alphanumeric. Fixes #18789. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent efddabc commit db28485

File tree

5 files changed

+94
-74
lines changed

5 files changed

+94
-74
lines changed

packages/@aws-cdk/aws-lambda/test/integ.lambda-insights-mapping.expected.json

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@
291291
{
292292
"Ref": "AWS::Region"
293293
},
294-
"1_0_98_0_x86_64"
294+
"1x0x98x0xx86x64"
295295
]
296296
}
297297
],
@@ -364,7 +364,7 @@
364364
{
365365
"Ref": "AWS::Region"
366366
},
367-
"1_0_119_0_x86_64"
367+
"1x0x119x0xx86x64"
368368
]
369369
}
370370
],
@@ -457,92 +457,92 @@
457457
"Mappings": {
458458
"CloudwatchlambdainsightsversionMap": {
459459
"af-south-1": {
460-
"1_0_98_0_x86_64": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8",
461-
"1_0_119_0_x86_64": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:9"
460+
"1x0x98x0xx86x64": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8",
461+
"1x0x119x0xx86x64": "arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:9"
462462
},
463463
"ap-east-1": {
464-
"1_0_98_0_x86_64": "arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8",
465-
"1_0_119_0_x86_64": "arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:9"
464+
"1x0x98x0xx86x64": "arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:8",
465+
"1x0x119x0xx86x64": "arn:aws:lambda:ap-east-1:519774774795:layer:LambdaInsightsExtension:9"
466466
},
467467
"ap-northeast-1": {
468-
"1_0_98_0_x86_64": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14",
469-
"1_0_119_0_x86_64": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:23"
468+
"1x0x98x0xx86x64": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:14",
469+
"1x0x119x0xx86x64": "arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension:23"
470470
},
471471
"ap-northeast-2": {
472-
"1_0_98_0_x86_64": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14",
473-
"1_0_119_0_x86_64": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:16"
472+
"1x0x98x0xx86x64": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:14",
473+
"1x0x119x0xx86x64": "arn:aws:lambda:ap-northeast-2:580247275435:layer:LambdaInsightsExtension:16"
474474
},
475475
"ap-south-1": {
476-
"1_0_98_0_x86_64": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14",
477-
"1_0_119_0_x86_64": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:16"
476+
"1x0x98x0xx86x64": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:14",
477+
"1x0x119x0xx86x64": "arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:16"
478478
},
479479
"ap-southeast-1": {
480-
"1_0_98_0_x86_64": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14",
481-
"1_0_119_0_x86_64": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:16"
480+
"1x0x98x0xx86x64": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:14",
481+
"1x0x119x0xx86x64": "arn:aws:lambda:ap-southeast-1:580247275435:layer:LambdaInsightsExtension:16"
482482
},
483483
"ap-southeast-2": {
484-
"1_0_98_0_x86_64": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14",
485-
"1_0_119_0_x86_64": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:16"
484+
"1x0x98x0xx86x64": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:14",
485+
"1x0x119x0xx86x64": "arn:aws:lambda:ap-southeast-2:580247275435:layer:LambdaInsightsExtension:16"
486486
},
487487
"ca-central-1": {
488-
"1_0_98_0_x86_64": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14",
489-
"1_0_119_0_x86_64": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:16"
488+
"1x0x98x0xx86x64": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:14",
489+
"1x0x119x0xx86x64": "arn:aws:lambda:ca-central-1:580247275435:layer:LambdaInsightsExtension:16"
490490
},
491491
"cn-north-1": {
492-
"1_0_98_0_x86_64": "arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8",
493-
"1_0_119_0_x86_64": "arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:9"
492+
"1x0x98x0xx86x64": "arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:8",
493+
"1x0x119x0xx86x64": "arn:aws-cn:lambda:cn-north-1:488211338238:layer:LambdaInsightsExtension:9"
494494
},
495495
"cn-northwest-1": {
496-
"1_0_98_0_x86_64": "arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8",
497-
"1_0_119_0_x86_64": "arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:9"
496+
"1x0x98x0xx86x64": "arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:8",
497+
"1x0x119x0xx86x64": "arn:aws-cn:lambda:cn-northwest-1:488211338238:layer:LambdaInsightsExtension:9"
498498
},
499499
"eu-central-1": {
500-
"1_0_98_0_x86_64": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14",
501-
"1_0_119_0_x86_64": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:16"
500+
"1x0x98x0xx86x64": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:14",
501+
"1x0x119x0xx86x64": "arn:aws:lambda:eu-central-1:580247275435:layer:LambdaInsightsExtension:16"
502502
},
503503
"eu-north-1": {
504-
"1_0_98_0_x86_64": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14",
505-
"1_0_119_0_x86_64": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:16"
504+
"1x0x98x0xx86x64": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:14",
505+
"1x0x119x0xx86x64": "arn:aws:lambda:eu-north-1:580247275435:layer:LambdaInsightsExtension:16"
506506
},
507507
"eu-south-1": {
508-
"1_0_98_0_x86_64": "arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8",
509-
"1_0_119_0_x86_64": "arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:9"
508+
"1x0x98x0xx86x64": "arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:8",
509+
"1x0x119x0xx86x64": "arn:aws:lambda:eu-south-1:339249233099:layer:LambdaInsightsExtension:9"
510510
},
511511
"eu-west-1": {
512-
"1_0_98_0_x86_64": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14",
513-
"1_0_119_0_x86_64": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:16"
512+
"1x0x98x0xx86x64": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:14",
513+
"1x0x119x0xx86x64": "arn:aws:lambda:eu-west-1:580247275435:layer:LambdaInsightsExtension:16"
514514
},
515515
"eu-west-2": {
516-
"1_0_98_0_x86_64": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14",
517-
"1_0_119_0_x86_64": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:16"
516+
"1x0x98x0xx86x64": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:14",
517+
"1x0x119x0xx86x64": "arn:aws:lambda:eu-west-2:580247275435:layer:LambdaInsightsExtension:16"
518518
},
519519
"eu-west-3": {
520-
"1_0_98_0_x86_64": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14",
521-
"1_0_119_0_x86_64": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:16"
520+
"1x0x98x0xx86x64": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:14",
521+
"1x0x119x0xx86x64": "arn:aws:lambda:eu-west-3:580247275435:layer:LambdaInsightsExtension:16"
522522
},
523523
"me-south-1": {
524-
"1_0_98_0_x86_64": "arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8",
525-
"1_0_119_0_x86_64": "arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:9"
524+
"1x0x98x0xx86x64": "arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:8",
525+
"1x0x119x0xx86x64": "arn:aws:lambda:me-south-1:285320876703:layer:LambdaInsightsExtension:9"
526526
},
527527
"sa-east-1": {
528-
"1_0_98_0_x86_64": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14",
529-
"1_0_119_0_x86_64": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:16"
528+
"1x0x98x0xx86x64": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:14",
529+
"1x0x119x0xx86x64": "arn:aws:lambda:sa-east-1:580247275435:layer:LambdaInsightsExtension:16"
530530
},
531531
"us-east-1": {
532-
"1_0_98_0_x86_64": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14",
533-
"1_0_119_0_x86_64": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:16"
532+
"1x0x98x0xx86x64": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14",
533+
"1x0x119x0xx86x64": "arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:16"
534534
},
535535
"us-east-2": {
536-
"1_0_98_0_x86_64": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14",
537-
"1_0_119_0_x86_64": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:16"
536+
"1x0x98x0xx86x64": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:14",
537+
"1x0x119x0xx86x64": "arn:aws:lambda:us-east-2:580247275435:layer:LambdaInsightsExtension:16"
538538
},
539539
"us-west-1": {
540-
"1_0_98_0_x86_64": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14",
541-
"1_0_119_0_x86_64": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:16"
540+
"1x0x98x0xx86x64": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:14",
541+
"1x0x119x0xx86x64": "arn:aws:lambda:us-west-1:580247275435:layer:LambdaInsightsExtension:16"
542542
},
543543
"us-west-2": {
544-
"1_0_98_0_x86_64": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14",
545-
"1_0_119_0_x86_64": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:16"
544+
"1x0x98x0xx86x64": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:14",
545+
"1x0x119x0xx86x64": "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:16"
546546
}
547547
}
548548
}

packages/@aws-cdk/aws-lambda/test/lambda-insights.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ describe('lambda-insights', () => {
9797
{
9898
Ref: 'AWS::Region',
9999
},
100-
'1_0_98_0_x86_64',
100+
'1x0x98x0xx86x64',
101101
],
102102
}],
103103
});
@@ -117,20 +117,20 @@ describe('lambda-insights', () => {
117117
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
118118
FunctionName: 'MyLambda1',
119119
Layers: [{
120-
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1_0_98_0_x86_64'],
120+
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1x0x98x0xx86x64'],
121121
}],
122122
});
123123

124124
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
125125
FunctionName: 'MyLambda2',
126126
Layers: [{
127-
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1_0_98_0_x86_64'],
127+
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1x0x98x0xx86x64'],
128128
}],
129129
});
130130

131131
Template.fromStack(stack).hasMapping('CloudwatchlambdainsightsversionMap', {
132132
'af-south-1': {
133-
'1_0_98_0_x86_64': 'arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8',
133+
'1x0x98x0xx86x64': 'arn:aws:lambda:af-south-1:012438385374:layer:LambdaInsightsExtension:8',
134134
},
135135
});
136136

@@ -218,21 +218,21 @@ describe('lambda-insights', () => {
218218
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
219219
FunctionName: 'MyLambda1',
220220
Layers: [{
221-
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1_0_119_0_x86_64'],
221+
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1x0x119x0xx86x64'],
222222
}],
223223
});
224224

225225
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
226226
FunctionName: 'MyLambda2',
227227
Layers: [{
228-
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1_0_119_0_arm64'],
228+
'Fn::FindInMap': ['CloudwatchlambdainsightsversionMap', { Ref: 'AWS::Region' }, '1x0x119x0xarm64'],
229229
}],
230230
});
231231

232232
Template.fromStack(stack).hasMapping('CloudwatchlambdainsightsversionMap', {
233233
'ap-south-1': {
234-
'1_0_119_0_x86_64': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:16',
235-
'1_0_119_0_arm64': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension-Arm64:1',
234+
'1x0x119x0xx86x64': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension:16',
235+
'1x0x119x0xarm64': 'arn:aws:lambda:ap-south-1:580247275435:layer:LambdaInsightsExtension-Arm64:1',
236236
},
237237
});
238238

packages/@aws-cdk/core/lib/cfn-mapping.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,16 @@ export class CfnMapping extends CfnRefElement {
4343

4444
constructor(scope: Construct, id: string, props: CfnMappingProps = {}) {
4545
super(scope, id);
46-
this.mapping = props.mapping ?? { };
46+
this.mapping = props.mapping ? this.validateMapping(props.mapping) : {};
4747
this.lazy = props.lazy;
4848
}
4949

5050
/**
5151
* Sets a value in the map based on the two keys.
5252
*/
5353
public setValue(key1: string, key2: string, value: any) {
54+
this.validateAlphanumeric(key2);
55+
5456
if (!(key1 in this.mapping)) {
5557
this.mapping[key1] = { };
5658
}
@@ -108,4 +110,16 @@ export class CfnMapping extends CfnRefElement {
108110
}
109111
this.lazyInformed = true;
110112
}
113+
114+
private validateMapping(mapping: Mapping): Mapping {
115+
Object.keys(mapping).forEach((m) => Object.keys(mapping[m]).forEach(this.validateAlphanumeric));
116+
return mapping;
117+
}
118+
119+
private validateAlphanumeric(value: any) {
120+
// https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html
121+
if (value.match(/[^a-zA-Z0-9]/g)) {
122+
throw new Error(`Attribute name '${value}' must contain only alphanumeric characters.`);
123+
}
124+
}
111125
}

packages/@aws-cdk/core/lib/private/region-lookup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function deployTimeLookup(stack: Stack, factName: string, lookupMap: Reco
3131
: [factName, 'value'] as const;
3232

3333
const mapId = `${ucfirst(factClass)}Map`;
34-
const factKey = factParam.replace(/[^a-zA-Z0-9]/g, '_');
34+
const factKey = factParam.replace(/[^a-zA-Z0-9]/g, 'x');
3535

3636
let mapping = stack.node.tryFindChild(mapId) as CfnMapping | undefined;
3737
if (!mapping) {

packages/@aws-cdk/core/test/mappings.test.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,35 +58,32 @@ describe('mappings', () => {
5858
},
5959
},
6060
});
61-
62-
6361
});
6462

6563
test('allow using unresolved tokens in find-in-map', () => {
6664
const stack = new Stack();
6765

6866
const mapping = new CfnMapping(stack, 'mapping', {
6967
mapping: {
70-
instanceCount: {
71-
'us-east-1': 12,
68+
'us-east-1': {
69+
instanceCount: 12,
7270
},
7371
},
7472
});
7573

76-
const v1 = mapping.findInMap('instanceCount', Aws.REGION);
77-
const v2 = Fn.findInMap(mapping.logicalId, 'instanceCount', Aws.REGION);
74+
const v1 = mapping.findInMap(Aws.REGION, 'instanceCount');
75+
const v2 = Fn.findInMap(mapping.logicalId, Aws.REGION, 'instanceCount');
7876

79-
const expected = { 'Fn::FindInMap': ['mapping', 'instanceCount', { Ref: 'AWS::Region' }] };
77+
const expected = { 'Fn::FindInMap': ['mapping', { Ref: 'AWS::Region' }, 'instanceCount'] };
8078
expect(stack.resolve(v1)).toEqual(expected);
8179
expect(stack.resolve(v2)).toEqual(expected);
8280
expect(toCloudFormation(stack).Mappings).toEqual({
8381
mapping: {
84-
instanceCount: {
85-
'us-east-1': 12,
82+
'us-east-1': {
83+
instanceCount: 12,
8684
},
8785
},
8886
});
89-
9087
});
9188

9289
test('no validation if first key is token and second is a static string', () => {
@@ -114,34 +111,43 @@ describe('mappings', () => {
114111
},
115112
},
116113
});
117-
118114
});
119115

120116
test('validate first key if it is a string and second is a token', () => {
121117
// GIVEN
122118
const stack = new Stack();
123119
const mapping = new CfnMapping(stack, 'mapping', {
124120
mapping: {
125-
size: {
126-
'us-east-1': 12,
121+
'us-east-1': {
122+
size: 12,
127123
},
128124
},
129125
});
130126

131127
// WHEN
132-
const v = mapping.findInMap('size', Aws.REGION);
128+
const v = mapping.findInMap(Aws.REGION, 'size');
133129

134130
// THEN
135-
expect(() => mapping.findInMap('not-found', Aws.REGION)).toThrow(/Mapping doesn't contain top-level key 'not-found'/);
136-
expect(stack.resolve(v)).toEqual({ 'Fn::FindInMap': ['mapping', 'size', { Ref: 'AWS::Region' }] });
131+
expect(() => mapping.findInMap('not-found', 'size')).toThrow(/Mapping doesn't contain top-level key 'not-found'/);
132+
expect(stack.resolve(v)).toEqual({ 'Fn::FindInMap': ['mapping', { Ref: 'AWS::Region' }, 'size'] });
137133
expect(toCloudFormation(stack).Mappings).toEqual({
138134
mapping: {
139-
size: {
140-
'us-east-1': 12,
135+
'us-east-1': {
136+
size: 12,
141137
},
142138
},
143139
});
140+
});
144141

142+
test('throws if mapping attribute name not alphanumeric', () => {
143+
const stack = new Stack();
144+
expect(() => new CfnMapping(stack, 'mapping', {
145+
mapping: {
146+
size: {
147+
'us-east-1': 12,
148+
},
149+
},
150+
})).toThrowError(/Attribute name 'us-east-1' must contain only alphanumeric characters./);
145151
});
146152
});
147153

0 commit comments

Comments
 (0)