はじめに
- こんにちは
- 最近、システム環境構築の業務に携わっており、自分で環境構築をする機会が増えてきました
- 対話型コマンドの自動化で ttl コレクションを作ったので、紹介させてもらいます
- 個人的な宣伝といった意味合いが強いですが、どなたかの参考になれば幸いです
【注意】
本記事は、Ansibleの概念やplaybookの実行方法といった「Ansibleの基本」については紹介しておりませんのでご注意ください。
本記事を理解するには少なくとも以下の知識が必要です
- ansible ―― サーバー構成管理・デプロイ・運用タスクを自動化するためのオープンソースツール。Red Hat が開発、IaC(Infrastructure as Code)の代表格のひとつ
- ansible-galaxy ―― Ansible のコレクションを開発し pip3のように開発/ダウンロードできるようにしたコミュニティハブ
- 冪等性 ―― ある操作を1回実行しても、複数回実行しても、最終的な結果が同じになる性質のこと
- teratermマクロ ―― Tera Term に付属するスクリプト言語で、端末操作を自動化するための仕組み
- 対話型コマンド ―― コマンド実行後にさらにコマンド入力が求められるようなものを指します。色々ありますが、例えば下記のようなものです
- sudoコマンド(コマンド実行後にパスワード入力を求められる)
- sshコマンド(パスワード入力を求められる)
ttlコレクションとは
- teratermマクロはwindowsでしか動かないので、teratermマクロのヘルプを見ながら Pythonにできるかぎり移植したansible-galaxyのコレクションです
- 実装しているのは SSH2, serial, telnet への接続で、CLI部分となります。yes/noボックスなどのGUIには対応していません(というかリモート側のGUIとか開けません)
環境準備
今回はWSLで実施します。詳細は下記です。
>wsl --version
WSL バージョン: 2.6.1.0
カーネル バージョン: 6.6.87.2-1
WSLg バージョン: 1.0.66
MSRDC バージョン: 1.2.6353
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26100.1-240331-1435.ge-release
Windows バージョン: 10.0.26200.7462
$ python3 --version
Python 3.12.3
$ ansible-playbook --version
ansible-playbook [core 2.20.0]
$ ansible-galaxy collection list | grep ttl
tand0.ttl 1.25.1
ttlコレクションをダウンロードして使えるようにするには?
こちらでダウンロードできます
$ ansible-galaxy collection install tand0.ttl
ttlコレクションのパラメータ
ttlコレクションのパラメータは以下の通りです
| パラメータ | 内容 | 選択肢(デフォルト値) |
|---|---|---|
| dir | コマンド実行前に移動するディレクトリ先 | path(None) |
| cmd | 実行するTTLのテキスト。filenameと同時に指定された場合 cmdが先に実行されます | str(None) |
| filename | TTLマクロのファイル名 | str(None) |
| creates | ファイルがあった場合はスキップする | path(None) |
| removes | ファイルがない場合はスキップする | path(None) |
| ignore_result | Falseのとき、result値が0の場合はエラーになる | bool(True) |
| param | TTLマクロに渡す引数 | list(None) |
ttlコレクションの属性
- ttlコレクションの属性は check_modeのみ実装しています
- check_modeがTrueの場合、構文チェックをするのみで実行しません
- check_modeがTrueにするには、ansible-playbook 起動時に以下のようにします
$ ansible-playbook site.yml --check
または、ttlモジュール指定時に以下のように記述します
- ttl:
filename: 0010_ok_connect.ttl
check_mode: False
ttlコレクションの戻り値
| 戻り値 | 内容 |
|---|---|
| changed | shellと同じく、実行するとTrueになります |
| cmd | パラメータのcmdと同じです |
| filename | パラメータのfilenameと同じです |
| ignore_result | パラメータのfilenameと同じです |
| stdout | 出力結果です |
| stdout_lines | 出力結果を行単位にリスト化したものです |
| param | 結果として得られるTTLマクロの引数です |
| start | 開始時刻です |
| delta | 終了から開始を引いた時間です |
| end | 終了時間です |
コード例
基本系
- 基本的なコレクションの読み出し方法です
- hosts: localhost
become: False
collections:
- tand0.ttl
tasks:
- name: assert OK
ttl:
cmd: |
result = 1
register: ttl_output
- TTLファイルを指定することも可能ですが、その場合は実行するサーバ上に実行するTTLファイルをあらかじめコピーしておくことが必要です
- hosts: localhost
become: False
collections:
- tand0.ttl
tasks:
- name: assert OK
ttl:
filename: XXX.ttl
register: ttl_output
エラーのチェック
-
ignore_resultを付けると、最後の resultをチェックして0の時にエラーをだすことができます。以下の例ではresultが0になっているので失敗で終了します
- name: result NG
ttl:
cmd: |
result = 0
ignore_result: False
register: ttl_output
戻り値の取得
- 戻り値の value でTTLのパラメータを取得できますので、そちらでチェックすることも可能です
- なお
check_modeが Trueの場合は構文チェックはされませんので値が入りません-
check_modeを考慮する場合はansible_check_modeで値が取れますので以下のように記述します
-
- name: ../test/0000_ok_test.ttl and param
ttl:
cmd: xxx = 1025
register: ttl_output
- name: param check
fail:
when: (not ansible_check_mode) and (ttl_output.value.xxx != 1025)
冪等性対策
-
shell や expectモジュールは処理が行われると changedがTrueになるのと同じく ttlコレクションも changedがTrueになります
-
冪等性対策として expectモジュールと同じく creates と removes が用意されています
-
creates はファイルが存在するとスキップします
-
removes はファイルが存在しないとスキップします
-
冪等性を担保するためには TTLマクロの中でこれらのファイルを追加または削除するとよいでしょう
-
以下は creates の例です。ZZZZZ.txt が存在するとスキップします
- name: ttl creates test
ttl:
filename: 0000_ok_test.ttl
creates: ZZZZZ.txt
chdir: ../test
ignore_result: False
register: ttl_output
- 以下は removes の例です。ZZZZZ.txt が存在しないとスキップします
- name: ttl creates test
ttl:
filename: 0000_ok_test.ttl
removes: ZZZZZ.txt
chdir: ../test
ignore_result: False
register: ttl_output
pexpectのように使う
コマンドライン処理として /bin/sh (windowsであればcmd)を起動することもできます
- name: "test: connect /cmd"
ttl:
cmd: |
connect '/cmd'
;
flushrecv
sendln 'pwd'
wait 'pwd'
wait '$'
;
flushrecv
sendln 'ls'
wait 'ls'
wait '$'
register: ttl_output
実行例
- 簡単な実行例を以下に示します
- hosts: localhost
become: False
collections:
- tand0.ttl
tasks:
- name: "test: connect SSH2"
ttl:
cmd: |
connect 'localhost:2200 /ssh /user=username /passwd=password'
pause 1
flushrecv
sendln 'ping localhost'
wait '$'
register: ttl_output
- name: "test: connect /cmd"
debug:
var: ttl_output.stdout_lines
- 実行結果は以下のようになります
$ ansible-playbook site_sample.yml
Note that the implicit localhost does not match 'all'
PLAY [localhost] *******************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************
ok: [localhost]
TASK [test: connect /cmd] **********************************************************************************************
changed: [localhost]
TASK [test: connect /cmd] **********************************************************************************************
ok: [localhost] => {
"ttl_output.stdout_lines": [
"root@localhost:~$ ping localhost",
"PING localhost (127.0.0.1) 56(84) bytes of data.",
"64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.070 ms",
"",
"--- localhost ping statistics ---",
"1 packets transmitted, 1 received, 0% packet loss, time 0ms",
"rtt min/avg/max/mdev = 0.070/0.070/0.070/0.000 ms",
"root@localhost:~$ "
]
}
PLAY RECAP *************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$
最後に
- いかがでしたでしょうか。対話型のコマンドは色々な種類があると思うのでttlコレクションをうまく使って自動化してみましょう!