puppet 3.7.4 → 3.7.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.

Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +11 -6
  3. data/ext/build_defaults.yaml +2 -2
  4. data/ext/systemd/puppet.service +1 -0
  5. data/lib/hiera/puppet_function.rb +71 -0
  6. data/lib/puppet.rb +12 -0
  7. data/lib/puppet/application/device.rb +22 -5
  8. data/lib/puppet/daemon.rb +13 -4
  9. data/lib/puppet/defaults.rb +27 -4
  10. data/lib/puppet/environments.rb +1 -1
  11. data/lib/puppet/error.rb +4 -0
  12. data/lib/puppet/functions.rb +118 -65
  13. data/lib/puppet/functions/assert_type.rb +5 -5
  14. data/lib/puppet/functions/each.rb +12 -12
  15. data/lib/puppet/functions/epp.rb +3 -4
  16. data/lib/puppet/functions/filter.rb +12 -12
  17. data/lib/puppet/functions/hiera.rb +29 -0
  18. data/lib/puppet/functions/hiera_array.rb +34 -0
  19. data/lib/puppet/functions/hiera_hash.rb +36 -0
  20. data/lib/puppet/functions/hiera_include.rb +50 -0
  21. data/lib/puppet/functions/inline_epp.rb +2 -3
  22. data/lib/puppet/functions/map.rb +12 -12
  23. data/lib/puppet/functions/reduce.rb +6 -6
  24. data/lib/puppet/functions/scanf.rb +3 -3
  25. data/lib/puppet/functions/slice.rb +10 -9
  26. data/lib/puppet/functions/with.rb +3 -4
  27. data/lib/puppet/graph/simple_graph.rb +5 -5
  28. data/lib/puppet/metatype/manager.rb +1 -1
  29. data/lib/puppet/node/environment.rb +1 -1
  30. data/lib/puppet/parser/ast/arithmetic_operator.rb +1 -1
  31. data/lib/puppet/parser/ast/collexpr.rb +1 -1
  32. data/lib/puppet/parser/compiler.rb +3 -3
  33. data/lib/puppet/parser/functions/create_resources.rb +1 -9
  34. data/lib/puppet/parser/functions/defined.rb +1 -1
  35. data/lib/puppet/parser/functions/hiera.rb +20 -11
  36. data/lib/puppet/parser/functions/hiera_array.rb +23 -13
  37. data/lib/puppet/parser/functions/hiera_hash.rb +25 -15
  38. data/lib/puppet/parser/functions/hiera_include.rb +20 -9
  39. data/lib/puppet/parser/functions/lookup.rb +1 -1
  40. data/lib/puppet/parser/functions/realize.rb +1 -1
  41. data/lib/puppet/parser/functions/scanf.rb +21 -12
  42. data/lib/puppet/parser/parser_factory.rb +2 -2
  43. data/lib/puppet/parser/relationship.rb +1 -1
  44. data/lib/puppet/parser/scope.rb +34 -7
  45. data/lib/puppet/pops.rb +2 -0
  46. data/lib/puppet/pops/binder/lookup.rb +24 -7
  47. data/lib/puppet/pops/binder/producers.rb +2 -2
  48. data/lib/puppet/pops/evaluator/closure.rb +1 -1
  49. data/lib/puppet/pops/evaluator/evaluator_impl.rb +109 -17
  50. data/lib/puppet/pops/evaluator/puppet_proc.rb +69 -0
  51. data/lib/puppet/pops/evaluator/runtime3_converter.rb +175 -0
  52. data/lib/puppet/pops/evaluator/runtime3_support.rb +15 -128
  53. data/lib/puppet/pops/functions/dispatch.rb +21 -17
  54. data/lib/puppet/pops/functions/dispatcher.rb +3 -3
  55. data/lib/puppet/pops/functions/function.rb +46 -14
  56. data/lib/puppet/pops/issues.rb +2 -2
  57. data/lib/puppet/pops/model/model_label_provider.rb +1 -1
  58. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  59. data/lib/puppet/pops/parser/eparser.rb +732 -724
  60. data/lib/puppet/pops/parser/heredoc_support.rb +1 -1
  61. data/lib/puppet/pops/parser/lexer2.rb +20 -22
  62. data/lib/puppet/pops/types/class_loader.rb +1 -1
  63. data/lib/puppet/pops/types/type_calculator.rb +104 -37
  64. data/lib/puppet/pops/types/type_factory.rb +1 -1
  65. data/lib/puppet/pops/types/types.rb +4 -1
  66. data/lib/puppet/pops/types/types_meta.rb +2 -2
  67. data/lib/puppet/pops/validation/checker4_0.rb +5 -3
  68. data/lib/puppet/provider/service/systemd.rb +1 -0
  69. data/lib/puppet/provider/yumrepo/inifile.rb +4 -1
  70. data/lib/puppet/resource.rb +3 -2
  71. data/lib/puppet/resource/catalog.rb +3 -2
  72. data/lib/puppet/resource/type.rb +1 -1
  73. data/lib/puppet/settings/environment_conf.rb +12 -4
  74. data/lib/puppet/type/package.rb +23 -13
  75. data/lib/puppet/util/autoload.rb +7 -7
  76. data/lib/puppet/util/errors.rb +4 -2
  77. data/lib/puppet/util/network_device/config.rb +5 -0
  78. data/lib/puppet/version.rb +1 -1
  79. data/lib/puppetx.rb +2 -2
  80. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/callee.rb +8 -0
  81. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/callee_ws.rb +8 -0
  82. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/metadata.json +9 -0
  83. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/caller.rb +5 -0
  84. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/caller_ws.rb +12 -0
  85. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/metadata.json +9 -0
  86. data/spec/integration/parser/environment_spec.rb +47 -0
  87. data/spec/integration/parser/future_compiler_spec.rb +11 -6
  88. data/spec/unit/application/device_spec.rb +52 -14
  89. data/spec/unit/daemon_spec.rb +0 -2
  90. data/spec/unit/environments_spec.rb +2 -2
  91. data/spec/unit/functions/assert_type_spec.rb +4 -25
  92. data/spec/unit/functions/hiera_spec.rb +127 -0
  93. data/spec/unit/functions/with_spec.rb +9 -4
  94. data/spec/unit/functions4_spec.rb +98 -35
  95. data/spec/unit/hiera/backend/puppet_backend_spec.rb +1 -1
  96. data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
  97. data/spec/unit/parser/functions/defined_spec.rb +5 -0
  98. data/spec/unit/parser/functions/lookup_spec.rb +5 -1
  99. data/spec/unit/parser/functions/scanf_spec.rb +30 -0
  100. data/spec/unit/parser/scope_spec.rb +5 -0
  101. data/spec/unit/pops/binder/injector_spec.rb +1 -1
  102. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +33 -5
  103. data/spec/unit/pops/loaders/loaders_spec.rb +22 -1
  104. data/spec/unit/pops/parser/lexer2_spec.rb +28 -16
  105. data/spec/unit/pops/parser/parse_heredoc_spec.rb +21 -0
  106. data/spec/unit/pops/types/type_calculator_spec.rb +141 -19
  107. data/spec/unit/pops/types/type_factory_spec.rb +2 -2
  108. data/spec/unit/pops/validator/validator_spec.rb +25 -3
  109. data/spec/unit/provider/service/systemd_spec.rb +20 -4
  110. data/spec/unit/provider/user/hpux_spec.rb +1 -1
  111. data/spec/unit/provider/yumrepo/inifile_spec.rb +1 -0
  112. data/spec/unit/settings/environment_conf_spec.rb +12 -1
  113. data/spec/unit/type/package_spec.rb +0 -20
  114. data/spec/unit/util/network_device/config_spec.rb +6 -0
  115. metadata +3422 -3405
@@ -73,7 +73,9 @@ Puppet::Type.type(:yumrepo).provide(:inifile) do
73
73
  # @return [Array<String>] All present directories that may contain yum repo configs.
74
74
  def self.reposdir(conf='/etc/yum.conf', dirs=['/etc/yum.repos.d', '/etc/yum/repos.d'])
75
75
  reposdir = find_conf_value('reposdir', conf)
76
- dirs << reposdir if reposdir
76
+ # Use directories in reposdir if they are set instead of default
77
+ dirs = reposdir.split(",").map(&:strip) if reposdir
78
+
77
79
 
78
80
  # We can't use the below due to Ruby 1.8.7
79
81
  # dirs.select! { |dir| Puppet::FileSystem.exist?(dir) }
@@ -100,6 +102,7 @@ Puppet::Type.type(:yumrepo).provide(:inifile) do
100
102
  def self.find_conf_value(value, conf='/etc/yum.conf')
101
103
  if Puppet::FileSystem.exist?(conf)
102
104
  file = Puppet::Util::IniConfig::PhysicalFile.new(conf)
105
+ file.read
103
106
  if (main = file.get_section('main'))
104
107
  main[value]
105
108
  end
@@ -211,6 +211,7 @@ class Puppet::Resource
211
211
  # @api public
212
212
  def initialize(type, title = nil, attributes = {})
213
213
  @parameters = {}
214
+ environment = attributes[:environment]
214
215
  if type.is_a?(Class) && type < Puppet::Type
215
216
  # Set the resource type to avoid an expensive `known_resource_types`
216
217
  # lookup.
@@ -441,7 +442,7 @@ class Puppet::Resource
441
442
  end
442
443
  end
443
444
 
444
- if Puppet[:parser] == 'current'
445
+ if !Puppet.future_parser?
445
446
  # If the value is an array with only one value, then
446
447
  # convert it to a single value. This is largely so that
447
448
  # the database interaction doesn't have to worry about
@@ -480,7 +481,7 @@ class Puppet::Resource
480
481
  end
481
482
 
482
483
  # Perform optional type checking
483
- if Puppet[:parser] == 'future'
484
+ if Puppet.future_parser?
484
485
  # Perform type checking
485
486
  arg_types = resource_type.argument_types
486
487
  # Parameters is a map from name, to parameter, and the parameter again has name and value
@@ -296,13 +296,14 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
296
296
  def resource(type, title = nil)
297
297
  # Always create a resource reference, so that it always
298
298
  # canonicalizes how we are referring to them.
299
+ attributes = { :environment => environment_instance }
299
300
  if title
300
- res = Puppet::Resource.new(type, title)
301
+ res = Puppet::Resource.new(type, title, attributes)
301
302
  else
302
303
  # If they didn't provide a title, then we expect the first
303
304
  # argument to be of the form 'Class[name]', which our
304
305
  # Reference class canonicalizes for us.
305
- res = Puppet::Resource.new(nil, type)
306
+ res = Puppet::Resource.new(nil, type, attributes)
306
307
  end
307
308
  res.catalog = self
308
309
  title_key = [res.type, res.title.to_s]
@@ -341,7 +341,7 @@ class Puppet::Resource::Type
341
341
  @argument_types = {}
342
342
  # Stop here if not running under future parser, the rest requires pops to be initialized
343
343
  # and that the type system is available
344
- return unless Puppet[:parser] == 'future' && name_to_type_hash
344
+ return unless Puppet.future_parser? && name_to_type_hash
345
345
  name_to_type_hash.each do |name, t|
346
346
  # catch internal errors
347
347
  unless @arguments.include?(name)
@@ -1,7 +1,7 @@
1
1
  # Configuration settings for a single directory Environment.
2
2
  # @api private
3
3
  class Puppet::Settings::EnvironmentConf
4
- VALID_SETTINGS = [:modulepath, :manifest, :config_version, :environment_timeout].freeze
4
+ VALID_SETTINGS = [:modulepath, :manifest, :config_version, :environment_timeout, :parser].freeze
5
5
 
6
6
  # Given a path to a directory environment, attempts to load and parse an
7
7
  # environment.conf in ini format, and return an EnvironmentConf instance.
@@ -37,8 +37,8 @@ class Puppet::Settings::EnvironmentConf
37
37
  # Configuration values are exactly those returned by the environment object,
38
38
  # without interpolation. This is a special case for the default configured
39
39
  # environment returned by the Puppet::Environments::StaticPrivate loader.
40
- def self.static_for(environment, environment_timeout = 0)
41
- Static.new(environment, environment_timeout)
40
+ def self.static_for(environment, parser, environment_timeout = 0)
41
+ Static.new(environment, environment_timeout, parser)
42
42
  end
43
43
 
44
44
  attr_reader :section, :path_to_env, :global_modulepath
@@ -100,6 +100,12 @@ class Puppet::Settings::EnvironmentConf
100
100
  end
101
101
  end
102
102
 
103
+ def parser
104
+ get_setting(:parser, Puppet.settings.value(:parser)) do |value|
105
+ value
106
+ end
107
+ end
108
+
103
109
  def config_version
104
110
  get_setting(:config_version) do |config_version|
105
111
  absolute(config_version)
@@ -152,10 +158,12 @@ class Puppet::Settings::EnvironmentConf
152
158
  # @api private
153
159
  class Static
154
160
  attr_reader :environment_timeout
161
+ attr_reader :parser
155
162
 
156
- def initialize(environment, environment_timeout)
163
+ def initialize(environment, environment_timeout, parser)
157
164
  @environment = environment
158
165
  @environment_timeout = environment_timeout
166
+ @parser = parser
159
167
  end
160
168
 
161
169
  def manifest
@@ -306,10 +306,19 @@ module Puppet
306
306
  end
307
307
 
308
308
  newparam(:source) do
309
- desc "Where to find the actual package. This must be a local file
310
- (or on a network file system) or a URL that your specific
311
- packaging type understands; Puppet will not retrieve files for you,
312
- although you can manage packages as `file` resources."
309
+ desc "Where to find the package file. This is only used by providers that don't
310
+ automatically download packages from a central repository. (For example:
311
+ the `yum` and `apt` providers ignore this attribute, but the `rpm` and
312
+ `dpkg` providers require it.)
313
+
314
+ Different providers accept different values for `source`. Most providers
315
+ accept paths to local files stored on the target system. Some providers
316
+ may also accept URLs or network drive paths. Puppet will not
317
+ automatically retrieve source files for you, and usually just passes the
318
+ value of `source` to the package installation command.
319
+
320
+ You can use a `file` resource if you need to manually copy package files
321
+ to the target system."
313
322
 
314
323
  validate do |value|
315
324
  provider.validate_source(value)
@@ -326,10 +335,14 @@ module Puppet
326
335
 
327
336
  newparam(:adminfile) do
328
337
  desc "A file containing package defaults for installing packages.
329
- This is currently only used on Solaris. The value will be
330
- validated according to system rules, which in the case of
331
- Solaris means that it should either be a fully qualified path
332
- or it should be in `/var/sadm/install/admin`."
338
+
339
+ This attribute is only used on Solaris. Its value should be a path to a
340
+ local file stored on the target system. Solaris's package tools expect
341
+ either an absolute file path or a relative path to a file in
342
+ `/var/sadm/install/admin`.
343
+
344
+ The value of `adminfile` will be passed directly to the `pkgadd` or
345
+ `pkgrm` command with the `-a <ADMINFILE>` option."
333
346
  end
334
347
 
335
348
  newparam(:responsefile) do
@@ -425,11 +438,8 @@ module Puppet
425
438
  newparam(:allow_virtual, :boolean => true, :parent => Puppet::Parameter::Boolean, :required_features => :virtual_packages) do
426
439
  desc 'Specifies if virtual package names are allowed for install and uninstall.'
427
440
 
428
- # In a future release, this should be defaulted to true and the below deprecation warning removed
429
- defaultto do
430
- Puppet.deprecation_warning('The package type\'s allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false.') unless value
431
- false
432
- end
441
+ # In a future release, this should be defaulted to true
442
+ defaultto false
433
443
  end
434
444
 
435
445
  autorequire(:file) do
@@ -70,11 +70,11 @@ class Puppet::Util::Autoload
70
70
  end
71
71
  end
72
72
 
73
- def loadall(path)
73
+ def loadall(path, env = nil)
74
74
  # Load every instance of everything we can find.
75
- files_to_load(path).each do |file|
75
+ files_to_load(path, env).each do |file|
76
76
  name = file.chomp(".rb")
77
- load_file(name, nil) unless loaded?(name)
77
+ load_file(name, env) unless loaded?(name)
78
78
  end
79
79
  end
80
80
 
@@ -90,8 +90,8 @@ class Puppet::Util::Autoload
90
90
  path and File.join(path, name)
91
91
  end
92
92
 
93
- def files_to_load(path)
94
- search_directories(nil).map {|dir| files_in_dir(dir, path) }.flatten.uniq
93
+ def files_to_load(path, env = nil)
94
+ search_directories(env).map {|dir| files_in_dir(dir, path) }.flatten.uniq
95
95
  end
96
96
 
97
97
  def files_in_dir(dir, path)
@@ -209,8 +209,8 @@ class Puppet::Util::Autoload
209
209
  #
210
210
  # This uses require, rather than load, so that already-loaded files don't get
211
211
  # reloaded unnecessarily.
212
- def loadall
213
- self.class.loadall(@path)
212
+ def loadall(env = nil)
213
+ self.class.loadall(@path, env)
214
214
  end
215
215
 
216
216
  def loaded?(name)
@@ -14,7 +14,7 @@ module Puppet::Util::Errors
14
14
  # Add line and file info to the supplied exception if info is available from
15
15
  # this object, is appropriately populated and the supplied exception supports
16
16
  # it. When other is supplied, the backtrace will be copied to the error
17
- # object.
17
+ # object and the 'original' will be dropped from the error.
18
18
  #
19
19
  # @param error [Exception] exception that is populated with info
20
20
  # @param other [Exception] original exception, source of backtrace info
@@ -25,7 +25,9 @@ module Puppet::Util::Errors
25
25
  error.original ||= other if error.respond_to?(:original=)
26
26
 
27
27
  error.set_backtrace(other.backtrace) if other and other.respond_to?(:backtrace)
28
-
28
+ # It is not meaningful to keep the wrapped exception since its backtrace has already
29
+ # been adopted by the error. (The instance variable is private for good reasons).
30
+ error.instance_variable_set(:@original, nil)
29
31
  error
30
32
  end
31
33
 
@@ -82,6 +82,11 @@ class Puppet::Util::NetworkDevice::Config
82
82
  when "type"
83
83
  device.provider = value
84
84
  when "url"
85
+ begin
86
+ URI.parse(value)
87
+ rescue URI::InvalidURIError
88
+ raise Puppet::Error, "#{value} is an invalid url"
89
+ end
85
90
  device.url = value
86
91
  when "debug"
87
92
  device.options[:debug] = true
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  module Puppet
10
- PUPPETVERSION = '3.7.4'
10
+ PUPPETVERSION = '3.7.5'
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -31,7 +31,7 @@ module Puppetx
31
31
  # @api public
32
32
  module Puppet
33
33
 
34
- if ::Puppet[:binder] || ::Puppet[:parser] == 'future'
34
+ if ::Puppet[:binder] || ::Puppet.future_parser?
35
35
  # Extension-points are registered here:
36
36
  # - If in a Ruby submodule it is best to create it here
37
37
  # - The class does not have to be required; it will be auto required when the binder
@@ -68,7 +68,7 @@ module Puppetx
68
68
 
69
69
  # @api public
70
70
  module SyntaxCheckers
71
- if ::Puppet[:binder] || ::Puppet[:parser] == 'future'
71
+ if ::Puppet[:binder] || ::Puppet.future_parser?
72
72
 
73
73
  # Classes in this name-space are lazily loaded as they may be overridden and/or never used
74
74
  # (Lazy loading is done by binding to the name of a class instead of a Class instance).
@@ -0,0 +1,8 @@
1
+ module Puppet::Parser::Functions
2
+ newfunction(:callee, :type => :rvalue, :doc => <<-EOS
3
+ A function using the 3x API
4
+ EOS
5
+ ) do |arguments|
6
+ "usee::callee() got '#{arguments[0]}'"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Puppet::Parser::Functions
2
+ newfunction(:callee_ws, :type => :rvalue, :doc => <<-EOS
3
+ A function using the 3x API
4
+ EOS
5
+ ) do |arguments|
6
+ "usee::callee_ws() got '#{self['passed_in_scope']}'"
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "test-usee",
3
+ "author": "test",
4
+ "description": "",
5
+ "license": "",
6
+ "source": "",
7
+ "version": "1.0.0",
8
+ "dependencies": []
9
+ }
@@ -0,0 +1,5 @@
1
+ Puppet::Functions.create_function(:'user::caller') do
2
+ def caller()
3
+ call_function('callee', 'first') + ' - ' + call_function('callee', 'second')
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ Puppet::Functions.create_function(:'user::caller_ws', Puppet::Functions::InternalFunction) do
2
+ dispatch :caller_ws do
3
+ scope_param
4
+ param 'String', :value
5
+ end
6
+
7
+ def caller_ws(scope, value)
8
+ scope = scope.compiler.newscope(scope)
9
+ scope['passed_in_scope'] = value
10
+ call_function_with_scope(scope, 'callee_ws')
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "test-user",
3
+ "author": "test",
4
+ "description": "",
5
+ "license": "",
6
+ "source": "",
7
+ "version": "1.0.0",
8
+ "dependencies": [{ "name": "test/usee" }]
9
+ }
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A parser environment setting" do
4
+
5
+ let(:confdir) { Puppet[:confdir] }
6
+ let(:environmentpath) { File.expand_path("envdir", confdir) }
7
+ let(:testingdir) { File.join(environmentpath, "testing") }
8
+
9
+ before(:each) do
10
+ FileUtils.mkdir_p(testingdir)
11
+ end
12
+
13
+ it "selects the given parser when compiling" do
14
+ manifestsdir = File.expand_path("manifests", confdir)
15
+ FileUtils.mkdir_p(manifestsdir)
16
+
17
+ File.open(File.join(testingdir, "environment.conf"), "w") do |f|
18
+ f.puts(<<-ENVCONF)
19
+ parser='future'
20
+ manifest =#{manifestsdir}
21
+ ENVCONF
22
+ end
23
+
24
+ File.open(File.join(confdir, "puppet.conf"), "w") do |f|
25
+ f.puts(<<-EOF)
26
+ environmentpath=#{environmentpath}
27
+ parser='current'
28
+ EOF
29
+ end
30
+
31
+ File.open(File.join(manifestsdir, "site.pp"), "w") do |f|
32
+ f.puts("notice( [1,2,3].map |$x| { $x*10 })")
33
+ end
34
+
35
+ expect { a_catalog_compiled_for_environment('testing') }.to_not raise_error
36
+ end
37
+
38
+ def a_catalog_compiled_for_environment(envname)
39
+ Puppet.initialize_settings
40
+ expect(Puppet[:environmentpath]).to eq(environmentpath)
41
+ node = Puppet::Node.new('testnode', :environment => 'testing')
42
+ expect(node.environment).to eq(Puppet.lookup(:environments).get('testing'))
43
+ Puppet.override(:current_environment => Puppet.lookup(:environments).get('testing')) do
44
+ Puppet::Parser::Compiler.compile(node)
45
+ end
46
+ end
47
+ end
@@ -600,12 +600,17 @@ describe "Puppet::Parser::Compiler" do
600
600
  expect(catalog).to have_resource("Notify[value second]")
601
601
  end
602
602
 
603
- it 'denies when missing required arguments' do
604
- expect do
605
- compile_to_catalog(<<-MANIFEST)
606
- with(1) |$x, $y| { }
607
- MANIFEST
608
- end.to raise_error(/Parameter \$y is required but no value was given/m)
603
+ # Conditinoally left out for Ruby 1.8.x since the Proc created for the expected number of arguments will accept
604
+ # a call with fewer arguments and then pass all arguments to the closure. The closure then receives an argument
605
+ # array of correct size with nil values instead of an array with too few arguments
606
+ unless RUBY_VERSION[0,3] == '1.8'
607
+ it 'denies when missing required arguments' do
608
+ expect do
609
+ compile_to_catalog(<<-MANIFEST)
610
+ with(1) |$x, $y| { }
611
+ MANIFEST
612
+ end.to raise_error(/Parameter \$y is required but no value was given/m)
613
+ end
609
614
  end
610
615
 
611
616
  it 'accepts anything when parameters are untyped' do
@@ -126,7 +126,6 @@ describe Puppet::Application::Device do
126
126
  describe "during setup" do
127
127
  before :each do
128
128
  @device.options.stubs(:[])
129
- Puppet.stubs(:info)
130
129
  Puppet[:libdir] = "/dev/null/lib"
131
130
  Puppet::SSL::Host.stubs(:ca_location=)
132
131
  Puppet::Transaction::Report.indirection.stubs(:terminus_class=)
@@ -271,6 +270,7 @@ describe Puppet::Application::Device do
271
270
  before :each do
272
271
  @device.options.stubs(:[]).with(:fingerprint).returns(false)
273
272
  Puppet.stubs(:notice)
273
+ @device.options.stubs(:[]).with(:detailed_exitcodes).returns(false)
274
274
  @device.options.stubs(:[]).with(:client)
275
275
  Puppet::Util::NetworkDevice::Config.stubs(:devices).returns({})
276
276
  end
@@ -283,7 +283,7 @@ describe Puppet::Application::Device do
283
283
  it "should get the device list" do
284
284
  device_hash = stub_everything 'device hash'
285
285
  Puppet::Util::NetworkDevice::Config.expects(:devices).returns(device_hash)
286
- @device.main
286
+ expect { @device.main }.to exit_with 1
287
287
  end
288
288
 
289
289
  it "should exit if the device list is empty" do
@@ -296,8 +296,8 @@ describe Puppet::Application::Device do
296
296
  Puppet[:confdir] = make_absolute("/dummy")
297
297
  Puppet[:certname] = "certname"
298
298
  @device_hash = {
299
- "device1" => OpenStruct.new(:name => "device1", :url => "url", :provider => "cisco"),
300
- "device2" => OpenStruct.new(:name => "device2", :url => "url", :provider => "cisco"),
299
+ "device1" => OpenStruct.new(:name => "device1", :url => "ssh://user:pass@testhost", :provider => "cisco"),
300
+ "device2" => OpenStruct.new(:name => "device2", :url => "https://user:pass@testhost/some/path", :provider => "rest"),
301
301
  }
302
302
  Puppet::Util::NetworkDevice::Config.stubs(:devices).returns(@device_hash)
303
303
  Puppet.stubs(:[]=)
@@ -310,38 +310,76 @@ describe Puppet::Application::Device do
310
310
 
311
311
  it "should set vardir to the device vardir" do
312
312
  Puppet.expects(:[]=).with(:vardir, make_absolute("/dummy/devices/device1"))
313
- @device.main
313
+ expect { @device.main }.to exit_with 1
314
314
  end
315
315
 
316
316
  it "should set confdir to the device confdir" do
317
317
  Puppet.expects(:[]=).with(:confdir, make_absolute("/dummy/devices/device1"))
318
- @device.main
318
+ expect { @device.main }.to exit_with 1
319
319
  end
320
320
 
321
321
  it "should set certname to the device certname" do
322
322
  Puppet.expects(:[]=).with(:certname, "device1")
323
323
  Puppet.expects(:[]=).with(:certname, "device2")
324
- @device.main
324
+ expect { @device.main }.to exit_with 1
325
325
  end
326
326
 
327
327
  it "should make sure all the required folders and files are created" do
328
328
  Puppet.settings.expects(:use).with(:main, :agent, :ssl).twice
329
- @device.main
329
+ expect { @device.main }.to exit_with 1
330
330
  end
331
331
 
332
332
  it "should initialize the device singleton" do
333
333
  Puppet::Util::NetworkDevice.expects(:init).with(@device_hash["device1"]).then.with(@device_hash["device2"])
334
- @device.main
334
+ expect { @device.main }.to exit_with 1
335
+ end
336
+
337
+ it "should print the device url scheme, host, and port" do
338
+ Puppet.expects(:info).with "starting applying configuration to device1 at ssh://testhost"
339
+ Puppet.expects(:info).with "starting applying configuration to device2 at https://testhost:443/some/path"
340
+ expect { @device.main }.to exit_with 1
335
341
  end
336
342
 
337
343
  it "should setup the SSL context" do
338
344
  @device.expects(:setup_host).twice
339
- @device.main
345
+ expect { @device.main }.to exit_with 1
340
346
  end
341
347
 
342
348
  it "should launch a configurer for this device" do
343
349
  @configurer.expects(:run).twice
344
- @device.main
350
+ expect { @device.main }.to exit_with 1
351
+ end
352
+
353
+ it "exits 1 when configurer raises error" do
354
+ @configurer.stubs(:run).raises(Puppet::Error).then.returns(0)
355
+ expect { @device.main }.to exit_with 1
356
+ end
357
+
358
+ it "exits 0 when run happens without puppet errors but with failed run" do
359
+ @configurer.stubs(:run).returns(6,2)
360
+ expect { @device.main }.to exit_with 0
361
+ end
362
+
363
+ it "exits 2 when --detailed-exitcodes and successful runs" do
364
+ @device.options.stubs(:[]).with(:detailed_exitcodes).returns(true)
365
+ @configurer.stubs(:run).returns(0,2)
366
+ expect { @device.main }.to exit_with 2
367
+ end
368
+
369
+ it "exits 1 when --detailed-exitcodes and failed parse" do
370
+ @configurer = stub_everything 'configurer'
371
+ Puppet::Configurer.stubs(:new).returns(@configurer)
372
+ @device.options.stubs(:[]).with(:detailed_exitcodes).returns(true)
373
+ @configurer.stubs(:run).returns(6,1)
374
+ expect { @device.main }.to exit_with 7
375
+ end
376
+
377
+ it "exits 6 when --detailed-exitcodes and failed run" do
378
+ @configurer = stub_everything 'configurer'
379
+ Puppet::Configurer.stubs(:new).returns(@configurer)
380
+ @device.options.stubs(:[]).with(:detailed_exitcodes).returns(true)
381
+ @configurer.stubs(:run).returns(6,2)
382
+ expect { @device.main }.to exit_with 6
345
383
  end
346
384
 
347
385
  [:vardir, :confdir].each do |setting|
@@ -369,7 +407,7 @@ describe Puppet::Application::Device do
369
407
  end
370
408
 
371
409
 
372
- @device.main
410
+ expect { @device.main }.to exit_with 1
373
411
 
374
412
  expect(found_devices).to eq(all_devices)
375
413
  end
@@ -399,7 +437,7 @@ describe Puppet::Application::Device do
399
437
  end
400
438
 
401
439
 
402
- @device.main
440
+ expect { @device.main }.to exit_with 1
403
441
 
404
442
  # make sure that we were called with each of the defined devices
405
443
  expect(found_devices).to eq(all_devices)
@@ -408,7 +446,7 @@ describe Puppet::Application::Device do
408
446
  it "should expire all cached attributes" do
409
447
  Puppet::SSL::Host.expects(:reset).twice
410
448
 
411
- @device.main
449
+ expect { @device.main }.to exit_with 1
412
450
  end
413
451
  end
414
452
  end