尝试使用GitLab CI来执行自制的Ansible模块CI

这是2018年 Ansible Advent Calendar 的第8篇文章。

我想在这里尝试一下使用GitLab CI进行Ansible自定义模块的CI。之前的一篇文章中我们介绍了如何使用GitLab CI。

(Note: The translation provided is in simplified Chinese. If you prefer traditional Chinese, please let me know.)

    • Ansibleモジュールを自作したらsanityテストをしてみよう

 

    Ansibleモジュールを自作したらunitテストをしてみよう

我撰写了一篇关于这个问题的文章,目的是为了手动测试并希望自动化sanity/unit测试以提高效率。
由于我在这里省略了一些解释部分,建议您先阅读上述文章,然后会更容易理解。

1. 环境

項目バージョンOSCentOS7.5GitLabCommunity Edition 11.5.0

2. 准备

2-1. GitLab安装

请参考以下内容以安装GitLab。

请点击以下链接,获取关于在CentOS 7上安装GitLab的详细说明:https://about.gitlab.com/install/#centos-7

准备gitlab-runner

请参考以下内容进行准备。
顺便提一下,我们将使用docker。

以下是该网址的汉语本地化短语(仅提供一种选项):

https://qiita.com/sky_jokerxx/items/2a264a0194a5cbc7bd12

– 这个链接是指向一个名为”sky_jokerxx”的个人主页的帖子。

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

创建存储库

在这里,我试着在GitLab上创建了以下仓库。

スクリーンショット 2018-11-25 0.16.28.png

__init__.py 是一个空文件。
output_name.py 的源代码如下。我在这基础上进行了一些修改,以便能够进行单元测试(只是添加了一个 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. 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. 单元测试的持续集成

在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

结果将如下所示。

unit_test_result.gif

最后

我在GitLab上尝试了对Ansible自定义模块进行静态解析的健全性测试和单元测试的持续集成。
如果想要在多个Python版本上进行测试,需要执行相当多的步骤,所以通过自动化可以提高效率并留下记录,这样可以获得证据,非常好 🙂
另外,通过使用GitLab可以同时进行代码管理和持续集成,非常方便 🙂

bannerAds