モジュールのデバッグ

詳細なデバッグ手順

Ansible モジュールは、モジュールファイルとラッパースクリプト内のさまざまな Python モジュールの boilerplate で構成される zip ファイルとしてまとめて置かれます。モジュールで実際に何が発生しているかを確認するには、ラッパーからファイルを抽出する必要があります。ラッパースクリプトは、これを可能にするヘルパーメソッドを提供します。

以下の手順では、ターゲットホストに localhost を使用していますが、同じ手順を使用してリモートホストに対してデバッグすることもできます。一時ファイルを使用せずにデバッグを行う簡単な方法は、「簡単なデバッグ」を参照してください。

  1. コントロールホストで ANSIBLE_KEEP_REMOTE_FILES1 に設定します。これにより、Ansible はモジュール実行後も削除せずにリモートモジュールファイルを維持します。-vvv オプションを使用すると、Ansible の詳細が表示されます。一時モジュールファイルのファイル名が表示されます。

    $ ANSIBLE_KEEP_REMOTE_FILES=1 ansible localhost -m ping -a 'data=debugging_session' -vvv
    <127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: badger
    <127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" )'
    <127.0.0.1> PUT /var/tmp/tmpjdbJ1w TO /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/AnsiballZ_ping.py
    <127.0.0.1> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/AnsiballZ_ping.py && sleep 0'
    localhost | SUCCESS => {
        "changed": false,
        "invocation": {
            "module_args": {
                "data": "debugging_session"
            },
            "module_name": "ping"
        },
        "ping": "debugging_session"
    }
    
  2. 前の手順から一時ディレクトリーに移動します。前のコマンドがリモートホストに対して実行した場合は、最初にそのホストに接続します。一時ディレクトリーに移動する前に、そのホストに接続します。

    $ ssh remotehost  # only if not debugging against localhost
    $ cd /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595
    
  3. ラッパーの explode コマンドを実行して、文字列を使用可能な Python ファイルに変換します。

    $ python AnsiballZ_ping.py explode
    Module expanded into:
    /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/debug_dir
    

    ラッパーファイルを調べたい場合は、小さい Python スクリプトに、大きな base64 でエンコードされた文字列が記載されます。文字列には、実行するモジュールが含まれます。

  4. 一時ディレクトリーを確認すると、以下のような構造が表示されます。

    ├── AnsiballZ_ping.py
    └── debug_dir
        ├── ansible
        │   ├── __init__.py
        │   ├── module_utils
        │   │   ├── __init__.py
        │   │   ├── _text.py
        │   │   ├── basic.py
        │   │   ├── common
        │   │   ├── compat
        │   │   ├── distro
        │   │   ├── parsing
        │   │   ├── pycompat24.py
        │   │   └── six
        │   └── modules
        │       ├── __init__.py
        │       └── ping.py
        └── args
    
    • AnsiballZ_ping.py base64 でエンコードされた文字列に保存されたモジュールコードを含む Python スクリプトで、モジュールを実行するためのさまざまなヘルパー関数が含まれます。

    • ping.py は、モジュール自体のコードです。このコードを変更して、モジュールまたはデバッグの目的を確認することができます。

    • args ファイルには JSON 文字列が含まれています。この文字列は、モジュール引数および、Ansible がモジュールに渡すその他の変数を含むディクショナリーで、動作を変更します。このファイルを変更して、モジュールに渡されるパラメーターを変更します。

    • ansible ディレクトリーには、modules のモジュールコードと、モジュールに使用される ansible.module_utils のコードが含まれています。Ansible には、モジュール内の ansible.module_utils インポートのファイルが含まれますが、他のモジュールからのファイルは含まれません。モジュールで ansible.module_utils.url が使用される場合は、Ansible にそれが含まれます。ただし、モジュールに requests が含まれる場合は、モジュールを実行する前に Python requests ライブラリー がシステムにインストールされていることを確認する必要があります。

    作成したモジュールコードではなく、モジュールのこの boilerplate コードの一部に問題があると思われる場合は、このディレクトリーのファイルを変更できます。

  5. 展開されたツリーのコードまたは引数を編集したら、execute サブコマンドを使用してこれを実行します。

    $ python AnsiballZ_ping.py execute
    {"invocation": {"module_args": {"data": "debugging_session"}}, "changed": false, "ping": "debugging_session"}
    

    このサブコマンドは、sys.path の最初の項目として debug_dir に絶対パスを挿入し、args ファイルの引数を使用してスクリプトを呼び出します。問題を理解するまで、このモジュールの実行を継続できます。変更を実際のモジュールファイルにコピーし、実際のモジュールが ansible または ansible-playbook で動作することをテストすることができます。

簡単なデバッグ

モジュール (ローカルまたはリモートのいずれか) でデバッガーを実行する最も簡単な方法は、epdb を使用します。任意のブレークポイントで、コントロールノードのモジュールコードに import epdb; epdb.serve() を追加します。デバッガーに接続するには、epdb.connect() を実行します。host および port を指定する方法は、epdb ドキュメント を参照してください。リモートノードに接続する場合は、コントロールノードとリモートノードとの間のファイアウォールが許可されているポートを使用するようにしてください。

この手法はリモートデバッガーと動作しますが、特定のリモートデバッグツールが機能する保証はありません。

q ライブラリーは、もう 1 つの便利なデバッグツールです。

print() ステートメントはモジュール内では機能しないため、特定のデータを確認する場合は例外を発生させます。モジュール内のどこかに raise Exception(some_value) を置き、通常どおり実行します。Ansible はこの例外を処理し、メッセージをコントロールノードに渡し、表示します。