みなさん、設定ファイル書いてますか? 私は書いてます。アプリケーションやミドルウェアの設定ファイルから各種クラウドリソースのプロビジョニング用のyml/jsonファイルまで、ITやってると設定ファイル書いて一日終わることもあるのではないでしょうか。というか現代的にはKubernetesですかね。毎日ymlと格闘してないですか?
しかし設定ファイルは環境ごとに大体同じようなものを複数書いたり、あるいは同じ種類(例えばアプリケーションの設定)のものだけどほんの一部だけ違うものがたくさん必要になったり、そういうことありますよね。もちろんAnsibleやらTerraformといったCI/CDツールを導入して自動化する、というのが正攻法ではありますが、プロダクション用途ではないサーバーをとりあえず5台立てて色々検証したいとか、そういう時はとりあえず設定ファイルだけ簡単にテンプレートエンジンで作りたい、とまあ平均的な日本人は考えているに違いありません。
しかし世にテンプレートエンジンは数多あれど、それってライブラリじゃないですか? つまりわざわざプログラミングしなきゃいけないわけ? 俺は別にプログラミングしたいんじゃない、単に設定ファイルをパッとたくさん作りたいだけなんだ! という皆さんのために、Dupler、こちら作りました。
これは何?
Duplerはテンプレートエンジンを動かすためのCLIツールです。内部的にはTiltというテンプレートエンジンが動いていますが、基本的にはRubyのERBのテンプレートを動かすものとして作っています。
単にテンプレートエンジンを使ってテキストファイルを生成するツールなので、もちろん設定ファイルを書くだけではなく、例えばテストデータを簡単に作るとか、その他のどんな用途にも利用可能です。
使い方
まずはgemでインストールします。
$ gem install dupler
任意のディレクトリに移動したら、dupler new
コマンドでduplerのプロジェクトディレクトリの雛形を作成します。
$ dupler new myproject
$ cd myproject
$ ls
README.md templates values.yaml
ここでvalues.yamlファイルは、テンプレートエンジン内で可変になるような値を設定する設定ファイルです。Duplerはこの値をtemplatesフォルダ内のテンプレートにあてて最終的な出力ファイルを作成します。
出力されたサンプルのvalues.yamlを見てみましょう。
# Dupler conf file
# Dupler special element is used for configuration of Dupler itself.
# Uncomment below to enable configuration.
# Dupler:
# time:
# format:
# default: "%Y-%m-%d %H:%M"
sample:
name: Dupler
records: 5
前半のコメントはとりあえず置いておいて、後半を見るとsampleというオブジェクトの中にnameとrecordsという値が設定されていますね。テンプレートからはこれらの値が参照できるようになります。
templates/sample.md.erbを見てみましょう。
# Dupler Example
This file is generated by <%= sample.name %> <%= Dupler::VERSION %>.
Generated at: <%= Time.now %>
## List sample
Iteration example with ActiveSupport time expression.
<% sample.records.times do |i| %>
- <%= i %>, <%= i.days.after.iso8601 %>
<% end %>
ERBの記法である<%= Rubyの式 %>
を使って色々書いてありますね。また後半では繰り返し処理のサンプル書かれています。とりあえずこの状態でこのテンプレートをレンダリングしてみましょう。
テンプレートのレンダリングにはdupler
コマンドを使います。
$ dupler
render: ./output/sample.md
これでoutputディレクトリが作成され、その中にsample.mdファイルがレンダリングされました。
# Dupler Example
This file is generated by Dupler 0.2.1.
Generated at: 2023-11-03 22:46:19 +0900
## List sample
Iteration example with ActiveSupport time expression.
- 0, 2023-11-03T22:46:19+09:00
- 1, 2023-11-04T22:46:19+09:00
- 2, 2023-11-05T22:46:19+09:00
- 3, 2023-11-06T22:46:19+09:00
- 4, 2023-11-07T22:46:19+09:00
ちなみにtemplatesフォルダには複数のテンプレートファイルを保存することができ、その場合は全てのテンプレートが自動的に処理されてoutputフォルダにレンダリング結果が保存されます。
オプション
デフォルトでは設定ファイルはvalues.yaml、出力ディレクトリはoutput、テンプレートファイルはtemplates/*ですが、これらは以下のように変更可能です。
$ dupler -c other-values.yaml other-output other-templates/*
ユースケース
見ていただいた通り、Duplerは超シンプルなテンプレートエンジンを使ってテキストファイルを出力するだけのツールです。ただ例えば、以下のような時にすごい便利なのでぜひ使ってみてください。
複数環境がある設定ファイルの自動生成
よくある開発環境、テスト環境(SIT/UAT/etc.)、ステージング環境、本番環境のような構成の時、設定ファイルの構造は同じだが接続情報や名前などだけが違う、ということがよくありますよね。こういうパターンの場合は同一のテンプレートに対して、環境に合わせた複数のvaluesファイルを使ってDuplerを使うと便利です。
$ dupler -c staging-values.yaml staging_output
テストデータ作成
上記のサンプルのように、ループ処理も普通にできますのでテストデータを簡単に作成する際にも便利です。あとこの場合、デフォルトでRailsでお馴染みのライブラリActiveSupportの機能が利用できます。特に日付関連の処理は劇的に便利です。
例えばサンプルを少しだけ変更した以下のようなテンプレートを考えてみます。
<% 5.times do |i| %>
- <%= i %>, <%= i.days.after.iso8601 %>, <%= ['a', 'b', 'c'].sample %>
<% end %>
こちらを簡単に説明すると、
- 5.timesで5回ループ
- i.days.after.iso8601は現時点からi日後の時刻をiso8601形式で出力
- 配列.sampleは配列の中からランダムに要素を取り出すRubyのメソッド
なので、例えばこのテンプレートは、
- 0, 2023-11-03T23:17:59+09:00, a
- 1, 2023-11-04T23:17:59+09:00, b
- 2, 2023-11-05T23:17:59+09:00, c
- 3, 2023-11-06T23:17:59+09:00, c
- 4, 2023-11-07T23:17:59+09:00, b
こういうふうにレンダリングされます。
あとは少し複雑な使い方として、例えばJSON lineのファイルをレンダリングすることを考えてみましょう。JSON形式で出力する場合、JSONとして正しいフォーマットになっていることが重要です。ここの例でやりたいことは以下です。
- JSON line形式のログファイルを書き出す
- 時刻
@timestamp
は1秒刻み -
message
はa, b, cからランダムに一つ選ぶ
この実装ではERB内でRubyのHashオブジェクトを作成して、JSONに変換しています。こうすることでJSONとしてのフォーマット間違いを防ぐことができますし、1行で書かなくて良いぶん読み書きも楽です。
<% sample.records.times do |i| %>
<%= {
'@timestamp': i.seconds.after.iso8601,
message: ['a', 'b', 'c'].sample
}.to_json %>
<% end %>
このテンプレートの出力結果は以下のようになります。
{"@timestamp":"2023-11-03T23:32:32+09:00","message":"a"}
{"@timestamp":"2023-11-03T23:32:33+09:00","message":"b"}
{"@timestamp":"2023-11-03T23:32:34+09:00","message":"c"}
{"@timestamp":"2023-11-03T23:32:35+09:00","message":"b"}
{"@timestamp":"2023-11-03T23:32:36+09:00","message":"c"}
こうなるともはやテンプレートエンジンと呼んでいいのかわからない使い方ですが、便利は便利です。
まとめ
というわけで、超シンプルなツールの割にすごい便利なので、Dupler使ってみてください。