RESTゲートウェイのnodeMetadata設定を楽にするツールを作ってみた


以下のようなツールを作って公開しました。（作成時間：約二時間）
機能は単純です。

>YAMLファイルをJSONにして書き出すツールです。 引数オプションにより、既存のJSONへキーを追加することも出来ます。

以上です。

https://www.npmjs.com/package/yml-to-json


# 具体的な使い方


https://qiita.com/nizveyl/items/c44b20f78e0e52ae945e


https://qiita.com/amenoudume/items/2de77a13bd9f44cb8a25


「RESTゲートウェイに任意のJSON拡張情報をもたせるnodeMetadata設定」の記事を参考に具体的な使い方をご紹介します。

## ツールのインストール

yml-to-jsonをグローバルインストールします。

```
npm install -g yml-to-json
```

## rest.ymlを準備

ファイル名は何でも良いです。

```yaml
nodeMetadata:
  greeting: "こんにちは"
  message:  "テキストメッセージだよ"
  foo:
    bar: "バー"
    baz: 
      greeting: "Hello!"
      array: [1,2,3,4,5]
```

Symbolのノード構成に合わせるると以下の様な感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934471/5a65289e-3310-547e-ada5-cb225f42504b.png)


## 書き換え先（追記先）のJSONファイルの確認

今回はRESTゲートウェイに任意のJSON拡張情報をもたせるので、以下のtarget/gateways/rest-gateway/rest.jsonを書き換えていきます。

`target/gateways/rest-gateway/rest.json`のパスを確認しておいてください
このパスは2022/12/18現在です。今後、仕様変更等でパスが変更になる可能性がありますので、その都度確認をしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934471/ba402548-9a43-90d7-e8f3-39017e25198a.png)

<details>
<summary>書き換え前の target/gateways/rest-gateway/rest.json の中身はこちら</summary>


```json
{
  "network": {
    "name": "testnet",
    "description": "Symbol Sainet Network"
  },
  "port": 3000,
  "protocol": "HTTP",
  "sslKeyPath": "/symbol-workdir/restSSL.key",
  "sslCertificatePath": "/symbol-workdir/restSSL.crt",
  "crossDomain": {
    "allowedHosts": [
      "*"
    ],
    "allowedMethods": [
      "GET",
      "POST",
      "PUT",
      "OPTIONS"
    ]
  },
  "uncirculatingAccountPublicKeys": [],
  "extensions": [
    "accountLink",
    "aggregate",
    "lockHash",
    "lockSecret",
    "mosaic",
    "metadata",
    "multisig",
    "namespace",
    "receipts",
    "restrictions",
    "transfer"
  ],
  "db": {
    "url": "mongodb://db:27017/",
    "name": "catapult",
    "pageSizeMin": 10,
    "pageSizeMax": 100,
    "maxConnectionAttempts": 15,
    "baseRetryDelay": 750,
    "connectionPoolSize": 10
  },
  "apiNode": {
    "host": "node",
    "port": 7900,
    "tlsClientCertificatePath": "/symbol-workdir/api-node-config/cert/node.crt.pem",
    "tlsClientKeyPath": "/symbol-workdir/api-node-config/cert/node.key.pem",
    "tlsCaCertificatePath": "/symbol-workdir/api-node-config/cert/ca.cert.pem",
    "timeout": 1000,
    "networkPropertyFilePath": "/symbol-workdir/api-node-config/config-network.properties",
    "nodePropertyFilePath": "/symbol-workdir/api-node-config/config-node.properties"
  },
  "websocket": {
    "mq": {
      "host": "broker",
      "port": 7902,
      "monitorInterval": 500,
      "connectTimeout": 10000,
      "monitorLoggingThrottle": 60000,
      "maxSubscriptions": 300
    },
    "allowOptionalAddress": true
  },
  "throttling": {
    "burst": 80,
    "rate": 60
  },
  "logging": {
    "console": {
      "formats": [
        "colorize",
        "simple"
      ],
      "level": "verbose",
      "handleExceptions": true
    },
    "file": {
      "formats": [
        "prettyPrint"
      ],
      "level": "verbose",
      "handleExceptions": true,
      "filename": "/symbol-workdir/logs/catapult-rest.log",
      "maxsize": 20971520,
      "maxFiles": 100
    }
  },
  "numBlocksTransactionFeeStats": 300,
  "deployment": {
    "deploymentTool": "symbol-bootstrap",
    "deploymentToolVersion": "1.1.9.2",
    "lastUpdatedDate": "2022-12-12"
  }
}
```

</details>

# ノードの停止

ツールの実行前にノードは停止しておきます。

```bash
symbol-bootstrap stop
```

# yml-to-jsonでrest.ymlの値をrest.jsonへ追記

以下のコマンドを実行します。

```bash
yml-to-json rest.yml target/gateways/rest-gateway/rest.json 
```

問題がなければ以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934471/18e2cb34-2bc0-c558-1f34-bcd47299cca8.png)

※エラーが表示された場合には、変換元のrest.ymlか変換先のrest.jsonが存在していない可能性があるので確認してください。

**引数オプションの説明**

- 第一引数（必須）：変換元YAMLファイル
- 第二引数（必須）：第一引数で指定されたYAMLをJSONに変換後、第二引数で指定したファイルに追記する。既存のキーが存在する場合は上書きされるので注意。
- 第三引数（オプション）：第一引数で指定されたYAMLをJSONに変換後、第二引数で指定したファイルには追記せず、第三引数に指定されたファイルに書き出す（主に確認用）

正常に処理が終わると以下のように第二引数で指定した`target/gateways/rest-gateway/rest.json`に第一引数で指定したrest.ymlの値が追記されます。
※第三引数を指定すると第二引数で指定したファイルには追記せず、第三引数に指定されたファイルにJSONを書き出します。主に変更される箇所を確認したりする際に使ってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934471/44c00797-8794-bc4b-83c0-e29e56ab28ec.png)


<details>
<summary>書き換え後の target/gateways/rest-gateway/rest.json の中身はこちら</summary>


```json
{
  "network": {
    "name": "testnet",
    "description": "Symbol Sainet Network"
  },
  "port": 3000,
  "protocol": "HTTP",
  "sslKeyPath": "/symbol-workdir/restSSL.key",
  "sslCertificatePath": "/symbol-workdir/restSSL.crt",
  "crossDomain": {
    "allowedHosts": [
      "*"
    ],
    "allowedMethods": [
      "GET",
      "POST",
      "PUT",
      "OPTIONS"
    ]
  },
  "uncirculatingAccountPublicKeys": [],
  "extensions": [
    "accountLink",
    "aggregate",
    "lockHash",
    "lockSecret",
    "mosaic",
    "metadata",
    "multisig",
    "namespace",
    "receipts",
    "restrictions",
    "transfer"
  ],
  "db": {
    "url": "mongodb://db:27017/",
    "name": "catapult",
    "pageSizeMin": 10,
    "pageSizeMax": 100,
    "maxConnectionAttempts": 15,
    "baseRetryDelay": 750,
    "connectionPoolSize": 10
  },
  "apiNode": {
    "host": "node",
    "port": 7900,
    "tlsClientCertificatePath": "/symbol-workdir/api-node-config/cert/node.crt.pem",
    "tlsClientKeyPath": "/symbol-workdir/api-node-config/cert/node.key.pem",
    "tlsCaCertificatePath": "/symbol-workdir/api-node-config/cert/ca.cert.pem",
    "timeout": 1000,
    "networkPropertyFilePath": "/symbol-workdir/api-node-config/config-network.properties",
    "nodePropertyFilePath": "/symbol-workdir/api-node-config/config-node.properties"
  },
  "websocket": {
    "mq": {
      "host": "broker",
      "port": 7902,
      "monitorInterval": 500,
      "connectTimeout": 10000,
      "monitorLoggingThrottle": 60000,
      "maxSubscriptions": 300
    },
    "allowOptionalAddress": true
  },
  "throttling": {
    "burst": 80,
    "rate": 60
  },
  "logging": {
    "console": {
      "formats": [
        "colorize",
        "simple"
      ],
      "level": "verbose",
      "handleExceptions": true
    },
    "file": {
      "formats": [
        "prettyPrint"
      ],
      "level": "verbose",
      "handleExceptions": true,
      "filename": "/symbol-workdir/logs/catapult-rest.log",
      "maxsize": 20971520,
      "maxFiles": 100
    }
  },
  "numBlocksTransactionFeeStats": 300,
  "deployment": {
    "deploymentTool": "symbol-bootstrap",
    "deploymentToolVersion": "1.1.9.2",
    "lastUpdatedDate": "2022-12-12"
  },
  "nodeMetadata": {
    "greeting": "こんにちは",
    "message": "テキストメッセージだよ",
    "foo": {
      "bar": "バー",
      "baz": {
        "greeting": "Hello!",
        "array": [
          1,
          2,
          3,
          4,
          5
        ]
      }
    }
  }
}
```

</details>


# ノードの起動

最後にノードを起動して変更が適応されたか確認します。

```bash
symbol-bootstrap run -d
```

`http://(ノードURL):3000/node/matadata`

# ちょっと便利なところ

>第二引数（必須）：第一引数で指定されたYAMLをJSONに変換後、第二引数で指定したファイルに追記する。既存のキーが存在する場合は上書きされるので注意。

第二引数で指定されたJSONファイルに既存のキーが存在している場合、そのキーを上書きします。
どういうことかというと、例えば先程追記したrest.ymlファイルの中身を以下のように変更して実行すると`target/gateways/rest-gateway/rest.json`のnodeMetadataが更新されます。

```rest.yml
nodeMetadata:
  message:  "今日も一日..."
  after:
    five: "飲みに行くぞ！"

```

再実行

```
yml-to-json rest.yml target/gateways/rest-gateway/rest.json
```

nodeMetadataキーの値が書き換わりましたね！便利！

```target/gateways/rest-gateway/rest.json
{
  "network": {
    "name": "testnet",
    "description": "Symbol Sainet Network"
  },
  
...省略

  "deployment": {
    "deploymentTool": "symbol-bootstrap",
    "deploymentToolVersion": "1.1.9.2",
    "lastUpdatedDate": "2022-12-12"
  },
  "nodeMetadata": {
    "message": "今日も一日...",
    "after": {
      "five": "飲みに行くぞ！"
    }
  }
}
```



# ツールについての注意点

このツールは主に自分用に作っています。
エラー処理やオプション等の実装は正直手抜きです。（制作時間二時間ですから。。。）使用の際にはその点理解して使ってください。
ツールは予告なくバージョンアップしていきますのでご了承ください。
また、本ツールに関するいかなる保証および賠償を行いません。 
従って本ツールに関して発生した問題は、使用者の責任および費用負担によって処理されるものとします。

# 最後に

**なぜ作ったか？** ということなのですが...単純にYAMLの方が慣れ親しんでいるからです。
あと、SymbolノードのカスタムプリセットもYAMLなので、そっちに合わせたほうが管理し易いと思ったのもあります。
かたやYAM、かたやJSON...と管理するのは面倒ですよね？（私は面倒だった...）


ちなみに、ノードが動かなくなったら下記のコマンドでrest.jsonを初期化出来ます。

```
symbol-bootstrap stop
symbol-bootstrap config --upgrade
symbol-bootstrap run -d
```

参考：

https://qiita.com/amenoudume/items/2de77a13bd9f44cb8a25#%E3%81%A1%E3%81%AA%E3%81%BF%E3%81%AB%E3%81%83