Closed khornberg closed 4 years ago
If I do something like Function.from_function_arn(self, 'x', core.Fn.get_att("SomeFunction", "Arn"))
I get a synth error like jsii.errors.JSIIError: Expected Scalar, got {"$jsii.byref":"@aws-cdk/core.Intrinsic@10015"}
However, core.Fn.import_value
does not result in a synth error
Where are you exporting the lambda’s logical ID that this stack is importing?
Okay. There’s a few things here. Fn.get_att(“someFunction”, “Arn”) would throw an error if you didn’t have a function with the logical ID of “someFunction” in the same stack (which is highly unlikely in a CDK stack).
Fn.Import_value(“SomeFunction”) will look for a CFN Export in the same account/region.
My assumption is that you are exporting a Lambda’s logical ID in a different stack when you should probably be exporting the Lambda’s Arn instead.
Happy to walk you though it if you can share your CDK or YAML
You are correct that the import value is in a different stack.
Outputs:
ValidateVersionBump:
Value:
Ref: ValidateVersionBumpLambdaFunction
Description: Name of the lambda function used in CodePipeline to disable ServiceCatalog updates
Export:
Name: ValidateVersionBumpLambda
I have a working CF template that defines the CodePipeline. I am trying recreate it using CDK.
This actions works and it also part of a separate stack.
Actions:
- Name: Validate-Version-Bump
RunOrder: 1
ActionTypeId:
Category: Invoke
Owner: AWS
Provider: Lambda
Version: '1'
InputArtifacts:
- Name: Artifact
Configuration:
FunctionName:
Fn::ImportValue: ValidateVersionBumpLambda
I have monkey patched the CDK output to fix the perceived errors above and the stack works. I guess I am expecting a fairly similar mapping of concepts between CloudFormation and CDK. If I am able to import the logical id of a function and it works in CF, then I expect to be able to do the same in CDK.
Given what you have said, is there a way to get the arn from a logical id import in CDK?
I’m not sure that would work. If your other stack was pure cloudformation (instead of CDK) it would still just import the Lambda’s name and not it’s ARN. I would change your export to export the ARN instead of the Name.
Outputs:
ValidateVersionBump:
Value:
!GetAtt ValidateVersionBumpLambdaFunction.Arn
Description: Name of the lambda function used in CodePipeline to disable ServiceCatalog updates
Export:
Name: ValidateVersionBumpLambda
You could also manually reconstruct the Arn from the Function’s Name (the current export) and the environment variables (AccountId, Region, etc...)
I’m not sure that would work.
I'm not sure either but it does ¯_(ツ)_/¯
Perhaps because the Configuration
is a json field and CloudFormation knows how to sort it out
Can you share your CDK code? If the Pipeline accepts a Function Name in regular cloudformation, the same thing should work in CDK. In your original issue you used from_function_arn() but then you imported a value that represented the function name, not the arn. You want either from_function_attributes() or one of the lookup methods.
Did some more digging. It looks like the Lambda module should have either a Lambda.from_name()
method added or from_attributes()
should accept a Lambda Function name as an attribute.
This should work for you. Unfortunately, until the Lambda Module adds the needed functions, you will have to reconstruct the Arn from the name, so that the Pipeline Construct can extract it.
from aws_cdk import core
from aws_cdk import core
from aws_cdk.aws_codepipeline import Artifact
from aws_cdk.aws_codepipeline import Pipeline
from aws_cdk.aws_codepipeline import StageProps
from aws_cdk.aws_codepipeline_actions import GitHubSourceAction
from aws_cdk.aws_codepipeline_actions import LambdaInvokeAction
from aws_cdk.aws_iam import Role
from aws_cdk.aws_lambda import Function
from aws_cdk.aws_s3 import Bucket
class FunctionImportStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
bucket = Bucket.from_bucket_name(
self, "artifacts", core.Fn.import_value("CodeArtifactsBucket")
)
pipeline_role = Role.from_role_arn(
self, "pipeline", core.Fn.import_value("CodePipelineRole")
)
lambda_arn = "arn:{partition}:lambda:{region}:{account_id}:function:{name}".format(
partition=core.Aws.PARTITION,
region=core.Aws.REGION,
account_id=core.Aws.ACCOUNT_ID,
name=core.Fn.import_value("SomeFunction")
)
pipeline = Pipeline(
self,
"Pipeline",
artifact_bucket=bucket,
role=pipeline_role,
stages=[
StageProps(
stage_name="Source",
actions=[
GitHubSourceAction(
action_name="Source",
run_order=1,
oauth_token=core.SecretValue("something"),
output=Artifact(artifact_name="SourceArtifact"),
owner="me",
repo="repo",
branch="master",
)
],
)
],
)
pipeline.add_stage(
stage_name="Fails",
actions=[
LambdaInvokeAction(
action_name="LambdaInvokeAction",
run_order=1,
lambda_= Function.from_function_arn(self, "function", lambda_arn)
)
]
)
Actually, this would even work too, since it appears to ignore the rest of the arn anyways.
pipeline.add_stage(
stage_name="Fails",
actions=[
LambdaInvokeAction(
action_name="LambdaInvokeAction",
run_order=1,
lambda_= Function.from_function_arn(self, "function", "arn:::::function:{}".format(core.Fn.import_value("SomeFunction")))
)
]
)
Thanks @rhboyd
lambda_arn = "arn:{partition}:lambda:{region}:{account_id}:function:{name}".format(
partition=core.Aws.PARTITION,
region=core.Aws.REGION,
account_id=core.Aws.ACCOUNT_ID,
name=core.Fn.import_value("SomeFunction")
)
worked but "arn:::::function:{}".format(core.Fn.import_value("SomeFunction"))
did not because that ends up as invalid in the policy document created by CDK.
@khornberg is there anything else we can help you with this issue?
No I've since moved on
:bug: Bug Report
What is the problem?
A CodePipeline with a LambdaInvokeAction wrongly assumes that ImportValue of a Lambda is the ARN but it is the logical ID. The pipeline policy also wrongly assumes the import value.
Reproduction Steps
Clone https://github.com/khornberg/cdk-bugs Install pip packages (assuming one has the npm package already) Run
cdk synth --path-metadata false --version-reporting false --app "python3 pipeline-lambda-invoke-action-bug.py"
Verbose Log
https://github.com/khornberg/cdk-bugs/blob/master/output.yaml
Pipeline action Lines 78-82 are wrong and will fail
Policy Lines 135-138
The action is created thus
Environment