こんにちは、水津です。
この記事は、IBM Cloud Advent Calendar 2017 23日目の投稿です。
はじめに
Node-REDで開発する際に困るのが、フローのバージョン管理。特に複数人で開発していると、間違って更新し他人の更新を消しちゃうことも。今回はそんな悩みを解決するために、IBM Cloud上のFunctionsとNode-REDを活用し、Node-REDのフロー定義更新を自動的にGitに反映する、Node-RED Flowの簡易的なバージョン管理システムを作りたいと思います。
構成
IBM GitLab の準備
まずは、Flow定義の保存先(バージョン管理先)となるGitLabのリポジトリを準備します。今回は、IBM Cloudが提供してますGitLab環境を用いたいと思います。
- テキトウな名称で新規リポジトリを作成ください。
- 作成後、リポジトリの「Project ID」をメモください。(あとで、API CALLの設定を行う際、使用します)
これでGitLabの準備は完了です。
IBM Cloud Functions(OpenWhisk)の実装
続いて、Node-REDのFlow定義が保存されているCloudantの更新を検知し動かす、「Functions(機能)」の実装を行っていきたいと思います。
- 「機能」の開始 > 概要より、「作成の開始」をクリックし、まずはシーケンスを作成します。
アクションのコードは以下のように定義ください。
function main(params) {
var msg = {};
msg.payload = params.id;
return msg;
}
- 続いて、作成したシーケンスにトリガーを追加します。追加するトリガーは、「Cloudant」を選択ください。
これで、CloudantのUpdateを検知し、WebsocketでUpdateされたDocumentのIDをSendする、Functions(機能)の実装が完了しました。
Node-RED の実装
続いて、Functions(機能)から送られてきたDocumentのIDをもとに、Flow定義をGitにPushするNode-REDのフローを定義します。
- まずは、Node-REDにGitLabに接続するためのNodeを追加します。パレットの管理より、ノードの追加で「gitlab」を検索し、node-red-contrib-gitlab ノードを追加ください。(私の自作ノードです)
- その後、以下のようにフローを定義ください。
フロー定義は以下になります。
[
{
"id": "f457b9b7.dea6d",
"type": "websocket in",
"z": "4ab9fe27.86f9c8",
"name": "",
"server": "166ec69b.fef401",
"client": "",
"x": 110,
"y": 100,
"wires": [
[
"80dfb138.ecced",
"1b444420.62923c"
]
]
},
{
"id": "80dfb138.ecced",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "true",
"x": 270,
"y": 100,
"wires": []
},
{
"id": "b03e8025.2dc4f8",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 650,
"y": 400,
"wires": []
},
{
"id": "6972a335.8a49f4",
"type": "GitLab-Update-RepositoryFile",
"z": "4ab9fe27.86f9c8",
"name": "",
"branch_name": "master",
"encoding": "text",
"gitlabconfig": "fa916f31.d3a12",
"x": 430,
"y": 400,
"wires": [
[
"b03e8025.2dc4f8"
]
]
},
{
"id": "d8082f39.a124",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "payload",
"x": 1030,
"y": 540,
"wires": []
},
{
"id": "87c6cbda.c168c",
"type": "catch",
"z": "4ab9fe27.86f9c8",
"name": "",
"scope": [
"6972a335.8a49f4"
],
"x": 360,
"y": 440,
"wires": [
[
"4d03b085.c2dcc",
"f4070782.4803a8"
]
]
},
{
"id": "4d03b085.c2dcc",
"type": "switch",
"z": "4ab9fe27.86f9c8",
"name": "",
"property": "_error.statusCode",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "400",
"vt": "num"
},
{
"t": "else"
}
],
"checkall": "true",
"outputs": 2,
"x": 390,
"y": 560,
"wires": [
[
"5055bcc.3113cc4"
],
[
"9780af03.3d19f"
]
]
},
{
"id": "9780af03.3d19f",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "true",
"x": 530,
"y": 580,
"wires": []
},
{
"id": "7dde70e9.f74138",
"type": "GitLab-Create-RepositoryFile",
"z": "4ab9fe27.86f9c8",
"name": "",
"branch_name": "master",
"encoding": "text",
"gitlabconfig": "fa916f31.d3a12",
"x": 820,
"y": 540,
"wires": [
[
"d8082f39.a124"
]
]
},
{
"id": "bee7ea4.93eca18",
"type": "comment",
"z": "4ab9fe27.86f9c8",
"name": "IBM Cloud Functions からMSG受信",
"info": "",
"x": 180,
"y": 60,
"wires": []
},
{
"id": "9c5b58f8.0a78d",
"type": "cloudant in",
"z": "4ab9fe27.86f9c8",
"name": "Flow定義を取得",
"cloudant": "",
"database": "nodered",
"service": "KS-Test-20171211-cloudantNoSQLDB",
"search": "_id_",
"design": "",
"index": "",
"x": 440,
"y": 140,
"wires": [
[
"26d24ca.e909734"
]
]
},
{
"id": "947eff54.91dc6",
"type": "function",
"z": "4ab9fe27.86f9c8",
"name": "Git PUSH MSG作成",
"func": "var payloadMessage = {\n \"file_path\": msg.process._id + \".json\",\n \"content\": msg.payload,\n \"commit_message\": \"Update Node-RED Flow\"\n};\n\nmsg.payload = payloadMessage;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 480,
"y": 260,
"wires": [
[
"7707921c.c4755c",
"6972a335.8a49f4"
]
]
},
{
"id": "1b444420.62923c",
"type": "function",
"z": "4ab9fe27.86f9c8",
"name": "IDを退避",
"func": "msg.process = {\n \"_id\" : msg.payload\n};\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 280,
"y": 140,
"wires": [
[
"9c5b58f8.0a78d"
]
]
},
{
"id": "7707921c.c4755c",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "true",
"x": 690,
"y": 260,
"wires": []
},
{
"id": "26d24ca.e909734",
"type": "json",
"z": "4ab9fe27.86f9c8",
"name": "",
"pretty": true,
"x": 290,
"y": 260,
"wires": [
[
"efda5601.e13fe8",
"947eff54.91dc6"
]
]
},
{
"id": "34bb144a.7dbd0c",
"type": "comment",
"z": "4ab9fe27.86f9c8",
"name": "Flow定義をbase64変換",
"info": "",
"x": 340,
"y": 300,
"wires": []
},
{
"id": "ce0f378e.d9db9",
"type": "comment",
"z": "4ab9fe27.86f9c8",
"name": "ファイル更新",
"info": "",
"x": 490,
"y": 360,
"wires": []
},
{
"id": "3d9fa74c.87c2f8",
"type": "comment",
"z": "4ab9fe27.86f9c8",
"name": "ファイル新規登録",
"info": "",
"x": 790,
"y": 500,
"wires": []
},
{
"id": "dfe5779d.fb3b28",
"type": "comment",
"z": "4ab9fe27.86f9c8",
"name": "まだファイルがなく失敗した場合",
"info": "",
"x": 250,
"y": 480,
"wires": []
},
{
"id": "efda5601.e13fe8",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 450,
"y": 220,
"wires": []
},
{
"id": "f4070782.4803a8",
"type": "debug",
"z": "4ab9fe27.86f9c8",
"name": "",
"active": true,
"console": "false",
"complete": "true",
"x": 510,
"y": 440,
"wires": []
},
{
"id": "5055bcc.3113cc4",
"type": "function",
"z": "4ab9fe27.86f9c8",
"name": "Git PUSH MSG作成",
"func": "msg.payload = msg.inputMessage.payload;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 580,
"y": 540,
"wires": [
[
"7dde70e9.f74138"
]
]
},
{
"id": "166ec69b.fef401",
"type": "websocket-listener",
"z": "",
"path": "/ws/push",
"wholemsg": "false"
},
{
"id": "fa916f31.d3a12",
"type": "gitlab-config",
"z": "",
"url": "https://git.ng.bluemix.net/api/v3",
"project_id": "11111",
"name": "TEST"
}
]
これで実装は完了です。
使ってみる
試しに動かしてみます。今回は(別の環境作ってないので)今回作成したNode-REDのフローの変更を検知しGitにPushさせる形で試します。
- Node-RED上で「デプロイ」ボタンを押します。そうすると、まずはFanctionsが走ります。Functionsでは以下のようなログが確認できます。
その後、Node-RED側に処理がわたり、Gitに(初回は)新規ファイルが追加されます。
- 試しに更新してみます。フローを少し変更し、「デプロイ」を押します。そうするとファイルの更新が行われ、Git上ではdiffも確認することができます。
まとめ
いかがでしたでしょうか。これでFlow更新時のバージョン管理が自動的に行われるようになりますので、Node-REDで複数人でフロー開発する際も安心して進められるのでは、と思います!