11

我创建了一个 lambda 和云形成模板,它授予 lambda 访问参数存储和秘密管理器的权限。当我测试 lambda 时,我在 export.handler 函数之外有以下函数:

function getParameterFromStore(param){
    let promise = new Promise(function(resolve, reject){
        console.log('++ ' + param.Path);
        servmgr.getParametersByPath(param, function(err, data){
            if(err){
                reject(console.log('Error getting parameter: ' + err, err.stack));
            } else {
                resolve(data);
            }
        });
    });

   let parameterResult = promise.then(function(result){
    console.log('---- result: '+ JSON.stringify(result));
        return result;
    });
   return parameterResult;
};

servmgr被实例化为var servmgr = new AWS.SSM();

当我从 export.handler 函数调用这个函数时,我这样做:

myFirstParam =  { Path : '/myPath/Service/servicesEndpoint'};

let endpointResult = getParameterFromStore(myFirstParam);

在 lambda 中,我有函数检索在 export.handler 函数 bt 之外定义的参数,该函数包含在一个 promise 中。

当我运行/测试这个 lambda 时,返回的对象总是未定义的......我得到了 Parameters[] 但没有值。

2019-02-20T21:42:41.340Z    2684fe88-d552-4560-a477-6761f2de6717    ++ /myPath/Service/serviceEndpoint
2019-02-20T21:42:41.452Z    2684fe88-d552-4560-a477-6761f2de6717    ---- result: {"Parameters":[]}

如何在运行时将参数值返回给 lambda?

更新

根据 Thales 的建议/回答,我将 lambda 简化为:

const getParameterFromStoreAsync = (param) => {
    return new Promise((resolve, reject) => {
        servmgr.getParametersByPath(param, (err, data) => {
            if(err){
                reject(console.log('Error getting parameter: ' + err, err.stack));
            } 
            return resolve(data);
        });
    });
};

exports.handler = async(event, ctx, callback) => {

console.log('INFO[lambda]: Event: [' + JSON.stringify(event, null, 2) + ']');

    console.log('this is the event' + JSON.stringify(event));
    sfdcEndPointParam =  { Path : '/PartnerBanking/Service/SfdcEndpoint'};
    let myendpoint = await getParameterFromStoreAsync(sfdcEndPointParam);

    console.log('### endpoint path: ' + JSON.stringify(myendpoint));

done = ()=>{}
callback(null, done());
};

我仍然看到在我的测试中返回一个空数组:

### endpoint path: {"Parameters":[]}

我还将函数移到回调中

exports.handler = (event,ctx, callback){
done = async()=>{
 console.log('this is the event' + JSON.stringify(event));
    sfdcEndPointParam =  { Path : '/PartnerBanking/Service/SfdcEndpoint'};
    let myendpoint = await getParameterFromStoreAsync(sfdcEndPointParam);

    console.log('### endpoint path: ' + JSON.stringify(myendpoint));}
}
callback(null, done());

同样的结果......空数组。还有什么要尝试的吗?

4

3 回答 3

17

这是因为您在代码执行getParameterFromStore之前返回,因此是. 如果您不想过多地更改代码,我会返回您创建的 Promise,如下所示:then()parameterResultundefined

function getParameterFromStore(param){
return new Promise(function(resolve, reject){
    console.log('++ ' + param.Path);
    servmgr.getParametersByPath(param, function(err, data){
        if(err){
            reject(console.log('Error getting parameter: ' + err, err.stack));
        } else {
            resolve(data);
        }
    });
});

};

最后,在函数的客户端上,您可以获得如下结果:

const myFirstParam =  { Path : '/myPath/Service/servicesEndpoint'}
getParameterFromStore(myFirstParam).then(console.log)

但是,在 NodeJS 中编码时,我强烈建议您改用async/await,这样您就可以逃离 Promise Hell(在 Promise 之后进行 chaninig Promise 以实现“同步”)

使用 async/await 时,您可以将代码设计为同步的。这是您的示例的重构版本,使用 async/await 以及箭头函数:

const getParameterFromStore = param => {
    return new Promise((resolve, reject) => {
        console.log('++ ' + param.Path);
        servmgr.getParametersByPath(param, (err, data) => {
            if (err) {
                console.log('Error getting parameter: ' + err, err.stack)
                return reject(err);
            }
            return resolve(data);
        });
    })
}

exports.handler = async (event) => {
   const endpointResult = await getParameterFromStore(event.someAttributeFromTheEventThatYouWantToUse)

   console.log(endpointResult)
};

编辑:在 OP 解决了第一个问题之后,我自己创建了一个工作示例。事实证明,OP 调用 API 的方式是不正确的。

这是完整的工作示例:

'use strict';

const AWS = require('aws-sdk')

AWS.config.update({
  region: 'us-east-1'
})

const parameterStore = new AWS.SSM()

const getParam = param => {
  return new Promise((res, rej) => {
    parameterStore.getParameter({
      Name: param
    }, (err, data) => {
        if (err) {
          return rej(err)
        }
        return res(data)
    })
  })
}

module.exports.get = async (event, context) => {
  const param = await getParam('MyTestParameter')
  console.log(param);
  return {
    statusCode: 200,
    body: JSON.stringify(param)
  };
};

注意Name必须作为对 ServiceManager.getAttribute 方法的 API 调用的一部分提供的属性。

这个属性在官方文档中有说明

我自己运行了这个,这是 CloudWatch Logs 中的输出:

在此处输入图像描述

如您所见,该值已成功返回。

希望这可以帮助!

于 2019-02-21T10:44:27.740 回答
1

如果您的 lambda 部署在 VPC 上,请确保已附加安全组并允许出站流量。它将能够自动访问参数存储。

https://aws.amazon.com/premiumsupport/knowledge-center/lambda-vpc-parameter-store/

于 2019-12-08T06:53:17.187 回答
1

一个更简单的解决方案是:

const getParameterFromStore = (params) => servmgr.getParametersByPath(params).promise();

const myFirstParam =  { Path : '/myPath/Service'};
getParameterFromStore(myFirstParam).then(console.log);

如您所见,SDK 本身提供了实用程序功能,您可以根据需要以异步或同步方式使用这些功能。

希望能帮助到你。

于 2020-06-27T16:07:11.117 回答