Repository: cloud-custodian/cloud-custodian

Issue:
Lambda-Specific Resource Actions Enhancement
We use Cloud Custodian to report on non-compliant Lambda functions, and having an action that suspends them like other resource types would be useful.

(I realize it's not really due to cost, it's more about maintenance and being able to contact someone when their code goes sideways.)

A really effective way of disabling lambdas is setting their concurrency to 0. Below is the script we've been using - it just takes as input a file name that has lambda function names deliminated by a newline char.

```
> import boto3
> 
> __filepath__ = 'lambda.txt'
> 
> def suspend_lambda(client, function_name):
>     response = client.put_function_concurrency(
>         FunctionName=function_name,
>         ReservedConcurrentExecutions=0
>     )
>     return response
> 
> def main():
>     
>     client = boto3.client('lambda', region_name = 'us-west-2')
>     
>     with open(__filepath__) as fp:
>         line = fp.readline()
>         while line:
>           try:
>             line = fp.readline().strip()
>             print(line)
>             response = suspend_lambda(client, line)
>           except Exception as e:
>             print(e)
>             pass
>     return
> 
> if __name__ == '__main__':
>     main()
```
If this is already a feature that I'm not aware of, please let me know 👍

EDIT: the code looks a little funny because github isn't commenting out the code right... 


Discussion:
one caveat we'll need to add a separate filter (at the cost of an api call per lambda) to retrieve extant reserved concurrency allocation. i took a stab at the action earlier today, for setting concurrency to a static value, deleting concurrency, and setting concurrency to a cw metric queried value.

Resolving patch:
diff --git a/c7n/resources/awslambda.py b/c7n/resources/awslambda.py
--- a/c7n/resources/awslambda.py
+++ b/c7n/resources/awslambda.py
@@ -13,7 +13,10 @@
 # limitations under the License.
 from __future__ import absolute_import, division, print_function, unicode_literals
 
+import jmespath
 import json
+import six
+
 from botocore.exceptions import ClientError
 
 from c7n.actions import ActionRegistry, BaseAction, RemovePolicyBase
@@ -110,6 +113,40 @@ class SubnetFilter(net_filters.SubnetFilter):
 filters.register('network-location', net_filters.NetworkLocation)
 
 
+@filters.register('reserved-concurrency')
+class ReservedConcurrency(ValueFilter):
+
+    annotation_key = "c7n:FunctionInfo"
+    value_key = '"c7n:FunctionInfo".Concurrency.ReservedConcurrentExecutions'
+    schema = type_schema('reserved-concurrency', rinherit=ValueFilter.schema)
+    permissions = ('lambda:GetFunction',)
+
+    def validate(self):
+        self.data['key'] = self.value_key
+        return super(ReservedConcurrency, self).validate()
+
+    def process(self, resources, event=None):
+        self.data['key'] = self.value_key
+        client = local_session(self.manager.session_factory).client('lambda')
+
+        def _augment(r):
+            try:
+                r[self.annotation_key] = self.manager.retry(
+                    client.get_function, FunctionName=r['FunctionArn'])
+                r[self.annotation_key].pop('ResponseMetadata')
+            except ClientError as e:
+                if e.response['Error']['Code'] == 'AccessDeniedException':
+                    self.log.warning(
+                        "Access denied getting lambda:%s",
+                        r['FunctionName'])
+                raise
+            return r
+
+        with self.executor_factory(max_workers=3) as w:
+            resources = list(filter(None, w.map(_augment, resources)))
+            return super(ReservedConcurrency, self).process(resources, event)
+
+
 @filters.register('event-source')
 class LambdaEventSource(ValueFilter):
     # this uses iam policy, it should probably use
@@ -134,6 +171,7 @@ def _augment(r):
                     self.log.warning(
                         "Access denied getting policy lambda:%s",
                         r['FunctionName'])
+                raise
 
         self.log.debug("fetching policy for %d lambdas" % len(resources))
         self.data['key'] = self.annotation_key
@@ -352,6 +390,61 @@ def process_resource_set(self, functions, tag_keys):
             client.untag_resource(Resource=arn, TagKeys=tag_keys)
 
 
+@actions.register('set-concurrency')
+class SetConcurrency(BaseAction):
+    """Set lambda function concurrency to the desired level.
+
+    Can be used to set the reserved function concurrency to an exact value,
+    to delete reserved concurrency, or to set the value to an attribute of
+    the resource.
+    """
+
+    schema = type_schema(
+        'set-concurrency',
+        required=('value',),
+        **{'expr': {'type': 'boolean'},
+           'value': {'oneOf': [
+               {'type': 'string'},
+               {'type': 'integer'},
+               {'type': 'null'}]}})
+
+    permissions = ('lambda:DeleteFunctionConcurrency',
+                   'lambda:PutFunctionConcurrency')
+
+    def validate(self):
+        if self.data.get('expr', False) and not isinstance(self.data['value'], six.text_type):
+            raise ValueError("invalid value expression %s" % self.data['value'])
+        return self
+
+    def process(self, functions):
+        client = local_session(self.manager.session_factory).client('lambda')
+        is_expr = self.data.get('expr', False)
+        value = self.data['value']
+        if is_expr:
+            value = jmespath.compile(value)
+
+        none_type = type(None)
+
+        for function in functions:
+            fvalue = value
+            if is_expr:
+                fvalue = value.search(function)
+                if isinstance(fvalue, float):
+                    fvalue = int(fvalue)
+                if isinstance(value, int) or isinstance(value, none_type):
+                    self.policy.log.warning(
+                        "Function: %s Invalid expression value for concurrency: %s",
+                        function['FunctionName'], fvalue)
+                    continue
+            if fvalue is None:
+                client.delete_function_concurrency(
+                    FunctionName=function['FunctionName'])
+            else:
+                client.put_function_concurrency(
+                    FunctionName=function['FunctionName'],
+                    ReservedConcurrentExecutions=fvalue)
+
+
 @actions.register('delete')
 class Delete(BaseAction):
     """Delete a lambda function (including aliases and older versions).


Test patch:
diff --git a/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.DeleteFunctionConcurrency_1.json b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.DeleteFunctionConcurrency_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.DeleteFunctionConcurrency_1.json
@@ -0,0 +1,16 @@
+{
+    "status_code": 204, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 204, 
+            "RequestId": "46596322-1265-11e8-8d62-87c470711278", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:31:21 GMT", 
+                "x-amzn-requestid": "46596322-1265-11e8-8d62-87c470711278", 
+                "connection": "keep-alive", 
+                "content-type": "application/json"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.GetFunction_1.json b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.GetFunction_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.GetFunction_1.json
@@ -0,0 +1,45 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Concurrency": {
+            "ReservedConcurrentExecutions": 5
+        }, 
+        "Code": {
+            "RepositoryType": "S3", 
+            "Location": "https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/644160558196/envcheck-1e140743-adb2-45e5-aead-4ebcbe741d15?X-Amz-Security-Token=FQoDYXdzEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDMSjoT5%2F9Uv7w%2BqHSyK3AzFNzhChufu%2F4eausIkLsEaX3W9im%2FOmiffDx0TTWVfYFhIFYmj6Gd6Acp%2BmP1xgmjYv9pJUEdWotvjDrQLv6KY%2B5T9ogbMm9sIYIhESvW4b0M8IuotmL5wnNfWQludcaaOLK6MHbxqAHY6T2CKQN384deHduIdhli4KI45owEG54p9fYfXUxu7xg%2B0T4pj4q2v%2F743iJWLK%2BDG9bA9%2F8hHLF0vPBXTsVweiOFfQn7Qqiq6NKSEOQH5ON1d84lE5Zn05HCO0WowNoszswKXBvdFWMUYT2fjkr9iLxNHkpW0l9n7RsCGJxWoGm12aIGycDTD5CDyUgJgLZfYPJCIfYEYulAsxu7VG2RAsyRlsG7BdCG379DfZiFTBorM3IZzlRG3JueB0if06z%2Be%2BiidAi2ANfxJA7QU%2FVVS9WzirZ2rljVbTltN2vXlWherINeJW0DL5hTR0fcieOTSjEdxungzbpFXowEAZZyh5W7W%2BzzULwobtPGQ6%2B%2BVB7LSLxtR2RxN0qwJguhOZiZTymgHq1K0nxOjEOxoZnrn2k6BzFvCJoeTLymactG49Gz8hDEk1HfLqPUonCIEousOW1AU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180215T153121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAJEDYJ7DVWIHC54BQ%2F20180215%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=6be3bf5552c1142553af08ed8c9d69c3325f5b620ed029fbabac775417df8f0d"
+        }, 
+        "Configuration": {
+            "TracingConfig": {
+                "Mode": "PassThrough"
+            }, 
+            "Version": "$LATEST", 
+            "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+            "FunctionName": "envcheck", 
+            "VpcConfig": {
+                "SubnetIds": [], 
+                "SecurityGroupIds": []
+            }, 
+            "MemorySize": 128, 
+            "CodeSize": 260, 
+            "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+            "Handler": "lambda_function.lambda_handler", 
+            "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+            "Timeout": 3, 
+            "LastModified": "2016-12-24T13:51:31.006+0000", 
+            "Runtime": "python2.7", 
+            "Description": ""
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "4638bb22-1265-11e8-8273-3394bc9ee644", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:31:21 GMT", 
+                "x-amzn-requestid": "4638bb22-1265-11e8-8273-3394bc9ee644", 
+                "content-length": "1881", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.GetFunction_2.json b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.GetFunction_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.GetFunction_2.json
@@ -0,0 +1,42 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Code": {
+            "RepositoryType": "S3", 
+            "Location": "https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/644160558196/envcheck-1e140743-adb2-45e5-aead-4ebcbe741d15?X-Amz-Security-Token=FQoDYXdzEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDJBkJcjoKckt0KYfJyK3Axip8%2FAxT84z0X9fDzLiQ3p5h8kYz6wjIaC6kP3r7FODovw%2BPHa%2BPUuH98svGadc3PZh%2FxyYqz%2FgSAaykVfLKiv84m668ijCUA5BBI2iudlZU2uoncmyBFHc75nBdNVUSCM%2FtKLgdw8BKgDJqEU%2FOheyI0hd8t2d%2B89UzsLsuI3V5C%2BK%2BzisZNi82kICHLyr%2BkVzARhJKopZy8puP2Wwn4JgvKz1d1gsYLBZQ5WjQbmDs8yKpW7BaRRPXmo%2FrgmSJnFKQ9IUsVEgORODUj4Vbl%2FCtSnyNnEiX2biydPsOIkwbUdUxkDxz2z7hSZhmuz3562HlJOuXFR%2BwYGD8MLKZTJ2jYXpHXZkBp9QUaMXr%2BQa8SqkTGS38sYc3UgoQlZmCqI5yJLF8G6eHAtFITGumrWj3PGSrhKte9f7EIHNCk8OdjPRWVsXdZngTmlu1BHzPmvHoy%2B%2F01fi7f3%2FBJs72FnHFagllx3MKzEYlrqhpssGhWowFxhANP%2F19haqn%2FT3L6HPIA55iawlpVnXzkZe5vTjW6Q3j6AbsnN6ivOJg3ZaLgoYDRxNck0NBvxOdVzHlXatKptXWIQo8LqW1AU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180215T153121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAI45JJEKBZKXUYGGQ%2F20180215%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=031eadaf70431e9a2e6ff6f027b92044ffc6c2873c3bb022fe907bc778257d1b"
+        }, 
+        "Configuration": {
+            "TracingConfig": {
+                "Mode": "PassThrough"
+            }, 
+            "Version": "$LATEST", 
+            "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+            "FunctionName": "envcheck", 
+            "VpcConfig": {
+                "SubnetIds": [], 
+                "SecurityGroupIds": []
+            }, 
+            "MemorySize": 128, 
+            "CodeSize": 260, 
+            "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+            "Handler": "lambda_function.lambda_handler", 
+            "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+            "Timeout": 3, 
+            "LastModified": "2016-12-24T13:51:31.006+0000", 
+            "Runtime": "python2.7", 
+            "Description": ""
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "467cc9c8-1265-11e8-aea6-01a92e75da57", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:31:21 GMT", 
+                "x-amzn-requestid": "467cc9c8-1265-11e8-aea6-01a92e75da57", 
+                "content-length": "1859", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.ListFunctions_1.json b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.ListFunctions_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.ListFunctions_1.json
@@ -0,0 +1,40 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Functions": [
+            {
+                "TracingConfig": {
+                    "Mode": "PassThrough"
+                }, 
+                "Version": "$LATEST", 
+                "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+                "FunctionName": "envcheck", 
+                "VpcConfig": {
+                    "SubnetIds": [], 
+                    "SecurityGroupIds": []
+                }, 
+                "MemorySize": 128, 
+                "CodeSize": 260, 
+                "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+                "Handler": "lambda_function.lambda_handler", 
+                "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+                "Timeout": 3, 
+                "LastModified": "2016-12-24T13:51:31.006+0000", 
+                "Runtime": "python2.7", 
+                "Description": ""
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "45f45fc2-1265-11e8-9406-fbe4a90c6843", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:31:20 GMT", 
+                "x-amzn-requestid": "45f45fc2-1265-11e8-9406-fbe4a90c6843", 
+                "content-length": "680", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.ListTags_1.json b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.ListTags_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_delete_concurrency/lambda.ListTags_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "461925de-1265-11e8-85c2-9f1fc66e2d7b", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:31:21 GMT", 
+                "x-amzn-requestid": "461925de-1265-11e8-85c2-9f1fc66e2d7b", 
+                "content-length": "11", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }, 
+        "Tags": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_1.json
@@ -0,0 +1,41 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Concurrency": {
+            "ReservedConcurrentExecutions": 10
+        }, 
+        "Code": {
+            "RepositoryType": "S3", 
+            "Location": "https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/644160558196/custodian-stop-night-asg-1bd1a3bd-7ffd-43a4-b6ca-db8c34b17324?X-Amz-Security-Token=FQoDYXdzEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDOiJuqueSYPOcKAW0SK3A0ROmiq6rdxYV7PMmZiy4PBHmkvmqen9B1eI6jDpXunokosS%2FG68l%2BCMwlL%2FpC62%2FcEqsVRZvbpCVQyYTAksJ9wmft9sWNTAcIwZzoembVFnnjk%2FlDIrFha%2F2yzNcjTldueFU1mUKruAtfkqYcvLWUOfdxWQgIj3Fnml2VCwQDVCWYxUmOUcqcGUtQyB49bHV5a6O%2BfGLCChD%2F48TSt1CnLP81ghkMIQRNlgUjZOGHmAcjq507P8%2B1Iet6zb8hgy%2Fsz7jKniujV7dvRtSytWuPbtzELLgoWBlBgo66Es7f03XZeqYcS83hIcYgkhvNqMGeFK0Ypj%2FVRAHvZdcOQ6xBPxJsJwST4IuUoBXr0Bq72POTM078lqO8zshlUlU7fICX4KHDIMuQoHlGbyzwKMd3FF5Yw26ogsxP5jLViYeYxl73lovV7WK85J6ZQJwjadqIo4b6CTGCwAeTRO9Pg9oCy0P4L3EL51YqlKmQyCfEirGE8dUgqNorVzgLPotsqCbmcbRQq9%2Bg7PgYU0CDOgM7r6tNEv0l4mCb%2Bxhn3HwncIx71IrSlgAVxD5%2Bto3v4ClwEFxiAUBRAojsKW1AU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180215T151831Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAIQLG6BOTOA5LY44Q%2F20180215%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=4ed5e12e36df153a0c5299465f3e772e80af5b890b4f5d2577055c396139a5ab"
+        }, 
+        "Configuration": {
+            "TracingConfig": {
+                "Mode": "PassThrough"
+            }, 
+            "Version": "$LATEST", 
+            "CodeSha256": "5sFjAF4J+TcRvn8y5vjdJfhHhBOz8n+ULMPFfJvIFx4=", 
+            "FunctionName": "custodian-stop-night-asg", 
+            "MemorySize": 512, 
+            "CodeSize": 1033678, 
+            "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:custodian-stop-night-asg", 
+            "Handler": "custodian_policy.run", 
+            "Role": "arn:aws:iam::644160558196:role/custodian-mu", 
+            "Timeout": 60, 
+            "LastModified": "2017-05-26T06:50:03.585+0000", 
+            "Runtime": "python2.7", 
+            "Description": "cloud-custodian lambda policy"
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7b6838af-1263-11e8-8229-a1114f107aea", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:31 GMT", 
+                "x-amzn-requestid": "7b6838af-1263-11e8-8229-a1114f107aea", 
+                "content-length": "1893", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_2.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_2.json
@@ -0,0 +1,42 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Code": {
+            "RepositoryType": "S3", 
+            "Location": "https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/644160558196/envcheck-1e140743-adb2-45e5-aead-4ebcbe741d15?X-Amz-Security-Token=FQoDYXdzEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDGALfvT5z5xAvpxODSK3A%2FI3EDaC9p9mJJHGlEPePaxiKUFi4nq2tYdm8xAo4GAb0OGcS%2BvIl3la0sWgPq0T8BK%2BmL1yQ46zwOFVSs9TwyigtmrEJViTmgrMa1UHYUxPUWi9%2FXmjRdDcXomLne7yCTtGff%2FLbfdf7dae2uYPJ6DcYK3ty55vE9%2ByV5XgRXUGcJGDaILYkwwEScRZ2UL2J9Bvfcz5qNKISK7YqNYNLzzyZOLZKBF7YjjWRECL6lInypdakVCNxJkArRN6%2FCRiG8yAFfEXhaNaiPUkbUYtEPe2ITwl7oU4Tb2sSMNAHXyAtbaRPRGJzVmn12eWOT2%2BzMmm9V8LAdixKG6DmNHI6J4PvIw8lJe1B5TTXmm9pHtpFJb8Zm3k21h1pq1xMU00qiulaOkSZ9ZfvieTF80eALyk6l%2FmJni2ywmw4boCDeOLrneAJZFDb%2Bt%2FNlTRdN3Fp0byMYLgzikCmuSNmJ7XTIDYDvp7H2HMtx1ri3i71J0Euia46Olbl8JXTHQneaZxSlpq8mQbHJ9P1UF7bmLCaUrdbcBnbNN57W67CMSf%2FLRruHqwh54PserLGRf1rrtuViG8fBYaqr4otbmW1AU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180215T151831Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAJPOQL52GW7BEMNTQ%2F20180215%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=163d31565479f58bb09265a0dc45cf6fd2ff1a3a9ae9a2881049799c7da77c0d"
+        }, 
+        "Configuration": {
+            "TracingConfig": {
+                "Mode": "PassThrough"
+            }, 
+            "Version": "$LATEST", 
+            "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+            "FunctionName": "envcheck", 
+            "VpcConfig": {
+                "SubnetIds": [], 
+                "SecurityGroupIds": []
+            }, 
+            "MemorySize": 128, 
+            "CodeSize": 260, 
+            "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+            "Handler": "lambda_function.lambda_handler", 
+            "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+            "Timeout": 3, 
+            "LastModified": "2016-12-24T13:51:31.006+0000", 
+            "Runtime": "python2.7", 
+            "Description": ""
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7b70c3d5-1263-11e8-85c2-9f1fc66e2d7b", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:31 GMT", 
+                "x-amzn-requestid": "7b70c3d5-1263-11e8-85c2-9f1fc66e2d7b", 
+                "content-length": "1843", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_3.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.GetFunction_3.json
@@ -0,0 +1,45 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Concurrency": {
+            "ReservedConcurrentExecutions": 10
+        }, 
+        "Code": {
+            "RepositoryType": "S3", 
+            "Location": "https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/644160558196/envcheck-1e140743-adb2-45e5-aead-4ebcbe741d15?X-Amz-Security-Token=FQoDYXdzEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDGXJS3DIOLZTGixrtyK3A%2BufrZ3f8iqouGGh7S2rjNHaKXbHSfXwjdC%2FoEUhuQOY56gTkyhxWp%2BVem%2FFTjR4sDODNFPuiphyOTiFpatzL52%2Bf7eLVbX8WTnlp731uOV80tr3ylyZNxHrEp8CfmiaUqNCEZJt3BhbNaaQytqviTjFBYjRUM4pqyL0snHZYkHGgw6atLvKsO3QDjwzSFQXo9FYpPOrqKlipYocoXWmA5tsWXFziprU%2Fw%2FM%2B7SK61DfQgm7teQKEavZ1OcQhpbNy9YKUllzDleg5vHW%2FonKE34bKNgIQjh6lJOEyh1hnIhj1XAgnNpvaKrZiz169FXla%2FkVYIGw2RwOv6z%2FDVEpB6LlLiuroQVxibyZdcjjOoi1idDHHdarEcQ0M3MWJz1Z6CxnWREIKBdP5IBNtPMdEg8p6Mhn05HNYZiKTB167lkGruiBJrV9EYpXxWG884%2Fy61GZcZorHz0SuLUuKtWkPSCqBIPT1hbm5wJ1f4DNeL6hXq5ERKXWKnX9zoXEku9EcIs6r71ddxUsCFxwML4PWOQMXsgDw7R141ve3PLALeOHWgn%2FGddwV4k9Z1q4EdjL5%2F%2BpgYqonb8o4LuW1AU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180215T151835Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAIB3KH4XAW6OD32OA%2F20180215%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=bb22f8808807a701a7954da0d21480f5a2885bbb383f40da7abecc78fe8fd5e1"
+        }, 
+        "Configuration": {
+            "TracingConfig": {
+                "Mode": "PassThrough"
+            }, 
+            "Version": "$LATEST", 
+            "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+            "FunctionName": "envcheck", 
+            "VpcConfig": {
+                "SubnetIds": [], 
+                "SecurityGroupIds": []
+            }, 
+            "MemorySize": 128, 
+            "CodeSize": 260, 
+            "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+            "Handler": "lambda_function.lambda_handler", 
+            "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+            "Timeout": 3, 
+            "LastModified": "2016-12-24T13:51:31.006+0000", 
+            "Runtime": "python2.7", 
+            "Description": ""
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7d9af6ff-1263-11e8-9567-3b2c7246d79a", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:35 GMT", 
+                "x-amzn-requestid": "7d9af6ff-1263-11e8-9567-3b2c7246d79a", 
+                "content-length": "1880", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListFunctions_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListFunctions_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListFunctions_1.json
@@ -0,0 +1,57 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Functions": [
+            {
+                "TracingConfig": {
+                    "Mode": "PassThrough"
+                }, 
+                "Version": "$LATEST", 
+                "CodeSha256": "5sFjAF4J+TcRvn8y5vjdJfhHhBOz8n+ULMPFfJvIFx4=", 
+                "FunctionName": "custodian-stop-night-asg", 
+                "MemorySize": 512, 
+                "CodeSize": 1033678, 
+                "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:custodian-stop-night-asg", 
+                "Handler": "custodian_policy.run", 
+                "Role": "arn:aws:iam::644160558196:role/custodian-mu", 
+                "Timeout": 60, 
+                "LastModified": "2017-05-26T06:50:03.585+0000", 
+                "Runtime": "python2.7", 
+                "Description": "cloud-custodian lambda policy"
+            }, 
+            {
+                "TracingConfig": {
+                    "Mode": "PassThrough"
+                }, 
+                "Version": "$LATEST", 
+                "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+                "FunctionName": "envcheck", 
+                "VpcConfig": {
+                    "SubnetIds": [], 
+                    "SecurityGroupIds": []
+                }, 
+                "MemorySize": 128, 
+                "CodeSize": 260, 
+                "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+                "Handler": "lambda_function.lambda_handler", 
+                "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+                "Timeout": 3, 
+                "LastModified": "2016-12-24T13:51:31.006+0000", 
+                "Runtime": "python2.7", 
+                "Description": ""
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7b1f483f-1263-11e8-9772-311cb0163833", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:31 GMT", 
+                "x-amzn-requestid": "7b1f483f-1263-11e8-9772-311cb0163833", 
+                "content-length": "1326", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListTags_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListTags_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListTags_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7b46f4d2-1263-11e8-8581-531a093f3a18", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:31 GMT", 
+                "x-amzn-requestid": "7b46f4d2-1263-11e8-8581-531a093f3a18", 
+                "content-length": "11", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }, 
+        "Tags": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListTags_2.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListTags_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.ListTags_2.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7b48a2db-1263-11e8-903e-e3506f211c0b", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:31 GMT", 
+                "x-amzn-requestid": "7b48a2db-1263-11e8-903e-e3506f211c0b", 
+                "content-length": "11", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }, 
+        "Tags": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.PutFunctionConcurrency_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.PutFunctionConcurrency_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency/lambda.PutFunctionConcurrency_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ReservedConcurrentExecutions": 10, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "7d776956-1263-11e8-a6f5-51f695bb8a84", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:18:35 GMT", 
+                "x-amzn-requestid": "7d776956-1263-11e8-a6f5-51f695bb8a84", 
+                "content-length": "35", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.GetFunction_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.GetFunction_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.GetFunction_1.json
@@ -0,0 +1,45 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Concurrency": {
+            "ReservedConcurrentExecutions": 5
+        }, 
+        "Code": {
+            "RepositoryType": "S3", 
+            "Location": "https://awslambda-us-east-2-tasks.s3.us-east-2.amazonaws.com/snapshots/644160558196/envcheck-1e140743-adb2-45e5-aead-4ebcbe741d15?X-Amz-Security-Token=FQoDYXdzEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDNUunI1l9BrBB6EEVyK3A5EhOlUopfOtU6tKP8J8iYTGAoNKWKpR4hUlV%2Bu1z9lxr7pVsjXDQTpQLXmgQkrTN6FVaU0nqtZHZ2sX8N7UJDjBAhgjcxNdb%2FNUkBTOgt%2FcOvWVZCyMcxjq%2F7FVbnygfFrCauo659JnH%2Bg4XacZz%2FVo0Nbu%2FDZcXVZhR9ix8L2mrcAN%2F1wFSs3W9ega8lxKRpqvkPNgPHzAG%2BGzzSizvAFFwtsIJP7hXKBEVRiqUaz2jbgud7u26IJcMkNRhXihurvr6QpG6k9ZMOhCgAmAR%2Fmg6MTLZPg5bAleYvjf1yhkg1gXKzUqIBy1x3wPPs%2F1VFx%2FDPU%2BKJABODqWKsbgWtte3UhgW67vlMqUT3b5q%2B8%2BkgSpHYPXHI7DfAshiBhViRWg3bjzE4d8mwBDidwXlZxVdDbt6JJ7dBiwV0gEm0Ao6FnLNk6b6vWri9HKx0rzSFLHXx5jzUHF%2Bb3c2qJpMS0au0Armd2WG9yFI%2BTnBv9sg02hbbJdb2%2B3CIHl2EoFwA69UBBoGmAibAB0%2FE5gFzbZD54iD8EEtVDtUBw996TSjh2WATHc2IdvCCnR%2FsDhyYwYc%2F7CRPUo4saW1AU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180215T152744Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAIFQ3ZIELD4L4JMCQ%2F20180215%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Signature=eb743fab4cef3bc9168642fa11fc3084cf098236fe293da7406e51b86c2e5eff"
+        }, 
+        "Configuration": {
+            "TracingConfig": {
+                "Mode": "PassThrough"
+            }, 
+            "Version": "$LATEST", 
+            "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+            "FunctionName": "envcheck", 
+            "VpcConfig": {
+                "SubnetIds": [], 
+                "SecurityGroupIds": []
+            }, 
+            "MemorySize": 128, 
+            "CodeSize": 260, 
+            "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+            "Handler": "lambda_function.lambda_handler", 
+            "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+            "Timeout": 3, 
+            "LastModified": "2016-12-24T13:51:31.006+0000", 
+            "Runtime": "python2.7", 
+            "Description": ""
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "c53982af-1264-11e8-ac3e-e587920d7fb8", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:27:44 GMT", 
+                "x-amzn-requestid": "c53982af-1264-11e8-ac3e-e587920d7fb8", 
+                "content-length": "1891", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.ListFunctions_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.ListFunctions_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.ListFunctions_1.json
@@ -0,0 +1,40 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Functions": [
+            {
+                "TracingConfig": {
+                    "Mode": "PassThrough"
+                }, 
+                "Version": "$LATEST", 
+                "CodeSha256": "8M2BSmxZu6Z8+V8ywJPG+JoRlAhYjSmoauKd8DqMZrY=", 
+                "FunctionName": "envcheck", 
+                "VpcConfig": {
+                    "SubnetIds": [], 
+                    "SecurityGroupIds": []
+                }, 
+                "MemorySize": 128, 
+                "CodeSize": 260, 
+                "FunctionArn": "arn:aws:lambda:us-east-2:644160558196:function:envcheck", 
+                "Handler": "lambda_function.lambda_handler", 
+                "Role": "arn:aws:iam::644160558196:role/lambda_basic_execution", 
+                "Timeout": 3, 
+                "LastModified": "2016-12-24T13:51:31.006+0000", 
+                "Runtime": "python2.7", 
+                "Description": ""
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "c475bd4f-1264-11e8-bf9e-bffcd06bad73", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:27:43 GMT", 
+                "x-amzn-requestid": "c475bd4f-1264-11e8-bf9e-bffcd06bad73", 
+                "content-length": "680", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.ListTags_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.ListTags_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.ListTags_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "c495a11a-1264-11e8-932c-11ff04738b37", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:27:43 GMT", 
+                "x-amzn-requestid": "c495a11a-1264-11e8-932c-11ff04738b37", 
+                "content-length": "11", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }, 
+        "Tags": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.PutFunctionConcurrency_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.PutFunctionConcurrency_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/lambda.PutFunctionConcurrency_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ReservedConcurrentExecutions": 5, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "c4d89d77-1264-11e8-870b-ad24adcbb408", 
+            "HTTPHeaders": {
+                "date": "Thu, 15 Feb 2018 15:27:44 GMT", 
+                "x-amzn-requestid": "c4d89d77-1264-11e8-870b-ad24adcbb408", 
+                "content-length": "34", 
+                "content-type": "application/json", 
+                "connection": "keep-alive"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_aws_lambda_set_concurrency_expr/monitoring.GetMetricStatistics_1.json b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/monitoring.GetMetricStatistics_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_aws_lambda_set_concurrency_expr/monitoring.GetMetricStatistics_1.json
@@ -0,0 +1,33 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Datapoints": [
+            {
+                "Timestamp": {
+                    "hour": 15, 
+                    "__class__": "datetime", 
+                    "month": 2, 
+                    "second": 0, 
+                    "microsecond": 0, 
+                    "year": 2018, 
+                    "day": 1, 
+                    "minute": 27
+                }, 
+                "Sum": 5.0, 
+                "Unit": "Count"
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "c4b69664-1264-11e8-b8b8-b1099c700db2", 
+            "HTTPHeaders": {
+                "x-amzn-requestid": "c4b69664-1264-11e8-b8b8-b1099c700db2", 
+                "date": "Thu, 15 Feb 2018 15:27:43 GMT", 
+                "content-length": "484", 
+                "content-type": "text/xml"
+            }
+        }, 
+        "Label": "Invocations"
+    }
+}
\ No newline at end of file
diff --git a/tests/test_lambda.py b/tests/test_lambda.py
--- a/tests/test_lambda.py
+++ b/tests/test_lambda.py
@@ -18,7 +18,7 @@
 from botocore.exceptions import ClientError
 from .common import BaseTest, functional
 from c7n.executor import MainThreadExecutor
-from c7n.resources.awslambda import AWSLambda
+from c7n.resources.awslambda import AWSLambda, ReservedConcurrency
 from c7n.mu import PythonPackageArchive
 
 
@@ -127,6 +127,72 @@ def test_delete(self):
         client = factory().client('lambda')
         self.assertEqual(client.list_functions()['Functions'], [])
 
+    def test_delete_reserved_concurrency(self):
+        self.patch(ReservedConcurrency, 'executor_factory', MainThreadExecutor)
+        factory = self.replay_flight_data('test_aws_lambda_delete_concurrency')
+        p = self.load_policy({
+            'name': 'lambda-concurrency',
+            'resource': 'lambda',
+            'filters': [
+                {'FunctionName': 'envcheck'},
+                {'type': 'reserved-concurrency', 'value': 'present'}],
+            'actions': [
+                {'type': 'set-concurrency',
+                 'value': None}],
+            }, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0]['FunctionName'], 'envcheck')
+
+        client = factory().client('lambda')
+        info = client.get_function(FunctionName=resources[0]['FunctionName'])
+        self.assertFalse('Concurrency' in info)
+
+    def test_set_expr_concurrency(self):
+        self.patch(ReservedConcurrency, 'executor_factory', MainThreadExecutor)
+        factory = self.replay_flight_data('test_aws_lambda_set_concurrency_expr')
+        p = self.load_policy({
+            'name': 'lambda-concurrency',
+            'resource': 'lambda',
+            'filters': [
+                {'type': 'metrics',
+                 'name': 'Invocations',
+                 'statistics': 'Sum',
+                 'op': 'greater-than',
+                 'value': 0}],
+            'actions': [
+                {'type': 'set-concurrency',
+                 'expr': True,
+                 'value':  "\"c7n.metrics\".\"AWS/Lambda.Invocations.Sum\"[0].Sum"}]
+            }, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0]['FunctionName'], 'envcheck')
+
+        client = factory().client('lambda')
+        info = client.get_function(FunctionName=resources[0]['FunctionName'])
+        self.assertEqual(info['Concurrency']['ReservedConcurrentExecutions'], 5)
+
+    def test_set_filter_concurrency(self):
+        self.patch(ReservedConcurrency, 'executor_factory', MainThreadExecutor)
+        factory = self.replay_flight_data('test_aws_lambda_set_concurrency')
+        p = self.load_policy({
+            'name': 'lambda-concurrency',
+            'resource': 'lambda',
+            'filters': [
+                {'type': 'reserved-concurrency',
+                 'value': 'absent'}],
+            'actions': [
+                {'type': 'set-concurrency',
+                 'value': 10}]}, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0]['FunctionName'], 'envcheck')
+
+        client = factory().client('lambda')
+        info = client.get_function(FunctionName=resources[0]['FunctionName'])
+        self.assertEqual(info['Concurrency']['ReservedConcurrentExecutions'], 10)
+                 
     def test_event_source(self):
         factory = self.replay_flight_data('test_aws_lambda_source')
         p = self.load_policy({