亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 go 中編寫前/后流量鉤子函數?

如何在 go 中編寫前/后流量鉤子函數?

Go
三國紛爭 2023-05-22 17:12:37
我開始使用 AWS SAM,現在我只有一些單元測試,但我想嘗試在預流量掛鉤函數中運行集成測試。不幸的是,似乎沒有 Golang 的代碼示例,我只能找到 Javascript 的代碼示例。我想從測試一個簡單查詢 DynamoDB 的 lambda 函數開始。
查看完整描述

2 回答

?
慕斯709654

TA貢獻1840條經驗 獲得超5個贊

這樣的事情有效:


package main


import (

    "context"

    "encoding/json"


    "github.com/aws/aws-lambda-go/lambda"

    "github.com/aws/aws-sdk-go/aws/session"

    "github.com/aws/aws-sdk-go/service/codedeploy"

)


type CodeDeployEvent struct {

    DeploymentId                  string `json:"deploymentId"`

    LifecycleEventHookExecutionId string `json:"lifecycleEventHookExecutionId"`

}


func HandleRequest(ctx context.Context, event CodeDeployEvent) (string, error) {


    // add some tests here and change status flag as needed . . .


    client := codedeploy.New(session.New())

    params := &codedeploy.PutLifecycleEventHookExecutionStatusInput{

        DeploymentId:                  &event.DeploymentId,

        LifecycleEventHookExecutionId: &event.LifecycleEventHookExecutionId,

        Status:                        "Succeeded",

    }


    req, _ := client.PutLifecycleEventHookExecutionStatusRequest(params)


    _ = req.Send()

}


查看完整回答
反對 回復 2023-05-22
?
12345678_0001

TA貢獻1802條經驗 獲得超5個贊

我開始實施這個并想分享我的完整解決方案。

在弄清楚如何使用它之后,我決定不使用它,因為它有幾個缺點。

  • 無法將新版本的金絲雀公開給用戶群的專用部分,這意味著有時他們會使用新版本或舊版本

  • 調用發布到 sns 的函數會觸發所有下游動作,這可能會獲取下游服務的新版本或舊版本,這會在破壞 API 的情況下導致很多問題

  • IAM 更改會立即影響兩個版本,可能會破壞舊版本。

相反,我將所有內容部署到預生產帳戶,運行我的集成和端到端測試,如果它們成功,我將部署到生產

創建金絲雀部署的 cdk 代碼:

const versionAlias = new lambda.Alias(this, 'Alias', {

    aliasName: "alias",

    version: this.lambda.currentVersion,

})


const preHook = new lambda.Function(this, 'LambdaPreHook', {

    description: "pre hook",

    code: lambda.Code.fromAsset('dist/upload/convert-pre-hook'),

    handler: 'main',

    runtime: lambda.Runtime.GO_1_X,

    memorySize: 128,

    timeout: cdk.Duration.minutes(1),

    environment: {

        FUNCTION_NAME: this.lambda.currentVersion.functionName,

    },

    reservedConcurrentExecutions: 5,

    logRetention: RetentionDays.ONE_WEEK,

})

// this.lambda.grantInvoke(preHook) // this doesn't work, I need to grant invoke to all functions :s

preHook.addToRolePolicy(new iam.PolicyStatement({

    actions: [

        "lambda:InvokeFunction",

    ],

    resources: ["*"],

    effect: iam.Effect.ALLOW,

}))


const application = new codedeploy.LambdaApplication(this, 'CodeDeployApplication')

new codedeploy.LambdaDeploymentGroup(this, 'CanaryDeployment', {

    application: application,

    alias: versionAlias,

    deploymentConfig: codedeploy.LambdaDeploymentConfig.ALL_AT_ONCE,

    preHook: preHook,

    autoRollback: {

        failedDeployment: true,

        stoppedDeployment: true,

        deploymentInAlarm: false,

    },

    ignorePollAlarmsFailure: false,

    // alarms:

    // autoRollback: codedeploy.A

    // postHook:

})

我的pre hook函數的go代碼。PutLifecycleEventHookExecutionStatus如果預掛鉤成功,則告訴代碼部署。不幸的是,如果部署消息失敗,您在 cdk 部署輸出中獲得的消息將毫無用處,因此您需要檢查掛鉤前/后日志。


為了實際運行集成測試,我只需調用 lambda 并檢查是否發生錯誤。


package main


import (

    "encoding/base64"

    "fmt"

    "log"

    "os"


    "github.com/aws/aws-lambda-go/lambda"

    "github.com/aws/aws-sdk-go/aws"

    "github.com/aws/aws-sdk-go/aws/session"

    "github.com/aws/aws-sdk-go/service/codedeploy"

    lambdaService "github.com/aws/aws-sdk-go/service/lambda"

)


var svc *codedeploy.CodeDeploy

var lambdaSvc *lambdaService.Lambda


type codeDeployEvent struct {

    DeploymentId                  string `json:"deploymentId"`

    LifecycleEventHookExecutionId string `json:"lifecycleEventHookExecutionId"`

}


func handler(e codeDeployEvent) error {

    params := &codedeploy.PutLifecycleEventHookExecutionStatusInput{

        DeploymentId:                  &e.DeploymentId,

        LifecycleEventHookExecutionId: &e.LifecycleEventHookExecutionId,

    }

    err := handle()

    if err != nil {

        log.Println(err)

        params.Status = aws.String(codedeploy.LifecycleEventStatusFailed)

    } else {

        params.Status = aws.String(codedeploy.LifecycleEventStatusSucceeded)

    }


    _, err = svc.PutLifecycleEventHookExecutionStatus(params)

    if err != nil {

        return fmt.Errorf("failed putting the lifecycle event hook execution status. the status was %s", *params.Status)

    }


    return nil

}


func handle() error {

    functionName := os.Getenv("FUNCTION_NAME")

    if functionName == "" {

        return fmt.Errorf("FUNCTION_NAME not set")

    }

    log.Printf("function name: %s", functionName)


    // invoke lambda via sdk

    input := &lambdaService.InvokeInput{

        FunctionName:   &functionName,

        Payload:        nil,

        LogType:        aws.String(lambdaService.LogTypeTail),                   // returns the log in the response

        InvocationType: aws.String(lambdaService.InvocationTypeRequestResponse), // synchronous - default

    }

    err := input.Validate()

    if err != nil {

        return fmt.Errorf("validating the input failed: %v", err)

    }


    resp, err := lambdaSvc.Invoke(input)

    if err != nil {

        return fmt.Errorf("failed to invoke lambda: %v", err)

    }


    decodeString, err := base64.StdEncoding.DecodeString(*resp.LogResult)

    if err != nil {

        return fmt.Errorf("failed to decode the log: %v", err)

    }

    log.Printf("log result: %s", decodeString)


    if resp.FunctionError != nil {

        return fmt.Errorf("lambda was invoked but returned error: %s", *resp.FunctionError)

    }

    return nil

}


func main() {

    sess, err := session.NewSession()

    if err != nil {

        return

    }

    svc = codedeploy.New(sess)

    lambdaSvc = lambdaService.New(sess)

    lambda.Start(handler)

}


查看完整回答
反對 回復 2023-05-22
  • 2 回答
  • 0 關注
  • 153 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號