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

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

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

# 

# This file is part of Ansible 

# 

# Ansible is free software: you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# Ansible is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the GNU General Public License 

# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 

 

# Make coding more python3-ish 

from __future__ import (absolute_import, division, print_function) 

__metaclass__ = type 

 

import ast 

import random 

import uuid 

 

from collections import MutableMapping 

from json import dumps 

 

 

from ansible import constants as C 

from ansible.errors import AnsibleError, AnsibleOptionsError 

from ansible.module_utils.six import iteritems, string_types 

from ansible.module_utils._text import to_native, to_text 

from ansible.parsing.splitter import parse_kv 

 

 

_MAXSIZE = 2 ** 32 

cur_id = 0 

node_mac = ("%012x" % uuid.getnode())[:12] 

random_int = ("%08x" % random.randint(0, _MAXSIZE))[:8] 

 

 

def get_unique_id(): 

global cur_id 

cur_id += 1 

return "-".join([ 

node_mac[0:8], 

node_mac[8:12], 

random_int[0:4], 

random_int[4:8], 

("%012x" % cur_id)[:12], 

]) 

 

 

def _validate_mutable_mappings(a, b): 

""" 

Internal convenience function to ensure arguments are MutableMappings 

 

This checks that all arguments are MutableMappings or raises an error 

 

:raises AnsibleError: if one of the arguments is not a MutableMapping 

""" 

 

# If this becomes generally needed, change the signature to operate on 

# a variable number of arguments instead. 

 

67 ↛ 68line 67 didn't jump to line 68, because the condition on line 67 was never true if not (isinstance(a, MutableMapping) and isinstance(b, MutableMapping)): 

myvars = [] 

for x in [a, b]: 

try: 

myvars.append(dumps(x)) 

except: 

myvars.append(to_native(x)) 

raise AnsibleError("failed to combine variables, expected dicts but got a '{0}' and a '{1}': \n{2}\n{3}".format( 

a.__class__.__name__, b.__class__.__name__, myvars[0], myvars[1]) 

) 

 

 

def combine_vars(a, b): 

""" 

Return a copy of dictionaries of variables based on configured hash behavior 

""" 

 

84 ↛ 85line 84 didn't jump to line 85, because the condition on line 84 was never true if C.DEFAULT_HASH_BEHAVIOUR == "merge": 

return merge_hash(a, b) 

else: 

# HASH_BEHAVIOUR == 'replace' 

_validate_mutable_mappings(a, b) 

result = a.copy() 

result.update(b) 

return result 

 

 

def merge_hash(a, b): 

""" 

Recursively merges hash b into a so that keys from b take precedence over keys from a 

""" 

 

_validate_mutable_mappings(a, b) 

 

# if a is empty or equal to b, return b 

102 ↛ 106line 102 didn't jump to line 106, because the condition on line 102 was never false if a == {} or a == b: 

return b.copy() 

 

# if b is empty the below unfolds quickly 

result = a.copy() 

 

# next, iterate over b keys and values 

for k, v in iteritems(b): 

# if there's already such key in a 

# and that key contains a MutableMapping 

if k in result and isinstance(result[k], MutableMapping) and isinstance(v, MutableMapping): 

# merge those dicts recursively 

result[k] = merge_hash(result[k], v) 

else: 

# otherwise, just copy the value from b to a 

result[k] = v 

 

return result 

 

 

def load_extra_vars(loader, options): 

extra_vars = {} 

124 ↛ 143line 124 didn't jump to line 143, because the condition on line 124 was never false if hasattr(options, 'extra_vars'): 

for extra_vars_opt in options.extra_vars: 

data = None 

extra_vars_opt = to_text(extra_vars_opt, errors='surrogate_or_strict') 

if extra_vars_opt.startswith(u"@"): 

# Argument is a YAML file (JSON is a subset of YAML) 

data = loader.load_from_file(extra_vars_opt[1:]) 

131 ↛ 133line 131 didn't jump to line 133, because the condition on line 131 was never true elif extra_vars_opt and extra_vars_opt[0] in u'[{': 

# Arguments as YAML 

data = loader.load(extra_vars_opt) 

else: 

# Arguments as Key-value 

data = parse_kv(extra_vars_opt) 

 

138 ↛ 141line 138 didn't jump to line 141, because the condition on line 138 was never false if isinstance(data, MutableMapping): 

extra_vars = combine_vars(extra_vars, data) 

else: 

raise AnsibleOptionsError("Invalid extra vars data supplied. '%s' could not be made into a dictionary" % extra_vars_opt) 

 

return extra_vars 

 

 

def load_options_vars(options, version): 

 

options_vars = {'ansible_version': version} 

aliases = {'check': 'check_mode', 

'diff': 'diff_mode', 

'inventory': 'inventory_sources', 

'subset': 'limit', 

'tags': 'run_tags'} 

 

for attr in ('check', 'diff', 'forks', 'inventory', 'skip_tags', 'subset', 'tags'): 

opt = getattr(options, attr, None) 

if opt is not None: 

options_vars['ansible_%s' % aliases.get(attr, attr)] = opt 

 

return options_vars 

 

 

def isidentifier(ident): 

""" 

Determines, if string is valid Python identifier using the ast module. 

Originally posted at: http://stackoverflow.com/a/29586366 

""" 

 

169 ↛ 170line 169 didn't jump to line 170, because the condition on line 169 was never true if not isinstance(ident, string_types): 

return False 

 

try: 

root = ast.parse(ident) 

except SyntaxError: 

return False 

 

177 ↛ 178line 177 didn't jump to line 178, because the condition on line 177 was never true if not isinstance(root, ast.Module): 

return False 

 

180 ↛ 181line 180 didn't jump to line 181, because the condition on line 180 was never true if len(root.body) != 1: 

return False 

 

183 ↛ 184line 183 didn't jump to line 184, because the condition on line 183 was never true if not isinstance(root.body[0], ast.Expr): 

return False 

 

186 ↛ 187line 186 didn't jump to line 187, because the condition on line 186 was never true if not isinstance(root.body[0].value, ast.Name): 

return False 

 

189 ↛ 190line 189 didn't jump to line 190, because the condition on line 189 was never true if root.body[0].value.id != ident: 

return False 

 

return True