Skip to content

Commit f4d8f5e

Browse files
Ben Kincaidoybed
Ben Kincaid
authored andcommitted
Introduce 'exclude_tags' (#124)
* added option for skip_tags var to omit objects * documented skip_tags in openshift_applier README * changed skip_tags to exclude_tags and allowed for use with filter_tags * fixed newline error * changed refrences in filter from filter_tags to include_tags * fixed filter_content function name * fixed include_list var * handle overlapping invocation of include_tags and exclude_tags with erroring out * added newline for ci job * same as before * removed blank line * remove trailing white space * updated error messages and default filter values * updated filter error
1 parent 1b87b99 commit f4d8f5e

File tree

5 files changed

+86
-20
lines changed

5 files changed

+86
-20
lines changed

roles/openshift-applier/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ openshift_cluster_content:
5151
file: <file source>
5252
action: <apply|create> # Optional: Defaults to 'apply'
5353
no_log: <True|False> # Optional: no_log at content level if functionality desired. Defaults to False
54-
tags: # Optional: Tags are only needed if `include_tags` is used
54+
tags: # Optional: Tags are only needed if `include_tags` or `exclude_tags` is used
5555
- tag1
5656
- tag2
5757
post_steps: # Optional: post-steps at content level can be added if desired
@@ -212,12 +212,15 @@ metadata:
212212

213213
### Filtering content based on tags
214214

215-
The `openshift-applier` supports the use of tags in the inventory (see example above) to allow for filtering which content should be processed and not. The `include_tags` variable/fact takes a comma separated list of tags that will be processed and only content with matching tags will be applied.
215+
The `openshift-applier` supports the use of tags in the inventory (see example above) to allow for filtering which content should be processed and not. The `include_tags` and `exclude_tags` variables/facts take a comma separated list of tags that will be processed. The `include_tags` will apply content **only** with the matching tags, while `exclude_tags` will apply **anything but** the content with the matching tags.
216216

217-
**_NOTE:_** Entries in the inventory without tags will not be processed when a valid list is supplied with the `include_tags` option.
217+
**_NOTE:_** Entries in the inventory without tags will not be processed when a valid list of tags is supplied with `include_tags`.
218+
219+
**_NOTE:_** If the same tag exists in both `include_tags` and `exclude_tags` the run will error out. Likewise, if tags from the two options annuls each other, the execution will also error out.
218220

219221
```
220222
include_tags=tag1,tag2
223+
exclude_tags=tag3,tag4
221224

222225
```
223226

roles/openshift-applier/defaults/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ client: oc
33
default_oc_action: apply
44
tmp_inv_dir: ''
55
include_tags: ''
6+
exclude_tags: ''
67
provision: True
78
params_from_vars: {}
89
oc_ignore_unknown_parameters: true

roles/openshift-applier/filter_plugins/applier-filters.py

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,98 @@
88
from urllib.request import urlopen
99

1010

11+
# Return content invoked with improper tag usage
12+
def get_invalid_tag_usage(applier_list, include_tags, exclude_tags):
13+
14+
if len(include_tags.strip()) == 0 or len(exclude_tags.strip()) == 0:
15+
return []
16+
17+
# Convert comma seperated list to an actual list and strip off whitespaces of each element
18+
include_list = include_tags.split(",")
19+
include_list = [i.strip() for i in include_list]
20+
21+
exclude_list = exclude_tags.split(",")
22+
exclude_list = [i.strip() for i in exclude_list]
23+
24+
repeated_tags = []
25+
# Loop through the main list to check if any tags were invoked incorrectly
26+
# - append to repeated_tags and return
27+
for a in applier_list[:]:
28+
if 'content' in a:
29+
for c in a['content'][:]:
30+
if 'tags' not in c:
31+
continue
32+
33+
include_matches = list(set(include_list) & set(c['tags']))
34+
35+
exclude_matches = list(set(exclude_list) & set(c['tags']))
36+
37+
if include_matches and exclude_matches:
38+
repeated_tags.append({
39+
'object': a.get("object", "[unknown]"),
40+
'name': c.get("name", "[unknown]"),
41+
'invoked_tags': include_matches + exclude_matches,
42+
})
43+
44+
return repeated_tags
45+
46+
1147
# Helper function to simplify the 'filter_applier_items' below
12-
def filter_content(content_dict, outer_list, filter_list):
13-
# If tags don't exists at all, just remove the 'content'
48+
def filter_content(content_dict, outer_list, include_list, exclude_list):
49+
# Handle if tags don't exist in the 'content' section
1450
if 'tags' not in content_dict:
15-
outer_list.remove(content_dict)
51+
if include_list:
52+
outer_list.remove(content_dict)
1653
return
1754

18-
# Find out of if any of the tags exists in the 'content' section
19-
intersect_list = [val for val in content_dict['tags'] if val in filter_list]
55+
# Handle if include_tags exists in the 'content' section
56+
if include_list:
57+
intersect_list = [
58+
val for val in content_dict['tags'] if val in include_list]
59+
if len(intersect_list) == 0:
60+
outer_list.remove(content_dict)
61+
return
2062

21-
# If none of the filter tags exists, remove it from the list
22-
if len(intersect_list) == 0:
23-
outer_list.remove(content_dict)
63+
# Handle if exclude_tags exists in the 'content' section
64+
if exclude_list:
65+
intersect_list = [
66+
val for val in content_dict['tags'] if val in exclude_list]
67+
if len(intersect_list) != 0:
68+
outer_list.remove(content_dict)
69+
return
2470

2571

2672
# Main 'filter_applier_items' function
27-
def filter_applier_items(applier_list, include_tags):
28-
# If no filter tags supplied - just return list as-is
29-
if len(include_tags.strip()) == 0:
73+
def filter_applier_items(applier_list, include_tags, exclude_tags):
74+
# If no tag lists supplied - just return list as-is
75+
if len(include_tags.strip()) == 0 and len(exclude_tags.strip()) == 0:
3076
return applier_list
3177

78+
exclude_list, include_list = [], []
79+
3280
# Convert comma seperated list to an actual list and strip off whitespaces of each element
33-
filter_list = include_tags.split(",")
34-
filter_list = [i.strip() for i in filter_list]
81+
if include_tags and len(include_tags.strip()) != 0:
82+
include_list = include_tags.split(",")
83+
include_list = [i.strip() for i in include_list]
84+
85+
if exclude_tags and len(exclude_tags.strip()) != 0:
86+
exclude_list = exclude_tags.split(",")
87+
exclude_list = [i.strip() for i in exclude_list]
3588

3689
# Loop through the main list to check tags
3790
# - use a copy to allow for elements to be removed at the same time as we iterrate
3891
for a in applier_list[:]:
3992
# Handle the 'content' entries
4093
if 'content' in a:
4194
for c in a['content'][:]:
42-
filter_content(c, a['content'], filter_list)
95+
filter_content(c, a['content'], include_list, exclude_list)
4396

4497
if len(a['content']) == 0:
4598
applier_list.remove(a)
4699

47100
return applier_list
48101

102+
49103
# Function used to determine a files location - i.e.: URL, local file/directory or "something else"
50104
def check_file_location(path):
51105
# default return values
@@ -64,7 +118,7 @@ def check_file_location(path):
64118
if (not path_status):
65119
try:
66120
url_status = urlopen(path)
67-
except (IOError,ValueError):
121+
except (IOError, ValueError):
68122
# Must be a pre-loaded template, nothing to do
69123
return return_vals
70124

@@ -84,8 +138,10 @@ def check_file_location(path):
84138

85139
class FilterModule(object):
86140
''' Filters to handle openshift_cluster_content data '''
141+
87142
def filters(self):
88143
return {
89144
'check_file_location': check_file_location,
90-
'filter_applier_items': filter_applier_items
145+
'filter_applier_items': filter_applier_items,
146+
'get_invalid_tag_usage': get_invalid_tag_usage
91147
}

roles/openshift-applier/tasks/error-on-unsupported.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@
2424
when:
2525
- unsupported_items is defined
2626
with_dict: "{{ unsupported_items }}"
27+
28+
- name: "Error out if any unsupported tag usage was found"
29+
fail:
30+
msg: "Confused - Do not know how to process the combination of tags for content {{ item.object }}/{{ item.name }} and include_tags/exclude_tags parameters."
31+
with_items:
32+
- "{{ openshift_cluster_content | get_invalid_tag_usage(include_tags, exclude_tags) }}"

roles/openshift-applier/tasks/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
- name: "Create OpenShift objects"
2727
include_tasks: process-content.yml
2828
with_items:
29-
- "{{ openshift_cluster_content | filter_applier_items(include_tags) | default([]) }}"
29+
- "{{ openshift_cluster_content | filter_applier_items(include_tags, exclude_tags) | default([]) }}"
3030
loop_control:
3131
loop_var: entry
3232
when:

0 commit comments

Comments
 (0)