如何在Lambda函数中使用CloudFormation资源?

时间:2016-05-09 05:14:11

标签: aws-lambda amazon-cloudformation amazon-elasticache serverless-framework

我已将Redis ElastiCache部分添加到我的s-resource-cf.json(CloudFormation模板),并选择其主机名作为输出。

if (someObject.doSomething()) //So if your function returns true then the below statement will be executed
{ 
   // print a statment
}
else //This will check for the false condition of your function
{
   // print a different statement           
}

我可以在运行"Resources": { ...snip... "Redis": { "Type": "AWS::ElastiCache::CacheCluster", "Properties": { "AutoMinorVersionUpgrade": "true", "AZMode": "single-az", "CacheNodeType": "cache.t2.micro", "Engine": "redis", "EngineVersion": "2.8.24", "NumCacheNodes": "1", "PreferredAvailabilityZone": "eu-west-1a", "PreferredMaintenanceWindow": "tue:00:30-tue:01:30", "CacheSubnetGroupName": { "Ref": "cachesubnetdefault" }, "VpcSecurityGroupIds": [ { "Fn::GetAtt": [ "sgdefault", "GroupId" ] } ] } } }, "Outputs": { "IamRoleArnLambda": { "Description": "ARN of the lambda IAM role", "Value": { "Fn::GetAtt": [ "IamRoleLambda", "Arn" ] } }, "RedisEndpointAddress": { "Description": "Redis server host", "Value": { "Fn::GetAtt": [ "Redis", "Address" ] } } } 时让CloudFormation输出Redis服务器主机,但是如何从Lambda函数中访问该输出呢?

此入门项目模板中没有任何内容引用示例项目附带的sls resources deploy。根据{{​​3}},模板仅可用于项目配置,无法从Lambda函数访问它们:

  

模板&变量仅适用于配置

     

模板和变量仅用于配置项目。此信息在lambda函数中不可用。要设置lambda函数可以使用的变量,请使用环境变量。

那么,如何在创建ElastiCache服务器的主机名后设置环境变量?

2 个答案:

答案 0 :(得分:2)

您可以在函数environment文件的s-function.json部分设置环境变量。此外,如果要阻止这些变量进入版本控制(例如,如果您的代码将发布到公共GitHub存储库),您可以将它们放在_meta/variables目录中的相应文件中,然后引用s-function.json个文件中的内容。只需确保在_meta文件中添加.gitignore行。

例如,在我的最新项目中,我需要连接到Redis Cloud服务器,但不想将连接详细信息提交给版本控制。我将变量放入我的_meta/variables/s-variables-[stage]-[region].json文件中,如下所示:

{
  "redisUrl": "...",
  "redisPort": "...",
  "redisPass": "..."
}

...并引用该函数的s-function.json文件中的连接设置变量:

"environment": {
  "REDIS_URL": "${redisUrl}",
  "REDIS_PORT": "${redisPort}",
  "REDIS_PASS": "${redisPass}"
}

然后我将此redis.js文件放在我的functions/lib目录中:

module.exports = () => {
  const redis = require('redis')
  const jsonify = require('redis-jsonify')
  const redisOptions = {
    host: process.env.REDIS_URL,
    port: process.env.REDIS_PORT,
    password: process.env.REDIS_PASS
  }

  return jsonify(redis.createClient(redisOptions))
}

然后,在任何需要连接到Redis数据库的函数中,我导入了redis.js

redis = require('../lib/redis')()

(有关我的无服务器/ Redis设置的更多详细信息以及我在使其工作时遇到的一些挑战,请参阅昨天发布的this question。)

答案 1 :(得分:2)

更新

CloudFormation的使用已经有所简化,因为该评论已在问题跟踪器中发布。我已向http://docs.serverless.com/docs/templates-variables提交了文档更新,并在gist中发布了我的配置的缩短版本。

可以在s-function.json Lambda配置文件中引用CloudFormation输出,以使这些输出可用作环境变量。

s-resource-cf.json输出部分:

"Outputs": {
    "redisHost": {
        "Description": "Redis host URI",
        "Value": {
            "Fn::GetAtt": [
                "RedisCluster",
                "RedisEndpoint.Address"
            ]
        }
    }
}

s-function.json环境部分:

"environment": {
    "REDIS_HOST": "${redisHost}"
},

Lambda函数中的用法:

exports.handler = function(event, context) {
    console.log("Redis host: ", process.env.REDIS_HOST);
};

旧回答

看起来在无服务器问题跟踪器(link)中找到/实施了解决方案。引用HyperBrain

CF输出变量

要让lambda访问CF输出变量,必须在lambda IAM角色中为其赋予cloudformation:describeStacks访问权限。

CF.loadVars()承诺会将所有CF输出变量添加到流程' 环境为SERVERLESS_CF_OutVar名称。它会增加几毫秒 你的lambda的启动时间。

按如下方式更改lambda处理程序:

// Require Serverless ENV vars
var ServerlessHelpers = require('serverless-helpers-js');
ServerlessHelpers.loadEnv();

// Require Logic
var lib = require('../lib');

// Lambda Handler
module.exports.handler = function(event, context) {
  ServerlessHelpers.CF.loadVars()
  .then(function() {
    lib.respond(event, function(error, response) {
      return context.done(error, response);
    });
  })
};