From 33030e0c2bb46fa909540bff6ae0153d48abc9c2 Mon Sep 17 00:00:00 2001 From: Cory Hall <43035978+corymhall@users.noreply.github.com> Date: Tue, 9 Aug 2022 17:49:37 -0400 Subject: [PATCH] docs(ssm): document how to use valueFromLookup for specific value formats (#21520) `StringParameter.valueFromLookup` can be used to retrieve a string value, but that value could be in any format and there are times where it is provided as input to properties that require a specific format (i.e. arn format). Because of the way that lookups are resolved, it is possible for the initial value to be the dummy value `dummy-value-for-${parameterName}` which might cause synth errors. Since there is no way for the CDK to know _how_ you will use the returned value, we can't really add logic to specifically handle edge cases. For example, we could have `valueFromLookup` always return a token, but then it would no longer be able to be used in cases where a `string` is required. See https://github.com/aws/aws-cdk/issues/8699#issuecomment-976159825 for a good analysis. This PR adds documentation instructing users how to handle these use cases. closes #8699, #9138 ---- ### All Submissions: * [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-ssm/README.md | 51 +++++++++++++++++++ .../aws-ssm/rosetta/default.ts-fixture | 4 +- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ssm/README.md b/packages/@aws-cdk/aws-ssm/README.md index 820a2fe2931be..406bab8b9f804 100644 --- a/packages/@aws-cdk/aws-ssm/README.md +++ b/packages/@aws-cdk/aws-ssm/README.md @@ -20,6 +20,56 @@ your CDK app by using `ssm.StringParameter.fromStringParameterAttributes`: [using SSM parameter](test/integ.parameter-store-string.lit.ts) +### Lookup existing parameters + +You can also use an existing parameter by looking up the parameter from the AWS environment. +This method uses AWS API calls to lookup the value from SSM during synthesis. + +```ts +const stringValue = ssm.StringParameter.valueFromLookup(stack, '/My/Public/Parameter'); +``` + +When using `valueFromLookup` an initial value of 'dummy-value-for-${parameterName}' +(`dummy-value-for-/My/Public/Parameter` in the above example) +is returned prior to the lookup being performed. This can lead to errors if you are using this +value in places that require a certain format. For example if you have stored the ARN for a SNS +topic in a SSM Parameter which you want to lookup and provide to `Topic.fromTopicArn()` + +```ts +const arnLookup = ssm.StringParameter.valueFromLookup(this, '/my/topic/arn'); +sns.Topic.fromTopicArn(this, 'Topic', arnLookup); +``` + +Initially `arnLookup` will be equal to `dummy-value-for-/my/topic/arn` which will cause +`Topic.fromTopicArn` to throw an error indicating that the value is not in `arn` format. + +For these use cases you need to handle the `dummy-value` in your code. For example: + +```ts +const arnLookup = ssm.StringParameter.valueFromLookup(this, '/my/topic/arn'); +let arnLookupValue: string; +if (arnLookup.includes('dummy-value')) { + arnLookupValue = this.formatArn({ + service: 'sns', + resource: 'topic', + resourceName: arnLookup, + }); + +} else { + arnLookupValue = arnLookup; +} + +sns.Topic.fromTopicArn(this, 'Topic', arnLookupValue); +``` + +Alternatively, if the property supports tokens you can convert the parameter value into a token +to be resolved _after_ the lookup has been completed. + +```ts +const arnLookup = ssm.StringParameter.valueFromLookup(this, '/my/role/arn'); +iam.Role.fromRoleArn(this, 'role', Lazy.string({ produce: () => arnLookup })); +``` + ## Creating new SSM Parameters in your CDK app You can create either `ssm.StringParameter` or `ssm.StringListParameter`s in @@ -43,3 +93,4 @@ new ssm.StringParameter(this, 'Parameter', { When specifying an `allowedPattern`, the values provided as string literals are validated against the pattern and an exception is raised if a value provided does not comply. + diff --git a/packages/@aws-cdk/aws-ssm/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-ssm/rosetta/default.ts-fixture index 66143d00d0bff..de86c8c95a2da 100644 --- a/packages/@aws-cdk/aws-ssm/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-ssm/rosetta/default.ts-fixture @@ -1,7 +1,9 @@ // Fixture with packages imported, but nothing else import { Construct } from 'constructs'; -import { Stack } from '@aws-cdk/core'; +import { Stack, Lazy } from '@aws-cdk/core'; import * as ssm from '@aws-cdk/aws-ssm'; +import * as sns from '@aws-cdk/aws-sns'; +import * as iam from '@aws-cdk/aws-iam'; class Fixture extends Stack { constructor(scope: Construct, id: string) {