Serverless-application-model: Transforms do not support Conditions

Created on 26 May 2017  路  31Comments  路  Source: aws/serverless-application-model

If I put a Condition on a resource of type "AWS::Serverless::Function", this condition is neither honored by the transform, nor is it passed through to the resources created by the transform. This makes it impossible to conditionally create transformed resources.

Tracking Conditions support:

  • [x] Serverless::Function

    • [x] Function resources (function, IAM role, etc) (v1.10.0)

    • [x] Event resources (permissions, integrations, etc) (v1.10.0) (see https://github.com/awslabs/serverless-application-model/issues/214 for tracking conditions support inside of events, which is not implemented in v1.10.0)

    • [x] Implicit API: Issue https://github.com/awslabs/serverless-application-model/issues/758

    • [x] Alias (v1.10.0)

  • [x] Serverless::Api (v1.10.0)
  • [x] Serverless::LayerVersion (v1.10.0)
  • [x] Serverless::Application (v1.10.0)
  • [x] Serverless::SimpleTable (v1.10.0)

Note: this is only for conditions at the Resource (top) level. For conditions in Events (not yet implemented), see #214

arecloudformation priorit2-important typfeature

Most helpful comment

Any updates or workarounds on this issue?

All 31 comments

Yup, feature request. We already have being implemented now. Will update once its ready.

I would add that my experience has been not just having the transform silently ignore conditions, but rather to have the conditions cause errors (perhaps behavior depends upon where in resource definition the condition is?).

In my case, I was trying to conditionally set the "Path" property on an API event in AWS::Serverless:Function like the following:

      Events:
        GetByKey:
          Type: Api
          Properties:
            Path: !If [DynamoHasRangeKey, '/{hashKey}/{rangeKey}', '/{hashKey}']
            Method: get

The condition above fails when trying to create a change set with generic "internal transform failure" message.

The conditional shown below is in the same resource definition and seems to work just fine.

      Environment:
        Variables:
          !If
            - DynamoHasRangeKey
            -
              DYNAMO_TABLE: !Ref DynamoDbTable
              DYNAMO_HASH_KEY: !Ref DynamoHashKey
              DYNAMO_HASH_KEY_TYPE: !Ref DynamoHashKeyType
              DYNAMO_RANGE_KEY: !Ref DynamoRangeKey
              DYNAMO_RANGE_KEY_TYPE: !Ref DynamoRangeKeyType
            -
              DYNAMO_TABLE: !Ref DynamoDbTable
              DYNAMO_HASH_KEY: !Ref DynamoHashKey
              DYNAMO_HASH_KEY_TYPE: !Ref DynamoHashKeyType

As noted in the related issue I opened, it would at least be useful to get some documentation around current support for conditions (i.e. which specific properties are compatible with conditions),

@mikecbrant that's not a condition, that's a function that evaluates a conditional test (If). Conditions look like this:

AWSTemplateFormatVersion: "2010-09-09"
Conditions: 
  IsTargetRegion: !Equals [ !Ref "AWS::Region", "us-west-2" ]
Resources: 
  NewVolume: 
    Type: "AWS::EC2::Volume"
    Properties: 
      Size: 100
    Condition: IsTargetRegion

The resource gets skipped entirely if the condition evaluates to false.

@brandond Yes, I suppose that would be proper nomenclature, however the intrinsic function in my example is tied to a condition that has defined in the Cloudformation template "Conditions" property (in this case DynamoHasRangeKey). That was probably not clear from my example. This functionality seems to break down in certain places in the template.

If conditional resource creation is eventually supported you might also have to support conditional events as in the following example where in some environments a bucket might not already exist and so it can be created and the event attached to the lambda. While in other environments the bucket may already exist and the trigger needs to be manually defined because cloudformation doesn't yet use existing resources.

For example

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Description: Lambda that responds to S3 events

Parameters:
    PreExistingBucket:
        Description: "Does an existing bucket exist (not managed by cloudformation)"
        Type: String
        Default: 'no'
        AllowedValues:
            - 'yes'
            - 'no'
        ConstraintDescription: must specify yes or no.

Conditions:
  NeedsSomeBucket: !Equals [ !Ref PreExistingBucket, 'no' ]

Resources:
    BucketEventConsumer:
        Type: AWS::Serverless::Function
        Properties:
            Handler: BucketEventConsumer.main.lambda_handler
            Runtime: python3.6
            CodeUri: bundle.zip
            Events:
                CreateMetaEvent:
                    Condition: NeedsSomeBucket
                    Type: S3
                    Properties:
                        Bucket: !Ref SomeBucket
                        Events: "s3:ObjectCreated:*"
                        Filter:
                            S3Key:
                                Rules:
                                    -
                                        Name: suffix
                                        Value: meta.json
    SomeBucket:
        Condition: NeedsSomeBucket
        Type: "AWS::S3::Bucket"
        Properties:
            BucketName: 'some-bucket-somewhere'
        DeletionPolicy: Retain

I'd like to draw your attention to the following crucial lines:

                CreateMetaEvent:
                    Condition: NeedsSomeBucket

@glenveegee That is an interesting thought and idea! Would you mind create a new issue with this use case? It will help us prioritize this in the future and will ensure it does not get lost or forgotten about in this issue (since they are slightly different).

Closing this in favor of #214

224 is a completely separate request and should NOT replace this issue. This is just asking for conditionals to be honored (passed through) - for example, if I put a conditional on a AWS::Serverless::Function, I expect those conditions to be passed through to the resources that the function template expands to (Lambda, IAM role, etc).

This was closed by mistake. Reopening.

Any work around for now?

Any updates or workarounds on this issue?

bump

bump

any update on this yet?

Happy to work with someone if they want to submit a PR for this.

Last message that is was being worked on was about a year ago:
Yup, feature request. We already have being implemented now. Will update once its ready.

Pretty please? :-)

Just been stung by this! Would really appreciate a fix for this soon. Thanks!

Have the same issue, don't want to create a AWS::Serverless::Function in a specific region but the condition is being ignored.

Same here. We need conditions to deploy AWS::Serverless::Function to specific stages. As example to deploy a delete function to test stage but not prod.
Condition is being ignored. It would be great if this is gets implemented.

Does anyone know if adding this feature for AWS::Serverless::Api is also in the works?

Just found this issue deploying between aws partitions. Hopefully there's a fix to this sooner rather then later.

Is this feature in the pipeline?

@alex-gausman We are reviewing it and it should be available with the next SAM release.

@Jacco Just merged in your PR to support conditions! Note, since that PR was submitted prior to our re:Invent release, it adds Condition support for AWS::Serverless::Function, AWS::Serverless::Api, and AWS::Serverless::SimpleTable, but not for the 2 new resource types added for re:Invent: AWS::Serverless::Application and AWS::Serverless::LayerVersion.

Wondering if you'd be willing to submit a PR to add Condition support to those two resources as well prior to our next release. 馃檹

Hi, Any timeline on when this fix (#142) will be released ?

This is staged for the v1.10.0 release (diff) which will be released soon

Released!

I'm having a hard time understanding what should and shouldn't be working at this point. Is this documented somewhere? The spec doesn't really mention conditions.

My reason for seeking this issue out is that I want a function that always exists, but with the ability to toggle whether that function is subscribed to an sns event based on a param evaluated in a condition. The idea is to "disable" the function from acting without having to delete the stack, or to delete the function from the stack.

For example ...

Parameters:
  IsListening:
    AllowedValues: [true, false]
    Default: true
    Type: String

Conditions:
  EventsActive: !Equals ['true', !Ref IsListening]

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Events:
        ExampleTopic:
          Type: SNS
          Condition: EventsActive

In the _Tracking Conditions support:_ checklist at the top of this issue, _Serverless::Function_ > _Events_ is checked off, but then the note next to that checkbox states that "conditions support inside of events [...] is not implemented".

It's not clear to me what the check-off is noting as completed, and it's not clear what exactly is meant by "support inside of events". Based on issue #214, I think what I'm trying to do is not yet possible, but it'd be great to confirm and to find some sort of user-friendly guidance about what _is_ supported.

@rhbecker good call out, we should make what parts of conditions are supported more clear in the documentation. For now, only conditions at the resource level (not property level) are supported in SAM resources.

I updated the first post in this issue with a little more information, will follow up with some more documentation updates later.

thx @keetonian

Was this page helpful?
0 / 5 - 0 ratings