てくなべ (tekunabe)

ansible / network / automation

[Ansible] tower_workflow_job_template_node モジュールでノード定義とリンク定義をうまくやる

はじめに

以前の記事で、Collection 版の tower モジュールである、tower_workflow_job_templatetower_workflow_job_template_nodeを利用してワークフローを作成する Playbook をご紹介しました。

tekunabe.hatenablog.jp

そのなかで、

本当はノードの作成とリンクをいっぺんにやりたかったのですが、先にノードが作成された後でないとリンクできないようでした。そのため、先にノード作成、あとでリンク、というように別のタスクにしています。

と書きました。

タスクを分けること自体はしょうがなさそうです。ですが、ノードの定義とノード間のリンク定義の処理が散漫して関係が分かりにくい点は、まだ改善の余地がありそうです。

この記事ではもう一工夫したいと思います。

tower_workflow_template モジュールjobがつかない)ではないので、ご注意ください。


■ 目指すワークフロー

前回と同じワークフローを目指します。

f:id:akira6592:20200403201625p:plain
目指すワークフロー


■ 準備

変数ファイルと Playbook を準備します。

変数ファイル

処理からノードやリンク定義をノードやリンク定義を変数ファイルとして用意します。

どこでもいいのですが、今回は workflow.yml とします。 単なる変数定義なので、ここではノードやリンクの定義をいっぺんにしても大丈夫です。

---
workflow:
  name: test_WF02   # ワークフロージョブテンプレートの名前
  nodes:          # 紐づけるワークフローノード
    - identifier: node101   # 内部識別ID
      unified_job_template: tower-sample-ok # 実行するジョブテンプレート
      success_nodes:  # 成功時に進めるノード(緑のリンク)
        - node201
        - node202
      failure_nodes:  # 障害発生時に進めるノード(赤のリンク)
        - node209
    - identifier: node201
      unified_job_template: tower-sample-ok
      success_nodes:
        - node301
    - identifier: node202
      unified_job_template: tower-sample-ok
      success_nodes:
        - node301
    - identifier: node209
      unified_job_template: tower-sample-ok
    - identifier: node301
      unified_job_template: tower-sample-ok
      all_parents_must_converge: true   # すべてのノードが成功で収束したときのみ実行

Playbook

Playbook は以下のとおりです。

先程作成した workflows.yml を読み込み、ワークフロージョブテンプレート本体の作成、ノードの作成、リンクの作成のタスクで都度呼び出します。

- hosts: tower
  gather_facts: no
  connection: local

  vars:
    conn: &conn
      tower_host: https://AWXのホスト
      tower_username: admin
      tower_password: xxxx
      validate_certs: no

  vars_files:
    - workflow.yml   # 先程定義した変数ファイル

  tasks:
    # ワークフロージョブテンプレート本体の作成
    - name: creat WFJT
      awx.awx.tower_workflow_job_template:
        <<: *conn
        name: "{{ workflow.name }}"   # 名前

    # ワークフローノードの作成
    - name: create WFJT node
      awx.awx.tower_workflow_job_template_node:
        <<: *conn
        identifier: "{{ item.identifier }}"   # 内部識別ID
        unified_job_template: "{{ item.unified_job_template }}"  # 実行するジョブテンプレート
        workflow_job_template: "{{ workflow.name }}"        # 関連付けるワークフロージョブテンプレート名
        all_parents_must_converge: "{{ item.all_parents_must_converge | default(omit) }}" 
      loop: "{{ workflow.nodes }}"

    # ワークフローノード間のリンクの作成
    - name: link
      awx.awx.tower_workflow_job_template_node:
        <<: *conn
        identifier: "{{ item.identifier }}"
        workflow_job_template: "{{ workflow.name }}"
        success_nodes: "{{ item.success_nodes | default(omit) }}" # 成功時に進めるノード(緑のリンク)
        failure_nodes: "{{ item.failure_nodes | default(omit) }}" # 障害発生時に進めるノード(赤のリンク)
      loop: "{{ workflow.nodes }}"
      when: (item.success_nodes is defined) or (item.failure_nodes is defined) # 次へのリンクを定義したノードのみ実行

これで、処理とノード定義をそれとなく分離できました。


実行

Playbook を実行します。

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

PLAY [tower] **********************************************************************************************************************************************************

TASK [creat WFJT] *****************************************************************************************************************************************************
changed: [awx1]

TASK [create WFJT node] ***********************************************************************************************************************************************
changed: [awx1] => (item={'identifier': 'node101', 'unified_job_template': 'tower-sample-ok', 'success_nodes': ['node201', 'node202'], 'failure_nodes': ['node209']})
changed: [awx1] => (item={'identifier': 'node201', 'unified_job_template': 'tower-sample-ok', 'success_nodes': ['node301']})
changed: [awx1] => (item={'identifier': 'node202', 'unified_job_template': 'tower-sample-ok', 'success_nodes': ['node301']})
changed: [awx1] => (item={'identifier': 'node209', 'unified_job_template': 'tower-sample-ok'})
changed: [awx1] => (item={'identifier': 'node301', 'unified_job_template': 'tower-sample-ok', 'all_parents_must_converge': True})

TASK [link] ***********************************************************************************************************************************************************
changed: [awx1] => (item={'identifier': 'node101', 'unified_job_template': 'tower-sample-ok', 'success_nodes': ['node201', 'node202'], 'failure_nodes': ['node209']})
changed: [awx1] => (item={'identifier': 'node201', 'unified_job_template': 'tower-sample-ok', 'success_nodes': ['node301']})
changed: [awx1] => (item={'identifier': 'node202', 'unified_job_template': 'tower-sample-ok', 'success_nodes': ['node301']})
skipping: [awx1] => (item={'identifier': 'node209', 'unified_job_template': 'tower-sample-ok'}) 
skipping: [awx1] => (item={'identifier': 'node301', 'unified_job_template': 'tower-sample-ok', 'all_parents_must_converge': True}) 

PLAY RECAP ************************************************************************************************************************************************************
awx1                       : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

無事に実行できました。

node209 や、 node301 は、success_nodesfailure_nodes も定義していなかったので、リンク定義のタスクはスキップされています。


■ 確認

f:id:akira6592:20200404105916p:plain
ワークフロージョブテンプレート本体

f:id:akira6592:20200404113059p:plain
ワークフローの定義