puppet 3.2.1 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (78) hide show
  1. data/install.rb +1 -1
  2. data/lib/puppet.rb +11 -0
  3. data/lib/puppet/indirector/report/processor.rb +1 -1
  4. data/lib/puppet/indirector/report/rest.rb +7 -0
  5. data/lib/puppet/indirector/resource/rest.rb +8 -0
  6. data/lib/puppet/indirector/rest.rb +80 -52
  7. data/lib/puppet/indirector/run/rest.rb +6 -0
  8. data/lib/puppet/network/formats.rb +20 -10
  9. data/lib/puppet/network/http/handler.rb +1 -1
  10. data/lib/puppet/node.rb +1 -1
  11. data/lib/puppet/node/facts.rb +23 -4
  12. data/lib/puppet/resource.rb +2 -4
  13. data/lib/puppet/resource/status.rb +28 -0
  14. data/lib/puppet/run.rb +24 -2
  15. data/lib/puppet/status.rb +6 -2
  16. data/lib/puppet/transaction/event.rb +19 -0
  17. data/lib/puppet/transaction/report.rb +40 -0
  18. data/lib/puppet/util/log.rb +19 -0
  19. data/lib/puppet/util/metric.rb +6 -0
  20. data/lib/puppet/util/monkey_patches.rb +0 -15
  21. data/lib/puppet/vendor.rb +55 -0
  22. data/lib/puppet/vendor/load_safe_yaml.rb +1 -0
  23. data/lib/puppet/vendor/require_vendored.rb +5 -0
  24. data/lib/puppet/vendor/safe_yaml/CHANGES.md +104 -0
  25. data/lib/puppet/vendor/safe_yaml/Gemfile +11 -0
  26. data/lib/puppet/vendor/safe_yaml/LICENSE.txt +22 -0
  27. data/lib/puppet/vendor/safe_yaml/README.md +179 -0
  28. data/lib/puppet/vendor/safe_yaml/Rakefile +6 -0
  29. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml.rb +253 -0
  30. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/deep.rb +34 -0
  31. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/date.rb +27 -0
  32. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/hexadecimal.rb +12 -0
  33. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/parse/sexagesimal.rb +26 -0
  34. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_handler.rb +92 -0
  35. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/psych_resolver.rb +52 -0
  36. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/resolver.rb +94 -0
  37. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/safe_to_ruby_visitor.rb +17 -0
  38. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_hack.rb +36 -0
  39. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_node_monkeypatch.rb +43 -0
  40. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/syck_resolver.rb +38 -0
  41. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform.rb +41 -0
  42. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_boolean.rb +21 -0
  43. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_date.rb +11 -0
  44. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_float.rb +33 -0
  45. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_integer.rb +25 -0
  46. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_nil.rb +18 -0
  47. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/to_symbol.rb +13 -0
  48. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/transform/transformation_map.rb +47 -0
  49. data/lib/puppet/vendor/safe_yaml/lib/safe_yaml/version.rb +3 -0
  50. data/lib/puppet/vendor/safe_yaml/run_specs_all_ruby_versions.sh +21 -0
  51. data/lib/puppet/vendor/safe_yaml/safe_yaml.gemspec +18 -0
  52. data/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.2.yaml +2 -0
  53. data/lib/puppet/vendor/safe_yaml/spec/exploit.1.9.3.yaml +2 -0
  54. data/lib/puppet/vendor/safe_yaml/spec/psych_resolver_spec.rb +10 -0
  55. data/lib/puppet/vendor/safe_yaml/spec/resolver_specs.rb +250 -0
  56. data/lib/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb +702 -0
  57. data/lib/puppet/vendor/safe_yaml/spec/spec_helper.rb +18 -0
  58. data/lib/puppet/vendor/safe_yaml/spec/support/exploitable_back_door.rb +29 -0
  59. data/lib/puppet/vendor/safe_yaml/spec/syck_resolver_spec.rb +10 -0
  60. data/lib/puppet/vendor/safe_yaml/spec/transform/base64_spec.rb +11 -0
  61. data/lib/puppet/vendor/safe_yaml/spec/transform/to_date_spec.rb +34 -0
  62. data/lib/puppet/vendor/safe_yaml/spec/transform/to_float_spec.rb +42 -0
  63. data/lib/puppet/vendor/safe_yaml/spec/transform/to_integer_spec.rb +59 -0
  64. data/lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb +49 -0
  65. data/lib/puppet/vendor/safe_yaml_patches.rb +9 -0
  66. data/lib/puppet/version.rb +1 -1
  67. data/spec/lib/puppet_spec/matchers.rb +8 -0
  68. data/spec/unit/application/facts_spec.rb +1 -0
  69. data/spec/unit/file_serving/metadata_spec.rb +20 -28
  70. data/spec/unit/indirector/report/rest_spec.rb +41 -0
  71. data/spec/unit/indirector/rest_spec.rb +307 -334
  72. data/spec/unit/network/formats_spec.rb +36 -27
  73. data/spec/unit/network/http/handler_spec.rb +3 -12
  74. data/spec/unit/node_spec.rb +14 -0
  75. data/spec/unit/resource_spec.rb +5 -35
  76. data/spec/unit/run_spec.rb +25 -6
  77. data/spec/unit/status_spec.rb +6 -0
  78. metadata +2566 -2521
data/install.rb CHANGED
@@ -107,7 +107,7 @@ end
107
107
 
108
108
  def do_libs(libs, strip = 'lib/')
109
109
  libs.each do |lf|
110
- olf = File.join(InstallOptions.site_dir, lf.gsub(/#{strip}/, ''))
110
+ olf = File.join(InstallOptions.site_dir, lf.sub(/^#{strip}/, ''))
111
111
  op = File.dirname(olf)
112
112
  if $haveftools
113
113
  File.makedirs(op, true)
data/lib/puppet.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'puppet/version'
2
2
 
3
3
  # see the bottom of the file for further inclusions
4
+ # Also see the new Vendor support - towards the end
5
+ #
4
6
  require 'facter'
5
7
  require 'puppet/error'
6
8
  require 'puppet/util'
@@ -153,6 +155,15 @@ module Puppet
153
155
  def self.newtype(name, options = {}, &block)
154
156
  Puppet::Type.newtype(name, options, &block)
155
157
  end
158
+
159
+ # Load vendored (setup paths, and load what is needed upfront).
160
+ # See the Vendor class for how to add additional vendored gems/code
161
+ require "puppet/vendor"
162
+ Puppet::Vendor.load_vendored
163
+
164
+ # Set default for YAML.load to unsafe so we don't affect programs
165
+ # requiring puppet -- in puppet we will call safe explicitly
166
+ SafeYAML::OPTIONS[:default_mode] = :unsafe
156
167
  end
157
168
 
158
169
  # This feels weird to me; I would really like for us to get to a state where there is never a "require" statement
@@ -48,7 +48,7 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
48
48
  end
49
49
 
50
50
  def processors(&blk)
51
- return if Puppet[:reports] == "none"
51
+ return [] if Puppet[:reports] == "none"
52
52
  reports.each do |name|
53
53
  if mod = Puppet::Reports.report(name)
54
54
  yield(mod)
@@ -5,4 +5,11 @@ class Puppet::Transaction::Report::Rest < Puppet::Indirector::REST
5
5
  use_server_setting(:report_server)
6
6
  use_port_setting(:report_port)
7
7
  use_srv_service(:report)
8
+
9
+ private
10
+
11
+ def deserialize_save(content_type, body)
12
+ format = Puppet::Network::FormatHandler.protected_format(content_type)
13
+ format.intern(Array, body)
14
+ end
8
15
  end
@@ -5,4 +5,12 @@ class Puppet::Resource::Rest < Puppet::Indirector::REST
5
5
 
6
6
  desc "Maniuplate resources remotely? Undocumented."
7
7
 
8
+ private
9
+
10
+ def deserialize_save(content_type, body)
11
+ # Body is [ral_res.to_resource, transaction.report]
12
+ format = Puppet::Network::FormatHandler.protected_format(content_type)
13
+ ary = format.intern(Array, body)
14
+ [Puppet::Resource.from_pson(ary[0]), Puppet::Transaction::Report.from_pson(ary[1])]
15
+ end
8
16
  end
@@ -42,36 +42,6 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
42
42
  Puppet.settings[port_setting || :masterport].to_i
43
43
  end
44
44
 
45
- # Figure out the content type, turn that into a format, and use the format
46
- # to extract the body of the response.
47
- def deserialize(response, multiple = false)
48
- case response.code
49
- when "404"
50
- return nil
51
- when /^2/
52
- raise "No content type in http response; cannot parse" unless response['content-type']
53
-
54
- content_type = response['content-type'].gsub(/\s*;.*$/,'') # strip any appended charset
55
-
56
- body = uncompress_body(response)
57
-
58
- # Convert the response to a deserialized object.
59
- if multiple
60
- model.convert_from_multiple(content_type, body)
61
- else
62
- model.convert_from(content_type, body)
63
- end
64
- else
65
- # Raise the http error if we didn't get a 'success' of some kind.
66
- raise convert_to_http_error(response)
67
- end
68
- end
69
-
70
- def convert_to_http_error(response)
71
- message = "Error #{response.code} on SERVER: #{(response.body||'').empty? ? response.message : uncompress_body(response)}"
72
- Net::HTTPError.new(message, response)
73
- end
74
-
75
45
  # Provide appropriate headers.
76
46
  def headers
77
47
  add_accept_encoding({"Accept" => model.supported_formats.join(", ")})
@@ -126,12 +96,15 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
126
96
  http_get(request, uri_with_query_string, headers)
127
97
  end
128
98
  end
129
- result = deserialize(response)
130
99
 
131
- return nil unless result
132
-
133
- result.name = request.key if result.respond_to?(:name=)
134
- result
100
+ if is_http_200?(response)
101
+ content_type, body = parse_response(response)
102
+ result = deserialize_find(content_type, body)
103
+ result.name = request.key if result.respond_to?(:name=)
104
+ result
105
+ else
106
+ nil
107
+ end
135
108
  end
136
109
 
137
110
  def head(request)
@@ -139,39 +112,49 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
139
112
  http_head(request, indirection2uri(request), headers)
140
113
  end
141
114
 
142
- case response.code
143
- when "404"
144
- return false
145
- when /^2/
146
- return true
147
- else
148
- # Raise the http error if we didn't get a 'success' of some kind.
149
- raise convert_to_http_error(response)
150
- end
115
+ !!is_http_200?(response)
151
116
  end
152
117
 
153
118
  def search(request)
154
- result = do_request(request) do |request|
155
- deserialize(http_get(request, indirection2uri(request), headers), true)
119
+ response = do_request(request) do |request|
120
+ http_get(request, indirection2uri(request), headers)
156
121
  end
157
122
 
158
- # result from the server can be nil, but we promise to return an array...
159
- result || []
123
+ if is_http_200?(response)
124
+ content_type, body = parse_response(response)
125
+ deserialize_search(content_type, body) || []
126
+ else
127
+ []
128
+ end
160
129
  end
161
130
 
162
131
  def destroy(request)
163
132
  raise ArgumentError, "DELETE does not accept options" unless request.options.empty?
164
133
 
165
- do_request(request) do |request|
166
- return deserialize(http_delete(request, indirection2uri(request), headers))
134
+ response = do_request(request) do |request|
135
+ http_delete(request, indirection2uri(request), headers)
136
+ end
137
+
138
+ if is_http_200?(response)
139
+ content_type, body = parse_response(response)
140
+ deserialize_destroy(content_type, body)
141
+ else
142
+ nil
167
143
  end
168
144
  end
169
145
 
170
146
  def save(request)
171
147
  raise ArgumentError, "PUT does not accept options" unless request.options.empty?
172
148
 
173
- do_request(request) do |request|
174
- deserialize http_put(request, indirection2uri(request), request.instance.render, headers.merge({ "Content-Type" => request.instance.mime }))
149
+ response = do_request(request) do |request|
150
+ http_put(request, indirection2uri(request), request.instance.render, headers.merge({ "Content-Type" => request.instance.mime }))
151
+ end
152
+
153
+ if is_http_200?(response)
154
+ content_type, body = parse_response(response)
155
+ deserialize_save(content_type, body)
156
+ else
157
+ nil
175
158
  end
176
159
  end
177
160
 
@@ -191,6 +174,51 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
191
174
 
192
175
  private
193
176
 
177
+ def is_http_200?(response)
178
+ case response.code
179
+ when "404"
180
+ false
181
+ when /^2/
182
+ true
183
+ else
184
+ # Raise the http error if we didn't get a 'success' of some kind.
185
+ raise convert_to_http_error(response)
186
+ end
187
+ end
188
+
189
+ def convert_to_http_error(response)
190
+ message = "Error #{response.code} on SERVER: #{(response.body||'').empty? ? response.message : uncompress_body(response)}"
191
+ Net::HTTPError.new(message, response)
192
+ end
193
+
194
+ # Returns the content_type, stripping any appended charset, and the
195
+ # body, decompressed if necessary (content-encoding is checked inside
196
+ # uncompress_body)
197
+ def parse_response(response)
198
+ if response['content-type']
199
+ [ response['content-type'].gsub(/\s*;.*$/,''),
200
+ body = uncompress_body(response) ]
201
+ else
202
+ raise "No content type in http response; cannot parse"
203
+ end
204
+ end
205
+
206
+ def deserialize_find(content_type, body)
207
+ model.convert_from(content_type, body)
208
+ end
209
+
210
+ def deserialize_search(content_type, body)
211
+ model.convert_from_multiple(content_type, body)
212
+ end
213
+
214
+ def deserialize_destroy(content_type, body)
215
+ model.convert_from(content_type, body)
216
+ end
217
+
218
+ def deserialize_save(content_type, body)
219
+ nil
220
+ end
221
+
194
222
  def environment
195
223
  Puppet::Node::Environment.new
196
224
  end
@@ -3,4 +3,10 @@ require 'puppet/indirector/rest'
3
3
 
4
4
  class Puppet::Run::Rest < Puppet::Indirector::REST
5
5
  desc "Trigger Agent runs via REST."
6
+
7
+ private
8
+
9
+ def deserialize_save(content_type, body)
10
+ model.convert_from(content_type, body)
11
+ end
6
12
  end
@@ -3,12 +3,20 @@ require 'puppet/network/format_handler'
3
3
  Puppet::Network::FormatHandler.create_serialized_formats(:yaml) do
4
4
  # Yaml doesn't need the class name; it's serialized.
5
5
  def intern(klass, text)
6
- YAML.safely_load(text)
6
+ data = YAML.load(text, :safe => true, :deserialize_symbols => true)
7
+ return data if data.is_a?(klass)
8
+ klass.from_pson(data)
7
9
  end
8
10
 
9
11
  # Yaml doesn't need the class name; it's serialized.
10
12
  def intern_multiple(klass, text)
11
- YAML.safely_load(text)
13
+ YAML.load(text, :safe => true, :deserialize_symbols => true).collect do |data|
14
+ if data.is_a?(klass)
15
+ data
16
+ else
17
+ klass.from_pson(data)
18
+ end
19
+ end
12
20
  end
13
21
 
14
22
  def render(instance)
@@ -45,11 +53,15 @@ Puppet::Network::FormatHandler.create_serialized_formats(:b64_zlib_yaml) do
45
53
  end
46
54
 
47
55
  def intern(klass, text)
48
- decode(text)
56
+ requiring_zlib do
57
+ Puppet::Network::FormatHandler.format(:yaml).intern(klass, decode(text))
58
+ end
49
59
  end
50
60
 
51
61
  def intern_multiple(klass, text)
52
- decode(text)
62
+ requiring_zlib do
63
+ Puppet::Network::FormatHandler.format(:yaml).intern_multiple(klass, decode(text))
64
+ end
53
65
  end
54
66
 
55
67
  def render(instance)
@@ -64,15 +76,13 @@ Puppet::Network::FormatHandler.create_serialized_formats(:b64_zlib_yaml) do
64
76
  true
65
77
  end
66
78
 
67
- def encode(text)
68
- requiring_zlib do
69
- Base64.encode64(Zlib::Deflate.deflate(text, Zlib::BEST_COMPRESSION))
70
- end
79
+ def decode(data)
80
+ Zlib::Inflate.inflate(Base64.decode64(data))
71
81
  end
72
82
 
73
- def decode(yaml)
83
+ def encode(text)
74
84
  requiring_zlib do
75
- YAML.safely_load(Zlib::Inflate.inflate(Base64.decode64(yaml)))
85
+ Base64.encode64(Zlib::Deflate.deflate(text, Zlib::BEST_COMPRESSION))
76
86
  end
77
87
  end
78
88
  end
@@ -265,7 +265,7 @@ module Puppet::Network::HTTP::Handler
265
265
  next result if param == :ip
266
266
  value = CGI.unescape(value)
267
267
  if value =~ /^---/
268
- value = YAML.safely_load(value)
268
+ value = YAML.load(value, :safe => true, :deserialize_symbols => true)
269
269
  else
270
270
  value = true if value == "true"
271
271
  value = false if value == "false"
data/lib/puppet/node.rb CHANGED
@@ -22,7 +22,7 @@ class Puppet::Node
22
22
  ::PSON.register_document_type('Node',self)
23
23
 
24
24
  def self.from_pson(pson)
25
- raise ArgumentError, "No name provided in pson data" unless name = pson['name']
25
+ raise ArgumentError, "No name provided in serialized data" unless name = pson['name']
26
26
 
27
27
  node = new(name)
28
28
  node.classes = pson['classes']
@@ -37,6 +37,26 @@ class Puppet::Node::Facts
37
37
  add_timestamp
38
38
  end
39
39
 
40
+ def initialize_from_hash(data)
41
+ @name = data['name']
42
+ @values = data['values']
43
+ # Timestamp will be here in YAML
44
+ timestamp = data['values']['_timestamp']
45
+ @values.delete_if do |key, val|
46
+ key =~ /^_/
47
+ end
48
+
49
+ #Timestamp will be here in pson
50
+ timestamp ||= data['timestamp']
51
+ timestamp = Time.parse(timestamp) if timestamp.is_a? String
52
+ self.timestamp = timestamp
53
+
54
+ self.expiration = data['expiration']
55
+ if expiration.is_a? String
56
+ self.expiration = Time.parse(expiration)
57
+ end
58
+ end
59
+
40
60
  # Convert all fact values into strings.
41
61
  def stringify
42
62
  values.each do |fact, value|
@@ -50,10 +70,9 @@ class Puppet::Node::Facts
50
70
  end
51
71
 
52
72
  def self.from_pson(data)
53
- result = new(data['name'], data['values'])
54
- result.timestamp = Time.parse(data['timestamp']) if data['timestamp']
55
- result.expiration = Time.parse(data['expiration']) if data['expiration']
56
- result
73
+ new_facts = allocate
74
+ new_facts.initialize_from_hash(data)
75
+ new_facts
57
76
  end
58
77
 
59
78
  def to_pson(*args)
@@ -28,8 +28,8 @@ class Puppet::Resource
28
28
  ATTRIBUTES = [:file, :line, :exported]
29
29
 
30
30
  def self.from_pson(pson)
31
- raise ArgumentError, "No resource type provided in pson data" unless type = pson['type']
32
- raise ArgumentError, "No resource title provided in pson data" unless title = pson['title']
31
+ raise ArgumentError, "No resource type provided in serialized data" unless type = pson['type']
32
+ raise ArgumentError, "No resource title provided in serialized data" unless title = pson['title']
33
33
 
34
34
  resource = new(type, title)
35
35
 
@@ -47,8 +47,6 @@ class Puppet::Resource
47
47
  end
48
48
  end
49
49
 
50
- resource.exported ||= false
51
-
52
50
  resource
53
51
  end
54
52
 
@@ -17,6 +17,13 @@ module Puppet
17
17
  @changed @resource_type @title @skipped @failed}.
18
18
  map(&:to_sym)
19
19
 
20
+
21
+ def self.from_pson(data)
22
+ obj = self.allocate
23
+ obj.initialize_from_hash(data)
24
+ obj
25
+ end
26
+
20
27
  # Provide a boolean method for each of the states.
21
28
  STATES.each do |attr|
22
29
  define_method("#{attr}?") do
@@ -67,6 +74,27 @@ module Puppet
67
74
  @title = resource.title
68
75
  end
69
76
 
77
+ def initialize_from_hash(data)
78
+ @resource_type = data['resource_type']
79
+ @title = data['title']
80
+ @resource = data['resource']
81
+ @file = data['file']
82
+ @line = data['line']
83
+ @evaluation_time = data['evaluation_time']
84
+ @change_count = data['change_count']
85
+ @out_of_sync_count = data['out_of_sync_count']
86
+ @tags = data['tags']
87
+ @time = data['time']
88
+ @out_of_sync = data['out_of_sync']
89
+ @changed = data['changed']
90
+ @skipped = data['skipped']
91
+ @failed = data['failed']
92
+
93
+ @events = data['events'].map do |event|
94
+ Puppet::Transaction::Event.from_pson(event)
95
+ end
96
+ end
97
+
70
98
  def to_yaml_properties
71
99
  YAML_ATTRIBUTES & instance_variables
72
100
  end
data/lib/puppet/run.rb CHANGED
@@ -33,6 +33,17 @@ class Puppet::Run
33
33
  @options = options
34
34
  end
35
35
 
36
+ def initialize_from_hash(hash)
37
+ @options = {}
38
+
39
+ hash['options'].each do |key, value|
40
+ @options[key.to_sym] = value
41
+ end
42
+
43
+ @background = hash['background']
44
+ @status = hash['status']
45
+ end
46
+
36
47
  def log_run
37
48
  msg = ""
38
49
  msg += "triggered run" % if options[:tags]
@@ -63,9 +74,20 @@ class Puppet::Run
63
74
  self
64
75
  end
65
76
 
66
- def self.from_pson( pson )
77
+ def self.from_hash(hash)
78
+ obj = allocate
79
+ obj.initialize_from_hash(hash)
80
+ obj
81
+ end
82
+
83
+ def self.from_pson(hash)
84
+ if hash['options']
85
+ return from_hash(hash)
86
+ end
87
+
67
88
  options = { :pluginsync => Puppet[:pluginsync] }
68
- pson.each do |key, value|
89
+
90
+ hash.each do |key, value|
69
91
  options[key.to_sym] = value
70
92
  end
71
93