自宅内でお遊び用にローカル用のDNSサーバーを設置してるのですが、設定ファイルの管理が面倒なのでGoogleスプレットシートのデータから設定情報に変換できるツールを作ってみました。
どこでも実行できるように完全初心者ですがHTML+JavaStipt+JQueryで作成しています。
特にJSはコーディングが拙い部分があると思いますがご容赦ください。
つくりたいもの
上のようにホストをスプレッドシートで管理をし、そのデータから以下のような設定ファイルを生成します。
とりあえず自宅で使っているunboundやルーターの簡易DNSサーバー機能向けのコンフィグに対応させます。
server:
local-data: "www.hoge.home. IN A 192.168.10.30"
local-data: "www.hoge.home. IN AAAA fe80::10"
local-data: "ns.hoge.home. IN A 192.168.10.5"
local-data: "mail.hoge.home. IN A 192.168.10.35"
dns host www.hoge.home ip 192.168.10.30
dns host www.hoge.home ip fe80::10
dns host ns.hoge.home ip 192.168.10.5
dns host mail.hoge.home ip 192.168.10.35
画面の作成
HTMLで適当に画面を作ります。
デザイン性皆無ですが、余力ができたらCSSで装飾したいと思います。
<body>
<h1>ホスト情報変換ツール</h1>
<div>
<h2>入力</h2>
<div>
<label for="input-format">形式</label>
<select name="input-format" id="input-format">
</select>
</div>
<div>
<textarea name="input-text" id="input-text" cols="64" rows="24"></textarea>
</div>
<button id="translate">変換</button>
</div>
<div>
<h2>出力</h2>
<label for="output-format">形式</label>
<select name="output-format" id="output-format">
</select>
-- 省略 --
<div>
<textarea name="output-text" id="output-text" cols="64" rows="24"></textarea>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"></script>
<script src="./js/hostconv.js"></script>
</body>
スクリプト
画面の対応形式一覧はJSのformatList
オブジェクトにまとめてJQeury使ってリスト候補を更新させます。対応形式ごとに入出力用の関数を作り、translate
関数からformatList
に登録してある担当の関数を呼び出します。
const formatList = {
json: {
name: 'JSON',
input: null,
output: (data) => { return JSON.stringify(data) }
},
spreadsheet: {
name: 'スプレッドシート',
input: inputSpreadsheet,
output: outputSpreadsheet
},
hosts: {
name: 'hosts',
input: null,
output: outputHosts
},
unbound: {
name: 'unbound',
input: null,
output: outputUnbound,
outOption: '#outopt-unbound'
},
ix: {
name: 'IX',
input: null,
output: outputIX,
outOption: '#outopt-ix'
}
};
$(() => {
//形式選択のコンボボックスに選択肢追加
Object.entries(formatList).forEach(format => {
const option = $('<option></option>', { value: format[0], text: format[1].name });
if (format[1].input) $('select#input-format').append(option.clone());
if (format[1].output) $('select#output-format').append(option.clone());
});
// --- 省略 ---
$('button#translate').click(translate); //変換ボタンが押されたら変換
})
function translate() {
const inputText = $('textarea#input-text').val();
const inputFormat = $('#input-format').val();
const outputFormat = $('#output-format').val();
if (inputFormat in formatList && formatList[inputFormat].input &&
outputFormat in formatList && formatList[outputFormat].output) {
//読み込み
const data = formatList[inputFormat].input(inputText);
//出力
const outputText = formatList[outputFormat].output(data);
$('textarea#output-text').val(outputText);
}
}
データ読み込み
入力されたテキストから以下の形式のオブジェクトに変換します。
[
{ domain: 'ドメイン名', ipv4: 'X.X.X.X', ipv6 : 'XXXX:XX::X'},
{ domain: 'hoge.example.com', ipv4: '10.1.1.1', ipv6 : ''},
.....,
....
]
スプレッドシートやExcelのデータをコピペするとタブ区切りになるので、split
で改行とタブ文字で分割しオブジェクトに代入しています。一応、アドレス形式が合ってるか正規表現でチェックする関数を作り、不正なデータは弾いてます。
function inputSpreadsheet(str) {
return str.split(/\r\n|\n/)
.map(line => line.split('\t'))
.map(v => ({ domain: v[0], ipv4: v[1], ipv6: v[2] }))
.filter(v => (checkDomain(v.domain)) && (checkIPv4(v.ipv4) || !v.ipv4) && (checkIPv6(v.ipv6) || !v.ipv6) && (v.ipv4 || v.ipv6));
}
データ出力
unboundのlocal-data(-ptr)の出力部分です。先ほど作成したオブジェクトの情報もとに設定テキストを生成します。逆引きのコンフィグの出力はON/OFF切り替えできるようにしています。また、出力テキストをそのまま設定ファイルにコピペできるようにインデントを入れられるようにもしています。
function outputUnbound(data) {
const indentList = {
none: '',
tab: '\t',
space2: ' ',
space4: ' ',
};
const indent = indentList[$('#unbound-indent').val()] || '';
const reverse = $('#unbound-reverse').prop("checked");
let output = data.reduce((acc, v) => (
acc + (v.ipv4 ? (indent + 'local-data: \"' + v.domain + '. IN A ' + v.ipv4 + '\"\n') : '')
+ (v.ipv6 ? (indent + 'local-data: \"' + v.domain + '. IN AAAA ' + v.ipv6 + '\"\n') : '')
), '');
if (reverse) {
output += '\n'
+ data.filter(v => v.ipv4)
.reduce((acc, v) => (acc + indent + 'local-data-ptr: \"' + v.ipv4 + ' ' + v.domain + '.\"\n'), '')
+ data.filter(v => v.ipv6)
.reduce((acc, v) => (acc + indent + 'local-data-ptr: \"' + v.ipv6 + ' ' + v.domain + '.\"\n'), '');
}
return output;
}
NEC IXルーター用のコンフィグ出力は以下になります。
function outputIX(data) {
const cmdIP = $('#ix-ip').val();
const ipv4 = (cmdIP === 'both' || cmdIP === 'ipv4');
const ipv6 = (cmdIP === 'both' || cmdIP === 'ipv6');
const pre = 'dns host ';
return data.reduce((acc, v) => (
acc +
(ipv4 ? (
(v.ipv4 ? (pre + v.domain + ' ip ' + v.ipv4 + '\n') : '') +
(v.ipv6 ? (pre + v.domain + ' ip ' + v.ipv6 + '\n') : '')
) : '') +
(ipv6 ? (
(v.ipv4 ? (pre + v.domain + ' ipv6 ' + v.ipv4 + '\n') : '') +
(v.ipv6 ? (pre + v.domain + ' ipv6 ' + v.ipv6 + '\n') : '')
) : '')
), '');
}
できあがったもの
GitHub Pageに上げています。https://caribouhy.github.io/hostconv/
ソース:https://github.com/caribouHY/hostconv
シートのセルをコピーし、
入力エリアにペーストします。
出力形式を選んで変換ボンタを押すと出力できます。
最後に
対応形式やオプションを増やしたり、画面のデザインを改良していきたいです。