日志显示Lambda已完全运行,但函数以退出状态1退出。

huangapple go评论75阅读模式
英文:

Logs show that Lambda ran completely, but function exits with exit status 1

问题

这是我的代码:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/ec2"
    "github.com/aws/aws-sdk-go-v2/service/ec2/types"
)

func main() {
    // 加载共享的 AWS 配置(~/.aws/config)
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Fatal(err)
    }

    // 创建 Amazon EC2 服务客户端
    ec2ServiceClient := ec2.NewFromConfig(cfg)

    // DescribeAddressesInput 没有过滤器表示列出所有地址
    IpListFilter := &ec2.DescribeAddressesInput{}

    // 请求 EC2 客户端列出所有弹性 IP
    result, err := ec2ServiceClient.DescribeAddresses(context.TODO(), IpListFilter)
    if err != nil {
        fmt.Println("获取 Amazon 弹性 IP 信息时出错:")
        fmt.Println(err)
        return
    }

    // 对于所有的 IP,检查它们是否有分配 ID。如果没有,它们可以被删除
    for _, a := range result.Addresses {
        fmt.Println("分配 ID:" + *a.AllocationId)
        fmt.Println("公共 IP:" + *a.PublicIp)

        // 如果此 EIP 没有与任何 AWS 资源关联,继续删除
        if a.AssociationId == nil {
            // 额外的灵活性步骤
            if isThisEIPKillable(a.Tags) {
                fmt.Println("即将被删除")
                // 释放/删除弹性 IP
                ReleaseAddressFilter := &ec2.ReleaseAddressInput{AllocationId: a.AllocationId}
                ec2ServiceClient.ReleaseAddress(context.TODO(), ReleaseAddressFilter)
                fmt.Println(*a.PublicIp + " 已删除")
            } else {
                fmt.Println(*a.PublicIp + " 已启用 KILLERHOLD 并将保留")
            }

        } else {
            fmt.Println("关联 ID:" + *a.AssociationId)
            fmt.Println("实例 ID:" + *a.InstanceId)
            fmt.Println("私有 IP 地址:" + *a.PrivateIpAddress)
        }

        fmt.Println("")
    }
}

// isThisEIPKillable 扫描弹性 IP 的标签,只有当 EIPKILLER 标签设置为 true 时返回 false
func isThisEIPKillable(tags []types.Tag) bool {
    for _, tag := range tags {
        if *tag.Key == "KILLERHOLD" && *tag.Value == "true" {
            return false
        }
    }
    return true
}

Lambda 函数具有运行所需的权限,即允许运行 ec2:ReleaseAddressec2:DescribeAddresses

进行测试时,我有一个与一个 EC2 实例关联的 EIP。根据 Lambda 的逻辑,Lambda 应该只打印输出并在没有任何错误的情况下退出。

但是实际情况是这样的。我已经删除了一些字符串以保护隐私:

START RequestId: 5a7446ed-6896-4e65-b795-35d1bfd6ca60 Version: $LATEST
分配 ID: eipalloc-08fexample952a7f7
公共 IP: XXX.XXX.XXX.XXX
关联 ID: eipassoc-0112e332e17959d76
实例 ID: i-096561051e41c2d60
私有 IP 地址: 10.2.1.38
2022/08/26 14:25:38 <nil>
分配 ID: eipalloc-08fexample952a7f7
公共 IP: XXX.XXX.XXX.XXX
关联 ID: eipassoc-011example959d76
实例 ID: i-09656examplec2d60
私有 IP 地址: 10.2.1.38
2022/08/26 14:25:39 <nil>
END RequestId: 5a7446ed-6896-4e65-b795-3exampleca60
REPORT RequestId: 5a7446ed-6896-4e65-b795-3examplea60	Duration: 402.33 ms	Billed Duration: 403 ms	Memory Size: 512 MB	Max Memory Used: 21 MB	
RequestId: 5a7446ed-6896-4e65-b795-3exampleca60 Error: Runtime exited with error: exit status 1
Runtime.ExitError
英文:

Here is my code:

package main

import (
    &quot;context&quot;
    &quot;fmt&quot;
    &quot;log&quot;

    &quot;github.com/aws/aws-sdk-go-v2/config&quot;
    &quot;github.com/aws/aws-sdk-go-v2/service/ec2&quot;
    &quot;github.com/aws/aws-sdk-go-v2/service/ec2/types&quot;
)

func main() {
    // Load the Shared AWS Configuration (~/.aws/config)
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Fatal(err)
    }

    // Create an Amazon EC2 service client
    ec2ServiceClient := ec2.NewFromConfig(cfg)

    // DescribeAddressesInput with no filter means list all addresses
    IpListFilter := &amp;ec2.DescribeAddressesInput{}

    // Ask EC2 client to list all Elastic IPs.
    result, err := ec2ServiceClient.DescribeAddresses(context.TODO(), IpListFilter)
    if err != nil {
        fmt.Println(&quot;Got an error retrieving information about your Amazon Elastic IPs:&quot;)
        fmt.Println(err)
        return
    }

    // Out of all IPs, check if they have an allocation ID. If not, they are candidate for deletion
    for _, a := range result.Addresses {
        fmt.Println(&quot;Allocation ID: &quot; + *a.AllocationId)
        fmt.Println(&quot;Public IP: &quot; + *a.PublicIp)

        // if this EIP is not associated with any AWS resources, proceed for killing.
        if a.AssociationId == nil {
            // extra step for flexibility
            if isThisEIPKillable(a.Tags) {
                fmt.Println(&quot;About to be killed&quot;)
                // Release/kill the Elastic IP
                ReleaseAddressFilter := &amp;ec2.ReleaseAddressInput{AllocationId: a.AllocationId}
                ec2ServiceClient.ReleaseAddress(context.TODO(), ReleaseAddressFilter)
                fmt.Println(*a.PublicIp + &quot; is not more&quot;)
            } else {
                fmt.Println(*a.PublicIp + &quot; has KILLERHOLD enabled and is going to stay&quot;)
            }

        } else {
            fmt.Println(&quot;Association ID: &quot; + *a.AssociationId)
            fmt.Println(&quot;Instance ID: &quot; + *a.InstanceId)
            fmt.Println(&quot;PrivateIpAddress: &quot; + *a.PrivateIpAddress)
        }

        fmt.Println(&quot;&quot;)
    }
}

// isThisEIPKillable scans to tags of Elastic IP and only return false when
// EIPKILLER is tag is set to true.
func isThisEIPKillable(tags []types.Tag) bool {
    for _, tag := range tags {
        if *tag.Key == &quot;KILLERHOLD&quot; &amp;&amp; *tag.Value == &quot;true&quot; {
            return false
        }
    }
    return true
}

The Lambda function has the necessary permission to run i.e. it is allowed to run ec2:ReleaseAddress and ec2:DescribeAddresses.

For testing, I have one EIP associated with one EC2 instance. According to the Lambda logic, the lambda should just print output and exit without any error.

But this is what happens. I have redacted some strings for privacy:

START RequestId: 5a7446ed-6896-4e65-b795-35d1bfd6ca60 Version: $LATEST
Allocation ID: eipalloc-08fexample952a7f7
Public IP: XXX.XXX.XXX.XXX
Association ID: eipassoc-0112e332e17959d76
Instance ID: i-096561051e41c2d60
PrivateIpAddress: 10.2.1.38
2022/08/26 14:25:38 &lt;nil&gt;
Allocation ID: eipalloc-08fexample952a7f7
Public IP: XXX.XXX.XXX.XXX
Association ID: eipassoc-011example959d76
Instance ID: i-09656examplec2d60
PrivateIpAddress: 10.2.1.38
2022/08/26 14:25:39 &lt;nil&gt;
END RequestId: 5a7446ed-6896-4e65-b795-3exampleca60
REPORT RequestId: 5a7446ed-6896-4e65-b795-3examplea60	Duration: 402.33 ms	Billed Duration: 403 ms	Memory Size: 512 MB	Max Memory Used: 21 MB	
RequestId: 5a7446ed-6896-4e65-b795-3exampleca60 Error: Runtime exited with error: exit status 1
Runtime.ExitError

答案1

得分: 2

根据 @jarmod 和 @Daniel 的发现,你编写的函数不符合文档中规定的格式。

假设你已经将处理程序配置为 main,下面是你旧代码与正确代码的差异。

@@ -5,14 +5,19 @@ import (
        "fmt"
        "log"
 
+       "github.com/aws/aws-lambda-go/lambda"
        "github.com/aws/aws-sdk-go-v2/config"
        "github.com/aws/aws-sdk-go-v2/service/ec2"
        "github.com/aws/aws-sdk-go-v2/service/ec2/types"
 )
 
-func main() {
+type MyEvent struct {
+       Name string `json:"name"`
+}
+
+func Handler(ctx context.Context, name MyEvent) (string, error) {
        // Load the Shared AWS Configuration (~/.aws/config)
-       cfg, err := config.LoadDefaultConfig(context.TODO())
+       cfg, err := config.LoadDefaultConfig(ctx)
        if err != nil {
                log.Fatal(err)
        }
@@ -27,8 +32,7 @@ func main() {
        result, err := ec2ServiceClient.DescribeAddresses(context.TODO(), IpListFilter)
        if err != nil {
                fmt.Println("Got an error retrieving information about your Amazon Elastic IPs:")
-               fmt.Println(err)
-               return
+               return "", err
        }
 
        // Out of all IPs, check if they have an allocation ID. If not, they are candidate for deletion
@@ -57,6 +61,7 @@ func main() {
 
                fmt.Println("")
        }
+       return "Done execution", nil
 }
 
 // isThisEIPKillable scans to tags of Elastic IP and only return false when
@@ -69,3 +74,7 @@ func isThisEIPKillable(tags []types.Tag) bool {
        }
        return true
 }
+
+func main() {
+       lambda.Start(Handler)
+}

基本上将所有逻辑移动到一个不同的函数中,比如 Handler,然后在 main 中使用 lambda.Start(Handler) 调用该函数。

参考 AWS Lambda function handler in Go 获取更多参考信息。

英文:

As figured out by @jarmod and @Daniel. The function you have written does not comply with the format prescribed in the docs.

Assuming that you have configured your handler to be main, here is a diff of your old code vs what it should be.

@@ -5,14 +5,19 @@ import (
        &quot;fmt&quot;
        &quot;log&quot;
 
+       &quot;github.com/aws/aws-lambda-go/lambda&quot;
        &quot;github.com/aws/aws-sdk-go-v2/config&quot;
        &quot;github.com/aws/aws-sdk-go-v2/service/ec2&quot;
        &quot;github.com/aws/aws-sdk-go-v2/service/ec2/types&quot;
 )
 
-func main() {
+type MyEvent struct {
+       Name string `json:&quot;name&quot;`
+}
+
+func Handler(ctx context.Context, name MyEvent) (string, error) {
        // Load the Shared AWS Configuration (~/.aws/config)
-       cfg, err := config.LoadDefaultConfig(context.TODO())
+       cfg, err := config.LoadDefaultConfig(ctx)
        if err != nil {
                log.Fatal(err)
        }
@@ -27,8 +32,7 @@ func main() {
        result, err := ec2ServiceClient.DescribeAddresses(context.TODO(), IpListFilter)
        if err != nil {
                fmt.Println(&quot;Got an error retrieving information about your Amazon Elastic IPs:&quot;)
-               fmt.Println(err)
-               return
+               return &quot;&quot;, err
        }
 
        // Out of all IPs, check if they have an allocation ID. If not, they are candidate for deletion
@@ -57,6 +61,7 @@ func main() {
 
                fmt.Println(&quot;&quot;)
        }
+       return &quot;Done execution&quot;, nil
 }
 
 // isThisEIPKillable scans to tags of Elastic IP and only return false when
@@ -69,3 +74,7 @@ func isThisEIPKillable(tags []types.Tag) bool {
        }
        return true
 }
+
+func main() {
+       lambda.Start(Handler)
+}

Basically move all the logic to a different function say Handler, and then invoke that function in main using lambda.Start(Handler)

Refer to AWS Lambda function handler in Go for reference.

huangapple
  • 本文由 发表于 2022年8月26日 22:51:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/73502880.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定