puppet 3.3.0 → 3.3.1.rc1

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/lib/puppet/configurer.rb +1 -7
  3. data/lib/puppet/defaults.rb +18 -6
  4. data/lib/puppet/file_bucket/file.rb +10 -1
  5. data/lib/puppet/forge/repository.rb +8 -2
  6. data/lib/puppet/graph/simple_graph.rb +1 -1
  7. data/lib/puppet/indirector/request.rb +18 -0
  8. data/lib/puppet/indirector/rest.rb +22 -1
  9. data/lib/puppet/indirector/status/local.rb +3 -1
  10. data/lib/puppet/indirector/yaml.rb +4 -18
  11. data/lib/puppet/network/http.rb +1 -0
  12. data/lib/puppet/network/http/handler.rb +11 -6
  13. data/lib/puppet/parser/yaml_trimmer.rb +1 -3
  14. data/lib/puppet/provider/package/dpkg.rb +2 -1
  15. data/lib/puppet/provider/package/rpm.rb +4 -2
  16. data/lib/puppet/provider/parsedfile.rb +9 -6
  17. data/lib/puppet/resource/status.rb +1 -1
  18. data/lib/puppet/status.rb +8 -0
  19. data/lib/puppet/transaction/additional_resource_generator.rb +1 -1
  20. data/lib/puppet/transaction/event.rb +1 -1
  21. data/lib/puppet/transaction/report.rb +6 -2
  22. data/lib/puppet/util/monkey_patches.rb +0 -52
  23. data/lib/puppet/util/storage.rb +5 -8
  24. data/lib/puppet/util/yaml.rb +23 -0
  25. data/lib/puppet/util/zaml.rb +14 -2
  26. data/lib/puppet/version.rb +1 -1
  27. data/spec/unit/agent_spec.rb +2 -0
  28. data/spec/unit/file_bucket/file_spec.rb +19 -13
  29. data/spec/unit/indirector/certificate/rest_spec.rb +1 -0
  30. data/spec/unit/indirector/report/rest_spec.rb +1 -0
  31. data/spec/unit/indirector/request_spec.rb +9 -0
  32. data/spec/unit/indirector/rest_spec.rb +22 -2
  33. data/spec/unit/indirector/run/local_spec.rb +3 -1
  34. data/spec/unit/indirector/status/local_spec.rb +11 -0
  35. data/spec/unit/indirector/status/rest_spec.rb +1 -1
  36. data/spec/unit/indirector/yaml_spec.rb +16 -40
  37. data/spec/unit/network/http/handler_spec.rb +17 -3
  38. data/spec/unit/pops/adaptable_spec.rb +0 -2
  39. data/spec/unit/provider/package/dpkg_spec.rb +31 -23
  40. data/spec/unit/provider/package/rpm_spec.rb +16 -8
  41. data/spec/unit/provider/parsedfile_spec.rb +86 -47
  42. data/spec/unit/transaction/report_spec.rb +5 -1
  43. data/spec/unit/transaction/resource_harness_spec.rb +1 -1
  44. data/spec/unit/util/monkey_patches_spec.rb +0 -13
  45. data/spec/unit/util/storage_spec.rb +49 -49
  46. data/spec/unit/util/yaml_spec.rb +41 -0
  47. metadata +2746 -2749
@@ -83,7 +83,7 @@ class Puppet::Transaction::Event
83
83
  end
84
84
 
85
85
  def to_yaml_properties
86
- YAML_ATTRIBUTES & instance_variables
86
+ YAML_ATTRIBUTES & super
87
87
  end
88
88
 
89
89
  private
@@ -312,11 +312,15 @@ class Puppet::Transaction::Report
312
312
  # @api private
313
313
  #
314
314
  def to_yaml_properties
315
- instance_variables - [:@external_times]
315
+ super - [:@external_times]
316
316
  end
317
317
 
318
318
  def self.supported_formats
319
- [Puppet[:report_serialization_format].intern]
319
+ [:pson, :yaml]
320
+ end
321
+
322
+ def self.default_format
323
+ Puppet[:report_serialization_format].intern
320
324
  end
321
325
 
322
326
  private
@@ -161,58 +161,6 @@ class Range
161
161
  alias_method :&, :intersection unless method_defined? :&
162
162
  end
163
163
 
164
- ########################################################################
165
- # The return type of `instance_variables` changes between Ruby 1.8 and 1.9
166
- # releases; it used to return an array of strings in the form "@foo", but
167
- # now returns an array of symbols in the form :@foo.
168
- #
169
- # Nothing else in the stack cares which form you get - you can pass the
170
- # string or symbol to things like `instance_variable_set` and they will work
171
- # transparently.
172
- #
173
- # Having the same form in all releases of Puppet is a win, though, so we
174
- # pick a unification and enforce than on all releases. That way developers
175
- # who do set math on them (eg: for YAML rendering) don't have to handle the
176
- # distinction themselves.
177
- #
178
- # In the sane tradition, we bring older releases into conformance with newer
179
- # releases, so we return symbols rather than strings, to be more like the
180
- # future versions of Ruby are.
181
- #
182
- # We also carefully support reloading, by only wrapping when we don't
183
- # already have the original version of the method aliased away somewhere.
184
- if RUBY_VERSION[0,3] == '1.8'
185
- unless Object.respond_to?(:puppet_original_instance_variables)
186
-
187
- # Add our wrapper to the method.
188
- class Object
189
- alias :puppet_original_instance_variables :instance_variables
190
-
191
- def instance_variables
192
- puppet_original_instance_variables.map(&:to_sym)
193
- end
194
- end
195
-
196
- # The one place that Ruby 1.8 assumes something about the return format of
197
- # the `instance_variables` method is actually kind of odd, because it uses
198
- # eval to get at instance variables of another object.
199
- #
200
- # This takes the original code and applies replaces instance_eval with
201
- # instance_variable_get through it. All other bugs in the original (such
202
- # as equality depending on the instance variables having the same order
203
- # without any promise from the runtime) are preserved. --daniel 2012-03-11
204
- require 'resolv'
205
- class Resolv::DNS::Resource
206
- def ==(other) # :nodoc:
207
- return self.class == other.class &&
208
- self.instance_variables == other.instance_variables &&
209
- self.instance_variables.collect {|name| self.instance_variable_get name} ==
210
- other.instance_variables.collect {|name| other.instance_variable_get name}
211
- end
212
- end
213
- end
214
- end
215
-
216
164
  # (#19151) Reject all SSLv2 ciphers and handshakes
217
165
  require 'openssl'
218
166
  class OpenSSL::SSL::SSLContext
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
  require 'sync'
3
3
  require 'singleton'
4
+ require 'puppet/util/yaml'
4
5
 
5
6
  # a class for storing state
6
7
  class Puppet::Util::Storage
@@ -32,12 +33,10 @@ class Puppet::Util::Storage
32
33
 
33
34
  def self.clear
34
35
  @@state.clear
35
- Storage.init
36
36
  end
37
37
 
38
38
  def self.init
39
39
  @@state = {}
40
- @@splitchar = "\t"
41
40
  end
42
41
 
43
42
  self.init
@@ -47,7 +46,7 @@ class Puppet::Util::Storage
47
46
  filename = Puppet[:statefile]
48
47
 
49
48
  unless File.exists?(filename)
50
- self.init unless !@@state.nil?
49
+ self.init if @@state.nil?
51
50
  return
52
51
  end
53
52
  unless File.file?(filename)
@@ -56,8 +55,8 @@ class Puppet::Util::Storage
56
55
  end
57
56
  Puppet::Util.benchmark(:debug, "Loaded state") do
58
57
  begin
59
- @@state = YAML.load(::File.read(filename))
60
- rescue => detail
58
+ @@state = Puppet::Util::Yaml.load_file(filename)
59
+ rescue Puppet::Util::Yaml::YamlLoadError => detail
61
60
  Puppet.err "Checksumfile #{filename} is corrupt (#{detail}); replacing"
62
61
 
63
62
  begin
@@ -84,9 +83,7 @@ class Puppet::Util::Storage
84
83
  Puppet.info "Creating state file #{Puppet[:statefile]}" unless FileTest.exist?(Puppet[:statefile])
85
84
 
86
85
  Puppet::Util.benchmark(:debug, "Stored state") do
87
- Puppet::Util.replace_file(Puppet[:statefile], 0660) do |fh|
88
- fh.print YAML.dump(@@state)
89
- end
86
+ Puppet::Util::Yaml.dump(@@state, Puppet[:statefile])
90
87
  end
91
88
  end
92
89
  end
@@ -0,0 +1,23 @@
1
+ require 'yaml'
2
+
3
+ module Puppet::Util::Yaml
4
+ if defined?(::Psych::SyntaxError)
5
+ YamlLoadExceptions = [::StandardError, ::Psych::SyntaxError]
6
+ else
7
+ YamlLoadExceptions = [::StandardError]
8
+ end
9
+
10
+ class YamlLoadError < Puppet::Error; end
11
+
12
+ def self.load_file(filename)
13
+ YAML.load_file(filename)
14
+ rescue *YamlLoadExceptions => detail
15
+ raise YamlLoadError.new(detail.message, detail)
16
+ end
17
+
18
+ def self.dump(structure, filename)
19
+ Puppet::Util.replace_file(filename, 0660) do |fh|
20
+ YAML.dump(structure, fh)
21
+ end
22
+ end
23
+ end
@@ -171,16 +171,28 @@ end
171
171
  ################################################################
172
172
 
173
173
  class Object
174
- def to_yaml_properties
175
- instance_variables # default YAML behaviour.
174
+ # Users of this method need to do set math consistently with the
175
+ # result. Since #instance_variables returns strings in 1.8 and symbols
176
+ # on 1.9, standardize on symbols
177
+ if RUBY_VERSION[0,3] == '1.8'
178
+ def to_yaml_properties
179
+ instance_variables.map(&:to_sym)
180
+ end
181
+ else
182
+ def to_yaml_properties
183
+ instance_variables
184
+ end
176
185
  end
186
+
177
187
  def yaml_property_munge(x)
178
188
  x
179
189
  end
190
+
180
191
  def zamlized_class_name(root)
181
192
  cls = self.class
182
193
  "!ruby/#{root.name.downcase}#{cls == root ? '' : ":#{cls.respond_to?(:name) ? cls.name : cls}"}"
183
194
  end
195
+
184
196
  def to_zaml(z)
185
197
  z.first_time_only(self) {
186
198
  z.emit(zamlized_class_name(Object))
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  module Puppet
10
- PUPPETVERSION = '3.3.0'
10
+ PUPPETVERSION = '3.3.1-rc1'
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -20,6 +20,8 @@ end
20
20
 
21
21
  describe Puppet::Agent do
22
22
  before do
23
+ Puppet::Status.indirection.stubs(:find).returns Puppet::Status.new("version" => Puppet.version)
24
+
23
25
  @agent = Puppet::Agent.new(AgentTestClient, false)
24
26
 
25
27
  # So we don't actually try to hit the filesystem.
@@ -15,18 +15,28 @@ describe Puppet::FileBucket::File do
15
15
  let(:bucketdir) { Puppet[:bucketdir] = tmpdir('bucket') }
16
16
  let(:destdir) { File.join(bucketdir, "8/b/3/7/0/2/a/d/#{digest}") }
17
17
 
18
- it "defines its supported format to be `:s`" do
19
- expect(Puppet::FileBucket::File.supported_formats).to eq([:s])
18
+ it "defaults to serializing to `:s`" do
19
+ expect(Puppet::FileBucket::File.default_format).to eq(:s)
20
20
  end
21
21
 
22
- it "serializes to `:s`" do
23
- expect(Puppet::FileBucket::File.new(contents).to_s).to eq(contents)
22
+ it "accepts s and pson" do
23
+ expect(Puppet::FileBucket::File.supported_formats).to include(:s, :pson)
24
24
  end
25
25
 
26
- it "deserializes from `:s`" do
27
- file = Puppet::FileBucket::File.from_s(contents)
26
+ it "can make a round trip through `s`" do
27
+ file = Puppet::FileBucket::File.new(contents)
28
28
 
29
- expect(file.contents).to eq(contents)
29
+ tripped = Puppet::FileBucket::File.convert_from(:s, file.render)
30
+
31
+ expect(tripped.contents).to eq(contents)
32
+ end
33
+
34
+ it "can make a round trip through `pson`" do
35
+ file = Puppet::FileBucket::File.new(contents)
36
+
37
+ tripped = Puppet::FileBucket::File.convert_from(:pson, file.render(:pson))
38
+
39
+ expect(tripped.contents).to eq(contents)
30
40
  end
31
41
 
32
42
  it "should raise an error if changing content" do
@@ -76,12 +86,8 @@ describe Puppet::FileBucket::File do
76
86
  end
77
87
 
78
88
  it "should convert the contents to PSON" do
79
- # The model class no longer defines to_pson and it is not a supported
80
- # format, but pson monkey patches Object#to_pson to return
81
- # Object#to_s.to_pson, and it monkey patches String#to_pson to wrap the
82
- # returned string in quotes. So it works in a way that is completely
83
- # unexpected, and it doesn't round-trip correctly, awesome.
84
- Puppet::FileBucket::File.new("file contents").to_pson.should == '"file contents"'
89
+ Puppet.expects(:deprecation_warning).with('Serializing Puppet::FileBucket::File objects to pson is deprecated.')
90
+ Puppet::FileBucket::File.new("file contents").to_pson.should == '{"contents":"file contents"}'
85
91
  end
86
92
 
87
93
  it "should load from PSON" do
@@ -51,6 +51,7 @@ rn/G
51
51
  response = stub 'response', :code => "200", :body => cert_string
52
52
  response.stubs(:[]).with('content-type').returns "text/plain"
53
53
  response.stubs(:[]).with('content-encoding')
54
+ response.stubs(:[]).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION).returns(Puppet.version)
54
55
  network.stubs(:verify_callback=)
55
56
  network.expects(:get).returns response
56
57
 
@@ -36,6 +36,7 @@ describe Puppet::Transaction::Report::Rest do
36
36
  obj = stub('http 200 ok', :code => code.to_s, :body => body)
37
37
  obj.stubs(:[]).with('content-type').returns(content_type)
38
38
  obj.stubs(:[]).with('content-encoding').returns(encoding)
39
+ obj.stubs(:[]).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION).returns(Puppet.version)
39
40
  obj
40
41
  end
41
42
 
@@ -334,6 +334,15 @@ describe Puppet::Indirector::Request do
334
334
  }
335
335
  end
336
336
 
337
+ it "should convert an array of values into a single yaml entry when in legacy mode" do
338
+ Puppet[:legacy_query_parameter_serialization] = true
339
+ request = a_request_with_options(:one => %w{one two})
340
+
341
+ the_parsed_query_string_from(request).should == {
342
+ "one" => ["--- \n - one\n - two"]
343
+ }
344
+ end
345
+
337
346
  it "should stringify simple data types inside an array" do
338
347
  request = a_request_with_options(:one => ['one', nil])
339
348
 
@@ -5,8 +5,28 @@ require 'puppet/indirector/errors'
5
5
  require 'puppet/indirector/rest'
6
6
 
7
7
  # Just one from each category since the code makes no real distinctions
8
- HTTP_ERROR_CODES = [300, 400, 500]
9
8
  shared_examples_for "a REST terminus method" do |terminus_method|
9
+ describe "when talking to an older master" do
10
+ it "should set backward compatibility settings" do
11
+ response.stubs(:[]).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION).returns nil
12
+
13
+ terminus.send(terminus_method, request)
14
+ Puppet[:report_serialization_format].should == 'yaml'
15
+ Puppet[:legacy_query_parameter_serialization].should == true
16
+ end
17
+ end
18
+
19
+ describe "when talking to a 3.3.1 master" do
20
+ it "should not set backward compatibility settings" do
21
+ response.stubs(:[]).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION).returns "3.3.1"
22
+
23
+ terminus.send(terminus_method, request)
24
+ Puppet[:report_serialization_format].should == 'pson'
25
+ Puppet[:legacy_query_parameter_serialization].should == false
26
+ end
27
+ end
28
+
29
+ HTTP_ERROR_CODES = [300, 400, 500]
10
30
  HTTP_ERROR_CODES.each do |code|
11
31
  describe "when the response code is #{code}" do
12
32
  let(:response) { mock_response(code, 'error messaged!!!') }
@@ -115,6 +135,7 @@ describe Puppet::Indirector::REST do
115
135
  obj = stub('http 200 ok', :code => code.to_s, :body => body)
116
136
  obj.stubs(:[]).with('content-type').returns(content_type)
117
137
  obj.stubs(:[]).with('content-encoding').returns(encoding)
138
+ obj.stubs(:[]).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION).returns(Puppet.version)
118
139
  obj
119
140
  end
120
141
 
@@ -174,7 +195,6 @@ describe Puppet::Indirector::REST do
174
195
  terminus_class.port.should == 543
175
196
  end
176
197
 
177
-
178
198
  it 'should default to :puppet for the srv_service' do
179
199
  Puppet::Indirector::REST.srv_service.should == :puppet
180
200
  end
@@ -4,11 +4,13 @@ require 'spec_helper'
4
4
  require 'puppet/indirector/run/local'
5
5
 
6
6
  describe Puppet::Run::Local do
7
- it "should be a sublcass of Puppet::Indirector::Code" do
7
+ it "should be a subclass of Puppet::Indirector::Code" do
8
8
  Puppet::Run::Local.superclass.should equal(Puppet::Indirector::Code)
9
9
  end
10
10
 
11
11
  it "should call runner.run on save and return the runner" do
12
+ Puppet::Status.indirection.stubs(:find).returns Puppet::Status.new
13
+
12
14
  runner = Puppet::Run.new
13
15
  runner.stubs(:run).returns(runner)
14
16
 
@@ -0,0 +1,11 @@
1
+ #! /usr/bin/env ruby
2
+ require 'spec_helper'
3
+
4
+ require 'puppet/indirector/status/local'
5
+
6
+ describe Puppet::Indirector::Status::Local do
7
+ it "should set the puppet version" do
8
+ Puppet::Status.indirection.terminus_class = :local
9
+ expect(Puppet::Status.indirection.find('*').version).to eq(Puppet.version)
10
+ end
11
+ end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  require 'puppet/indirector/status/rest'
5
5
 
6
6
  describe Puppet::Indirector::Status::Rest do
7
- it "should be a sublcass of Puppet::Indirector::REST" do
7
+ it "should be a subclass of Puppet::Indirector::REST" do
8
8
  Puppet::Indirector::Status::Rest.superclass.should equal(Puppet::Indirector::REST)
9
9
  end
10
10
  end
@@ -4,6 +4,12 @@ require 'spec_helper'
4
4
  require 'puppet/indirector/yaml'
5
5
 
6
6
  describe Puppet::Indirector::Yaml do
7
+ include PuppetSpec::Files
8
+
9
+ class TestSubject
10
+ attr_accessor :name
11
+ end
12
+
7
13
  before :all do
8
14
  @indirection = stub 'indirection', :name => :my_yaml, :register_terminus_type => nil
9
15
  Puppet::Indirector::Indirection.expects(:instance).with(:my_yaml).returns(@indirection)
@@ -16,11 +22,10 @@ describe Puppet::Indirector::Yaml do
16
22
  before :each do
17
23
  @store = @store_class.new
18
24
 
19
- @subject = Object.new
20
- @subject.singleton_class.send(:attr_accessor, :name)
25
+ @subject = TestSubject.new
21
26
  @subject.name = :me
22
27
 
23
- @dir = File.expand_path("/what/ever")
28
+ @dir = tmpdir("yaml_indirector")
24
29
  Puppet[:clientyamldir] = @dir
25
30
  Puppet.run_mode.stubs(:master?).returns false
26
31
 
@@ -87,54 +92,25 @@ describe Puppet::Indirector::Yaml do
87
92
  @request.stubs(:instance).returns Object.new
88
93
  proc { @store.save(@request) }.should raise_error(ArgumentError)
89
94
  end
90
-
91
- it "should convert Ruby objects to YAML and write them to disk using a write lock" do
92
- yaml = @subject.to_yaml
93
- file = mock 'file'
94
- path = @store.send(:path, @subject.name)
95
- FileTest.expects(:exist?).with(File.dirname(path)).returns(true)
96
- Puppet::Util.expects(:replace_file).with(path, 0660).yields(file)
97
- file.expects(:print).with(yaml)
98
-
99
- @store.save(@request)
100
- end
101
-
102
- it "should create the indirection subdirectory if it does not exist" do
103
- yaml = @subject.to_yaml
104
- file = mock 'file'
105
- path = @store.send(:path, @subject.name)
106
- dir = File.dirname(path)
107
-
108
- FileTest.expects(:exist?).with(dir).returns(false)
109
- Dir.expects(:mkdir).with(dir)
110
-
111
- Puppet::Util.expects(:replace_file).yields(file)
112
- file.expects(:print).with(yaml)
113
-
114
- @store.save(@request)
115
- end
116
95
  end
117
96
 
118
97
  describe "when retrieving YAML" do
119
98
  it "should read YAML in from disk and convert it to Ruby objects" do
120
- path = @store.send(:path, @subject.name)
121
- yaml = @subject.to_yaml
122
-
123
- FileTest.expects(:exist?).with(path).returns true
124
- File.expects(:read).with(path).returns yaml
99
+ @store.save(Puppet::Indirector::Request.new(:my_yaml, :save, "testing", @subject))
125
100
 
126
- @store.find(@request).instance_variable_get("@name").should == :me
101
+ @store.find(Puppet::Indirector::Request.new(:my_yaml, :find, "testing", nil)).name.should == :me
127
102
  end
128
103
 
129
104
  it "should fail coherently when the stored YAML is invalid" do
130
- path = @store.send(:path, @subject.name)
131
- FileTest.expects(:exist?).with(path).returns(true)
105
+ saved_structure = Struct.new(:name).new("testing")
132
106
 
133
- # Something that will fail in yaml
134
- File.expects(:read).returns "--- foo:\n 1,2,3\nargh"
107
+ @store.save(Puppet::Indirector::Request.new(:my_yaml, :save, "testing", saved_structure))
108
+ File.open(@store.path(saved_structure.name), "w") do |file|
109
+ file.puts "{ invalid"
110
+ end
135
111
 
136
112
  expect {
137
- @store.find(@request)
113
+ @store.find(Puppet::Indirector::Request.new(:my_yaml, :find, "testing", nil))
138
114
  }.to raise_error(Puppet::Error, /Could not parse YAML data/)
139
115
  end
140
116
  end