serverless-application-model: Swagger templates don't get transformed when using DefinitionUri
Hi,
I’m trying to package a swagger spec using the flow proposed by SAM, but it doesn’t do the transform properly.
When specifying an AWS::Serverless:Api
resource, I have two options for the swagger spec:
DefinitionUri
DefinitionBody
When I use DefinitionUri
, then any references to Lambda functions in my swagger document will not get transformed to the actual ARNs of the Lambda functions, e.g. (in swagger.yaml)
...
x-amazon-apigateway-integration:
responses:
default:
statusCode: 200
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations"
According to the swagger CORS example in the SAM examples folder, you use DefinitionBody
. The problem with using DefinitionBody
is that the aws cloudformation package
command does not transform any references to a local swagger file into a remote file in S3.
The workaround is that I actually put the swagger spec in S3 myself, but this is clunky and contrary to the existing model.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 59
- Comments: 32 (11 by maintainers)
Any news on this issue ? We just came across the same problem.
For me the solution is for the aws cloudformation package command to upload your swagger file the same way it does with the function CodeUri.
This is a current blocker for us too.
There is no way to use aws cloudformation package and DefinitionBody as it’s not a field that has it’s reference substituted.
https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html
Sorry @Joel-fogue this fell off my radar a bit.
In case you or anyone else is still interested, here is how I’ve set up my CloudFormation template:
In your Swagger template, you can then do things like:
the important step is to have the swagger template copied to an S3 bucket, so my build step for CodeBuild looks something like:
Hope this helps, sorry for the late response.
I’d recommend using the
AWS::Include
transform to have CloudFormation automatically include the OpenApi file in your template for you. You can still reference an external file, like inDefinitionUri
, but without the drawback of not being able to resolve CFN intrinsics in it or having SAM integrations not work.Here’s an example:
I’ve reached out to the API Gateway team to see if they will fix the underlying issue. However, if they are unable to fix it we may be able to do something like this:
DefinitionUri
to also accept anObject
sam package
, SAM will perform operations onDefinitionUri
based on the configuration specifiedPath
will be either a local file path, or an S3 path. If it’s an S3 path, it will be downloaded.Inline: true
will replaceDefinitionUri
withDefinitionBody
and inline the contents of the swagger file there. SAM will then perform transforms against thatDefinitionBody
as normal.Upload: true
will upload to S3. Default to false as I think most don’t want this, however, there are cases where you still want to upload to S3 (e.g if you’re using that to generate documentation).Upload: true
will thrown an error if an S3 path is provided inPath
.We’ll create an RFC for this and accept contributions if people think this will solve their problem.
I can confirm along with @joquijada this does work with our build pipeline too (via Jenkins, though it uses regular AWS CloudFormation/SAM commands).
Interestingly the AWS::Include documentation says this:
All the examples show S3, and but it does indeed work with a local URI:
template.yaml
It looks like the CLI tools are now smart enough to upload the file to the same S3 bucket and reference it. This was definitely NOT the case in late July 2019 because I had to write a workaround to upload the Swagger spec to S3, then pass the S3 URI to the stack as a parameter for use in the
DefinitionBody
section.CloudFormation Service > Select Stack > Template Tab
I’ve encountered this issue as well. Eagerly waiting for sam to support this. I can’t see any reasonable use for
DefinitionUri
when you would have to hardcode the references to your lambdas. But ideally, I really shouldn’t be forced to add API Gateway integration code to the swagger file when I already have the API mappings on my function definitions.@AlexThomas90210 Until cloudformation package supports it, I added an
aws s3 cp
command into our build system (CodeBuild) .Any update on the proposed new feature is there a PR yet?
We haven’t found a simple way to make this work as part of the SAM transform, we are still following up with CloudFormation team. If that doesn’t work out, the next best option would be to change the sam cli package command to inline swagger that is referenced in a separate file.
@oharaandrew314 I kinda agree; I was able to get things working normally without the swagger way; but instead implicitly defining the api endpoints within the sam template.yml but I just thought it was cleaner with swagger. Now I no longer think so unless I don’t understand the swagger example (api_swagger_cors); it looks like you define the lambda function twice:
My expectation would be that the swagger definition file would take care of creating the API as well as pointing to the right lambdas through the Fn::Sub: right above.
Could anyone tell me why one would choose the Swagger way over the other way which is to just list out all functions and endpoints in the sam template and let sam create the api for you implicitly?
Thanks @dacgray for providing a working example for the issue.
Closing as there is already a solution. Please use
DefinitionBody
withAWS::Include
.I got everything working with this setup - took me a good few hours to figure everything out - so I hope this saves someone some time.
This demos two endpoints each pointing to different functions.
Dev:
Deploy:
Delete:
Template.yaml
swagger-node.yaml
samconfig.toml
/node-<world|moon>/app.js
I did a CodeBuild a few days ago with a
template.yml
to define a Lambda and an API that references a local swagger file, and the local swagger file reference got automatically transformed into a remote file in S3. Maybe a more recent version of the AWS CLI released after this issue got created that supports this feature. Below is mytemplate.yml
andbuildspect.yml
for reference,template.yml
buildspec.yml
@praneetap any updates on this?
@brettstack Thank you. This will be helpful. In the meantime, what is the best-practice recommendation?
Currently I am think that I need to rip out the Swagger code and rebuild the API definition in pure CloudFormation – which does not sound like fun. I get the impression there is a reason people prefer to use Swagger.