Need help searching/deleting aws lambda function versions that are older then 5 and not live. Need some assistance with paginator to find all of them

Question:

I am trying to update my python script that will look through my aws accounts and delete lambda function versions. The idea is to keep only the latest 5 and live. At the moment my script is able to do this successfully, but it will not find all the lambdas.
I believe I need to add a paginator to my code to get the remaining lambdas, but need some help doing that. Some of my accounts have over 300 lambdas.
Below is my code:

import boto3

def clean_old_lambda_versions(client):
    functions = client.list_functions()['Functions']
    for function in functions:
        arn = function['FunctionArn']
        print(arn)
        all_versions = []

        versions = client.list_versions_by_function(
            FunctionName=arn)
        # Page through all the versions
        while True:
            page_versions = [int(v['Version']) for v in versions['Versions'] if not v['Version'] == '$LATEST']
            all_versions.extend(page_versions)
            try:
                marker = versions['NextMarker']
            except:
                break
            versions = client.list_versions_by_function(
                FunctionName=arn, Marker=marker)

        # Sort and keep the last 5
        all_versions.sort()
        print('Which versions must go?')
        print(all_versions[0:-5])
        print('Which versions will live')
        print(all_versions[-5::])
        for chopBlock in all_versions[0:-5]:
            functionArn = '{}:{}'.format(arn, chopBlock)
            client.delete_function(FunctionName=functionArn)

if __name__ == '__main__':
    client = boto3.client('lambda', region_name='us-east-1')
    clean_old_lambda_versions(client)
Asked By: user3303441

||

Answers:

The documentation for both list_functions() and list_versions_by_function() says "Lambda returns up to 50 functions/versions per call".

To paginate the call:

  • If the call returns a non-null NextMarker
  • Call the API again…
  • Passing the NextMarker value in the Marker field

Alternatively, use the paginator provided on ListFunctions — Boto3 documentation:

paginator = client.get_paginator('list_functions')

See also the example from Paginators — Boto3 documentation:

import boto3

# Create a client
client = boto3.client('s3', region_name='us-west-2')

# Create a reusable Paginator
paginator = client.get_paginator('list_objects')

# Create a PageIterator from the Paginator
page_iterator = paginator.paginate(Bucket='my-bucket')

for page in page_iterator:
    print(page['Contents'])

This means that you could use something like:

import boto3

client = boto3.client('lambda')
paginator = client.get_paginator('list_functions')
page_iterator = paginator.paginate()

for page in page_iterator:
    print(page['Functions'])
Answered By: John Rotenstein