Repository: serverless/serverless (JavaScript)
Date: 2019-09-05 22:48:30+00:00
Task type: Feature

Issue:
Support Condition and DependsOn
<!--
1. If you have a question and not a feature request please ask first at http://forum.serverless.com
2. Please check if an issue already exists. This feature may have already been requested
3. Check out and follow our Guidelines: https://github.com/serverless/serverless/blob/master/CONTRIBUTING.md
4. Fill out the whole template so we have a good overview on the issue
5. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the Issue
6. Please follow the template, otherwise we'll have to ask you to update it
-->

# This is a Feature Proposal

## Description

Allow users to specify `condition` and `dependsOn` on functions and compile them to CloudFormation `Condition` and `DependsOn` for the Lambda function resource.


Issue discussion:

Solution patch:
diff --git a/docs/providers/aws/guide/serverless.yml.md b/docs/providers/aws/guide/serverless.yml.md
index 5bbbf1b1b89..e96a65004a8 100644
--- a/docs/providers/aws/guide/serverless.yml.md
+++ b/docs/providers/aws/guide/serverless.yml.md
@@ -190,6 +190,10 @@ functions:
     layers: # An optional list Lambda Layers to use
       - arn:aws:lambda:region:XXXXXX:layer:LayerName:Y # Layer Version ARN
     tracing: Active # optional, can be 'Active' or 'PassThrough' (overwrites the one defined on the provider level)
+    condition: SomeCondition # optional, adds 'Condition' clause
+    dependsOn: # optional, appends these additional resources to the 'DependsOn' list
+      - MyThing
+      - MyOtherThing
     events: # The Events that trigger this Function
       - http: # This creates an API Gateway HTTP endpoint which can be used to trigger this function.  Learn more in "events/apigateway"
           path: users/create # Path for this endpoint
diff --git a/lib/plugins/aws/package/compile/functions/index.js b/lib/plugins/aws/package/compile/functions/index.js
index 9ced25d7c2c..004cf14c936 100644
--- a/lib/plugins/aws/package/compile/functions/index.js
+++ b/lib/plugins/aws/package/compile/functions/index.js
@@ -43,7 +43,9 @@ class AwsCompileFunctions {
         if ('Fn::GetAtt' in role) {
           // role is an "Fn::GetAtt" object
           compiledFunction.Properties.Role = role;
-          compiledFunction.DependsOn = [role['Fn::GetAtt'][0]];
+          compiledFunction.DependsOn = (compiledFunction.DependsOn || []).concat(
+            role['Fn::GetAtt'][0]
+          );
         } else if ('Fn::ImportValue' in role) {
           // role is an "Fn::ImportValue" object
           compiledFunction.Properties.Role = role;
@@ -58,11 +60,13 @@ class AwsCompileFunctions {
         } else if (role === 'IamRoleLambdaExecution') {
           // role is the default role generated by the framework
           compiledFunction.Properties.Role = { 'Fn::GetAtt': [role, 'Arn'] };
-          compiledFunction.DependsOn = ['IamRoleLambdaExecution'];
+          compiledFunction.DependsOn = (compiledFunction.DependsOn || []).concat(
+            'IamRoleLambdaExecution'
+          );
         } else {
           // role is a Logical Role Name
           compiledFunction.Properties.Role = { 'Fn::GetAtt': [role, 'Arn'] };
-          compiledFunction.DependsOn = [role];
+          compiledFunction.DependsOn = (compiledFunction.DependsOn || []).concat(role);
         }
         break;
       default:
@@ -183,6 +187,14 @@ class AwsCompileFunctions {
       newFunction.Properties.Description = functionObject.description;
     }
 
+    if (functionObject.condition) {
+      newFunction.Condition = functionObject.condition;
+    }
+
+    if (functionObject.dependsOn) {
+      newFunction.DependsOn = (newFunction.DependsOn || []).concat(functionObject.dependsOn);
+    }
+
     if (functionObject.tags || this.serverless.service.provider.tags) {
       const tags = Object.assign({}, this.serverless.service.provider.tags, functionObject.tags);
       newFunction.Properties.Tags = [];


Test patch:
diff --git a/lib/plugins/aws/package/compile/functions/index.test.js b/lib/plugins/aws/package/compile/functions/index.test.js
index 654e4bfb033..bd533359344 100644
--- a/lib/plugins/aws/package/compile/functions/index.test.js
+++ b/lib/plugins/aws/package/compile/functions/index.test.js
@@ -2432,5 +2432,39 @@ describe('AwsCompileFunctions', () => {
         ).to.deep.equal(compiledFunction);
       });
     });
+
+    it('should set Condition when specified', () => {
+      awsCompileFunctions.serverless.service.functions = {
+        func: {
+          handler: 'func.function.handler',
+          name: 'new-service-dev-func',
+          condition: 'IsE2eTest',
+        },
+      };
+
+      return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => {
+        expect(
+          awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources
+            .FuncLambdaFunction.Condition
+        ).to.equal('IsE2eTest');
+      });
+    });
+
+    it('should include DependsOn when specified', () => {
+      awsCompileFunctions.serverless.service.functions = {
+        func: {
+          handler: 'func.function.handler',
+          name: 'new-service-dev-func',
+          dependsOn: ['MyThing', 'MyOtherThing'],
+        },
+      };
+
+      return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => {
+        expect(
+          awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources
+            .FuncLambdaFunction.DependsOn
+        ).to.deep.equal(['FuncLogGroup', 'MyThing', 'MyOtherThing', 'IamRoleLambdaExecution']);
+      });
+    });
   });
 });