てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] 「ansible-pylibssh not installed, falling back to paramiko」という警告の意味と対処

はじめに

最近のバージョンの Ansible で Cisco IOS などのネットワーク機器に操作する Playbook を実行すると、以下のような警告(WARNING)を見かけたことはないでしょうか、

[WARNING]: ansible-pylibssh not installed, falling back to paramiko

エラーではないので、実行できるといえばできるのですが気になることもあると思います。

この警告の意味と表示させない対処方法についてまとめます。

意味

ネットワークモジュールが長らく内部的に利用している SSH クライアントライブラリとして、paramiko があります。

最近は ansible-pylibssh というもの新しいものもあります。登場した経緯は Ansible の公式ブログの記事に書かれています。

そして、各ネットワークモジュールが内部的に利用している ansible.netcommon コレクションの 3.0.0 から、デフォルトでは以下の動作になりました(該当 changelog))。Ansible Community Package の正式バージョンとしては 6.0.0 からです。

  • 条件1: ansible-pylibssh がインストールされている場合は ansible-pylibssh を優先的で利用
  • 条件2: ansible-pylibssh がインストールされていない場合は paramiko を利用(フォールバック)

これは、ansible.netcommon.network_cli コネクションプラグインでいうと、ssh_type パラメーターのデフォルトが auto になったことによる動作です。

例の警告は、条件2のときに「ansible-pylibssh がインストールされていない場合は paramiko を利用するよ」というメッセージです。

明示的に paramikoansible-pylibssh を使うと設定していなくて、自動的に動作をこうしたよ、と伝えてくれる形です。

発生条件

分かっている範囲の発生条件をまとめると以下の通りです。

  • ansible.netcommon コレクション 3.0.0 以上を利用
  • ansible-pylibssh は未インストール
  • ansible.netcommon.network_cliコネクションプラグインのパラメーターで、ssh_typeが デフォルトのauto` のまま

対処

ssh_type が デフォルトの auto のままで、paramiko にフォールバックする動作をさせなければ、警告は表示されなくなります。

つまり、大きく分けて2つの対処方法があります。

  • ansible-pylibssh をインストールしつつ auto に任せる
  • paramikoansible-pylibssh か明示指定する

それぞれの設定方法は以下のとおりです。

対処方法1: ansible-pylibssh をインストールしつつ auto に任せる

あらかじめ ansible-pylibssh をインストールすれば paramiko にフォールバックすることはありません。

このアプローチにする場合は、pipansible-pylibssh をインストールします。

pip install ansible-pylibssh

これで ansible-pylibssh を使うことになります。paramiko と挙動が変わってくる部分もあります。

対処方法2: paramiko を使うことを明示指定する

paramiko を使うよ、と明示的に指定しても警告が表示されなくなります。

変数で指定する場合:

ansible_network_cli_ssh_type: paramiko

ansible.cfg で指定する場合:

[persistent_connection]
ssh_type = paramiko

環境変数で指定する場合:

ANSIBLE_NETWORK_CLI_SSH_TYPE=paramiko

補足

もちろん、ansible-pylibssh をインストールしたうえで、ansible-pylibssh を使うと明示指定しても大丈夫です。

ansible-pylibssh を使うと明示指定する場合の設定値は ansible-pylibssh ではなく libssh である点に注意が必要です(ssh_type パラメーターのドキュメントはここちら)。

変数で指定する場合:

ansible_network_cli_ssh_type: libssh

ansible.cfg で指定する場合:

[persistent_connection]
ssh_type = libssh

環境変数で指定する場合:

ANSIBLE_NETWORK_CLI_SSH_TYPE=libssh

なお、どっちが使われたのかは、ansible-playbook-vvvv をつけると確認できます。詳細は以下の記事を参照してください。

tekunabe.hatenablog.jp

おわりに

最近では、AAP のデフォルトの Execution Environment (実行環境コンテナ)にも ansible-pylibssh が入っていたりするので、知らず知らずのうちに ansible-pylibssh を使っているというケースも増えてくるかなともいます。

[Ansible] AnsibleをバージョンアップしたらCisco IOSに対するPlaybookが認証エラーになった原因と対処

はじめに

先日、Ansible 4系から 6系にバージョンアップしたら、今まで正常に動いていた Cisco IOS に対して処理する Playbook が動かなくなる現象に出会いました。

以下のように、認証エラーです。

fatal: [sw01]: FAILED! => {"changed": false, "msg": "Failed to authenticate: Authentication failed."}

認証情報は変えてないので不思議でした。

Ansible 4系は ansible-core としては 2.11 系、Ansible 6系は 2.13 系です。この間で仕様変更的になことが起きたようです。

調べてみると、どうやら、変数として ansible_password を設定していても、デフォルトの秘密鍵 ~/.ssh/id_rsa を見つけてそれを利用しているためのようでした(ペアの公開鍵は対象に未設定)。

以下の条件で再現しました。

  • ansible.netcommon コレクション 2.4.0 以上
  • ansible-core 2.12.9 以上 or ansible-core 2.13.4 以上
  • コントロールノードに ~/.ssh/id_rsa あり。ただし、ペアの公開鍵はターゲットノードに仕込んでいない
  • paramiko 使用

おそらく、Cisco IOS に限らない現象だと思います。

以下、調べたことなどをまとめます。

基本前提環境

  • paramiko インストール済み
  • ansible-pylibssh は未インストール
  • Python 3.9
  • RHEL 8.6

再現

再現を試みた環境やファイルについてです。

環境

~/.ssh/id_rsa がある状態です。

ただし、この秘密鍵のペアの公開鍵は、Ansible の接続対象の機器には仕込んでいない状況です。

ファイル類

イベントリファイル

インベントリファイルは以下のようなものを利用しました。

inventory.ini

[ios]
ios01 ansible_host=192.168.1.11

変数定義ファイル

インベントリファイルで定義した ios グループの変数は以下の通りです。

認証には公開鍵認証方式ではなく、パスワード認証(ansible_password変数)を利用する意図です。

group_vars/ios.yml

---
ansible_network_os: cisco.ios.ios
ansible_connection: ansible.netcommon.network_cli
ansible_user: dummy_user
ansible_password: dummy_password    # パスワード認証を利用したい

Playbook

実行する Playbook は、show コマンドを実行するだけの簡単なものです。

ios_show.yml

---
- hosts: ios01
  gather_facts: false
  tasks:
    - name: show version
      cisco.ios.ios_command:
        commands:
          - show version

実行

ansible-core 2.11 系のころは正常に実行できましたが、今回は

  • ansible-core 2.13.5
  • ansible.netcommon コレクション 4.0.0
  • cisco.ios コレクション 4.0.0

の環境で実行します。

$ ansible-playbook -i inventory.ini ios_show.yml 

PLAY [ios01] *************************************************************************************

TASK [show version] ******************************************************************************
[WARNING]: ansible-pylibssh not installed, falling back to paramiko
fatal: [ios01]: FAILED! => {"changed": false, "msg": "Failed to authenticate: Authentication failed."}

PLAY RECAP ***************************************************************************************
ios01   : ok=0  changed=0  unreachable=0  failed=1  skipped=0  rescued=0  ignored=0

認証エラー Failed to authenticate: Authentication failed. となってしまいました。

なお、~/.ssh/id_rsa を適当な名前に変更したら OK になりました。

NG条件まとめ

色々試していくと、冒頭にも書いた通り、以下の条件でNGとなりました。

  • ansible.netcommon コレクション 2.4.0 以上
  • ansible-core 2.12.9 以上 or ansible-core 2.13.4 以上
  • コントロールノードに ~/.ssh/id_rsa あり。ただし、ペアの公開鍵はターゲットノードに仕込んでいない
  • paramiko 使用

対処

ansible-core や ansible.netcommon コレクションのバージョンはそのまま、かつパスワード認証のままにしても、対処方法はいくつか考えらます。

対処1: デフォルトの秘密鍵を探さないように指定

今回は、デフォルトの秘密鍵(今回は ~/.ssh/id_rsa)を探して見つかって、それを使ったがターゲットノードにペアの公開鍵がないくて認証エラーという状態でした。

パスワード認証を利用したい場合は、秘密鍵を探さないように指定できます。PARAMIKO_LOOK_FOR_KEYS という設定項目を利用します。

ansible.cfg で指定する場合

[paramiko_connection]
look_for_keys = False

環境変数で指定する場合

ANSIBLE_PARAMIKO_LOOK_FOR_KEYS=False

対処2: pylibssh を利用する

ネットワークモジュールが長らく内部的に利用している SSH クライアントライブラリとして、paramiko があります。

最近は pylibsshPythonのパッケージ名としてはansible-pylibssh)というもの新しいものもあります。登場した経緯は Ansible の公式ブログの記事に書かれています。

今回は、paramiko から pylibssh を利用するように変更したら、パスワード認証のまま認証が通るようになりました。

手順は以下の通りです。

  1. pylibssh のインストール

    pip でインストールする。

     pip install ansible-pylibssh
    
  2. pylibssh を利用するように指定

    group_vars/ios.yml に以下を追加する。 yaml ansible_network_cli_ssh_type: libssh なお、ansible.netcommon コレクション 3.0.0 以上では、デフォルトの ansible_network_cli_ssh_type: auto の場合でも pylibssh がインストールされていれば pylibssh を優先で使う仕様になりました。そのため、厳密には ansible.netcommon コレクション 3.0.0 以上では、明示的な指定は必要ありません。

    他にも、環境変数で指定する方法もあります。詳細は ansible.netcommon.network_cli コネクションプラグインのドキュメントssh_type パラメーターの欄を参照してください。

環境によっては、pylibssh を利用するようにしたことで別の現象が発生することもあるので、これはこれで確認が必要そうです。

参考

ansble.netcommon 4.0.0 時点の実装として、password の指定があって private_key_file の指定がない場合は鍵を探さない、という実装は残っていそうだが、詳細は追えていない。これに頼らないほうが無難そう。

おまけ: 試行錯誤ツイート

[Ansible] Python から Playbook を実行できる ansible-sdk をためしてみた

はじめに

最近、ansible/ansible-sdk というリポジトリが公開されました。

Python から Playbook を実行できるようです。とりあえず気になるので試してみました。

リポジトリ内にサンプルの Python スクリプトと、Playbookが入ってるので試すだけならかなり簡単でした。

現状はまだPyPi にも公開されておらず、ドキュメント上も TBD な箇所も多いため、発展途上のようです。書いてあることがすぐ通用しなくなる可能性が高いのでご了承ください。雰囲気だけということで・・。

[2023/05/14 追記ここから]

2023/03/08 に バージョン 1.0.0 としてリリースされていたようです。PyPi にも登録され、pip install ansible-sdk でインストールできるようになりました。ただし、記事全体的に 2022年10月に試した時点となっていますのでご注意ください。

[追記ここまで]

インストール

ドキュメントにインストール方法が掲載されています。

https://github.com/ansible/ansible-sdk/blob/main/docs/source/install.rst

まずは ansible-sdk リポジトリを clone して、できたディレクトリに移動します。

git clone https://github.com/ansible/ansible-sdk.git
cd ansible-sdk

(ドキュメントにあった git clone git://github.com/ansible/ansible-sdkOperation timed out というエラーになってしまったので、https にしました)

続いて関連パッケージのインストールです。今回試す範囲では不要そうなものもありますが、今回用の venv 内にとりあえず全部インストールしてみます。

pip install ansible-core
pip install ansible-runner
pip install receptorctl

最後に、ansible-sdk をインストールします。

pip install -e .

先述の通りまだ PyPi に登録されていないので、git clone して このようにする必要があります。

ansible 関連の Python パッケージは以下のようになりました。

 % pip list | grep -i ansible
ansible-core    2.13.5
ansible-runner  2.2.1
ansible-sdk     0.0.1   /Users/sakana/Documents/git/ansible-sdk

ここでの ansible-sdk のバージョン表記は 0.0.1 となりました。ただ、リポジトリ上は現状はまだタグやリリースがない状態です。

おためし

サンプル類の調査とそれの実行を試します。

サンプルはすべて、このコミット時点のものです。

サンプル類の調査

clone したディレクトリの examples 内にサンプルがいくつかあります。

% cd examples
% tree
├── datadir
│   ├── inventory
│   │   └── hosts
│   └── project
│       └── pb.yml
├── example_common.py
├── example_docker_job.py
├── example_mesh_job.py
├── example_podman_job.py
├── example_subprocess_job.py
└── receptor_config
    ├── bar.yml
    ├── baz.yml
    └── foo.yml

example_*.py の種類を見るといくつか形式があるようです。今思えば mesh に対応するために receptorctl をインストールするという手順だったのかなと思います。

今回は、一番シンプルそうな example_subprocess_job.py を試します。

example_subprocess_job.py

import asyncio


from ansible_sdk.executors import AnsibleSubprocessJobExecutor, AnsibleSubprocessJobOptions
from example_common import run_one_stdout, run_one_events, run_many


async def main():
    executor = AnsibleSubprocessJobExecutor()
    executor_options = AnsibleSubprocessJobOptions()

    await run_one_stdout(executor, executor_options)
    await run_one_events(executor, executor_options)
    await run_many(executor, executor_options)


if __name__ == '__main__':
    asyncio.run(main())

import されている example_common.py の方も見てみます。run_one_stdout だけ抜粋します。

async def run_one_stdout(executor, executor_options):
    """
    Run a single playbook job with several hosts and echo the display output as it arrives
    """
    try:
        job_def = AnsibleJobDef(data_dir='datadir', playbook='pb.yml')
        job_status = await executor.submit_job(job_def, executor_options)

        async for line in job_status.stdout_lines:
            print(line)

        # directly await the job object
        print('*** directly awaiting the job status...')
        await job_status
    finally:
        print('all done, exiting

Running Ansible jobs のドキュメントによると、以下のような使い方のようです。

  • AnsibleJobDed でジョブを定義する
    • JobExecutor でジョブを実行する
  • 今回の場合は、example_subprocess_job.pyimport している AnsibleSubprocessJobExecutorJobExecutor に当たるということだと思います。

AnsibleJobDeddata_dir で指定されているディレクトdatadir には Playbook と インベントリがありました。

# expamples ディレクトリ抜粋
├── datadir
│   ├── inventory
│   │   └── hosts
│   └── project
│       └── pb.yml

invnetory ディレクトリにインベントリファイルを入れ、project ディレクトリに Playbook を入れておくのは、ansible-runner のディレクトリ構造と同じですね。

この pb.ymlPython 経由で実行するということのようです。pingwait_forshell モジュールを利用した簡単な内容です。

インベントリは inventory/hosts が利用されます。

実行

お目当ての example_subprocess_job.py を実行します。

・・・と一回ためしたのですが、ログが沢山表示されてよくわからなくなってしまったので、実行する箇所をしぼりました。

    await run_one_stdout(executor, executor_options)   # これだけ
    # await run_one_events(executor, executor_options)
    # await run_many(executor, executor_options)

気を取り直して、再度実行。

% python example_subprocess_job.py

PLAY [taskhosts] ***************************************************************

TASK [Gathering Facts] *********************************************************
[WARNING]: Platform darwin on host h4 is using the discovered Python
interpreter at /usr/local/bin/python3.10, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.13/reference_appendices/interpreter_discovery.html for more information.
ok: [h4]
[WARNING]: Platform darwin on host h2 is using the discovered Python
interpreter at /usr/local/bin/python3.10, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.13/reference_appendices/interpreter_discovery.html for more information.
ok: [h2]
[WARNING]: Platform darwin on host h3 is using the discovered Python
interpreter at /usr/local/bin/python3.10, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.13/reference_appendices/interpreter_discovery.html for more information.
ok: [h3]
[WARNING]: Platform darwin on host h1 is using the discovered Python
interpreter at /usr/local/bin/python3.10, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.13/reference_appendices/interpreter_discovery.html for more information.
ok: [h1]
[WARNING]: Platform darwin on host h5 is using the discovered Python
interpreter at /usr/local/bin/python3.10, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.13/reference_appendices/interpreter_discovery.html for more information.
ok: [h5]

TASK [ping] ********************************************************************
ok: [h5]
ok: [h2]
ok: [h3]
ok: [h4]
ok: [h1]

TASK [wait_for] ****************************************************************
ok: [h4]
ok: [h2]
ok: [h1]
ok: [h5]
ok: [h3]

TASK [shell] *******************************************************************
changed: [h4]
changed: [h3]
changed: [h5]
changed: [h2]
changed: [h1]

PLAY RECAP *********************************************************************
h1                         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
h2                         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
h3                         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
h4                         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
h5                         : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
*** directly awaiting the job status...
all done, exiting

っぽいのが表示されました。

なお、Gathering Facts で表示されている、Python インタープリターの警告は、明示的に指定していないと表示されるものです。

気になる場合は、inventory/hostsansible_python_interpreter 変数で指定するなりします。

[taskhosts:vars]
ansible_connection=local
ansible_pipelining=true
# 以下追記例
ansible_python_interpreter=/Users/sakana/envs/as/bin/python

おわりに

用意されたとても簡単なサンプルを動かしただけですが、ansible-sdk を試してみました。

使ったことないですが、Ansible の Python APIよりも簡単に使える雰囲気でした。ansible-runner を経由するおかげでしょうか。

先日書いたansible-rulebook もそうですが、何かに Ansible を組み込む手段が最近増えてきたように思います。

参考資料

もっと作り込まれたデモ github.com

www.youtube.com

www.youtube.com

[Ansible] Playbook ならぬ Rulebook、イベントドリブンな ansible-rulebook を試してみた

はじめに

先日 Ansible の公式ブログで、Event-Driven Ansible という言葉が含まれるブログが次々と投稿されました。

また、AnsibleFest 2022 の 10/19 の Key Note でも Event-Driven Ansible が紹介されていました。

動画 (40:13 ころから)

www.youtube.com

また、個人的には GitHubAnsible Organizationをフォローしてるのですが、たしかに最近それっぽいリポジトリがいくつかパブリックになりました。なのでそのうち何か発表があるかなと楽しみにしていました。

Event-Driven Ansible というのは、外部からのイベントを検出し、条件にあえば特定のアクションを実行する仕組みのようです。これまでは基本的に人がPlaybookをキックしますが、それとはまた別で、人が介在しないアプローチ。まっさきに IFTTT や StackStorm を連想しました。

Event-Driven Ansible を実現するツールとして ansible-rulebookがあります。まだ developer preview という扱いのようです。

まだあまり情報が多くないですが、簡単なものでためしてみたのでまとめます。まだまだ、環境含めて全体的に手探りです・・。

  • 環境
    • ansible-rulebook 0.9.4
    • ansible.eda コレクション 1.3.2
    • ansible-core 2.13.5
    • Python 3.9.7 (3.8 以上が要件)
    • RHEL 8.6

Event-Driven Ansible を実現する要素

Event-Driven Ansible を理解するために重要そうな4つの要素があります。

1. Rulebook: どういうときに何をさせたいかの定義ファイル

検出したいイベントの発生源、条件、実行したいアクションを YAML で定義するファイルです。遠目で見ると Playbook のように見えます。

以降紹介する、 source、condition(rule)、action の定義を含みます。以下の関係です。

  • rulebook
    • source
    • condition (rule)
    • action

2. source: イベントの発生源

イベントの発生源です。例えば Webhook や Kafka、Azure Event Bus などです。

拡張性のためか、ansible collection によって追加できる仕組みのようです。

現状、イベントソースを含むコレクションとしては ansible.eda (eda は Event-Driven Ansible の略)があるようです。後でこのコレクションを利用して試します。

ansible.eda コレクション 0.9.4 には、例えばイベントソースが含まれています(詳細はこちら)。

  • webhook
  • alertmanager
  • file
  • kafka
  • azure_service_bus
  • url_check

これらを見ると、他システムとの連携イメージが湧きそうです。また、「ansible-rulebook は何に対応しているか?」という問いには「どのイベントソースがあるか」という調べ方になるケースが多そうです。

StackStorm でいうと Sensor のようなものかなと思います。

3. condition(rule): 条件

何かを実行するための条件です。主に source からのイベントに含まれる情報を元にします。例えば「飛んできた Webhook に含まれるペイロード内の messagesakana だったら」のような条件です。

condition の例(Rulebook 抜粋)

      condition: event.payload.message == "sakana"

複数の条件も指定できます。

AND 条件:

      condition:
        all:
          - event.payload.message == "sakana"
          - event.payload.user == "taro"

OR 条件:

      condition:
        any:
          - event.payload.message == "sakana"
          - event.payload.message == "fish"

なお、Rulebook の書式上は conditions という書式を利用しますが、仕組みの説明上は rule と表現されることもあるようです。

4. ction: 実行させたい処理

condition にマッチしたときに実行させたい処理です。以下は一例です。

  • run_playbook: 指定した Playbook を実行する (あとで扱う)
  • run_module: 指定した モジュールのを実行する
  • debug: デバッグ情報を表示する

すべての action 一覧はこちらです

ここまでの source と condition と action をとても雑に表現すると、以下のようなイメージでしょうか。

# 雑なイメージ
if (sourceを元にしたcondition):
  action

環境の準備

ここから、ansible-rulebook を試すための環境を準備します。

インストール・設定

インストール方法に関する公式ドキュメントはこちらです。

github.com

ここでは私の環境で私が試した方法を掲載します。上記ドキュメントは後で見つけたため、方法が微妙に異なるのでご了承ください。一次ソースとしてはドキュメントを参照してください。

本体

本体を pip でインストールします。

pip install ansible-rulebook

この時点で ansible-runner も入りました(ansible-core はない)。

環境変数JAVA_HOME` が必要なので、設定します。私の環境の場合は以下の通り。

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-17.0.5.0.8-2.el8_6.x86_64

JAVA_HOME を設定しないと ansible-rulebook --version すらエラーになります。

関連パッケージなど

後で分かったのですが、別途 Ansible 環境が必要だったので ansible-core もインストールします。

pip install ansible-core

今回使うイベントソースが入っている ansible.eda コレクションをインストールします。

ansible-galaxy collection install ansible.eda

ほか、これも後でエラーが起きてから気づいたのですが、今回使う ansible.eda コレクション内の webhook イベントソースが aiohttp を使うのでインストールします。

pip install aiohttp

何が必要になるかは、利用するイベントソースによって異なります。

おためし

環境ができたので試します。手軽さを重視して、すべてローカルホストで完結する内容です。

Rulebook の準備

お手軽にそれらしことを体験できそうな Webhook をイベントソースとする Rulebook を試してみます。

test-rulebook.yml

---
- name: Hello Events
  hosts: localhost

  sources:
    - ansible.eda.webhook:
        host: 0.0.0.0
        port: 5000

  rules:
    - name: Say Hello
      condition: event.payload.message == "sakana"
      action:
        run_playbook:
          name: test_playbook.yml

この Rulebook の定義内容は以下の通りです。

  • Sensor: Webhook の受け口として、Web サーバー を起動してポート番号 5000 (デフォルト通り)で待ち受ける
  • Condition: こに対して messagesakana というペイロードの Webhook が飛んできたら・・
  • Action: test_playbook.yml (あとでrulebookと同じディレクトリに作成)という Playbook を実行する

インベントリファイルの準備

ansible-rulebook の実行にはインベントリが必要です。

今回は必要最低限の以下のファイルを用意しました。

inventory.yml

---
all:
  hosts:
    localhost:

Playbook の準備

Rulebook 内の条件がマッチしたときに実行する Playbook を準備します。

test_playbook.yml

---
- name: debug msg play
  hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: debug msg
      ansible.builtin.debug:
        msg: HELLO!!

実行

まず待受側として Rulebook を実行します。コマンドは ansible-rulebook です。

ansible-rulebook -i inventory.yml --rulebook test_rulebook.yml --verbose

ここで指定している ansible-rulebook コマンドの主なオプションは以下のとおりです。

  • -i: インベントリファイル名を指定。--inventory でも可
  • --rulebook : Rulebook ファイル名、またはコレクション内の Rulebook を指定。単にファイル名だけ指定するのも可
  • --verbose : 詳細なログを画面上に表示する(任意)。-v のように省略できないので注意

ansible-rulebook 側はフォアグラウンドで待ち受け状態になります(--verbose 付きなのでログが多めです)。

$ ansible-rulebook -i inventory.yml --rulebook test_rulebook.yml --verbose
INFO:ansible_rulebook.app:Starting sources
INFO:ansible_rulebook.app:Starting rules
INFO:ansible_rulebook.engine:run_ruleset
INFO:ansible_rulebook.engine:ruleset define: {"name": "Hello Events", "hosts": ["localhost"], "sources": [{"EventSource": {"name": "ansible.eda.webhook", "source_name": "ansible.eda.webhook", "source_args": {"host": "0.0.0.0", "port": 5000}, "source_filters": []}}], "rules": [{"Rule": {"name": "Say Hello", "condition": {"AllCondition": [{"EqualsExpression": {"lhs": {"Event": "payload.message"}, "rhs": {"String": "sakana"}}}]}, "action": {"Action": {"action": "run_playbook", "action_args": {"name": "test_playbook.yml"}}}, "enabled": true}}]}
INFO:ansible_rulebook.engine:load source
INFO:ansible_rulebook.engine:load source filters
INFO:ansible_rulebook.engine:Calling main in ansible.eda.webhook
INFO:ansible_rulebook.engine:Waiting for event from Hello Events
(ここで待機)

条件にマッチする Webhook リクエス

続いて、Webhook を再現するために、同じホストから以下の curl を叩きます。条件にマッチするように messagesakanaペイロードを仕込んでいます。endpointansible-rulebook 側の仕様で、固定のようです。

curl -H 'Content-Type: application/json' -d "{\"message\": \"sakana\"}" 127.0.0.1:5000/endpoint

すると、待ち受け状態の ansible-rilebook 側で、以下のログが続きました。

INFO:aiohttp.access:127.0.0.1 [21/10月/2022:06:21:57 +0000] "POST /endpoint HTTP/1.1" 200 158 "-" "curl/7.61.1"
INFO:ansible_rulebook.rule_generator:calling Say Hello
INFO:ansible_rulebook.engine:call_action run_playbook
INFO:ansible_rulebook.engine:substitute_variables [{'name': 'test_playbook.yml'}] [{'event': {'payload': {'message': 'sakana'}, 'meta': {'headers': {'Accept': '*/*', 'User-Agent': 'curl/7.61.1', 'Host': '127.0.0.1:5000', 'Content-Length': '21', 'Content-Type': 'application/json'}, 'endpoint': 'endpoint'}}, 'fact': {'payload': {'message': 'sakana'}, 'meta': {'headers': {'Accept': '*/*', 'User-Agent': 'curl/7.61.1', 'Host': '127.0.0.1:5000', 'Content-Length': '21', 'Content-Type': 'application/json'}, 'endpoint': 'endpoint'}}}]
INFO:ansible_rulebook.engine:action args: {'name': 'test_playbook.yml'}
INFO:ansible_rulebook.builtin:running Ansible playbook: test_playbook.yml
INFO:ansible_rulebook.builtin:ruleset: Hello Events, rule: Say Hello
INFO:ansible_rulebook.builtin:Calling Ansible runner

PLAY [debug msg play] **********************************************************

TASK [debug msg] ***************************************************************
ok: [localhost] => {
    "msg": "HELLO!!"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

無事に条件にマッチし、run_playbook で指定した Playbook が実行されました。

動画です(次に説明するマッチしないパターンも含みます)。

条件にマッチしない Webhook リクエス

条件にマッチしない以下のリクエストの場合は、Playbook は実行されませんでした。

$ curl -H 'Content-Type: application/json' -d "{\"message: \"fish\"}" 127.0.0.1:5000/endpoint

来たリクエストの概要だけログに表示されました。--verbose による挙動です。

INFO:aiohttp.access:127.0.0.1 [21/10月/2022:06:22:49 +0000] "POST /endpoint HTTP/1.1" 200 158 "-" "curl/7.61.1"

なるほどなるほど。

Webhook (イベントソース)の内容を Playbook 内で参照する

先ほどの Playbook は、べた書きの文字列を表示するだけでした。せっかくなので、イベントソースの内容、今回では飛んできた Webhook のペイロードの値も扱いたいと思って調べました。

action として debug を指定すると、イベントソースの色々な情報が表示されました。

Rulebook は以下の通りです。

- name: Hello Events
  hosts: localhost

  sources:
    - ansible.eda.webhook:
        host: 0.0.0.0
        port: 5000

  rules:
    - name: Say Hello
      condition: event.payload.message == "sakana"
      action:
        debug:        # デバッグの指定

上記 Rulebook を実行中に、条件にマッチする Webhook をリクスエストをすると、以下のようにイベントソースの内容が色々表示されました。

INFO:ansible_rulebook.engine:call_action debug
INFO:ansible_rulebook.engine:substitute_variables [{}] [{'event': {'payload': {'message': 'sakana'}, 'meta': {'headers': {'Accept': '*/*', 'User-Agent': 'curl/7.61.1', 'Host': '127.0.0.1:5000', 'Content-Length': '21', 'Content-Type': 'application/json'}, 'endpoint': 'endpoint'}}, 'fact': {'payload': {'message': 'sakana'}, 'meta': {'headers': {'Accept': '*/*', 'User-Agent': 'curl/7.61.1', 'Host': '127.0.0.1:5000', 'Content-Length': '21', 'Content-Type': 'application/json'}, 'endpoint': 'endpoint'}}}]
INFO:ansible_rulebook.engine:action args: {}
=============================================================================================
kwargs:
{'facts': {},
 'hosts': ['localhost'],
 'inventory': {'all': {'hosts': {'localhost': None}}},
 'project_data_file': None,
 'ruleset': 'Hello Events',
 'source_rule_name': 'Say Hello',
 'source_ruleset_name': 'Hello Events',
 'variables': {'event': {'meta': {'endpoint': 'endpoint',
                                  'headers': {'Accept': '*/*',
                                              'Content-Length': '21',
                                              'Content-Type': 'application/json',
                                              'Host': '127.0.0.1:5000',
                                              'User-Agent': 'curl/7.61.1'}},
                         'payload': {'message': 'sakana'}},
               'fact': {'meta': {'endpoint': 'endpoint',
                                 'headers': {'Accept': '*/*',
                                             'Content-Length': '21',
                                             'Content-Type': 'application/json',
                                             'Host': '127.0.0.1:5000',
                                             'User-Agent': 'curl/7.61.1'}},
                        'payload': {'message': 'sakana'}}}}
===================

上記の内容のうち、event.payload.message を Playbook に埋め込んでみます。

---
- name: debug msg play
  hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: debug msg
      ansible.builtin.debug:
        msg: "{{ event.payload.message }}"    # イベントソースの情報を利用

Rulebook 内の action を debug から run_playbook に戻します。

# ...(略)...
      action:
        run_playbook:
          name: test_playbook.yml

上記 Rulebook を実行中に、条件にマッチする Webhook をリクスエストをすると、以下のように event.payload.message の値(sakana)が表示されました。

INFO:aiohttp.access:127.0.0.1 [21/10月/2022:06:33:42 +0000] "POST /endpoint HTTP/1.1" 200 158 "-" "curl/7.61.1"
INFO:ansible_rulebook.rule_generator:calling Say Hello
INFO:ansible_rulebook.engine:call_action run_playbook
INFO:ansible_rulebook.engine:substitute_variables [{'name': 'test_playbook.yml'}] [{'event': {'payload': {'message': 'sakana'}, 'meta': {'headers': {'Accept': '*/*', 'User-Agent': 'curl/7.61.1', 'Host': '127.0.0.1:5000', 'Content-Length': '21', 'Content-Type': 'application/json'}, 'endpoint': 'endpoint'}}, 'fact': {'payload': {'message': 'sakana'}, 'meta': {'headers': {'Accept': '*/*', 'User-Agent': 'curl/7.61.1', 'Host': '127.0.0.1:5000', 'Content-Length': '21', 'Content-Type': 'application/json'}, 'endpoint': 'endpoint'}}}]
INFO:ansible_rulebook.engine:action args: {'name': 'test_playbook.yml'}
INFO:ansible_rulebook.builtin:running Ansible playbook: test_playbook.yml
INFO:ansible_rulebook.builtin:ruleset: Hello Events, rule: Say Hello
INFO:ansible_rulebook.builtin:Calling Ansible runner

PLAY [debug msg play] **********************************************************

TASK [debug msg] ***************************************************************
ok: [localhost] => {
    "msg": "sakana"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

無事に、実行された Playbook 内でイベントソースの内容を扱えました。

おわりに

Event-Driven Ansible の中心となるツール ansible-rulebook を試してみました。

今後は対応するイベントソースが増えていくと更に可能性が広がりそうです。 イベントソースは collection に含められるようなので、すでに配布やインストールの仕組みがすでに整ってるのは良い条件に思います。

また、こちらの記事によると、AAP のコンポーネントになることが計画されているそうです。

Event-Driven Ansible is planned to become a component of Red Hat Ansible Automation Platform.

今回は、ローカルホストで完結するよう簡単なサンプルでした。まだ、分かっていない仕組み、扱っていないイベントソースや action が色々あります。

今後の動向もチェックしていきたいと思います。

まだ理解していないこと

現時点ではまだ以下の点がまだ理解しきれていません。またあとで調べたいと思います。まだ少し触っただけですので、そもそも認識が及んでいない領域もあります。

  • ansible-rulebook と一緒にインストールされる ansible-runner の使われ方
    • docker を止めてる状態でも正常に Playbook が実行した(明示的にインストールした ansible-core によるものの模様)
  • インベントリと 各 hosts: の関係
    • 今回はすべて lcoalhost で完結する内容だったが、ansible-rulebook-i で指定したイベントリファイルと Rulebook 冒頭の hosts: 、Playbook 冒頭の hosts: がどういう関係なのか
  • 内部で Drools がどのように使わているか
    • 今回 JAVA_HOME を設定したが、使われてるのかよくわかっていない
    • この記事によると「Event-Driven Ansible contains a decision framework that was built using Drools」とある

参考

Event-Driven Ansible 総合情報

https://www.ansible.com/event-driven

Event-Driven Ansible 関連の公式ブログの記事たち

https://www.ansible.com/blog/topic/event-driven-automation

Event-Driven Ansible を含むハンズオンのラボ環境

https://www.ansible.com/products/ansible-training

ansible-rulebook リポジトリ

https://github.com/ansible/ansible-rulebook

ansible-rulebook ドキュメント

https://ansible-rulebook.readthedocs.io/en/latest/

直近の関連ウェビナー

https://www.redhat.com/en/events/webinar/event-driven-ansible-office-hours-november

https://www.redhat.com/en/events/webinar/event-driven-ansible-office-hours-december

関連動画

雰囲気がわかりやすいです

www.youtube.com

Git Ops とからめる

www.youtube.com

[Ansible/AAP] 書籍「Demystifying Ansible Automation Platform」はAAPの全体と自動化と応用が学べる貴重な書籍

はじめに

2022/09/30 に Ansible Automation Platform の Automation Controller を中心とした各プロダクト、サービスについて解説している「Demystifying Ansible Automation Platform」という書籍が発売されました。

demystifying と言う言葉は今回はじめて知りました。「(…の)神秘を解く」という意味だそうです。

www.packtpub.com

https://www.amazon.co.jp/dp/1803244887www.amazon.co.jp

先日の記事で軽く紹介しました。完璧に読み込んだというわけではないですが、一通目を通したので概要や気づきなどをご紹介します。

Acknowledgements(謝辞)

Thank you, Sean Sullivan and, Packt Publishing, for the opportunity to review!

本書については、著者の Sean Sullivan 氏よりレビューのご依頼をいただき、Packt Publishing より書籍データを頂戴いたしました。今回はこのような機会をいただきありがとうございました。

Ansible Fest 2022 では Using Configuration as Code on Ansible Automation Platform という、CaC 関連のお話もあるようです。





本書の特徴

主観ですが、特徴だと思った点をあげます。

特徴1: AAP の全体を知れる

AAP と聞いてまっさきに思い浮かべるのは Automation Controller(旧Ansible Tower) かも知れません。

本来、AAP には Automation Hub などほかのプロダクトやサービスも含まれていて、本書では全体的に触れられています。

ページ数としてはやはり、代表的なプロダクトである Automation Controller についてがおそらく一番多いです。

特徴2: CaC (Configuration asCode) による自動化が知れる

Automation Controller や Automation Hub のインストールや設定作業を自動化する方法が紹介されています。

Automation Controller で、というよりAutomation Controller の設定を自動化、ということです。

本書では CaC (Configuration asCode) と表現しています。サンプルは GitHubリポジトリにアップされています。

特徴3: Automation Controller の応用的な使い方も解説

インストールや基本的な設定の他にも、応用的なワークフローの使い方や、他システムとの連携、Automation Mesh によるスケーラビリティについても解説されています。

こんな人に向いているかも?

特徴を踏まえ、以下のような人に向いているかもと思います。

  • AAP の中に Automation Controller(旧Ansible Tower)だけでなく、ほかにどんな物があるか知りたい人
  • Automation Controller や (Private) Automation Hub の設定を自動化したい人
  • AAP は使わないけど、コンテナ化された実行環境について知りたい人

各パート・章の概要

本書は3つのパートに分かれていて、パート内の各章の概要についてご紹介します。

■ Part 1: Getting Ansible Automation Platform Up and Running

AAP の概要や、複数のインストール方法、各種設定についての説明があるパートです。

Chapter 1: Introduction to Ansible Automation Platform

AAP の概要を紹介している章です。

Automation Controller(旧Ansible Tower)だけなく、Execution Environment、Automation Hub や Automation Service Catalog(APA2.2 でオンプレ化)、Red Hat Insights Red Hat Insights for Red Hat AAP、Ansible content tools(ansible-navigator、VS Code の拡張など) にも触れられています。

この章の時点で、AAP は Automation Controller だけじゃないこと、ほかにどんなものがあるかが知れます。

個人的にありがたかったのは、アップストリームとレッドハット公式プロダクトとの違いについて言及されていた点です。たとば、AWX と Automation Controller のような関係のことです。なんとなくは知っていたものの、明記されていて助かりました。

重要なキーワード: CaC (Configuration as Code)

ほか、本書の大きな特徴である CaC (Configuration asCode)についての説明もされています。コード(ここではYAML)による設定の自動化です。 たとえば、Automation Controller は GUI を備えていて、直感的に操作できる一方、他の環境にもう一つ建てるとなると差分に気を使うことになります。コードで管理しておけば、再現性も高く、変更の追跡もしやすくなります。

本書では、いくつかのコレクションを利用した、設定の自動化サンプルが掲載されています。扱っているコレクションは以下の通りです。

  • 基本コレクション(呼び方は私の独断です)
    • awx.awx
    • ansible.tower
    • ansible.controller
  • 派生コレクション(呼び方は私の独断です)
    • redhat_cop.controller_configuration
    • redhat_cop.ah_configuration
    • redhat_cop.ee_utilties

AAP のプロダクトの設定自動化の情報は他では多くない上に、著者らが作成した派生コレクションたちの解説が読めるのはとても有意義だと思いました。

Chapter 2: Installing Ansible Automation Platform

(OpenShiftを利用しない)一般的なインストール方法を紹介する章です。Autmation mesh や High availability な構成にも触れられています。

インストール方法は、公式サイトにも掲載されていますが、本書では CaC、つまりここでは Playbook で自動化する方法が紹介されています。

Chapter 3: Installing Ansible Automation Platform on OpenShift

今度は OpenShift クラスタにインストールする方法の紹介です。

私自身は OpenShift を使ったことがないのですが、OpenShift クラスタに AAP をインストールしたい場合は参考になりそうです。サンプルも掲載されています。

また、最初のほうでは minimuke で AWX する方法も解説されていました。本書のタイトルはあくまで AAP なので、ここまで解説されてるのは意外でした。

Chapter 4: Configuring Settings and Authentication

Automation Controller や、 Automation Hub に対する認証の設定方法の紹介の章です。

SSO による認証の設定と、直接設定する方法が紹介されています。

■ Part 2: Configuring AAP

Part 1 でインストールが終わったので、次は各種設定についてのパートです。

Chapter 5: Configuring the Basics after Installation

インストール後の基本的な設定として、組織、認証情報タイプ、認証情報の設定を紹介する章です。カスタムの認証情報タイプまでていねいに説明されているのが助かります。

ほか、Automation Controller 上の各オブジェクトのインポートとエクスポートについても紹介されています。すでに手動で設定が進んでいる場合でも、この方法でエクスポートしれば、CaC 化がしやすそうですね。

Chapter 6: Configuring Role-Based Access Control

Automation Controller や Automation Hub におけるロールベースアクセス制御(RBAC)の説明と設定方法を紹介する章です。

RBAC 機能を利用すると、たとえば Automation Controllerで、ジョブの実行はできるけど設定変更はできない、といった制御ができるようになります。

少し機能を試すだけであれば、一人でadmin相当の権限ユーザーだけでも良いかも知れませんが、やはり組織で活用するためには権限制御の機能は重要だと思います。

Automation Hub の RBAC 機能はまだ馴染みがなかったので解説があってありがたいです。

Chapter 7: Creating Inventory, and Other Inventory Pieces

Automation Controller でのインベントリの作成について紹介する章です。.

静的なインベントリのほか、AWS、GCE、Azure、VMware vCenter のようなダイナミックインフラストラクチャに基づく動的な、組み込みインベントリプラグインについても触れられています。

個人的によかったのは、組み込みではないインベントリプラグインとして netbox.netbox.nb_inventory の使い方が紹介されている点でした。

それから、まさかのインベントリプラグインを自作するためのPythonコード例まで載っていました。

Chapter 8: Creating Execution Environments

コンテナによる Ansible の実行環境である Execution Environment (EE)の概要、利用、ビルド、Automation Hub への push 方法などについて紹介する章です。

もともとAnsibleを使っていたけど、ここ1-2年の状況を追えていない方にとっては「え、コンテナ?」となって、この章が一番インパクトがあるかもしれません。

ツールとしては ansible-builder が出てきます。ビルドするイメージの定義ファイルである exuection-environment.yml の書き方も紹介されています。

Chapter 9: Automation Hub Management

Automation Hub で コレクションや EE を管理する方法などについて紹介する章です。

機能の紹介だけでなく「Best practices for maintaining execution environments」では、おすすめのEEの管理方法が記載されています。

これまでの venv のほうが気軽といえば気軽でしたが、運用にのってしまえば EE のほうが便利になるかなと思っています。

Chapter 10: Creating Job Templates and Workflows

プロジェクトの作成や、Automation Controller のメイン機能であろうジョブテンプレートとワークフロージョブテンプレートの作成について紹介する章です。

個人的な経験では、各種テンプレートは似て非なるものを作っていくことが多く、この作業を自動化するとラクになりました。画面上のオプションの数も多いですからね。

ジョブスライシングの話もあります。ここで、「スライスの数は大きくしすぎず、実行ノードの数以下にすることが推奨」旨の説明がされていました。チューニングのポイントは迷いどころなので、このようなガイドがあるのはありがたいですね。

本書は、要所要所でこのような実用的な話があるのが助かります。

■ Part 3: Extending Ansible Tower

Ansible Tower、というか Automation Controller のさらに応用的な内容のパートです。

Chapter 11: Creating Advanced Workflows and Jobs

アーティファクトや承認、通知を利用するような高度なワークフローの作成方法を紹介する章です。

あるジョブででの値を後続のジョブで利用するためには set_stats モジュールを利用するのですが、その例が掲載されています。ここでは、set_stats で設定された値は、変数名の頭に _ をつける規則が紹介されています。

通知はメールやSlackについて(特にSlack)扱われています。

Automation Controller を活用していくと、ジョブ間の値の渡しや、ワークフローの一時停止、通知を利用するケースがあるので、本章のような応用的な内容もありがたいです。

Chapter 12: Using CI/CD to Interact with the Automation Controller

Automation Controller や Automation Hub と CI/CD の組み合わせ方を紹介する章です。

CI/CD との組み合わせと一口にいってもいろいろありますが、本章では以下のようなユースケースが取り上げられていました。

  • GitHub Actionsを利用した、設定の維持管理
  • GitLab/GitHub のパイプラインからジョブを実行することを想定したPlaybook、アドホックコマンド実行
  • バックアップ、リストア

「AAPで」CI/CD、ではなく「AAPの」CI/CD、という感じでしょうか。CaC だけでも応用的だとおもっていましたが、更に応用的な内容でした。

Chapter 13: Integration with Other Services

ログやメトリクス系の他サービスと連携する方法を紹介する章です。

具体的には以下のものです。

  • Splunk
  • Automation Analytics for Red Hat AAP
  • Prometheus

Automation Analytics for Red Hat AAP は、AAP に含まれる解析サービスで、SaaS として提供されています。

Chapter 14: Automating at Scale with Automation Mesh

Automation Controller のスケーラビリティと信頼性を向上させる仕組みである Automation mesh を紹介する章です。

Automation mesh は AAP 2.1 で導入された機能で、なかなかに奥が深いです。本章で、どのようなノードの種類があってどういう動きをするのか、どういうユースケースがあるのかが解説されています。

構成次第で様々なパターンがあり得るのでユースケースが載っているのはありがたいです。

Chapter 15: Using Automation Services Catalog

AAP 2.2 でオンプレプロダクトとなった、Automation Services Catalog (ASCと略されてました) について紹介する章です。

正直私自身は一番ピンときていないプロダクトだったのですが、少し理解が進みました。ざっくり、Auotmartion Controller のジョブテンプレートをラップして、カタログとして仕立て上げて、各部門に使ってもらうためのものかなと捉えました。

まだ構築したことないのですが、P268 に

ASC relies solely on a Single Sign-On (SSO) server for authentication.

とあり、構築のハードルが高めのように思いました。


おわりに

Demystifying Ansible Automation Platform」は、AAPの全体を知り、インストールのや設定の自動化まで紹介されている大変有用な書籍でした。

より興味が深いところを、もう一度読んでみようかと思います。

[Ansible/AAP] Ansible Automation Platform のツール・プロダクト群を学べる書籍「Demystifying Ansible Automation Platform」が発売された

はじめに

2022/09/30 に、Ansible Automation Platform(AAP)について解説された書籍(洋書)「Demystifying Ansible Automation Platform」が発売されました。

Ansible をとりまくツールやプロダクト群を学んだり、Automation Controller (旧Ansible Tower)の設定を自動化したいときには良さそうな書籍です。

この度、大変ありがたいことに、本書の著者 Sean Sullivan 氏よりレビューのご依頼をいただき、Packt Publishing より書籍データを頂戴いたしました。まだ読み切っていないのですが、取り急ぎかんたんにご紹介したいと思います。

www.packtpub.com

www.amazon.co.jp

目次

Amazon のページ から目次を引用します。

  1. Introduction to Ansible Automation Platform
  2. Installing Ansible Automation Platform
  3. Installing Ansible Automation Platform on OpenShift
  4. Configuring Settings and Authentication
  5. Configuring the Basics after Installation
  6. Configuring Role-Based Access Control
  7. Creating Inventory, and Other Inventory Pieces
  8. Creating Execution Environments
  9. Automation Hub Management
  10. Creating Job Templates and Workflows
  11. Creating Advanced Workflows and Jobs
  12. Using CI/CD to Interact with Automation Controller
  13. Integration with Other Services
  14. Automating at Scale with Automation Mesh
  15. Using Automation Services Catalog

Chapter 1 では、AAP の全体感の説明があります。その後、インストール方法や、RBACのような管理機能、インベントリや Execution Environment (EE: コンテナによる実行環境)、ジョブテンプレート、ワークフローのような、よく使う機能が解説されています。

扱っているのが AAP 2.2 なので、新しいですね。

Configuration as code (CaC)

この書籍の一番の特徴は、AAP 内の製品(Automation ControllerとAutomation Hub)の設定自体を Ansible でやっていくスタイルである点だと思います。画面キャプチャも所々ありますが、それより Playbook のほうが紙面を占めている様子です。

書籍内では Configuration as code (CaC) と呼んでいます。

具体的には、awx.awx コレクション、ansible.controller コレクション、それから redhat_cop.controller_configuration コレクションについて扱われています。

「画面ぽちぽちはつらい、複数台建てるときの差分にも気を遣う・・。自動化できればいいな」という方には良い内容ではないでしょうか。

Automation Controller だけじゃない

AAP の代表的な製品といえば Automation Controller だと思いますが、AAPはそれ以外にも製品・サービスがあります。

個人的にこれまで書籍では見たことがなかったのですが、本書籍では Automation Hub (Chapter 9)や、Automation Service Catalog (Chapter 15)についても書かれています。

Automation Service Catalog は(AAP 2.2 で)オンプレ提供に変わったという点含まて記述されていて、やはりかなり新しい情報が載っているなと思いました。

おわりに

Automation Controller だけでなく、Automation Hub などの他の製品、それから ansible-builderansible-navigator など新しいツールについても書かれています。

引き続き読みすすめていきたいと思います。

[AWX/React] はじめて AWX の UI を修正するまでにやったこと(React何もわからん状態から)

はじめに

AWX の UI (画面)で一部修正したい箇所があり、修正してPRを出したところマージしていただきました。

github.com

AWX の UI 修正は今回が初めてでした。特にフロントエンドは分からないことが多い状態からでしたが、どうにか無事にマージしていただきました。

この記事では、技術的な調査や修正、PR提出までのやったことをまとめます。

[2022/10/04 追記] バージョン 21.7.0 としてリリースされました( Changelog)。

修正したかった箇所

各画面の右上にベルアイコンがあり、ワークフロージョブテンプレートの実行中に承認ノード止まっている待ちの数を示すのですが、待ちが0のときと1以上のときで見た目の変化が少なく分かりにくいなと感じていました。

数字が変わるのみで、承認待ち有無が視覚的にはわかりにくく感じた(上段が承認待ちなし、下段が承認待ち1件)

なのでここを修正してみようと思いました。

最終的にはこうしました。

承認待ちがあるときは色も変わるようにした

React の調査

AWXの UI は React (17系)で作られていることが分かったので、まず React について調べました。そもそも JavaScript は、入力フォームのバリデーションで昔少し使ったことがある程度なので、まず最近の JavaScript の書きっぷりがわからない状態でした。

関連する書籍をいくつか読んでいくことにしました。

www.sbcr.jp

上記の本で、React の前提知識である最近の JavaScript の書きっぷり、コンポーネントの考え方、JSX、Props、State、副作用などのReact の基本が学習できました。

もうちょっと別の React の本を読んでみたいなと思って以下の本を読みました。

www.c-r.com

そもそもフロントエンドの全体像が分かっていないなと思ったので、次に以下の本を読みました。先にこれを読んでおけばよかったかなと思いました。

bookplus.nikkei.com

一番新しそうな本として以下の本も読みました。ただし、今までわからなかった部分の補足としてつまみ読みという感じです。AWX では Next.js を使っていないようなので Next.js のパートは、さーっと読むにとどめました。

booklog.jp

最後はこちら。関数型プログラミングのところはほぼ飛ばしてしまいました・・。

www.oreilly.co.jp

今回は本の読み方として、体系的に学びたいというよりは、修正に必要な知識を取り込みたい、というスタンスです。

AWX のコードもなんとなーく、少しだけですが読めるようになってきました。

ただ、JavaScript についてはこの記号、書き方なんだっけ?となり、React としては、これやるとどうなるんだっけ?と思うことは相変わらず多々ありました。

修正箇所の特定

AWX の UI のコードは、awx/ui ディレクトリにあるようです。この中から、画面右上のあのバッジを定義しているコンポーネントを探せば良いわけです。が、ちょっと自信がなかったので、React Developer Tools という Chrome 拡張を使って、コンポーネントの階層が確認できたのが助かりました。

AWX は PatternFlyというコンポーネント集を利用しています。現状のバッジは、ベルアイコンは BellIconというアイコン、数字部分は Badge というものを使っていることが分かりました。

PatternFlyのページはあとでも何回か見る機会がありました。

開発環境の構築

なんとなくコードが追えるようになったり、修正箇所が特定できても、ちょっといじって変化を見て・・という工程を繰り返さないと理解が深まらないことが多々あります。

なので、コードを修正するための環境をつくりました。詳細は別の記事にまとめています。

tekunabe.hatenablog.jp

修正作業

ようやく修正作業です。修正して確認して・・を繰り返しました。ホットリロード便利ですね。

テストを書くか迷ったんですが、既存のテストの粒度感をみて書きませんでした。書く練習もしてみれば良かったなとは思います。

PR提出

どきどきしながら PR を出しました。

薄々感じていたのですが、最初にやった修正でもちょっとまだ変化が分かりにくいかなと思っていました。それもあってか、別のコンポーネント Notification badge に差し替えたほうが良いとコメントいただきました。なるほど確かにと思って、再度修正しました。

今回始めての PR 提出だったのですが、このリポジトリの仕組みとしては、初めての場合はCIを走らせるのに承認が必要でした。いざ承認されて CI が走ったら失敗しました。今回の私の修正とは無関係なようでした。レビュアーの方に rebase を指示されたので rebase して force push しました。CONTRIBUTING.md にも merge ではなく rebase でという旨の記述がありました。

We like to keep our commit history clean, and will require resubmission of pull requests that contain merge commits. Use git pull --rebase, rather than git pull, and git rebase, rather than git merge.

Cypress によるテスト(これは手動でキックするようです)は失敗しましたが、これも無関係だったようで、マージしていただきました。

この修正を含むリリースは現時点はまだですが、21.7.0 とか 22.0.0 とかのバージョンに含まれるのかなと思います。

おわりに

はじめてでしたが、無事にマージされてよかったです。 この修正が Automation Controlelr にも入るのか、いつ入るのかは分かりませんが、入ると良いなぁと思っています。