CodeBuild의 Slack 알림을 Terraform에서 빨리 설정합니다.

최근 CodeBuild를 이용하기 시작했습니다만, CircleCI등과 같이는 바삭하고 Slack 통지를 할 수 없는 것을 조금 답답하게 느꼈습니다. 빌드의 상태가 Slack상에서 편하게 파악할 수 없으면 콘솔을 보러 가거나 사고 리소스를 빼앗기게 되는군요.

거기서 좋은 통지를 하려고 해도, 바로 이것이라고 하는 Terraform Module이 없었기 때문에 module를 만들어 보았습니다.

en30/codebuild-to-slack/aws | Terraform Module Registry

이를 통해 CodeBuild에서 다음 이벤트를 Slack에 쉽게 알릴 수 있습니다.
  • IN_PROGRESS : 시작
  • SUCCEEDED : 성공
  • FAILED : 실패
  • FAULT : AWS측으로 인한 실패?
  • TIMED_OUT : 타임 아웃
  • STOPPED : 중지

  • 실제 알림 예


    사용법



    main.tf
    variable "encrypted_slack_webhook_url" {}
    
    resource "aws_kms_key" "slack_webhook_url" {
      description = "Key for Slack Webhook URL"
    }
    
    module "codebuild_notification" {
      source = "en30/codebuild-to-slack/aws"
    
      version                     = "0.0.1"
      encrypted_slack_webhook_url = "${var.encrypted_slack_webhook_url}"
      slack_channel               = "#app"
      kms_key_arn                 = "${aws_kms_key.slack_webhook_url.arn}"
    }
    
    encrypted_slack_webhook_url는 다음과 같이 AWS CLI를 사용하여 얻을 수 있습니다.
    $ aws kms encrypt --key-id $AWS_KMS_KEY_ID --plaintext $SLACK_WEBHOOK_URL --query CiphertextBlob --output text
    
    $AWS_KMS_KEY_ID 는 module에 kms_key_arn 로 배달해 key id, $SLACK_WEBHOOK_URL 는 Slack의 Incoming Webhook URL입니다.

    위의 예와 같이 키도 Terraform으로 만들려고하면
  • aws_kms_key 의 작성 ( terraofmr apply ①)
  • 키를 사용하여 webhook url을 암호화
  • module을 이용한 통지 설치 ( terraofrm apply ②)

  • 그리고 terraform apply 로 한발로 갈 수 없는 것이 기분 나쁜 곳입니다만, 좋으면 사용해 보세요!

    내용의 간략한 설명



    하고 있는 일로
  • CodeBuild의 빌드 상태 변경에 대한 CloudWatch Event에서 Lambda를 시작합니다.
  • Lambda에서 이벤트 정보를 성형하여 Slack 알림

  • 입니다. Lambda에 Ruby Runtime도 들어간 것이며, 나는 Ruby를 좋아해서 Lambda는 Ruby로 썼습니다.

    그렇게 재미있는 곳이 있는 것은 아니지만, Lambda의 배치를 간단하게 하기 위해서, 표준 라이브러리, Lambda의 환경에 원래 들어 있는 aws-sdk 뿐으로 끝내도록(듯이) 하고 있습니다.

    notify_slack.rb
    require "uri"
    require "net/http"
    require "json"
    require "base64"
    require "aws-sdk"
    
    COLORS = {
      "SUCCEEDED" => "good",
      "FAILED" => "danger",
      "FAULT" => "danger",
      "TIMED_OUT" => "danger",
      "STOPPED" => "warning",
    }.freeze
    
    def decrypt(encrypted_url)
      client = Aws::KMS::Client.new
      client.decrypt(ciphertext_blob: Base64.decode64(encrypted_url)).plaintext
    end
    
    def build_url(region, project, slug)
      region, project, slug = [region, project, slug].map(&URI.method(:encode_www_form_component))
      "https://#{region}.console.aws.amazon.com/codesuite/codebuild/projects/#{project}/build/#{slug}/log"
    end
    
    def format(event) # rubocop:disable Metrics/MethodLength
      project = event["detail"]["project-name"]
      status = event["detail"]["build-status"]
      slug = event["detail"]["build-id"].split("/").last
    
      {
        attachments: [
          {
            color: COLORS[status],
            title: slug,
            title_link: build_url(event["region"], project, slug),
            fallback: status,
            fields: [
              {
                title: "Status",
                value: status,
                short: true,
              },
              {
                title: "Initiator",
                value: event["detail"]["additional-information"]["initiator"],
                short: true,
              },
            ],
          },
        ],
      }
    end
    
    def notify_slack(slack_url, payload)
      Net::HTTP.post_form(URI.parse(slack_url), payload: JSON.dump(payload))
    end
    
    def lambda_handler(event:, context:)
      slack_url = decrypt(ENV["ENCRYPTED_SLACK_WEBHOOK_URL"])
    
      payload = {
        channel: ENV["SLACK_CHANNEL"],
        username: ENV["SLACK_USERNAME"],
        icon_emoji: ENV["SLACK_EMOJI"],
      }.merge(format(event))
    
      notify_slack(slack_url, payload)
    end
    

    이상입니다.

    AWS도 Terraform도 사용하기 시작해 날이 얕기 때문에, 뭔가 조금이라도 신경이 쓰이는 부분이 있으면 부담없이 코멘트나 Issue 작성을 부탁합니다.

    참고


  • CodeBuild의 시작과 끝을 Slack에 알리기 - blog.ton-up.net
  • terraform-aws-modules/terraform-aws-notify-slack: Terraform module which creates SNS topic and Lambda function which sends notifications to Slack
  • 좋은 웹페이지 즐겨찾기