blob: 3a3aefd264c50e26c9d5bb45fe214d491357d5f2 [file] [log] [blame]
Samuli Silvius542bdfd2019-03-19 13:40:50 +02001.. This work is licensed under a Creative Commons Attribution 4.0 International License.
2.. http://creativecommons.org/licenses/by/4.0
3.. Copyright 2019 Samsung Electronics Co., Ltd.
4
5OOM ONAP Offline Installer Testing Guide
6^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7
8This testing guide describes how offline installer can be tested in local
9development environment (laptop) without the need for actual servers.
10
11Documentation refers to files/directories in ``ansible`` directory of this repository.
12
13Introduction
14============
15
16Offline installer uses Molecule_ for testing all roles.
17
18Molecule is tool for ansible roles development and testing. In this project
19Molecule is used for integration type of testing for both roles and playbooks.
20Role code is tested against simulated host.
21
22Molecule is designed to test single Ansible_ role in isolation. Offline installer however
23has many small roles that are dependent on each other and also execution order for roles
24is meaningful. In that respect Molecule's design does not offer sufficient level
25of testing as it's lacking playbook level of scenario testing by default.
26Luckily Molecule is highly configurable and it is possible to achieve a higher level of
27testing scenarios for the offline installer.
28
29Testing with Molecule is divided to two levels of testing:
30 1) role level testing (as per Molecule design)
31 2) playbook level testing (offline installer own setup)
32
33Purpose
34=======
35
36The purpose of using testing framework like Molecule is to make possible for developer to
37verify ansible code changes locally in own laptop without the need for big resources.
38
39Developer is also expected to do development of the Ansible code and the Molecule test
40code at the same time.
41Offline installer does not have unittest level of testing for the ansible code.
42
43Any commit made to ansible code base needs to first pass Molecule tests before
44it's merged.
45
46Test levels
47===========
48
49To cover both testing levels (role and playbook) with maximum benefit and minimum
50copy-pasting, the testing code should be written in reusable way.
51
52Reusable test code can be achieved by writing all prepare/cleanup and other
53helping code as a roles into main test directory.
54Also testinfra_ test code can be shared between different roles and between different scenarios
55of one role.
56
57Testing of role and one scenario (one execution run of molecule) is fully
58defined by **molecule.yml** file.
59
60molecule.yml file is always located in directory:
61
62 <tested-role>/molecule/<scenario>/molecule.yml
63
64i.e. one role can have multiple scenarios (different configuration, OS etc. whatever user wants)
65to execute tests for same role. Each scenario has own molecule.yml file and own testinfra
66tests.
67
68Molecule.yml file is the only file that cannot be re-used (except with symbolic links) but
69all other resources can be reused by referencing those in molecule.yml file or/and indirectly
70from resources molecule.yml is pointing to.
71
72**tested-role** is clear in case of normal role level testing, but in playbook level testing the
73tested-role is just an invented role name and directory with molecule directory inside but no
74actual ansible role code.
75
76Role level testing
77------------------
78
79The target is to test single role in isolation just like Molecule is designed.
80Role level testing is supposed to cover:
81
82- Syntax checking (Yamllint_, `Ansible lint`_, flake8_)
83- Ansible code testing
84- Idempotence testing
85- Verifying role results from target hosts (testinfra tests)
86
87Ansible code testing can/should also cover all different options how this role
88can be run (`scenario <https://molecule.readthedocs.io/en/latest/configuration.html#root-scenario>`_).
89Different molecule runs can be implemented as own scenarios (in addition to default scenario)
90or default scenario playbook can be extended to run role tests multiple times just adjusting
91configuration between.
92
Bartek Grzybowskic265b832019-04-09 13:22:43 +020093Single scenario example with nexus role
Samuli Silvius542bdfd2019-03-19 13:40:50 +020094::
95
96 ├── infrastructure.yml
97 ├── roles
98 │   ├── nexus
99 │   │   ├── defaults
100 │   │   ├── files
101 │   │   ├── molecule
102 │   │   │   └── default
103 │   │   │   ├── molecule.yml
104 │   │   │   ├── playbook.yml
105 │   │   │   ├── prepare.yml
106 │   │   │   └── tests
107 │   │   ├── tasks
108 │   │   └── vars
109
Bartek Grzybowskic265b832019-04-09 13:22:43 +0200110Multiple scenario example with chrony role
111::
112
113 roles/chrony
114 ├── defaults
115 │   └── main.yml
116 ├── handlers
117 │   └── main.yml
118 ├── molecule
119 │   ├── default
120 │   │   ├── molecule.yml
121 │   │   ├── playbook.yml
122 │   │   └── prepare.yml
123 │   └── ubuntu
124 │   └── molecule.yml
125 ├── tasks
126 │   └── main.yml
127 └── templates
128 └── chrony.conf.j2
129
130By default molecule runs just default scenario. To run specific one ``-s <scenario name>``
131option must be used. The only subcommands supporting ``--all`` switch for playing with
132all scenarios are ``test`` and ``destroy``. If using other ones ``-s`` must be used.
133
134The cross-scenario code reuse paradigm should be rather implemented inside particular
135scenario's ``molecule.yml`` file than by using filesystem symlinks. All provisioner
136playbooks should be located in default scenarios directory then and referenced in
137alternative scenarios as follows
138::
139
140 provisioner:
141 name: ansible
142 lint:
143 name: ansible-lint
144 env:
145 ANSIBLE_ROLES_PATH: ../../../../test/roles
146 playbooks:
147 prepare: ../default/prepare.yml
148 converge: ../default/playbook.yml
149
Samuli Silvius542bdfd2019-03-19 13:40:50 +0200150Playbook level testing
151----------------------
152
153Playbook level testing is this project's (offline installer) own
154setup and way of using Molecule. The target is to raise testing level
155from single role testing up to single playbook testing.
156
157Playbook level testing can be used also to run multiple playbooks and/or
158playbooks multiple times with different configuration.
159
160The aim is to verify multiple roles working together i.e. higher level of
161integration testing.
162
163Practically the **tested-role** is just a wrapper directory to conform
164molecule required directory structure and provide a name for the test.
165Directory itself does not contain any ansible role code, but just
166molecule files configured to run multiple other roles.
167
168Playbook level test directories should be named consistently according to
169tested playbook and prefix string ``play`` and with optional description
170if there are multiple scenarios for single playbook:
171
172 play-<playbookname>[-<description>]
173
174E.g.
175
176- ``play-infrastructure``
177- ``play-resources``
178
179As role's are tested with own molecule tests in isolation, playbook level tests
180should focus to integration of the roles and should avoid of repeating same tests
181as done already for individual roles.
182
183Playbook level testing is supposed to cover:
184 - Ansible code testing
185
186Basically it's easier to highlight what is supposed to be **avoided** in playbook level
187testing for the reason not to repeat the same that is done already in role level testing.
188
189- Syntax checking is left out already by default as molecule does linting only for the
190 role code where molecule is run, and in this case tested-role is empty.
191
192- Idempotence can be tested, but should be disabled (by default) in molecule.yml because
193 it takes too much time and was tested already for individual roles.
194
195- Verifying target hosts with testinfra tests can be done but then something else
196 should be tested as in role based tests. And if those 2 would overlap it's better
197 to leave them out.
198
199Example with infrastructure playbook level test files
200::
201
202 ├── infrastructure.yml
203 └── test
204 ├── play-infrastructure
205 │   └── molecule
206 │   └── default
207 │   ├── molecule.yml
208 │   ├── playbook.yml
209 │   ├── prepare.yml
210 │   └── tests
211
212Test code reuse and naming
213===========================
214
215As both testing levels test the same Ansible roles, there are a need
216to share common code for both of them.
217
218Testinfra_ Python code should be shared when also playbook level
219tests verify target hosts. However sharing is not limited only for the 2 test levels
220but also between different roles.
221
222Individual role have testinfra tests on directory:
223
224 roles/<role>/molecule/<scenario>/tests
225
226and any commonly usable testinfra Python code should be placed to directory:
227
228 test/testinfra
229
230Ansible role testing uses several resources defined by provisioner section of
231molecule.yml
232https://molecule.readthedocs.io/en/latest/configuration.html#provisioner
233
234Most common resources that are written for role testing are:
235
236- playbook.yml (mandatory but can include specific code)
237- prepare.yml
238- cleanup.yml
239- create.yml
240- destroy.yml
241
242all of which can be just placed to scenario directory together with playbook.yml
243(without editing molecule.yml when in default directory) and all of which can
244include ansible code to do something e.g. prepare role for testing.
245
246Example molecule files:
247
248Role level tests for nexus role:
249 - roles/nexus/molecule/default/molecule.yml
250 - roles/nexus/molecule/default/playbook.yml
251 - roles/nexus/molecule/default/prepare.yml
252playbook level tests for infrastructure playbook:
253 - test/play-infrastructure/molecule/default/molecule.yml
254 - test/play-infrastructure/molecule/default/playbook.yml
255 - test/play-infrastructure/molecule/default/prepare.yml
256
257Sharing all test code should be done by writing them in the form of ansible
258roles and placing commonly usable roles into:
259
260 test/roles/<testrole>
261
262Test roles should be named consistently according to action it's needed and
263role for it's for together with optional description:
264
265 <action>-<role>[-<description>]
266
267Examples of commonly used test roles
268::
269
270 ├── infrastructure.yml
271 └── test
272 ├── play-infrastructure
273 └── roles
274 ├── post-certificates
275 ├── prepare-common
276 ├── prepare-dns
277 ├── prepare-docker
278 ├── prepare-nexus
279 └── prepare-nginx
280
281Molecule platform images
282========================
283
284Molecule can build images of the tested hosts on the fly with default
285Dockerfile template (docker driver) or from a Dockerfile provided by user.
286In case of Vagrant driver used box image can be also fully customized by user.
287
Bartek Grzybowskic265b832019-04-09 13:22:43 +0200288To speed up testing and lessen the footprint of code for image preparation it's
289preferred to use unmodified images from Docker Registry whenever possible (can be
290pulled prior to running Molecule) or pre-build images created from Dockerfiles
291listed below. Most significant feature of those is support for Systemd, so they
292should be used in cases where ansible's 'systemd' module is used.
Samuli Silvius542bdfd2019-03-19 13:40:50 +0200293
294Used Dockerfiles/Box definitions are kept in following directory structure
295::
296
297 └── test
298 └── images
299 ├── docker
300 │   ├── build-all.sh
301 │   ├── centos7
302 │   │   ├── build.sh
Samuli Silvius542bdfd2019-03-19 13:40:50 +0200303 │   │   └── Dockerfile
304 │   └── ubuntu
305 │   ├── build.sh
306 │   └── Dockerfile
307 └── vagrant
308
Bartek Grzybowskic265b832019-04-09 13:22:43 +0200309``Build-all.sh`` is a script for building all images, ``build.sh`` scripts in
310particular platforms subdirs are for building just specific images. Keep in mind
311that while images from Docker Registry will be downloaded automatically at run
312time, the above ones **must** be built manually prior to launching Molecule.
313
Samuli Silvius542bdfd2019-03-19 13:40:50 +0200314Build images
315------------
316
317Build all platforms images before running Molecule tests. Building can be done
318with the following single command:
319
320 test/images/docker/build-all.sh
321
322Install
323=======
324
325Molecule can be installed in multiple ways and in this guide 2 different ways is
326covered.
327
328- Install Molecule with pip in virtual environment
329- Use Molecule provided docker container to run Molecule
330
331Install with pip
332----------------
333
334This is a OS dependent and some prerequisites needs to be installed, but after
335prerequisites are installed installing Molecule can be done by calling following
336script:
337
338 source test/bin/install-molecule.sh
339
340As for the required OS packages, see example for Ubuntu in the install-molecule.sh
341script's comments or from Molecule_ pages.
342
343Note that sourcing the script is not needed to get Molecule installed but it leaves
344you already into virtual environment and ready to run Molecule.
345
346To get out from virtual environment issue:
347
348 deactivate
349
350And next time to activate virtual environment again before running Molecule, issue:
351
352 source ~/molecule_venv/bin/activate
353
354And here the directory ``~/molecule_venv`` is just the default virtual environment
355path that install-molecule.sh script is using and can be overridden with
356``VENV_PATH`` environment variable.
357
358Use Molecule docker container
359-----------------------------
360
361Molecule provides docker containers images via quay.io_ where Molecule, Ansible
362and all needed dependencies are build to the image.
363
364In this way of using Molecule, no installation is needed and only docker is the
365prerequisite for running Molecule.
366
367For using provided image to test offline-installer roles, following scripts are
368provided:
369
370Build container image:
371 ``test/molecule-docker/build.sh``
372
373This will build image named ``molecule-dev`` with strict version tag.
374
375Set molecule into the PATH:
376 ``source test/bin/set_molecule_paths.sh``
377
378That will add the actual Molecule run wrapper script test/bin/molecule.sh to path
379usable from everywhere similarly than molecule with pip and virtual environment.
380
381Run Molecule wrapper script:
382 ``test/bin/molecule.sh``
383
384For running Molecule. Using ``molecule-dev`` image and the exact version defined by
385test/docker/build.sh script.
386
387Usage
388=====
389
390Basic usage of molecule tests. See more detailed instructions from Molecule_
391
392Run complete testing for a role or a playbook:
393
3941. cd roles/<role> or cd test/play-<playbook-name>
3952. molecule test
396
397Develop a role code and run testing during the coding:
398
3991. cd roles/<role>
4002. Edit ansible code and molecule test code when needed
4013. molecule converge
4024. Repeat steps 2 and 3 until code is ready and molecule tests are passing
4035. molecule test
404
405.. _Molecule: https://molecule.readthedocs.io
406.. _quay.io: https://quay.io/repository/ansible/molecule
407.. _Testinfra: https://testinfra.readthedocs.io
408.. _Flake8: http://flake8.pycqa.org
409.. _Yamllint: https://github.com/adrienverge/yamllint
410.. _Ansible Lint: https://github.com/ansible/ansible-lint
411.. _Ansible: https://www.ansible.com/