てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] Jinja2 テンプレートによる生成結果をansible.builtin.template ルックアッププラグインで表示する

この記事は Ansible Advent Calendar 2023 2日目の記事です。

はじめに

ある時、Jinja2 テンプレートを書いていて、試行錯誤しながら結果がどうなるか確認したい時がありました。

ansible.builtin.template モジュールで、ファイルを生成してから確認する形でも良かったのですが、そのときはそれよりも Playbook の実行ログの中で確認したい気持ちが強かったです。ansible.builtin.template モジュール戻り値には生成結果が入りません。方法をその場で考えようととしたのですが、その時は思い浮かびませんでした。

少しあとで ansible.builtin.template モジュールではなく、ansible.builtin.template lookup プラグインの結果を ansible.buitlin.debug モジュールで表示すればいいと気が付きました。

その方法を試したときのことをまとめます。

  • 環境
    • ansible-core 2.15.6

サンプル

Playbook は以下の通り。vars で定義した変数を、テンプレートファイル test.j2 内で利用します。

---
- hosts: localhost
  gather_facts: false
  connection: local

  vars:
    fishes:
      - kingyo
      - ugui
      - oikawa

  tasks:
    - name: Debug Jinja2 template
      ansible.builtin.debug:
        msg: "{{ lookup('ansible.builtin.template', 'test.j2') }}"

Jinja2 テンプレートは以下の通り。

{% for i in fishes %}
Hello {{ i }}.
{% endfor %}

実行結果

まず普通に実行した結果です。

% ansible-playbook -i inventory.ini template.yml

PLAY [localhost] **************************************************************************************************

TASK [Debug Jinja2 template] **************************************************************************************
ok: [localhost] => {
    "msg": "Hello kingyo.\nHello ugui.\nHello oikawa.\n"
}

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

一応生成結果が表示されてますね。が改行が入ると見にくいです。

コールバックプラグインcommunitu.general.yaml に変更します。ここでは アドホックな指定で。

% ANSIBLE_STDOUT_CALLBACK=community.general.yaml ansible-playbook -i inventory.ini template.yml

PLAY [localhost] ***************************************************************************************************

TASK [Debug Jinja2 template] **************************************************************************************
ok: [localhost] => 
  msg: |-
    Hello kingyo.
    Hello ugui.
    Hello oikawa.

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

改行されて見やすくなりました。

おわりに

今回は ansible.builtin.debug モジュールと組み合わせましたが、ルックアッププラグインは他のモジュールのオプションや、vars ディレクティブによる変数定義などにも組み込めるので、小回りが効きます。

Playbook 内に Jinaj2 構文を書くのを避けたい場合は、ansible.builtin.template ルックアッププラグインを組み合わせるのも良さそうです。

参考

表示のさせ方あれこれ

tekunabe.hatenablog.jp

tekunabe.hatenablog.jp

[Ansible] ansible.utils.fact_diff フィルターで変数間のdiffをする(モジュールではなく)

この記事は Ansible Advent Calendar 2023 1日目の記事です。

はじめに

先日リリースされた ansible.utils コレクションのバージョン 3.0.0 と 2.12.0 で、ansible.utils.fact_diff フィルタープラグインが追加されました。

(3.0.0 からは ansible-core 2.14.0 以上が要件)

これまでも ansible.utils.fact_diff モジュールがあって、変数同士の diff を見るのに便利でした。これのフィルター版です。

モジュールは一つのタスクとして独立して定義しておく必要があります。一方、フィルターの場合は、他のモジュールのオプションや vars ディレクティブによる変数定義に組み込んだりできます。

この記事では簡単な例で試した結果をまとめます。

  • ansible-core 2.15.6
  • ansible.utils 3.0.0

例1: ごく簡単な例

使い方の基本を抑えるために、とても簡単な例を試します。

ansible.builtin.debug モジュールの msg オプションに、2つのリストの比較結果を指定しています。

    - name: Debug fact_diff filter
      ansible.builtin.debug:
        msg: "{{ before | ansible.utils.fact_diff(after) }}"
      vars:
        before:
          - 1
          - 2
          - 3
        after:
          - 1
          - 22
          - 3

実行結果は以下の通り。Unified Diff 形式の結果が1行1要素のリストとして表示されました。ansible.utils.fact_diff モジュールでいう、戻り値の中の diff_lines に相当する形式のようです。

TASK [Debug fact_diff filter] ******************************************************************************
ok: [ios01] => {
    "msg": [
        "--- before",
        "+++ after",
        "@@ -1,3 +1,3 @@",
        " 1",
        "-2",
        "+22",
        " 3",
        ""
    ]
}

なお、似たようなことを ansible.utils.fact_diff モジュールでやる場合は以下のような書き方です。

    # モジュールの場合
    - name: Debug fact_diff module
      ansible.utils.fact_diff:
        before:
          - 1
          - 2
          - 3
        after:
          - 1
          - 22
          - 3

以下のような結果になります。register で比較結果を変数にいれることもできますが、何もしなくてもログに表示されます。

# モジュールの場合
TASK [Debug fact_diff module] ***********************************************************************
--- before
+++ after
@@ -1,3 +1,3 @@
 1
-2
+22
 3

changed: [ios01]

例2: 少し工夫した例(比較対象外の指定)

比較はしたいけどここは無視したいというケースもあります。ansible.utils.fact_diff モジュールでは、plugins > vars > skip_lines オプションで指定するものです。フィルターにも同じ機能があります。

以下の例では、Cisco IOS の機器のインターフェースの description を変更する際、前後のコンフィグ間の diff を表示する例です。何も意識しないと、設定の内容に直接関係ない行が差分として検出されてしまうので、無視する行を指定しています。

    # 事前コンフィグの取得
    - name: Get before config
      cisco.ios.ios_command:
        commands:
          - show running-config
      register: before_running_config
  
    # 設定変更
    - name: Configure
      cisco.ios.ios_interfaces:
        config:
          - name: GigabitEhternet0/1
            description: hogehoge!!

    # 事後コンフィグの取得        
    - name: Get after config
      cisco.ios.ios_command:
        commands:
          - show running-config
      register: after_running_config

    # コンフィグ差分の表示
    - name: Debug diff
      ansible.builtin.debug:
        msg: "{{ before | ansible.utils.fact_diff(after, plugin=plugin) }}"   # plugin オプションの指定
      vars:
        before: "{{ before_running_config.stdout[0] }}"
        after: "{{ after_running_config.stdout[0] }}"
        plugin:    # plugin オプションに指定する値の定義
          vars:
            skip_lines:    # 無視したい行の定義
              - "^! Last configuration change at.+"
              - "^Current configuration .+ "

ansible.utils.fact_diff(after, plugin=plugin) のところがやや分かりにくいかもしれませんが、plugin オプションに、変数 plugin を指定しています(ここではタスクの vars で定義)。

結果は以下のとおりです。

TASK [Get before config] ***********************************************
ok: [ios01]

TASK [Configure] *******************************************************
changed: [ios01]

TASK [Get after config] ************************************************
ok: [ios01]

TASK [Debug diff] ******************************************************
    "msg": [
        "--- before",
        "+++ after",
        "@@ -75,7 +75,7 @@",
        "  media-type rj45",
        " !",
        " interface GigabitEthernet0/1",
        "- description hogehoge",
        "+ description hogehoge!!",
        "  ip address 172.16.2.1 255.255.255.252",
        "  no ip redirects",
        "  duplex auto",
        ""
    ]
}

おわりに

ansible.utils.fact_diff モジュールと同等の機能を、ansible.utils.fact_diff フィルターでもできそうだという感覚が得られました。

フィルターのほうが小回りがきくので、今後使うことが増えるかもしれません。

[Ansible] Ansible 公式ブログ以外の redhat.com 上の Ansible 記事

はじめに

Ansible には The Inside Playbook (https://www.ansible.com/blog) という公式ブログがあります。

Ansible に関する公式ソースで即時性のある情報源として、とても重宝しています。

割と最近気づいたのですが、他にも redhat.com ドメインのブログ的な情報で Ansible のものがあります。

簡単ですがいくつかご紹介します。

■ Enable Sysadmin

結構な Ansible 率です。

www.redhat.com

ただし、最近は更新がストップしているようです。

Ansible 系の記事の例

www.redhat.com

www.redhat.com

■ Enable Architect

www.redhat.com

こちらも、最近は更新がストップしているようです。。。

Ansible 系の記事の例

www.redhat.com

www.redhat.com

Red Hat Developer の Blog

これも結構な Ansible 率です。

developers.redhat.com

Ansible 系の記事の例

developers.redhat.com

developers.redhat.com

Red Hat Partner Connect Blog

頻度は高くないですが。

connect.redhat.com

Ansible 系の記事の例

connect.redhat.com

おわりに

他にもあるかもしれません。もしあれば @akira6592 まで教えていただけると幸いです!

[Ansible/EDA] ansible.eda.webhook イベントソースプラグインでトークンによる認証をかける

はじめに

これまで何度かansible.eda.webhook イベントソースプラグインを使って、Webhook 経由で何かを動かすということを試してみました。

このイベントソースプラグインは認証機能を持たせることもできるので、トークンによる認証を試してみました。

  • 検証環境
    • ansible.eda コレクション 1.4.2
    • EDA Controller 1.0.0
      • バージョン番号は rpm のファイル名から類推
      • AAP 2.4 のインストーラーで構築したもの

Rulebook

以下のような Rulebook を利用します。

ポイントは token オプションです。

---
- name: Hello Events
  hosts: all

  sources:
    - ansible.eda.webhook:
        host: 0.0.0.0
        port: 5000
        token: 72232ecb-8b5f-15ed-5d28-597840a98608   # ポイント

  rules:
    - name: Say Hello
      condition: event.payload is defined
      action:
        debug:
          msg: "{{ event }}"

ここでは分かりやすさのためにべた書きしていますが、本来は変数化したほうがよいと思います。

リクエストおためし

EDA Controller で上記 Rulebook を利用したアクティベーションを作成し、さっそくリクエストを試します。

認証 OK 例

リクエスト:

curl -X POST http://192.168.1.144:5000/endpoint \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer 72232ecb-8b5f-15ed-5d28-597840a98608' \
  -d '{"message": "sakana"}'

レスポンス:

endpoint

ansible.eda.webhook の仕様として、エンドポイントの文字列がレスポンスの body になります。

認証 NG 例

せっかくなので、認証が正常でないパターンもためします。

なお、HTTP ステータスコードはすべて 401 で、アクティベーションのログとしては以下のようなログになります。

2023-08-08 12:31:05,530 - aiohttp.access - INFO - 10.0.2.100 [08/Aug/2023:12:31:05 +0000] "POST /endpoint HTTP/1.1" 401 188 "-" "curl/7.88.1"

Authorization ヘッダーフィールドなし

リクエスト:

curl -X POST http://192.168.1.144:5000/endpoint \
  -H 'Content-Type: application/json' \
  -d '{"message": "sakana"}'

レスポンス:

401: Missing authorization token

トークン間違い

リクエスト:

curl -X POST http://192.168.1.144:5000/endpoint \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer xxinvalidxx' \
  -d '{"message": "sakana"}'

レスポンス:

Invalid authorization token

Basic 認証(未サポート)

リクエスト:

curl -X POST http://192.168.1.144:5000/endpoint \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic hogehoge' \
  -d '{"message": "sakana"}'

レスポンス:

Only Bearer type is accepted

おわりに

ansible.eda.webhook イベントソースプラグインを、トークンによる認証とあわせて使ってみました。認証なしの Webhook を許可させたくないときには便利そうです。

今回の token に指定するような値を管理するための、認証情報の機能を作るのはどうかという issue がありました。

github.com

[Ansible/EDA] ansible-rulebook 1.0.1 で run_job_template のみ Automation Controller に接続確認するようになった

はじめに

これまで ansible-rulebook では、どんな action でも連携先の Automation Controller に接続確認しにく仕様がありました。

ansible-rulebook 1.0.1 で、action が run_job_template のときのみ接続確認する改善が行われました。

Release v1.0.1 · ansible/ansible-rulebook · GitHub

Don't try to connect with AWX when no run_job_template action is used

関連PR :[AAP-13209] Skip connecting to controller if no run_job_template action by mkanoor · Pull Request #538 · ansible/ansible-rulebook · GitHub

簡単に動作確認してみます。

  • 検証環境
    • ansible-rulebook 1.0.0 (DE はregistry.redhat.io/ansible-automation-platform-24/de-supported-rhel8:1.0.0-77)
    • ansible-rulebook 1.0.1 (DE はregistry.redhat.io/ansible-automation-platform-24/de-supported-rhel8:1.0.0-107)

動作確認

actiondebug を指定した Rulebook を利用し、ansible-rulebook の 1.0.0 と 1.0.1 とで違いを確認します。

before: ansible-rulebook 1.0.0

まずは、ansible-rulebook 1.0.0 での挙動です。

以下 Attempting to connect to Controller とあるように、接続確認をしています。

Attempting to login to registry: registry.redhat.io
Pulling image registry.redhat.io/ansible-automation-platform-24/de-supported-rhel8:1.0.0-77
Starting Container
Container args ['ansible-rulebook', '--worker', '--websocket-ssl-verify', 'no', '--websocket-address', 'wss://host.containers.internal/api/eda/ws/ansible-rulebook', '--id', '943', '--heartbeat', '300', '-v']
2023-08-08 05:09:00,395 - ansible_rulebook.app - INFO - Starting worker mode

2023-08-08 05:09:00,395 - ansible_rulebook.websocket - INFO - websocket wss://host.containers.internal/api/eda/ws/ansible-rulebook connecting

2023-08-08 05:09:00,425 - ansible_rulebook.websocket - INFO - websocket wss://host.containers.internal/api/eda/ws/ansible-rulebook connected

2023-08-08 05:09:00,468 - ansible_rulebook.job_template_runner - INFO - Attempting to connect to Controller https://192.168.1.143

2023-08-08 05:09:00,862 - ansible_rulebook.app - INFO - AAP Version 4.4.0

2023-08-08 05:09:00,863 - ansible_rulebook.app - INFO - Starting sources

2023-08-08 05:09:00,863 - ansible_rulebook.app - INFO - Starting rules

...(略)...

after: ansible-rulebook 1.0.1

次に、ansible-rulebook 1.0.1 での挙動です。

先ほどあった Attempting to connect to Controller から始まる接続確認のログは見当たりませんでした。

Attempting to login to registry: registry.redhat.io
Pulling image registry.redhat.io/ansible-automation-platform-24/de-supported-rhel8:1.0.0-102
Starting Container
Container args ['ansible-rulebook', '--worker', '--websocket-ssl-verify', 'no', '--websocket-address', 'wss://host.containers.internal/api/eda/ws/ansible-rulebook', '--id', '944', '--heartbeat', '300', '-v']
2023-08-08 05:10:43,637 - ansible_rulebook.app - INFO - Starting worker mode

2023-08-08 05:10:43,637 - ansible_rulebook.websocket - INFO - websocket wss://host.containers.internal/api/eda/ws/ansible-rulebook connecting

2023-08-08 05:10:43,681 - ansible_rulebook.websocket - INFO - websocket wss://host.containers.internal/api/eda/ws/ansible-rulebook connected

2023-08-08 05:10:43,769 - ansible_rulebook.app - INFO - Starting sources

2023-08-08 05:10:43,769 - ansible_rulebook.app - INFO - Starting rules

...(略)...

補足

[Cloudflare] Cloudflare Tunnel のトンネルの起動をサービス化する

はじめに

前回の記事 では、Cloudflare Tunnel を cloudflared tunnel run トンネル名 で起動しました。

フォアグラウンドでの起動ではなく、サービスとして起動したかったので試しました。基本的には以下の公式ドキュメント通りです。試行錯誤したあとに少しアレンジしています。

developers.cloudflare.com

  • 検証環境

設定ファイルの編集

まず設定ファイル(前回の記事でいう /home/admin/.cloudflared/config.yml)を修正します。

修正ポイントは、credentials-file で指定する認証情報の JSON ファイルのパスです。

これまでは、一般ユーザー admin で作業していたので、/home/admin/.cloudflared/config.yml というパスでした。サービス化するにあたって、ココじゃない感があるので /etc/cloudflared ディレクトリ配下にすることにします。

# トンネルのID
tunnel: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 
# トンネル作成時に生成された認証情報ファイル
credentials-file: /etc/cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json   # パスを変更

# Ingress rules
# どのホスト名のリクエストを内部のどのサービスに転送するかの設定
ingress:
  - hostname: sv01.example.com
    service: https://10.0.1.1   # ローカルの転送先 sv01
    originRequest:
      noTLSVerify: true         # 証明書検証の無視(ラボ環境のため)
  - hostname: sv02.example.com
    service: https://10.0.1.2   # ローカルの転送先 sv02
    originRequest:
      noTLSVerify: true         # 証明書検証の無視(ラボ環境のため)
  - service: http_status:404    # どのホスト名にもマッチしない場合

パスの変更に合わせて、/etc/cloudflared/ ディレクトリの作成と JSON ファイルもコピーしておきます。(残ったものは後で削除予定

$ whoami
admin
$ sudo mkdir /etc/cloudflared
$ sudo cp /home/admin/.cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json /etc/cloudflared/
$
$ ll /etc/cloudflared/
total 4
-r--------. 1 root root 161 Aug  6 11:30 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json

なお、credentials-file で指定した JSON ファイルが見つからないと、サービスのインストールコマンド実行時にエラーになってしまいます。

参考: https://community.cloudflare.com/t/cloudflared-tunnel-service-run-failing-setup-ubuntu/472882

サービスのインストール

続いてサービスをインストールします。cloudflared コマンド側にサービスのインストール機能があるようです。

$ sudo cloudflared --config /home/admin/.cloudflared/config.yml service install
2023-08-06T02:36:53Z INF Using Systemd
2023-08-06T02:36:54Z INF Linux service for cloudflared installed successfully
$

補足: 公式ドキュメントの手順との差分

当初、公式ドキュメント通り、一般ユーザーから単に cloudflared service install を実行したら、以下のエラーで失敗しました。

failed to copy /home/admin/.cloudflared/config.yml to /etc/cloudflared/config.yml: open /etc/cloudflared/config.yml: permission denied

設定ファイルを /etc/cloudflared/ ディレクトリにコピーしようとして、権限がないというエラーです。

続いて sudo をつけて sudo cloudflared service install としましたが、今度は設定ファイルが見つからないというエラーになりました。

Cannot determine default configuration path. No file [config.yml config.yaml] in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp /etc/cloudflared /usr/local/etc/cloudflared]

sudo を付けているので ~/.cloudflared は、 /root/.cloudflared ディレクトリを示しますが、そのディレクトリには config.yml がなく、他の候補のディレクトリ(~/.cloudflare-warp など)にもないということです。あるのは /home/admin/.cloudflared/config.yml です。ということで、前述のように、sudo のほか、明示的に設定ファイルのパスを指定するために --config オプション付きで、インストールコマンドを実行しました。

サービスのとトンネルの状態確認

サービス cloudflared はすでにサービスが開始されていました。OS起動時のサービス起動も enabled です。

$ systemctl status cloudflared
● cloudflared.service - cloudflared
     Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; vendor preset: disabled)
     Active: active (running) since Mon 2023-08-06 11:36:54 JST; 3min 0s ago
   Main PID: 11098 (cloudflared)
      Tasks: 6 (limit: 11060)
     Memory: 26.4M
        CPU: 204ms
     CGroup: /system.slice/cloudflared.service
             └─11098 /usr/bin/cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run

Aug 06 11:36:54 gateway cloudflared[11098]: 2023-08-06T02:36:54Z INF Initial protocol quic
...()...

トンネルの CONNECTIONS もあります(未接続時は空欄)。

$ cloudflared tunnel list
You can obtain more detailed information for each tunnel with `cloudflared tunnel info <name/uuid>`
ID                                   NAME    CREATED              CONNECTIONS
aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa gateway 2023-08-06T02:27:19Z 2xKIX, 2xNRT

そして、今回ルールを定義した以下 2ホストのアクセスをして目的の画面が開くことを確認します。

不要ファイルの削除

ここまでで、各ファイルの配置は以下のようになっています。

$ ls -l /home/admin/.cloudflared/
total 12
-rw-------. 1 admin admin 1938 Aug  6 11:26 cert.pem
-rw-r--r--. 1 admin admin  754 Aug  6 11:28 config.yml
-r--------. 1 admin admin  161 Aug  6 11:27 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json
$
$ ls -l /etc/cloudflared/
total 8
-rw-r--r--. 1 root root 754 Aug  6 11:36 config.yml
-r--------. 1 root root 161 Aug  6 11:30 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json

/etc/cloudflared/config.yml がサービスのインストールコマンドによってコピーされたファイルです。

$ diff /home/admin/.cloudflared/config.yml /etc/cloudflared/config.yml
$

トンネルの起動に必要なファイルは /ect/cloudflared ディレクトリに寄せたので、/home/admin/.cloudflared/ 配下の設定ファイルと認証情報 JSON ファイルは不要になりました。それぞれ削除します。

$ rm /home/admin/.cloudflared/config.yml
$ rm /home/admin/.cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json

ホスト追加時のオペレーション

今後、公開したいサーバー/サービスが増えてき場合の手順も、サービス化に伴い少し変わりました。

  1. 設定ファイル ./etc/cloudflared/config.ymlingress の追記
  2. CNAME の追加: cloudflared tunnel route dns gateway 追加ホスト名
  3. トンネルの再開: (sudo systemctl restart cloudflared)

おわりに

Cloudflare Tunnel のトンネル接続をサービス化しました。

積み残し課題は1点。 トンネルは常に利用したいわけではないので、必要に応じて開け締めしたいところです。ですが、トンネル自体を削除すると、UUID が変わったりと不都合です。なので、CNAME レコードの追加と削除をもって、トンネルの開け締めをしようかと検討中です。

[Ansible/EDA] EDA Controller のプロジェクト更新とアクティベーションの再開を REST API で操作する

はじめに

以前の記事で、EDA Controller の REST API の操作を試しました。お作法はなんとなく分かったので次のお題にうつります。

もともと API を使いたくなったきっかけにもなるのですが、Rulebook の書き方を試行錯誤しているとき、

  1. リポジトリ上の Rulebook の修正
  2. プロジェクトの同期
  3. アクティベーションの再開
  4. 新しいアクティベーション履歴のログを開く

という一連の作業が地味に面倒でした。なので今回はこれを API 経由でやるというお題にします。

(現状、アクチベーション再開時にプロジェクトの同期を走らせるような設定は見当たりませんでした。そもそも手元の Rulebook を CLI (ansible-rulebook) で動かすという手もありますが)

  • 環境
    • EDA Controller 1.0.0
      • バージョン番号は rpm のファイル名から類推
      • AAP 2.4 のインストーラーで構築したもの

引き続き、REST API を叩くのには curl コマンドを利用します。

プロジェクトの同期

プロジェクトの同期は /api/eda/v1/projects/{プロジェクトID}/sync/ への `POST です。

今回の対象のプロジェクトID は 1 です。あらかじめ画面操作時の URL か、/api/eda/v1/projects/ への GET で調べておきます。

リクエスト:

curl -X POST 'https://(EDA Controllerのアドレス)/api/eda/v1/projects/1/sync/' -k -s \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic (ユーザー:パスワードのBase64エンコード文字列)' \
  | python3 -m json.tool

レスポンス:

{
    "name": "rulebook-sample",
    "description": "",
    "credential_id": null,
    "id": 1,
    "url": "",
    "git_hash": "708782695db79751a2f21d27b689aa815bd59593",
    "import_state": "pending",
    "import_error": null,
    "import_task_id": "99a7682c-41cf-4f37-af19-dfd1a2acfe0a",
    "created_at": "2023-08-05T02:37:52.758560Z",
    "modified_at": "2023-08-07T08:21:47.990192Z"
}

アクティベーションの再開

アクティベーションの再開をするには、予め対象の アクティベーションID を特定しておく必要があります。

準備: アクティベーションID の確認

アクティベーションID の確認は、/api/eda/v1/activations/GET です。

リクエスト:

curl -X GET 'https://(EDA Controllerのアドレス)/api/eda/v1/activations/' -k -s \
  -H 'Authorization: Basic (ユーザー:パスワードのBase64エンコード文字列)' \
  | python3 -m json.tool

レスポンス:

{
    "count": 1,
    "next": null,
    "previous": null,
    "page_size": 20,
    "page": 1,
    "results": [
        {
            "id": 7,
            "name": "hello_webhook",
            "description": "",
            "is_enabled": true,
            "status": "running",
            "decision_environment_id": 1,
            "project_id": 1,
            "rulebook_id": 8,
            "extra_var_id": null,
            "restart_policy": "always",
            "restart_count": 0,
            "rulebook_name": "webhook_debug.yml",
            "rules_count": 1,
            "rules_fired_count": 0,
            "created_at": "2023-08-07T07:47:33.341471Z",
            "modified_at": "2023-08-07T08:27:39.642858Z"
        }
    ]
}

今回は1つしかアクティベーションがないですが、対象の アクティベーション ID は 7 と特定できました。

再開

実際のアクティベーション再開は、/api/eda/v1/activations/{アクティベーションID}/restart/ への POST です。

リクエスト:

curl -X POST 'https://(EDA Controllerのアドレス)/api/eda/v1/activations/7/restart/' -k -s \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic (ユーザー:パスワードのBase64エンコード文字列)'

レスポンスはありません。アクティベーションインスタンスの ID がレスポンスに入ってると助かりますが、別途調べることにします(後述)。

画面を見ると、新しいアクティベーションインスタンスが「実行中」になっています。ログはここから追っていけばよいことになります。

アクティベーションが再開された後

おまけ: アクティベーションのログ確認

ログは画面で確認するのでも十分ですが、API でのログの確認方法も調べたのでついでにやってみました。

準備: アクティベーションインスタンス ID 特定

まず、アクティベーションインスタンスのIDを特定する必要があります。先ほどの図でいう 936 です。

アクティベーションインスタンスの一覧表示は /api/eda/v1/activations/{アクティベーションID}/instances/ への GET です。

アクティベーションインスタンスという言葉はこのエンドポイントからとりました)

リクエスト:

curl -X GET 'https://(EDA Controllerのアドレス)/api/eda/v1/activations/7/instances/' -k -s \
  -H 'Authorization: Basic (ユーザー:パスワードのBase64エンコード文字列)' \
  | python3 -m json.tool

レスポンス:

{
    "count": 11,
    "next": null,
    "previous": null,
    "page_size": 20,
    "page": 1,
    "results": [
        {
            "id": 936,
            "name": "hello_webhook",
            "status": "running",
            "activation_id": 7,
            "started_at": "2023-08-07T08:37:44.939620Z",
            "ended_at": null
        },
        {
            "id": 935,
            "name": "hello_webhook",
            "status": "failed",
            "activation_id": 7,
            "started_at": "2023-08-07T08:37:15.507197Z",
            "ended_at": "2023-08-07T08:37:21.123188Z"
        },
        // ...(略)...

"status": "running" な ID が 936 だと特定できました。

ログ確認

アクティベーションインスタンスごととのログの確認をするには、/api/eda/v1/activation-instances/{アクティベーションインスタンスID}/logs/ への GET です。

リクエスト:

curl -X GET 'https://(EDA Controllerのアドレス)/api/eda/v1/activation-instances/936/logs/' -k -s \
  -H 'Authorization: Basic (ユーザー:パスワードのBase64エンコード文字列)' \
  | python3 -m json.tool

レスポンス:

{
    "count": 24,
    "next": "/api/eda/v1/activation-instances/936/logs/?page=2",
    "previous": null,
    "page_size": 20,
    "page": 1,
    "results": [
        {
            "id": 61796,
            "line_number": 0,
            "log": "Attempting to login to registry: registry.redhat.io",
            "activation_instance": 936
        },
        {
            "id": 61799,
            "line_number": 1,
            "log": "Pulling image registry.redhat.io/ansible-automation-platform-24/de-supported-rhel8:latest",
            "activation_instance": 936
        },
        {
            "id": 61800,
            "line_number": 2,
            "log": "Starting Container",
            "activation_instance": 936
        },
        // ...(略)...
        {
            "id": 61817,
            "line_number": 19,
            "log": "2023-08-07 08:37:52,860 - ansible_rulebook.websocket - INFO - websocket wss://host.containers.internal/api/eda/ws/ansible-rulebook connecting\n",
            "activation_instance": 936
        }
    ]
}

現状は、ログの古い順に表示されました。一度に表示するログの件数を指定するには、GET パラメーター ?page_size=30 のように付加します。

ただ、これは GET した時のログまでしかないので、追加分のログを見たいときは再度 GET する必要があります。画面で見ると自動更新されるので、ログ確認についてはやはり画面のほうが便利かなと思います。

おわりに

リポジトリ上の Rulebook を修正した後に操作していた、プロジェクトの同期、アクティベーションの再開、ログの確認までは API で操作してみました。

また、条件は不明ですが、試行錯誤しているときに意図しないアクティベーションインスタンスが作成(結果的に Webhook 待ち受けポートがかぶってエラー)されるときがたまにあったのですが、詳細はおえていません。

まだ改善の余地はありますが、API での操作方法は分かったので、ここからまた工夫したいと思います。