puppet 7.16.0-x64-mingw32 → 7.17.0-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +66 -5
- data/ext/systemd/puppet.service +1 -1
- data/lib/puppet/agent.rb +20 -2
- data/lib/puppet/application/agent.rb +3 -13
- data/lib/puppet/application/apply.rb +2 -2
- data/lib/puppet/configurer.rb +1 -1
- data/lib/puppet/defaults.rb +11 -1
- data/lib/puppet/http/client.rb +22 -2
- data/lib/puppet/parameter.rb +19 -4
- data/lib/puppet/pops/evaluator/deferred_resolver.rb +46 -6
- data/lib/puppet/pops/functions/dispatcher.rb +10 -6
- data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +7 -6
- data/lib/puppet/pops/types/type_mismatch_describer.rb +22 -1
- data/lib/puppet/provider/package/puppetserver_gem.rb +7 -16
- data/lib/puppet/provider/package/yum.rb +8 -3
- data/lib/puppet/provider/user/directoryservice.rb +15 -8
- data/lib/puppet/ssl/ssl_provider.rb +65 -12
- data/lib/puppet/ssl/state_machine.rb +13 -17
- data/lib/puppet/transaction.rb +22 -0
- data/lib/puppet/type/user.rb +3 -0
- data/lib/puppet/type.rb +20 -3
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet.rb +1 -14
- data/man/man5/puppet.conf.5 +11 -3
- data/man/man8/puppet-agent.8 +2 -2
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/application/agent_spec.rb +157 -0
- data/spec/integration/application/apply_spec.rb +74 -0
- data/spec/integration/http/client_spec.rb +27 -10
- data/spec/lib/puppet_spec/https.rb +1 -1
- data/spec/lib/puppet_spec/puppetserver.rb +39 -2
- data/spec/unit/agent_spec.rb +6 -2
- data/spec/unit/application/agent_spec.rb +26 -16
- data/spec/unit/daemon_spec.rb +2 -11
- data/spec/unit/http/client_spec.rb +18 -0
- data/spec/unit/pops/evaluator/deferred_resolver_spec.rb +26 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +1 -1
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +167 -1
- data/spec/unit/provider/package/puppetserver_gem_spec.rb +2 -2
- data/spec/unit/provider/user/directoryservice_spec.rb +1 -1
- data/spec/unit/ssl/ssl_provider_spec.rb +75 -1
- data/spec/unit/ssl/state_machine_spec.rb +1 -0
- data/tasks/generate_cert_fixtures.rake +5 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39cbb24d30ce1b44d52015647d271a626c59d55cb7a0a31a7159de16b74b4ce4
|
4
|
+
data.tar.gz: 7705591fc0fd2ed3559c29d7d90f803a6730ac835207e919e92195145aae0a8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8a67243e1e989aebe187b5281f7df8bda31c0c7b3ce27c50f4d5ed146d3a6c164e9125a114a9d1d65a6969f14979b9e448c0df079689b5616ec61217ef5ca55
|
7
|
+
data.tar.gz: cef70451f5c9c09e871807b61c04d4d38270878b13bbdebb107391f6c98cc87f77d789b81fb2399358c64e86f5d1764ee8b41fab004ee5465e3f6bdc17dc46b1
|
data/Gemfile.lock
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/puppetlabs/packaging
|
3
|
-
revision:
|
3
|
+
revision: b791353d4f81dbb1df5ce3d79e95bd008b47beb6
|
4
4
|
branch: 1.0.x
|
5
5
|
specs:
|
6
|
-
packaging (0.106.
|
6
|
+
packaging (0.106.3.6.gb791353)
|
7
7
|
apt_stage_artifacts
|
8
8
|
artifactory (~> 3)
|
9
9
|
csv (= 3.1.5)
|
10
|
+
google-cloud-storage
|
11
|
+
googleauth
|
10
12
|
rake (>= 12.3)
|
11
13
|
release-metrics
|
12
14
|
|
13
15
|
PATH
|
14
16
|
remote: .
|
15
17
|
specs:
|
16
|
-
puppet (7.
|
18
|
+
puppet (7.17.0)
|
17
19
|
CFPropertyList (~> 2.2)
|
18
20
|
concurrent-ruby (~> 1.0)
|
19
21
|
deep_merge (~> 1.0)
|
@@ -40,12 +42,19 @@ GEM
|
|
40
42
|
crack (0.4.5)
|
41
43
|
rexml
|
42
44
|
csv (3.1.5)
|
45
|
+
declarative (0.0.20)
|
43
46
|
deep_merge (1.2.2)
|
44
47
|
diff-lcs (1.5.0)
|
48
|
+
digest-crc (0.6.4)
|
49
|
+
rake (>= 12.0.0, < 14.0.0)
|
45
50
|
docopt (0.6.1)
|
46
51
|
facter (4.2.9)
|
47
52
|
hocon (~> 1.3)
|
48
53
|
thor (>= 1.0.1, < 2.0)
|
54
|
+
faraday (2.3.0)
|
55
|
+
faraday-net_http (~> 2.0)
|
56
|
+
ruby2_keywords (>= 0.0.4)
|
57
|
+
faraday-net_http (2.0.3)
|
49
58
|
fast_gettext (1.1.2)
|
50
59
|
ffi (1.15.5)
|
51
60
|
gettext (3.2.9)
|
@@ -55,24 +64,63 @@ GEM
|
|
55
64
|
fast_gettext (~> 1.1.0)
|
56
65
|
gettext (>= 3.0.2, < 3.3.0)
|
57
66
|
locale
|
67
|
+
google-apis-core (0.5.0)
|
68
|
+
addressable (~> 2.5, >= 2.5.1)
|
69
|
+
googleauth (>= 0.16.2, < 2.a)
|
70
|
+
httpclient (>= 2.8.1, < 3.a)
|
71
|
+
mini_mime (~> 1.0)
|
72
|
+
representable (~> 3.0)
|
73
|
+
retriable (>= 2.0, < 4.a)
|
74
|
+
rexml
|
75
|
+
webrick
|
76
|
+
google-apis-iamcredentials_v1 (0.10.0)
|
77
|
+
google-apis-core (>= 0.4, < 2.a)
|
78
|
+
google-apis-storage_v1 (0.14.0)
|
79
|
+
google-apis-core (>= 0.4, < 2.a)
|
80
|
+
google-cloud-core (1.6.0)
|
81
|
+
google-cloud-env (~> 1.0)
|
82
|
+
google-cloud-errors (~> 1.0)
|
83
|
+
google-cloud-env (1.6.0)
|
84
|
+
faraday (>= 0.17.3, < 3.0)
|
85
|
+
google-cloud-errors (1.2.0)
|
86
|
+
google-cloud-storage (1.36.2)
|
87
|
+
addressable (~> 2.8)
|
88
|
+
digest-crc (~> 0.4)
|
89
|
+
google-apis-iamcredentials_v1 (~> 0.1)
|
90
|
+
google-apis-storage_v1 (~> 0.1)
|
91
|
+
google-cloud-core (~> 1.6)
|
92
|
+
googleauth (>= 0.16.2, < 2.a)
|
93
|
+
mini_mime (~> 1.0)
|
94
|
+
googleauth (1.1.3)
|
95
|
+
faraday (>= 0.17.3, < 3.a)
|
96
|
+
jwt (>= 1.4, < 3.0)
|
97
|
+
memoist (~> 0.16)
|
98
|
+
multi_json (~> 1.11)
|
99
|
+
os (>= 0.9, < 2.0)
|
100
|
+
signet (>= 0.16, < 2.a)
|
58
101
|
hashdiff (1.0.1)
|
59
|
-
hiera (3.
|
60
|
-
hiera-eyaml (3.
|
102
|
+
hiera (3.9.0)
|
103
|
+
hiera-eyaml (3.3.0)
|
61
104
|
highline
|
62
105
|
optimist
|
63
106
|
highline (2.0.3)
|
64
107
|
hocon (1.3.1)
|
65
108
|
hpricot (0.8.6)
|
109
|
+
httpclient (2.8.3)
|
66
110
|
json-schema (2.8.1)
|
67
111
|
addressable (>= 2.4)
|
112
|
+
jwt (2.3.0)
|
68
113
|
locale (2.1.3)
|
114
|
+
memoist (0.16.2)
|
69
115
|
memory_profiler (1.0.0)
|
70
116
|
method_source (1.0.0)
|
117
|
+
mini_mime (1.1.2)
|
71
118
|
minitar (0.9)
|
72
119
|
msgpack (1.5.1)
|
73
120
|
multi_json (1.15.0)
|
74
121
|
mustache (1.1.1)
|
75
122
|
optimist (3.0.1)
|
123
|
+
os (1.1.4)
|
76
124
|
parallel (1.22.1)
|
77
125
|
parser (2.7.2.0)
|
78
126
|
ast (~> 2.4.1)
|
@@ -94,6 +142,11 @@ GEM
|
|
94
142
|
release-metrics (1.1.0)
|
95
143
|
csv
|
96
144
|
docopt
|
145
|
+
representable (3.2.0)
|
146
|
+
declarative (< 0.1.0)
|
147
|
+
trailblazer-option (>= 0.1.1, < 0.2.0)
|
148
|
+
uber (< 0.2.0)
|
149
|
+
retriable (3.1.2)
|
97
150
|
rexml (3.2.5)
|
98
151
|
ronn (0.7.3)
|
99
152
|
hpricot (>= 0.8.2)
|
@@ -126,10 +179,18 @@ GEM
|
|
126
179
|
rubocop (~> 0.49.0)
|
127
180
|
ruby-prof (1.4.3)
|
128
181
|
ruby-progressbar (1.11.0)
|
182
|
+
ruby2_keywords (0.0.5)
|
129
183
|
scanf (1.0.0)
|
130
184
|
semantic_puppet (1.0.4)
|
185
|
+
signet (0.16.1)
|
186
|
+
addressable (~> 2.8)
|
187
|
+
faraday (>= 0.17.5, < 3.0)
|
188
|
+
jwt (>= 1.5, < 3.0)
|
189
|
+
multi_json (~> 1.10)
|
131
190
|
text (1.3.1)
|
132
191
|
thor (1.2.1)
|
192
|
+
trailblazer-option (0.1.2)
|
193
|
+
uber (0.1.0)
|
133
194
|
unicode-display_width (1.8.0)
|
134
195
|
vcr (5.1.0)
|
135
196
|
webmock (3.14.0)
|
data/ext/systemd/puppet.service
CHANGED
data/lib/puppet/agent.rb
CHANGED
@@ -45,11 +45,19 @@ class Puppet::Agent
|
|
45
45
|
result = nil
|
46
46
|
wait_for_lock_deadline = nil
|
47
47
|
block_run = Puppet::Application.controlled_run do
|
48
|
-
splay
|
48
|
+
# splay may sleep for awhile!
|
49
|
+
splay(client_options.fetch(:splay, Puppet[:splay]))
|
50
|
+
|
51
|
+
# waiting for certs may sleep for awhile depending on onetime, waitforcert and maxwaitforcert!
|
52
|
+
# this needs to happen before forking so that if we fail to obtain certs and try to exit, then
|
53
|
+
# we exit the main process and not the forked child.
|
54
|
+
ssl_context = wait_for_certificates(client_options)
|
55
|
+
|
49
56
|
result = run_in_fork(should_fork) do
|
50
57
|
with_client(client_options[:transaction_uuid], client_options[:job_id]) do |client|
|
51
58
|
client_args = client_options.merge(:pluginsync => Puppet::Configurer.should_pluginsync?)
|
52
59
|
begin
|
60
|
+
# lock may sleep for awhile depending on waitforlock and maxwaitforlock!
|
53
61
|
lock do
|
54
62
|
# NOTE: Timeout is pretty heinous as the location in which it
|
55
63
|
# throws an error is entirely unpredictable, which means that
|
@@ -57,7 +65,9 @@ class Puppet::Agent
|
|
57
65
|
# sanity. The only thing a Puppet agent should do after this
|
58
66
|
# error is thrown is die with as much dignity as possible.
|
59
67
|
Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do
|
60
|
-
|
68
|
+
Puppet.override(ssl_context: ssl_context) do
|
69
|
+
client.run(client_args)
|
70
|
+
end
|
61
71
|
end
|
62
72
|
end
|
63
73
|
rescue Puppet::LockError
|
@@ -84,6 +94,8 @@ class Puppet::Agent
|
|
84
94
|
rescue StandardError => detail
|
85
95
|
Puppet.log_exception(detail, _("Could not run %{client_class}: %{detail}") % { client_class: client_class, detail: detail })
|
86
96
|
nil
|
97
|
+
ensure
|
98
|
+
Puppet.runtime[:http].close
|
87
99
|
end
|
88
100
|
end
|
89
101
|
end
|
@@ -137,4 +149,10 @@ class Puppet::Agent
|
|
137
149
|
ensure
|
138
150
|
@client = nil
|
139
151
|
end
|
152
|
+
|
153
|
+
def wait_for_certificates(options)
|
154
|
+
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
|
155
|
+
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert, onetime: Puppet[:onetime])
|
156
|
+
sm.ensure_client_certificate
|
157
|
+
end
|
140
158
|
end
|
@@ -158,7 +158,7 @@ applying the whole thing.
|
|
158
158
|
'--fingerprint' is a one-time flag. In this mode 'puppet agent' runs
|
159
159
|
once and displays on the console (and in the log) the current certificate
|
160
160
|
(or certificate request) fingerprint. Providing the '--digest' option
|
161
|
-
allows to use a different digest algorithm to generate the fingerprint.
|
161
|
+
allows you to use a different digest algorithm to generate the fingerprint.
|
162
162
|
The main use is to verify that before signing a certificate request on
|
163
163
|
the master, the certificate request the master received is the same as
|
164
164
|
the one the client sent (to prevent against man-in-the-middle attacks
|
@@ -383,15 +383,11 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
383
383
|
|
384
384
|
log_config if Puppet[:daemonize]
|
385
385
|
|
386
|
-
# run ssl state machine, waiting if needed
|
387
|
-
ssl_context = wait_for_certificates
|
388
|
-
|
389
386
|
# Each application is responsible for pushing loaders onto the context.
|
390
387
|
# Use the current environment that has already been established, though
|
391
388
|
# it may change later during the configurer run.
|
392
389
|
env = Puppet.lookup(:current_environment)
|
393
|
-
Puppet.override(
|
394
|
-
current_environment: env,
|
390
|
+
Puppet.override(current_environment: env,
|
395
391
|
loaders: Puppet::Pops::Loaders.new(env, true)) do
|
396
392
|
if Puppet[:onetime]
|
397
393
|
onetime(daemon)
|
@@ -434,7 +430,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
434
430
|
|
435
431
|
def onetime(daemon)
|
436
432
|
begin
|
437
|
-
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time]})
|
433
|
+
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time], :waitforcert => options[:waitforcert]})
|
438
434
|
rescue => detail
|
439
435
|
Puppet.log_exception(detail)
|
440
436
|
end
|
@@ -524,10 +520,4 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
524
520
|
|
525
521
|
daemon
|
526
522
|
end
|
527
|
-
|
528
|
-
def wait_for_certificates
|
529
|
-
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
|
530
|
-
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert)
|
531
|
-
sm.ensure_client_certificate
|
532
|
-
end
|
533
523
|
end
|
@@ -241,7 +241,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
241
241
|
end
|
242
242
|
|
243
243
|
# Resolve all deferred values and replace them / mutate the catalog
|
244
|
-
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, apply_environment)
|
244
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, apply_environment, Puppet[:preprocess_deferred])
|
245
245
|
|
246
246
|
# Translate it to a RAL catalog
|
247
247
|
catalog = catalog.to_ral
|
@@ -350,7 +350,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
350
350
|
raise Puppet::Error, _("Could not deserialize catalog from %{format}: %{detail}") % { format: format, detail: detail }, detail.backtrace
|
351
351
|
end
|
352
352
|
# Resolve all deferred values and replace them / mutate the catalog
|
353
|
-
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, configured_environment)
|
353
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, configured_environment, Puppet[:preprocess_deferred])
|
354
354
|
|
355
355
|
catalog.to_ral
|
356
356
|
end
|
data/lib/puppet/configurer.rb
CHANGED
@@ -112,7 +112,7 @@ class Puppet::Configurer
|
|
112
112
|
catalog_conversion_time = thinmark do
|
113
113
|
# Will mutate the result and replace all Deferred values with resolved values
|
114
114
|
if facts
|
115
|
-
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(facts, result, Puppet.lookup(:current_environment))
|
115
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(facts, result, Puppet.lookup(:current_environment), Puppet[:preprocess_deferred])
|
116
116
|
end
|
117
117
|
|
118
118
|
catalog = result.to_ral
|
data/lib/puppet/defaults.rb
CHANGED
@@ -1534,7 +1534,7 @@ EOT
|
|
1534
1534
|
:type => :file,
|
1535
1535
|
:mode => "0640",
|
1536
1536
|
:desc => "Transactional storage file for persisting data between
|
1537
|
-
transactions for the purposes of
|
1537
|
+
transactions for the purposes of inferring information (such as
|
1538
1538
|
corrective_change) on new data received."
|
1539
1539
|
},
|
1540
1540
|
:clientyamldir => {
|
@@ -2021,6 +2021,16 @@ EOT
|
|
2021
2021
|
being evaluated. This allows you to interactively see exactly
|
2022
2022
|
what is being done.",
|
2023
2023
|
},
|
2024
|
+
:preprocess_deferred => {
|
2025
|
+
:default => true,
|
2026
|
+
:type => :boolean,
|
2027
|
+
:desc => "Whether puppet should call deferred functions before applying
|
2028
|
+
the catalog. If set to `true`, then all prerequisites needed for the
|
2029
|
+
deferred function must be satified prior to puppet running. If set to
|
2030
|
+
`false`, then deferred functions will follow puppet relationships and
|
2031
|
+
ordering. This allows puppet to install prerequisites needed for a
|
2032
|
+
deferred function and call the deferred function in the same run."
|
2033
|
+
},
|
2024
2034
|
:summarize => {
|
2025
2035
|
:default => false,
|
2026
2036
|
:type => :boolean,
|
data/lib/puppet/http/client.rb
CHANGED
@@ -98,7 +98,7 @@ class Puppet::HTTP::Client
|
|
98
98
|
# used if :include_system_store is set to true
|
99
99
|
# @param [Integer] redirect_limit default number of HTTP redirections to allow
|
100
100
|
# in a given request. Can also be specified per-request.
|
101
|
-
# @param [Integer] retry_limit number of HTTP
|
101
|
+
# @param [Integer] retry_limit number of HTTP retries allowed in a given
|
102
102
|
# request
|
103
103
|
#
|
104
104
|
def initialize(pool: Puppet::HTTP::Pool.new(Puppet[:http_keepalive_timeout]), ssl_context: nil, system_ssl_context: nil, redirect_limit: 10, retry_limit: 100)
|
@@ -300,6 +300,24 @@ class Puppet::HTTP::Client
|
|
300
300
|
# @api public
|
301
301
|
def close
|
302
302
|
@pool.close
|
303
|
+
@default_ssl_context = nil
|
304
|
+
@default_system_ssl_context = nil
|
305
|
+
end
|
306
|
+
|
307
|
+
def default_ssl_context
|
308
|
+
cert = Puppet::X509::CertProvider.new
|
309
|
+
password = cert.load_private_key_password
|
310
|
+
|
311
|
+
ssl = Puppet::SSL::SSLProvider.new
|
312
|
+
ctx = ssl.load_context(certname: Puppet[:certname], password: password)
|
313
|
+
ssl.print(ctx)
|
314
|
+
ctx
|
315
|
+
rescue => e
|
316
|
+
# TRANSLATORS: `message` is an already translated string of why SSL failed to initialize
|
317
|
+
Puppet.log_exception(e, _("Failed to initialize SSL: %{message}") % { message: e.message })
|
318
|
+
# TRANSLATORS: `puppet agent -t` is a command and should not be translated
|
319
|
+
Puppet.err(_("Run `puppet agent -t`"))
|
320
|
+
raise e
|
303
321
|
end
|
304
322
|
|
305
323
|
protected
|
@@ -458,7 +476,9 @@ class Puppet::HTTP::Client
|
|
458
476
|
cacerts = cert_provider.load_cacerts || []
|
459
477
|
|
460
478
|
ssl = Puppet::SSL::SSLProvider.new
|
461
|
-
@default_system_ssl_context = ssl.create_system_context(cacerts: cacerts)
|
479
|
+
@default_system_ssl_context = ssl.create_system_context(cacerts: cacerts, include_client_cert: true)
|
480
|
+
ssl.print(@default_system_ssl_context)
|
481
|
+
@default_system_ssl_context
|
462
482
|
end
|
463
483
|
|
464
484
|
def apply_auth(request, basic_auth)
|
data/lib/puppet/parameter.rb
CHANGED
@@ -177,15 +177,15 @@ class Puppet::Parameter
|
|
177
177
|
end
|
178
178
|
|
179
179
|
# @overload unmunge {|| ... }
|
180
|
-
# Defines an optional method used to convert the parameter value to DSL/string form
|
180
|
+
# Defines an optional method used to convert the parameter value from internal form to DSL/string form.
|
181
181
|
# If an `unmunge` method is not defined, the internal form is used.
|
182
182
|
# @see munge
|
183
|
-
# @note This adds a method with the name `
|
183
|
+
# @note This adds a method with the name `unsafe_unmunge` in the created parameter class.
|
184
184
|
# @dsl type
|
185
185
|
# @api public
|
186
186
|
#
|
187
187
|
def unmunge(&block)
|
188
|
-
define_method(:
|
188
|
+
define_method(:unsafe_unmunge, &block)
|
189
189
|
end
|
190
190
|
|
191
191
|
# Sets a marker indicating that this parameter is the _namevar_ (unique identifier) of the type
|
@@ -415,10 +415,21 @@ class Puppet::Parameter
|
|
415
415
|
# @return [Object] the unmunged value
|
416
416
|
#
|
417
417
|
def unmunge(value)
|
418
|
+
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue)
|
419
|
+
|
420
|
+
unsafe_unmunge(value)
|
421
|
+
end
|
422
|
+
|
423
|
+
# This is the default implementation of `unmunge` that simply produces the value (if it is valid).
|
424
|
+
# The DSL method {unmunge} should be used to define an overriding method if unmunging is required.
|
425
|
+
#
|
426
|
+
# @api private
|
427
|
+
#
|
428
|
+
def unsafe_unmunge(value)
|
418
429
|
value
|
419
430
|
end
|
420
431
|
|
421
|
-
# Munges the value to internal form.
|
432
|
+
# Munges the value from DSL form to internal form.
|
422
433
|
# This implementation of `munge` provides exception handling around the specified munging of this parameter.
|
423
434
|
# @note This method should not be overridden. Use the DSL method {munge} to define a munging method
|
424
435
|
# if required.
|
@@ -426,6 +437,8 @@ class Puppet::Parameter
|
|
426
437
|
# @return [Object] the munged (internal) value
|
427
438
|
#
|
428
439
|
def munge(value)
|
440
|
+
return value if value.is_a?(Puppet::Pops::Evaluator::DeferredValue)
|
441
|
+
|
429
442
|
begin
|
430
443
|
ret = unsafe_munge(value)
|
431
444
|
rescue Puppet::Error => detail
|
@@ -459,6 +472,8 @@ class Puppet::Parameter
|
|
459
472
|
# @api public
|
460
473
|
#
|
461
474
|
def validate(value)
|
475
|
+
return if value.is_a?(Puppet::Pops::Evaluator::DeferredValue)
|
476
|
+
|
462
477
|
begin
|
463
478
|
unsafe_validate(value)
|
464
479
|
rescue ArgumentError => detail
|
@@ -3,6 +3,16 @@ require_relative '../../../puppet/parser/script_compiler'
|
|
3
3
|
module Puppet::Pops
|
4
4
|
module Evaluator
|
5
5
|
|
6
|
+
class DeferredValue
|
7
|
+
def initialize(proc)
|
8
|
+
@proc = proc
|
9
|
+
end
|
10
|
+
|
11
|
+
def resolve
|
12
|
+
@proc.call
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
# Utility class to help resolve instances of Puppet::Pops::Types::PDeferredType::Deferred
|
7
17
|
#
|
8
18
|
class DeferredResolver
|
@@ -20,9 +30,9 @@ class DeferredResolver
|
|
20
30
|
# are to be mixed into the scope
|
21
31
|
# @return [nil] does not return anything - the catalog is modified as a side effect
|
22
32
|
#
|
23
|
-
def self.resolve_and_replace(facts, catalog, environment = catalog.environment_instance)
|
24
|
-
compiler = Puppet::Parser::ScriptCompiler.new(environment, catalog.name,
|
25
|
-
resolver = new(compiler)
|
33
|
+
def self.resolve_and_replace(facts, catalog, environment = catalog.environment_instance, preprocess_deferred = true)
|
34
|
+
compiler = Puppet::Parser::ScriptCompiler.new(environment, catalog.name, preprocess_deferred)
|
35
|
+
resolver = new(compiler, preprocess_deferred)
|
26
36
|
resolver.set_facts_variable(facts)
|
27
37
|
# TODO:
|
28
38
|
# # When scripting the trusted data are always local, but set them anyway
|
@@ -53,11 +63,12 @@ class DeferredResolver
|
|
53
63
|
resolver.resolve(value)
|
54
64
|
end
|
55
65
|
|
56
|
-
def initialize(compiler)
|
66
|
+
def initialize(compiler, preprocess_deferred = true)
|
57
67
|
@compiler = compiler
|
58
68
|
# Always resolve in top scope
|
59
69
|
@scope = @compiler.topscope
|
60
70
|
@deferred_class = Puppet::Pops::Types::TypeFactory.deferred.implementation_class
|
71
|
+
@preprocess_deferred = preprocess_deferred
|
61
72
|
end
|
62
73
|
|
63
74
|
# @param facts [Puppet::Node::Facts] the facts to set in $facts in the compiler's topscope
|
@@ -106,6 +117,24 @@ class DeferredResolver
|
|
106
117
|
end
|
107
118
|
end
|
108
119
|
|
120
|
+
def resolve_lazy_args(x)
|
121
|
+
if x.is_a?(DeferredValue)
|
122
|
+
x.resolve
|
123
|
+
elsif x.is_a?(Array)
|
124
|
+
x.map {|v| resolve_lazy_args(v) }
|
125
|
+
elsif x.is_a?(Hash)
|
126
|
+
result = {}
|
127
|
+
x.each_pair {|k,v| result[k] = resolve_lazy_args(v) }
|
128
|
+
result
|
129
|
+
elsif x.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
|
130
|
+
# rewrap in a new Sensitive after resolving any nested deferred values
|
131
|
+
Puppet::Pops::Types::PSensitiveType::Sensitive.new(resolve_lazy_args(x.unwrap))
|
132
|
+
else
|
133
|
+
x
|
134
|
+
end
|
135
|
+
end
|
136
|
+
private :resolve_lazy_args
|
137
|
+
|
109
138
|
def resolve_future(f)
|
110
139
|
# If any of the arguments to a future is a future it needs to be resolved first
|
111
140
|
func_name = f.name
|
@@ -117,8 +146,19 @@ class DeferredResolver
|
|
117
146
|
mapped_arguments.insert(0, @scope[var_name])
|
118
147
|
end
|
119
148
|
|
120
|
-
|
121
|
-
|
149
|
+
if @preprocess_deferred
|
150
|
+
# call the function (name in deferred, or 'dig' for a variable)
|
151
|
+
@scope.call_function(func_name, mapped_arguments)
|
152
|
+
else
|
153
|
+
# call the function later
|
154
|
+
DeferredValue.new(
|
155
|
+
Proc.new {
|
156
|
+
# deferred functions can have nested deferred arguments
|
157
|
+
resolved_arguments = mapped_arguments.map { |arg| resolve_lazy_args(arg) }
|
158
|
+
@scope.call_function(func_name, resolved_arguments)
|
159
|
+
}
|
160
|
+
)
|
161
|
+
end
|
122
162
|
end
|
123
163
|
|
124
164
|
def map_arguments(args)
|
@@ -19,6 +19,10 @@ class Puppet::Pops::Functions::Dispatcher
|
|
19
19
|
@dispatchers.empty?
|
20
20
|
end
|
21
21
|
|
22
|
+
def find_matching_dispatcher(args, &block)
|
23
|
+
@dispatchers.find { |d| d.type.callable_with?(args, block) }
|
24
|
+
end
|
25
|
+
|
22
26
|
# Dispatches the call to the first found signature (entry with matching type).
|
23
27
|
#
|
24
28
|
# @param instance [Puppet::Functions::Function] - the function to call
|
@@ -28,19 +32,19 @@ class Puppet::Pops::Functions::Dispatcher
|
|
28
32
|
#
|
29
33
|
# @api private
|
30
34
|
def dispatch(instance, calling_scope, args, &block)
|
31
|
-
|
32
|
-
|
35
|
+
|
36
|
+
dispatcher = find_matching_dispatcher(args, &block)
|
37
|
+
unless dispatcher
|
33
38
|
args_type = Puppet::Pops::Types::TypeCalculator.singleton.infer_set(block_given? ? args + [block] : args)
|
34
39
|
raise ArgumentError, Puppet::Pops::Types::TypeMismatchDescriber.describe_signatures(instance.class.name, signatures, args_type)
|
35
40
|
end
|
36
|
-
|
37
|
-
|
38
|
-
msg = found.invoke(instance, calling_scope, args)
|
41
|
+
if dispatcher.argument_mismatch_handler?
|
42
|
+
msg = dispatcher.invoke(instance, calling_scope, args)
|
39
43
|
raise ArgumentError, "'#{instance.class.name}' #{msg}"
|
40
44
|
end
|
41
45
|
|
42
46
|
catch(:next) do
|
43
|
-
|
47
|
+
dispatcher.invoke(instance, calling_scope, args, &block)
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
@@ -18,7 +18,7 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
|
|
18
18
|
def self.create(loader, typed_name, source_ref, ruby_code_string)
|
19
19
|
# Assert content of 3x function by parsing
|
20
20
|
assertion_result = []
|
21
|
-
if assert_code(ruby_code_string, assertion_result)
|
21
|
+
if assert_code(ruby_code_string, source_ref, assertion_result)
|
22
22
|
unless ruby_code_string.is_a?(String) && assertion_result.include?(:found_newfunction)
|
23
23
|
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 }
|
24
24
|
end
|
@@ -69,15 +69,15 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
|
|
69
69
|
end
|
70
70
|
private_class_method :get_binding
|
71
71
|
|
72
|
-
def self.assert_code(code_string, result)
|
72
|
+
def self.assert_code(code_string, source_ref, result)
|
73
73
|
ripped = Ripper.sexp(code_string)
|
74
74
|
return false if ripped.nil? # Let the next real parse crash and tell where and what is wrong
|
75
|
-
ripped.each {|x| walk(x, result) }
|
75
|
+
ripped.each {|x| walk(x, source_ref, result) }
|
76
76
|
true
|
77
77
|
end
|
78
78
|
private_class_method :assert_code
|
79
79
|
|
80
|
-
def self.walk(x, result)
|
80
|
+
def self.walk(x, source_ref, result)
|
81
81
|
return unless x.is_a?(Array)
|
82
82
|
first = x[0]
|
83
83
|
case first
|
@@ -89,13 +89,14 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
|
|
89
89
|
when :def, :defs
|
90
90
|
# There should not be any calls to def in a 3x function
|
91
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") % {
|
92
|
+
raise SecurityError, _("Illegal method definition of method '%{method_name}' in source %{source_ref} on line %{line} in legacy function. See %{url} for more information") % {
|
93
93
|
method_name: mname,
|
94
|
+
source_ref: source_ref,
|
94
95
|
line: mline,
|
95
96
|
url: "https://puppet.com/docs/puppet/latest/functions_refactor_legacy.html"
|
96
97
|
}
|
97
98
|
end
|
98
|
-
x.each {|v| walk(v, result) }
|
99
|
+
x.each {|v| walk(v, source_ref, result) }
|
99
100
|
end
|
100
101
|
private_class_method :walk
|
101
102
|
|
@@ -581,6 +581,15 @@ module Types
|
|
581
581
|
end
|
582
582
|
end
|
583
583
|
|
584
|
+
def get_deferred_function_return_type(value)
|
585
|
+
func = Puppet.lookup(:loaders).private_environment_loader.
|
586
|
+
load(:function, value.name)
|
587
|
+
dispatcher = func.class.dispatcher.find_matching_dispatcher(value.arguments)
|
588
|
+
raise ArgumentError, "No matching arity found for #{func.class.name} with arguments #{value.arguments}" unless dispatcher
|
589
|
+
dispatcher.type.return_type
|
590
|
+
end
|
591
|
+
private :get_deferred_function_return_type
|
592
|
+
|
584
593
|
# Validates that all entries in the _param_hash_ exists in the given param_struct, that their type conforms
|
585
594
|
# with the corresponding param_struct element and that all required values are provided.
|
586
595
|
# An error message is created for each problem found.
|
@@ -598,7 +607,19 @@ module Types
|
|
598
607
|
value = param_hash[name]
|
599
608
|
value_type = elem.value_type
|
600
609
|
if param_hash.include?(name)
|
601
|
-
|
610
|
+
if Puppet::Pops::Types::TypeFactory.deferred.implementation_class == value.class
|
611
|
+
if (df_return_type = get_deferred_function_return_type(value))
|
612
|
+
result << describe(value_type, df_return_type, [ParameterPathElement.new(name)]) unless value_type.generalize.assignable?(df_return_type.generalize)
|
613
|
+
else
|
614
|
+
warning_text = _("Deferred function %{function_name} has no return_type, unable to guarantee value type during compilation.") %
|
615
|
+
{function_name: value.name }
|
616
|
+
Puppet.warn_once('deprecations',
|
617
|
+
"#{value.name}_deferred_warning",
|
618
|
+
warning_text)
|
619
|
+
end
|
620
|
+
else
|
621
|
+
result << describe(value_type, TypeCalculator.singleton.infer_set(value), [ParameterPathElement.new(name)]) unless value_type.instance?(value)
|
622
|
+
end
|
602
623
|
else
|
603
624
|
result << MissingParameter.new(nil, name) unless missing_ok || elem.key_type.is_a?(POptionalType)
|
604
625
|
end
|