본문 바로가기

DevOps/Slack & API Gateway

Slack으로 CICD 승인체계 구성하기 - 2. Lambda

 

CICD 구성

 

앞선 글에 이어서 이제 위에서 2단계 ~ 4단계까지 구성을 하나씩 해보도록 하겠습니다.

 

먼저, 2단계를 수행해주는 람다함수를 만들어보겠습니다.

Slack Interactive Component입니다.

슬랙채널에 버튼 같은 요소를 직접 작성하여 Slacker를 통해 구현하며, Slack Bot Token으로 인증하여 메세지를 채널에 전달합니다.

 

 

전 글에서 마지막에 본 Slack Bot Token을 환경변수에 저장해주도록 하겠습니다.

만약 보안상의 염려가 되신다면, KMS를 통해 암호화하신 후 사용하셔도 좋습니다.

 

이제 Layer입니다.

Slacker 라이브러리를 사용하기 때문에 해당 라이브러리를 바로 Layer로 올려서 사용해주시면 됩니다.

python.zip
1.06MB

 

소스코드는 아래와 같습니다.

import os
from slacker import Slacker

def lambda_handler(event, context):
	token = os.environ['slack_bot_token']
	build_info = event['params']['header']['buildinfo'].split('/')
	build_name = build_info[0]
	build_num = build_info[1]
	build_commnet = build_info[2]
	print(build_commnet)
	if token == event['params']['header']['Authorization']:
		slack = Slacker(token)
		attachments = [
		  {
		    "callback_id": "approval",
		    "attachment_type": "default",
		    "text": "Please Check this deploy " + build_name + "-" + build_num + "\n" + build_commnet,
		    "actions": [
		      {
		        "name": "Approve",
		        "text": "Approve This Deploy",
		        "type": "button",
		        "style": "primary",
		        "value": "YES",
		        "confirm": {
		          "title": "Are you sure?",
		          "text": "Do you approve this deploy "+build_name+"?",
		          "ok_text": "Yes",
		          "dismiss_text": "No"
		        }
		      },
		      {
		        "name": "Abort",
		        "text": "Abort This Deploy",
		        "type": "button",
		        "style": "danger",
		        "value": "NO",
		        "confirm": {
		          "title": "Are you sure?",
		          "text": "Do you abort this deploy "+build_name+"?",
		          "ok_text": "Yes",
		          "dismiss_text": "No"
		        }
		      }
		    ]
		  }
		]
		slack.chat.post_message(channel='#jenkins', attachments=attachments)

 

이제 채널에서 위와 같은 interactive component를 받았다면,

해당 응답에 대해서 Jenkins Rest API를 통해 젠킨스에 배포 승인 or 거절 응답을 전달해주는 람다함수를 만들도록 하겠습니다.

 

Jenkins REST API를 사용하려면, 젠킨스 계정에서 API Key를 생성해야합니다.

유저 -> 사용하고자 하는 계정 -> 설정에서 Add new Token을 해주세요

 

이제, 4번 역할을 해주는 람다함수를 만들겠습니다.

 

 

환경변수에 아까 만들었던 jenkins key 값과 맨 처음 slack app을 만들었을때 인증토큰값을 아래와 같이 환경변수로 넣어주겠습니다.

 

 

REST API를 콜해줘야하기 때문에 requests 라이브러리를 레이어로 추가해주겠습니다. 아래 파일을 Layer로 만들어서 추가시켜주세요.

python.zip
0.97MB

 

소스코드 입니다.  domain을 사용하시는 젠킨스 도메인으로 바꿔주셔야합니다.

import os
import requests
from requests.auth import HTTPBasicAuth

def get_job_num(domain, UserName, PassWord, build_name):
    url = domain + 'job/'+build_name+'/lastBuild/buildNumber'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 
    }
    response = requests.get(url, headers=headers, auth=HTTPBasicAuth(UserName, PassWord))
    print("build num : " + response.text)
    return response.text

def lambda_handler(event, context):
    token = os.environ['slack_app_token']
    if token == event['token']:
        approval = event['actions'][0]['value']
        build_name = event['original_message']['attachments'][0]
        build_name = build_name['actions'][0]['confirm']
        build_name = build_name['text'].split(' ')[-1]
        build_name = build_name[:-1]
        print(build_name)
        UserName = "admin"
        PassWord = os.environ['jenkins_api_key']
        InputId = "80adb01b62fc2c9465c11b6c53a29857"
        
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 
        }
        form_data = "json=%7B%22parameter%22%3A%20%5B%7B%22name%22%3A%20%22APPROVE%22%2C%20%22value%22%3A%20%22"+approval+"%22%7D%5D%7D"
        
        domain = '{your domain}'
        url = domain + 'job/'+build_name+'/'+get_job_num(domain, UserName,PassWord, build_name)+'/wfapi/inputSubmit?inputId=' + InputId     
        response = requests.post(url, headers=headers, auth=HTTPBasicAuth(UserName, PassWord), data=form_data)
        print(response.text)
        if response.status_code == 200:
            if approval == "YES":
                return {
                    "text": "Success Approve Build"
                }
            else:
                return {
                    "text": "Abort This Build"
                }
        else:
            return {
                "text": "Failed Approve Build"
            }
    else:
        return {
            "text": "Invalid Token"
        }

 

람다 구성이 끝났습니다.

 

이제 다음 게시글에서 API Gateway 구성 및 Lambda 연동을 해주고,

Slack에서 API Gateway 호출, 젠킨스 파이프라인에서 API Gateway 호출하는 법을 알아 보도록 하겠습니다.