LoginSignup
5
11

More than 5 years have passed since last update.

How to use ansible-playbook from python code - Ansible playbookをPython コードから実行する

Last updated at Posted at 2018-10-28

Overview

ただし、こちらの記事の記載の通り既存のplaybookが完成している場合、
互換性がないので使えない。

python nativeで最初から作るならば問題ないが、
既にAnsibleで作ってしまった環境を徐々に移行していくためには
当面、ansible-playbookを実行する必要がある。
従ってpython native コードに求められる機能は主に二つ。

  • ansible-playbook を読み込める(実行できる)
    • 既存のレシピを実行する為
  • ansible-playbook を生成できる
    • 完全に移行するまでは ansile-playbook... の実行も続くため

どうやってansible-playbookを実行するか

perl の systemみたいに ansible-playbook xxxx としてシェルを呼ぶのでは意味が無い。
ちゃんとpythonから呼ぶ必要がある
どうやら ansible playbook-executor を使えば良いようだ。

具体的には以下の部分。
play_sourceを定義し、TQMを用いた場合と異なり
PlaybookExecutor に渡すことで、ansible-playbookコマンドを実行した通りの動作になる。
resultや出力の制御を行っていないがその辺はおいおい。


    pbex = PlaybookExecutor(
        playbooks=[playbook_path],
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        options=options,
        passwords=passwords
    )
    results = pbex.run()

taskを直接記述する場合

        play_source = dict(
            name="Ansible Play",
            hosts=['localhost'],
            gather_facts='no',
            tasks=[dict(action=dict(
                module='command',
                args=dict(cmd='/usr/bin/uptime')
            ))]
        )
        play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

        tqm = None
        results_callback = ResultCallback()
        try:
            tqm = TaskQueueManager(
                inventory=inventory,
                variable_manager=variable_manager,
                loader=loader,
                options=options,
                passwords=passwords,
                stdout_callback=results_callback,
            )

2018.10.29 追記

以下のようにPlaybookExecutor._tqm._stdout_callbackをフックしてやれば拾えた。
既存サンプルを更新しても良いが比較できるように
ansible-runner_callback.py として commit しました。

class ResultCallback(CallbackBase):

    def __init__(self, *args, **kwargs):
        super(ResultCallback, self).__init__(*args, **kwargs)
        self.host_ok = {}
        self.host_unreachable = {}
        self.host_failed = {}

    def v2_runner_on_unreachable(self, result):
        super(ResultCallback, self).v2_runner_on_unreachable(result)
        print(json.dumps({result._host.name: result._result}, indent=4))

    def v2_runner_on_ok(self, result, **kwargs):
        super(ResultCallback, self).v2_runner_on_ok(result)
        print(json.dumps({result._host.name: result._result}, indent=4))

    def v2_runner_on_failed(self, result, *args, **kwargs):
        super(ResultCallback, self).v2_runner_on_failed(result)
        print(json.dumps({result._host.name: result._result}, indent=4))

    executor = PlaybookExecutor(
        playbooks=[playbook_path],
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        options=options,
        passwords=passwords
    )
    results_callback = ResultCallback()
    executor._tqm._stdout_callback = results_callback
    results = executor.run()

サンプルスクリプト

5
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
11