대망의 Cloud Functions의 Go 대응! Cloud Build의 통지를 Go로 구현!!
tl;dr
Cloud Functions Go
마지막 날 (2019/1/17) Cloud Functions에서 Go를 사용할 수있게되었습니다
Cloud Functions: Go 1.11 is now a supported language | Google Cloud Blog
지금까지 베타판입니다만, GCP의 베타는 프로덕션 레벨이므로 여러가지 사용해 가고 싶네요.
Cloud Build 알림 샘플
Cloud Build 실행 결과를 Cloud Functions를 사용하여 Slack에 알리는 샘플이 공식 문서에 있습니다.
Configuring notifications for third-party services | Cloud Build Documentation | Google Cloud
Node.js로 작성된 것입니다만, 이쪽을 이번 Go로 재작성해 보았습니다.
Go 버전의 Cloud Functions
소스는 다음과 같습니다. 1
function.go
package function
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"cloud.google.com/go/functions/metadata"
slack "github.com/ashwanthkumar/slack-go-webhook"
"github.com/pkg/errors"
"google.golang.org/api/cloudbuild/v1"
)
const SlackWebhookURL = "[SLACK_WEBHOOK]"
var (
projectID string
resource string
// Skip if the current status is not in the status list.
// Add additional statues to list if you'd like:
// QUEUED, WORKING, SUCCESS, FAILURE,
// INTERNAL_ERROR, TIMEOUT, CANCELLED
status = map[string]bool{
"SUCCESS": true,
"FAILURE": true,
"INTERNAL_ERROR": true,
"TIMEOUT": true,
}
)
func init() {
projectID = os.Getenv("GCP_PROJECT")
resource = fmt.Sprintf("projects/%s/topics/cloud-builds", projectID)
}
type PubSubMessage struct {
Data string `json:"data"`
}
// Subscribe is the main function called by Cloud Functions.
func Subscribe(ctx context.Context, m PubSubMessage) error {
meta, err := metadata.FromContext(ctx)
if err != nil {
return errors.Wrap(err, "Failed to get metadata")
}
if meta.Resource.Name != resource {
fmt.Printf("%s is not wathing resource\n", meta.Resource.Name)
return nil
}
build, err := eventToBuild(m.Data)
if err != nil {
return errors.Wrap(err, "Failed to decode event data")
}
if _, ok := status[build.Status]; !ok {
fmt.Printf("%s status is skipped\n", build.Status)
return nil
}
// Send message to Slack.
message := createSlackMessage(build)
errs := slack.Send(SlackWebhookURL, "", message)
if len(errs) > 0 {
return errors.Errorf("Failed to send a message to Slack: %s", errs)
}
return nil
}
// eventToBuild transforms pubsub event message to a Build struct.
func eventToBuild(data string) (*cloudbuild.Build, error) {
d, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, errors.Wrap(err, "Failed to decode base64 data")
}
build := cloudbuild.Build{}
err = json.Unmarshal(d, &build)
if err != nil {
return nil, errors.Wrap(err, "Failed to decode to JSON")
}
return &build, nil
}
// createSlackMessage creates a message from a build object.
func createSlackMessage(build *cloudbuild.Build) slack.Payload {
title := "Build Logs"
a := slack.Attachment{
Title: &title,
TitleLink: &build.LogUrl,
}
a.AddField(slack.Field{
Title: "Status",
Value: build.Status,
})
p := slack.Payload{
Text: fmt.Sprintf("Build `%s`", build.Id),
Markdown: true,
Attachments: []slack.Attachment{a},
}
return p
}
쫓기 쉽도록 원래의 Node.js의 소스의 코멘트 거의 그대로 실었습니다.
Node.js 버전을 보면 알 수 있듯이 Cloud Build에서 오는 PubSub Message에는
data
필드가 있으며 그 내용은 JSON을 base64로 인코딩 한 것입니다.여기에서 데이터를 검색하기 위해 Go에서도 base64 디코드 → JSON 디코딩 처리를
eventToBuild
로 구현하고 있습니다.빌드 데이터 구조는 Google
cloudbuild.v1
패키지의 Build 구조체에 정의 된 것을 사용합니다.status
를 체크하고있는 것은, Node라고 Array.prototype.indexOf
를 사용하고 있습니다만, Go의 슬라이스라고 그러한 메소드는 없고, 프리미티브에 for
를 쓰게 되므로, map
의 키 로 유효한 status
를 정의했습니다.Slack에게 InCommingWebhook을 통해 알리는 부분은 ashwanthkumar/slack-go-webhook 2을 사용했습니다.
이제 다음과 같은 명령으로 배포하면 사용할 수 있을 것입니다…입니다! 3
$ gcloud functions deploy Subscribe --runtime go111 \
--trigger-topic cloud-builds
소스는 Github에도 올려져 있습니다. ↩
확실히 조사한 한 이것 이외 라이브러리 없는 것 같았다 ↩
실제로이 소스에서 시도하지는 않지만 현재 프로젝트에서 비슷한 코드로 작동합니다. ↩
Reference
이 문제에 관하여(대망의 Cloud Functions의 Go 대응! Cloud Build의 통지를 Go로 구현!!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/iwata@github/items/76545282ec136a4f271d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)