Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/aws-cdk-lib/aws-kms/lib/key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ export class Key extends KeyBase {
dummyValue: {
keyId: Key.DEFAULT_DUMMY_KEY_ID,
},
ignoreErrorOnMissingContext: options.returnDummyKeyOnMissing,
mustExist: !options.returnDummyKeyOnMissing,
}).value;

return new Import(attributes.keyId,
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk-lib/aws-ssm/lib/parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ export class StringParameter extends ParameterBase implements IStringParameter {
provider: cxschema.ContextProvider.SSM_PARAMETER_PROVIDER,
props: { parameterName },
dummyValue: defaultValue || `dummy-value-for-${parameterName}`,
ignoreErrorOnMissingContext: defaultValue !== undefined,
mustExist: defaultValue === undefined,
}).value;

return value;
Expand Down
77 changes: 72 additions & 5 deletions packages/aws-cdk-lib/core/lib/context-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,70 @@
*/
export interface GetContextValueOptions extends GetContextKeyOptions {
/**
* The value to return if the context value was not found and a missing
* context is reported.
* The value to return if the lookup has not yet been performed.
*
* Upon first synthesis, the lookups has not yet been performed. The
* `getValue()` operation returns this value instead, so that synthesis can
* proceed. After synthesis completes the first time, the actual lookup will
* be performed and synthesis will run again with the *real* value.
*
* Dummy values should preferably have valid shapes so that downstream
* consumers of lookup values don't throw validation exceptions if they
* encounter a dummy value (or all possible downstream consumers need to
* effectively check for the well-known shape of the dummy value); throwing an
* exception would error out the synthesis operation and prevent the lookup
* and the second, real, synthesis from happening.
*
* ## Connection to mustExist
*
* `dummyValue` is also used as the official value to return if the lookup has
* failed and `mustExist == false`.
*/
readonly dummyValue: any;

/**
* When True, the context provider will not throw an error if missing context
* is reported
* Whether the resource must exist
*
* If this is set (the default), the query fails if the value or resource we
* tried to look up doesn't exist.
*
* If this is `false` and the value we tried to look up could not be found, the
* failure is suppressed and `dummyValue` is officially returned instead.
*
* When this happens, `dummyValue` is encoded into cached context and it will
* never be refreshed anymore until the user runs `cdk context --reset <key>`.
*
* Note that it is not possible for the CDK app code to make a distinction
* between "the lookup has not been performed yet" and "the lookup didn't
* find anything and we returned a default value instead".
*
* ## Context providers
*
* This feature must explicitly be supported by context providers. It is
* currently supported by:
*
* - KMS key provider
* - SSM parameter provider
*
* ## Note to implementors
*
* The dummy value should not be returned for all SDK lookup failures. For
* example, "no network" or "no credentials" or "malformed query" should
* not lead to the dummy value being returned. Only the case of "no such
* resource" should.
*
* @default true
*/
readonly mustExist?: boolean;

/**
* Ignore a lookup failure and return the `dummyValue` instead
*
* `mustExist` is the recommended alias for this deprecated
* property (note that its value is reversed).
*
* @default false
* @deprecated Use mustExist instead
*/
readonly ignoreErrorOnMissingContext?: boolean;
}
Expand Down Expand Up @@ -92,6 +146,10 @@
}

public static getValue(scope: Construct, options: GetContextValueOptions): GetContextValueResult {
if ((options.mustExist !== undefined) && (options.ignoreErrorOnMissingContext !== undefined)) {
throw new Error('Only supply one of \'mustExist\' and \'ignoreErrorOnMissingContext\'');

Check warning on line 150 in packages/aws-cdk-lib/core/lib/context-provider.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L150 was not covered by tests
}

const stack = Stack.of(scope);

if (Token.isUnresolved(stack.account) || Token.isUnresolved(stack.region)) {
Expand All @@ -108,10 +166,19 @@
// if context is missing or an error occurred during context retrieval,
// report and return a dummy value.
if (value === undefined || providerError !== undefined) {
// Render 'ignoreErrorOnMissingContext' iff one of the parameters is supplied.
const ignoreErrorOnMissingContext = options.mustExist !== undefined || options.ignoreErrorOnMissingContext !== undefined
? (options.mustExist !== undefined ? !options.mustExist : options.ignoreErrorOnMissingContext)
: undefined;

// build a version of the props which includes the dummyValue and ignoreError flag
const extendedProps: { [p: string]: any } = {
dummyValue: options.dummyValue,
ignoreErrorOnMissingContext: options.ignoreErrorOnMissingContext,

// Even though we renamed the user-facing property, the field in the
// cloud assembly still has the original name, which is somewhat wrong
// because it's not about missing context.
ignoreErrorOnMissingContext,
...props,
};

Expand Down