ansibleのcollectionにPRを送る流れ
はじめに
この記事は、ansible公式のcollectionにPull Requestを送る流れをまとめたものです。
基本的にはドキュメントが豊富でその流れに沿って進める事ができますが、躓いた部分も多くありましたので、記事にしてみました。
実際に送ったPull Requestは下記になります。
環境準備
下記にて動作確認をしています。
項目 | バージョン |
---|---|
macOS | 11.2.3(BigSur) |
python(system) | 3.9.4 |
ansible | 2.10.9 |
docker | 20.10.6 |
pyenv | 1.2.26 |
リポジトリのfork/clone
Pull Requestを送る対象のリポジトリをfork/cloneしてきますが、注意点があります。
後述するテストを行う際に、ansible-test
コマンドを使用しますが、下記ディレクトリ構成にしないと上手く動かないようです。
{任意のディレクトリ}/ansible_collections/{namespace}/{collection}/
namespaceとcollectionはリポジトリ名から確認できます(namespace.collectionという形になっています)。
ansible-collections/junipernetworks.junos
をcloneする例は下記になります。
> mkdir -p ~/dev/ansible_collections/junipernetworks
> git clone https://github.com/minefuto/junipernetworks.junos ~/dev/ansible_collections/junipernetworks/junos
ansibleのインストール
ansibleをvenv環境にインストールします。
venvのファイルが邪魔にならないように、とりあえず~/dev
配下にvenv環境を作成します。
> cd ~/dev
> python3 -m venv venv
> source venv/bin/activate
venv> pip install ansible
venv> ansible --version
ansible 2.10.9
config file = None
configured module search path = ['/Users/minefuto/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
executable location = /usr/local/bin/ansible
python version = 3.9.4 (default, Apr 5 2021, 01:50:46) [Clang 12.0.0 (clang-1200.0.32.29)]
pythonパッケージのインストール
使用するcollectionに必要なpythonパッケージをインストールします。
また、toxもテストの際に必要になるためインストールしておきます。
venv> cd ~/dev/ansible_collections/junipernetworks/junos
venv> pip install tox
venv> pip install -r requirements.txt
venv> pip install -r test-requirements.txt
docker/pyenvのインストール
後述するansible-test
コマンドを使用する際にdocker/pyenvを使用する場合があるため、必要に応じて下記を参考にそれぞれのツールをインストールします。
collectionの動作確認
cloneしたcollectionのコードを使用してansibleを動かせるかを確認します。
ansibleはデフォルトではconfigured module search path
配下のモジュールを読み込むため、~/dev/ansible_collections
配下にcloneしたものは読み込んでくれません。
venv> ansible --version
ansible 2.10.9
config file = None
configured module search path = ['/Users/minefuto/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
-snip-
configured module search path
は、環境変数ANSIBLE_LIBRARY
で変更する事ができるため、~/dev/ansible_collections/{namespace}/{collection}
を指定し、上手く反映されているか確認します。
venv> export ANSIBLE_LIBRARY=/Users/minefuto/dev/ansible_collections/junipernetworks/junos
venv> ansible --version
ansible 2.10.9
config file = None
configured module search path = ['/Users/minefuto/dev/ansible_collections/junipernetworks/junos']
-snip-
指定ができたら、ansible-doc
コマンドを使用して、実際に~/dev/ansible_collections
配下のモジュールを呼び出してみます。
正常に呼び出せていたら、呼び出し元のpythonファイルがcloneしてきたファイルとなります。
venv> ansible-doc -t module junos_command
> JUNOS_COMMAND (/Users/minefuto/dev/ansible_collections/junipernetworks/junos/plugins/modules/junos_command.py)
-snip-
この状態になれば、その他のコマンド(ansible-playbook
等)でもcloneしてきたcollection内のモジュールを呼び出せるようになっているはずです。
テストの動作確認
コードに変更を加える前にテストを正しく実行できるかを確認します。
ansible公式のcollectionでは、主に下記4つのテストを通す必要があります。
各collection毎に必要なテストは異なりますので、詳細はドキュメントを確認して下さい。
- tox
- Sanityテスト
- Unitテスト
- Integrationテスト
ansible-testコマンドについて
Sanity/Unit/Integrationテストを行うためのコマンドとなります。
いくつかの実行方法がありますが、今回は下記の2つ紹介します。
- docker環境での実行
- ローカル環境での実行
docker環境での実行
docker環境での実行方法は、自動的にコンテナを作成し、複数のpythonバージョンでテストを行ってくれます。
dockerさえインストールしていれば、その他環境を準備する必要がないため、特に理由がなければこちらを使う方が簡単かと思います。
下記コマンドにてdocker環境で各種テストを実行できます。
特定のpythonバージョンでのみテストを行いたい場合は、--python
オプションにより指定可能です。
venv> ansible-test <testの種類> --docker -v
venv> ansible-test <testの種類> --docker -v --python 3.8
テストに使用するdockerイメージは下記が使用され、デフォルトでは2.9.0が使用されるようです。
collectionが2.9.0をサポートしていない場合等、使用するdockerイメージを変更したい場合は、下記のようにバージョン指定する事ができます。venv> ansible-test <testの種類> --docker quay.io/ansible/default-test-container:2.10.0
ローカル環境での実行
ローカル環境での実行方法は、複数のpythonバージョンでテストを行う場合、pyenvでテストに必要な複数のpythonバージョンをインストールしておく必要があります。
また、各pythonバージョン毎に個別でvenv環境構築や依存パッケージのインストール等が必要となるため、docker環境で上手く動かない場合等に使用すれば良いかと思います。
下記コマンドにてローカル環境で各種テストを実行できます。
venv環境では--python-interpriter
を使用して明示的にvenvのpythonを指定します。
Import Errorが発生した場合は、必要に応じて不足しているpythonパッケージをpip
コマンドでインストールして下さい。
ansible-test <testの種類> --python 3.9 -v --python-interpreter $(which python)
他のpythonバージョンでansible-test
コマンドを実行する場合は、下記のようにpyenvでバージョン変更し、venvの作成からやり直して下さい。
venv> deactivate
> cd ~/dev
> pyenv global 3.8.7
> python3 -m venv venv38
> source venv/bin/activate
> cd ~/dev/ansible_collections/junipernetworks/junos
venv38> pip install ansible
venv38> pip install -r requirements.txt
venv38> pip install -r test-requirements.txt
venv38> ansible-test <testの種類> --python 3.8 -v --python-interpreter $(which python)
tox
toxは複数のpythonバージョンでテストやコードフォーマットの確認を行う事ができるツールですが、ansible公式のcollectionではblack/flake8等によるコードフォーマットの確認のみに使用しているようです。
下記コマンドにてtoxによるチェックを実行し、エラーがない事を確認します。
venv> tox -elinters
-snip-
_________________________________________________________ summary __________________________________________________________
linters: commands succeeded
congratulations :)
Sanityテスト
Sanityテストは、docに記載されている型と実際のコードの型が一致しているかや、必要なモジュールがimportできるか等、様々な静的解析を行います。
テスト内容の詳細はドキュメントを確認して下さい。
下記コマンドにてdocker環境又はローカル環境でSanityテストを実行し、エラーがない事を確認します。
venv> ansible-test sanity --docker -v
venv> ansible-test sanity --python 3.9 -v --python-interpreter $(which python)
注意点として依存するcollectionがある場合、下記のようなエラーが発生して失敗します。
Running sanity test 'import' with Python 3.9
ERROR: Found 76 import issue(s) on python 3.9 which need to be resolved:
-snip-
依存するcollectionについては、galaxy.yml
のdependenciesに記載されています。
---
authors:
- Ansible Network Community (ansible-network)
dependencies:
"ansible.netcommon": ">=2.0.0"
-snip-
解決するには、依存するcollectionを下記形式で配置する必要があります。
{任意のディレクトリ}/ansible_collections/{namespace}/{collection}/
ansible-collections/junipernetworks.junos
が依存している、ansible-collections/ansible.netcommon
を配置する場合は、下記のように配置します。
> mkdir -p ~/dev/ansible_collections/ansible
> git clone https://github.com/ansible-collections/ansible.netcommon ~/dev/ansible_collections/ansible/netcommon
Unitテスト
Unitテストは、test/unit
配下のテストコードを実行します。
下記コマンドにてdocker環境又はローカル環境でUnitテストを実行し、エラーがない事を確認します。
venv> ansible-test units --docker -v
venv> ansible-test units --python 3.9 -v --python-interpreter $(which python)
Integrationテスト
Integrationテストは、実際に操作する対象のネットワーク機器を用意し、test/integration/targets/{module名}
配下に準備されたplaybookを実行し、正常に動作するかを確認するテストとなります。
ネットワーク機器の準備
テスト対象のネットワーク機器を準備する必要があります。
準備するネットワーク機器については、公式が実際にCIを回している機器と一致させると良いかと思います。
詳細はGithubのPull Requestページから連携しているCIツール(zuul)のログから確認する事ができます。
ansible-collections/junipernetworks.junos
は、vsrx3 18.4R1
を使用しているようです。
inventoryファイルの準備
テストに使用するinventoryファイルを準備する必要があります。
こちらも公式が実際にCIに使用しているinventoryファイルをCIツール(zuul)のログから確認してきて、必要な項目のみ自分の環境用に変更する形が良いかと思います。
ansible-collections/junipernetworks.junos
は、下記のinventoryファイルを使用しているようです。
# This file is generated by Ansible
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
#
[junos]
vsrx3-18.4R1 ansible_host=38.108.68.235 ansible_user=zuul
[yang:children]
junos
[junos:vars]
ansible_network_os=junipernetworks.junos.junos
ansible_python_interpreter=/home/zuul/venv/bin/python
netconf={'transport': 'netconf'}
[netconf]
vsrx3-18.4R1 ansible_host=38.108.68.235 ansible_user=zuul
[netconf:vars]
ansible_network_os=junipernetworks.junos.junos
ansible_python_interpreter=/home/zuul/venv/bin/python
netconf={'transport': 'netconf'}
自分の環境用に修正したinventoryファイルを適当な場所(今回は~/inventory
)に保存します。
テストの実行
下記コマンドにてIntegrationテストを実行し、エラーがない事を確認します。
(docker環境ではなぜか上手く動かなかったため、ローカル環境にて実行しています)
venv> ansible-test network-integration --inventory ~/inventory
コード変更作業
テストが正常に動作する事を確認できたら、実際にPull Requestを送るための変更やテストコードを追加していきます。
変更が完了したら、再度テストを実行しエラーが発生しない事を確認します。
また、変更作業を行った後は、changelogを追加する必要があります。
changelogは、changelogs/fragments/
配下にyamlファイルを下記フォーマットで新しく作成します。
---
minor_changes:
- Change src element from str to path for junos_scp.
過去のPull Requestのchangelogを確認すれば、どのような形で記載するのかイメージしやすいかと思います。
changelogの詳細なルールについては、ドキュメントを確認して下さい。
Pull Request
ここまできたら、実際にPull Requestを送ります(下記は実際に送ってみたものです)。
送った後はCIが無事完了したかを確認したり、メンテナの方のレビューを待ちましょう。
問題がなければ無事マージされるはずです。
CIでエラーが発生した場合は、下記のようにPull RequestページのChecksタブからログを確認し、なぜ失敗したのかを確認してみましょう。
CIツール(zuul)側の内部エラーでテストが失敗する可能性もあるようなので、その場合はメンテナの方が再度CIを回してくれます。
あとがき
ここまでがansible-collections/junipernetworks.junos
にPull Requestを送り、マージされるまでの流れとなります。
個人的には、ansible-test
コマンドを正常に動作させるのが難しく、環境構築等に手間取りました。
試行錯誤しながらなんとかやってみた結果になるため、誤っている点やもっと良い方法があればご指摘いただければ幸いです。
Discussion