首页 > 解决方案 > 将 NodeJS 运行时中的变量传回 CloudFormation

问题描述

我有一个 CF 模板,它在 Javascript 中使用无服务器函数来实例化 AWS Connect 实例,因为 Connect 没有实际的 CF 资源。我使用环境变量将值从 CF 传递到内联 Javascript。现在我需要反过来:从 JS 中提取其中一些值并将它们传递回 CF 模板的其他部分。那么,问题是,如何将变量从 Javascript 传递到 CloudFormation?我怀疑我需要使用 Systems Manager Parameter store 之类的东西,但也许有更简单的方法?具体来说,我需要以下代码段中的值“serviceRole”可传递给其他 CF 资源:

CreateConnectInstance:
Type: AWS::Serverless::Function
Properties:
  Handler: index.handler
  Runtime: nodejs12.x
  Description: Invoke a function to create an AWS Connect instance.
  MemorySize: 128
  Timeout: 8
  Role: !GetAtt LambdaExecutionRole.Arn
  Tracing: Active
  Layers:
    - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:layer:node_sdk:1"
  Environment:
    Variables:
      IdentityManagementType:
        Ref: IdentityManagementType
      InboundCallsEnabled:
        Ref: InboundCallsEnabled
      InstanceAlias:
        Ref: InstanceAlias
      OutboundCallsEnabled:
        Ref: OutboundCallsEnabled
      Region:
        Ref: Region
      #Optional Values
      ClientToken: !If
        - HasClientToken
        - !Ref ClientToken
        - !Ref "AWS::NoValue"
      DirectoryId: !If
        - HasClientToken
        - !Ref ClientToken
        - !Ref "AWS::NoValue"

  InlineCode: |
    var AWS = require('aws-sdk');
    var response = require('cfn-response');
    var connect = new AWS.Connect({apiVersion: '2017-08-08', region: process.env.Region});
    exports.handler = (event, context) => {
      console.log("Request Received:\n" + JSON.stringify(event));
      var instanceId;
      var serviceRole;
      var isInboundCallsEnabled = (process.env.InboundCallsEnabled == 'true');
      var isOutboundCallsEnabled = (process.env.OutboundCallsEnabled == 'true');
      var params = {
        InboundCallsEnabled: isInboundCallsEnabled,
        OutboundCallsEnabled: isOutboundCallsEnabled,
        IdentityManagementType: process.env.IdentityManagementType,
        ClientToken: process.env.ClientToken,
        DirectoryId: process.env.DirectoryId,
        InstanceAlias: process.env.InstanceAlias
      };
      connect.createInstance(params, function (err, data) {
        if (err) {
          let responseData = { Error: "Create Instance Failed" };
          console.log(responseData.Error + ":\n", err);
          response.send(event, context, "FAILED", responseData);
          instanceId = data.Id;
        }
        else {
          console.log("Connect Instance Creation Successful");
          console.log(JSON.stringify(data));
          response.send(event, context, "SUCCESS", data);
        }
      });
      connect.describeInstance({InstanceId: instanceId}, function (err,data) {
        console.log(JSON.stringify(data));
        serviceRole = data.Instance.ServiceRole; // ***NEED TO EXTRACT THIS VALUE to CF***
      });
    }

它通过以下方式在同一模板中调用:

InvokeLambda:
  Type: AWS::CloudFormation::CustomResource
  DependsOn: CreateConnectInstance
  Version: "1.0"
  Properties:
    ServiceToken: !Sub ${CreateConnectInstance.Arn}

标签: node.jsamazon-web-servicesaws-lambdaamazon-cloudformationaws-serverless

解决方案


在向 CloudFormation 发送“SUCCESS”响应时,您可以使用响应对象的Data字段将 Service Role 作为键值对传递。这样,在自定义资源之后创建的所有资源都可以使用Fn::GetAtt访问此信息。从文档

获得 SUCCESS 响应后,AWS CloudFormation 继续进行堆栈操作。如果返回 FAILED 响应或没有响应,则操作失败。自定义资源的任何输出数据都存储在预签名的 URL 位置。模板开发人员可以使用 Fn::GetAtt 函数检索该数据。


推荐阅读