簡體   English   中英

AWS lambda:在本地調用可訪問 s3 的 python lambda 函數

[英]AWS lambda: Invoking locally a python lambda function with access to s3

在部署之前,我剛剛開始學習使用亞馬遜的無服務器框架在我的 linux PC 上本地開發 python lambda 函數。 該過程包括通過sam init初始化文件結構,然后通過sam build應用程序,最后使用 ike sam local invoke調用該函數。

在調用這樣的函數時,我無法訪問我的 s3 存儲桶,如下所示。 如果有人能指出為什么錯誤的例子不起作用,我將不勝感激。 為冗長的文字道歉。

工作示例

假設我的應用程序是這樣的:

# app.py

import json

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
        }),
    }

果然,如果我運行sam build; sudo sam local invoke HelloWorldFunction --no-event sam build; sudo sam local invoke HelloWorldFunction --no-event ,這將成功運行並返回:

>sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

>sudo sam local invoke HelloWorldFunction --no-event
Invoking app.lambda_handler (python3.8)

Fetching lambci/lambda:python3.8 Docker container image......
Mounting /home/username/Tmp/myapp/myapp/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: af24271f-50f0-15b7-2e09-f11a513c04d4 Version: $LATEST
END RequestId: af24271f-50f0-15b7-2e09-f11a513c04d4
REPORT RequestId: af24271f-50f0-15b7-2e09-f11a513c04d4  Init Duration: 265.92 ms    Duration: 1.94 ms   Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 25 MB  

{"statusCode":200,"body":"{\"message\": \"hello world\"}"}

導致錯誤的示例變體

但是,當涉及如下 boto3 時,調用不起作用。

  1 # app.py                                                                       
  2                                                                                
  3 import json                                                                    
  4 import boto3                                                                                        
  5                                                                                
  6 s3 = boto3.resource('s3')                                                      
  7 buckets = [bucket.name for bucket in s3.buckets.all()]                         
  8 print('a bucket is', buckets[0])                                               
  9                                                                                
 10 def lambda_handler(event, context):                                            
 11     return {                                                                   
 12         "statusCode": 200,                                                     
 13         "body": json.dumps({                                                   
 14             "message": "hello world",                                          
 15         }),                                                                    
 16     }            

sam local build運行良好,但是sudo sam local invoke HelloWorldFunction --no-event給出了這個錯誤:

>sudo sam local invoke HelloWorldFunction --no-event
Invoking app.lambda_handler (python3.8)

Fetching lambci/lambda:python3.8 Docker container image......
Mounting /home/username/Tmp/myapp/myapp/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
[ERROR] ClientError: An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.
Traceback (most recent call last):
  File "/var/lang/lib/python3.8/imp.py", line 234, in load_module
    return load_source(name, filename, file)
  File "/var/lang/lib/python3.8/imp.py", line 171, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 702, in _load
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/var/task/app.py", line 7, in <module>
    buckets = [bucket.name for bucket in s3.buckets.all()]
  File "/var/task/app.py", line 7, in <listcomp>
    buckets = [bucket.name for bucket in s3.buckets.all()]
  File "/var/runtime/boto3/resources/collection.py", line 83, in __iter__
    for page in self.pages():
  File "/var/runtime/boto3/resources/collection.py", line 161, in pages
    pages = [getattr(client, self._py_operation_name)(**params)]
  File "/var/runtime/botocore/client.py", line 316, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 626, in _make_api_call
    raise error_class(parsed_response, operation_name)

{"errorType":"ClientError","errorMessage":"An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.","stackTrace":["  File \"/var/lang/lib/python3.8/imp.py\", line 234, in load_module\n    return load_source(name, filename, file)\n","  File \"/var/lang/lib/python3.8/imp.py\", line 171, in load_source\n    module = _load(spec)\n","  File \"\u003cfrozen importlib._bootstrap\u003e\", line 702, in _load\n","  File \"\u003cfrozen importlib._bootstrap\u003e\", line 671, in _load_unlocked\n","  File \"\u003cfrozen importlib._bootstrap_external\u003e\", line 783, in exec_module\n","  File \"\u003cfrozen importlib._bootstrap\u003e\", line 219, in _call_with_frames_removed\n","  File \"/var/task/app.py\", line 7, in \u003cmodule\u003e\n    buckets = [bucket.name for bucket in s3.buckets.all()]\n","  File \"/var/task/app.py\", line 7, in \u003clistcomp\u003e\n    buckets = [bucket.name for bucket in s3.buckets.all()]\n","  File \"/var/runtime/boto3/resources/collection.py\", line 83, in __iter__\n    for page in self.pages():\n","  File \"/var/runtime/boto3/resources/collection.py\", line 161, in pages\n    pages = [getattr(client, self._py_operation_name)(**params)]\n","  File \"/var/runtime/botocore/client.py\", line 316, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n","  File \"/var/runtime/botocore/client.py\", line 626, in _make_api_call\n    raise error_class(parsed_response, operation_name)\n"]}
START RequestId: e8a504ed-3f84-13d2-5f8a-846c6aa34da8 Version: $LATEST
END RequestId: e8a504ed-3f84-13d2-5f8a-846c6aa34da8
REPORT RequestId: e8a504ed-3f84-13d2-5f8a-846c6aa34da8  Init Duration: 1035.42 ms   Duration: 5.52 ms   Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 41 MB  

奇怪的是,如果我用 python 運行它,一切都很好:

>python app.py 
a bucket is bucket-fjlkajsdr

> aws s3 ls
2020-04-29 13:31:49 bucket-fjlkajsdr
2020-04-29 13:59:37 bucket2-lkjlasdfasdf
2020-04-28 16:07:37 bucket3-lkadsfasd

所以我確實安裝了正確的憑據,並且可以從我的 PC 訪問我的 s3 存儲桶。

我的問題是:有人可以解釋為什么在本地調用該函數不起作用嗎?

模板.yaml

您還可以在這里找到放置在 app 文件夾中的 template.yaml:

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

  Sample SAM Template for myapp

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 30

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      Policies: AmazonS3FullAccess
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

我認為這是因為您使用 sudo 來調用sam local ,因此有效用戶是 root,因此 AWS SDK 正在獲取 root 的 ~/.aws/credentials 文件而不是您的 ~/.aws/credentials 文件。

PS 我不希望您必須sudo才能運行 SAM。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM