0%

RESTクライアントのCLIをNode.jsのCommander.jsを使って作成する

開発中のRESTクライアントはcurlコマンドを使っていましたが、他の人に使ってもらうためにコマンドラインツールが必要になります。サーバーと同じ開発言語のNode.jsで実装します。サーバーやデータベースのコンテナとセットにしてDocker Composeで配布する予定ですが、動作確認のためとりあえず単体で動くサンプルを作成しました。

プロジェクトの作成

プロジェクトのディレクトリを作成して以下のようなファイルを作成します。

$ cd ~/node_apps/iot-util
$ tree .
.
├── Dockerfile
├── app.js
├── commands
│   └── status.js
├── docker-compose.yml
├── node_modules -> /dist/node_modules
└── package.json

Dockerホストのプロジェクトのディレクトリに/dist/node_modulesへのシムリンクを作成します。

$ cd ~/node_apps/iot-util
$ ln -s /dist/node_modules .

Node.jsの実行はDockerコンテナで行いますが、イメージ再作成とnode_modulesの再ビルドを回避するためnode_modulesはDockerホストのボリュームにマウントして使います。ベースイメージはオフィシャルのnode:0.12を使います。

~/node_apps/iot-util/Dockerfile
FROM node:0.12
MAINTAINER Masato Shimizu <ma6ato@gmail.com>

RUN mkdir -p /app
WORKDIR /app

COPY package.json /app/
RUN mkdir -p /dist/node_modules && ln -s /dist/node_modules /app/node_modules && \
npm install
COPY . /app
ENTRYPOINT ["npm", "start"]

Docker Composeを使ってビルドとCLIの実行をします。環境変数のMESHBLU_URLは後でdocker-compose.ymlのlinksから取得します。

~/node_apps/iot-util/docker-compose.yml
iotutil:
build: .
volumes:
- .:/app
environment:
- MESHBLU_URL=https://10.3.0.165/

Commander.jsを使う

Node.jsにはCLIを作るためのパッケージがいくつかありますが、よく使われているCommander.jsで実装していきます。

~/node_apps/iot-util/package.json
{
"name": "iot-util",
"description": "IoT Toolkit",
"version": "0.0.1",
"private": true,
"dependencies": {
"commander": "^2.8.1",
"request": "^2.55.0"
},
"scripts": {"start": "node app.js"}
}

以下のサイトを参考にしてエントリーポイントのapp.jsに必要なコードを書きます。

~/node_apps/iot-util/app.js
#!/usr/bin/env node

var program = require('commander')
, status = require('./commands/status.js');

program
.version('0.0.1')
.usage('<command>');

program
.command('status')
.description('show status')
.action(status.commandStatus);

program.parse(process.argv);
if (process.argv.length < 2) {
console.log('You must specify a command'.red);
program.help();
}

exports.program = program;

個別のコマンドはファイル名にコマンド名をつけて、commandsディレクトリに配置します。今回はサンプルにstatus.jsを作成しました。サーバーは自己署名の証明書を使っています。Node.jsのrequestパッケージの場合はcurl --insecureに相当するrejectUnauthorized: falseのオプションを付けます。

~/node_apps/iot-util/commands/status.js
var request = require('request')
, path = require('path');

module.exports = {
commandStatus: function(symbol, command) {

var filename = path.basename(__filename),
cmd = filename.substr(0, filename.lastIndexOf('.'));

var options = {
url: process.env.MESHBLU_URL + cmd ,
agentOptions: {
rejectUnauthorized: false
}
}

request.get(options,function(error, response, body) {
if (!error && response.statusCode == 200){
var body = JSON.parse(body);
console.log(body);
} else if (error) {
console.log('Error: ' + error);
}
});
}
}

CLIの実行

Dockerイメージのビルドをします。

$ cd ~/node_apps/iot-util
$ docker-compose build

コマンドファイルと同じ名前の引数を渡してMeshbluのstatusを取得してみます。

$ docker-compose run --rm iotutil status

> iot-util@0.0.1 start /app
> node app.js "status"

{ meshblu: 'online' }
Removing iotutil_iotutil_run_1...

ヘルプを実行する場合は、--に続けて--helpフラグを標準入力から取得します。

$ docker-compose run --rm iotutil -- --help

> iot-util@0.0.1 start /app
> node app.js "--help"


Usage: app <command>


Commands:

status show status

Options:

-h, --help output usage information
-V, --version output the version number

Removing iotutil_iotutil_run_1...