見出し画像

たぶんあまり知られていないAnsibleのタスクデバッガー

こんにちは。自動化エンジニアの水谷です。
Ansible Playbookのデバッグについては、あまり書かれている記事も見かけないので、今回はAnsibleバージョン2.5以降に搭載されているデバッグ機能について書いてみたいと思います。


debugger キーワード

一般的なプログラム言語の場合、(Visual Studioなどの)IDEにデバッグ機能が搭載されており、そこでブレークポイントを設定したり、変数の値を確認しながらステップ実行してデバッグを行ったりしますが、Ansibleにはそのような高級なデバッガーがありません。

しかし、Ansibleでは"debugger"キーワードをPlaybookに埋め込むことで、簡単なデバッグができるようになっています。具体的には、タスクが実行された際に、"debugger"キーワードで指定した条件が満たされた場合に、デバッグプロンプトが表示され、そこでデバッグコマンドが実行できるようになっているのです。

例えば、あるタスク内で"debugger: on_failed"と記述しておくと、そのタスクの実行が失敗の結果で終了した場合にデバッグモードとなり、コマンドが入力できるようになります。

なお、このキーワードは、タスク以外にも、PlayやRole、またはGroupに対して記述することができます。

デバッガー起動条件

デバッガーが起動する条件は以下の5つがあります。これを"debugger: "の後に記述することになります。

・always:常にdebugger起動
・on_unreachable:ホストに到達できなかった場合に起動
・on_failed:taskがFailしたときに
・on_skipped:taskがスキップされたときに
・never:debuggerは起動しない

この中で主に使われるのは、"on_failed"になります。

以下にPlayでの記述とタスクでの記述の例を示します。

Playでの使用例

---
- hosts: all
  debugger: on_failed
  tasks:
    - name: install apache
      yum:
        name: httpd
        state: present


taskでの使用例

---
- hosts: all
  tasks:
    - name: install apache
      yum:
        name: httpd
        state: present
      debugger: always

"debugger"キーワードを複数の場所で記述した場合は、より狭い範囲での指定が優先されます。上の例のように、Playの中では"on_failed"として、タスクの実行が失敗した場合にデバッグモードになるように記述していますが、下のタスクでは"always"としていますので、タスクが成功しても失敗しても、このタスクの実行が終わった時点でデバッグモードになります。

デバッグコマンド

さて、条件が満たされデバッグモードに入った場合、下の例のようなプロンプトが表示されます。

[192.108.1.1] TASK: my task (debug) >

ここでデバッグコマンドが実行できるのですが、コマンド数は非常に少なく、以下の5つのみです。

p (print): 変数の表示
u (update_task): Taskの更新
r (redo): Taskの再実行
c (continue): Playの実行継続
q (quit): Play実行終了

また、変数への代入式を記述することで、変数の更新ができます。

少ないとはいえ、Playbookのデバッグで重要となる変数の値の確認や、また変数の値の変更ができますので、デバッグを行うための最低限のコマンドが実装されていると言えます。

では、コマンドを1つずつ見ていきましょう。

変数の表示 (p コマンド)

"p task.args"でタスク引数を表示します。

p task.args → すべての引数
p task.args['name'] → 特定の引数

"p task_vars"はタスク変数を表示します。

p task_vars → すべての変数
p task_vars['inventory_file'] → 特定の変数

ホスト情報の表示は"p host"です。

p host

また、タスク実行結果を表示するには"p result._result"とします。標準出力だけを表示することもできます。

p result._result
p result._result['stdout'] → 標準出力を表示

タスク引数および変数の更新
以下のように記述することで、タスク引数を更新することができます。

task.args['name']='new_value'

同様に変数の更新は以下のように記述します。

task_vars['name']='new value'

※task_varsを更新した場合はu(update_task)コマンドを実行して(内部的にタスクの再構築を行う)必要があります。

実際に試してみると

では、以下のPlaybookを例にして実際にデバッガーの動作を見てみましょう。

---
- name: test playbook
  hosts: windows
  gather_facts: false
  vars:
    package: notepadplus
  tasks:
    - name: install notepad++
      win_chocolatey:
        name: "{{ package }}"
        state: present
      debugger: on_failed

このPlaybookは"win_chocolatey"モジュールを使って、Notepad++をインストールするものですが、変数"package"が"notepadplusplus"とすべきところが"notepadplus"となっています。このため、タスクは失敗し、デバッグモードに移行するはずです。

実際に実行してみると以下のようになります。

画像1

そこで、"p result._result['stdout']"を実行して、標準出力を見てみます。

画像2

これにより、パッケージが見つからなかったことがエラーの原因だとわかります。つまり、タスク引数"package"が正しくないようです。

では、"p task.args"でタスク引数を表示してみましょう。

画像3

では、"package"引数を"notepadplusplus"に変更して、"r (redo)"コマンドで再実行してみましょう。

画像4

これでタスクの実行が成功し、Notepad++がインストールされました。

debugger: 以外での設定方法

最後に2点ほど補足です。

1つ目は、デバッガーの起動制御が、Playbookの中だけではなくansible.cfgでもできることです。これには、ansible.cfgに以下の2行を追加します。

[defaults]
enable_task_debugger = True

また、環境変数"ANSIBLE_ENABLE_TASK_DEBUGGER"を"True"とすることでも、デバッガーが起動するようにできます。

2つ目は、PlaybookをAnsible TowerやAWXで実行する場合は、Playbook内の"debugger"を削除する必要があることです。

これは、そのPlaybookをAnsible TowerやAWXで実行している状況でデバッガーが起動すると、(UI上からコマンドを入力することができないため)Playbookの実行が終了せずに止まった状態が続いてしまうためです。

――――――――――――――――――――――――――――――――――

執筆者プロフィール:水谷 裕一
大手外資系IT企業で15年間テストエンジニアとして、多数のプロジェクトでテストの自動化作業を経験。その後画像処理系ベンチャーを経てSHIFTに入社。
SHIFTでは、テストの自動化案件を2件こなした後、株式会社リアルグローブ・オートメーティッド(RGA)にPMとして出向中。RGAでは主にAnsibleに関する案件をプレーイングマネジャーとして担当しながら、Ansibleの社内教育や、外部セミナー講師も行っている。

画像5

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら 
https://recruit.shiftinc.jp/career/