puppet 3.8.4 → 3.8.5

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.

@@ -19,17 +19,17 @@ build_msi:
19
19
  ref: 'refs/tags/3.8.3'
20
20
  repo: 'git://github.com/puppetlabs/puppet_for_the_win.git'
21
21
  facter:
22
- ref: 'refs/tags/2.4.4'
22
+ ref: 'refs/tags/2.4.5'
23
23
  repo: 'git://github.com/puppetlabs/facter.git'
24
24
  hiera:
25
25
  ref: 'refs/tags/1.3.4'
26
26
  repo: 'git://github.com/puppetlabs/hiera.git'
27
27
  sys:
28
28
  ref:
29
- x86: 'refs/tags/1.9.3-p551.6'
30
- x64: 'refs/tags/2.0.0.9-x64'
29
+ x86: 'refs/tags/1.9.3-p551.8'
30
+ x64: 'refs/tags/2.0.0.11-x64'
31
31
  repo: 'git://github.com/puppetlabs/puppet-win32-ruby.git'
32
- apt_host: 'apt.puppetlabs.com'
32
+ apt_signing_server: 'apt.puppetlabs.com'
33
33
  apt_repo_url: 'http://apt.puppetlabs.com'
34
34
  apt_repo_path: '/opt/repository/incoming'
35
35
  ips_repo: '/var/pkgrepo'
data/lib/puppet/daemon.rb CHANGED
@@ -24,6 +24,7 @@ class Puppet::Daemon
24
24
  SIGNAL_CHECK_INTERVAL = 5
25
25
 
26
26
  attr_accessor :agent, :server, :argv
27
+ attr_reader :signals
27
28
 
28
29
  def initialize(pidfile, scheduler = Puppet::Scheduler::Scheduler.new())
29
30
  @scheduler = scheduler
@@ -107,13 +108,21 @@ class Puppet::Daemon
107
108
  # Trap a couple of the main signals. This should probably be handled
108
109
  # in a way that anyone else can register callbacks for traps, but, eh.
109
110
  def set_signal_traps
110
- signals = {:INT => :stop, :TERM => :stop }
111
- # extended signals not supported under windows
112
- signals.update({:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs }) unless Puppet.features.microsoft_windows?
113
- signals.each do |signal, method|
111
+ [:INT, :TERM].each do |signal|
114
112
  Signal.trap(signal) do
115
- Puppet.notice "Caught #{signal}; storing #{method}"
116
- @signals << method
113
+ Puppet.notice "Caught #{signal}; exiting"
114
+ stop
115
+ end
116
+ end
117
+
118
+ # extended signals not supported under windows
119
+ if !Puppet.features.microsoft_windows?
120
+ signals = {:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs }
121
+ signals.each do |signal, method|
122
+ Signal.trap(signal) do
123
+ Puppet.notice "Caught #{signal}; storing #{method}"
124
+ @signals << method
125
+ end
117
126
  end
118
127
  end
119
128
  end
data/lib/puppet/node.rb CHANGED
@@ -18,6 +18,8 @@ class Puppet::Node
18
18
 
19
19
  ::PSON.register_document_type('Node',self)
20
20
 
21
+ ENVIRONMENT = 'environment'.freeze
22
+
21
23
  def self.from_data_hash(data)
22
24
  raise ArgumentError, "No name provided in serialized data" unless name = data['name']
23
25
 
@@ -58,7 +60,7 @@ class Puppet::Node
58
60
  if @environment
59
61
  @environment
60
62
  else
61
- if env = parameters["environment"]
63
+ if env = parameters[ENVIRONMENT]
62
64
  self.environment = env
63
65
  elsif environment_name
64
66
  self.environment = environment_name
@@ -80,6 +82,13 @@ class Puppet::Node
80
82
  else
81
83
  @environment = env
82
84
  end
85
+
86
+ # Keep environment_name attribute and parameter in sync if they have been set
87
+ unless @environment.nil?
88
+ @parameters[ENVIRONMENT] = @environment.name if @parameters.include?(ENVIRONMENT)
89
+ self.environment_name = @environment.name if instance_variable_defined?(:@environment_name)
90
+ end
91
+ @environment
83
92
  end
84
93
 
85
94
  def has_environment_instance?
@@ -129,7 +138,7 @@ class Puppet::Node
129
138
  @parameters[name] = value unless @parameters.include?(name)
130
139
  end
131
140
 
132
- @parameters["environment"] ||= self.environment.name.to_s
141
+ @parameters[ENVIRONMENT] ||= self.environment.name.to_s
133
142
  end
134
143
 
135
144
  # Calculate the list of names we might use for looking
@@ -39,7 +39,7 @@ class Puppet::Pops::Evaluator::AccessOperator
39
39
  fail(Puppet::Pops::Issues::BAD_STRING_SLICE_ARITY, @semantic.left_expr, {:actual => keys.size})
40
40
  when 1
41
41
  # Note that Ruby 1.8.7 requires a length of 1 to produce a String
42
- k1 = coerce_numeric(keys[0], @semantic.keys, scope)
42
+ k1 = coerce_numeric(keys[0], @semantic.keys[0], scope)
43
43
  bad_access_key_type(o, 0, k1, Integer) unless k1.is_a?(Integer)
44
44
  k2 = 1
45
45
  k1 = k1 < 0 ? o.length + k1 : k1 # abs pos
@@ -50,8 +50,8 @@ class Puppet::Pops::Evaluator::AccessOperator
50
50
  o[ k1, k2 ]
51
51
  end
52
52
  when 2
53
- k1 = coerce_numeric(keys[0], @semantic.keys, scope)
54
- k2 = coerce_numeric(keys[1], @semantic.keys, scope)
53
+ k1 = coerce_numeric(keys[0], @semantic.keys[0], scope)
54
+ k2 = coerce_numeric(keys[1], @semantic.keys[1], scope)
55
55
  [k1, k2].each_with_index { |k,i| bad_access_key_type(o, i, k, Integer) unless k.is_a?(Integer) }
56
56
 
57
57
  k1 = k1 < 0 ? o.length + k1 : k1 # abs pos (negative is count from end)
@@ -317,6 +317,9 @@ class Puppet::Pops::Evaluator::AccessOperator
317
317
  end
318
318
  ranged_integer = Puppet::Pops::Types::PIntegerType.new()
319
319
  from, to = keys
320
+ # NOTE! Do not merge the following line to 4.x. It has the same check in the initialize method
321
+ raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
322
+
320
323
  ranged_integer.from = from == :default ? nil : from
321
324
  ranged_integer.to = to == :default ? nil : to
322
325
  ranged_integer
@@ -333,6 +336,9 @@ class Puppet::Pops::Evaluator::AccessOperator
333
336
  end
334
337
  ranged_float = Puppet::Pops::Types::PFloatType.new()
335
338
  from, to = keys
339
+ # NOTE! Do not merge the following line to 4.x. It has the same check in the initialize method
340
+ raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
341
+
336
342
  ranged_float.from = from == :default || from.nil? ? nil : Float(from)
337
343
  ranged_float.to = to == :default || to.nil? ? nil : Float(to)
338
344
  ranged_float
@@ -428,6 +434,9 @@ class Puppet::Pops::Evaluator::AccessOperator
428
434
  end
429
435
  ranged_integer = Puppet::Pops::Types::PIntegerType.new()
430
436
  from, to = keys
437
+ # NOTE! Do not merge the following line to 4.x. It has the same check in the initialize method
438
+ raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
439
+
431
440
  ranged_integer.from = from == :default ? nil : from
432
441
  ranged_integer.to = to == :default ? nil : to
433
442
  ranged_integer
@@ -546,6 +546,10 @@ module Puppet::Pops::Issues
546
546
  "Resource Override can only operate on resources, got: #{label.label(actual)}"
547
547
  end
548
548
 
549
+ DUPLICATE_PARAMETER = hard_issue :DUPLICATE_PARAMETER, :param_name do
550
+ "The parameter '#{param_name}' is declared more than once in the parameter list"
551
+ end
552
+
549
553
  RESERVED_PARAMETER = hard_issue :RESERVED_PARAMETER, :container, :param_name do
550
554
  "The parameter $#{param_name} redefines a built in parameter in #{label.the(container)}"
551
555
  end
@@ -1069,11 +1069,7 @@ class Puppet::Pops::Types::TypeCalculator
1069
1069
  to = range.to
1070
1070
  x = from.nil? ? 1 : from
1071
1071
  y = to.nil? ? TheInfinity : to
1072
- if x < y
1073
- [x, y]
1074
- else
1075
- [y, x]
1076
- end
1072
+ [x, y]
1077
1073
  end
1078
1074
 
1079
1075
  # @api private
@@ -17,6 +17,9 @@ module Puppet::Pops::Types::TypeFactory
17
17
  # @api public
18
18
  #
19
19
  def self.range(from, to)
20
+ # NOTE! Do not merge the following line to 4.x. It has the same check in the initialize method
21
+ raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
22
+
20
23
  t = Types::PIntegerType.new()
21
24
  # optimize eq with symbol (faster when it is left)
22
25
  t.from = from unless (:default == from || from == 'default')
@@ -28,6 +31,9 @@ module Puppet::Pops::Types::TypeFactory
28
31
  # @api public
29
32
  #
30
33
  def self.float_range(from, to)
34
+ # NOTE! Do not merge the following line to 4.x. It has the same check in the initialize method
35
+ raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
36
+
31
37
  t = Types::PFloatType.new()
32
38
  # optimize eq with symbol (faster when it is left)
33
39
  t.from = Float(from) unless :default == from || from.nil?
@@ -121,11 +121,7 @@ module Puppet::Pops
121
121
  def range
122
122
  f = from || NEGATIVE_INFINITY
123
123
  t = to || INFINITY
124
- if f < t
125
- [f, t]
126
- else
127
- [t,f]
128
- end
124
+ [f, t]
129
125
  end
130
126
 
131
127
  # Returns Enumerator if no block is given
@@ -133,11 +129,7 @@ module Puppet::Pops
133
129
  def each
134
130
  return self.to_enum unless block_given?
135
131
  return nil if from.nil? || to.nil?
136
- if to < from
137
- from.downto(to) {|x| yield x }
138
- else
139
- from.upto(to) {|x| yield x }
140
- end
132
+ from.upto(to) {|x| yield x }
141
133
  end
142
134
 
143
135
  def hash
@@ -212,11 +204,7 @@ module Puppet::Pops
212
204
  return [0, INFINITY] if size_type.nil?
213
205
  f = size_type.from || 0
214
206
  t = size_type.to || INFINITY
215
- if f < t
216
- [f, t]
217
- else
218
- [t,f]
219
- end
207
+ [f, t]
220
208
  end
221
209
 
222
210
  def hash
@@ -233,6 +233,7 @@ class Puppet::Pops::Validation::Checker4_0
233
233
  def check_EppExpression(o)
234
234
  if o.eContainer.is_a?(Puppet::Pops::Model::LambdaExpression)
235
235
  internal_check_no_capture(o.eContainer, o)
236
+ internal_check_parameter_name_uniqueness(o.eContainer)
236
237
  end
237
238
  end
238
239
 
@@ -327,12 +328,14 @@ class Puppet::Pops::Validation::Checker4_0
327
328
  def check_HostClassDefinition(o)
328
329
  check_NamedDefinition(o)
329
330
  internal_check_no_capture(o)
331
+ internal_check_parameter_name_uniqueness(o)
330
332
  internal_check_reserved_params(o)
331
333
  end
332
334
 
333
335
  def check_ResourceTypeDefinition(o)
334
336
  check_NamedDefinition(o)
335
337
  internal_check_no_capture(o)
338
+ internal_check_parameter_name_uniqueness(o)
336
339
  internal_check_reserved_params(o)
337
340
  end
338
341
 
@@ -366,6 +369,13 @@ class Puppet::Pops::Validation::Checker4_0
366
369
  end
367
370
  end
368
371
 
372
+ def internal_check_parameter_name_uniqueness(o)
373
+ unique = Set.new
374
+ o.parameters.each do |p|
375
+ acceptor.accept(Issues::DUPLICATE_PARAMETER, p, {:param_name => p.name}) unless unique.add?(p.name)
376
+ end
377
+ end
378
+
369
379
  def check_IfExpression(o)
370
380
  rvalue(o.test)
371
381
  end
@@ -39,6 +39,11 @@ Puppet::Type.type(:group).provide :windows_adsi do
39
39
  return '' if users.nil? or !users.kind_of?(Array)
40
40
  users = users.map do |user_name|
41
41
  sid = Puppet::Util::Windows::SID.name_to_sid_object(user_name)
42
+ if !sid
43
+ resource.debug("#{user_name} (unresolvable to SID)")
44
+ next user_name
45
+ end
46
+
42
47
  if sid.account =~ /\\/
43
48
  account, _ = Puppet::Util::Windows::ADSI::User.parse_name(sid.account)
44
49
  else
@@ -50,6 +55,10 @@ Puppet::Type.type(:group).provide :windows_adsi do
50
55
  return users.join(',')
51
56
  end
52
57
 
58
+ def member_valid?(user_name)
59
+ ! Puppet::Util::Windows::SID.name_to_sid_object(user_name).nil?
60
+ end
61
+
53
62
  def group
54
63
  @group ||= Puppet::Util::Windows::ADSI::Group.new(@resource[:name])
55
64
  end
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'puppet/provider/package'
5
5
  require 'xmlrpc/client'
6
+ require 'puppet/util/http_proxy'
6
7
 
7
8
  Puppet::Type.type(:package).provide :pip,
8
9
  :parent => ::Puppet::Provider::Package do
@@ -56,7 +57,16 @@ Puppet::Type.type(:package).provide :pip,
56
57
  # cache of PyPI's package list so this operation will always have to
57
58
  # ask the web service.
58
59
  def latest
59
- client = XMLRPC::Client.new2("http://pypi.python.org/pypi")
60
+ http_proxy_host = Puppet::Util::HttpProxy.http_proxy_host
61
+ http_proxy_port = Puppet::Util::HttpProxy.http_proxy_port
62
+ if http_proxy_host && http_proxy_port
63
+ proxy = "#{http_proxy_host}:#{http_proxy_port}"
64
+ else
65
+ # nil is acceptable
66
+ proxy = http_proxy_host
67
+ end
68
+
69
+ client = XMLRPC::Client.new2("http://pypi.python.org/pypi", proxy)
60
70
  client.http_header_extra = {"Content-Type" => "text/xml"}
61
71
  client.timeout = 10
62
72
  result = client.call("package_releases", @resource[:name])
@@ -204,6 +204,12 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
204
204
  # Read a plist, whether its format is XML or in Apple's "binary1"
205
205
  # format.
206
206
  def self.read_plist(path)
207
+ begin
208
+ return Plist::parse_xml(path)
209
+ rescue ArgumentError => detail
210
+ Puppet.debug("Error reading #{path}: #{detail}. Retrying with plutil.")
211
+ end
212
+
207
213
  begin
208
214
  Plist::parse_xml(plutil('-convert', 'xml1', '-o', '/dev/stdout', path))
209
215
  rescue Puppet::ExecutionFailure => detail
@@ -151,7 +151,11 @@ Puppet::Type.type(:service).provide :upstart, :parent => :debian do
151
151
  end
152
152
 
153
153
  def status
154
- return super if not is_upstart?
154
+ if (@resource[:hasstatus] == :false) ||
155
+ @resource[:status] ||
156
+ ! is_upstart?
157
+ return super
158
+ end
155
159
 
156
160
  output = status_exec(@resource[:name].split)
157
161
  if output =~ /start\//
@@ -387,7 +387,7 @@ class Puppet::Resource
387
387
  begin
388
388
  Puppet::DataBinding.indirection.find(
389
389
  name,
390
- :environment => scope.environment.to_s,
390
+ :environment => scope.environment,
391
391
  :variables => scope)
392
392
  rescue Puppet::DataBinding::LookupError => e
393
393
  raise Puppet::Error.new("Error from DataBinding '#{Puppet[:data_binding_terminus]}' while looking up '#{name}': #{e.message}", e)
@@ -80,7 +80,9 @@ module Puppet
80
80
 
81
81
  newproperty(:members, :array_matching => :all, :required_features => :manages_members) do
82
82
  desc "The members of the group. For directory services where group
83
- membership is stored in the group objects, not the users."
83
+ membership is stored in the group objects, not the users. Use
84
+ with auth_membership to determine whether the specified members
85
+ are inclusive or the minimum."
84
86
 
85
87
  def change_to_s(currentvalue, newvalue)
86
88
  currentvalue = currentvalue.join(",") if currentvalue != :absent
@@ -99,16 +101,26 @@ module Puppet
99
101
  def is_to_s(currentvalue)
100
102
  if provider.respond_to?(:members_to_s)
101
103
  currentvalue = '' if currentvalue.nil?
102
- return provider.members_to_s(currentvalue.split(','))
104
+ currentvalue = currentvalue.is_a?(Array) ? currentvalue : currentvalue.split(',')
105
+
106
+ return provider.members_to_s(currentvalue)
103
107
  end
104
108
 
105
109
  super(currentvalue)
106
110
  end
107
111
  alias :should_to_s :is_to_s
112
+
113
+ validate do |value|
114
+ if provider.respond_to?(:member_valid?)
115
+ return provider.member_valid?(value)
116
+ end
117
+ end
108
118
  end
109
119
 
110
120
  newparam(:auth_membership, :boolean => true, :parent => Puppet::Parameter::Boolean) do
111
- desc "whether the provider is authoritative for group membership."
121
+ desc "Whether the provider is authoritative for group membership. This
122
+ must be set to true to allow setting the group to no members with
123
+ `members => [],`."
112
124
  defaultto true
113
125
  end
114
126
 
@@ -372,7 +372,10 @@ module Puppet::Util::Windows::Security
372
372
  dacl.allow(well_known_nobody_sid, nobody_allow)
373
373
 
374
374
  # TODO: system should be first?
375
- dacl.allow(well_known_system_sid, system_allow)
375
+ flags = !isdir ? 0 :
376
+ Puppet::Util::Windows::AccessControlEntry::CONTAINER_INHERIT_ACE |
377
+ Puppet::Util::Windows::AccessControlEntry::OBJECT_INHERIT_ACE
378
+ dacl.allow(well_known_system_sid, system_allow, flags)
376
379
 
377
380
  # add inherit-only aces for child dirs and files that are created within the dir
378
381
  inherit_only = Puppet::Util::Windows::AccessControlEntry::INHERIT_ONLY_ACE
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  module Puppet
10
- PUPPETVERSION = '3.8.4'
10
+ PUPPETVERSION = '3.8.5'
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -237,6 +237,24 @@ describe "Puppet::Util::Windows::Security", :if => Puppet.features.microsoft_win
237
237
  system_aces.each do |ace|
238
238
  ace.mask.should == klass::FILE_ALL_ACCESS && ! ace.inherited?
239
239
  end
240
+
241
+ if Puppet::FileSystem.directory?(path)
242
+ system_aces.each do |ace|
243
+ ace.object_inherit?.should be_true
244
+ ace.container_inherit?.should be_true
245
+ end
246
+
247
+ # it's critically important that this file be default created
248
+ # and that this file not have it's owner / group / mode set by winsec
249
+ nested_file = File.join(path, 'nested_file')
250
+ File.new(nested_file, 'w').close
251
+
252
+ system_aces = winsec.get_aces_for_path_by_sid(nested_file, sids[:system])
253
+ # even when SYSTEM is the owner (in CI), there should be an inherited SYSTEM
254
+ system_aces.any? do |ace|
255
+ ace.mask == klass::FILE_ALL_ACCESS && ace.inherited?
256
+ end.should be_true
257
+ end
240
258
  end
241
259
 
242
260
  describe "for modes that require deny aces" do
@@ -47,15 +47,24 @@ describe Puppet::Daemon, :unless => Puppet.features.microsoft_windows? do
47
47
  let(:server) { stub("Server", :start => nil, :wait_for_shutdown => nil) }
48
48
 
49
49
  describe "when setting signal traps" do
50
- signals = {:INT => :stop, :TERM => :stop }
51
- signals.update({:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}) unless Puppet.features.microsoft_windows?
52
- signals.each do |signal, method|
53
- it "should log and call #{method} when it receives #{signal}" do
54
- Signal.expects(:trap).with(signal).yields
50
+ [:INT, :TERM].each do |signal|
51
+ it "logs a notice and exits when sent #{signal}" do
52
+ Signal.stubs(:trap).with(signal).yields
53
+ Puppet.expects(:notice).with("Caught #{signal}; exiting")
54
+ daemon.expects(:stop)
55
55
 
56
- Puppet.expects(:notice)
56
+ daemon.set_signal_traps
57
+ end
58
+ end
59
+
60
+ {:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}.each do |signal, method|
61
+ it "logs a notice and remembers to call #{method} when it receives #{signal}" do
62
+ Signal.stubs(:trap).with(signal).yields
63
+ Puppet.expects(:notice).with("Caught #{signal}; storing #{method}")
57
64
 
58
65
  daemon.set_signal_traps
66
+
67
+ expect(daemon.signals).to eq([method])
59
68
  end
60
69
  end
61
70
  end
@@ -48,6 +48,14 @@ describe Puppet::Node do
48
48
  node.parameters["environment"] = :bar
49
49
  node.environment.name.should == :bar
50
50
  end
51
+
52
+ it "should allow its environment parameter to be set by attribute after initialization" do
53
+ node = Puppet::Node.new("foo", { :parameters => { 'environment' => :foo } })
54
+ node.environment_name = :foo
55
+ node.environment = :bar
56
+ expect(node.environment_name).to eq(:bar)
57
+ expect(node.parameters['environment']).to eq(:bar)
58
+ end
51
59
  end
52
60
 
53
61
  it "can survive a round-trip through YAML" do
@@ -123,9 +123,9 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl/AccessOperator' do
123
123
  expect(evaluate(expr)).to eql(range(1,1))
124
124
  end
125
125
 
126
- it 'produces an Integer[from, <from]' do
126
+ it 'gives an error for Integer[from, <from]' do
127
127
  expr = fqr('Integer')[1,0]
128
- expect(evaluate(expr)).to eql(range(1,0))
128
+ expect{evaluate(expr)}.to raise_error(/'from' must be less or equal to 'to'/)
129
129
  end
130
130
 
131
131
  it 'produces an error for Integer[] if there are more than 2 keys' do
@@ -154,9 +154,9 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl/AccessOperator' do
154
154
  expect(evaluate(expr)).to eql(float_range(1.0,1.0))
155
155
  end
156
156
 
157
- it 'produces a Float[from, <from]' do
157
+ it 'gives an error for Float[from, <from]' do
158
158
  expr = fqr('Float')[1.0,0.0]
159
- expect(evaluate(expr)).to eql(float_range(1.0,0.0))
159
+ expect{evaluate(expr)}.to raise_error(/'from' must be less or equal to 'to'/)
160
160
  end
161
161
 
162
162
  it 'produces an error for Float[] if there are more than 2 keys' do
@@ -8,4 +8,9 @@ module ParserRspecHelper
8
8
  parser = Puppet::Pops::Parser::Parser.new()
9
9
  parser.parse_string(code)
10
10
  end
11
+
12
+ def parse_epp(code)
13
+ parser = Puppet::Pops::Parser::EppParser.new()
14
+ parser.parse_string(code)
15
+ end
11
16
  end
@@ -177,6 +177,18 @@ describe "validating 4x" do
177
177
  end
178
178
  end
179
179
 
180
+ context 'for parameter names' do
181
+ ['class', 'define'].each do |word|
182
+ it "should require that #{word} parameter names are unique" do
183
+ expect(validate(parse("#{word} foo($a = 10, $a = 20) {}"))).to have_issue(Puppet::Pops::Issues::DUPLICATE_PARAMETER)
184
+ end
185
+ end
186
+
187
+ it "should require that template parameter names are unique" do
188
+ expect(validate(parse_epp("<%-| $a, $a |-%><%= $a == doh %>"))).to have_issue(Puppet::Pops::Issues::DUPLICATE_PARAMETER)
189
+ end
190
+ end
191
+
180
192
  context 'for reserved parameter names' do
181
193
  ['name', 'title'].each do |word|
182
194
  it "produces an error when $#{word} is used as a parameter in a class" do
@@ -35,11 +35,13 @@ describe Puppet::Type.type(:group).provider(:windows_adsi), :if => Puppet.featur
35
35
  let(:user1) { stub(:account => 'user1', :domain => '.', :to_s => 'user1sid') }
36
36
  let(:user2) { stub(:account => 'user2', :domain => '.', :to_s => 'user2sid') }
37
37
  let(:user3) { stub(:account => 'user3', :domain => '.', :to_s => 'user3sid') }
38
+ let(:invalid_user) { SecureRandom.uuid }
38
39
 
39
40
  before :each do
40
41
  Puppet::Util::Windows::SID.stubs(:name_to_sid_object).with('user1').returns(user1)
41
42
  Puppet::Util::Windows::SID.stubs(:name_to_sid_object).with('user2').returns(user2)
42
43
  Puppet::Util::Windows::SID.stubs(:name_to_sid_object).with('user3').returns(user3)
44
+ Puppet::Util::Windows::SID.stubs(:name_to_sid_object).with(invalid_user).returns(nil)
43
45
  end
44
46
 
45
47
  describe "#members_insync?" do
@@ -123,6 +125,9 @@ describe Puppet::Type.type(:group).provider(:windows_adsi), :if => Puppet.featur
123
125
  it "should return a user string like DOMAIN\\USER,DOMAIN2\\USER2" do
124
126
  provider.members_to_s(['user1', 'user2']).should == '.\user1,.\user2'
125
127
  end
128
+ it "should return the username when it cannot be resolved to a SID (for the sake of resource_harness error messages)" do
129
+ expect(provider.members_to_s([invalid_user])).to eq("#{invalid_user}")
130
+ end
126
131
  end
127
132
  end
128
133
 
@@ -12,7 +12,6 @@ describe provider_class do
12
12
  @client = stub_everything('client')
13
13
  @client.stubs(:call).with('package_releases', 'real_package').returns(["1.3", "1.2.5", "1.2.4"])
14
14
  @client.stubs(:call).with('package_releases', 'fake_package').returns([])
15
- XMLRPC::Client.stubs(:new2).returns(@client)
16
15
  end
17
16
 
18
17
  describe "parse" do
@@ -118,23 +117,53 @@ describe provider_class do
118
117
  end
119
118
 
120
119
  describe "latest" do
120
+ context "connecting directly" do
121
121
 
122
- it "should find a version number for real_package" do
123
- @resource[:name] = "real_package"
124
- @provider.latest.should_not == nil
125
- end
122
+ before :each do
123
+ XMLRPC::Client.expects(:new2).with("http://pypi.python.org/pypi", nil).returns(@client)
124
+ end
126
125
 
127
- it "should not find a version number for fake_package" do
128
- @resource[:name] = "fake_package"
129
- @provider.latest.should == nil
130
- end
126
+ it "should find a version number for real_package" do
127
+ @resource[:name] = "real_package"
128
+ @provider.latest.should_not == nil
129
+ end
130
+
131
+ it "should not find a version number for fake_package" do
132
+ @resource[:name] = "fake_package"
133
+ @provider.latest.should == nil
134
+ end
135
+
136
+ it "should handle a timeout gracefully" do
137
+ @resource[:name] = "fake_package"
138
+ @client.stubs(:call).raises(Timeout::Error)
139
+ lambda { @provider.latest }.should raise_error(Puppet::Error)
140
+ end
131
141
 
132
- it "should handle a timeout gracefully" do
133
- @resource[:name] = "fake_package"
134
- @client.stubs(:call).raises(Timeout::Error)
135
- lambda { @provider.latest }.should raise_error(Puppet::Error)
136
142
  end
137
143
 
144
+ context "connecting via a proxy" do
145
+ before :each do
146
+ Puppet::Util::HttpProxy.expects(:http_proxy_host).returns 'some_host'
147
+ Puppet::Util::HttpProxy.expects(:http_proxy_port).returns 'some_port'
148
+ XMLRPC::Client.expects(:new2).with("http://pypi.python.org/pypi", "some_host:some_port").returns(@client)
149
+ end
150
+
151
+ it "should find a version number for real_package" do
152
+ @resource[:name] = "real_package"
153
+ @provider.latest.should_not == nil
154
+ end
155
+
156
+ it "should not find a version number for fake_package" do
157
+ @resource[:name] = "fake_package"
158
+ @provider.latest.should == nil
159
+ end
160
+
161
+ it "should handle a timeout gracefully" do
162
+ @resource[:name] = "fake_package"
163
+ @client.stubs(:call).raises(Timeout::Error)
164
+ lambda { @provider.latest }.should raise_error(Puppet::Error)
165
+ end
166
+ end
138
167
  end
139
168
 
140
169
  describe "install" do
@@ -274,6 +274,7 @@ describe Puppet::Type.type(:service).provider(:launchd) do
274
274
  }
275
275
  end
276
276
  let(:busted_plist_path) { '/Library/LaunchAgents/org.busted.plist' }
277
+ let(:binary_plist_path) { '/Library/LaunchAgents/org.binary.plist' }
277
278
 
278
279
  it "[17624] should warn that the plist in question is being skipped" do
279
280
  provider.expects(:launchd_paths).returns(['/Library/LaunchAgents'])
@@ -284,6 +285,8 @@ describe Puppet::Type.type(:service).provider(:launchd) do
284
285
  end
285
286
 
286
287
  it "[15929] should skip plists that plutil cannot read" do
288
+ Plist.expects(:parse_xml).with(busted_plist_path).raises(ArgumentError, 'boom')
289
+ Puppet.expects(:debug).with("Error reading #{busted_plist_path}: boom. Retrying with plutil.")
287
290
  provider.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout',
288
291
  busted_plist_path).raises(Puppet::ExecutionFailure, 'boom')
289
292
  Puppet.expects(:warning).with("Cannot read file #{busted_plist_path}; " +
@@ -291,6 +294,14 @@ describe Puppet::Type.type(:service).provider(:launchd) do
291
294
  "Details: boom")
292
295
  provider.read_plist(busted_plist_path)
293
296
  end
297
+
298
+ it "should read binary plists with plutil" do
299
+ Plist.expects(:parse_xml).with(binary_plist_path).raises(ArgumentError, 'boom')
300
+ Puppet.expects(:debug).with("Error reading #{binary_plist_path}: boom. Retrying with plutil.")
301
+ provider.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout', binary_plist_path).returns('plist')
302
+ Plist.expects(:parse_xml).with('plist').returns('plist_map')
303
+ expect(provider.read_plist(binary_plist_path)).to eq('plist_map')
304
+ end
294
305
  end
295
306
  it "should return the cached value when available" do
296
307
  provider.instance_variable_set(:@label_to_path_map, {'xx'=>'yy'})
@@ -100,6 +100,63 @@ describe Puppet::Type.type(:service).provider(:upstart) do
100
100
  provider.status.should == :running
101
101
  end
102
102
 
103
+ describe "when a special status command is specifed" do
104
+ it "should use the provided status command" do
105
+ resource = Puppet::Type.type(:service).new(:name => 'foo', :provider => :upstart, :status => '/bin/foo')
106
+ provider = provider_class.new(resource)
107
+ provider.stubs(:is_upstart?).returns(true)
108
+
109
+ provider.expects(:status_exec).with(['foo']).never
110
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => false, :combine => true)
111
+ Process::Status.any_instance.stubs(:exitstatus).returns(0)
112
+ provider.status
113
+ end
114
+
115
+ it "should return :stopped when the provided status command return non-zero" do
116
+ resource = Puppet::Type.type(:service).new(:name => 'foo', :provider => :upstart, :status => '/bin/foo')
117
+ provider = provider_class.new(resource)
118
+ provider.stubs(:is_upstart?).returns(true)
119
+
120
+ provider.expects(:status_exec).with(['foo']).never
121
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => false, :combine => true)
122
+ $CHILD_STATUS.stubs(:exitstatus).returns 1
123
+ provider.status.should == :stopped
124
+ end
125
+
126
+ it "should return :running when the provided status command return zero" do
127
+ resource = Puppet::Type.type(:service).new(:name => 'foo', :provider => :upstart, :status => '/bin/foo')
128
+ provider = provider_class.new(resource)
129
+ provider.stubs(:is_upstart?).returns(true)
130
+
131
+ provider.expects(:status_exec).with(['foo']).never
132
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => false, :combine => true)
133
+ $CHILD_STATUS.stubs(:exitstatus).returns 0
134
+ provider.status.should == :running
135
+ end
136
+ end
137
+
138
+ describe "when :hasstatus is set to false" do
139
+ it "should return :stopped if the pid can not be found" do
140
+ resource = Puppet::Type.type(:service).new(:name => 'foo', :hasstatus => false, :provider => :upstart)
141
+ provider = provider_class.new(resource)
142
+ provider.stubs(:is_upstart?).returns(true)
143
+
144
+ provider.expects(:status_exec).with(['foo']).never
145
+ provider.expects(:getpid).returns nil
146
+ provider.status.should == :stopped
147
+ end
148
+
149
+ it "should return :running if the pid can be found" do
150
+ resource = Puppet::Type.type(:service).new(:name => 'foo', :hasstatus => false, :provider => :upstart)
151
+ provider = provider_class.new(resource)
152
+ provider.stubs(:is_upstart?).returns(true)
153
+
154
+ provider.expects(:status_exec).with(['foo']).never
155
+ provider.expects(:getpid).returns 2706
156
+ provider.status.should == :running
157
+ end
158
+ end
159
+
103
160
  it "should properly handle services with 'start' in their name" do
104
161
  resource = Puppet::Type.type(:service).new(:name => "foostartbar", :provider => :upstart)
105
162
  provider = provider_class.new(resource)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.4
4
+ version: 3.8.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-03 00:00:00.000000000 Z
12
+ date: 2016-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: facter