boto / boto3

AWS SDK for Python
https://aws.amazon.com/sdk-for-python/
Apache License 2.0
8.99k stars 1.86k forks source link

Unable to execute Pricing.Client.list_price_lists in AWS Lambda #4255

Closed yf7qq closed 3 weeks ago

yf7qq commented 3 weeks ago

Describe the issue

Hi, Is this issue due to "This feature is in preview release and is subject to change" according to this documentation? I am able to execute this command in Jupyter Notebook, but unable to do so in Lambda. Thank you for answering my question!

Links

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/pricing/client/list_price_lists.html#Pricing.Client.list_price_lists

tim-finnigan commented 3 weeks ago

Thanks for reaching out. I tested this both locally and in Lambda and it ran successfully:

from datetime import datetime
import boto3
print(boto3.__version__)
client = boto3.client('pricing', region_name='us-east-1')

response = client.list_price_lists(
    ServiceCode='AmazonEC2',
    EffectiveDate=datetime(2024, 1, 1),
    RegionCode='us-east-1',
    CurrencyCode='USD'
)

print(response)

Can you provide a code snippet for reproducing the issue? What error do you get when running the command in Lambda? Does your Lambda execution role have pricing:ListPriceList permissions? Also please note the available regions/endpoints for the AWS Price List Service here: https://docs.aws.amazon.com/general/latest/gr/billing.html

yf7qq commented 3 weeks ago

Hi Tim,

Thank you for the quick response. Below is my code:

def lambda_handler(event, context):
    pricing_client = boto3.client('pricing')
    # first call describe_services api to list out the first x number of services 
    service_response = pricing_client.describe_services(FormatVersion='aws_v1')
    #extract the content within the services JSON string
    all_services = service_response['Services']

    # pagination looks for the services in the next pages 
    while "NextToken" in service_response:
        service_response = pricing_client.describe_services(FormatVersion='aws_v1', NextToken=service_response['NextToken'])
        all_services.extend(service_response["Services"])

    # Process the services
    service_code_list = []

    # Iterate over the services and append the service code into the list above
    for service in all_services:
        service_code_list.append(service['ServiceCode'])

    # Create for loop to retrieve each service in the list extracted from above
    all_list_price = []
    for service in service_code_list:

        paginator = pricing_client.get_paginator('list_price_lists')

        response_iterator = paginator.paginate(
        ServiceCode=service,
        EffectiveDate=datetime(2023, 1, 1),
        #RegionCode='string',
        CurrencyCode='USD',
        PaginationConfig={
            #'MaxItems': 123,
            #'PageSize': 100,
            #'StartingToken': 'string'
        })

        for i in response_iterator:
            all_list_price.extend(i["PriceLists"])

    PriceListArnList = []
    for item in all_list_price: 
        PriceListArn = item.get('PriceListArn')
        PriceListArnList.append(PriceListArn)

This is the error message:

Response
{
  "errorMessage": "'list_price_lists'",
  "errorType": "KeyError",
  "requestId": "be794ebb-edc5-404f-8ddd-729ff0c02832",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 33, in lambda_handler\n    paginator = pricing_client.get_paginator('list_price_lists')\n",
    "  File \"/opt/python/botocore/client.py\", line 734, in get_paginator\n    if not self.can_paginate(operation_name):\n",
    "  File \"/opt/python/botocore/client.py\", line 796, in can_paginate\n    actual_operation_name = self._PY_TO_OP_NAME[operation_name]\n"
  ]
}

I also called the describe_services API and that worked. Also made sure that Lambda execution role has the ListPriceLists permission.

Thanks!

tim-finnigan commented 3 weeks ago

Thanks for following up — can you verify your Boto3/Botocore versions in your Lambda function? For example:

import boto3
import botocore
print(boto3.__version__)
print(botocore.__version__)

For the ListPriceLists Pricing API it looks like you need at least Boto3 1.26.82 and Botocore 1.29.82. Are you using Boto3/Botocore versions in your Lambda that are older than those? Your code above works for me in Lambda, and I'm using the default Python 3.11 runtime which currently has version 1.34.145. This troubleshooting guide has more info on Lambda layers: https://repost.aws/knowledge-center/lambda-python-runtime-errors.

yf7qq commented 3 weeks ago

Thanks Tim! It's resolved now. My Python version was outdated in Lambda, which was causing the issue.

tim-finnigan commented 3 weeks ago

Thanks Tim! It's resolved now. My Python version was outdated in Lambda, which was causing the issue.

Glad it's working now! I'll go ahead and close the issue.

github-actions[bot] commented 3 weeks ago

This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.