puppet 2.6.12 → 2.6.13

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 (43) hide show
  1. data/CHANGELOG +30 -0
  2. data/CONTRIBUTING.md +299 -0
  3. data/conf/redhat/puppet.spec +4 -1
  4. data/ext/upload_facts.rb +120 -0
  5. data/lib/puppet.rb +1 -1
  6. data/lib/puppet/application/inspect.rb +5 -2
  7. data/lib/puppet/application/queue.rb +11 -1
  8. data/lib/puppet/application/resource.rb +3 -0
  9. data/lib/puppet/defaults.rb +2 -1
  10. data/lib/puppet/indirector/facts/inventory_service.rb +20 -0
  11. data/lib/puppet/indirector/report/processor.rb +2 -0
  12. data/lib/puppet/network/handler/filebucket.rb +2 -0
  13. data/lib/puppet/network/handler/fileserver.rb +1 -0
  14. data/lib/puppet/network/handler/master.rb +1 -0
  15. data/lib/puppet/network/handler/report.rb +2 -0
  16. data/lib/puppet/network/handler/runner.rb +1 -0
  17. data/lib/puppet/network/handler/status.rb +2 -0
  18. data/lib/puppet/network/http_server.rb +3 -0
  19. data/lib/puppet/network/http_server/mongrel.rb +129 -0
  20. data/lib/puppet/provider/exec/posix.rb +6 -3
  21. data/lib/puppet/provider/exec/shell.rb +11 -2
  22. data/lib/puppet/resource/catalog.rb +6 -3
  23. data/lib/puppet/ssl/host.rb +2 -0
  24. data/lib/puppet/type/cron.rb +13 -12
  25. data/lib/puppet/type/file.rb +2 -2
  26. data/lib/puppet/type/file/source.rb +1 -1
  27. data/lib/puppet/type/user.rb +8 -0
  28. data/lib/puppet/util.rb +16 -41
  29. data/lib/puppet/util/settings.rb +1 -1
  30. data/lib/puppet/util/suidmanager.rb +48 -14
  31. data/spec/unit/application/inspect_spec.rb +5 -0
  32. data/spec/unit/application/resource_spec.rb +25 -0
  33. data/spec/unit/configurer_spec.rb +5 -0
  34. data/spec/unit/indirector/facts/inventory_service_spec.rb +22 -0
  35. data/spec/unit/indirector/report/processor_spec.rb +7 -5
  36. data/spec/unit/resource/catalog_spec.rb +54 -7
  37. data/spec/unit/ssl/host_spec.rb +58 -9
  38. data/spec/unit/type/file_spec.rb +6 -0
  39. data/spec/unit/type/user_spec.rb +8 -0
  40. data/spec/unit/util/settings_spec.rb +11 -0
  41. data/spec/unit/util/suidmanager_spec.rb +210 -0
  42. metadata +11 -5
  43. data/test/puppet/tc_suidmanager.rb +0 -120
@@ -154,7 +154,7 @@ module Puppet
154
154
  fail detail, "Could not retrieve file metadata for #{source}: #{detail}"
155
155
  end
156
156
  end
157
- fail "Could not retrieve information from source(s) #{value.join(", ")}" unless result
157
+ fail "Could not retrieve information from environment #{Puppet[:environment]} source(s) #{value.join(", ")}" unless result
158
158
  result
159
159
  end
160
160
 
@@ -165,6 +165,14 @@ module Puppet
165
165
  return "changed password"
166
166
  end
167
167
  end
168
+
169
+ def is_to_s( currentvalue )
170
+ return '[old password hash redacted]'
171
+ end
172
+ def should_to_s( newvalue )
173
+ return '[new password hash redacted]'
174
+ end
175
+
168
176
  end
169
177
 
170
178
  newproperty(:password_min_age, :required_features => :manages_password_age) do
data/lib/puppet/util.rb CHANGED
@@ -29,7 +29,6 @@ module Util
29
29
  end
30
30
  end
31
31
 
32
-
33
32
  def self.synchronize_on(x,type)
34
33
  sync_object,users = 0,1
35
34
  begin
@@ -47,35 +46,24 @@ module Util
47
46
  # Change the process to a different user
48
47
  def self.chuser
49
48
  if group = Puppet[:group]
50
- group = self.gid(group)
51
- raise Puppet::Error, "No such group #{Puppet[:group]}" unless group
52
- unless Puppet::Util::SUIDManager.gid == group
53
- begin
54
- Puppet::Util::SUIDManager.egid = group
55
- Puppet::Util::SUIDManager.gid = group
56
- rescue => detail
57
- Puppet.warning "could not change to group #{group.inspect}: #{detail}"
58
- $stderr.puts "could not change to group #{group.inspect}"
59
-
60
- # Don't exit on failed group changes, since it's
61
- # not fatal
62
- #exit(74)
63
- end
49
+ begin
50
+ Puppet::Util::SUIDManager.change_group(group, true)
51
+ rescue => detail
52
+ Puppet.warning "could not change to group #{group.inspect}: #{detail}"
53
+ $stderr.puts "could not change to group #{group.inspect}"
54
+
55
+ # Don't exit on failed group changes, since it's
56
+ # not fatal
57
+ #exit(74)
64
58
  end
65
59
  end
66
60
 
67
61
  if user = Puppet[:user]
68
- user = self.uid(user)
69
- raise Puppet::Error, "No such user #{Puppet[:user]}" unless user
70
- unless Puppet::Util::SUIDManager.uid == user
71
- begin
72
- Puppet::Util::SUIDManager.initgroups(user)
73
- Puppet::Util::SUIDManager.uid = user
74
- Puppet::Util::SUIDManager.euid = user
75
- rescue => detail
76
- $stderr.puts "Could not change to user #{user}: #{detail}"
77
- exit(74)
78
- end
62
+ begin
63
+ Puppet::Util::SUIDManager.change_user(user, true)
64
+ rescue => detail
65
+ $stderr.puts "Could not change to user #{user}: #{detail}"
66
+ exit(74)
79
67
  end
80
68
  end
81
69
  end
@@ -90,18 +78,14 @@ module Util
90
78
  if useself
91
79
 
92
80
  Puppet::Util::Log.create(
93
-
94
81
  :level => level,
95
82
  :source => self,
96
-
97
83
  :message => args
98
84
  )
99
85
  else
100
86
 
101
87
  Puppet::Util::Log.create(
102
-
103
88
  :level => level,
104
-
105
89
  :message => args
106
90
  )
107
91
  end
@@ -262,9 +246,6 @@ module Util
262
246
  Puppet.debug "Executing '#{str}'"
263
247
  end
264
248
 
265
- arguments[:uid] = Puppet::Util::SUIDManager.convert_xid(:uid, arguments[:uid]) if arguments[:uid]
266
- arguments[:gid] = Puppet::Util::SUIDManager.convert_xid(:gid, arguments[:gid]) if arguments[:gid]
267
-
268
249
  if execution_stub = Puppet::Util::ExecutionStub.current_value
269
250
  return execution_stub.call(command, arguments)
270
251
  end
@@ -306,14 +287,8 @@ module Util
306
287
  $stderr.reopen(error_file)
307
288
 
308
289
  3.upto(256){|fd| IO::new(fd).close rescue nil}
309
- if arguments[:gid]
310
- Process.egid = arguments[:gid]
311
- Process.gid = arguments[:gid] unless @@os == "Darwin"
312
- end
313
- if arguments[:uid]
314
- Process.euid = arguments[:uid]
315
- Process.uid = arguments[:uid] unless @@os == "Darwin"
316
- end
290
+ Puppet::Util::SUIDManager.change_group(arguments[:gid], true) if arguments[:gid]
291
+ Puppet::Util::SUIDManager.change_user(arguments[:uid], true) if arguments[:uid]
317
292
  ENV['LANG'] = ENV['LC_ALL'] = ENV['LC_MESSAGES'] = ENV['LANGUAGE'] = 'C'
318
293
  if command.is_a?(Array)
319
294
  Kernel.exec(*command)
@@ -726,7 +726,7 @@ if @config.include?(:run_mode)
726
726
  end
727
727
 
728
728
  Puppet::Util::SUIDManager.asuser(*chown) do
729
- mode = obj.mode || 0640
729
+ mode = obj.mode ? obj.mode.to_i : 0640
730
730
  args << "w" if args.empty?
731
731
 
732
732
  args << mode
@@ -36,12 +36,6 @@ module Puppet::Util::SUIDManager
36
36
  end
37
37
  module_function :groups=
38
38
 
39
- if Facter['kernel'].value == 'Darwin'
40
- # Cannot change real UID on Darwin so we set euid
41
- alias :uid :euid
42
- alias :gid :egid
43
- end
44
-
45
39
  def self.root?
46
40
  Process.uid == 0
47
41
  end
@@ -50,23 +44,63 @@ module Puppet::Util::SUIDManager
50
44
  def asuser(new_uid=nil, new_gid=nil)
51
45
  return yield if Puppet.features.microsoft_windows? or !root?
52
46
 
53
- # We set both because some programs like to drop privs, i.e. bash.
54
- old_uid, old_gid = self.uid, self.gid
55
47
  old_euid, old_egid = self.euid, self.egid
56
- old_groups = self.groups
57
48
  begin
58
- self.egid = convert_xid :gid, new_gid if new_gid
59
- self.initgroups(convert_xid(:uid, new_uid)) if new_uid
60
- self.euid = convert_xid :uid, new_uid if new_uid
49
+ change_group(new_gid) if new_gid
50
+ change_user(new_uid) if new_uid
61
51
 
62
52
  yield
63
53
  ensure
64
- self.euid, self.egid = old_euid, old_egid
65
- self.groups = old_groups
54
+ change_group(old_egid)
55
+ change_user(old_euid)
66
56
  end
67
57
  end
68
58
  module_function :asuser
69
59
 
60
+ def change_group(group, permanently=false)
61
+ gid = convert_xid(:gid, group)
62
+ raise Puppet::Error, "No such group #{group}" unless gid
63
+
64
+ if permanently
65
+ begin
66
+ Process::GID.change_privilege(gid)
67
+ rescue NotImplementedError
68
+ Process.egid = gid
69
+ Process.gid = gid
70
+ end
71
+ else
72
+ Process.egid = gid
73
+ end
74
+ end
75
+ module_function :change_group
76
+
77
+ def change_user(user, permanently=false)
78
+ uid = convert_xid(:uid, user)
79
+ raise Puppet::Error, "No such user #{user}" unless uid
80
+
81
+ if permanently
82
+ begin
83
+ Process::UID.change_privilege(uid)
84
+ rescue NotImplementedError
85
+ # If changing uid, we must be root. So initgroups first here.
86
+ initgroups(uid)
87
+ Process.euid = uid
88
+ Process.uid = uid
89
+ end
90
+ else
91
+ # If we're already root, initgroups before changing euid. If we're not,
92
+ # change euid (to root) first.
93
+ if Process.euid == 0
94
+ initgroups(uid)
95
+ Process.euid = uid
96
+ else
97
+ Process.euid = uid
98
+ initgroups(uid)
99
+ end
100
+ end
101
+ end
102
+ module_function :change_user
103
+
70
104
  # Make sure the passed argument is a number.
71
105
  def convert_xid(type, id)
72
106
  map = {:gid => :group, :uid => :user}
@@ -13,6 +13,11 @@ describe Puppet::Application::Inspect do
13
13
 
14
14
  before :each do
15
15
  @inspect = Puppet::Application[:inspect]
16
+ @inspect.preinit
17
+ end
18
+
19
+ it "should operate in agent run_mode" do
20
+ @inspect.class.run_mode.name.should == :agent
16
21
  end
17
22
 
18
23
  describe "during setup" do
@@ -230,4 +230,29 @@ describe Puppet::Application::Resource do
230
230
 
231
231
  end
232
232
  end
233
+
234
+ describe "when handling file type" do
235
+ before :each do
236
+ Facter.stubs(:loadfacts)
237
+ @resource.preinit
238
+ end
239
+
240
+ it "should raise an exception if no file specified" do
241
+ @resource.command_line.stubs(:args).returns(['file'])
242
+
243
+ lambda { @resource.main }.should raise_error(RuntimeError, /Listing all file instances is not supported/)
244
+ end
245
+
246
+ it "should output a file resource when given a file path" do
247
+ res = Puppet::Type.type(:file).new(:path => "/etc").to_resource
248
+ Puppet::Resource.expects(:find).returns(res)
249
+
250
+ @resource.command_line.stubs(:args).returns(['file', '/etc'])
251
+ @resource.expects(:puts).with do |args|
252
+ args.should =~ /file \{ '\/etc'/m
253
+ end
254
+
255
+ @resource.main
256
+ end
257
+ end
233
258
  end
@@ -90,6 +90,11 @@ describe Puppet::Configurer do
90
90
  Puppet::Util::Log.stubs(:close)
91
91
  end
92
92
 
93
+ after :all do
94
+ Puppet::Node::Facts.indirection.reset_terminus_class
95
+ Puppet::Resource::Catalog.indirection.reset_terminus_class
96
+ end
97
+
93
98
  it "should prepare for the run" do
94
99
  @agent.expects(:prepare)
95
100
 
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rspec
2
+ require 'spec_helper'
3
+
4
+ require 'puppet/indirector/facts/inventory_service'
5
+
6
+ describe Puppet::Node::Facts::InventoryService do
7
+ it "should suppress failures and warn when saving facts" do
8
+ facts = Puppet::Node::Facts.new('foo')
9
+ request = Puppet::Indirector::Request.new(:facts, :save, facts)
10
+
11
+ Net::HTTP.any_instance.stubs(:put).raises(Errno::ECONNREFUSED)
12
+
13
+ Puppet.expects(:warning).with do |msg|
14
+ msg =~ /Could not upload facts for foo to inventory service/
15
+ end
16
+
17
+ expect {
18
+ subject.save(request)
19
+ }.should_not raise_error
20
+ end
21
+ end
22
+
@@ -25,9 +25,11 @@ describe Puppet::Transaction::Report::Processor, " when saving a report" do
25
25
 
26
26
  it "should not process the report if reports are set to 'none'" do
27
27
  Puppet::Reports.expects(:report).never
28
- Puppet.settings.expects(:value).with(:reports).returns("none")
28
+ Puppet[:reports] = 'none'
29
29
 
30
- request = stub 'request', :instance => mock("report")
30
+ request = Puppet::Indirector::Request.new(:indirection_name, :head, "key")
31
+ report = Puppet::Transaction::Report.new('apply')
32
+ request.instance = report
31
33
 
32
34
  @reporter.save(request)
33
35
  end
@@ -40,14 +42,14 @@ end
40
42
 
41
43
  describe Puppet::Transaction::Report::Processor, " when processing a report" do
42
44
  before do
43
- Puppet.settings.stubs(:value).with(:reports).returns("one")
45
+ Puppet[:reports] = "one"
44
46
  Puppet.settings.stubs(:use)
45
47
  @reporter = Puppet::Transaction::Report::Processor.new
46
48
 
47
49
  @report_type = mock 'one'
48
50
  @dup_report = mock 'dupe report'
49
51
  @dup_report.stubs(:process)
50
- @report = mock 'report'
52
+ @report = Puppet::Transaction::Report.new('apply')
51
53
  @report.expects(:dup).returns(@dup_report)
52
54
 
53
55
  @request = stub 'request', :instance => @report
@@ -74,7 +76,7 @@ describe Puppet::Transaction::Report::Processor, " when processing a report" do
74
76
  end
75
77
 
76
78
  it "should not raise exceptions" do
77
- Puppet.settings.stubs(:value).with(:trace).returns(false)
79
+ Puppet[:trace] = false
78
80
  @dup_report.expects(:process).raises(ArgumentError)
79
81
  proc { @reporter.save(@request) }.should_not raise_error
80
82
  end
@@ -507,7 +507,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
507
507
  lambda { @catalog.alias(@one, "other") }.should_not raise_error
508
508
  end
509
509
 
510
- it "should create aliases for resources isomorphic resources whose names do not match their titles" do
510
+ it "should create aliases for isomorphic resources whose names do not match their titles" do
511
511
  resource = Puppet::Type::File.new(:title => "testing", :path => @basepath+"/something")
512
512
 
513
513
  @catalog.add_resource(resource)
@@ -515,7 +515,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
515
515
  @catalog.resource(:file, @basepath+"/something").should equal(resource)
516
516
  end
517
517
 
518
- it "should not create aliases for resources non-isomorphic resources whose names do not match their titles" do
518
+ it "should not create aliases for non-isomorphic resources whose names do not match their titles" do
519
519
  resource = Puppet::Type.type(:exec).new(:title => "testing", :command => "echo", :path => %w{/bin /usr/bin /usr/local/bin})
520
520
 
521
521
  @catalog.add_resource(resource)
@@ -531,11 +531,6 @@ describe Puppet::Resource::Catalog, "when compiling" do
531
531
  @catalog.resource("notify", "other").should equal(@one)
532
532
  end
533
533
 
534
- it "should ignore conflicting aliases that point to the aliased resource" do
535
- @catalog.alias(@one, "other")
536
- lambda { @catalog.alias(@one, "other") }.should_not raise_error
537
- end
538
-
539
534
  it "should fail to add an alias if the aliased name already exists" do
540
535
  @catalog.add_resource @one
541
536
  proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError)
@@ -589,6 +584,58 @@ describe Puppet::Resource::Catalog, "when compiling" do
589
584
  @catalog.create_resource :file, args
590
585
  @catalog.resource("File[/yay]").should equal(resource)
591
586
  end
587
+
588
+ describe "when adding resources with multiple namevars" do
589
+ before :each do
590
+ Puppet::Type.newtype(:multiple) do
591
+ newparam(:color, :namevar => true)
592
+ newparam(:designation, :namevar => true)
593
+
594
+ def self.title_patterns
595
+ [ [
596
+ /^(\w+) (\w+)$/,
597
+ [
598
+ [:color, lambda{|x| x}],
599
+ [:designation, lambda{|x| x}]
600
+ ]
601
+ ] ]
602
+ end
603
+ end
604
+ end
605
+
606
+ it "should add an alias using the uniqueness key" do
607
+ @resource = Puppet::Type.type(:multiple).new(:title => "some resource", :color => "red", :designation => "5")
608
+
609
+ @catalog.add_resource(@resource)
610
+ @catalog.resource(:multiple, "some resource").must == @resource
611
+ @catalog.resource("Multiple[some resource]").must == @resource
612
+ @catalog.resource("Multiple[red 5]").must == @resource
613
+ end
614
+
615
+ it "should conflict with a resource with the same uniqueness key" do
616
+ @resource = Puppet::Type.type(:multiple).new(:title => "some resource", :color => "red", :designation => "5")
617
+ @other = Puppet::Type.type(:multiple).new(:title => "another resource", :color => "red", :designation => "5")
618
+
619
+ @catalog.add_resource(@resource)
620
+ expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias Multiple\[another resource\] to \["red", "5"\].*resource \["Multiple", "red", "5"\] already defined/)
621
+ end
622
+
623
+ it "should conflict when its uniqueness key matches another resource's title" do
624
+ @resource = Puppet::Type.type(:file).new(:title => "/tmp/foo")
625
+ @other = Puppet::Type.type(:file).new(:title => "another file", :path => "/tmp/foo")
626
+
627
+ @catalog.add_resource(@resource)
628
+ expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias File\[another file\] to \["\/tmp\/foo"\].*resource \["File", "\/tmp\/foo"\] already defined/)
629
+ end
630
+
631
+ it "should conflict when its uniqueness key matches the uniqueness key derived from another resource's title" do
632
+ @resource = Puppet::Type.type(:multiple).new(:title => "red leader")
633
+ @other = Puppet::Type.type(:multiple).new(:title => "another resource", :color => "red", :designation => "leader")
634
+
635
+ @catalog.add_resource(@resource)
636
+ expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias Multiple\[another resource\] to \["red", "leader"\].*resource \["Multiple", "red", "leader"\] already defined/)
637
+ end
638
+ end
592
639
  end
593
640
 
594
641
  describe "when applying" do
@@ -82,8 +82,6 @@ describe Puppet::SSL::Host do
82
82
 
83
83
  context "with dns_alt_names" do
84
84
  before :each do
85
- Puppet[:dns_alt_names] = 'one, two'
86
-
87
85
  @key = stub('key content')
88
86
  key = stub('key', :generate => true, :save => true, :content => @key)
89
87
  Puppet::SSL::Key.stubs(:new).returns key
@@ -92,17 +90,68 @@ describe Puppet::SSL::Host do
92
90
  Puppet::SSL::CertificateRequest.stubs(:new).returns @cr
93
91
  end
94
92
 
95
- it "should not include subjectAltName if not the local node" do
96
- @cr.expects(:generate).with(@key, {})
93
+ describe "explicitly specified" do
94
+ before :each do
95
+ Puppet[:dns_alt_names] = 'one, two'
96
+ end
97
+
98
+ it "should not include subjectAltName if not the local node" do
99
+ @cr.expects(:generate).with(@key, {})
97
100
 
98
- Puppet::SSL::Host.new('not-the-' + Puppet[:certname]).generate
101
+ Puppet::SSL::Host.new('not-the-' + Puppet[:certname]).generate
102
+ end
103
+
104
+ it "should include subjectAltName if I am a CA" do
105
+ @cr.expects(:generate).
106
+ with(@key, { :dns_alt_names => Puppet[:dns_alt_names] })
107
+
108
+ Puppet::SSL::Host.localhost
109
+ end
99
110
  end
100
111
 
101
- it "should include subjectAltName if I am a CA" do
102
- @cr.expects(:generate).
103
- with(@key, { :dns_alt_names => Puppet[:dns_alt_names] })
112
+ describe "implicitly defaulted" do
113
+ let(:ca) { stub('ca', :sign => nil) }
104
114
 
105
- Puppet::SSL::Host.localhost
115
+ before :each do
116
+ Puppet[:dns_alt_names] = ''
117
+
118
+ Puppet::SSL::CertificateAuthority.stubs(:instance).returns ca
119
+ end
120
+
121
+ it "should not include defaults if we're not the CA" do
122
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns false
123
+
124
+ @cr.expects(:generate).with(@key, {})
125
+
126
+ Puppet::SSL::Host.localhost
127
+ end
128
+
129
+ it "should not include defaults if not the local node" do
130
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
131
+
132
+ @cr.expects(:generate).with(@key, {})
133
+
134
+ Puppet::SSL::Host.new('not-the-' + Puppet[:certname]).generate
135
+ end
136
+
137
+ it "should not include defaults if we can't resolve our fqdn" do
138
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
139
+ Facter.stubs(:value).with(:fqdn).returns nil
140
+
141
+ @cr.expects(:generate).with(@key, {})
142
+
143
+ Puppet::SSL::Host.localhost
144
+ end
145
+
146
+ it "should provide defaults if we're bootstrapping the local master" do
147
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
148
+ Facter.stubs(:value).with(:fqdn).returns 'web.foo.com'
149
+ Facter.stubs(:value).with(:domain).returns 'foo.com'
150
+
151
+ @cr.expects(:generate).with(@key, {:dns_alt_names => "puppet, web.foo.com, puppet.foo.com"})
152
+
153
+ Puppet::SSL::Host.localhost
154
+ end
106
155
  end
107
156
  end
108
157