I tried ChatOps with Slack x API Gateway x Lambda (Python) x RDS

background

--There was a request to input Seed data (re-insert test data) into RDS of the verification environment (AWS) at any time. ――Since it is easiest to do from slack (it is easy to not depend on the development environment of the developer!), We created a mechanism to reflect the data from slack to RDS of the verification environment.

Technology stack used

Premise

For the sake of brevity, the following has already been done and we will proceed.

--Seed file already exists in S3 --I think there is a way to clone the Seed file from github, but since the implementation around authentication seems to be troublesome, I put the Seed file in S3 --The RDS instance to which Seed is sent already exists.

Overall picture

By executing the command from slack to the bot with the following feeling, the data is reflected in the verification environment and the completion notification is returned to slack. スクリーンショット 2019-12-18 11.29.36.png

Implementation

① Make lambda

Create a function

--Open Create Function from lambda to create a new function --Select Create from scratch --Create a new execution role --I want to access S3, so I will grant S3 access authority after creating it (such as Amazon S3 FullAccess)

スクリーンショット 2019-12-18 11.54.17.png

-** [Stumbling point] ** Since lambda accesses RDS, open the edit screen and specify the same VPC as RDS from Network at the bottom. --Even if you access RDS from lambda without setting this, it will time out ... スクリーンショット 2019-12-18 12.03.53.png

-** [Stumbling point] ** I installed Lambda in the same VPC as RDS to access RDS above, but since I can not access S3 from that state by default, VPC end for S3 referring to the following Make points -How to access S3 from Lambda in VPC

-** [Stumbling point] ** When returning the execution result from lambda to slack, lambda returns a message via the Internet, but for that purpose the specified VPC is a NAT gateway (or NAT instance) to the public subnet. You need to have, so please set by referring to the following --How do I allow internet access to my VPC's Lambda function? --If you do not do this, you will not be able to access the Internet from lambda and you will not be able to notify slack of the processing result (in lambda it will be timeout ..)

Write python code

As a process, it looks like this. The constant is like reading the value set in the environment variable of lambda.

lambda_function.py


import json
import logging
import os
import psycopg2
import boto3
import re
import urllib.request

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

#PostgreSQL connection settings
def get_pg_con():
  return psycopg2.connect(
    host=os.getenv('DB_HOST'),
    database=os.getenv('DB_NAME'),
    port=os.getenv('DB_PORT'),
    user=os.getenv('DB_USER'),
    password=os.getenv('DB_PASSWORD'))

#Get Seed files from S3
def get_seed_file_from_s3():
  bucket_name = os.getenv('S3_BUCKECT_NAME')
  file_name = os.getenv('S3_TARGET_FILE_NAME')
  s3 = boto3.client('s3')
  response = s3.get_object(Bucket=bucket_name, Key=file_name)
  return response['Body'].read().decode('utf-8')

#Run Seed file to RSD
def exec_seed():
  str_sql = get_seed_file_from_s3()
  conn = get_pg_con()
  cur = conn.cursor()
  cur.execute("BEGIN")
  #If you insert the file obtained from S3, the SQL in the file will be executed from above.
  cur.execute(str_sql)
  conn.commit()
  cur.close()
  conn.close()

#Reply to slack
def post_message_to_channel(channel, message):
  url = "https://slack.com/api/chat.postMessage"
  headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer {0}".format(os.getenv('SLACK_BOT_USER_ACCESS_TOKEN'))
  }

  data = {
    "token": os.getenv('SLACK_BOT_USER_ACCESS_TOKEN'),
    "channel": channel, #Notify the channel that executed Seed
    "text": message,
  }
  req = urllib.request.Request(url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST")
  with urllib.request.urlopen(req) as response:
    #Write the execution result in the log
    response_body = response.read().decode("utf-8")
    logger.info(response_body)

#Check the token sent when slack hits lambda
def is_verified_token(event):
  token = event.get("token")
  if token != os.environ["SLACK_BOT_VERIFY_TOKEN"]:
    return False
  return True

#Check if you put Seed execution keyword in slack
#This time"run"Execute Seed if the wording is included
def is_mached_pattern(text):
  pattern = r"run"
  result = re.search(pattern, text)
  if result:
    return True
  return False

#Entry point
def lambda_handler(event, context):
  #For the time being, plunge the request contents into the log
  logging.info(json.dumps(event))

  #Authentication of Slack's Event API
  if "challenge" in event:
    return event["challenge"]

  #Check token
  if not is_verified_token(event):
    logger.info("token is not verified!!!")
    return "OK"

  target_channel = event.get("event").get("channel")
  #In the message received from slack"run"Returns INFO information if there is no wording
  request_text = event.get("event").get("text")
  if not is_mached_pattern(request_text):
    post_message_to_channel(target_channel, "*[INFO]*Write how to use lightly:muscle:")
    return

  post_message_to_channel(target_channel, "I'll do it!")

  try:
    exec_seed()
    post_message_to_channel(target_channel, "Has completed!:rocket:")
  except Exception as e:
    logger.info(e)
    post_message_to_channel(event.get("event").get("channel"), e)

--This time, I want to access RDS (assuming PostgreSQL), so I need a library called psycopg2. Except for the standard library that Python has, it is necessary to zip it together and upload it to lambda, so refer to the following and zip the above Python file and psycopg2 in the local environment and upload it to lambda.

--When uploading with zip, specify the entry point to be executed at lambda startup in handler with file name.method name. --You can see that the uploaded file contains psycopg2. スクリーンショット 2019-12-18 12.22.05.png

② Make API Gateway

--In order to execute lambda from slack, it is necessary to access via API Gateway, so create API Gateway --At this time, API Gateway and lambda will also be linked. ――Specifically, I think it is very easy to understand if you refer to the following -[Try ChatOps with Slack and Lambda Step 2: Create API Gateway](https://qiita.com/yasuabe2613/items/6219d243ffcfe7690e78#%E3%82%B9%E3%83%86%E3%83%83 % E3% 83% 97% EF% BC% 92-api-gateway-% E4% BD% 9C% E6% 88% 90)

--The created API Gateway tests against lambda and returns a response, which is ready.

③ Make a slack app

--Create an app for bots from https://api.slack.com/apps --At this time, we will also link slack and API Gateway. --The specific procedure is Slack of [AWS (API Gateway + Lambda (Python)) + Bot creation using Slack API](https://nmmmk.hatenablog.com/entry/2018/10/10/001548) The app creation is very easy to understand

④ Check the operation

――With the following feeling, hit the bot from slack and get a reply and you're done! --Invite the bot to the target channel and type the command (this time I made a bot named @ genkan-dev-seed)

スクリーンショット 2019-12-18 11.17.53.png

Impressions

――By installing lambda in a specific VPC, I stumbled upon various things around the network (basic important!) .. ――If you can execute it from slack, it is very convenient because there is no environment difference for each executor!

Other references

Around psycopg2 (where Seed is executed from Python to RDS)

-I tried connecting to PostgreSQL with Python -Python sample that executes the contents of the SQL file given as an argument to the PostgreSQL DB -I tried throwing a variable SQL statement from Python code to PostgreSQL

Cooperation between slack and lambda

-Slack app_mention specifications (official)

Recommended Posts

I tried ChatOps with Slack x API Gateway x Lambda (Python) x RDS
LINE BOT with Python + AWS Lambda + API Gateway
I tried to make "Sakurai-san" a LINE BOT with API Gateway + Lambda
I tried fp-growth with python
I tried scraping with Python
I tried scraping with python
I tried hitting the API with echonest's python client
Quickly take a query string with API Gateway-> Lambda (Python)
I tried follow management with Twitter API and Python (easy)
Create API with Python, lambda, API Gateway quickly using AWS SAM
[AWS] Create API with API Gateway + Lambda
I tried web scraping with python.
I tried running prolog with python 3.8.2.
I tried SMTP communication with Python
I made a Twitter Bot with Go x Qiita API x Lambda
I tried to summarize everyone's remarks on slack with wordcloud (Python)
[Python] I wrote a REST API using AWS API Gateway and Lambda.
LINE BOT (Messaging API) development with API Gateway and Lambda (Python) [Part 2]
Wrangle x Python book I tried it [2]
Simple Slack API client made with Python
I tried scraping Yahoo News with Python
I tried sending an email with python.
I tried non-photorealistic rendering with Python + opencv
I tried using UnityCloudBuild API from Python
I tried a functional language with Python
I tried recursion with Python ② (Fibonacci sequence)
Wrangle x Python book I tried it [1]
Easy REST API with API Gateway / Lambda / DynamoDB
#I tried something like Vlookup with Python # 2
I tried to delete bad tweets regularly with AWS Lambda + Twitter API
I tried to get the authentication code of Qiita API with Python.
I tried to get the movie information of TMDb API with Python
I tried hitting Mastodon API with Ruby (Faraday) / Python (Pycurl) / PHP (Curl)
I tried "smoothing" the image with Python + OpenCV
[AWS SAM] Create API with DynamoDB + Lambda + API Gateway
View images on S3 with API Gateway + Lambda
I tried "differentiating" the image with Python + OpenCV
I tried "License OCR" with Google Vision API
I tried L-Chika with Raspberry Pi 4 (Python edition)
I tried using mecab with python2.7, ruby2.3, php7
I tried function synthesis and curry with python
I tried to output LLVM IR with Python
I tried "binarizing" the image with Python + OpenCV
Sample to send slack notification with python lambda
I tried running faiss with python, Go, Rust
I tried to automate sushi making with python
[AWS] Try tracing API Gateway + Lambda with X-Ray
I tried playing mahjong with Python (single mahjong edition)
Export RDS snapshot to S3 with Lambda (Python)
I tried connecting AWS Lambda with other services
I tried "Receipt OCR" with Google Vision API
I tried running Deep Floor Plan with Python 3.6.10.
I tried sending an email with SendGrid + Python
Amazon API Gateway and AWS Lambda Python version
[Python] Mention to multiple people with Slack API
I tried to automate internal operations with Docker, Python and Twitter API + bonus
Try implementing a Cisco Spark bot with AWS Lambda + Amazon API Gateway (Python)
I tried to find out how to streamline the work flow with Excel x Python ②
I tried to find out how to streamline the work flow with Excel x Python ④
I tried to implement Minesweeper on terminal with python
I tried to get started with blender python script_Part 01