-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjenkins-tags.py
More file actions
executable file
·147 lines (122 loc) · 4.85 KB
/
jenkins-tags.py
File metadata and controls
executable file
·147 lines (122 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/python3
import argparse
import os
import sys
import re
import requests
def parse_args():
ap = argparse.ArgumentParser()
ap.add_argument('-l', '--list', action='store_true', help="Output comma-separated list of nodes")
ap.add_argument('-o', '--offline', action='store_true', help="Print offline hosts as well (marked OFFLINE)")
ap.add_argument('-O', '--onlyoffline', action='store_true', help="Print only offline hosts")
ap.add_argument('-t', '--tags', nargs='*', help="tags to search for (any present)")
ap.add_argument('-T', '--alltags', nargs='*', help="tags to search for (all present)")
ap.add_argument('-n', '--negative', action='store_true', help="negate -t or -T (none of these tags present or these specific tags not present together")
ap.add_argument('-d', '--delimiter', help="char to separate tags in output", default=',')
ap.add_argument('-g', '--group', action="store_true", help="format for jenkins group vars")
return ap.parse_args()
def intersection(list1, list2):
'''
list1 is a list of REs; search for a full match for each RE
in each member of list2, and return the members that match
(fully)
>>> intersection(['foo', 'bar'], ['foobar', 'foobaz'])
[]
>>> intersection(['foo.*', 'bar'], ['foobar', 'foobaz'])
['foobar', 'foobaz']
>>> intersection(['.*baz', '.*bar'], ['foobar', 'foobaz'])
['foobar', 'foobaz']
'''
return [l2 for l2 in list2 if [l1 for l1 in list1 if re.fullmatch(l1, l2)]]
def one_for_one(list1, list2):
'''
Does list1 of patterns match list2 in at least one match per
pattern?
'''
for pat in list1:
count = len([l2 for l2 in list2 if re.fullmatch(pat, l2)])
if count < 1:
return False
return True
def expand_csv_to_list(l):
newl = l
if l and len(l) == 1 and ',' in l[0]:
newl = l[0].split(',')
return newl
sets_of_interest = (
("arm64", "jammy"),
("amd64", "jammy"),
("arm64", "centos9"),
("amd64", "centos9"),
)
def main():
host = os.environ.get('JENKINS_HOST', 'jenkins.ceph.com')
args = parse_args()
res = requests.get(f'https://{host}/computer/api/json')
res.raise_for_status()
nodes = res.json()
hosts = []
for host in nodes['computer']:
if host['_class'] != 'hudson.slaves.SlaveComputer':
continue
if not (args.offline or args.onlyoffline or args.group) and host['offline']:
continue
if args.onlyoffline and not host['offline']:
continue
tags = list()
for d in host['assignedLabels']:
tags.extend([v for k,v in d.items()])
tags = sorted(tags)
args.tags = expand_csv_to_list(args.tags)
args.alltags = expand_csv_to_list(args.alltags)
if not args.negative:
# skip if tags don't contain any of the requested tags
if args.tags and not intersection(args.tags, tags):
continue
# skip if tags don't contain all of the requested tags
if args.alltags:
i = intersection(args.alltags, tags)
if not one_for_one(args.alltags, i):
continue
else:
# skip if tags contain any of the requested tags
if args.tags and intersection(args.tags, tags):
continue
# skip if tags contain all of the requested tags
if args.alltags:
i = intersection(args.alltags, tags)
if one_for_one(args.alltags, i):
continue
name = host['displayName']
# don't output the IP addr
if '+' in name:
name = name[name.index('+')+1:]
offline_reason = host.get('offlineCauseReason')
hosts.append({"name": name, "offline": host['offline'], "tags": tags, "offline_reason": offline_reason})
if args.list:
print(args.delimiter.join([host['name'] for host in hosts]))
elif args.group:
for host in hosts:
name = host["name"] if '.' in host["name"] else f'{host["name"]}.front.sepia.ceph.com'
tags = host["tags"]
print(f'{name}: \"{" ".join(tags)}\"')
else:
counts = dict()
for host in hosts:
offlinestr=''
if host["offline"]:
offlinestr = 'OFFLINE'
if 'offline_reason' in host:
offlinestr += f' {host["offline_reason"]}'
print(f'{host["name"]}: {args.delimiter.join(host["tags"])} {offlinestr}')
for t in sets_of_interest:
s = set(t)
if s <= set(host["tags"]):
key = ' '.join(sorted(s))
if key in counts:
counts[key] += 1
else:
counts[key] = 1
print(counts)
if __name__ == "__main__":
sys.exit(main())