简体   繁体   English

我们如何使用Java编写的AWS Lambda函数访问和响应CloudFormation自定义资源?

[英]How do we access and respond to CloudFormation custom resources using an AWS Lambda function written in Java?

I have am AWS Lambda function written in Java that I would like to use as part of a response to an AWS CloudFormation function. 我有用Java编写的AWS Lambda函数,我想将其用作对AWS CloudFormation函数的响应的一部分。 Amazon provides two detailed examples on how to create a CloudFormation custom resource that returns its value based on an AWS Lambda function written in Node.js, however I have been having difficulty translating the Lambda examples into Java. Amazon提供了两个关于如何创建CloudFormation自定义资源的详细示例 ,该资源根据Node.js编写的AWS Lambda函数返回其值,但是我一直难以将Lambda示例转换为Java。 How can we setup our AWS Java function so that it reads the value of the pre-signed S3 URL passed in as a parameter to the Lambda function from CloudFormation and send back our desired response to the waiting CloudFormation template? 我们如何设置我们的AWS Java函数,以便它从CloudFormation读取作为参数传递给Lambda函数的预签名S3 URL的值,并将所需的响应发送回等待的CloudFormation模板?

After back and forth conversation with AWS, here are some code samples I've created that accomplish this. 在与AWS进行来回对话之后,以下是我创建的一些代码示例。

First of all, assuming you want to leverage the predefined interfaces for creating Handlers , you can implement RequestsHandler and define the HandleRequest methods like so: 首先,假设您想利用预定义的接口来创建处理程序 ,您可以实现RequestsHandler并定义HandleRequest方法,如下所示:

public class MyCloudFormationResponder implements RequestHandler<Map<String, Object>, Object>{
    public Object handleRequest(Map<String,Object> input, Context context) {
        ...
    }
}

The Map<String, Object> is a Map of the values sent from your CloudFormation resource to the Lambda function. Map<String, Object>是从CloudFormation资源发送到Lambda函数的值的映射。 An example CF resource: 示例CF资源:

"MyCustomResource": {
  "Type" : "Custom::String",
  "Version" : "1.0",
  "Properties": {
    "ServiceToken": "arn:aws:lambda:us-east-1:xxxxxxx:function:MyCloudFormationResponderLambdaFunction",
    "param1": "my value1",
    "param2": ["t1.micro", "m1.small", "m1.large"]
  }
}

can be analyzed with the following code 可以使用以下代码进行分析

    String responseURL = (String)input.get("ResponseURL");
    context.getLogger().log("ResponseURLInput: " + responseURL);
    context.getLogger().log("StackId Input: " + input.get("StackId"));
    context.getLogger().log("RequestId Input: " + input.get("RequestId"));
    context.getLogger().log("LogicalResourceId Context: " + input.get("LogicalResourceId"));
    context.getLogger().log("Physical Context: " + context.getLogStreamName());
    @SuppressWarnings("unchecked")
    Map<String,Object> resourceProps = (Map<String,Object>)input.get("ResourceProperties");
    context.getLogger().log("param 1: " + resourceProps.get("param1"));
    @SuppressWarnings("unchecked")
    List<String> myList = (ArrayList<String>)resourceProps.get("param2");
    for(String s : myList){
        context.getLogger().log(s);
    }

The key things to point out here, beyond what is explained in the NodeJS examples in the AWS documentation are 除了AWS文档中的NodeJS示例中解释的内容之外,这里要指出的关键事项是

  • (String)input.get("ResponseURL") is the pre-signed S3 URL that you need to respond back to (more on this later) (String)input.get("ResponseURL")是您需要回复的预签名S3 URL(稍后会详细介绍)
  • (Map<String,Object>)input.get("ResourceProperties") returns the map of your CloudFormation custom resource "Properties" passed into the Lambda function from your CF template. (Map<String,Object>)input.get("ResourceProperties")返回从CF模板传递到Lambda函数的CloudFormation自定义资源“Properties”的映射。 I provided a String and ArrayList as two examples of object types that can be returned, though several others are possible 我提供了一个String和ArrayList作为可以返回的对象类型的两个示例,尽管其他几个是可能的

In order to respond back to the CloudFormation template custom resource instantiation, you need to execute an HTTP PUT call back to the ResponseURL previously mentioned and include most of the following fields in the variable cloudFormationJsonResponse . 为了响应CloudFormation模板自定义资源实例化,您需要执行HTTP PUT调用回到前面提到的ResponseURL,并在变量cloudFormationJsonResponse包含大部分以下字段。 Below is how I've done this 以下是我如何做到这一点

    try {
        URL url = new URL(responseURL);
        HttpURLConnection connection=(HttpURLConnection)url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("PUT");
        OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
        JSONObject cloudFormationJsonResponse = new JSONObject();
        try {
            cloudFormationJsonResponse.put("Status", "SUCCESS");
            cloudFormationJsonResponse.put("PhysicalResourceId", context.getLogStreamName());
            cloudFormationJsonResponse.put("StackId", input.get("StackId"));
            cloudFormationJsonResponse.put("RequestId", input.get("RequestId"));
            cloudFormationJsonResponse.put("LogicalResourceId", input.get("LogicalResourceId"));
            cloudFormationJsonResponse.put("Data", new JSONObject().put("CFAttributeRefName", "some String value useful in your CloudFormation template"));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        out.write(cloudFormationJsonResponse.toString());
        out.close();
        int responseCode = connection.getResponseCode();
        context.getLogger().log("Response Code: " + responseCode);
    } catch (IOException e) {
        e.printStackTrace();
    }

Of particular note is the node "Data" above which references an additional com.amazonaws.util.json.JSONObject in which I include any attributes that are required in my CloudFormation template. 特别值得注意的是上面的节点“数据”引用了另一个com.amazonaws.util.json.JSONObject ,其中我包含了我的CloudFormation模板中所需的任何属性。 In this case, it would be retrieved in CF template with something like { "Fn::GetAtt": [ "MyCustomResource", "CFAttributeRefName" ] } 在这种情况下,它将在CF模板中检索,类似{ "Fn::GetAtt": [ "MyCustomResource", "CFAttributeRefName" ] }

Finally, you can simply return null since nothing would be returned from this function as it's the HTTPUrlConnection that actually responds to the CF call. 最后,您可以简单地return null因为这个函数不会返回任何内容,因为它是实际响应CF调用的HTTPUrlConnection

Neil, 尼尔,

I really appreciate your great documentation here. 我非常感谢你的精彩文档。 I would add a few things that I found useful: 我会添加一些我觉得有用的东西:

input.get("RequestType") - This comes back as "Create", "Delete", etc. You can use this value to determine what to do when a stack is created, deleted, etc.. input.get(“RequestType”) - 返回“Create”,“Delete”等。您可以使用此值来确定创建,删除堆栈等时要执行的操作。

As far as security, I uploaded the Lambda Functions and set the VPC, subnets, and security group (default) manually so I can reuse it with several cloudformationn scripts. 就安全性而言,我上传了Lambda函数并手动设置了VPC,子网和安全组(默认),因此我可以将其与多个cloudformationn脚本一起重用。 That seems to be working okay. 这似乎工作正常。

I created one Lambda function that gets called by the CF scripts and one I can run manually in case the first one fails. 我创建了一个由CF脚本调用的Lambda函数,一个我可以手动运行,以防第一个失败。

This excellent gradle aws plugin makes it easy to upload Java Lambda functions to AWS. 这个优秀的gradle aws插件可以轻松地将Java Lambda函数上传到AWS。

Gradle AWS Plugin Gradle AWS插件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 CloudFormation 模板更新 AWS Lambda function - How do I update AWS Lambda function using CloudFormation template 使用 lambda 的自定义资源以 cloudformation 导出输出 - exporting outputs in cloudformation using custom resources with lambda 如何为使用 CloudFormation 模板创建的 AWS Lambda function 添加触发器? - How to add triggers for a AWS Lambda function created using a CloudFormation template? AWS CloudFormation中的Lambda函数 - Lambda Function in AWS CloudFormation 如何读取用Java编写的AWS Lambda函数中的文件? - How to read a file in AWS Lambda Function written in Java ? 如何使用 aws aws-codebuild、codedeploy、cloudformation 的服务为 aws lambda 与 java 配置持续集成 - How to configure continuous integration for aws lambda with java using the services of aws aws-codebuild, codedeploy, cloudformation 从Lambda函数内部访问AWS CloudFormation ARN - Access AWS CloudFormation ARN from inside Lambda Function AWS CloudFormation自定义lambda函数停留在创建状态 - AWS CloudFormation custom lambda function stuck in create state AWS Lambda:如何使用java从Lambda函数访问S3存储桶 - AWS Lambda : How to access S3 bucket from Lambda function using java 我如何运行AWS Lambda函数以使我知道CloudFormation已完成整个堆栈的创建 - How do I run a AWS Lambda function to let me know that CloudFormation has completed the entire stack creation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM