Prevent duplicate role insertion into roles: (#50552)

* Corner case in which import_role would add another instance of a role with the same signature into roles: when it already existed there.

  roles:
	- name: a
  tasks:
       - import_role: name=a

  would execute role 'a' 3 times instead of the intended 2 (x2 in roles: phase +1 in tasks:)

* added tests

(cherry picked from commit eca7c3c8c7)
This commit is contained in:
Brian Coca 2019-01-16 13:39:03 -05:00 committed by Toshio Kuratomi
parent 41214d4426
commit 4a89749dd5
11 changed files with 64 additions and 0 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- prevent import_role from inserting dupe into `roles:` execution when duplicate signature role already exists in the section.

View file

@ -149,6 +149,9 @@ class Role(Base, Become, Conditional, Taggable):
params['from_files'] = from_files
if role_include.vars:
params['vars'] = role_include.vars
params['from_include'] = from_include
hashed_params = hash_params(params)
if role_include.role in play.ROLE_CACHE:
for (entry, role_obj) in iteritems(play.ROLE_CACHE[role_include.role]):

View file

@ -0,0 +1 @@
shippable/posix/group3

View file

@ -0,0 +1,18 @@
- name: test that import_role adds one (just one) execution of the role
hosts: localhost
gather_facts: false
tags: ['importrole']
roles:
- name: a
tasks:
- name: import role ignores dupe rule
import_role: name=a
- name: test that include_role adds one (just one) execution of the role
hosts: localhost
gather_facts: false
tags: ['includerole']
roles:
- name: a
tasks:
- include_role: name=a

View file

@ -0,0 +1,19 @@
- name: play should only show 1 invocation of a, as dependencies in this play are deduped
hosts: testhost
gather_facts: false
tags: [ 'inroles' ]
roles:
- role: a
- role: b
- role: c
- name: play should only show 1 invocation of a, as dependencies in this play are deduped even outside of roles
hosts: testhost
gather_facts: false
tags: [ 'acrossroles' ]
roles:
- role: a
- role: b
tasks:
- name: execute role c which depends on a
import_role: name=c

View file

@ -0,0 +1 @@
- debug: msg=A

View file

@ -0,0 +1,2 @@
dependencies:
- name: a

View file

@ -0,0 +1 @@
- debug: msg=B

View file

@ -0,0 +1,2 @@
dependencies:
- name: a

View file

@ -0,0 +1 @@
- debug: msg=C

View file

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -eux
# test no dupes when dependencies in b and c point to a in roles:
[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags inroles "$@" | grep -c '"msg": "A"')" = "1" ]
[ "$(ansible-playbook no_dupes.yml -i ../../inventory --tags acrossroles "$@" | grep -c '"msg": "A"')" = "1" ]
# but still dupe across plays
[ "$(ansible-playbook no_dupes.yml -i ../../inventory "$@" | grep -c '"msg": "A"')" = "2" ]
# include/import can execute another instance of role
[ "$(ansible-playbook allowed_dupes.yml -i ../../inventory --tags importrole "$@" | grep -c '"msg": "A"')" = "2" ]
[ "$(ansible-playbook allowed_dupes.yml -i ../../inventory --tags includerole "$@" | grep -c '"msg": "A"')" = "2" ]