quixoten-puppetdb-terminus 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5638341ba0d3ae5fe31ed83d385ef11f3ea7368
4
- data.tar.gz: a84380223cf2cd971a11376e54f98bbc4815e363
3
+ metadata.gz: 616f4054f25a66e89ff21c6af1a5d2777210c25a
4
+ data.tar.gz: 35b9513e9f12f34bd6bee4fb02f5d29fc8aec0c1
5
5
  SHA512:
6
- metadata.gz: 39986de0b1ce9704f30eb68f83e8a2d017f185eebe091e0c793ac7b1ce86ea364968eb2eddec46d572a5f8f44816d974d3fa0eac5c93ea4c500cd0a401977c54
7
- data.tar.gz: c24beffee4862e5587357f5a3f5f602c97752e4e196895265be3e04408a9753d1461a91b76622abdf5b586feb170db9b6e6e4b04e45aabc033bba795727dcba3
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, 6)
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].sort
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
- def self.utf8_string(str)
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.encode('UTF-8')
164
+ coerce_to_utf8(str, error_context_str)
62
165
  rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError => e
63
- # If we got an exception, the string is either invalid or not
64
- # convertible to UTF-8, so drop those bytes.
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
 
@@ -1,6 +1,6 @@
1
1
  module PuppetDB
2
2
  module Terminus
3
- VERSION = "3.1.1"
3
+ VERSION = "3.2.0"
4
4
  UPSTREAM_VERSION = VERSION.split(".")[0..2].join(".")
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quixoten-puppetdb-terminus
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devin Christensen