Versuchen Sie, SlackBot mit Ruby x Sinatra auf AWS Lambda auszuführen

Konfiguration, auf die in diesem Artikel abgezielt werden soll

Untitled Diagram(1).png

① Führen Sie eine bestimmte Aktion in Slack aus. (* Slash-Befehl diesmal) (2) Starten Sie Lambda über das API-Gateway. ③ Führen Sie die in Lambda platzierte Funktion aus und geben Sie die Informationen zurück.

slackbot(2).gif

↑ Es sieht so aus wie ein Operationsbild. Dieses Mal werde ich SlackBot verschieben, der die aktuelle Temperatur eines bestimmten Bereichs zurückgibt.

Zielgruppe

Was ist Lambda?

AWS Lambda ist ein Computerdienst, mit dem Sie Code ausführen können, ohne einen Server bereitstellen oder verwalten zu müssen. AWS Lambda führt Code nur bei Bedarf aus und skaliert automatisch von wenigen Anforderungen pro Tag auf Tausende von Anforderungen pro Sekunde. Sie zahlen nur für die von Ihnen verwendete Rechenzeit - keine Gebühren, es sei denn, der Code wird ausgeführt. Mit AWS Lambda können Sie Code in jeder Anwendung oder jedem Back-End-Service virtuell ausführen, ohne dass eine Verwaltung erforderlich ist. AWS Lambda führt Code auf einer hochverfügbaren Computerinfrastruktur aus und verwaltet alle Ihre Computerressourcen, einschließlich Server- und Betriebssysteme, Systemwartung, Kapazitätsbereitstellung und automatische Skalierung, Codeüberwachung und Protokollierung. Ausführen. Sie müssen lediglich den Code in einer der von AWS Lambda unterstützten Sprachen angeben. (Zitat: Amazon offizielles Dokument)

Es ist schwer zu verstehen, ob es nur so ist, aber der Punkt ist, dass Sie keinen Server benötigen, um das Programm auszuführen.

Wenn Sie ein Programm ausführen möchten, dauert es normalerweise viel Zeit, einen Server zu kaufen und verschiedene Middleware zu installieren. In Lambda verwaltet AWS all dies, also Entwickler Es scheint, dass Sie sich nur auf die Erstellung des Quellcodes konzentrieren müssen.

Vorteile der Verwendung von Lambda

Bei einem SlackBot wie diesem halte ich Lambda für richtig, da er nicht immer nur bei Bedarf betriebsbereit sein muss.

Wenn die Implementierung so leicht wie SlackBot ist, ist die Bereitstellungsmethode mit Heroku usw. Standard, aber ich habe heutzutage das Gefühl, AWS zu verwenden.

Spezifikation

Sprache: Ruby2.5 Rahmen: Sinatra Infrastruktur: AWS Lambda

Ausgefülltes Formular: slack-bot-on-aws-lambda

Erstellen Sie SlackBot

Erstellen Sie zunächst den wesentlichen SlackBot.

Erstellen Sie ein Verzeichnis

$ mkdir slack-bot-on-aws-lambda
$ cd slack-bot-on-aws-lambda

Geben Sie die Ruby-Version an

# 2.Jede 5er Serie ist in Ordnung
$ rbenv local 2.5.1 

Installieren Sie Sinatra

$ bundle init

Generieren Sie eine Gemfile mit dem Befehl ↑ und bearbeiten Sie sie wie folgt.

./Gemfile


# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'sinatra'

Dann installieren Sie Gem.

$ bundle install --path vendor/bundle

Um den Vorgang zu überprüfen, werde ich eine Seite implementieren, die vorerst "Hello World!" Zurückgibt.

$ touch main.rb

ruby:./main.rb


require 'sinatra'

get '/' do
  'Hello World!'
end

Starten Sie danach Sinatra.

$ bundle exec ruby main.rb

[2020-09-21 20:47:35] INFO  WEBrick 1.4.2
[2020-09-21 20:47:35] INFO  ruby 2.5.1 (2018-03-29) [x86_64-darwin19]
== Sinatra (v2.1.0) has taken the stage on 4567 for development with backup from WEBrick
[2020-09-21 20:47:35] INFO  WEBrick::HTTPServer#start: pid=50418 port=4567

Standardmäßig wird Sinatra unter der Portnummer "4567" ausgeführt, greifen Sie also auf "[localhost: 4567](localhost: 4567)" zu.

スクリーンショット 2020-09-21 20.50.33.png

Erfolg, wenn "Hallo Welt!" Angezeigt wird.

Implementierte ein Programm, das Wetterinformationen zurückgibt

Wir werden ein Programm implementieren, das Wetterinformationen zurückgibt. Dies ist die Hauptfunktion des diesmal erstellten SlackBot.

Holen Sie sich den OpenWeather API-Schlüssel

https://openweathermap.org/ スクリーンショット 2020-09-21 20.54.33.png

Registrieren Sie sich als Mitglied auf der oben genannten Website und erhalten Sie einen API-Schlüssel.

スクリーンショット 2020-09-21 20.59.28_censored.jpg

Obwohl der Dienst in englischer Sprache verfasst ist, entfällt eine ausführliche Erläuterung, da er bis zu einem gewissen Grad intuitiv bedient werden kann. Wenn Sie es wirklich nicht verstehen, können Sie über Google so viele Artikel erhalten, wie Sie möchten.

Installiere verschiedene Edelsteine

Da für die zukünftige Verarbeitung einige Edelsteine erforderlich sind, installieren Sie sie sofort zu diesem Zeitpunkt.

./Gemfile


gem 'faraday'
gem 'rack'
gem 'rack-contrib'
gem 'rubysl-base64'
gem 'slack-ruby-bot'

Vergessen Sie nicht, die Installation zu "bündeln".

$ bundle install --path vendor/bundle

Erstellen Sie src / weather.rb

$ mkdir src
$ touch src/weather.rb

Erstellen Sie src / weather.rb und schreiben Sie wie folgt.

ruby:./src/weather.rb


require 'json'

class Weather
  def current_temp(locate)
    end_point_url = 'http://api.openweathermap.org/data/2.5/weather'
    api_key = #OpenWeather API-Schlüssel früher erhalten

    res = Faraday.get(end_point_url + "?q=#{locate},jp&APPID=#{api_key}")
    res_body = JSON.parse(res.body)

    temp = res_body['main']['temp']
    celsius = temp - 273.15
    celsius_round = celsius.round

    return "Die aktuelle Temperatur von Nerima#{celsius_round.to_s}Es ist ℃."
  end
end

Bearbeiten Sie main.rb.

ruby:./main.rb


require 'slack-ruby-client'
require 'sinatra'
require './src/weather'

Slack.configure do |conf|
  conf.token = #SlackBot-Token
end

get '/' do
  'This is SlackBot on AWS Lambda'
end

post '/webhook' do
  client = Slack::Web::Client.new

  channel_id = params['channel_id']
  command = params['command']

  case command
    when '/nerima'
    #Schrägstrich Befehl "/Wenn "nerima" ausgeführt wird, wird die folgende Verarbeitung ausgeführt.
      weather = Weather.new
      client.chat_postMessage channel: channel_id, text: weather.current_temp('Nerima'), as_user: true
      # 'Nerima'Sie können den Teil von ändern. Wenn Sie zu "Shinjuku" wechseln, sollte die Temperatur in Shinjuku zurückgegeben werden.
  end

  return
end

Lesen Sie den folgenden Artikel, wie Sie ein SlackBot-Token erhalten.

Referenz: [Erstellen eines Bots zur Verwendung im Arbeitsbereich](https://slack.com/intl/ja-jp/help/articles/115005265703-%E3%83%AF%E3%83%BC%E3%82% AF% E3% 82% B9% E3% 83% 9A% E3% 83% BC% E3% 82% B9% E3% 81% A7% E5% 88% A9% E7% 94% A8% E3% 81% 99% E3% 82% 8B% E3% 83% 9C% E3% 83% 83% E3% 83% 88% E3% 81% AE% E4% BD% 9C% E6% 88% 90) Siehe auch: API-Token-Generierung und -Regeneration (https://slack.com/intl/ja-jp/help/articles/215770388-API-%E3%83%88%E3%83%BC%E3%82 % AF% E3% 83% B3% E3% 81% AE% E7% 94% 9F% E6% 88% 90% E3% 81% A8% E5% 86% 8D% E7% 94% 9F% E6% 88% 90 )

Tatsächliche Funktionsprüfung

Es gibt einige Dinge, die Sie tun müssen, um SlackBot mit dem Befehl slash aufzurufen.

https://api.slack.com/apps/ スクリーンショット 2020-09-21 21.33.08.png Greifen Sie auf die URL oben zu und wählen Sie den entsprechenden Bot aus.

スクリーンショット 2020-09-21 21.37.35.png Im Menü auf der linken Seite befindet sich ein Element mit dem Namen "Schrägstrichbefehle". Wählen Sie es aus und klicken Sie auf "Neuen Befehl erstellen". スクリーンショット 2020-09-21 21.40.08.png Geben Sie jeden Artikel ein.

--Befehl: Beliebiger Schrägstrichbefehl. ――Dieses Mal gehen wir davon aus, dass die aktuelle Temperatur in Tokios Nerima Ward zurückgegeben wird, also verwenden wir "/ nerima", aber in Shinjuku Ward ist beispielsweise "/ shinjuku" in Ordnung. )

Klicken Sie unten rechts auf "Speichern", wenn die Eingabe abgeschlossen ist.

スクリーンショット 2020-09-21 21.53.38.png Geben Sie nach dem Erstellen des Schrägstrichbefehls "/ nerima" in den Kanal ein, in dem Sie den SlackBot hinzugefügt haben. Hoffentlich erhalten Sie eine Antwort von SlackBot wie das Bild. (Es ist auch möglich, das Bild und den Namen in den Einstellungen zu ändern.) スクリーンショット 2020-09-21 22.04.20.png Wenn etwas schief geht, sollte das Protokoll an das Terminal ausgegeben werden. Debuggen Sie daher entsprechend.

Bereitstellung bei AWS Lambda

Nachdem der normale Betrieb bestätigt wurde, ist er endlich für die Produktion mit AWS Lambda bereit.

Installieren Sie AWS CLI

Dieses Mal werden wir mit einem Tool namens "AWS CLI" bereitstellen. Wenn Sie es also noch nicht installiert haben, installieren Sie es.

$ brew install awscli

IAM-Benutzer erstellen

Erstellen Sie einen IAM-Benutzer, um die Bereitstellungsarbeit auszuführen. スクリーンショット 2020-09-21 22.11.08.png Gehen Sie zunächst zu "IAM" -> "Richtlinie" -> "Richtlinie erstellen" und fügen Sie die folgende Anweisung auf der Registerkarte "JSON" ein. スクリーンショット 2020-09-21 22.13.26.png

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "apigateway:*",
                "cloudformation:*",
                "dynamodb:*",
                "events:*",
                "iam:*",
                "lambda:*",
                "logs:*",
                "route53:*",
                "s3:*"
             ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Siehe auch: Minimal Deploy IAM-Richtlinie (https://rubyonjets.com/docs/extras/minimal-deploy-iam/)

スクリーンショット 2020-09-21 22.15.47.png Geben Sie den Namen und die Beschreibung der Richtlinie ein und klicken Sie auf "Richtlinie erstellen".

スクリーンショット 2020-09-21 22.17.27.png Gehen Sie anschließend zu "IAM" -> "Benutzer" -> "Benutzer erstellen", geben Sie ihm einen geeigneten Namen, aktivieren Sie "Zugriff nach Programm" und fahren Sie mit dem nächsten fort.

スクリーンショット 2020-09-21 22.17.47.png Wählen Sie die zuvor erstellte "Minimal Deploy IAM-Richtlinie" unter "Vorhandene Richtlinie direkt anhängen" aus und fahren Sie mit der nächsten fort.

スクリーンショット 2020-09-21 22.17.59.png

(Tags sind optional) Am Ende wird ein Bestätigungsbildschirm angezeigt. Wenn also keine Probleme auftreten, klicken Sie auf "Benutzer erstellen".

スクリーンショット 2020-09-21 22.18.13_censored.jpg Anschließend werden zwei "Zugriffsschlüssel-ID" und "geheimer Zugriffsschlüssel" ausgegeben. Bewahren Sie sie daher an einem sicheren Ort auf, wenn Sie die CSV-Datei herunterladen oder notieren.

AWS CLI-Einstellungen

$ aws configure

AWS Access Key ID #Zuvor erstellte Zugriffsschlüssel-ID
AWS Secret Access Key #Der geheime Zugriffsschlüssel, den Sie zuvor erstellt haben
Default region name # ap-northeast-1 
Default output format # json 

Wenn Sie im Terminal "aws configure" eingeben, werden Sie interaktiv nach verschiedenen Dingen gefragt. Geben Sie daher jeweils die erforderlichen Informationen ein.

Erstellen Sie verschiedene Dateien

Erstellen Sie nach dem Festlegen der AWS-CLI verschiedene Dateien, die für die Bereitstellung erforderlich sind.

ruby:./config.ru


require 'rack'
require 'rack/contrib'
require_relative './main'

set :root, File.dirname(__FILE__)

run Sinatra::Application

ruby:./lambda.rb


require 'json'
require 'rack'
require 'base64'

$app ||= Rack::Builder.parse_file("#{__dir__}/config.ru").first
ENV['RACK_ENV'] ||= 'production'

def handler(event:, context:)
  body = if event['isBase64Encoded']
    Base64.decode64 event['body']
  else
    event['body']
  end || ''

  headers = event.fetch 'headers', {}

  env = {
    'REQUEST_METHOD' => event.fetch('httpMethod'),
    'SCRIPT_NAME' => '',
    'PATH_INFO' => event.fetch('path', ''),
    'QUERY_STRING' => Rack::Utils.build_query(event['queryStringParameters'] || {}),
    'SERVER_NAME' => headers.fetch('Host', 'localhost'),
    'SERVER_PORT' => headers.fetch('X-Forwarded-Port', 443).to_s,

    'rack.version' => Rack::VERSION,
    'rack.url_scheme' => headers.fetch('CloudFront-Forwarded-Proto') { headers.fetch('X-Forwarded-Proto', 'https') },
    'rack.input' => StringIO.new(body),
    'rack.errors' => $stderr,
  }

  headers.each_pair do |key, value|
    name = key.upcase.gsub '-', '_'
    header = case name
      when 'CONTENT_TYPE', 'CONTENT_LENGTH'
        name
      else
        "HTTP_#{name}"
    end
    env[header] = value.to_s
  end

  begin
    status, headers, body = $app.call env

    body_content = ""
    body.each do |item|
      body_content += item.to_s
    end

    response = {
      'statusCode' => status,
      'headers' => headers,
      'body' => body_content
    }
    if event['requestContext'].has_key?('elb')
      response['isBase64Encoded'] = false
    end
  rescue Exception => exception
    response = {
      'statusCode' => 500,
      'body' => exception.message
    }
  end

  response
end

template.yaml


AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  SinatraFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      FunctionName: SlackBot
      Handler: lambda.handler
      Runtime: ruby2.5
      CodeUri: './'
      MemorySize: 512
      Timeout: 30
      Events:
        SinatraApi:
            Type: Api
            Properties:
                Path: /
                Method: ANY
                RestApiId: !Ref SinatraAPI
  SinatraAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: SlackBotAPI
      StageName: Prod
      DefinitionBody:
        swagger: '2.0'
        basePath: '/Prod'
        info:
          title: !Ref AWS::StackName
        paths:
          /{proxy+}:
            x-amazon-apigateway-any-method:
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SinatraFunction.Arn}/invocations'
                passthroughBehavior: 'when_no_match'
                httpMethod: POST
                type: 'aws_proxy'
          /:
            get:
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SinatraFunction.Arn}/invocations'
                passthroughBehavior: 'when_no_match'
                httpMethod: POST
                type: 'aws_proxy'
  ConfigLambdaPermission:
    Type: 'AWS::Lambda::Permission'
    DependsOn:
    - SinatraFunction
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref SinatraFunction
      Principal: apigateway.amazonaws.com
Outputs:
  SinatraAppUrl:
    Description: App endpoint URL
    Value: !Sub "https://${SinatraAPI}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

Ich werde hier weglassen, was jeder darstellt. (Weil dieser Bereich das offizielle aws-Dokument fast so verwendet, wie es ist) Siehe auch: aws-samples / serverless-sinatra-sample

Erstellen eines S3-Buckets

Da der AWS S3-Bucket im Voraus vorbereitet werden muss, erstellen Sie einen geeigneten S3-Bucket.

Referenz: So erstellen Sie einen Bucket für AWS S3

Bereitstellen

Führen Sie den folgenden Befehl aus.

$ aws cloudformation package \
     --template-file template.yaml \
     --output-template-file serverless-output.yaml \
     --s3-bucket #S3-Bucket-Name zuvor erstellt

Uploading to a3a55f6abf5f21a2e1161442e53b27a8  12970487 / 12970487.0  (100.00%)
Successfully packaged artifacts and wrote output template to file serverless-output.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /Users/Nutzername/Verzeichnisname/serverless-output.yaml --stack-name <YOUR STACK NAME>

Dann sollte automatisch eine Datei mit dem Namen "serverless-output.yaml" im Verzeichnis generiert werden. Führen Sie daher den folgenden Befehl basierend darauf aus.

$ aws cloudformation deploy --template-file serverless-output.yaml \
     --stack-name slack-bot \
     --capabilities CAPABILITY_IAM

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - slack-bot

Wenn "Erfolgreich" angezeigt wird, ist die Bereitstellung erfolgreich.

スクリーンショット 2020-09-21 22.49.32_censored.jpg

Wenn Sie zu "Lambda" -> "Funktion" wechseln, werden die zuvor bereitgestellten Inhalte angezeigt. Greifen Sie daher auf den unter "API-Gateway" beschriebenen API-Endpunkt zu.

スクリーンショット 2020-09-21 22.53.09.png

ruby:./main.rb


get '/' do
  'This is SlackBot on AWS Lambda'
end

Wenn "Dies ist SlackBot auf AWS Lambda" wie erwartet in der Anforderung get '/' in main.rb zurückgegeben wird, kann beurteilt werden, ob es ordnungsgemäß funktioniert.

Anforderungs-URL für Schrägstrichbefehle ändern

https://api.slack.com/apps/

スクリーンショット 2020-09-21 23.00.35_censored.jpg Kehren Sie zur Seite mit den SlackBot-Einstellungen zurück und ändern Sie die Anforderungs-URL von "Schrägstrichbefehle" in den gerade erstellten Endpunkt. (Https: //********.execute-api.ap-northeast-1.amazonaws.com/Prod/webhook ")

スクリーンショット 2020-09-21 23.06.41.png Schließlich gab ich wieder "/ nerima" in den Slack-Kanal ein und war froh, wenn die Antwort richtig zurückkam.

スクリーンショット 2020-09-21 23.07.45.png Wenn dies nicht funktioniert, sollte das Protokoll in CloudWatch ausgegeben werden. Debuggen Sie es daher entsprechend.

Nachwort

Danke für deine harte Arbeit!

Dieses Mal berührte ich AWS Lambda mit dem Thema, einen einfachen SlackBot mit Lambda auszuführen. Ich konnte die Größe von Lamda nicht wirklich erkennen, weil ich nicht viele Funktionen implementiert habe, aber ich denke, dass es ein sehr praktischer Service ist, wenn es gut genutzt wird.

Ich habe keine schwierigen Operationen durchgeführt, daher sollte es im Grunde funktionieren, wenn Sie das Verfahren befolgen, aber wenn etwas stecken bleibt, würde ich es begrüßen, wenn Sie in den Kommentaren darauf hinweisen könnten.

Recommended Posts

Versuchen Sie, SlackBot mit Ruby x Sinatra auf AWS Lambda auszuführen
Versuchen Sie, eine mit Quarkus erstellte App auf Heroku auszuführen
Erstellen Sie ein periodisches Programm mit Ruby x AWS Lambda x CloudWatch-Ereignissen
Einführung in Rspec mit Ruby on Rails x Docker
Veröffentlichen Sie die mit Ruby on Rails erstellte App
Ich habe mit Ruby On Rails ein Portfolio erstellt
Benachrichtigen Sie Slack of AWS-Rechnungen täglich mit Lambda für Ruby
Veröffentlichen Sie regelmäßig Bild-Tweets auf Twitter mit AWS Lambda + Java
Erstellen Sie einen SlackBot mit AWS Lambda & API Gateway in Java
Erstellen Sie AWS Lambda mit Quarkus
Als ich versuchte, das AWS SDK mit Ruby + Lambda zu verwenden, war "sam local" durcheinander.
Mit [AWS] CodeStar können Sie ein Spring (Java) -Projekt erstellen, das auf Lambda in nur 3 Minuten ausgeführt wird! !!
Installieren Sie Ruby mit pacman auf MSYS2
[Ruby on Rails] Leseversuch (: [],: Schlüssel)
Versuchen Sie, den Cloudera Manager mit Docker auszuführen
Ist Java unter AWS Lambda langsam?
Programmieren mit Ruby (unterwegs)
Hallo Welt mit AWS Lambda + Java
Versuchen Sie, Spring Boot auf Kubernetes auszuführen
Versuchen Sie, AWS X-Ray in Java auszuführen
Installieren Sie Ruby unter Ubuntu 20.04 mit rbenv
Führen Sie C-Binärdateien auf AWS Lambda aus
So erstellen Sie eine Ruby on Rails-Entwicklungsumgebung mit Docker (Rails 6.x)
Erste Schritte mit Micronaut 2.x ~ Native Build und Bereitstellung für AWS Lambda ~
So erstellen Sie eine Ruby on Rails-Entwicklungsumgebung mit Docker (Rails 5.x)