こちらは Ansible Advent Calendar 2018 の8日目の記事です。
ここでは、GitLab CIを使ったAnsible自作モジュールのCIについてやってみたいと思います。
以前
という記事を書いたのですが、これは手動でテストをしているのでsanity/unit test共に自動化して効率化を図ってみたいと思います。
ここではいくつか説明を省略している部分があるので上記の記事を一読していただいてからの方が理解しやすかと思われます。
1. 環境
項目 | バージョン |
---|---|
OS | CentOS7.5 |
GitLab | Community Edition 11.5.0 |
2. 準備
2-1. GitLabインストール
GitLabのインストールについては以下を参考にしてください。
https://about.gitlab.com/install/#centos-7
2-2. gitlab-runnnerの準備
以下を参考にして準備してください。
ちなみに、dockerを使います。
https://qiita.com/sky_jokerxx/items/2a264a0194a5cbc7bd12
3. CIをやってみる
3-1. Dockerイメージの作成
Dockerイメージは以下の選択肢があります。
- 公式のDockerイメージを使う
- 自分でイメージを作る
前者にいたっては、既に使用可能になっているものなので、簡単に使えます。
ただ、Pythonのバージョンが全部(Python2.6〜3.7がインストールされている)入っており容量的には大きくないります。
後者だと、一から準備する手間がありますが必要なものだけインストールすれば公式よりは容量が少なくなります。
例えば、テストするPythonのバージョンが決まりきっているのであれば一から作るという選択肢もあります。
ここでは、前者のあらかじめ用意されているイメージを使ってみようと思います。
3-1-1. Dockerfile作成
自作したモジュールは ansible/modules
配下の適切なグループに保存してもらえればいいのですが、ここでは自作ということで ansible/modules/salf_made
と test/units/modules/salf_made
というディレクトリを作成し、その中に自作したモジュールとテスト用ソースを保存する想定で作成します。
FROM quay.io/ansible/default-test-container:latest
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN cd /opt && \
git clone https://github.com/ansible/ansible.git && \
cd ansible && \
mkdir lib/ansible/modules/salf_made/ && \
mkdir test/units/modules/salf_made
RUN apt-get -y install man-db
3-1-2. Dockerイメージの作成
[root@GitLab ~]# mkdir ansible-ci-docker
[root@GitLab ~]# cd ansible-ci-docker/
[root@GitLab ansible-ci-docker]# vi Dockerfile
(上記のDockerfileをコピー)
[root@GitLab ansible-ci-docker]# docker build . -t ansible-ci:latest
3-2. リポジトリの作成
ここでは、GitLabに以下のリポジトリを作成してみました。
__init__.py
は空です。
output_name.py
のソースは以下のようになっています。ここのを元にunit testが出来るよう一部修正(sum関数を追加してるだけ)して再利用しています
test_output_name.py
のソースについては Unit test CI
で説明します。(sanityテストでは不要です)
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, sky_joker
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
module: output_name
short_description: module that outputs a name.
author:
- sky_joker (@sky-jocker)
version_added: 2.x
description:
- Output the specified name.
requirements:
- python >= 2.7
options:
name:
description:
- Specify name.
required: True
'''
EXAMPLES = '''
---
- output_name:
name: taro
register: r
- debug: msg="{{ r }}"
'''
from ansible.module_utils.basic import AnsibleModule
def sum(a, b):
return a + b
def main():
argument_spec = dict(
name=dict(type="str", required=True)
)
module = AnsibleModule(argument_spec, supports_check_mode=True)
result = dict(changed=False)
name = module.params['name']
if(name):
result['name'] = name
module.exit_json(**result)
else:
module.fail_json(msg="Please specify name.")
if __name__ == "__main__":
main()
GitLab CI用のファイルを作成してみます。
ここでは、Python2.7、3.6、3.7でsanity testのCIをやってみます。
image: ansible-ci:latest
stages:
- sanity_test
python2.7:
stage: sanity_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test sanity --python 2.7 output_name
only:
- master
python3.6:
stage: sanity_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test sanity --python 3.6 output_name
only:
- master
python3.7:
stage: sanity_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test sanity --python 3.7 output_name
only:
- master
3-3. Sanity Test CI
.gitlab-ci.yml
を作成してコミットしてリポジトリにマージするとCIが実行されます。
[root@GitLab example]# vi .gitlab-ci.yml
(上記の.gitlab-ci.ymlをコピペする)
[root@GitLab example]# git add .
[root@GitLab example]# git commit -m 'update'
[master 64a2491] update
1 file changed, 12 insertions(+), 3 deletions(-)
[root@GitLab example]# git push origin master
Username for 'http://192.168.0.115': example
Password for 'http://example@192.168.0.115':
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 383 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To http://192.168.0.115/example/example.git
1763223..64a2491 master -> master
結果は以下のようになります。
3-4. Unit test CI
CIのステージに unit_test
を追加してCIを実行してみます。
.gitlab-ci.yml
は以下のようになります。
image: ansible-ci:latest
stages:
- sanity_test
- unit_test
sanity_python2.7:
stage: sanity_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test sanity --python 2.7 output_name
only:
- master
sanity_python3.6:
stage: sanity_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test sanity --python 3.6 output_name
only:
- master
sanity_python3.7:
stage: sanity_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test sanity --python 3.7 output_name
only:
- master
unit_python2.7:
stage: unit_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cp test_output_name.py /opt/ansible/test/units/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test units --python 2.7 output_name
only:
- master
unit_python3.6:
stage: unit_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cp test_output_name.py /opt/ansible/test/units/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test units --python 3.6 output_name
only:
- master
unit_python3.7:
stage: unit_test
script:
- cp __init__.py /opt/ansible/lib/ansible/modules/salf_made
- cp output_name.py /opt/ansible/lib/ansible/modules/salf_made
- cp test_output_name.py /opt/ansible/test/units/modules/salf_made
- cd /opt/ansible
- . hacking/env-setup
- ansible-test units --python 3.7 output_name
only:
- master
テストで使う test_output_name
は以下のようにしました。
from ansible.modules.salf_made.output_name import sum
def test_sum():
assert sum(1, 2) == 3
結果は以下のようになります。
4. 最後に
Ansibleの自作モジュールの静的解析のsanityテストとunitテストのCIをGitLabでやってみました。
複数のPythonバージョンでテストをしようと思うと結構手順があるので自動化することで効率化ができたり記録が残るのでエビデンスが取れて良いと思います :)
後、GitLabを使うことでコードの管理とCIが同時に出来て便利ですね :)