SORACOM Peek for SIMをcliで試す

# この記事は

先日発表された、SORACOM Peek for SIMをcliからも試してみたというお話です。

SORACOM Peek for SIMをコンソールから試した記事はこちらを参照ください。

https://qiita.com/kkimura/items/ae396d1e95d238ce31f4

# soracom cliを準備する

まずはcliの準備です。[GitHub](https://github.com/soracom/soracom-cli)にアクセスし、ドキュメントに従ってインストール・設定します。

Peek for SIMはv0.8.0から対応していますので、古いバージョンをご利用の方はアップデートをお願いします。

# コマンドを調べる

まずはコマンドを調べてみましょう。以前私が書いた[こちらの記事](https://qiita.com/kkimura/items/ddd83e763fa5203222dd)に従ってコンソールの挙動からAPIを探してもいいのですが、恐らくSIMの操作だからコマンド`sims`のサブコマンドにあるんじゃないかなーと推測できますのでヘルプを見てみましょう。

```bash
$ soracom sims --help
Manage SIMs.

Usage:
  soracom sims [command]

Available Commands:
  .....
  create-packet-capture-session Create Packet Capture Session
  .....
  delete-packet-capture-session Delete Packet Capture Session
  .....
  get-packet-capture-session    Get Packet Capture Session
  ....
  list-packet-capture-sessions  List Packet Capture Sessions
  ....
  stop-packet-capture-session   Stop SIM Packet Capture Session
  ....
```

`*****-packet-capture-session`ってのがありますね。create/delete/get/list/stopと、コンソールから見た機能が一通りできそうな名前のコマンドが並んでいます。
コンソールの動作を実現するにはlistで一覧を表示、createでキャプチャ開始、getで状態を確認し、stopで停止。削除するときはdeleteというところでしょう。

では、このサブコマンドの使い方を調べます。まずはコマンドラインのヘルプを見ます。サンプルとして`create-packet-capture-session`を見てみましょう。

```bash
$ soracom sims create-packet-capture-session --help
Create a packet capture session associated with the SIM

Usage:
  soracom sims create-packet-capture-session [flags]

Flags:
      --body string     JSON string or @filename for API request body.
      --duration int
  -h, --help            help for create-packet-capture-session
      --prefix string
      --sim-id string   The SIM ID for which a packet capture session is created
....
```

durationとprefixはコンソールからも指定したキャプチャ時間とファイル名(PREFIX)ですね。対象のSIMを指定するためにSIM IDが必要なのも分かります。
残るbodyの形式を知る必要がありそうです。

# APIリファレンスを読む

こういうときは[SORACOM APIリファレンス](https://users.soracom.io/ja-jp/tools/api/reference/)を参照します。

`/sims/{sim_id}/packet_capture_sessions` というエンドポイントのGET/POSTでキャプチャーセッションの作成・一覧取得ができ、`​/sims​/{sim_id}​/packet_capture_sessions​/{session_id}`というエンドポイントのGET/POST/DELETEで、指定したキャプチャーセッションの取得・停止・削除ができるようです。つまり、コマンドとの対応は

| コマンド | エンドポイント | メソッド |
| --- | --- | --- |
| list | `/sims/{sim_id}/packet_capture_sessions` | GET |
| create | `/sims/{sim_id}/packet_capture_sessions` | POST
| get | `​/sims​/{sim_id}​/packet_capture_sessions​/{session_id}` | GET |
| stop | `​/sims​/{sim_id}​/packet_capture_sessions​/{session_id}` | POST |
| delete | `​/sims​/{sim_id}​/packet_capture_sessions​/{session_id}` | DELETE |

となります。REST APIのお手本のような設計ですね！

肝心のcreateの引数の件ですが、該当のドキュメントによると

```json
{
  "duration": 0,
  "prefix": "string"
}
```

となっています。おっと、これはdurationとprefixが入ってるので、コマンドラインから引数で指定するときは不要なのかもしれません。あとでちょっと試してみましょう。

# 実際にやってみる

では、早速やってみます。

## 1. SIM IDの取得

まずは全てのサブコマンドで必要になるSIM IDを取得します。コマンドは同じく`sim`のサブコマンド`list`です。持っているSIMの一覧が配列で返ってくるので、該当のものを探しますしょう。

```bash
$ soracom sims list
[
        {
                "activeProfileId": "*********************",
                "createdTime": *********,
                "expiryAction": null,
                "expiryTime": null,
....
                "simId": "*********************",
                "speedClass": "s1.minimum",
                "status": "active",
                "tags": {
                        "name": "GPSマルチユニット",
....
]
```

SIMに付けた名前は`tags.name`に入ってるので、この辺を手がかりに探しましょう(上記の「GPSマルチユニット」は私が付けた名前です)。`simId`の値をあとで使いやすいように環境変数に入れておきましょう。

```bash
$ export SIMID=****************
```

## 2. キャプチャーセッションの一覧

一覧を取得してみます。

```bash
$ soracom sims list-packet-capture-sessions --sim-id $SIMID
[
        {
                "createdTime": "2021-05-29T00:37:44.03Z",
                "duration": 150,
                "endedTime": "2021-05-29T00:39:56.71Z",
                "fileSizeInBytes": 585,
                "operatorId": "************",
                "prefix": "gpsmultiunit",
                "scheduledTime": "2021-05-29T00:37:44.025Z",
                "sessionId": "***********************",
                "startedTime": "2021-05-29T00:37:44.092Z",
                "status": "STOPPED"
        },
....
]
```

コンソールから作成したセッションが取得できました。

## 3. キャプチャーセッションを作成する

`duration`を150秒、`prefix`を「fromcli」で作ってみましょう。

```bash
soracom sims create-packet-capture-session --sim-id $SIMID --duration 150 --prefix fromcli
{
        "createdTime": "2021-05-29T01:26:09.100476Z",
        "duration": 150,
        "fileSizeInBytes": 0,
        "operatorId": "***************",
        "prefix": "fromcli",
        "scheduledTime": "2021-05-29T01:26:09.09663Z",
        "sessionId": "**************************",
        "status": "REQUESTED"
}
```

やはりdurationとprefixをパラメータで指定するとbodyは不要のようですね。

念の為、一覧も見てみましょう。ついでにsessionIdを環境変数に入れておきましょう。

```bash
$ soracom sims list-packet-capture-sessions --sim-id $SIMID
[
        {
                "createdTime": "2021-05-29T01:26:09.1Z",
                "duration": 150,
                "fileSizeInBytes": 0,
                "operatorId": "***************",
                "prefix": "fromcli",
                "scheduledTime": "2021-05-29T01:26:09.096Z",
                "sessionId": "*******************",
                "startedTime": "2021-05-29T01:26:09.204Z",
                "status": "CAPTURING"
        },
....
]
$ export SESSIONID="*********"
```

できてますね。statusが「REQUESTED」から「CAPTURING」になっています。

## 4. キャプチャーセッションの状態を確認する

作成したキャプチャーセッションの状態を見てみましょう。

```bash
$ soracom sims get-packet-capture-session --sim-id $SIMID --session-id $SESSIONID
{
        "createdTime": "2021-05-29T01:26:09.1Z",
        "duration": 150,
        "fileSizeInBytes": 0,
        "operatorId": "*****************",
        "prefix": "fromcli",
        "scheduledTime": "2021-05-29T01:26:09.096Z",
        "sessionId": "*****************",
        "startedTime": "2021-05-29T01:26:09.204Z",
        "status": "CAPTURING"
}
```

listで取ったときと同じ内容が表示されます。

しばらく待って、終了したらもう一度やってみましょう。

```bash
soracom sims get-packet-capture-session --sim-id $SIMID --session-id $SESSIONID
{
        "createdTime": "2021-05-29T01:32:28.089Z",
        "duration": 150,
        "endedTime": "2021-05-29T01:34:58.242Z",
        "fileSizeInBytes": 585,
        "operatorId": "**************",
        "prefix": "fromcli",
        "scheduledTime": "2021-05-29T01:32:28.082Z",
        "sessionId": "**************************",
        "startedTime": "2021-05-29T01:32:28.169Z",
        "status": "DONE",
        "url": "https://soracom-packet-capture-outputs.s3.ap-northeast-1.amazonaws.com/*****/fromcli_******.pcap?X-Amz-Security-Token=*****"
}
```

statusがDONEになり、urlという属性が増えてますね。s3の署名付きURLのようです。

## 5. ファイルを取得する

基本的には先ほどの署名付きURLにアクセスすると取得できるのですが、コンソールからコピペしてると環境によっては`&`が`\u0026`に置き換えられてる場合もあるので、こんな感じで取得するといいと思います(コピペでうまく行かなくてしばらく悩みました・・)。

```json
$ curl -o fromcli.pcap `soracom sims get-packet-capture-session --sim-id $SIMID --session-id $SESSIONID | jq -r '.url'`
```

なお、URLは期限がありますので、必ずファイル取得直前に`get-packet-capture-session`で取得します。上記のワンライナーなら問題ないですね。

(2021年6月20日追記)
@bearmini からこの置き換えについてコメントを頂きましたので、こちらにも転記させて頂きます。コメントありがとうございます！

> & が \u0026 に置き換えられてしまう件ですが、soracom-cli のデフォルト動作として API のレスポンスの JSON をそのまま出力するのではなく、indent しながら pretty print するためにこの置き換えが発生してしまっています。（Go の json.Marshal() の動作がデフォルトでそのようになっています。）
> 
> これを回避するには、--raw-output というオプションを付けて実行します。
これで indent されることはなくなり人間にとっては読みづらくなりますが、API のレスポンスがそのまま出力されるようになりますので署名付き URL などが改変されてしまうこともなくなります。

ということなので、

```bash
$ curl -o fromcli.pcap `soracom sims get-packet-capture-session --sim-id $SIMID --session-id $SESSIONID --raw-output
```

と`--raw-output`オプションを付けるとコピペでもうまくいきます。

## 6. stop

キャプチャーを途中で止めてみましょう。

```bash
$ $ soracom sims create-packet-capture-session --sim-id $SIMID --duration 150 --prefix fromcli-tostop
{
        "createdTime": "2021-05-29T02:07:32.400685Z",
        "duration": 150,
        "fileSizeInBytes": 0,
        "operatorId": "*********",
        "prefix": "fromcli-tostop",
        "scheduledTime": "2021-05-29T02:07:32.394171Z",
        "sessionId": "********************",
        "status": "REQUESTED"
}
$ export SESSIONID="**********************"
$ soracom sims stop-packet-capture-session --sim-id $SIMID --session-id $SESSIONID
{
        "createdTime": "2021-05-29T02:07:32.4Z",
        "duration": 150,
        "fileSizeInBytes": 0,
        "operatorId": "************",
        "prefix": "fromcli-tostop",
        "scheduledTime": "2021-05-29T02:07:32.394Z",
        "sessionId": "******************",
        "startedTime": "2021-05-29T02:07:32.504Z",
        "status": "POSTPROCESSING"
}
$ soracom sims get-packet-capture-session --sim-id $SIMID --session-id $SESSIONID
{
        "createdTime": "2021-05-29T02:07:32.4Z",
        "duration": 150,
        "endedTime": "2021-05-29T02:08:34.658Z",
        "fileSizeInBytes": 24,
        "operatorId": "***********",
        "prefix": "fromcli-tostop",
        "scheduledTime": "2021-05-29T02:07:32.394Z",
        "sessionId": "********************",
        "startedTime": "2021-05-29T02:07:32.504Z",
        "status": "STOPPED",
        "url": "https://soracom-packet-capture-outputs.s3.ap-northeast-1.amazonaws.com/**********/fromcli-tostop********"
}
```

セッションの状態を取得してみると、statusが先ほどのDONEではなくSTOPPEDになってるのが分かります。正しく停止できたようです。

## 7. delete

最後に後片付けとして、このセッションを削除してみましょう。

```bash
$ soracom sims delete-packet-capture-session --sim-id $SIMID --session-id $SESSIONID
{
        "createdTime": "2021-05-29T02:07:32.4Z",
        "duration": 150,
        "endedTime": "2021-05-29T02:08:34.658Z",
        "fileSizeInBytes": 24,
        "operatorId": "*************",
        "prefix": "fromcli-tostop",
        "scheduledTime": "2021-05-29T02:07:32.394Z",
        "sessionId": "*********************",
        "startedTime": "2021-05-29T02:07:32.504Z",
        "status": "STOPPED"
}
$ soracom sims get-packet-capture-session --sim-id $SIMID --session-id $SESSIONID
Error: {"code":"SEM0001","message":"No such resource found"}
```

無事削除されていますね。

# 実際使うとき

今回は結果が分かりやすいようにcreateの戻り値もそのまま表示していましたが、普段使うときには環境変数に直接sessionIdを渡した方が便利かと思います。

ファイル取得の時のように`jq`を使って

```bash
$ export SESSIONID=`soracom sims create-packet-capture-session --sim-id $SIMID --duration 150 --prefix fromcli | jq -r .sessionId`
```

とかすると便利かなと思います。

# まとめ

SORACOM Peek for SIMをcliから触ってみました。

私がコマンドの使い方を調べる手順もそのまま書いてみましたので、今後新しい機能をcliで試される際にもお役に立てば幸いです。