Go
golang

デプロイ先でのファイルハッシュ値とディレクトリ構成をチェックしたい、そんな時に使えるツールをGo言語で作りました!

More than 1 year has passed since last update.

発端

お仕事で、時々以下のような需要がありました。

  • インストーラで配置したファイルやディレクトリが意図した構成になっているか確認したい
  • 上記に加えて個々のファイルが意図したバージョンになっているかハッシュ値で確認したい

デプロイ先の評価環境に別途ツールをインストールせずにチェックできるツールが欲しいなぁと思い、
Go言語でgckdirというツールを作りました٩( 'ω' )و

各プラットフォーム向けの最新バイナリは、こちらからダウンロードしてくださいm(_ _)m

こんなツールです

以下のような特徴があります。

  • 正解のハッシュテーブルファイル(*.json)を生成できる
  • 生成したハッシュテーブルファイル(*.json)とツールだけコピーすれば、デプロイ先でチェックができる
    • 評価環境のレジストリやパッケージマネージャに影響を与えることなくチェックができる
  • チェック結果がFailなら0以外のExitCodeが返る
    • スクリプト内で使用する際に、判定結果によって条件分岐ができる
  • チェック結果をレポートhtmlとして出力できる
    • 結果確認がちょっとだけしやすくなる☆
  • ハッシュ値の違いは無視して、ファイルとディレクトリの構成だけチェックできる
    • 開発序盤から中盤の「ファイルなどの配置だけチェックしたい」時期に使うイメージ
  • 困ったら-hオプションでいい感じのヘルプが表示されます

ハッシュテーブル生成

以下のようにサブコマンドにgenerateまたはgenを指定することで正解ファイルを生成します。

$ ./gckdir gen (正解のディレクトリ) (ハッシュテーブルファイル名.json)

デプロイ先でチェック

以下のようにサブコマンドにverifyまたはverを指定することで、正解ファイルやディレクトリと対象のディレクトリとを比較検証します。

$ ./gckdir ver (ハッシュテーブルファイル名.json) (対象ディレクトリ)

verコマンドに--reportオプションをつければBootstrapで少し見やすくしたレポートhtmlを生成します。

$ ./gckdir ver --report --output (レポートファイル名.html) (ハッシュテーブルファイル名.json) (対象ディレクトリ)

レポートファイルの名前を指定する時は--outputオプションに続けて名前を指定して実行してください。指定しない場合は自動的に日時からResult_{YYYYMMDD}-{hhmmss}.{nanosecond}.htmlという感じの名前で保存されます。

さらに、verコマンドに--openオプションをつけて実行すれば、規定のブラウザでレポートhtmlを開きます。(デスクトップ環境のみ)

「まだモジュールは差し替わるけど、ファイルやディレクトリの配置がうまくいってるかだけ確認したい」というときのために--no-hvオプションも用意しています。

$ ./gckdir ver --no-hv (ハッシュテーブルファイル名.json) (対象ディレクトリ)

困ったら-h

サブコマンド

「えっと、どんなサブコマンドがあるんだっけ?」、そんなときには-hオプションをつけて実行してください。

$ ./gckdir -h

image.png

サブコマンドのオプション

「あれ、このサブコマンドのオプションは・・?」、そんなときにもサブコマンドの後に-hをつけて実行してください。

$ ./gckdir verify -h

image.png

謝辞

Gitみたいにサブコマンドとオプションでいろいろな使い方ができるcliツールを簡単に作れたのは、ひとえに@tcnksmさんのgcliのおかげです。この場をお借りしてお礼申し上げます。

gcli

いや、ほんとうに素晴らしいんです、gcli。めちゃくちゃ感動したのでもうちょっとお話させてください。

例えばgenerateverifyサブコマンドをもったclitestというツールを作ろうと思ったら、以下を実行するだけでcliとしての大部分が自動生成されます。(もっと詳しい情報はGitHub公式ページのREADMEをご覧ください。)

$ gcli new -c generate -c verify clitest

「よし作ろう」となった瞬間にgcliでスケルトンを生成して、次の瞬間にはコマンドの中身の実装に専念できます。これからGo言語でcliを作るすべての人にオススメしたいツールです。

os.Exitとrun関数

今回作ったgckdirツールでも使っている小技ですが、mainを下記のように実装してrun関数が適切なExitCodeを返すことで、run関数でのdeferをしっかり実行した後でExitすることができます。os.Exitdeferを実行せずに即時終了してしまうため、このハック結構重要です。

func main() {
    os.Exit(run(os.Args))
}

さらにExitCodeをiotaを使ったconstで定義しておくと、C#などでの0始まりのenum型のように使えて便利です。

const (
    // ExitCodeOK means that this app successfully finished to run.
    ExitCodeOK int = iota
    // ExitCodeVerificationFailed means that the Verification has ended with errors.
    ExitCodeVerificationFailed
    // ExitCodeFailed means that this app failed to run. Please check the error message.
    ExitCodeFailed
...
)

このrun関数を用いる技は、@tcnksmさんがみんなのGo言語[現場で使える実践テクニック]の4章で書いておられる「コマンドラインツールを作る」という記事を読んで習得しました。私のようにちゃんとしたcliを初めて作る方は、こちらも読みながら開発をすすめるととってもはかどるかと思います。