Newer
Older

Andreas Hamacher
committed
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
import pandas as pd
import zipfile
import json
import os,sys,yaml
def task_result(task):
# 0 is skipped (Because of a conditional"
# 1 is not changed (everything should be 1)
# 2 is changed (you should run ansible playbook to fix the cluster)
# 3 is skipped due to check mode (you should not write a role like this)
# 4 is failed. You've got somethign to fix.
if "skipped" in task and task["skipped"] is True:
if "skipped_reason" in task and task["skipped_reason"] == "Conditional result was False":
return 0
if "msg" in task and task["msg"] == "skipped, running in check mode":
return 3
if "failed" in task and task["failed"]:
return 4
if "changed" in task:
if task["changed"]:
return 2
else:
return 1
def change_value(change):
if change == False:
return 1
if change == True:
return 2
return 0
def change_str(change):
if change == 0:
return "N/A"
if change == 1:
return "False"
if change == 2:
return "True"
if change == 3:
return "Skipped in check mode"
if change == 4:
return "Failed"
def get_changes(data):
for play in data['plays']:
for task in play['tasks']:
for host,hosttask in task['hosts'].items():
#yield {'task':task['task']['name'],'host':host,'change':change_value(hosttask['changed']),'changestr':hosttask['changed'],'taskid':task['task']['id']}
yield {'task':task['task']['name'],'host':host,'change':task_result(hosttask),'changestr':change_str(task_result(hosttask)),'taskid':task['task']['id']}
#def change_value(change):
# if change == False:
# return 1
# if change == True:
# return 2
# return 0
#
#def change_str(change):
# if change == 0:
# return "N/A"
# if change == 1:
# return "False"
# if change == 2:
# return "True"
#
#def get_changes(data):
# for play in data['plays']:
# for task in play['tasks']:
# for host,hosttask in task['hosts'].items():
# yield {'task':task['task']['name'],'host':host,'change':change_value(hosttask['changed']),'changestr':hosttask['changed'],'taskid':task['task']['id']}
def load_data(artifactfile="artifacts.zip", nodeclass="compute_ansible_check.log"):
#with zipfile.ZipFile(artifactfile,'r') as zipf:
# data = json.loads(zipf.read(nodeclass))
with open(nodeclass) as f:
data = json.loads(f.read())
# Create my dataframe from a list of dictionaries
df = pd.DataFrame(list(get_changes(data)))
# Extract a mapping from the taskid to the task name
taskmap = df[['task','taskid']].copy().drop_duplicates().set_index('taskid')
# reindex the list of values, so that each change even can be referecned by a unique combination of host and taskid
midx = pd.MultiIndex.from_frame((df[['host','taskid']]))
df = df.set_index(midx);
# Assume that ever host executes every task. Use fillna to fill in task which hosts don't execute
#print(df)
#print(df.unstack('taskid'))
df.fillna(0)
#df=df.unstack('taskid').fillna(0).stack()
# Since our dataframe is now bigger (has those pesky NaNs filled in with zeros) create a new list of hosts and tasks.
hosts = df.index.get_level_values(0)
df['host']=hosts
tasks = list(map(lambda x: taskmap.loc[x]['task'],df.index.get_level_values(1)))
df['task'] = tasks
changestr = list(map(lambda x: change_str(x), df['change']))
df['changestr'] = changestr
df['taskid'] = df.index.get_level_values(1)
return df
import logging
from slack_logger import SlackHandler, SlackFormatter
slack_hook = os.environ['SLACK_HOOK']
logger = logging.getLogger()
logger.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
sh = SlackHandler(username='m3-ansible-check', icon_emoji=':robot_face:', url=slack_hook)
sh.setLevel(logging.DEBUG)
logger.addHandler(sh)
df = load_data(nodeclass="compute_ansible_check.log")
if (len(sys.argv)>1 and sys.argv[1]=='outputChangedNodeList'):
print(yaml.dump(list(df[df.change == 2].host.unique())))
sys.exit(0)
nodes = len(df.host.unique())
changed = len(df[df.change == 2].host.unique())
failed = len(df[df.change == 4].host.unique())
logger.info("{} Compute nodes, {} had at least one change {} had at least one failed task".format(nodes,changed,failed))
df = load_data(nodeclass="login_ansible_check.log")
nodes = len(df.host.unique())
changed = len(df[df.change == 2].host.unique())
failed = len(df[df.change == 4].host.unique())
logger.info("{} Login nodes, {} had at least one change {} had at least one failed task".format(nodes,changed,failed))
df = load_data(nodeclass="mgmt_ansible_check.log")
nodes = len(df.host.unique())
changed = len(df[df.change == 2].host.unique())
failed = len(df[df.change == 4].host.unique())
logger.info("{} Management nodes, {} had at least one change {} had at least one failed task".format(nodes,changed,failed))