Skip to content

Commit 122f9de

Browse files
authored
Merge branch 'main' into scheduler-alpha-module-graduation
2 parents 20e14c3 + 0787840 commit 122f9de

File tree

7 files changed

+83
-16
lines changed

7 files changed

+83
-16
lines changed

packages/aws-cdk-lib/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const enableNoThrowDefaultErrorIn = [
5050
'aws-docdb',
5151
'aws-dynamodb',
5252
'aws-ecr',
53+
'aws-ecr-assets',
5354
'aws-efs',
5455
'aws-elasticloadbalancing',
5556
'aws-elasticloadbalancingv2',

packages/aws-cdk-lib/aws-ec2/lib/prefix-list.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Construct } from 'constructs';
2-
import { ValidationError } from 'jsonschema';
32
import { CfnPrefixList } from './ec2.generated';
43
import * as cxschema from '../../cloud-assembly-schema';
5-
import { IResource, Lazy, Resource, Names, ContextProvider, Token } from '../../core';
4+
import { IResource, Lazy, Resource, Names, ContextProvider, Token, ValidationError } from '../../core';
65
import { addConstructMetadata } from '../../core/lib/metadata-resource';
76

87
/**

packages/aws-cdk-lib/aws-ecr-assets/lib/image-asset.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import { Construct } from 'constructs';
44
import { FingerprintOptions, FollowMode, IAsset } from '../../assets';
55
import * as ecr from '../../aws-ecr';
6-
import { Annotations, AssetStaging, FeatureFlags, FileFingerprintOptions, IgnoreMode, Stack, SymlinkFollowMode, Token, Stage, CfnResource } from '../../core';
6+
import { Annotations, AssetStaging, FeatureFlags, FileFingerprintOptions, IgnoreMode, Stack, SymlinkFollowMode, Token, Stage, CfnResource, ValidationError, UnscopedValidationError } from '../../core';
77
import * as cxapi from '../../cx-api';
88

99
/**
@@ -435,14 +435,14 @@ export class DockerImageAsset extends Construct implements IAsset {
435435
// resolve full path
436436
const dir = path.resolve(props.directory);
437437
if (!fs.existsSync(dir)) {
438-
throw new Error(`Cannot find image directory at ${dir}`);
438+
throw new ValidationError(`Cannot find image directory at ${dir}`, this);
439439
}
440440

441441
// validate the docker file exists
442442
this.dockerfilePath = props.file || 'Dockerfile';
443443
const file = path.join(dir, this.dockerfilePath);
444444
if (!fs.existsSync(file)) {
445-
throw new Error(`Cannot find file at ${file}`);
445+
throw new ValidationError(`Cannot find file at ${file}`, this);
446446
}
447447

448448
const defaultIgnoreMode = FeatureFlags.of(this).isEnabled(cxapi.DOCKER_IGNORE_SUPPORT)
@@ -582,7 +582,7 @@ export class DockerImageAsset extends Construct implements IAsset {
582582
function validateProps(props: DockerImageAssetProps) {
583583
for (const [key, value] of Object.entries(props)) {
584584
if (Token.isUnresolved(value)) {
585-
throw new Error(`Cannot use Token as value of '${key}': this value is used before deployment starts`);
585+
throw new UnscopedValidationError(`Cannot use Token as value of '${key}': this value is used before deployment starts`);
586586
}
587587
}
588588

@@ -593,7 +593,7 @@ function validateProps(props: DockerImageAssetProps) {
593593
function validateBuildProps(buildPropName: string, buildProps?: { [key: string]: string }) {
594594
for (const [key, value] of Object.entries(buildProps || {})) {
595595
if (Token.isUnresolved(key) || Token.isUnresolved(value)) {
596-
throw new Error(`Cannot use tokens in keys or values of "${buildPropName}" since they are needed before deployment`);
596+
throw new UnscopedValidationError(`Cannot use tokens in keys or values of "${buildPropName}" since they are needed before deployment`);
597597
}
598598
}
599599
}

packages/aws-cdk-lib/aws-ecr-assets/lib/tarball-asset.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import { Construct } from 'constructs';
44
import { IAsset } from '../../assets';
55
import * as ecr from '../../aws-ecr';
6-
import { AssetStaging, Stack, Stage } from '../../core';
6+
import { AssetStaging, Stack, Stage, ValidationError } from '../../core';
77

88
/**
99
* Options for TarballImageAsset
@@ -60,7 +60,7 @@ export class TarballImageAsset extends Construct implements IAsset {
6060
super(scope, id);
6161

6262
if (!fs.existsSync(props.tarballFile)) {
63-
throw new Error(`Cannot find file at ${props.tarballFile}`);
63+
throw new ValidationError(`Cannot find file at ${props.tarballFile}`, this);
6464
}
6565

6666
const stagedTarball = new AssetStaging(this, 'Staging', { sourcePath: props.tarballFile });

packages/aws-cdk-lib/aws-kms/lib/key.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ export class Key extends KeyBase {
741741
dummyValue: {
742742
keyId: Key.DEFAULT_DUMMY_KEY_ID,
743743
},
744-
ignoreErrorOnMissingContext: options.returnDummyKeyOnMissing,
744+
mustExist: !options.returnDummyKeyOnMissing,
745745
}).value;
746746

747747
return new Import(attributes.keyId,

packages/aws-cdk-lib/aws-ssm/lib/parameter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ export class StringParameter extends ParameterBase implements IStringParameter {
585585
provider: cxschema.ContextProvider.SSM_PARAMETER_PROVIDER,
586586
props: { parameterName },
587587
dummyValue: defaultValue || `dummy-value-for-${parameterName}`,
588-
ignoreErrorOnMissingContext: defaultValue !== undefined,
588+
mustExist: defaultValue === undefined,
589589
}).value;
590590

591591
return value;

packages/aws-cdk-lib/core/lib/context-provider.ts

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,70 @@ export interface GetContextKeyOptions {
3030
*/
3131
export interface GetContextValueOptions extends GetContextKeyOptions {
3232
/**
33-
* The value to return if the context value was not found and a missing
34-
* context is reported.
33+
* The value to return if the lookup has not yet been performed.
34+
*
35+
* Upon first synthesis, the lookups has not yet been performed. The
36+
* `getValue()` operation returns this value instead, so that synthesis can
37+
* proceed. After synthesis completes the first time, the actual lookup will
38+
* be performed and synthesis will run again with the *real* value.
39+
*
40+
* Dummy values should preferably have valid shapes so that downstream
41+
* consumers of lookup values don't throw validation exceptions if they
42+
* encounter a dummy value (or all possible downstream consumers need to
43+
* effectively check for the well-known shape of the dummy value); throwing an
44+
* exception would error out the synthesis operation and prevent the lookup
45+
* and the second, real, synthesis from happening.
46+
*
47+
* ## Connection to mustExist
48+
*
49+
* `dummyValue` is also used as the official value to return if the lookup has
50+
* failed and `mustExist == false`.
3551
*/
3652
readonly dummyValue: any;
3753

3854
/**
39-
* When True, the context provider will not throw an error if missing context
40-
* is reported
55+
* Whether the resource must exist
56+
*
57+
* If this is set (the default), the query fails if the value or resource we
58+
* tried to look up doesn't exist.
59+
*
60+
* If this is `false` and the value we tried to look up could not be found, the
61+
* failure is suppressed and `dummyValue` is officially returned instead.
62+
*
63+
* When this happens, `dummyValue` is encoded into cached context and it will
64+
* never be refreshed anymore until the user runs `cdk context --reset <key>`.
65+
*
66+
* Note that it is not possible for the CDK app code to make a distinction
67+
* between "the lookup has not been performed yet" and "the lookup didn't
68+
* find anything and we returned a default value instead".
69+
*
70+
* ## Context providers
71+
*
72+
* This feature must explicitly be supported by context providers. It is
73+
* currently supported by:
74+
*
75+
* - KMS key provider
76+
* - SSM parameter provider
77+
*
78+
* ## Note to implementors
79+
*
80+
* The dummy value should not be returned for all SDK lookup failures. For
81+
* example, "no network" or "no credentials" or "malformed query" should
82+
* not lead to the dummy value being returned. Only the case of "no such
83+
* resource" should.
84+
*
85+
* @default true
86+
*/
87+
readonly mustExist?: boolean;
88+
89+
/**
90+
* Ignore a lookup failure and return the `dummyValue` instead
91+
*
92+
* `mustExist` is the recommended alias for this deprecated
93+
* property (note that its value is reversed).
4194
*
4295
* @default false
96+
* @deprecated Use mustExist instead
4397
*/
4498
readonly ignoreErrorOnMissingContext?: boolean;
4599
}
@@ -92,6 +146,10 @@ export class ContextProvider {
92146
}
93147

94148
public static getValue(scope: Construct, options: GetContextValueOptions): GetContextValueResult {
149+
if ((options.mustExist !== undefined) && (options.ignoreErrorOnMissingContext !== undefined)) {
150+
throw new Error('Only supply one of \'mustExist\' and \'ignoreErrorOnMissingContext\'');
151+
}
152+
95153
const stack = Stack.of(scope);
96154

97155
if (Token.isUnresolved(stack.account) || Token.isUnresolved(stack.region)) {
@@ -108,10 +166,19 @@ export class ContextProvider {
108166
// if context is missing or an error occurred during context retrieval,
109167
// report and return a dummy value.
110168
if (value === undefined || providerError !== undefined) {
169+
// Render 'ignoreErrorOnMissingContext' iff one of the parameters is supplied.
170+
const ignoreErrorOnMissingContext = options.mustExist !== undefined || options.ignoreErrorOnMissingContext !== undefined
171+
? (options.mustExist !== undefined ? !options.mustExist : options.ignoreErrorOnMissingContext)
172+
: undefined;
173+
111174
// build a version of the props which includes the dummyValue and ignoreError flag
112175
const extendedProps: { [p: string]: any } = {
113176
dummyValue: options.dummyValue,
114-
ignoreErrorOnMissingContext: options.ignoreErrorOnMissingContext,
177+
178+
// Even though we renamed the user-facing property, the field in the
179+
// cloud assembly still has the original name, which is somewhat wrong
180+
// because it's not about missing context.
181+
ignoreErrorOnMissingContext,
115182
...props,
116183
};
117184

0 commit comments

Comments
 (0)