Implement tag filter strategy

Renames the "artifacting" strategy to "tagfilter" and implements
a more generic tag skipping implementation that can be defined
from within the ansible vars structure dynamically on a per-host,
per-group, or per-playbook basis.

To use the tagfilter strategy, run the playbook with
strategy: tagfilter

and define a hostvar named "skip_tags". Skip tags can be a string
or a list, and any tag CONTAINING a skip tag (an exact match is not
needed) will be skipped.

Also added is a check for a var called "skip_handlers", defaulted
to True. When skip_handlers is enabled, no handlers will be run
regardless of whether the task is skipped or not. If set to False,
handlers will be allowed to run as normal except when tasks are
skipped by the skip_tags.

Change-Id: I649707e6744e03763c4e786d203716ebf657ab48
This commit is contained in:
Logan V 2017-02-23 23:11:33 -06:00
parent 655d777734
commit 5d6c040d18
4 changed files with 140 additions and 4 deletions

View File

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
# #
import itertools
import os import os
import linear import linear
@ -21,10 +22,17 @@ import linear
class StrategyModule(linear.StrategyModule): class StrategyModule(linear.StrategyModule):
def _queue_task(self, host, task, task_vars, play_context): def _queue_task(self, host, task, task_vars, play_context):
"""Wipe the notification system and return for config tasks.""" """Wipe the notification system and return for config tasks."""
task.notify = None skip_handlers = task_vars.get('skip_handlers', True)
skip_tags = os.environ.get('OS_ANSIBLE_SKIP_TAGS', 'config') if skip_handlers:
skip_tags = skip_tags.split(',') task.notify = None
if any([True for i in skip_tags if i in task.tags]): skip_tags = task_vars.get('skip_tags')
if skip_tags:
if not hasattr(skip_tags, '__iter__'):
skip_tags = (skip_tags,)
else:
skip_tags = ()
if any([True for (i, j) in itertools.product(skip_tags, task.tags)
if i in j]):
return return
else: else:
return super(StrategyModule, self)._queue_task( return super(StrategyModule, self)._queue_task(

View File

@ -0,0 +1,125 @@
---
# Copyright 2017, Logan Vig <logan2211@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
- name: Test the tagfilter execution strategy with a list of skip tags
hosts: localhost
strategy: tagfilter
gather_facts: no
vars:
skip_tags:
- skipit
- tagskip
tasks:
- name: Test skipped task
debug:
msg: "This task is skipped"
register: skipped_task
tags:
# Multiple tags specified before the skip tag to make sure the .product()
# loop in the strategy is working properly. (ie. ensure each element in
# the skip_tags list is being checked against each element in this tag
# list.)
- test-tag1
- test-tag2
- test-tag3
- test-tag4
- test-skipit
- name: Test unskipped task
command: /bin/true
register: run_task
notify: Skipped Handler
tags:
- test-runit
handlers:
- name: Skipped Handler
debug:
msg: "This handler is always skipped"
register: skipped_handler
post_tasks:
- name: Check task run states
assert:
that:
- "skipped_task is not defined"
- "run_task | changed"
- "skipped_handler is not defined"
- name: Test the tagfilter execution strategy with a string skip tag
hosts: localhost
strategy: tagfilter
gather_facts: no
vars:
skip_tags: skipit
tasks:
- name: Test skipped task
debug:
msg: "This task is skipped"
register: skipped_task
tags:
- test-skipit
- name: Test unskipped task
command: /bin/true
register: run_task
notify: Skipped Handler
tags:
- test-runit
handlers:
- name: Skipped Handler
debug:
msg: "This handler is always skipped"
register: skipped_handler
post_tasks:
- name: Check task run states
assert:
that:
- "skipped_task is not defined"
- "run_task | changed"
- "skipped_handler is not defined"
- name: Test the tagfilter execution strategy with handlers enabled
hosts: localhost
strategy: tagfilter
gather_facts: no
vars:
skip_handlers: False
skip_tags: skipit
tasks:
- name: Test skipped task
command: /bin/true
register: skipped_task
notify: Skipped Handler
tags:
- test-skipit
- name: Test unskipped task
command: /bin/true
register: run_task
notify: Run Handler
tags:
- test-runit
handlers:
- name: Skipped Handler
debug:
msg: "This handler is always skipped"
register: skipped_handler
- name: Run Handler
command: /bin/true
register: run_handler
post_tasks:
- name: Check task run states
assert:
that:
- "skipped_task is not defined"
- "run_task | changed"
- "skipped_handler is not defined"
- "run_handler | changed"

View File

@ -17,3 +17,5 @@
- include: test-config_template.yml - include: test-config_template.yml
- include: test-filters.yml - include: test-filters.yml
- include: test-strategy-tagfilter.yml

View File

@ -32,6 +32,7 @@ setenv =
ANSIBLE_CONNECTION_PLUGINS={toxinidir}/connection ANSIBLE_CONNECTION_PLUGINS={toxinidir}/connection
ANSIBLE_FILTER_PLUGINS={toxinidir}/filter ANSIBLE_FILTER_PLUGINS={toxinidir}/filter
ANSIBLE_LOOKUP_PLUGINS={toxinidir}/lookup ANSIBLE_LOOKUP_PLUGINS={toxinidir}/lookup
ANSIBLE_STRATEGY_PLUGINS={toxinidir}/strategy
ANSIBLE_LIBRARY={toxinidir}/library ANSIBLE_LIBRARY={toxinidir}/library