quixoten-puppetdb-terminus 3.1.1 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 616f4054f25a66e89ff21c6af1a5d2777210c25a
|
4
|
+
data.tar.gz: 35b9513e9f12f34bd6bee4fb02f5d29fc8aec0c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52e43ec18885c215f8bd500a4682591aa57301c21d3ff2ca1313bb672f73f3441cd202abd1db0ac287e19f7d00918b6a046f14517fadc07eb0fdedf434c4d916
|
7
|
+
data.tar.gz: 6998777cc272a6cd011f96805f4dccd0d831ae2df3cd49967e420dc6aa8f27ab98b3a98dbcaee3b66d3c71c68610692d185d9ee5440d9d8ca7bd093fa303ab16
|
@@ -10,7 +10,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
|
|
10
10
|
def save(request)
|
11
11
|
profile("catalog#save", [:puppetdb, :catalog, :save, request.key]) do
|
12
12
|
catalog = munge_catalog(request.instance, extract_extra_request_data(request))
|
13
|
-
submit_command(request.key, catalog, CommandReplaceCatalog,
|
13
|
+
submit_command(request.key, catalog, CommandReplaceCatalog, 7)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -24,6 +24,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
|
|
24
24
|
:transaction_uuid => request.options[:transaction_uuid],
|
25
25
|
:environment => request.environment.to_s,
|
26
26
|
:producer_timestamp => request.options[:producer_timestamp] || Time.now.iso8601(5),
|
27
|
+
:code_id => request.options[:code_id],
|
27
28
|
}
|
28
29
|
end
|
29
30
|
|
@@ -51,6 +52,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
|
|
51
52
|
add_environment(data, extra_request_data[:environment])
|
52
53
|
add_producer_timestamp(data, extra_request_data[:producer_timestamp])
|
53
54
|
change_name_to_certname(data)
|
55
|
+
add_code_id(data, extra_request_data[:code_id])
|
54
56
|
|
55
57
|
data
|
56
58
|
end
|
@@ -114,6 +116,18 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
|
|
114
116
|
hash
|
115
117
|
end
|
116
118
|
|
119
|
+
# Include code_id in hash, returning the complete hash.
|
120
|
+
#
|
121
|
+
# @param hash [Hash] original data hash
|
122
|
+
# @param code_id [String] code_id
|
123
|
+
# @return [Hash] returns original hash augmented with transaction_uuid
|
124
|
+
# @api private
|
125
|
+
def add_code_id(hash, code_id)
|
126
|
+
hash['code_id'] = code_id
|
127
|
+
|
128
|
+
hash
|
129
|
+
end
|
130
|
+
|
117
131
|
# Version is an integer (time since epoch in millis). The wire
|
118
132
|
# format specifies version should be a string
|
119
133
|
#
|
@@ -200,7 +214,7 @@ class Puppet::Resource::Catalog::Puppetdb < Puppet::Indirector::REST
|
|
200
214
|
params = resource['parameters']
|
201
215
|
UnorderedMetaparams.each do |metaparam|
|
202
216
|
if params[metaparam].kind_of? Array then
|
203
|
-
values = params[metaparam].
|
217
|
+
values = params[metaparam].sort_by {|x| x.to_s}
|
204
218
|
params[metaparam] = values unless values.empty?
|
205
219
|
end
|
206
220
|
end
|
@@ -31,37 +31,141 @@ module CharEncoding
|
|
31
31
|
|
32
32
|
Utf8ReplacementChar = [ 0xEF, 0xBF, 0xBD ].pack("c*")
|
33
33
|
|
34
|
+
DEFAULT_INVALID_CHAR = "\ufffd"
|
34
35
|
|
35
|
-
|
36
|
+
# @api private
|
37
|
+
def self.all_indexes_of_char(str, char)
|
38
|
+
(0..str.length).find_all{ |i| str[i] == char}
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
#
|
43
|
+
# Takes an array and returns a sub-array without the last element
|
44
|
+
#
|
45
|
+
# @return [Object]
|
46
|
+
def self.drop_last(array)
|
47
|
+
array[0..-2]
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
# Takes an array of increasing integers and collapses the sequential
|
53
|
+
# integers into ranges
|
54
|
+
#
|
55
|
+
# @param index_array an array of sorted integers
|
56
|
+
# @return [Range]
|
57
|
+
def self.collapse_ranges(index_array)
|
58
|
+
ranges = index_array.each.inject([]) do |spans, n|
|
59
|
+
if spans.empty? || spans.last.end != n - 1
|
60
|
+
spans << Range.new(n, n)
|
61
|
+
else
|
62
|
+
drop_last(spans) << Range.new(spans.last.begin,n)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @api private
|
68
|
+
#
|
69
|
+
# Scans the string s with bad characters found at bad_char_indexes
|
70
|
+
# and returns an array of messages that give some context around the
|
71
|
+
# bad characters. This will give up to 100 characters prior to the
|
72
|
+
# bad character and 100 after. It will return fewer if it's at the
|
73
|
+
# beginning of a string or if another bad character appears before
|
74
|
+
# reaching the 100 characters
|
75
|
+
#
|
76
|
+
# @param str string coming from to_pson, likely a command to be submitted to PDB
|
77
|
+
# @param bad_char_indexes an array of indexes into the string where invalid characters were found
|
78
|
+
# @return [String]
|
79
|
+
def self.error_char_context(str, bad_char_indexes)
|
80
|
+
bad_char_ranges = collapse_ranges(bad_char_indexes)
|
81
|
+
bad_char_ranges.each_with_index.inject([]) do |state, (r, index)|
|
82
|
+
gap = r.to_a.length
|
83
|
+
|
84
|
+
prev_bad_char_end = bad_char_ranges[index-1].end + 1 if index > 0
|
85
|
+
next_bad_char_begin = bad_char_ranges[index+1].begin - 1 if index < bad_char_ranges.length - 1
|
86
|
+
|
87
|
+
start_char = [prev_bad_char_end || 0, r.begin-100].max
|
88
|
+
end_char = [next_bad_char_begin || str.length - 1, r.end+100].min
|
89
|
+
x = [next_bad_char_begin || str.length, r.end+100, str.length]
|
90
|
+
prefix = str[start_char..r.begin-1]
|
91
|
+
suffix = str[r.end+1..end_char]
|
92
|
+
|
93
|
+
state << "'#{prefix}' followed by #{gap} invalid/undefined bytes then '#{suffix}'"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api private
|
98
|
+
#
|
99
|
+
# Warns the user if an invalid character was found. If debugging is
|
100
|
+
# enabled will also log contextual information about where the bad
|
101
|
+
# character(s) were found
|
102
|
+
#
|
103
|
+
# @param str A string coming from to_pson, likely a command to be submitted to PDB
|
104
|
+
# @param error_context_str information about where this string came from for use in error messages
|
105
|
+
# @return String
|
106
|
+
def self.warn_if_invalid_chars(str, error_context_str)
|
107
|
+
bad_char_indexes = all_indexes_of_char(str, DEFAULT_INVALID_CHAR)
|
108
|
+
if bad_char_indexes.empty?
|
109
|
+
str
|
110
|
+
else
|
111
|
+
Puppet.warning "#{error_context_str} ignoring invalid UTF-8 byte sequences in data to be sent to PuppetDB, see debug logging for more info"
|
112
|
+
if Puppet.settings[:log_level] == "debug"
|
113
|
+
Puppet.debug error_context_str + "\n" + error_char_context(str, bad_char_indexes).join("\n")
|
114
|
+
end
|
115
|
+
|
116
|
+
str
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# @api private
|
121
|
+
#
|
122
|
+
# Attempts to coerce str to UTF-8, if that fails will output context
|
123
|
+
# information using error_context_str
|
124
|
+
#
|
125
|
+
# @param str A string coming from to_pson, likely a command to be submitted to PDB
|
126
|
+
# @param error_context_str information about where this string came from for use in error messages
|
127
|
+
# @return Str
|
128
|
+
def self.coerce_to_utf8(str, error_context_str)
|
129
|
+
str_copy = str.dup
|
130
|
+
# This code is passed in a string that was created by
|
131
|
+
# to_pson. to_pson calls force_encoding('ASCII-8BIT') on the
|
132
|
+
# string before it returns it. This leaves the actual UTF-8 bytes
|
133
|
+
# alone. Below we check to see if this is the case (this should be
|
134
|
+
# most common). In this case, the bytes are still UTF-8 and we can
|
135
|
+
# just encode! and we're good to go. If They are not valid UTF-8
|
136
|
+
# bytes, that means there is probably some binary data mixed in
|
137
|
+
# the middle of the UTF-8 string. In this case we need to output a
|
138
|
+
# warning and give the user more information
|
139
|
+
str_copy.force_encoding("UTF-8")
|
140
|
+
if str_copy.valid_encoding?
|
141
|
+
str_copy.encode!("UTF-8")
|
142
|
+
else
|
143
|
+
# This is force_encoded as US-ASCII to avoid any overlapping
|
144
|
+
# byte related issues that could arise from mis-interpreting a
|
145
|
+
# random extra byte as part of a multi-byte UTF-8 character
|
146
|
+
str_copy.force_encoding("US-ASCII")
|
147
|
+
warn_if_invalid_chars(str_copy.encode!("UTF-8",
|
148
|
+
:invalid => :replace,
|
149
|
+
:undef => :replace,
|
150
|
+
:replace => DEFAULT_INVALID_CHAR),
|
151
|
+
error_context_str)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.utf8_string(str, error_context_str)
|
36
156
|
if RUBY_VERSION =~ /^1.8/
|
37
157
|
# Ruby 1.8 doesn't have String#encode and related methods, and there
|
38
158
|
# appears to be a bug in iconv that will interpret some byte sequences
|
39
159
|
# as 6-byte characters. Thus, we are forced to resort to some unfortunate
|
40
160
|
# manual chicanery.
|
41
161
|
warn_if_changed(str, ruby18_clean_utf8(str))
|
42
|
-
elsif str.encoding == Encoding::UTF_8
|
43
|
-
# If we get here, we're in ruby 1.9+, so we have the string encoding methods
|
44
|
-
# available. However, just because a ruby String object is already
|
45
|
-
# marked as UTF-8, that doesn't guarantee that its contents are actually
|
46
|
-
# valid; and if you call ruby's ".encode" method with an encoding of
|
47
|
-
# "utf-8" for a String that ruby already believes is UTF-8, ruby
|
48
|
-
# seems to optimize that to be a no-op. So, we have to do some more
|
49
|
-
# complex handling...
|
50
|
-
|
51
|
-
# If the string already has valid encoding then we're fine.
|
52
|
-
return str if str.valid_encoding?
|
53
|
-
|
54
|
-
# If not, we basically have to walk over the characters and replace
|
55
|
-
# them by hand.
|
56
|
-
warn_if_changed(str, str.each_char.map { |c| c.valid_encoding? ? c : "\ufffd"}.join)
|
57
162
|
else
|
58
|
-
# if we get here, we're ruby 1.9 and the current string is *not* encoded
|
59
|
-
# as UTF-8. Thus we can actually rely on ruby's "encode" method.
|
60
163
|
begin
|
61
|
-
str
|
164
|
+
coerce_to_utf8(str, error_context_str)
|
62
165
|
rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError => e
|
63
|
-
|
64
|
-
|
166
|
+
# If we got an exception, the string is either invalid or not
|
167
|
+
# convertible to UTF-8, so drop those bytes.
|
168
|
+
|
65
169
|
warn_if_changed(str, str.encode('UTF-8', :invalid => :replace, :undef => :replace))
|
66
170
|
end
|
67
171
|
end
|
@@ -42,7 +42,7 @@ class Puppet::Util::Puppetdb::Command
|
|
42
42
|
#
|
43
43
|
# This is roughly inline with how Puppet serializes for catalogs as of
|
44
44
|
# Puppet 4.1.0. We need a better answer to non-utf8 data end-to-end.
|
45
|
-
}.to_pson)
|
45
|
+
}.to_pson, "Error encoding a '#{command}' command for host '#{certname}'")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|