Skip to content

Commit cbd271e

Browse files
authored
fix(bedrock-alpha): added missing validation when prompt uses default variant (#35366)
### Issue # (if applicable) Closes #<issue number here>. ### Reason for this change When using Prompts and PromptVariants in bedrock, you can define the default variant your prompt will use, but if you dont add it to the variants array too, it will fail at deployment time. ### Description of changes Added a validation that checks the correct conditions at synth time, so you don't waste time and leave a stack with a bad deployment ### Describe any new or updated permissions being added NA ### Description of how you validated changes Unit tests. We don't create integ tests for validations (synth time) as they wont add any additional value ### Checklist - [X] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent bfb54b0 commit cbd271e

File tree

2 files changed

+62
-30
lines changed

2 files changed

+62
-30
lines changed

packages/@aws-cdk/aws-bedrock-alpha/bedrock/prompts/prompt.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Arn, ArnFormat, IResource, Lazy, Resource } from 'aws-cdk-lib/core';
1+
import { Arn, ArnFormat, IResource, Lazy, Resource, ValidationError } from 'aws-cdk-lib/core';
22
import * as bedrock from 'aws-cdk-lib/aws-bedrock';
33
import * as iam from 'aws-cdk-lib/aws-iam';
44
import * as kms from 'aws-cdk-lib/aws-kms';
@@ -287,6 +287,7 @@ export class Prompt extends PromptBase implements IPrompt {
287287
// ------------------------------------------------------
288288
// Validation
289289
// ------------------------------------------------------
290+
this.validatePromptDefault(props);
290291
this.node.addValidation({ validate: () => this.validatePromptName() });
291292
this.node.addValidation({ validate: () => this.validatePromptVariants() });
292293
this.node.addValidation({ validate: () => this.validateDescription() });
@@ -378,6 +379,16 @@ export class Prompt extends PromptBase implements IPrompt {
378379
return errors;
379380
}
380381

382+
/**
383+
* Validates that if the prompt has a default, it was also added to the variants array
384+
* @param props - The properties set in the constructor
385+
*/
386+
private validatePromptDefault(props: PromptProps) {
387+
if (props.defaultVariant && !props.variants?.includes(props.defaultVariant)) {
388+
throw new ValidationError('The \'defaultVariant\' needs to be included in the \'variants\' array.', this);
389+
}
390+
}
391+
381392
/**
382393
* Validates whether the description length is within the allowed limit.
383394
* @returns Array of validation error messages, empty if valid

packages/@aws-cdk/aws-bedrock-alpha/test/bedrock/prompts/prompt.test.ts

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -155,32 +155,32 @@ describe('Prompt', () => {
155155
});
156156
});
157157

158-
test('validates prompt name pattern - invalid names', () => {
159-
const invalidNames = [
160-
'-invalid', // starts with hyphen
161-
'invalid-', // ends with hyphen
162-
'a'.repeat(101), // too long
163-
'', // empty
164-
'invalid name', // contains space
165-
'invalid@name', // contains special character
166-
];
167-
168-
invalidNames.forEach((name, index) => {
169-
expect(() => {
170-
new bedrock.Prompt(stack, `TestPrompt${index}`, {
171-
promptName: name,
172-
});
173-
}).not.toThrow(); // Validation happens at synthesis time, not construction time
158+
test.each([
159+
['-invalid', 'starts with hyphen'],
160+
['a'.repeat(101), 'too long'],
161+
['', 'empty'],
162+
['invalid name', 'contains space'],
163+
['invalid@name', 'contains special character'],
164+
])('validates prompt name pattern - %s (%s)', (invalidName, _description) => {
165+
new bedrock.Prompt(stack, 'TestPrompt', {
166+
promptName: invalidName,
174167
});
168+
169+
expect(() => {
170+
Template.fromStack(stack);
171+
}).toThrow(/Valid characters are a-z, A-Z, 0-9, _ \(underscore\) and - \(hyphen\). Must not begin with a hyphen and must be 1-100 characters long/);
175172
});
176173

177174
test('validates description length', () => {
175+
new bedrock.Prompt(stack, 'TestPrompt', {
176+
promptName: 'test-prompt',
177+
description: 'a'.repeat(251), // too long
178+
});
179+
180+
// Validation happens at synthesis time, not construction time
178181
expect(() => {
179-
new bedrock.Prompt(stack, 'TestPrompt', {
180-
promptName: 'test-prompt',
181-
description: 'a'.repeat(251), // too long
182-
});
183-
}).not.toThrow(); // Validation happens at synthesis time, not construction time
182+
Template.fromStack(stack);
183+
}).toThrow(/Description must be 200 characters or less/);
184184
});
185185

186186
test('validates maximum number of variants', () => {
@@ -192,12 +192,15 @@ describe('Prompt', () => {
192192
}),
193193
);
194194

195+
new bedrock.Prompt(stack, 'TestPrompt', {
196+
promptName: 'test-prompt',
197+
variants,
198+
});
199+
200+
// Validation happens at synthesis time, not construction time
195201
expect(() => {
196-
new bedrock.Prompt(stack, 'TestPrompt', {
197-
promptName: 'test-prompt',
198-
variants,
199-
});
200-
}).not.toThrow(); // Validation happens at synthesis time, not construction time
202+
Template.fromStack(stack);
203+
}).toThrow(/Too many variants specified/);
201204
});
202205

203206
test('validates unique variant names', () => {
@@ -213,12 +216,30 @@ describe('Prompt', () => {
213216
promptText: 'Text 2',
214217
});
215218

219+
new bedrock.Prompt(stack, 'TestPrompt', {
220+
promptName: 'test-prompt',
221+
variants: [variant1, variant2],
222+
});
223+
224+
// Validation happens at synthesis time, not construction time
225+
expect(() => {
226+
Template.fromStack(stack);
227+
}).toThrow(/Duplicate variant names found/);
228+
});
229+
230+
test('validates default variant is added to variants array', () => {
231+
const defaultVariant = bedrock.PromptVariant.text({
232+
variantName: 'default-variant',
233+
model: foundationModel,
234+
promptText: 'Text',
235+
});
236+
216237
expect(() => {
217238
new bedrock.Prompt(stack, 'TestPrompt', {
218-
promptName: 'test-prompt',
219-
variants: [variant1, variant2],
239+
promptName: 'my-test-prompt',
240+
defaultVariant: defaultVariant,
220241
});
221-
}).not.toThrow(); // Validation happens at synthesis time, not construction time
242+
}).toThrow('The \'defaultVariant\' needs to be included in the \'variants\' array.');
222243
});
223244
});
224245

0 commit comments

Comments
 (0)