sironekotoroの日記

Perl で楽をしたい

Perl の自作モジュールを AWS Lambda 上で Perl 5.34 で動かす

とりあえず満足

前回の続きです。

sironekotoro.hateblo.jp

自分の中では以下の要求が叶えられておらず不完全燃焼のままでありました。

  • Perl 5.32 の Lambda Layer を利用して自作モジュール含め外部モジュールを動かしたい。

    • 前回はカスタムランタイムから起動させた Perl 5.16.3 だった。

    • 特に Perl 5.32 じゃなければいけないとか、 Perl 5.16.3 だと困るという事情は無い。

      • 新しい Perl で動かしてみたい!という強い気持ちです。
  • https に通信したい。

    • できるよねーって思って軽い気持ちで AWS Lambda 上から use HTTP::Tiny して Yahoo! Japanhttps://www.yahoo.co.jp/) のページを get したらエラーが出た。

      • IO::Socket::SSLNet::SSLeay が無いっていわれる。が、ランタイムにインストールしてもエラーが出た。
    • 阿部寛のホームページ(http://abehiroshi.la.coocan.jp/)は get できた。http だから。

  • 相変わらず Web コンソールから操作するが、左側のファイル一覧ペインにモジュールのフォルダが入ってるのがなんとなく嫌だったので、Lambda レイヤーにまとめたかった。

    • 好みの問題です。

    • 好み以外にも、コードソース右上の「アップロード」からアップする zip ファイルが 3MB 超えたあたりでコードソースの画面での編集ができなくなります。実行は可能。

      • aws cli 使うのが普通?なのかなぁ。だからあんまり気にされてないと思う。

こんな方法で動かしました

基本は前回と同じ、なのですが書いてきます。

誰のためって 2021 年の GW 前の自分、数日後、数ヶ月後の自分のためです。

  1. AWS Lambda のページ右上の「関数の作成」から関数作る。

    f:id:sironekotoro:20210522235858p:plain

  2. 以下を選択・入力。

    1. 関数の作成: 一から作成

    2. 基本的な情報

      • 関数名: 任意の名前(例では perl5_34_https

      • ランタイム: Amazon Linux 2 でユーザー独自のブートストラップを提供する

    f:id:sironekotoro:20210523000620p:plain

  3. Lambda 関数のページが出てきたら、ページの一番下にあるレイヤー部の「レイヤーの追加」をクリックする。

    f:id:sironekotoro:20210523001546p:plain

  4. 以下を選択・入力

    • Layer source: ARN を指定

    • ARN: arn:aws:lambda:ap-northeast-1:445285296882:layer:perl-5-34-runtime-al2:1

    設定が終わるとこうなる。

    f:id:sironekotoro:20210523003221p:plain

    • リージョンが東京(ap-northeast-1)以外の場合は shogo82148 さんのこちらを参照。最近(2021/5/20)発表になった Perl 5.34 が早くもある!ので使わせてもらう。

    github.com

  5. コードソース部の左側にあるファイル一覧から初期で存在する3つのファイルを右クリック -> Delete で削除する。

    • bootstrap.sample
    • hello.sh.sample
    • README.md

    f:id:sironekotoro:20210523003800p:plain

    • 削除せずとも良いけど使わないので・・・
  6. hello.pl を作成する

    • なんで hello.pl かというと、最初に選択したカスタムランタイムでのハンドラ(プログラムを動かすプログラム、Lambda 実行時に動くファイルとサブルーチン)名が hello.handler になっているから。

    • 気に入らない場合はランタイム設定の編集ボタンから変更可能。

      • ここでは変えないでいく。
    • ファイル名.サブルーチン名 という命名ルール。

    f:id:sironekotoro:20210523004322p:plain

    • 左側の先ほどファイルを削除したところを右クリックして New File を選択する。

    • ファイル名は hello.pl 。ハンドラで変えた場合にはそれに相当するファイル名にする。

    • コードはこんな感じで。特別なことはせず、とりあえず動くか確認。最後の 1; を忘れないこと。

    gist.github.com

    • コードを書いたら、CTRL + s でファイルを保存。

    • そして、上にある Deploy ボタンを押す!これを押さないと反映されないので注意。ボタンの右側には Change not deployed と出て警告してくれる。

    f:id:sironekotoro:20210523005629p:plain

    • Deploy が成功すると ボタンが押せなくなり、右側に緑色で Changes deployed と表示される。

    f:id:sironekotoro:20210523005737p:plain

  7. テスト

    • Test ボタンを押すと、まず初期のテストの名前をつけるよう画面が表示される

    • イベント名: firstTest または任意の名前。文字の利用制限がある

    • イベント名を入れたら右下の 作成 ボタンを押してテストを作成する

    • コードソースの画面に戻るので、Test のボタンを押す。Response が Return の内容になり、以下の画面になればok

    f:id:sironekotoro:20210523010242p:plain

  8. http のサイトへのアクセスを試す

    • まず、http のサイトにアクセスできるかやってみます。

      • 阿部寛さんのサイト、2021 年 5 月 23 日現在は文字コードが Shift JIS でした。それに合わせで decode 入れてるのと、タイトルタグの中身をとるときに正規表現の名前付きキャプチャを使っています。

    gist.github.com

    f:id:sironekotoro:20210523013446p:plain

  9. https のサイトへのアクセスを試す

    gist.github.com

    で、この時点ではこのエラーが出ます。エラーコード 599。タイトルの取得に失敗しています。

    f:id:sironekotoro:20210523014722p:plain

    実際どういう応答かなー?と、レスポンスの中身を見てみることにします。

    return で返しているハッシュリファレンスに1行加えます content => $res->{content},

    はい、ここで HTTPS のサイトにアクセスするためのモジュールである IO::Socket::SSLNet::SSLeay が無いよー、というエラーであることが判明するわけです。

    f:id:sironekotoro:20210523015559p:plain

外部モジュールを入れた圧縮ファイルを作る

ここに辿り着くまでが数日かかったんですが、数日彷徨ったり勘違いした記憶はうちだけのものとして、あっさり解決策書いていきます。

全てはここ Run in Local using Docker に書いてあるんですが、せっかくなのでこのままやっていきます。

ここで先に追加した Lambda Layer と同じバージョンの Docker Image を利用して、モジュールを手元の環境にインストールし、それを zip で圧縮して Lambda のレイヤーとして登録し利用します。

うわ、俺が数日わからなかったところがなんと1行で。

  1. 手元に作業用の適当なフォルダを作ります。

    今回は lambda-layer-perl-https という名前のフォルダにしました。

  2. フォルダの中に以下のファイルを作成します

    • cpanfile

    • install.sh

      • install.sh には実行権限を付けておきます $ chmod +x install.sh

    gist.github.com

    f:id:sironekotoro:20210523021314p:plain

  3. フォルダの中に入ったら、以下のコマンドをターミナルに貼り付けて実行します

    $ docker run --rm -v $(PWD):/var/task shogo82148/p5-aws-lambda:build-5.34.al2 ./install.sh

  4. 終わると、作業用フォルダの中に local というフォルダが作成されています。これを zip で圧縮します。

    今回は作業用フォルダの中で以下のコマンドで圧縮ファイルを作成します。

    $ zip -r ../lambda-layer-perl-https.zip local/

    作業用フォルダの上の階層に lambda-layer-perl-https.zip という zip ファイルが作成されます。

圧縮ファイルを Lambda Layer として登録する

  1. AWS Lambda のページからレイヤーのページに移動する

  2. 右上の レイヤーの作成 ボタンを押す

  3. 以下を選択・入力

    • 名前: lambda-layer-perl-https

    • zip をアップロード のラジオボタンを選択

    • 「アップロード」ボタンから、作成した zip ファイルを選択してアップロード

      f:id:sironekotoro:20210523032417p:plain

    • アップロードできたら、右下の「作成」ボタンを押す

  4. レイヤーが作成されるので、作成したバージョンの ARN をコピーする

    f:id:sironekotoro:20210523032417p:plain

AWS Lambda にレイヤーを追加する

ここは Perl のレイヤーを追加した時と同じです。エラーが出た Lambda のページに戻りレイヤーを追加します。

f:id:sironekotoro:20210523033333p:plain

パスを追加する

追加した Lambda Layer のモジュールは、Lambda 上のパスからは /opt/local/lib/perl5/ にあるように見えます。

このため、use lib qw(/opt/local/lib/perl5); という 1 行を追加してモジュール検索パスに加えます。

f:id:sironekotoro:20210523033852p:plain

再度実行する

デプロイを忘れずに。再度 Test ボタンを押して Yahoo のページタイトルが取れていれば成功です。お疲れ様でした。

f:id:sironekotoro:20210523034011p:plain

おまけ

GitHub にあるモジュールは cpanfile に required 'git://github.com/〜' と書くことでもいけそうなんですが、ログ上はなんか失敗しているんですよね・・・

ただ、cpanfile じゃなくて install.sh の方に cpanm --notest --local-lib local --no-man-pages --installdeps 'git://github.com/〜 って書くとインストールが終わったりします。

まぁ、もともと cpanm は git からのインストールはサポート外なので、そのつもりで。

何が時間かかったか

Lambda の環境を入れた Docker コンテナである lambci/lambda を使って作ったモジュールを、Perl 5.32 のレイヤーで動かそうとしていた。

なお、XSの依存のないモジュールであればこれでも動く(ので問題の切り分けが遅れに遅れた)

動かして学ぶ!Slackアプリ開発入門 でハマったところ

動かして学ぶ!Slackアプリ開発入門

いやー、やっぱ書いてある通りに動くって助かる、ありがたいよなぁという本です。

(まだ 30% 程度だけど)

この本では node.js と Slack の公式フレームワークの Bolt を使って Slack アプリというか、ボットを作っていきます。

リスト4-4

const app = new App({
    token: process.env.SLACK_BOT_TOKEN,
    signingSecret: process.env.SLACK_SIGNING_SECRET
});

その次のところ、このトークンを環境変数に設定するところ、export が必要では?

・・・と思ったら、これはシェル変数ってやつだった。

だから同じコンソールで作業してね、と書いてあるのか。なるほど。

まだ全然知らないことばかりだわ。

まだ読み終えてないですが

「Chapter 5 ランチのお店を選んでくれるボットを作ろう」に入るところ まで進みました。

・・・が、いつも通り我慢できずに Slack のスラッシュコマンドからの POST を Perl(Mojolicious::Lite) で受けて返す、その次に API Gateway + Lambda(Perl Layer) で動かす、などでこう、満足してしまいました。

ただまぁ、この本を読み終えたわけではなし。

この先、この本で書いてあるアイデアから、また何かをしてみたい・・・というのが生まれてくるはず。

ということで読み進めていきます。

Perl の自作モジュールを AWS Lambda で動かす

GWずっとこれやってた

平年であれば帰省して甥っ子姪っ子と遊んだり・・・いや、もう遊んでもらえない歳になってしまったか。

まぁ、今年もコロナ禍で帰省するわけにはいかない感じなので、Perl の自作モジュールを AWS Lambda で動かすってのをやってました。

最終日にしてやっと動くようになったので、自分用の備忘録で書いておきます。

こんな感じで動かしました

shogo82148.github.io

ここに書いてあるまま +α です。

+α 分を書いていきます。

  • bootstrapinstall.sh には chmod +x で実行権限をつけておく。

  • Github からスクリプトを入れる際には、パッケージのビルドスクリプトに git を入れておく。

  • cpanm は GitHub からのインストールを正式にサポートはしていないが、 git://github.com/〜 でいける。うちの場合にはこう書きました。

#!/bin/sh
yum install -y gcc git perl-App-cpanminus
cpanm -l local --notest --installdeps .
cpanm -l local --notest git://github.com/sironekotoro/Zengin-Perl.git

あと、最後に圧縮して AWS Lambda に上げるところですが

docker run --rm -v "$PWD":/var/task lambci/lambda-base ./install.sh
zip -r ../dist.zip .

zip -r ../dist.zip . で、 dist.zip の後に . スペースとドットが必要です。まぁ、その場でわかるとは思うけど(一瞬わからなくて???ってなった人)

そして、圧縮した zip ファイルですが、AWS Lambda のここからアップロードします。コード書くところの右上の「アップロード元」ってところ。

f:id:sironekotoro:20210509132706p:plain

同じファイル名で何か書いてある場合には上書きされます。

アップロードするとこんな感じになります。圧縮されたファイルが展開されて左側に色々と増えてます。

f:id:sironekotoro:20210509133741p:plain

なお、この方法で動かす場合には、Lambda Layer に追加の Perl ランタイムは不要です。

ランタイムは「カスタムランタイムを利用」にしておきます。

f:id:sironekotoro:20210509133002p:plain

ハンドラは hello.handler としていますが、この場合、Lambda 起動したときに動く Perlスクリプトhello.pl 内の handler サブルーチンです。

なんでこんなに時間がかかったのか

  1. AWS Lambda で Perl を動かすには、Perl の Lambda Layer が必須だと思っていた。が、これがどこにも書いていない、完全な思い込み。不要だった。

    自分の思い込みで、これだけで 3 日くらい費やした気がします。

    カスタムランタイムをアップロードしつつ、Perl のランタイムレイヤーを追加したりしてた。

  2. 自作モジュールをインストールするのに当初は SSH でのインストールをやろうとしていました。

    が、そうすると Docker イメージに SSH秘密鍵を設定する必要があり、それをするのに手間取りました。しかし、最終的には cpanm git://〜 の形で解決。

  3. XS利用モジュールがうまく動かなかった。

    自作のモジュールでは Function::ParametersFile::Slurp を利用していましたが、これを検索パスから辿ることができず、またこれから依存しているモジュールが見つからない、ということで難儀しました。

    どうも、XS という C 言語のバイナリを利用しているモジュールがうまく動いていないことに気づきました。

    これに関しては、自作モジュール側を改修して、これらのモジュールを外しました。

    テストを書いていたおかげで、安心して書き直すことができました。

  4. AWS Lambda 用にモジュールをローカルにインストールする為に使う lambci/lambda と、AWS Lambda に追加する Perl Runtime Leyer の役割を理解しておらず、混乱した

  5. というか、今回の方法でインストールされる Perl は 5.016003 なんだけど、どういう方法で入っているのかわからない。標準モジュールのはずの Data::Dumper も明示的に cpanfile に書かないとダメ。Perl Runtime Leyer は Perl 5.032 で標準モジュールは普通に利用できる。

他にもまぁ、アホだ間抜けだ注意不足だなどなど、色々あるんですが、なんとか動きました。

多分、このエントリにも勘違いが入ってるんだろーなーと思います。

動機

AWS でLambda をどうこうっていうと、まぁ普通はサポートしている言語のものが多いです。当たり前ですが。

そこで、Perl を動かしてやろうじゃないか、ってのが一つ。

次に、コンソールから aws cli 使ってアップロードってのが常道で多数派だとは思うのですが、であればこのWebコンソールからもできるはずで、そちらで動かしてみたい、というのが一つ

なお、本来の目的は全銀コード検索を Slack のスラッシュコマンドからやりたい!ってやつだったのですが、先週社内勉強会でこの話したところ「herokuの方が向いてんじゃない?」とのことだったので、そりゃそうだと納得。そのうちherokuで動かしたいと思います。

前に一回やったんで、また過去の自分のブログ記事が助けになるはず。

GWの終わりに

カレンダー通りだったんですが、とはいえ随分な時間を費やしましたわ。

でも、こうやってまとめると2600文字ちょっと。1週間前の自分に教えてあげたいー、そしたらもっと前に進むことできたのにー

Perl入学式 オンライン 2021 第1回お疲れ様でした

Perl入学式 オンライン 2021 第1回

受講された方、サポーターの方、お疲れ様でした。 講師の人です。

今回は Windows の方には事前に環境構築をお願いしており、おかげで従来の第 1 回の範囲を超えて四則演算まで到達することができました。

環境構築が間に合わなかった方、5月中旬に予定されている第 2 回まで時間があります。環境構築にチャレンジしてみませんか?

以下のテキスト、動画、そして質問等があれば Discord で Perl入学式のサポーターが回答します。

github.com

www.youtube.com

discord.com

また、講義途中でわからなくなってしまった方、 Discord で質問いただければ、サポーター陣が回答します。

ぜひ質問してください。

過去の第1回エントリ

sironekotoro.hateblo.jp

sironekotoro.hateblo.jp

sironekotoro.hateblo.jp

sironekotoro.hateblo.jp

GUICUI

従来利用しているマウスとファイル・フォルダを操作する GUI と異なり、キーボードとコマンドで操作する CUI は戸惑うことも多いと思います。

とはいえ、プログラムを学ぶときに CUI は(今のところ)避けて通ることができません。

今回の第 1 回で、普段の GUI で行っているようなファイル作成、移動・名前変更、コピー、削除、フォルダ作成、フォルダ削除ができるようになりました。

これらのコマンドとプログラム(もちろん Perl も)を組み合わせることで、GUI では手間のかかることも簡単にできるようになります。

もちろん、初心者の方が「簡単に」できるようになるまでは時間が必要ですが、時間をかけて学べばできるようになります。

例えば、フォルダの中にあるファイル名の先頭に定型の文字、例えば「処理済_」をつけるとか・・・GUI でこれをやるとしたら結構大変だと思うんですよね。

・・・ってことで適当に課題を思いついてしまったので、適当に実装してみましたがこんな感じです。

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;

# add_done.pl
# このプログラムと同じフォルダにあるファイルを対象にする
# sample ってついているファイル名のファイルの先頭に 処理済み_ という
# 提携文をつける
opendir my $DH , '.' or die;
for my $file (readdir $DH){
    next if $file !~ /sample/;

    my $newfile = "処理済み_$file";
    system "mv $file $newfile";
}
closedir $DH;

・・・無理矢理 Perl で処理した感アリアリなのですが、まぁそこはともかく。

変更前

f:id:sironekotoro:20210426005557p:plain

変更後

f:id:sironekotoro:20210426005553p:plain

20 個くらいであればまぁ、手でやるのとプログラム書くので同じ時間くらいだとは思うんですが、10000 個とかになると手でやってられないですよね。

もちろんファイル変更専用のツールもあるのですが、プログラム学ぶとそれ(ファイル名変更)以外のこともできるので、応用の範囲は広いです。

放課後ミニコーナーや Discord で質問・やりたいことをお待ちしてます

今回は「Twitter のフォロワー数調査を行いたい」という要望がありました。

これを実現するには、もちろん人間が頑張るってのもあるんですが、プログラムで頑張ってもらうというのが現実的だと思います。

Twitter API 使って、フォロワーのIDをカウントするのが普通のやり方でしょうか。

API というのはプログラムからアプリケーション(ここではtwitter)の情報を取得する際の窓口、くらいに思ってください。

developer.twitter.com

このAPI を使うには、Twitter に利用申請が必要です。

dev.classmethod.jp

www.itti.jp

Twitter API を利用できるようになったら、Perl のモジュールを利用して情報を取得する、っていう感じです。

metacpan.org

これらは Perl 入学式の範囲ではないですが、こういう手順がありますよーという感じで、わかる範囲で回答できます。

世の中には、たくさんのツールがあります。

自分が欲しいツールを誰かが先に作っていればいいのですが、なければ作るしかありません。その手助けができれば幸いです。

オンライン第 2 回

5 月中旬くらいを予定しています。

次回は以下を予定してますが、変わるかも知れません。配列くらいまでいけるかな?

  • 文字列連結
  • 標準入力
  • 条件分岐「if 文, else 文」
  • 論理演算子「&&(かつ), ||(または)」

開催日は公式アカウントや Discord で告知します。

Perl入学式 2021 始まります! & Perl で 画像を自動トリミングする

Perl 入学式 2021 始まります!

前回更新が 4 月 2 日だったので、3 週間ぶりくらいですか。おひさしぶりです。

ブログも書かずに何をしていたかというと、2021 年度 Perl 入学式の準備をしておりました。

4 月 24 日です!

perl-entrance.connpass.com

2021 年度は、2019 年度までのように手元の PC に Perl をインストールして学習する方法をとります。

macOS ユーザであれば、そのままシステムにインストールされている Perl を利用して学習を進めます。

Windows ユーザの方は以下の動画リストとマニュアルを参考にインストールを行ってください。

github.com

www.youtube.com

うまくいかない場合などには、Perl 入学式の Discord で質問を受けます。活用ください。

Discord の招待リンクです

皆様の参加をお待ちしております!

Perl で画像を自動トリミングしたい

以下のような画像を大量にトリミングする必要が出てきました。これは 1920 x 932 のサイズの画像です。

f:id:sironekotoro:20210420192254p:plain

この、真っ白い部分だけを別のファイルにして抜き出したい!という要望です。要望を出したのは自分ですが・・・

1. 素直に画像ソフトを使って抜き出す

フリーで利用できる GIMP という画像編集ソフトがあります。

www.gimp.org

何冊か本も出ており、うちも下の本を手元に置いています。

GIMP を利用して 1 枚 1 枚心を込めて画像を抜き出していくのも一つの方法です。

が、ちょっと自分には辛い・・・今回だけで 200 枚以上処理する必要あるし。

BIMP というソフトを利用することで 一連の処理をバッチ処理のようにつなげることもできます。

バッチ処理といえば、macOS に入っている Autometer と プレビューの組み合わせでもいけるのかな・・・(思いつき

が、ここはせっかくなので Perl でやってみます。

2. Perl + ImageMagick

Perl で画像を扱う、というかプログラムから画像を扱うときには ImageMagick というソフトを使うのが定番とされていました。

imagemagick.org

が、この ImageMagick は多機能であるが故にインストールが大変なソフトとしても知られています。

うちも何回か挫折しています。

最近だったら Docker や、macOS であれば homebrew 使って入れるのがいいかも知れません。

また、手元で動かすにはいいのですが、世界に公開するサービスに組み込む際には脆弱性に気をつける必要があります。以下は報告されている脆弱性のリストです。

jvndb.jvn.jp

とにかく、 ImageMagick さえ安定して入っていれば、 Perl から ImageMagick を扱うモジュールを通して操作することができます。

しかし今回はこれを使わずにやります。

3. Perl + Imager

インストール&動作確認テスト的なやつ

Perl の画像処理モジュールに Imager というのがあります。これを使います。

metacpan.org

いつものように cpanm Imager でインストール。

SYNOPSYS みて、ふむふむって感じで自分で試してみます。お手軽そうな画像のサイズ縮小をやってみます。

さっきの画像と同じ場所にスクリプト置いて実行します・・・

あっさり成功しました。縦横のサイズが半分になってます。

input.png : 1920x932
output.png : 960x466

ピクセルを指定して切り抜き

では本題。

GIMP で画像を拡大して拡大してルーラーで計ったところ、横(x軸)の白い部分は 631 ピクセルから 1289 ピクセル目までということがわかりました。

縦(y軸)は 932 ピクセルでフルに利用しています。

この情報をもとに抜き出してみます。

こちらもあっさり成功です。きれいに白い所が抜きだせたようです。速度も 1 枚 0.2 秒ほどで申し分なし。

input.png : 1920x932
output_imager_manually_crop.png : 658x932

自動で切り抜き( Imager::Trim

さて、ここでやっぱり楽をしたいなーってなります。

いちいち、画像の部分だけピクセルを測るのが面倒だ、と。このような「よくある要望」は実装されていることが多いです。

実際、Imager::Trim というのがあるんですが、当初うちの環境ではうまく動きませんでした・・・

しかし、このブログを書くにあたって色々検証した結果、fuzz の値を調整し、背景色の情報 color の引数をちゃんと渡すことで警告なしで動くことが判明しました。

# 動く
my $color_cropped_img = $cropped_img->trim( fuzz => 7, color => $color );

# エラーは出るが動く
my $color_cropped_img = $cropped_img->trim( fuzz => 7 );

# エラーは出ないが、切り抜きは失敗する
my $color_cropped_img = $cropped_img->trim( fuzz => 6, color => $color );

ただし遅い。1 枚 10 秒くらいかかります。

input.png : 1920x932
    trim_top:0
    trim_bottom:932
    trim_left:631
    trim_right:1289
output_imger_trim.png : 658x932

自動で切り抜き( Imager::Filter::Autocrop

他のモジュールを探したところ Imager::Filter::Autocrop を見つけました。

こちらは 1 枚 3 秒ほど。この方法を取ることにしました。

input.png : 1920x932
output_imager_filter_autocrop.png : 658x932

md5 で雑に確認してみましたが、どのファイルも同じバイナリのようです。

$ md5 output*
md5: output: Is a directory
MD5 (output_imager_filter_autocrop.png) = ab744b9263aada986381630da980b1f9
MD5 (output_imager_manually_crop.png) = ab744b9263aada986381630da980b1f9
MD5 (output_imager_trim.png) = ab744b9263aada986381630da980b1f9

ということで、画像の抜き出しをやってみた記事でした。

困ったら情報を整理して聞いてみよう!

誰かに聞くつもりで内容をまとめると、そこで気づきが出て解決につながっちゃうというね。

ちなみに、解決しなかったら Perl 入学式の Discord で聞くつもりでおりました。

Perl を使った AWS Lambda を API Gateway に登録してブラウザから Hello, World する

前回までのあらすじ

sironekotoro.hateblo.jp

AWS Lambda で Perl を動かすことに成功した sironekotoro.

しかし、それは AWS Lambda 上で「動かしただけ」であり、なんのアクションもインプットもないものだった・・・

ってわけで

・・・いや、アクションもインプットもあったら Hello, World じゃないやろ。

今回は AWS Lambda と Amazon API Gateway を組み合わせてみます。

ブラウザでアクセスすると Hello, World! って出てくる、そういうのを目指します。

AWS Lambda の準備

なお、2021年04月02日時点での画面での記述です。

前回と同じ部分ありますが、まぁ、そういうものだと思ってお付き合いください。

ただし、2ヶ月後も同じ設定項目が、同じ名前で、同じ画面にあるかどうか・・・

  1. AWS Lambda のページ右上にある「関数の作成」をクリックする

  2. 関数の作成

    • 「1から作成」を選択
    • 関数名:my_perl_function
    • ランタイム:Amazon Linux 2 でユーザー独自のブートストラップを提供する
    • 実行ロール:デフォルトの「基本的な Lambda アクセス権限で新しいロールを作成」のまま

    右下の「関数の作成」をクリックする

  3. 「関数の概要」の画面にある Layers(0) をクリックする f:id:sironekotoro:20210402173323p:plain

    • レイヤーの追加をクリックする f:id:sironekotoro:20210402174221p:plain

    • 「ARN を指定」を選択する

    • Amazon リソースネーム(ARN)に以下を入力する arn:aws:lambda:ap-northeast-1:445285296882:layer:perl-5-32-runtime-al2:1 f:id:sironekotoro:20210402174249p:plain

    保存をクリックする。「関数の概要」のところで Layers(1) となっていればok

    f:id:sironekotoro:20210402173902p:plain

  4. コードソース

    • 今回はデフォルトで用意されている bootstrap.sample, hello.sh.sample, README.md を削除しておきます。

      • 該当のファイル名の上で右クリック -> Delete を選択 f:id:sironekotoro:20210402174917p:plain
    • File から New File を選択し、エディタ部に以下のようにコードを書きます。

    • 書いたら File から Save As を選択してファイルを保存します。または Ctrl + s 。 f:id:sironekotoro:20210402191718p:plain f:id:sironekotoro:20210402191840p:plain

  5. テスト

    • エディタ部の上にある「Test」をクリックします

      • ラジオボタンは「新しいテストイベントの作成」でそのまま
      • イベント名はなんでも良いですが、ここでは「first1」としておきます
      • 下のエディタ部分は触らずに右下の「作成」ボタンをクリックします
    • ここで、Test の右隣にある Deploy ボタンをクリックします f:id:sironekotoro:20210402180608p:plain

    • デプロイが成功すると、Deploy の右にある表示が緑色で「Changes Deployed」に変わります。 f:id:sironekotoro:20210402181653p:plain

    • 再度、Test ボタンを押すと、エディタ部にタブが一つ増えテスト結果が表示されます。 f:id:sironekotoro:20210402192124p:plain

ここまでが AWS Lambda 側の準備です。

このテストはは、用意されたJSONをそのまま受け取り、body に入れて返しているというものです。

テスト結果を見ると、Web アプリ作っている人にはお馴染みの Content-TypestatusCode がありますね。

この段階でよく(自分が)引っかかるポイントは、Deploy ボタン押すのを忘れてテストやって反映されてない!ってやるやつです。

Amazon API Gateway の準備

  1. AWS のページ上部にある検索窓に API Gateway と入れて、そこから API Gateway の設定ページに進みます。 f:id:sironekotoro:20210402182713p:plain

  2. API のタイプ選択ですが、今回は 「HTTP API」で作成してみます。右下にある構築をクリックします。 f:id:sironekotoro:20210402193341p:plain

  3. 「統合を追加」のボタンをクリックし、以下のように設定します

    • 統合:Lambda
    • AWSリージョン:Lambda を作ったリージョン(今回は ap-northeast-1 (東京リージョン)) を選択
    • Lambda 関数:作成した Lambda の名前 `` を選択
    • api 名:任意に設定できるが、今回は Lambda 関数名に合わせて my_perl_api とする

    f:id:sironekotoro:20210402193739p:plain

    「次へ」をクリック

  4. ルートを設定

    ここで、HTTP のメソッドに応じた Lambda 関数を設定することができるが、今回は 1 つだけなので ANY のままでよい。

    リソースパスが API のエンドポイントになる(今回は Lambda 関数名である my_perl_function

    f:id:sironekotoro:20210402194400p:plain

    「次へ」をクリック

  5. API はバージョンによって v1 とか v2 などのようにバージョン分けすることができる。

    が、今回はそこまで改修しないのでデフォルトで設定されている通り、自動バージョニングを設定する。

    f:id:sironekotoro:20210402201205p:plain

    「次へ」をクリック

  6. 確認画面が出るので、「作成」をクリック f:id:sironekotoro:20210402201454p:plain

これで出来上がり。

f:id:sironekotoro:20210402201628p:plain

「URLを呼び出す」のところにある URL をクリックすると・・・このように not found になります。

f:id:sironekotoro:20210402201810p:plain

このURLの後ろにエンドポイントである /my_perl_function を追加してみます。

f:id:sironekotoro:20210402201938p:plain

出ました! Hello! World

これで、 AWS Lambda で作成した関数を AMAZON API Gateway に紐づけることができました。

詰まったところ

  • return で返すハッシュリファレンスを encode_jsonエンコードして返したらうまくいかなかった => 返り値は自動でエンコードしてくれる親切仕様だった

  • ログどうやって出すんだろ・・・? って試行錯誤しているうちにできたっぽい。

    API Gateway の左側メニューにある「ログ記録」を有効にして、Cloudwatch Logs の設定が必要とか言われたんで適当に作り、その ARN を貼り付けたらできた。

    ここもちゃんと解説できるようになりたいなぁ。

    f:id:sironekotoro:20210402204925p:plain

「PHPでもサーバーレス!AWS Lambda Custom Runtime 入門」でさっそく詰まる

AWS Lambda で詰まった

  • 前回AWS Lambda を使って Perl を動かして Hello, World! まではできた
  • Lambda 上で自作のモジュールを動かしたいけど、やり方がわからない
    • コンテナの所定のフォルダに入れる?
    • どのコンテナ使うの?Alpineとかでいいの?

AWS Lambda 標準でサポートされていない Perl を使うっていう獣道をいくんだから、分からないの仕方ないよねー

で、この本を読んでみることにしました。 id:taiko19xx さんの本です。

PHP以外の言語でカスタムランタイムを実行する際にも役に立つ一冊です。

この一言にすがる気持ちで・・・

そう、PHPAWS Lambda 標準でサポートされていない言語なので、何かわかるのではないか!?と。

時の流れは無常

この本は 2019 年に発行された本です。そして、2 年もあれば AWS の設定画面が変わるには十分すぎる時間なわけです。

と言うわけで、最初の phpinfo() を出すところまでの画面ショットと解説です。

もちろん、自分用です。

自分は AWS Lambda 触って日が浅いです。Amazon 公式のハンズオンを見て動かしただけというレベル感です。

pages.awscloud.com

ハンズオンごとに登録を求められるのが本当に鬱陶しいのですが、まぁ、相手は企業やしな・・・と言う寛大な気持ちで登録してハンズオン見させてもらっています。

2.1 Lambdaの設定をする

  • 図2.4:名前とランタイム

    • 「関数の作成」 -> ランタイムの選択「ユーザー独自のブートストラップを提供する」とあるが、ない。
    • Amazon Linux 2 でユーザー独自のブートストラップを提供する」を選択
  • 図2.7:関数にレイヤーを追加

    • 画面上部の「ARN を指定」のラジオボタンを選択
    • 画面下部の「ARN を指定」の入力欄に arn:aws:lambda:ap-northeast-1:834655946912:layer:php-demo-layer:4 を入力
      • PC 版 kindle からコピペするとハイフンが消えてしまうようなので注意
    • 画面右下の「追加」ボタンをクリック
  • 図2.13:ハンドラを変更

    • ハンドラはコードエディタの下、ランタイム設定の右上にある「編集」ボタンをクリックしてデフォルトの hello.handler から変更する
  • そして、ここが大事なのですが、コードを書いた後にデプロイする必要があります。

    • f:id:sironekotoro:20210329183705p:plain
    • この画像のオレンジ色の「Deploy」ボタンをクリックすること!
    • このボタンを押していないと、API Gateway と関連づけてもエラーになります。
      • ブラウザで API Gateway の呼び出し先をクリックした時のエラー
      • Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0 Fatal error: Unknown: Failed opening required 'index.php' (include_path='.:/usr/share/pear7:/usr/share/php7') in Unknown on line 0
      • f:id:sironekotoro:20210329184103p:plain

2.2 API Gateway の設定をする

  • 図2.15:APIGatewayのコンソール

    • API タイプを選択」の画面になるので「REST API」の「構築」ボタンをクリック
    • f:id:sironekotoro:20210328230854p:plain
      • この確認画面が出たらokボタンをクリックして閉じる
  • 図2.16:APIの新規作成

    • 「新しい API」のラジオボタンを選択
    • 名前と説明
      • API名:CustomRuntimeFirstFunction
      • 説明:空欄でok
  • 図2.20:権限の許可

    • f:id:sironekotoro:20210328231512p:plain
    • ここまでは掲載通りいける感じ。くれぐれも「Lambda プロキシ統合の使用」のチェックを忘れないこと!
      • もちろん自分が忘れたのでここで注釈として書いておきます・・・
      • f:id:sironekotoro:20210329185113p:plain
  • ステージ

    • f:id:sironekotoro:20210328232129p:plain
  • 画面確認

    • f:id:sironekotoro:20210328232346p:plain

ということで

回り道してる感もあるんですが、それもまた楽しからずや、です。