AWS SAM本地环境变量

63

我在这里遵循README:https://github.com/awslabs/aws-sam-local

我有一个用Python 3.6编写的Lambda函数,与这里的helloworld示例类似:https://github.com/awslabs/aws-sam-local/tree/develop/samples/hello-world/python

template.yml如下所示:

AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: MyFunction1 API
Resources:
  MyFunction1:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: MyFunction1
      Handler: lambda_module.lambda_handler
      Runtime: python3.6
      CodeUri: lambda.zip
      MemorySize: 128
      Timeout: 10
      Policies:
        -AWSLamdbaBasicExecutionRole
      Events:
        BingLambdaEndpoint:
          Type: Api
          Properties:
            Path: MyFunction1/search
            Method: get

我在lambda函数中有环境变量,但是无法在启动时连接它们。文档说我可以创建一个environments.json文件,并在调用命令上附加以下内容:使用invoke的 --env-vars参数

我的环境文件看起来像这个例子,但是我得到了一个错误:Unable to find environment variable: api_key

environment.json如下:

{
  "MyFunction1": {
    "api_key": "123456789",
    "BUCKET_NAME": "testBucket"
  }
}

我运行的命令如下:

sam local invoke MyFunction1 --env-vars environment_variables.json -e event.json

有人能提供额外的见解吗?

6个回答

86

如果您想以这种方式在SAM Local中使用任何环境变量,则这些变量需要存在于SAM模板中。根据GitHub问题反馈

… SAM Local仅解析在SAM模板中定义的环境变量。

在模板中,您可以不提供值、提供空字符串或选择明智的默认值。

包含环境变量的模板部分:

Resources:
  MyFunction1:
    Type: 'AWS::Serverless::Function'
    Properties:
      .....
      Environment:
        Variables:
          api_key:
          BUCKET_NAME:

您可以将环境变量文件视为覆盖模板“已知”的环境变量的机制。它不起作用作为向本地运行时注入任意环境变量的机制。


1
我理解这一点,但是在运行 Lambda 时,它似乎没有环境变量的知识。然而,我可以在模板文件中配置它们并且可以正常工作。我想使用单独的配置文件来存储我的变量,就像 Sam 本地文档中所述。 - gotjava2012
2
当我在查找使用环境变量的参考资料时,我从谷歌上找到了这篇文章。根据有关sam本地环境变量的文档:“Environment”键定义了变量和默认值。可以使用“--env-vars”cli参数来定义一个json文件以覆盖这些值。我将在答案中更新这些信息。 - Frank Robert Anderson
1
你也可以在全局级别应用它:Globals: Function: Environment: Variables: api_key: - James Burke

46

模板文件

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
  
Globals:

  Function:
    Timeout: 3

Parameters:

  SomeVar:
    Type: String
    Description: My SomeVar
    Default: default value

Resources:

  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Environment:
        Variables:
          SOME_VAR: !Ref SomeVar
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

Outputs:

  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

参考https://github.com/awslabs/aws-sam-cli/issues/1163#issuecomment-557874976

接着在代码中实现

console.log(process.env.SOME_VAR);

执行sam local start-api命令时,它会打印default value

如果执行sam local start-api --parameter-overrides SomeVar=other_value命令,则它将打印other_value

然后,如果创建名为env.json的文件并添加此内容

{ "PreviewsFunction": { "SOME_VAR": "123" } }

当你运行sam local start-api --env-vars env.json时,它会打印123

p.s. start-api/start-lambda/invoke 的使用方式相同,但似乎sam deploy只能使用 --parameter-overrides SomeVar=other_value 而不支持 --env-vars


3
谢谢!这太棒了……终于有些理智的处理环境变量和SAM了。好处是当你运行 sam deploy --guided 时,会提示你添加任何你指定的环境变量,就像这样。正是我所需要的。 - Darragh Enright
它无法使用env.json文件,仍然会打印出默认值和env.json。 - user13266580
1
仍然打印默认值! - M-sAnNan
还要在控制台中添加"NoEcho: true"以防止打印机密信息。 - Amaimersion

12

请确保在template.yml中声明了变量。配置文件可以覆盖变量,但不会在原始模板中不存在变量时创建变量。


谢谢!我一直在尝试使用sam build --use container --container-env-var-file env.json拉取环境变量,但是我没有在template.yaml文件中预先声明这些变量,所以它一直失败。 - James Lin

5

我也遇到了相同的问题。当我运行以下代码时

sam local start-api --env-vars  env.json 

env.json文件中的值未被读取。 对我有帮助的解决方法是在env.json中使用以下格式

"Parameters": {
    "PARAM_NAME": "VALUE"
}

另一种格式对我没有起作用:

{ "function": { "PARAM_NAME": "VALUE" } }

2
你可以使用选项-n, --env-vars PATH。这是一个JSON文件,你需要有一个与模板中资源名称相对应的对象。

template.yaml:

...
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      ...
      Environment:
        Variables:
          SOME_VAR: !Ref SomeVar
...

假设您的变量文件名为.env.local.json。内容应该类似于以下内容:
{
  "HelloWorldFunction": {
     "SOME_VAR": "NEW_VALUE"
  }
}

然后你需要运行以下命令:
``` sam local start-api --env-vars .env.local.json ```

文件.env.local.json实际上存放在哪里? - undefined

1

确保您的模板参数具有NoEcho等于true,就像这个示例中的一样:

Parameters:
  # Build variables
  Stage:
    Type: String
  # Environment variables
  MssqlServer:
    Type: String
    NoEcho: true
  MssqlDatabase:
    Type: String
    NoEcho: true
  MssqlUser:
    Type: String
    NoEcho: true
  MssqlPassword:
    Type: String
    NoEcho: true

然后,您可以通过以下命令简单地传递环境变量:
sam deploy --parameter-overrides "MssqlServer='$MSSQL_SERVER' MssqlDatabase='$MSSQL_DATABASE' MssqlUser='$MSSQL_USER' MssqlPassword='$MSSQL_PASSWORD' Stage=dev" --config-env dev

我不确定这是否适用于此处,但AWS建议不要将机密信息放入“可动态引用的值”中。请参见此处:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html“要确定哪些资源属性构成资源类型的主标识符,请参阅该资源的资源引用文档。在返回值部分中,Ref函数返回值表示组成资源类型主标识符的资源属性。”除非这就是NoEcho的作用? - Steven Staley
与其直接嵌入敏感信息到您的CloudFormation模板中,我们建议您在堆栈模板中使用动态参数来引用存储和管理在CloudFormation之外的敏感信息,例如在AWS Systems Manager参数存储或AWS Secrets Manager中。有关更多信息,请参阅不要在您的模板中嵌入凭据最佳实践。 更多信息请参见:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html - Steven Staley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接