Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
本地调试python 3.7 AWS lambda_Python_Amazon Web Services_Aws Lambda - Fatal编程技术网

本地调试python 3.7 AWS lambda

本地调试python 3.7 AWS lambda,python,amazon-web-services,aws-lambda,Python,Amazon Web Services,Aws Lambda,我使用运行时python 3.7为AWS Lambda创建了一个zip文件,其中包含main.py和entrypointhandler函数 zip文件使用3.7.3 python打包在EC2上的AmazonLinux映像中 我在AWS lambda上运行时遇到一些错误,因此决定是否有办法在本地运行该函数 我的main.py如下: import datetime import logging import os import re import subprocess import boto3 i

我使用运行时python 3.7为AWS Lambda创建了一个zip文件,其中包含
main.py
和entrypoint
handler
函数

zip文件使用3.7.3 python打包在EC2上的AmazonLinux映像中

我在AWS lambda上运行时遇到一些错误,因此决定是否有办法在本地运行该函数

我的main.py如下:

import datetime
import logging
import os
import re
import subprocess

import boto3
import certbot.main
import raven

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def list_files(folder_path):
  onlyfiles = [f for f in listdir(folder_path) if path.isfile(path.join(folder_path, f))]
  logger.info('## path')
  logger.info(onlyfiles)


def read_and_delete_file(path):
  with open(path, 'r') as file:
    contents = file.read()
  os.remove(path)
  return contents


def provision_cert(email, domains):
  certbot.main.main([
    'certonly',                             # Obtain a cert but don't install it
    '-n',                                   # Run in non-interactive mode
    '--agree-tos',                          # Agree to the terms of service,
    '--email', email,                       # Email
    '--dns-route53',                        # Use dns challenge with route53
    '-d', domains,                          # Domains to provision certs for
    # Override directory paths so script doesn't have to be run as root
    '--config-dir', '/tmp/config-dir/',
    '--work-dir', '/tmp/work-dir/',
    '--logs-dir', '/tmp/logs-dir/',
  ])

  first_domain = domains.split(',')[0]
  first_domain_cert_folder = re.sub('\*\.', '', first_domain)
  path = '/tmp/config-dir/live/' + first_domain_cert_folder + '/'
  logger.info('## path')
  logger.info(path)

  list_files(path)

  return {
    'certificate': read_and_delete_file(path + 'cert.pem'),
    'private_key': read_and_delete_file(path + 'privkey.pem'),
    'certificate_chain': read_and_delete_file(path + 'fullchain.pem')
  }

def should_provision(domains):
  existing_cert = find_existing_cert(domains)
  if existing_cert:
    now = datetime.datetime.now(datetime.timezone.utc)
    not_after = existing_cert['Certificate']['NotAfter']
    return (not_after - now).days <= 30
  else:
    return True

def find_existing_cert(domains):
  domains = frozenset(domains.split(','))

  client = boto3.client('acm')
  paginator = client.get_paginator('list_certificates')
  iterator = paginator.paginate(PaginationConfig={'MaxItems':1000})

  for page in iterator:
    for cert in page['CertificateSummaryList']:
      cert = client.describe_certificate(CertificateArn=cert['CertificateArn'])
      sans = frozenset(cert['Certificate']['SubjectAlternativeNames'])
      if sans.issubset(domains):
        return cert

  return None

def notify_via_sns(topic_arn, domains, certificate):
  process = subprocess.Popen(['openssl', 'x509', '-noout', '-text'],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
  stdout, stderr = process.communicate(certificate)

  client = boto3.client('sns')
  client.publish(TopicArn=topic_arn,
    Subject='Issued new LetsEncrypt certificate',
    Message='Issued new certificates for domains: ' + domains + '\n\n' + stdout,
  )

def upload_cert_to_acm(cert, domains):
  existing_cert = find_existing_cert(domains)
  certificate_arn = existing_cert['Certificate']['CertificateArn'] if existing_cert else None

  client = boto3.client('acm')
  acm_response = client.import_certificate(
    CertificateArn=certificate_arn,
    Certificate=cert['certificate'],
    PrivateKey=cert['private_key'],
    CertificateChain=cert['certificate_chain']
  )

  return None if certificate_arn else acm_response['CertificateArn']

def handler(event, context):
  try:
    domains = os.environ['LETSENCRYPT_DOMAINS']
    if should_provision(domains):
      cert = provision_cert(os.environ['LETSENCRYPT_EMAIL'], domains)
      upload_cert_to_acm(cert, domains)
      notify_via_sns(os.environ['NOTIFICATION_SNS_ARN'], domains, cert['certificate'])
  except:
    client = raven.Client(os.environ['SENTRY_DSN'], transport=raven.transport.http.HTTPTransport)
    client.captureException()
    raise
导入日期时间
导入日志记录
导入操作系统
进口稀土
导入子流程
进口boto3
导入certbot.main
进口乌鸦
logger=logging.getLogger()
logger.setLevel(logging.INFO)
def列表文件(文件夹路径):
onlyfiles=[f表示listdir(文件夹路径)中的f,如果path.isfile(path.join(文件夹路径,f))]
logger.info(“##路径”)
logger.info(仅适用于文件)
def read_和_delete_文件(路径):
打开(路径“r”)作为文件:
contents=file.read()
删除操作系统(路径)
返回内容
def供应证书(电子邮件、域):
certbot.main.main([
“certonly”,获取证书但不安装
'-n',#以非交互模式运行
“--同意”,同意服务条款,
“--电子邮件”,电子邮件,#电子邮件
“--dns-route53”,对route53使用dns质询
'-d',域,#要为其提供证书的域
#重写目录路径,这样脚本就不必以root用户身份运行
“--config dir”,”/tmp/config dir/“,
“--工作目录”,“/tmp/work dir/”,
'--logs dir','/tmp/logs dir/',
])
first_domain=domains.split(',')[0]
first\u domain\u cert\u folder=re.sub('\*\.','',first\u domain)
path='/tmp/config dir/live/'+first_domain_cert_folder+'/'
logger.info(“##路径”)
logger.info(路径)
列出\u文件(路径)
返回{
“证书”:读取和删除文件(路径+“cert.pem”),
“私钥”:读取和删除文件(路径+“privkey.pem”),
“证书链”:读取和删除文件(路径+'fullchain.pem')
}
def应提供(域):
现有证书=查找现有证书(域)
如果现有证书:
现在=datetime.datetime.now(datetime.timezone.utc)
not_after=现有_证书['Certificate']['NotAfter']

return(not_after-now).days正如您所发现的,您可以使用AWS SAM(带Docker)在本地进行调试

以下是关于入门的分步指南:

先决条件

pipenv shell
pipenv install package-names
  • 安装Docker:
  • 安装AWS CLI:
  • 安装AWS SAM CLI:
  • 安装pipenv:
  • 创建示例项目

    有助于让您了解结构并在本地进行调试,然后您可以用示例代码替换自己的代码

    saminit——运行时python3.7

    添加依赖项

    pipenv shell
    pipenv install package-names
    
    本地运行和调试

    pipenv lock -r > requirements.txt
    sam build --manifest requirements.txt
    sam local invoke HelloWorldFunction --event event.json
    
    部署到AWS Lambda

    如果需要,制作一个新的存储桶,用于存储功能代码:

    aws s3 mb s3://bucket name

    创建并运行.sh脚本:

    #!/bin/bash
    
    pipenv lock -r > requirements.txt && sam build --manifest requirements.txt
    
    sam package \
        --output-template-file packaged.yaml \
        --s3-bucket bucket-name
    
    sam deploy \
        --template-file packaged.yaml \
        --stack-name name-of-lambda-stack \
        --capabilities CAPABILITY_IAM \
        --region us-east-1
    
    替换:

    • bucket name
      带有存储功能代码的S3 bucket的名称
    • lambda堆栈的名称
      以及要部署到的AWS lambda堆栈的名称
    • us-east-1
      ,如果需要,另配一个

    您的函数现在已部署到AWS Lambda。

    感谢您的详细编写!明天早上我要试一试:)我需要创建虚拟环境吗?对于在docker主机上运行的python项目,我通常使用
    pipenv
    作为虚拟环境(尽管您可能使用
    virtualenv
    )。