Skip to content

Commit

Permalink
Replace ci_make role by custom action plugin
Browse files Browse the repository at this point in the history
Replacing a whole role by a single action plugin allows a faster run,
while reducing drastically the amount of tasks.

Note that this action plugin requires a small change to the
community.general.make module[1] - it should be merged in the following
hours/days.

[1] ansible-collections/community.general#6160
  • Loading branch information
cjeanner committed Mar 9, 2023
1 parent 14eb374 commit 2c5f636
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 250 deletions.
8 changes: 8 additions & 0 deletions ci_framework/plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Custom ansible plugins and modules

## action_plugins/ci_make
This wraps `community.general.make` module, mostly. It requires an additional
parameter, `output_dir`, in order to output the `make` generated command.

It requires a pull-request to merge in the community.general collection:
https://github.com/ansible-collections/community.general/pull/6160
57 changes: 57 additions & 0 deletions ci_framework/plugins/action/ci_make.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# This specific action plugin needs a version of community.general collection
# providing this patch:
# https://github.com/ansible-collections/community.general/pull/6160
# While the "make" command will actually run, it won't be able to generate
# the needed file.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os

from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleActionFail, AnsibleError
from ansible.utils.display import Display

ERR_UPDATE_COLLECTION = '''"command" not found in community.genera.make output.
Please update collection. The expected reproducer file will NOT be generated!
'''


class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
super(ActionModule, self).run(tmp, task_vars)
module_args = self._task.args.copy()

if 'output_dir' not in module_args:
raise AnsibleActionFail('output_dir parameter is missing')

output_dir = module_args.pop('output_dir')
# Check for directory
if not os.path.exists(output_dir):
raise AnsibleError("%s doesn't exist" % output_dir)
if not os.path.isdir(output_dir):
raise AnsibleError("%s isn't a directory" % output_dir)
if not os.access(output_dir, os.W_OK):
raise AnsibleError("%s isn't writable" % output_dir)

# Run module only if all conditions are here for file creation
mod_ret = self._execute_module(module_name='community.general.make',
module_args=module_args,
task_vars=task_vars, tmp=tmp)
del tmp
if 'command' not in mod_ret:
Display().warning(ERR_UPDATE_COLLECTION)
return mod_ret

# Generate file - with this PR, the module will output the built
# command: https://github.com/ansible-collections/community.general/pull/6160
# First get directory content and count files
fnum = len([n for n in os.listdir(output_dir)
if os.path.isfile(os.path.join(output_dir, n))])
clean_task_name = self._task._name.replace(' ', '_').lower()
fname = '%i_%s.sh' % (fnum, clean_task_name)
with open(os.path.join(output_dir, fname), 'w') as fh:
fh.write('#!/bin/sh\n' + mod_ret['command'] + '\n')
os.chmod(os.path.join(output_dir, fname), 0o755)

return mod_ret
13 changes: 0 additions & 13 deletions ci_framework/roles/ci_make/README.md

This file was deleted.

21 changes: 0 additions & 21 deletions ci_framework/roles/ci_make/defaults/main.yml

This file was deleted.

41 changes: 0 additions & 41 deletions ci_framework/roles/ci_make/meta/main.yml

This file was deleted.

43 changes: 0 additions & 43 deletions ci_framework/roles/ci_make/molecule/default/converge.yml

This file was deleted.

8 changes: 0 additions & 8 deletions ci_framework/roles/ci_make/molecule/default/molecule.yml

This file was deleted.

34 changes: 0 additions & 34 deletions ci_framework/roles/ci_make/molecule/default/prepare.yml

This file was deleted.

66 changes: 0 additions & 66 deletions ci_framework/roles/ci_make/tasks/main.yml

This file was deleted.

24 changes: 0 additions & 24 deletions ci_framework/roles/ci_make/templates/make_script.j2

This file was deleted.

3 changes: 3 additions & 0 deletions ci_framework/tests/integration/integration.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[defaults]
remote_tmp=/tmp
local_tmp=/tmp
55 changes: 55 additions & 0 deletions ci_framework/tests/integration/targets/make/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
- name: Create some directories
ansible.builtin.file:
path: "/tmp/{{ item }}"
state: directory
loop:
- artifacts
- project_makefile

- name: Inject dummy Makefile
ansible.builtin.copy:
dest: /tmp/project_makefile/Makefile
content: |
.DEFAULT_GOAL := help
.RECIPEPREFIX := >
FOO_BAR ?= "toto"
help:
> @echo "This is the help thing showing ${FOO_BAR}"
- name: Run ci_make without any params
register: no_params
ci_make:
chdir: /tmp/project_makefile
output_dir: /tmp/artifacts

- name: Run ci_make with a param
register: with_params
ci_make:
chdir: /tmp/project_makefile
output_dir: /tmp/artifacts
params:
FOO_BAR: starwars

- name: Ensure we have correct output
ansible.builtin.assert:
that:
- no_params.stdout == 'This is the help thing showing toto'
- with_params.stdout == 'This is the help thing showing starwars'

- name: Check generated files
block:
- name: Gather files
register: reproducer_scripts
ansible.builtin.stat:
path: "/tmp/artifacts/{{ item }}"
loop:
- '0_run_ci_make_without_any_params.sh'
- '1_run_ci_make_with_a_param.sh'

- name: Assert file status
ansible.builtin.assert:
that:
- item.stat.exists is defined
- item.stat.exists
loop: "{{ reproducer_scripts.results }}"

0 comments on commit 2c5f636

Please sign in to comment.