Closed sanathkr closed 6 years ago
_examples/2016-10-31/api_swaggercors seems to inject the function logical name. Could we somehow get the full ARN such that we don't have to hard-code region
and accountId
into Swagger (or defining them as stage variables) as well? Thanks
Yes, getting the full ARN would be useful. This will solve my problem with using a stage variable for the account ID - #87
Our current cheapo workaround (since we cannot use the inlined body directly in other tools like Swagger Editor, or for input validation) is to maintain a separate swagger.yaml
, but format everything as if it was inside the SAM template (i.e. we can reference parameters through ${}
syntax).
We then terminate the actual SAM template with the Api resource, but instead of specifying a value of the DefinitionBody
as the last parameter (after an obvious !Sub |-
), we concatenate the Swagger file before packaging the application (YAML lets you do that if you also properly indent all lines of the Swagger file, either explicitly in the file or using a regular expression in gulp-replace
or something similar).
Nice, it seems like now we will be able to use http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html to directly insert the Swagger YAML stored on S3 (but before any substitutions are made). Will report back once I test it.
Eager to see what possible with include transform, wonder if they will allow you to point to a local template like aws package
does.
Finally got it working! In my SAM template:
Api:
Type: AWS::Serverless::Api
Properties:
StageName: Latest
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: !Sub s3://${ArtifactsBucket}/swagger.yaml
where ArtifactsBucket
refers to the bucket where I upload my Swagger spec prior to 'packaging' the SAM template. Then, in the Swagger template itself I can use the intrinsics, e.g.
x-amazon-apigateway-integration:
type: aws_proxy
httpMethod: POST
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetProjects.Arn}/invocations
I'm using the long Fn::Sub
notation here instead of just !Sub
, because Swagger doesn't natively support the latter, and also because the docs on AWS::Include
Transform say that shorthand forms are not supported yet.
On a side note, just wasted ~4 hours troubleshooting the Invalid ARN specified in the request
error, thinking that Fn::Sub
for function ARNs doesn't work. Turns out, I only forgot to prepend an ARN reference for authorizerCredentials
role in the spec (I'm using a custom authorizer). I really wish API Gateway import errors were more informative! Like specifying the concrete line that fails.. In any case, just make sure to prepend Fn::Sub
/Fn::Ref
/Fn::GetAtt
to ALL of your CloudFormation references in the spec.
P.S. Not sure about local references, that would be awesome though!
Any update on using local reference with AWS::Include?
Also, I tried passing in the Lambda ARN and the region as stage variables as shown above by @sanathkr, but this did not work. Still got an "Invalid ARN specified in the request" error. Is this pattern no longer supported?
I tried the stage variables approach too and it did not work for me either. Will try the approach @dinvlad suggested.
@dinvlad your approach looks great, but is there a way to avoid the manual swagger file upload? I would rather reference a local file (as I'm currently doing with DefinitionUri
), and I'd expect cloudformation package
to take care of the packaging for me.
Does it make sense? Am I missing something obvious?
@alexcasalboni agreed, that would be awesome. I don't think CF currently supports that though. package
might though, but that is part of CLI so perhaps we should ask there.
Also, you can paste your entire swagger inside CF template, and reference variables the same way. But that blows up the size of the SAM template, which is currently limited to 51.2 KB (last time I checked).
@dinvlad Yes, that's what I'm doing right now. Inlining a small API sounded reasonable. And thanks for the template size limit, that's good to know!
Note that, at least for me, the method @dinvlad recommends doesn't work if the Include
'd Swagger file is > whatever the size limit is. Gets the following error in CF console:
Errors found during import: Unable to put integration on 'GET' for resource at path '/account': The item is too large. Please reduce the item size.
Template size limit is 460KB if you upload it to S3 and pass the S3 URL to CloudFormation.
I don't see us doing this at the moment for external swagger files. Best is to either inline the Swagger file or use AWS::Include
to let CloudFormation inline the file on runtime.
When using a Swagger file to define an API, users have to explicitly specify
Stage Variables
to hold the Lambda function ARN and use the stage variable in their Swagger template to specify the integration. This is not intuitive.We could simplify this process by automatically injecting the Stage Variable when users specify an API Event source to their Lambda Function
When customers specify a template like this:
we could inject a StageVariable to the API resource where variable name is equal to the function resource's logical name and value equal to the function's ARN