-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
Description:
SAM should support Conditions, as proposed in #142. Adding conditions to events was implemented in #653 and fixed in #755 for everything except for API events referencing the implicit API.
Problem Statement:
Supporting CloudFormation Conditions for API Events that use SAM's implicit API is not as straightforward as supporting them for other event types.
Details:
When a Serverless Function defines an event that uses the implicit API, SAM creates the implicit API as well as any other resources needed by that API. If multiple functions define events that use the implicit API, these events all refer to the same implicit API. This means that this one API and supporting resources needs to be created or not created based on many different functions with possibly different Conditions, as well as the paths inside of the API.
This is for conditions specified on a Serverless Function, like the following example; these conditions need to be added to the resources that are created (like the implicit API). Support for Conditions added inside of the Events property is not in the scope of this proposal and is covered in #214 .
MyFunction:
Condition: MyCondition
Type: AWS::Serverless::Function
Properties:
...
Events:
ApiEvent: ...
Solution:
- If no Conditions are used, then nothing needs to be changed
- If one function references the implicit API and that function has a condition, then that condition will be added to both the API paths and the API resources
- Note: Conditions need to be added to the API resources. See ServerlessRestApi Resources section below.
- If functions with conditions and functions without conditions reference the implicit API, then conditions need to be placed on the API paths but not on the API resources
- If multiple conditions are present, then each path will have its corresponding condition and those conditions will be combined into an aggregate condition that will be added to the API resources.
Changes Required:
- Add ability to add conditions to implicit API paths
- Add ability to create an aggregate condition if necessary
- Add ability to add the aggregate condition to API resources if necessary
ServerlessRestApi Paths:
Adding conditions on the path definitions is required for conditions to work for API events from Serverless Functions.
NOTE: In implementing this feature, I found that the condition should be added inside of the method instead of inside the path. This still allows several methods to be added per path instead of just one, and each one can have their own condition as needed. This has been verified to work in deploying to CFN.
Example:
"paths": {
"/add": {
"get": {
"Fn::If": [
"Condition",
{
Integrations...
}
},
{"Ref": "AWS::NoValue"}
]
},
"post": {
"Fn::If": [
"Condition",
{
Integrations...
}
},
{"Ref": "AWS::NoValue"}
]
}
}
}
ServerlessRestApi Resources:
The resources themselves need to be conditionally created based on the conditions on the Serverless Functions that have API events. This can be accomplished by adding an aggregated condition to these resources. See the next section on creating an aggregate condition.
If you try to create an ApiGateway Deployment resource that references an ApiGateway RestApi resource that doesn't have any paths, the following error is encountered.
10 Jan 2019 20:44:25 ServerlessRestApiDeployment15289cf229 CREATE_FAILED The REST API doesn't contain any methods (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 84632892-1518-11e9-b53b-9d3e41c7c615)
Combining Conditions:
Conditions can be combined using the Fn::Or
intrinsic function, as follows. SAM will create an aggregate condition of all conditions used on Serverless Functions that reference the implicit API IFF no condition-less functions reference the implicit API. If a function without a condition references the API, the API will always be needed and not need to be conditionally created.
"Conditions": {
"Condition1":...,
"Condition2":...,
"SamImplicitApiCondition": {"Fn::Or": [{"Condition": "Condition1"}, {"Condition": "Condition2" }]}
}
...
"Resources: {
"ServerlessRestApi": {
"Condition": "SamImplicitApiCondition",
"Type": "AWS::ApiGateway::RestApi",
...
},
"ServerlessRestApiDeployment123hash": {
"Condition": "SamImplicitApiCondition",
"Type": "AWS::ApiGateway::Deployment",
...
}
}
The above example assumes that there are two functions in the template, each one with a separate condition, and each define an implicit API event.