puppet 6.0.5 → 6.0.7

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +30 -0
  3. data/Gemfile.lock +14 -14
  4. data/lib/puppet.rb +4 -4
  5. data/lib/puppet/application.rb +1 -1
  6. data/lib/puppet/application/filebucket.rb +6 -1
  7. data/lib/puppet/configurer.rb +6 -6
  8. data/lib/puppet/confine/boolean.rb +45 -0
  9. data/lib/puppet/confine/false.rb +7 -1
  10. data/lib/puppet/confine/true.rb +7 -1
  11. data/lib/puppet/defaults.rb +21 -29
  12. data/lib/puppet/functions/call.rb +2 -1
  13. data/lib/puppet/network/http/connection.rb +15 -5
  14. data/lib/puppet/pops/issues.rb +4 -0
  15. data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +60 -4
  16. data/lib/puppet/pops/model/factory.rb +38 -4
  17. data/lib/puppet/pops/parser/egrammar.ra +2 -2
  18. data/lib/puppet/pops/parser/heredoc_support.rb +17 -7
  19. data/lib/puppet/pops/parser/lexer2.rb +6 -1
  20. data/lib/puppet/pops/parser/locator.rb +106 -86
  21. data/lib/puppet/pops/parser/parser_support.rb +11 -2
  22. data/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  23. data/lib/puppet/provider/file/windows.rb +49 -1
  24. data/lib/puppet/provider/group/windows_adsi.rb +4 -1
  25. data/lib/puppet/provider/package/windows.rb +5 -1
  26. data/lib/puppet/provider/service/upstart.rb +16 -6
  27. data/lib/puppet/settings.rb +10 -5
  28. data/lib/puppet/transaction.rb +8 -6
  29. data/lib/puppet/transaction/resource_harness.rb +1 -0
  30. data/lib/puppet/type/exec.rb +27 -5
  31. data/lib/puppet/type/file/mode.rb +6 -1
  32. data/lib/puppet/type/filebucket.rb +12 -8
  33. data/lib/puppet/util/command_line.rb +5 -1
  34. data/lib/puppet/util/log.rb +7 -2
  35. data/lib/puppet/util/pidlock.rb +14 -1
  36. data/lib/puppet/util/windows/process.rb +73 -5
  37. data/lib/puppet/util/windows/security.rb +29 -8
  38. data/lib/puppet/version.rb +1 -1
  39. data/locales/ja/puppet.po +149 -132
  40. data/locales/puppet.pot +197 -148
  41. data/man/man5/puppet.conf.5 +14 -6
  42. data/man/man8/puppet-agent.8 +1 -1
  43. data/man/man8/puppet-apply.8 +1 -1
  44. data/man/man8/puppet-catalog.8 +1 -1
  45. data/man/man8/puppet-config.8 +1 -1
  46. data/man/man8/puppet-describe.8 +1 -1
  47. data/man/man8/puppet-device.8 +1 -1
  48. data/man/man8/puppet-doc.8 +1 -1
  49. data/man/man8/puppet-epp.8 +1 -1
  50. data/man/man8/puppet-facts.8 +1 -1
  51. data/man/man8/puppet-filebucket.8 +6 -2
  52. data/man/man8/puppet-generate.8 +1 -1
  53. data/man/man8/puppet-help.8 +1 -1
  54. data/man/man8/puppet-key.8 +1 -1
  55. data/man/man8/puppet-lookup.8 +1 -1
  56. data/man/man8/puppet-man.8 +1 -1
  57. data/man/man8/puppet-module.8 +1 -1
  58. data/man/man8/puppet-node.8 +1 -1
  59. data/man/man8/puppet-parser.8 +1 -1
  60. data/man/man8/puppet-plugin.8 +1 -1
  61. data/man/man8/puppet-report.8 +1 -1
  62. data/man/man8/puppet-resource.8 +1 -1
  63. data/man/man8/puppet-script.8 +1 -1
  64. data/man/man8/puppet-ssl.8 +1 -1
  65. data/man/man8/puppet-status.8 +1 -1
  66. data/man/man8/puppet.8 +2 -2
  67. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load2.rb +11 -0
  68. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load3.rb +11 -0
  69. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load4.rb +11 -0
  70. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load5.rb +12 -0
  71. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/good_func_load.rb +9 -0
  72. data/spec/integration/provider/file/windows_spec.rb +162 -0
  73. data/spec/integration/type/file_spec.rb +0 -19
  74. data/spec/unit/application_spec.rb +8 -1
  75. data/spec/unit/configurer_spec.rb +6 -7
  76. data/spec/unit/confine/false_spec.rb +27 -0
  77. data/spec/unit/confine/true_spec.rb +27 -0
  78. data/spec/unit/defaults_spec.rb +0 -14
  79. data/spec/unit/network/http/connection_spec.rb +1 -1
  80. data/spec/unit/pops/loaders/loaders_spec.rb +70 -3
  81. data/spec/unit/pops/parser/locator_spec.rb +45 -0
  82. data/spec/unit/pops/parser/parse_heredoc_spec.rb +111 -15
  83. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +9 -0
  84. data/spec/unit/provider/group/windows_adsi_spec.rb +7 -1
  85. data/spec/unit/provider/package/windows_spec.rb +12 -1
  86. data/spec/unit/provider/service/systemd_spec.rb +7 -5
  87. data/spec/unit/settings_spec.rb +36 -0
  88. data/spec/unit/transaction/resource_harness_spec.rb +26 -0
  89. data/spec/unit/transaction_spec.rb +29 -0
  90. data/spec/unit/type/exec_spec.rb +47 -0
  91. data/spec/unit/type/filebucket_spec.rb +8 -6
  92. data/spec/unit/util/command_line_spec.rb +23 -2
  93. data/spec/unit/util/execution_spec.rb +2 -2
  94. data/spec/unit/util/log_spec.rb +15 -0
  95. data/spec/unit/util/pidlock_spec.rb +21 -1
  96. data/spec/unit/util/storage_spec.rb +19 -19
  97. metadata +16 -3
  98. data/MAINTAINERS +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e7c2bc0111b2e033b65c4bcb206af53954e69805812cc1ffdaf5ae103f43025
4
- data.tar.gz: 8f0572d225fd59f44cb7a9f3ace27cf00dc89be129d463a68d27a95260b69e88
3
+ metadata.gz: bdb0f821f583cdd5b960e8cc3da5d7d3282b65b88dd916e750f4ea9e905cb378
4
+ data.tar.gz: 88c1f38b1391d7d3891fffc293ffb710211a39170b004dd48c3c2842e7242fbe
5
5
  SHA512:
6
- metadata.gz: 0d52140a9090bd3fa9a1602851d5db2aff0af29acd1dad574d988bdd1c716842e08da3ce9b20af5e38bfd8739033d1bb6353bdff86a94894aecf513a7ac3d896
7
- data.tar.gz: fcbb5ca85c2d6796c3b454f1bb2ed0361b4b96d52a443f8458dca65b83d94c7a253ab4af64bf379c0cf41c70a5c2d805a56cf157a034e6c7a934546c622df570
6
+ metadata.gz: 258a0a46db0416862963aa7a5da9c3181dcb4872ca78b9302e407dd1eac5946a68eca67273bea249644734da38c7b910b60734abf6fbcfefe0560df5889dada9
7
+ data.tar.gz: 7274911a1608d735c3b6e2bb98254325ec72d431573a7d222796bf75299a9dc0c64ed1a0b68685de31e9b105811c18ebdac4713728b4003f36c80c01bfade482
@@ -0,0 +1,30 @@
1
+ # default to platform-core
2
+ * @puppetlabs/platform-core
3
+
4
+ # platform-os
5
+ /lib/puppet/type/group @puppetlabs/platform-os
6
+ /lib/puppet/type/package @puppetlabs/platform-os
7
+ /lib/puppet/type/service @puppetlabs/platform-os
8
+ /lib/puppet/type/user @puppetlabs/platform-os
9
+ /lib/puppet/provider/group @puppetlabs/platform-os
10
+ /lib/puppet/provider/package @puppetlabs/platform-os
11
+ /lib/puppet/provider/service @puppetlabs/platform-os
12
+ /lib/puppet/provider/user @puppetlabs/platform-os
13
+
14
+ # language
15
+ /lib/puppet/datatypes @puppetlabs/language
16
+ /lib/puppet/functions @puppetlabs/language
17
+ /lib/puppet/pal @puppetlabs/language
18
+ /lib/puppet/parser @puppetlabs/language
19
+ /lib/puppet/pops @puppetlabs/language
20
+ /lib/puppet/syntax_checkers @puppetlabs/language
21
+
22
+ # puppet device
23
+ /lib/puppet/application/device.rb @puppetlabs/networking
24
+ /lib/puppet/util/network_device @puppetlabs/networking
25
+
26
+ # puppet module
27
+ /lib/puppet/application/module.rb @puppetlabs/pdk
28
+ /lib/puppet/face/module @puppetlabs/pdk
29
+ /lib/puppet/forge @puppetlabs/pdk
30
+ /lib/puppet/module_tool @puppetlabs/pdk
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- puppet (6.0.5)
4
+ puppet (6.0.7)
5
5
  CFPropertyList (~> 2.2)
6
6
  facter (>= 2.4.0, < 4)
7
7
  fast_gettext (~> 1.1.2)
@@ -15,7 +15,7 @@ GEM
15
15
  remote: https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/
16
16
  specs:
17
17
  CFPropertyList (2.3.6)
18
- addressable (2.5.2)
18
+ addressable (2.6.0)
19
19
  public_suffix (>= 2.0.2, < 4.0)
20
20
  artifactory (2.8.2)
21
21
  ast (2.4.0)
@@ -34,9 +34,9 @@ GEM
34
34
  locale
35
35
  hashdiff (0.3.8)
36
36
  hiera (3.5.0)
37
- hiera-eyaml (2.1.0)
37
+ hiera-eyaml (3.0.0)
38
38
  highline (~> 1.6.19)
39
- trollop (~> 2.0)
39
+ optimist
40
40
  highline (1.6.21)
41
41
  hocon (1.2.5)
42
42
  hpricot (0.8.6)
@@ -50,23 +50,24 @@ GEM
50
50
  minitar (0.8)
51
51
  mocha (1.5.0)
52
52
  metaclass (~> 0.0.1)
53
- msgpack (1.2.6)
53
+ msgpack (1.2.9)
54
54
  multi_json (1.13.1)
55
55
  mustache (1.1.0)
56
- packaging (0.99.21)
56
+ optimist (3.0.0)
57
+ packaging (0.99.24)
57
58
  artifactory (~> 2)
58
59
  rake (~> 12.3)
59
- parallel (1.12.1)
60
- parser (2.5.3.0)
60
+ parallel (1.14.0)
61
+ parser (2.6.2.0)
61
62
  ast (~> 2.4.0)
62
63
  powerpack (0.1.2)
63
64
  pry (0.12.2)
64
65
  coderay (~> 1.1.0)
65
66
  method_source (~> 0.9.0)
66
67
  public_suffix (3.0.3)
67
- puppet-resource_api (1.6.2)
68
+ puppet-resource_api (1.8.1)
68
69
  hocon (>= 1.0)
69
- puppetserver-ca (1.2.1)
70
+ puppetserver-ca (1.3.1)
70
71
  facter (>= 2.0.1, < 4)
71
72
  racc (1.4.9)
72
73
  rainbow (2.2.2)
@@ -107,17 +108,16 @@ GEM
107
108
  rubocop (~> 0.49.0)
108
109
  ruby-prof (0.17.0)
109
110
  ruby-progressbar (1.10.0)
110
- safe_yaml (1.0.4)
111
+ safe_yaml (1.0.5)
111
112
  semantic_puppet (1.0.2)
112
113
  text (1.3.1)
113
- trollop (2.9.9)
114
- unicode-display_width (1.4.1)
114
+ unicode-display_width (1.5.0)
115
115
  vcr (2.9.3)
116
116
  webmock (1.24.6)
117
117
  addressable (>= 2.3.6)
118
118
  crack (>= 0.3.2)
119
119
  hashdiff
120
- yard (0.9.16)
120
+ yard (0.9.18)
121
121
 
122
122
  PLATFORMS
123
123
  ruby
@@ -138,14 +138,14 @@ module Puppet
138
138
  # @api public
139
139
  # @param args [Array<String>] the command line arguments to use for initialization
140
140
  # @return [void]
141
- def self.initialize_settings(args = [])
142
- do_initialize_settings_for_run_mode(:user, args)
141
+ def self.initialize_settings(args = [], require_config = true)
142
+ do_initialize_settings_for_run_mode(:user, args, require_config)
143
143
  end
144
144
 
145
145
  # private helper method to provide the implementation details of initializing for a run mode,
146
146
  # but allowing us to control where the deprecation warning is issued
147
- def self.do_initialize_settings_for_run_mode(run_mode, args)
148
- Puppet.settings.initialize_global_settings(args)
147
+ def self.do_initialize_settings_for_run_mode(run_mode, args, require_config = true)
148
+ Puppet.settings.initialize_global_settings(args, require_config)
149
149
  run_mode = Puppet::Util::RunMode[run_mode]
150
150
  Puppet.settings.initialize_app_defaults(Puppet::Settings.app_defaults_for_run_mode(run_mode))
151
151
  Puppet.push_context(Puppet.base_context(Puppet.settings), "Initial context after settings initialization")
@@ -425,7 +425,7 @@ class Application
425
425
  Puppet::Util::Log.newdestination(arg)
426
426
  options[:setdest] = true
427
427
  rescue => detail
428
- Puppet.log_exception(detail)
428
+ Puppet.log_and_raise(detail, _("Could not set logdest to %{dest}.") % { dest: arg })
429
429
  end
430
430
  end
431
431
 
@@ -107,8 +107,13 @@ configuration options can also be generated by running puppet with
107
107
  information and the bucket located at the '$bucketdir' setting
108
108
  by default.
109
109
 
110
+ * --server_list:
111
+ A list of comma seperated servers; only the first entry is used for file storage.
112
+ This setting takes precidence over `server`.
113
+
110
114
  * --server:
111
- The server to send the file to, instead of locally.
115
+ The server to use for file storage. This setting is only used if `server_list`
116
+ is not set.
112
117
 
113
118
  * --todate:
114
119
  (list only) Select bucket files until 'todate'.
@@ -226,13 +226,13 @@ class Puppet::Configurer
226
226
  # mode. We shouldn't try to do any failover in that case.
227
227
  if options[:catalog].nil? && do_failover
228
228
  server, port = find_functional_server
229
+ if server.nil?
230
+ raise Puppet::Error, _("Could not select a functional puppet master from server_list: '%{server_list}'") % { server_list: Puppet[:server_list] }
231
+ else
232
+ Puppet.debug _("Selected puppet server: %{server}:%{port}") % { server: server, port: port }
233
+ report.master_used = "#{server}:#{port}"
234
+ end
229
235
  Puppet.override(server: server, serverport: port) do
230
- if server
231
- Puppet.debug _("Selected puppet server: %{server}:%{port}") % { server: server, port: port }
232
- report.master_used = "#{server}:#{port}"
233
- else
234
- Puppet.warning _("Could not select a functional puppet server")
235
- end
236
236
  completed = run_internal(options)
237
237
  end
238
238
  else
@@ -0,0 +1,45 @@
1
+ require 'puppet/confine'
2
+
3
+ # Common module for the Boolean confines. It currently
4
+ # contains just enough code to implement PUP-9336.
5
+ class Puppet::Confine
6
+ module Boolean
7
+ # Returns the passing value for the Boolean confine.
8
+ def passing_value
9
+ raise NotImplementedError, "The Boolean confine %{confine} must provide the passing value." % { confine: self.class.name }
10
+ end
11
+
12
+ # The Boolean confines 'true' and 'false' let the user specify
13
+ # two types of values:
14
+ # * A lambda for lazy evaluation. This would be something like
15
+ # confine :true => lambda { true }
16
+ #
17
+ # * A single Boolean value, or an array of Boolean values. This would
18
+ # be something like
19
+ # confine :true => true OR confine :true => [true, false, false, true]
20
+ #
21
+ # This override distinguishes between the two cases.
22
+ def values
23
+ # Note that Puppet::Confine's constructor ensures that @values
24
+ # will always be an array, even if a lambda's passed in. This is
25
+ # why we have the length == 1 check.
26
+ unless @values.length == 1 && @values.first.respond_to?(:call)
27
+ return @values
28
+ end
29
+
30
+ # We have a lambda. Here, we want to enforce "cache positive"
31
+ # behavior, which is to cache the result _if_ it evaluates to
32
+ # the passing value (i.e. the class name).
33
+
34
+ return @cached_value unless @cached_value.nil?
35
+
36
+ # Double negate to coerce the value into a Boolean
37
+ calculated_value = !! @values.first.call
38
+ if calculated_value == passing_value
39
+ @cached_value = [calculated_value]
40
+ end
41
+
42
+ [calculated_value]
43
+ end
44
+ end
45
+ end
@@ -1,6 +1,12 @@
1
- require 'puppet/confine'
1
+ require 'puppet/confine/boolean'
2
2
 
3
3
  class Puppet::Confine::False < Puppet::Confine
4
+ include Puppet::Confine::Boolean
5
+
6
+ def passing_value
7
+ false
8
+ end
9
+
4
10
  def self.summarize(confines)
5
11
  confines.inject(0) { |count, confine| count + confine.summary }
6
12
  end
@@ -1,6 +1,12 @@
1
- require 'puppet/confine'
1
+ require 'puppet/confine/boolean'
2
2
 
3
3
  class Puppet::Confine::True < Puppet::Confine
4
+ include Puppet::Confine::Boolean
5
+
6
+ def passing_value
7
+ true
8
+ end
9
+
4
10
  def self.summarize(confines)
5
11
  confines.inject(0) { |count, confine| count + confine.summary }
6
12
  end
@@ -922,21 +922,21 @@ EOT
922
922
  Whether certificate revocation checking should be enabled, and what level of
923
923
  checking should be performed.
924
924
 
925
- When certificate revocation is enabled Puppet expects the contents of its CRL
926
- to be one or more PEM encoded CRLs concatenated together. When using a cert
927
- bundle CRLs for all CAs in the chain of trust must be included in the crl file
928
- with the first CRL listed being for the root of the chain, the last being for
929
- the leaf CA.
925
+ When certificate revocation is enabled, Puppet expects the contents of its CRL
926
+ to be one or more PEM-encoded CRLs concatenated together. When using a cert
927
+ bundle, CRLs for all CAs in the chain of trust must be included in the crl file.
928
+ The chain should be ordered from least to most authoritative, with the first CRL
929
+ listed being for the root of the chain and the last being for the leaf CA.
930
930
 
931
- When certificate_revocation is set to 'true' or 'chain', Puppet will ensure
931
+ When certificate_revocation is set to 'true' or 'chain', Puppet ensures
932
932
  that each CA in the chain of trust has not been revoked by its issuing CA.
933
933
 
934
- When certificate_revocation is set to 'leaf', Puppet will verify certs against
935
- the issuing CA's revocation list but not verify the revocation status of the
936
- issuing CA or any CA above it within the chain of trust.
934
+ When certificate_revocation is set to 'leaf', Puppet verifies certs against
935
+ the issuing CA's revocation list, but it does not verify the revocation status
936
+ of the issuing CA or any CA above it within the chain of trust.
937
937
 
938
- When certificate_revocation is set to 'false', Puppet will disable all
939
- certificate revocation checking and will not attempt to download the CRL.
938
+ When certificate_revocation is set to 'false', Puppet disables all
939
+ certificate revocation checking and does not attempt to download the CRL.
940
940
  EOT
941
941
  },
942
942
  :digest_algorithm => {
@@ -1452,30 +1452,12 @@ EOT
1452
1452
  :server => {
1453
1453
  :default => "puppet",
1454
1454
  :desc => "The puppet master server to which the puppet agent should connect.",
1455
- :call_hook => :on_initialize_and_write,
1456
- :hook => proc { |value|
1457
- if Puppet.settings.set_by_config?(:server) && Puppet.settings.set_by_config?(:server_list)
1458
- #TRANSLATOR 'server' and 'server_list' are setting names and should not be translated
1459
- message = _('Attempted to set both server and server_list.')
1460
- message += ' ' + _('Server setting will not be used.')
1461
- Puppet.deprecation_warning(message, :SERVER_DUPLICATION)
1462
- end
1463
- }
1464
1455
  },
1465
1456
  :server_list => {
1466
1457
  :default => [],
1467
1458
  :type => :server_list,
1468
1459
  :desc => "The list of puppet master servers to which the puppet agent should connect,
1469
1460
  in the order that they will be tried.",
1470
- :call_hook => :on_initialize_and_write,
1471
- :hook => proc { |value|
1472
- if Puppet.settings.set_by_config?(:server) && Puppet.settings.set_by_config?(:server_list)
1473
- #TRANSLATOR 'server' and 'server_list' are setting names and should not be translated
1474
- message = _('Attempted to set both server and server_list.')
1475
- message += ' ' + _('Server setting will not be used.')
1476
- Puppet.deprecation_warning(message, :SERVER_DUPLICATION)
1477
- end
1478
- }
1479
1461
  },
1480
1462
  :use_srv_records => {
1481
1463
  :default => false,
@@ -1948,6 +1930,16 @@ EOT
1948
1930
  referencing variables that are explicitly set to undef).
1949
1931
  EOT
1950
1932
  },
1933
+ :func3x_check => {
1934
+ :default => true,
1935
+ :type => :boolean,
1936
+ :desc => <<-'EOT'
1937
+ Causes validation of loaded legacy Ruby functions (3x API) to raise errors about illegal constructs that
1938
+ could cause harm or that simply does not work. This flag is on by default. This flag is made available
1939
+ so that the validation can be turned off in case the method of validation is faulty - if encountered, please
1940
+ file a bug report.
1941
+ EOT
1942
+ },
1951
1943
  :tasks => {
1952
1944
  :default => false,
1953
1945
  :type => :boolean,
@@ -69,7 +69,8 @@ Puppet::Functions.create_function(:call, Puppet::Functions::InternalFunction) do
69
69
  end
70
70
 
71
71
  def call_impl_block(scope, function_name, *args, &block)
72
- call_function_with_scope(scope, function_name, *args, &block)
72
+ # The call function must be able to call functions loaded by any loader visible from the calling scope.
73
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluator.external_call_function(function_name, args, scope, &block)
73
74
  end
74
75
 
75
76
  def call_deferred(scope, deferred)
@@ -298,12 +298,22 @@ module Puppet::Network::HTTP
298
298
  def execute_request(connection, request)
299
299
  start = Time.now
300
300
  connection.request(request)
301
- rescue EOFError => e
301
+ rescue => exception
302
302
  elapsed = (Time.now - start).to_f.round(3)
303
- uri = @site.addr + request.path.split('?')[0]
304
- eof = EOFError.new(_('request %{uri} interrupted after %{elapsed} seconds') % {uri: uri, elapsed: elapsed})
305
- eof.set_backtrace(e.backtrace) unless e.backtrace.empty?
306
- raise eof
303
+ uri = [@site.addr, request.path.split('?')[0]].join('/')
304
+ eclass = exception.class
305
+
306
+ err = case exception
307
+ when EOFError
308
+ eclass.new(_('request %{uri} interrupted after %{elapsed} seconds') % {uri: uri, elapsed: elapsed})
309
+ when Timeout::Error
310
+ eclass.new(_('request %{uri} timed out after %{elapsed} seconds') % {uri: uri, elapsed: elapsed})
311
+ else
312
+ eclass.new(_('request %{uri} failed: %{msg}') % {uri: uri, msg: exception.message})
313
+ end
314
+
315
+ err.set_backtrace(exception.backtrace) unless exception.backtrace.empty?
316
+ raise err
307
317
  end
308
318
 
309
319
  def with_connection(site, &block)
@@ -760,6 +760,10 @@ module Issues
760
760
  _("An escape char for @() may only appear once. Got '%{escapes}'") % { escapes: escapes.join(', ') }
761
761
  end
762
762
 
763
+ HEREDOC_DIRTY_MARGIN = hard_issue :HEREDOC_DIRTY_MARGIN, :heredoc_line do
764
+ _("Heredoc with text in the margin is not allowed (line %{heredoc_line} in this heredoc)") % { heredoc_line: heredoc_line }
765
+ end
766
+
763
767
  ILLEGAL_BOM = hard_issue :ILLEGAL_BOM, :format_name, :bytes do
764
768
  _("Illegal %{format} Byte Order mark at beginning of input: %{bom} - remove these from the puppet source") % { format: format_name, bom: bytes }
765
769
  end
@@ -1,7 +1,10 @@
1
1
  # The RubyLegacyFunctionInstantiator instantiates a Puppet::Functions::Function given the ruby source
2
2
  # that calls Puppet::Functions.create_function.
3
3
  #
4
+ require 'ripper'
4
5
  class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
6
+ UNKNOWN = '<unknown>'.freeze
7
+
5
8
  # Produces an instance of the Function class with the given typed_name, or fails with an error if the
6
9
  # given ruby source does not produce this instance when evaluated.
7
10
  #
@@ -13,9 +16,15 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
13
16
  # @return [Puppet::Pops::Functions.Function] - an instantiated function with global scope closure associated with the given loader
14
17
  #
15
18
  def self.create(loader, typed_name, source_ref, ruby_code_string)
16
- unless ruby_code_string.is_a?(String) && ruby_code_string =~ /Puppet\:\:Parser\:\:Functions.*newfunction/m
17
- raise ArgumentError, _("The code loaded from %{source_ref} does not seem to be a Puppet 3x API function - no 'newfunction' call.") % { source_ref: source_ref }
19
+ # When func3x turned on, assert content by parsing, when turned off continue with (legacy) undefined behavior
20
+ if Puppet[:func3x_check]
21
+ assertion_result = []
22
+ assert_code(ruby_code_string, assertion_result)
23
+ unless ruby_code_string.is_a?(String) && assertion_result.include?(:found_newfunction)
24
+ raise ArgumentError, _("The code loaded from %{source_ref} does not seem to be a Puppet 3x API function - no 'newfunction' call.") % { source_ref: source_ref }
25
+ end
18
26
  end
27
+
19
28
  # make the private loader available in a binding to allow it to be passed on
20
29
  loader_for_function = loader.private_loader
21
30
  here = get_binding(loader_for_function)
@@ -26,14 +35,14 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
26
35
  environment = Puppet.lookup(:current_environment)
27
36
  func_info = Puppet::Parser::Functions.environment_module(environment).get_function_info(typed_name.name.to_sym)
28
37
  if func_info.nil?
29
- # This will to do the 3x loading and define the "function_<name>" and "real_function_<name>" methods
38
+ # This will do the 3x loading and define the "function_<name>" and "real_function_<name>" methods
30
39
  # in the anonymous module used to hold function definitions.
31
40
  #
32
41
  func_info = eval(ruby_code_string, here, source_ref, 1)
33
42
 
34
43
  # Validate what was loaded
35
44
  unless func_info.is_a?(Hash)
36
- # TRANSLATORS - the word 'newfunction' shoud not be translated as it is a method name.
45
+ # TRANSLATORS - the word 'newfunction' should not be translated as it is a method name.
37
46
  raise ArgumentError, _("Illegal legacy function definition! The code loaded from %{source_ref} did not return the result of calling 'newfunction'. Got '%{klass}'") % { source_ref: source_ref, klass: func_info.class }
38
47
  end
39
48
  unless func_info[:name] == "function_#{typed_name.name()}"
@@ -60,4 +69,51 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
60
69
  binding
61
70
  end
62
71
  private_class_method :get_binding
72
+
73
+ def self.assert_code(code_string, result)
74
+ ripped = Ripper.sexp(code_string)
75
+ return if ripped.nil? # Let the next real parse crash and tell where and what is wrong
76
+ ripped.each {|x| walk(x, result) }
77
+ end
78
+ private_class_method :assert_code
79
+
80
+ def self.walk(x, result)
81
+ return unless x.is_a?(Array)
82
+ first = x[0]
83
+ case first
84
+ when :fcall, :call
85
+ # Ripper returns a :fcall for a function call in a module (want to know there is a call to newfunction()).
86
+ # And it returns :call for a qualified named call
87
+ identity_part = find_identity(x)
88
+ result << :found_newfunction if identity_part.is_a?(Array) && identity_part[1] == 'newfunction'
89
+ when :def, :defs
90
+ # There should not be any calls to def in a 3x function
91
+ mname, mline = extract_name_line(find_identity(x))
92
+ raise SecurityError, _("Illegal method definition of method '%{method_name}' on line %{line}' in legacy function. See %{url} for more information") % {
93
+ method_name: mname,
94
+ line: mline,
95
+ url: "https://puppet.com/docs/puppet/latest/functions_refactor_legacy.html"
96
+ }
97
+ end
98
+ x.each {|v| walk(v, result) }
99
+ end
100
+ private_class_method :walk
101
+
102
+ def self.find_identity(rast)
103
+ rast.find{|x| x.is_a?(Array) && x[0] == :@ident }
104
+ end
105
+ private_class_method :find_identity
106
+
107
+ # Extracts the method name and line number from the Ripper Rast for an id entry.
108
+ # The expected input (a result from Ripper :@ident entry) is an array with:
109
+ # [0] == :def (or :defs for self.def)
110
+ # [1] == method name
111
+ # [2] == [ <filename>, <linenumber> ]
112
+ #
113
+ # Returns an Array; a tuple with method name and line number or "<unknown>" if either is missing, or format is not the expected
114
+ #
115
+ def self.extract_name_line(x)
116
+ (x.is_a?(Array) ? [ x[1], x[2].is_a?(Array) ? x[2][1] : nil] : [nil, nil]).map {|v| v.nil? ? UNKNOWN : v }
117
+ end
118
+ private_class_method :extract_name_line
63
119
  end