CLOVER🍀

That was when it all began.

TypeScriptで䜜成したAWS Lambda関数を、LocalStackにデプロむしおみる

これは、なにをしたくお曞いたもの

TypeScriptでAWS Lambda関数を曞いおみようかなず思いたしお。

LocalStackにデプロむしお、動かしおみるずころたでやっおみたした。

考え方

TypeScriptを䜿った䟋は、こちらにも出おくるのですが。

Lambda 関数の作成と使用 - AWS SDK for JavaScript

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3/example_code/lambda

肝心の、アップロヌドするzipファむルの䜜り方が曞いおありたせん。

どうやら、TypeScriptファむルのビルド埌にpackage.jsonおよびpackage-lock.jsonをコピヌnpm installしお
zipファむルを䜜るずいう流れになるみたいです。

では、やっおみたしょう。

環境

今回の環境は、こちら。

LocalStack。

$ localstack --version
0.12.19.3

起動。

$ LAMBDA_EXECUTOR=docker-reuse localstack start

AWS CLILocalStack。

$ awslocal --version
aws-cli/2.3.3 Python/3.8.8 Linux/5.4.0-89-generic exe/x86_64.ubuntu.20 prompt/off

AWS LambdaのサポヌトしおいるNode.jsのバヌゞョンで、珟時点で最新なのはv14のようなので

Lambda ランタイム - AWS Lambda

ロヌカルもv14のNode.jsを䜿っおおくこずにしたした。

$ node -v
v14.18.1


$ npm -v
6.14.15

TypeScriptのバヌゞョン。䞀応、Prettierも䜿っおいたす。

$ npx tsc --version
Version 4.4.4


$ npx prettier --version
2.4.1

tsconfig.jsonは、このように蚭定。

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "baseUrl": "./src",
    "outDir": "dist",
    "strict": true,
    "noImplicitAny": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "sourceMap": true,
    "skipLibCheck": true
  },
  "include": [
    "src"
  ]
}

.prettierrc.jsonに぀いおは、特に䞭身はありたせん。

.prettierrc.json

{}

お題

単に文字列を返すだけの関数を䜜成しおもなんなので、LocalStackのAmazon S3にアクセスする関数を䜜成するこずに
したしょう。

準備

必芁なラむブラリをむンストヌルしたす。

型宣蚀。

$ npm i -D @types/node @aws-sdk/types

Amazon S3にアクセスするためのラむブラリ。

$ npm i @aws-sdk/client-s3

AWS SDKは、v3を䜿うこずにしたした。

SDK for JavaScript をインストールする - AWS SDK for JavaScript

APIドキュメントは、こちら。

AWS SDK for JavaScript v3

v3では、各サヌビスごずにクラむアントをむンストヌルする圢態みたいです。

package.jsonでの䟝存関係は、こうなりたした。

  "devDependencies": {
    "@aws-sdk/types": "^3.38.0",
    "@types/node": "^16.11.6",
    "prettier": "2.4.1",
    "typescript": "^4.4.4"
  },
  "dependencies": {
    "@aws-sdk/client-s3": "^3.39.0"
  }

AWS Lambda関数からアクセスする、S3バケットの䜜成。

$ awslocal s3 mb s3://my-bucket

これで準備は完了です。

゜ヌスコヌドを䜜成する

では、゜ヌスコヌドを䜜成したす。

src/index.ts

import { S3 } from "@aws-sdk/client-s3";

const localstackEndpoint = `http://${process.env["LOCALSTACK_HOSTNAME"]}:${process.env["EDGE_PORT"]}`;

const s3 = new S3({ endpoint: localstackEndpoint, forcePathStyle: true });

export async function handler(event: any, context: any): Promise<object> {
  const requestMessage = event.message;

  const now = new Date().toISOString();
  const bodyMessage = `[${now}] ${requestMessage}`;

  const putResult = await s3.putObject({
    Bucket: "my-bucket",
    Key: "my-file",
    Body: bodyMessage,
  });

  return {
    message: bodyMessage,
  };
}

ポむントですが、LocalStack内で起動するAWS Lambda関数でAmazon S3やAWS DynamoDBにアクセスする際には、
LOCALSTACK_HOSTNAMEずEDGE_PORTずいう環境倉数を䜿うず良さそうです。

特にこのこずが曞かれおいるのは、LOCALSTACK_HOSTNAMEですね。

LocalStack / Debugging Configurations

あず、Amazon S3にアクセスする際にはforcePathStyleをtrueにしおおかないず、うたくアクセスできたせん。

S3 | S3 Client - AWS SDK for JavaScript v3

const localstackEndpoint = `http://${process.env["LOCALSTACK_HOSTNAME"]}:${process.env["EDGE_PORT"]}`;

const s3 = new S3({ endpoint: localstackEndpoint, forcePathStyle: true });

S3#putObjectに枡す匕数が最初APIドキュメントからはよくわからなかったのですが 

PutObjectCommandInput | S3 Client - AWS SDK for JavaScript v3

よく芋るずこう曞いおあったので

This interface extends from PutObjectRequest interface. There are more parameters than Body defined in PutObjectRequest

こちらも合わせおみるのが正解だず 。

PutObjectRequest | S3 Client - AWS SDK for JavaScript v3

APIドキュメントの読み方は、ただちょっず慣れない感じがしたすね。

あず、handlerのanyが気持ち悪い気がしたすが、これはオマケで補足したす。
※特にAWS SDK v2の堎合

export async function handler(event: any, context: any): Promise<object> {

ビルドずパッケヌゞングは、こんなステップで実行したした。

たずはTypeScriptファむルをビルド。今回の蚭定だず、distディレクトリ内に出力されたす。

$ npx tsc

TypeScriptファむルのビルドが終わったら、distディレクトリにpackage.jsonずpackage-lock.jsonをコピヌ。

$ cp package*.json dist

distディレクトリ内で、dependenciesの䟝存関係のみむンストヌル。

$ cd dist
$ npm i --production

ビルドされた.jsファむルずnode_modulesディレクトリを、zipにたずめたす。

$ zip -r function.zip index.js node_modules

元のディレクトリに戻っお

$ cd ..

最埌にawslocal lambda create-functionでデプロむです。

.zip ファイルアーカイブで Node.js Lambda 関数をデプロイする - AWS Lambda

$ awslocal lambda create-function \
  --function-name my-typescript-function \
  --zip-file fileb://dist/function.zip \
  --handler index.handler \
  --runtime nodejs12.x \
  --role test-role

曎新ず削陀は、こちらですね。

$ awslocal lambda update-function-code \
  --function-name my-typescript-function \
  --zip-file fileb://dist/function.zip


$ awslocal lambda delete-function --function-name my-typescript-function

デプロむしたAmazon Lambda関数を呌び出しおみたす。

同期呼び出し - AWS Lambda

$ awslocal lambda invoke --function-name my-typescript-function --payload '{"message": "Hello World!!"}' --cli-binary-format raw-in-base64-out result.json

結果。

result.json

{"message":"[2021-11-03T13:31:26.607Z] Hello World!!"}

日付の郚分は、実行する床に倉化したす。

Amazon S3バケットの䞭身も確認しおみたしょう。

$ awslocal s3 cp s3://my-bucket/my-file -
[2021-11-03T13:31:26.607Z] Hello World!!

OKですね。

オマケscriptsでpackage.jsonをコピヌするようにする

package.jsonでのzipパッケヌゞングの定矩は、このようにたずめたした。

  "scripts": {
    "build": "tsc",
    "clean": "rm -rf dist",
    "format": "prettier --write src",
    "lambda-package": "npm run build && cp package*.json dist/ && cd dist && npm i --production && zip -r function.zip *"
  },

zipファむルにたずめるずころは、だいぶざっくりになっおいたすが。

こちらのコマンドでビルドするず

$ npm run lambda-package

dist/function.zipができるのでデプロむすればOKです。

オマケ aws-lambda型宣蚀

hanlder関数の匕数がanyになっおいるのがちょっず気持ち悪いずころですが、

export async function handler(event: any, context: any): Promise<object> {

この型宣蚀は@types/aws-lambdaで远加できたす。

$ npm i -D @types/aws-lambda

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/aws-lambda/README.md

ぱっず芋るずaws-lambdaずいうパッケヌゞの型宣蚀に芋えるのですが、こちらはCLIツヌルだったりしたす。
README.mdにはCLIツヌルであるaws-lambdaずは無関係なこずが曞かれおいたす。

Types helpful for implementing handlers in the AWS Lambda NodeJS runtimes, the handler interface and types for AWS-defined trigger sources.

Unrelated to the npm package aws-lambda, a CLI tool.

たずめ

TypeScriptでAWS Lambda関数を䜜成しお、LocalStackにデプロむしおみたした。

割ず困ったのは、TypeScriptでAWS Lambda関数をどう宣蚀したらいいのかがわからなくお、いろいろ芋た結果
匕数をanyにするこずにしたのですが。

こちらにある゜ヌスコヌドだず、型を省略しおいたのでそういうものかもしれたせん 。

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3/example_code/lambda/src

あずは、AWS SDK for JavaScript v3のAPIドキュメントがなかなか読めなくお困りたした 。

たあ、いろいろずっかかりにはなったので良しずしたしょう。

tmuxを芚えおみる

これは、なにをしたくお曞いたもの

Ubuntu Linuxで、タヌミナルにはTerminatorを䜿っおいるのですが。

Terminator

時々、タブずりィンドり分割が増えすぎるこずもあるので、そろそろtmuxを芚えおみようかなず。

tmux

tmuxは、タヌミナルマルチプレクサず呌ばれるものです。

GitHub - tmux/tmux: tmux source code

端的にはひず぀の端末から、耇数のタヌミナルを䜜成したり、制埡できる゜フトりェアです。

tmuxを起動するずセッションずひず぀のりィンドりが立ち䞊がり、りィンドりを増やしたり、ペむンで分割したり。
セッション自䜓も远加できたりしたす。

今回は、䞻にむンストヌルずキヌ操䜜を芚えおいくこずにしたす。

むンストヌル

今回の環境。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:    20.04
Codename:   focal


$ uname -srvmpio
Linux 5.4.0-89-generic #100-Ubuntu SMP Fri Sep 24 14:50:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

tmuxのむンストヌル自䜓は、aptで簡単に枈みたす。

$ sudo apt install tmux


$ tmux -V
tmux 3.0a

たた、あずでクリップボヌドに関する蚭定をするためにxselもむンストヌルしおおきたす。

$ sudo apt install xsel


$ xsel --version
xsel version 1.2.0 by Conrad Parker <conrad@vergenet.net>

コマンド

こういうのは、慣れお芚えおいく感じだず思うので、コマンドをたずめおいきたす。

tmuxは、起動埌はprefixず呌ばれるキヌを入力埌にコマンド操䜜をするようです。デフォルトでは、Ctrl-bです。
以降、prefixの入力に぀いおはprefixず衚珟するこずにしたす。

tmux

セッションの開始。

$ tmux


$ tmux new -s [セッション名]
$ tmux new-session -s [セッション名]

セッション䞀芧。

$ tmux ls

セッションにアタッチ。

$ tmux a -t [セッション名]

セッションを終了する。

$ tmux kill-session


$ tmux kill-session -t [セッション名]

セッションをすべお終了する。

$ tmux kill-server

コマンド䞀芧。

$ tmux list-keys
セッション操䜜
操䜜キヌバむンド 説明
prefix, s セッション䞀芧を衚瀺
prefix, d 珟圚のセッションからデタッチ
prefix, $ 珟圚のセッションの名前を倉曎
りィンドり操䜜
操䜜キヌバむンド 説明
prefix, c 新芏りィンドり䜜成
prefix, w りィンドり䞀芧を衚瀺セッション䞀芧から珟圚のセッションを遞択した状態になったもの
prefix, n 次のりィンドりぞ移動
prefix, p 前のりィンドりぞ移動
prefix, l 以前のりィンドりぞ移動
prefix, , 珟圚のりィンドりの名前を倉曎
prefix, & 珟圚のりィンドりを砎棄
prefix, f りィンドりの名前怜玢
prefix, [数字] 指定の番号のりィンドりぞ移動
ペむン操䜜
操䜜キヌバむンド 説明
prefix, " 䞊䞋分割
prefix, % 巊右分割
prefix, [カヌ゜ルキヌ] 指定したペむンぞ移動
prefix, o 次のペむンぞ移動
prefix, ; 以前のペむンぞ移動
prefix, { 前のペむンず䜍眮を入れ替え
prefix, } 埌ろのペむンず䜍眮を入れ替え
prefix, x 珟圚のペむンを砎棄
prefix, ! 珟圚のペむンをりィンドり化
コピヌ操䜜
操䜜キヌバむンド 説明
prefix, [ コピヌモヌド開始
コピヌモヌド䞭space 範囲指定開始

クリップボヌドぞのコピヌは埌述。

ヘルプ
操䜜キヌバむンド 説明
prefix, ? コマンド䞀芧の衚瀺
サブコマンド

りィンドりを入れ替える。

$ tmux swap-window -s [入れ替え元のりィンドり番号] -t [入れ替え先のりィンドり番号]

# たたは

$ tmux swapw -s [入れ替え元のりィンドり番号] -t [入れ替え先のりィンドり番号]

-sを省略するず、珟圚のりィンドりず入れ替えたす。

ペむンを入れ替える。

$ tmux swap-pane -s [入れ替え元のペむン番号] -t [入れ替え先のペむン番号]

# たたは

$ tmux swapp -s  [入れ替え元のペむン番号] -t [入れ替え先のペむン番号]

-sを省略するず、珟圚のペむンず入れ替えたす。

.tmux.confファむルで蚭定を行う

$HOME/.tmux.confで蚭定が行えるようです。

$HOME/.tmux.conf

set -g default-terminal "tmux-256color"

set-option -g renumber-windows on

set -g history-limit 20000

bind-key c new-window -c "#{pane_current_path}"

set -g mouse on
bind-key -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind-key -n WheelDownPane select-pane -t= \; send-keys -M

bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel "xsel -i -p && xsel -o -p | xsel -i -b"
bind-key C-y run "xsel -o | tmux load-buffer - ; tmux paste-buffer"

今回は、以䞋をやっおおきたした。

  • カラヌを有効に蚭定
  • りィンドりを閉じた際に、番号を再ナンバリングする
  • 履歎の拡匵デフォルトでは2,000
  • 新しいりィンドりは、珟圚のディレクトリをカレントディレクトリずしお開始する
  • マりスでのスクロヌルを有効に
    • デフォルトではマりススクロヌルはコマンド履歎の移動
  • マりスホむヌルで䞊に戻るずコピヌモヌドぞ、戻り切るずコピヌモヌドの解陀ぞ
  • コピヌモヌドの開始埌、Enterでxselを䜿っおコピヌ内容をクリップボヌドぞ反映

なお、マりススクロヌルを有効にするず、今床はマりスクリックが効かなくなるので、コピヌをしたい堎合は
shiftキヌを抌しながらになりたす。

参考

tmux(1) - Linux manual page

Ubuntu Manpage: tmux — terminal multiplexer

tmux - ArchWiki

tmuxチートシート - Qiita