SORACOM Napter + Funkを使って、Lambda関数をコマンドのように扱う

# これは

NapterとFunkを使うと、Lambda関数をあたかもコマンドのように使えるな・・という思いつきの一発芸です。
ただ、色々使い道はありそうな気がします。

# 前提

ラズベリーパイ(sshでログインできてcurlが動くなら何でもOK)を準備し、sshでログインできるようにします。そして、SORACOM Airを用いてSORACOMのサービスに繋がるようにします(ここまでは割愛)。

# Lambdaの準備

起動するLambda関数を準備します。
今回はネタとして「引数でコマンド与えたらそれがそのままLambdaの実行環境で動く」というものにしています。
[こちらの記事](https://qiita.com/shiro01/items/a6f2516fa89a3f2c4bfe)を参考に、以下の関数(python3)を準備します。

```python
import subprocess

def hello(event, context):
    cmd = event['cmd']  
    out = subprocess.run(cmd, stdout=subprocess.PIPE)    
    return out.stdout.decode()
```

そして、ARNをコピーし、Funkで起動するためのIAMアカウントを作成します。
この辺りのFunkの設定は[こちらの記事](https://qiita.com/kkimura/items/c33962e426e84720dc31)を参照してください。

# シェルスクリプトの準備

Napterでラズベリーパイにオンデマンドリモートアクセス出来るようにして、コマンドを実行して、Napterの後片付けをするシェルスクリプトを作成します。SORACOM cliでNapterを使う部分は[こちらの記事](https://qiita.com/kkimura/items/50375cac7b4cc99d36a1)を参考にしてください。

```bash
#!/bin/sh
IMSI=***********
soracom port-mappings create --body @napter.json 2>&1 /dev/null
PORT=`soracom port-mappings get --imsi $IMSI |jq '.[].port'`
IPADDR=`soracom port-mappings get --imsi $IMSI |jq -r '.[].ipAddress'`
CMD=`echo $@|sed s'/ /","/g'`
CMD="{\"cmd\":[\"$CMD\"]}"
echo $CMD |\
 ssh -p $PORT $IPADDR curl -s -X POST -d @- http://funk.soracom.io/|\
 sed s/\\\\n/\\$'\n'/g
soracom port-mappings delete --port $PORT --ip-address $IPADDR
```

5-6行目はこのシェルスクリプトに渡された引数を

```json
{
  "cmd": [ "arg1","arg2","arg3" ]
}
```

というJSONに整形しています。

7-9行目でsshを使ってラズベリーパイにアクセスし、curlコマンドでFunkを呼び出し、戻り値の改行を処理しています。

# 実行してみる

さっそくやってみましょう。実際には実行ごとにssh先のIPアドレス/ポートが変わるのでそのままだと毎回known_hostsにホストキーを追加するかを聞かれますが、気になる方はStrictHostKeyCheckingオプションをnoにするなりで回避してください。

```bash
%./napter.sh ls -la /
"total 8
dr-xr-xr-x  21 root         root  285 May  3 17:22 .
dr-xr-xr-x  21 root         root  285 May  3 17:22 ..
dr-xr-xr-x   2 root         root  731 May  3 17:22 bin
dr-xr-xr-x   2 root         root    3 Jan  6  2012 boot
drwxr-xr-x   2 root         root 4096 Jul 12 05:56 dev
drwxr-xr-x  49 root         root 1703 May  3 17:22 etc
drwxr-xr-x   2 root         root    3 Jan  6  2012 home
dr-xr-xr-x   5 root         root   58 May  3 17:22 lib
dr-xr-xr-x   5 root         root 3022 May  3 17:22 lib64
drwxr-xr-x   2 root         root    3 Jan  6  2012 media
drwxr-xr-x   2 root         root    3 Jan  6  2012 mnt
drwxr-xr-x   2 root         root    3 May  3 17:22 opt
dr-xr-xr-x 137 root         root    0 Jul 12 06:54 proc
dr-xr-x---   2 root         root    3 Jan  6  2012 root
dr-xr-xr-x   2 root         root  786 May  3 17:22 sbin
drwxr-xr-x   2 root         root    3 Jan  6  2012 selinux
drwxr-xr-x   2 root         root    3 Jan  6  2012 srv
drwxr-xr-x   2 root         root    3 Jan  6  2012 sys
drwx------   2 sbx_user1079  467 4096 Jul 12 06:54 tmp
drwxr-xr-x  13 root         root  200 May  3 17:22 usr
drwxr-xr-x  23 root         root  300 May  3 17:22 var
"
```

バッチリですね！

# まとめ

Lambda関数を安全にコマンドとして呼び出せるというのは結構ネタとしては使い道ありそうかなーと思ってやってみました。

# (補足)aws cliでええんちゃう？

・・と思って僕もやってみたんですが、

```bash
%aws lambda invoke --invocation-type Event --function-name subprocess-dev-hello\
 --payload '{"cmd":["ls","-la","/"]}' -
{
    "StatusCode": 202
}
```

って感じで戻り値が取れなかったのでやっぱりFunkは神サービスと言うことで。
試してませんがCloudWatch Logsに出力させてそれを拾うところまでやればaws cliだけでもいけるかな？