初めに
今年の正月くらいにRustの公式の入門みたいなページを読んだはいいけど何も作らず今日まで来てしまったので、
いい加減何か作ろうと思ったらちょうどいい題材があったのでそれで入門しようという感じ。
家のサーバで動かしてもいいですが AWS Lambda
がコスト的にも管理的にも楽なのでこれでやります。
アプリはあんま作らないので割と初心気味
最終的に作るものですが、
このコロナのご時世で会社全体でリモートとなり、今まで雑にやってきたけどSlackのステータスはしっかり変更しようね!
...とはなったけどめんどくさいとか忘れてたとなるのでその辺りをいい感じにしてくれるものを作ろうと思います。
方針
ステータスの方針についてはまだ決まってないのもあるのでとりあえずですが、
1日一回業務開始時間に実行させ、
今日が土日か自分の終日予定に休み系のワードがあればステータスを休暇に変え、なければステータスなしに変更するものを作ります。
もしくは業務終了時間に固定で業務終了に切り替えるもの。
まず AWS Lambda
でRustで動かします。
公式のサンプルをAWS Lambda上で動かす
cargoはドキュメント読みながらちょっとだけ動かすときにインストールしてるので省略
rustのlambda用のランタイムは上記っぽいのでcargo init
をして上記をコピペで動かしてみます。
コピペして出たエラーから必要そうなパッケージをざっくり調べて追加したらとりあえず以下でなんとかなりました。
[dependencies]
lambda_runtime = "*"
simple-error = "*"
serde_derive = "*"
serde = { version = "*", features = ["derive"] }
とりあえずこれでcargo build
が成功したのでcargo run
をしてみます。
thread 'main' panicked at 'Could not find runtime API env var: environment variable not found', /Users/***/.cargo/registry/src/github.com-1ecc6299db9ec823/lambda_runtime_core-0.1.2/src/runtime.rs:79:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
ダメでした。
環境変数ガー問題なのでとりあえずLambda上なら動くだろうと信じて AWS Lambda
にあげてみます。
AWSのブログ参考に...と思ってみたら動かすコードも含め色々必要なのが全部載ってました...
とりあえずコードの内容はそのままにcargo.toml
に上記ページの[[bin]]
から3行を追加し、
その他 bashの内容を黙々と実行していきます。
じっくり読みはしてませんがとりあえず雰囲気とコマンドだけ動かせばいけるやろうの精神です。
どうやらカスタムランタイムでもSAMが利用できるみたいですが、
一旦動くかを確認したいので以下の部分まで進め、zipにしたものをlambdaにあげます。
zip -j rust.zip ./target/x86_64-unknown-linux-musl/release/bootstrap
テストイベントをコピペしたらエラーを吐きましたが
単純にAWS側のサンプルとdocs.rsのサンプルの変数の違いなので以下に変更して実行
{
"first_name": "Fizz",
"last_name": "Buzz"
}
動きました。
ちなみにこの状態でもローカルで実行したら環境変数の問題は起きて実行できませんでした。
{
"message": "Hello, Foo!"
}
SAMで実行・デプロイする
この状態では環境変数をなんとかしないとローカルでは実行できず
毎回buildしてzipで固めてGUIでアップロードをとらないと確認できません。
環境変数をどうにかするのもいいですが、デプロイで楽をするためにもSAMでなんとかできるようにしましょう。
AWS CLIやSAMのインストールは今回できている環境なので省略します。
テンプレートを作る
テンプレートについてですが、
少し調べたところカスタムランタイムはRuntime: provided
と指定してやれば良いみたいです。
ここまでわかればあとは公式ドキュメントと睨めっこするだけです。
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-resource-function.html
後で足せばいいのでとりあえず以下で作りました。
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
ChangeSlackStatusProject:
Type: "AWS::Serverless::Function"
Properties:
FunctionName: ChangeSlackStatus
Handler: main
Runtime: provided
CodeUri: ./rust.zip
ビルドする
失敗
とりあえずbuildしてみましたが、providedはサポートしていないって言われました。
上の方で参考にしたAWSのブログにはSAMテンプレート使って sam build
できるよ!って書いてあったので、
おそらく何か方法はあるはずです。
最悪 zip
で固めればできるのと、一旦実行デプロイまでをみたいので後日もしくはこの記事の投稿後に頑張ろうと思います。
$ sam build
Building resource 'ChangeSlackStatus'
Build Failed
Error: 'provided' runtime is not supported
デプロイする
とりあえずソースコードは先ほど手動で作ったものがあるのでそれを使ってデプロイします。
お手軽に--guided
を使ってデプロイします。
$ sam deploy --guided
Configuring SAM deploy
======================
Looking for samconfig.toml : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: ChangeSlackStatusProject
AWS Region [us-east-1]: ap-northeast-1
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: Y
Save arguments to samconfig.toml [Y/n]: Y
(中略)
CloudFormation events from changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role ChangeSlackStatusProjectRole -
CREATE_IN_PROGRESS AWS::IAM::Role ChangeSlackStatusProjectRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role ChangeSlackStatusProjectRole -
CREATE_IN_PROGRESS AWS::Lambda::Function ChangeSlackStatusProject -
CREATE_IN_PROGRESS AWS::Lambda::Function ChangeSlackStatusProject Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function ChangeSlackStatusProject -
CREATE_COMPLETE AWS::CloudFormation::Stack ChangeSlackStatusProject -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - ChangeSlackStatusProject in ap-northeast-1
無事できました。
テスト用のイベントを作り忘れたので(そもそもSAMでできるのか?)
最初の手動デプロイと同じ方法でテストイベントを作り実行しましたが、無事に実行することができました。
ローカルで実行する
さて、順番が逆になってしまいましたが、ローカルで実行します。
とりあえずこのままsam local invoke
をしてもイベントがないので当然のようにエラーが出ます。
{"errorType":"JsonError","errorMessage":"JsonError: missing field `first_name` at line 1 column 2"}
なので、event用のjsonを作成しましょう。
{
"first_name": "Fizz",
"last_name": "Buzz"
}
あとは-e
で作ったイベントファイルを指定して実行するだけです。
$ sam local invoke -e event.json
Invoking main (provided)
Decompressing /xxxxx/StatusByClaneder/rust.zip
う
Fetching lambci/lambda:provided Docker container image......
Mounting /private/var/folders/lj/tt21hqgj7s3f0t3bgghmllkm0000gn/T/tmp0ob6vo6n as /var/task:ro,delegated inside runtime container
START RequestId: fe10b830-cbfa-1b9d-6b74-464b57a38f44 Version: $LATEST
END RequestId: fe10b830-cbfa-1b9d-6b74-464b57a38f44
REPORT RequestId: fe10b830-cbfa-1b9d-6b74-464b57a38f44 Init Duration: 97.80 ms Duration: 4.03 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 10 MB
{"message":"Hello, Fizz!"}
無事にローカルでも実行できました。
1日目を終えて
書き終えて気づきましたが
今日は実行基盤を整えるところで終わりとなり、肝心のRustコードはコピペだけとなりました。
とはいえCargo.toml
を少し書いたり、コードを少し読んだり、
(Lambdaの話ですが)カスタムランタイムのデプロイができたり学びはそれなりにありました。
終わったものを後で書いているわけではなく、なんだったら記事を書きながら試していたので、
2日目はいつになることなのか...それどころかやる気が消滅し2日目なんてなかったことになるかもしれません。
こうやって書いていくこと脅迫観念を作っているのでなんとか頑張って完成まで目指そうと思います。
2日目〜はGoogleカレンダーから情報を取るところまでなんとかする予定です。
実際は切りのいいところまで行ったら投稿に予定です。