Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

# Copyright: (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> 

 

# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 

 

from __future__ import (absolute_import, division, print_function) 

__metaclass__ = type 

 

from copy import deepcopy 

 

from ansible.parsing.dataloader import DataLoader 

from ansible.vars.clean import strip_internal_keys 

 

_IGNORE = ('failed', 'skipped') 

_PRESERVE = ('attempts', 'changed', 'retries') 

 

 

class TaskResult: 

''' 

This class is responsible for interpreting the resulting data 

from an executed task, and provides helper methods for determining 

the result of a given task. 

''' 

 

def __init__(self, host, task, return_data, task_fields=None): 

self._host = host 

self._task = task 

 

28 ↛ 31line 28 didn't jump to line 31, because the condition on line 28 was never false if isinstance(return_data, dict): 

self._result = return_data.copy() 

else: 

self._result = DataLoader().load(return_data) 

 

if task_fields is None: 

self._task_fields = dict() 

else: 

self._task_fields = task_fields 

 

@property 

def task_name(self): 

return self._task_fields.get('name', None) or self._task.get_name() 

 

def is_changed(self): 

return self._check_key('changed') 

 

def is_skipped(self): 

# loop results 

if 'results' in self._result: 

results = self._result['results'] 

# Loop tasks are only considered skipped if all items were skipped. 

# some squashed results (eg, yum) are not dicts and can't be skipped individually 

51 ↛ exit,   51 ↛ 522 missed branches: 1) line 51 didn't finish the generator expression on line 51, 2) line 51 didn't jump to line 52, because the condition on line 51 was never true if results and all(isinstance(res, dict) and res.get('skipped', False) for res in results): 

return True 

 

# regular tasks and squashed non-dict results 

return self._result.get('skipped', False) 

 

def is_failed(self): 

58 ↛ 60line 58 didn't jump to line 60, because the condition on line 58 was never true if 'failed_when_result' in self._result or \ 

'results' in self._result and True in [True for x in self._result['results'] if 'failed_when_result' in x]: 

return self._check_key('failed_when_result') 

else: 

return self._check_key('failed') 

 

def is_unreachable(self): 

return self._check_key('unreachable') 

 

def needs_debugger(self, globally_enabled=False): 

_debugger = self._task_fields.get('debugger') 

 

ret = False 

71 ↛ 72line 71 didn't jump to line 72, because the condition on line 71 was never true if globally_enabled and (self.is_failed() or self.is_unreachable()): 

ret = True 

 

74 ↛ 75line 74 didn't jump to line 75, because the condition on line 74 was never true if _debugger in ('always',): 

ret = True 

76 ↛ 77line 76 didn't jump to line 77, because the condition on line 76 was never true elif _debugger in ('never',): 

ret = False 

78 ↛ 79line 78 didn't jump to line 79, because the condition on line 78 was never true elif _debugger in ('on_failed',) and self.is_failed(): 

ret = True 

80 ↛ 81line 80 didn't jump to line 81, because the condition on line 80 was never true elif _debugger in ('on_unreachable',) and self.is_unreachable(): 

ret = True 

82 ↛ 83line 82 didn't jump to line 83, because the condition on line 82 was never true elif _debugger in('on_skipped',) and self.is_skipped(): 

ret = True 

 

return ret 

 

def _check_key(self, key): 

'''get a specific key from the result or its items''' 

 

if isinstance(self._result, dict) and key in self._result: 

return self._result.get(key, False) 

else: 

flag = False 

for res in self._result.get('results', []): 

95 ↛ 94line 95 didn't jump to line 94, because the condition on line 95 was never false if isinstance(res, dict): 

flag |= res.get(key, False) 

return flag 

 

def clean_copy(self): 

 

''' returns 'clean' taskresult object ''' 

 

# FIXME: clean task_fields, _task and _host copies 

result = TaskResult(self._host, self._task, {}, self._task_fields) 

 

# statuses are already reflected on the event type 

if result._task and result._task.action in ['debug']: 

# debug is verbose by default to display vars, no need to add invocation 

ignore = _IGNORE + ('invocation',) 

else: 

ignore = _IGNORE 

 

113 ↛ 114line 113 didn't jump to line 114, because the condition on line 113 was never true if self._result.get('_ansible_no_log', False): 

x = {"censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result"} 

for preserve in _PRESERVE: 

if preserve in self._result: 

x[preserve] = self._result[preserve] 

result._result = x 

119 ↛ 130line 119 didn't jump to line 130, because the condition on line 119 was never false elif self._result: 

result._result = deepcopy(self._result) 

 

# actualy remove 

for remove_key in ignore: 

if remove_key in result._result: 

del result._result[remove_key] 

 

# remove almost ALL internal keys, keep ones relevant to callback 

strip_internal_keys(result._result, exceptions=('_ansible_verbose_always', '_ansible_item_label', '_ansible_no_log')) 

 

return result