■ はじめに
以前の記事 [Ansible][ACI] EPG に紐付けされている Contract 一覧を取得する - てくなべ (tekunabe)で、aci_epg_to_contract
モジュール を利用して、EPG に紐付けられている Contract 一覧を取得するサンプルをご紹介しました。
一方で、aci_rest
モジュール を利用する方法もあります。aci_rest
モジュールでは、APIC REST API の仕様をより意識する必要がある代わりに、他のモジュールでは手の届かなかった柔軟な処理ができます。
たとえば、aci_epg_to_contract
モジュールでは、Provide Contract、Consumed Contract それぞれ別に取得する必要がありました。aci_rest
モジュールでは、リクエストする URL を工夫することで、Provide Contract、Consumed Contract 両方いっぺんに取得できます。
この記事では簡単なサンプルをもとにして説明します。
参考
aci_epg_to_contract
モジュールを利用する場合はこちら
■ APIC 側画面
以前の記事 https://tekunabe.hatenablog.jp/entry/2019/11/04/ansible_aci_get_epg_contracts:titile と同様に、ある EPG に
- Provided Contract: c_sql、c_web
- Consumed Contract: c_test
と設定されている状態を想定します。
■ Playbook
取得には、aci_rest
モジュールを利用します。
ポイントは path
オプション
aci_epg_to_contract
モジュールでは、contract_type: provider
のときにクエリストリングに rsp-subtree-class=fvRsProv
を、contract_type: consumer
のときに rsp-subtree-class=fvRsCons
を付加します。
一方、今回利用する aci_rest
モジュールでは、クエリストリングも自分で指定できます。rsp-subtree-class=fvRsProv,fvRsCons
と指定することで、Provide Contract、Consumed Contract 両方いっぺんに取得するようにリクエストできます。
また、今回の場合、EPG の子オブジェクトまでの取得だけで十分なので、rsp-subtree=all
ではなく、rsp-subtree=children
を指定します。
少々雑ですが、各 Contract の情報をのまま debug
で表示します。
--- - hosts: apic gather_facts: no tasks: # get contracts (provided/consumed) - name: get contracts aci_rest: host: "{{ ansible_host }}" username: "{{ username }}" password: "{{ password }}" validate_certs: no method: get path: /api/mo/uni/tn-tenant1/ap-ap1/epg-epg1.json?rsp-subtree-class=fvRsProv,fvRsCons&rsp-subtree=children register: result # debug contracts - name: debug contracts debug: msg: "{{ item }}" loop: "{{ result.imdata[0].fvAEPg.children | default([]) }}" loop_control: label: "{{ ansible_loop.index0 }}" extended: yes
■ 実行
Playbook を実行します。
$ ansible-playbook -i ../../inventory.ini get_contracts_rest.yml PLAY [apic] ******************************************************************** TASK [get contracts] *********************************************************** ok: [apic01] TASK [debug contracts] ********************************************************* ok: [apic01] => (item=0) => { "msg": { "fvRsProv": { // Provided Contract "attributes": { "annotation": "", "childAction": "", "ctrctUpd": "ctrct", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "matchT": "AtleastOne", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "prio": "unspecified", "rType": "mo", "rn": "rsprov-c_sql", "state": "formed", "stateQual": "none", "status": "", "tCl": "vzBrCP", "tContextDn": "", "tDn": "uni/tn-tenant1/brc-c_sql", "tRn": "brc-c_sql", "tType": "name", "tnVzBrCPName": "c_sql", // Contract 名 "triggerSt": "triggerable", "uid": "15374", "updateCollection": "no" } } } } ok: [apic01] => (item=1) => { "msg": { "fvRsProv": { // Provided Contract "attributes": { "annotation": "", "childAction": "", "ctrctUpd": "ctrct", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "matchT": "AtleastOne", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "prio": "unspecified", "rType": "mo", "rn": "rsprov-c_web", "state": "formed", "stateQual": "none", "status": "", "tCl": "vzBrCP", "tContextDn": "", "tDn": "uni/tn-tenant1/brc-c_web", "tRn": "brc-c_web", "tType": "name", "tnVzBrCPName": "c_web", // Contract 名 "triggerSt": "triggerable", "uid": "15374", "updateCollection": "no" } } } } ok: [apic01] => (item=2) => { "msg": { "fvRsCons": { // Consumed Contract "attributes": { "annotation": "", "childAction": "", "ctrctUpd": "ctrct", "deplInfo": "", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "prio": "unspecified", "rType": "mo", "rn": "rscons-c_test", "state": "formed", "stateQual": "none", "status": "", "tCl": "vzBrCP", "tContextDn": "", "tDn": "uni/tn-tenant1/brc-c_test", "tRn": "brc-c_test", "tType": "name", "tnVzBrCPName": "c_test", // Contract 名 "triggerSt": "triggerable", "uid": "15374", "updateCollection": "no" } } } } PLAY RECAP ********************************************************************* apic01 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
各 debug モジュールの取得で
- Provided Contract: c_sql、c_web
- Consumed Contract: c_test
となっていることを確認できました。
参考: query で取得したデータの全体
参考のために query した結果の全体の中身も掲載します。
クリックして広げて見る
{ "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "failed": false, "imdata": [ { "fvAEPg": { "attributes": { "annotation": "", "childAction": "", "configIssues": "", "configSt": "applied", "descr": "", "dn": "uni/tn-tenant1/ap-ap1/epg-epg1", "exceptionTag": "", "extMngdBy": "", "floodOnEncap": "disabled", "fwdCtrl": "", "hasMcastSource": "no", "isAttrBasedEPg": "no", "isSharedSrvMsiteEPg": "no", "lcOwn": "local", "matchT": "AtleastOne", "modTs": "2019-11-03T14:54:44.955+00:00", "monPolDn": "uni/tn-common/monepg-default", "name": "epg1", "nameAlias": "", "pcEnfPref": "unenforced", "pcTag": "32771", "prefGrMemb": "exclude", "prio": "unspecified", "scope": "2555904", "shutdown": "no", "status": "", "triggerSt": "triggerable", "txId": "17293822569102705193", "uid": "15374" }, "children": [ { "fvRsCons": { "attributes": { "annotation": "", "childAction": "", "ctrctUpd": "ctrct", "deplInfo": "", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "prio": "unspecified", "rType": "mo", "rn": "rscons-c_test", "state": "formed", "stateQual": "none", "status": "", "tCl": "vzBrCP", "tContextDn": "", "tDn": "uni/tn-tenant1/brc-c_test", "tRn": "brc-c_test", "tType": "name", "tnVzBrCPName": "c_test", "triggerSt": "triggerable", "uid": "15374", "updateCollection": "no" }, "children": [ { "fvCollectionCont": { "attributes": { "childAction": "deleteNonPresent", "collectionDn": "uni/tn-tenant1/brc-c_test", "lcOwn": "local", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "name": "", "nameAlias": "", "rn": "collectionDn-[uni/tn-tenant1/brc-c_test]", "status": "" } } } ] } }, { "fvRsProv": { "attributes": { "annotation": "", "childAction": "", "ctrctUpd": "ctrct", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "matchT": "AtleastOne", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "prio": "unspecified", "rType": "mo", "rn": "rsprov-c_sql", "state": "formed", "stateQual": "none", "status": "", "tCl": "vzBrCP", "tContextDn": "", "tDn": "uni/tn-tenant1/brc-c_sql", "tRn": "brc-c_sql", "tType": "name", "tnVzBrCPName": "c_sql", "triggerSt": "triggerable", "uid": "15374", "updateCollection": "no" }, "children": [ { "fvCollectionCont": { "attributes": { "childAction": "deleteNonPresent", "collectionDn": "uni/tn-tenant1/brc-c_sql", "lcOwn": "local", "modTs": "2019-11-03T15:28:38.764+00:00", "monPolDn": "uni/tn-common/monepg-default", "name": "", "nameAlias": "", "rn": "collectionDn-[uni/tn-tenant1/brc-c_sql]", "status": "" } } } ] } }, { "fvRsProv": { "attributes": { "annotation": "", "childAction": "", "ctrctUpd": "ctrct", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "matchT": "AtleastOne", "modTs": "2019-11-04T01:39:51.572+00:00", "monPolDn": "uni/tn-common/monepg-default", "prio": "unspecified", "rType": "mo", "rn": "rsprov-c_web", "state": "formed", "stateQual": "none", "status": "", "tCl": "vzBrCP", "tContextDn": "", "tDn": "uni/tn-tenant1/brc-c_web", "tRn": "brc-c_web", "tType": "name", "tnVzBrCPName": "c_web", "triggerSt": "triggerable", "uid": "15374", "updateCollection": "no" }, "children": [ { "fvCollectionCont": { "attributes": { "childAction": "deleteNonPresent", "collectionDn": "uni/tn-tenant1/brc-c_web", "lcOwn": "local", "modTs": "2019-11-03T15:16:07.253+00:00", "monPolDn": "uni/tn-common/monepg-default", "name": "", "nameAlias": "", "rn": "collectionDn-[uni/tn-tenant1/brc-c_web]", "status": "" } } } ] } } ] } } ], "status": -1, "totalCount": 1, "warnings": [ "Platform darwin on host apic01 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information." ] }
■ まとめ
aci_rest
モジュール を利用して、EPG に紐付けれられている Contract の一覧を取得しました。
aci_epg_to_contract
モジュールではできない取得方法ができました。
使い分け方としては、基本は aci_epg_to_contract
のような各オブジェクト用のモジュールを利用し、それでもできない場合のみ、aci_rest
を利用する、といった形になるかと思います。
参考
[Ansible][ACI] EPG に紐付けされている Contract 一覧を取得する - てくなべ (tekunabe)