puppet 6.25.1 → 6.28.0

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +101 -34
  5. data/lib/puppet/agent.rb +47 -11
  6. data/lib/puppet/application/agent.rb +2 -12
  7. data/lib/puppet/application/lookup.rb +74 -24
  8. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  9. data/lib/puppet/configurer.rb +8 -14
  10. data/lib/puppet/defaults.rb +13 -3
  11. data/lib/puppet/face/generate.rb +2 -0
  12. data/lib/puppet/file_serving/metadata.rb +3 -0
  13. data/lib/puppet/file_system/file_impl.rb +7 -7
  14. data/lib/puppet/file_system/jruby.rb +1 -1
  15. data/lib/puppet/file_system/windows.rb +4 -4
  16. data/lib/puppet/file_system.rb +1 -1
  17. data/lib/puppet/functions/next.rb +18 -1
  18. data/lib/puppet/functions/tree_each.rb +0 -1
  19. data/lib/puppet/functions/versioncmp.rb +6 -2
  20. data/lib/puppet/generate/type.rb +9 -0
  21. data/lib/puppet/http/client.rb +22 -2
  22. data/lib/puppet/node.rb +1 -1
  23. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  24. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  25. data/lib/puppet/pops/parser/eparser.rb +813 -794
  26. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  27. data/lib/puppet/provider/package/puppetserver_gem.rb +7 -16
  28. data/lib/puppet/provider/package/windows/exe_package.rb +30 -1
  29. data/lib/puppet/provider/package/windows/package.rb +2 -1
  30. data/lib/puppet/provider/package/windows.rb +14 -1
  31. data/lib/puppet/provider/service/init.rb +5 -4
  32. data/lib/puppet/provider/user/directoryservice.rb +5 -0
  33. data/lib/puppet/ssl/ssl_provider.rb +75 -19
  34. data/lib/puppet/ssl/state_machine.rb +13 -17
  35. data/lib/puppet/ssl/verifier.rb +6 -0
  36. data/lib/puppet/transaction/persistence.rb +22 -12
  37. data/lib/puppet/type/exec.rb +1 -1
  38. data/lib/puppet/type/file/data_sync.rb +1 -1
  39. data/lib/puppet/type/user.rb +43 -38
  40. data/lib/puppet/util/json.rb +17 -0
  41. data/lib/puppet/util/log.rb +7 -2
  42. data/lib/puppet/util/monkey_patches.rb +6 -2
  43. data/lib/puppet/util/package.rb +25 -16
  44. data/lib/puppet/util/yaml.rb +21 -2
  45. data/lib/puppet/util.rb +1 -2
  46. data/lib/puppet/version.rb +1 -1
  47. data/lib/puppet.rb +2 -14
  48. data/locales/puppet.pot +5 -10454
  49. data/man/man5/puppet.conf.5 +21 -2
  50. data/man/man8/puppet-agent.8 +1 -1
  51. data/man/man8/puppet-apply.8 +1 -1
  52. data/man/man8/puppet-catalog.8 +1 -1
  53. data/man/man8/puppet-config.8 +1 -1
  54. data/man/man8/puppet-describe.8 +1 -1
  55. data/man/man8/puppet-device.8 +1 -1
  56. data/man/man8/puppet-doc.8 +1 -1
  57. data/man/man8/puppet-epp.8 +1 -1
  58. data/man/man8/puppet-facts.8 +1 -1
  59. data/man/man8/puppet-filebucket.8 +1 -1
  60. data/man/man8/puppet-generate.8 +1 -1
  61. data/man/man8/puppet-help.8 +1 -1
  62. data/man/man8/puppet-key.8 +1 -1
  63. data/man/man8/puppet-lookup.8 +9 -6
  64. data/man/man8/puppet-man.8 +1 -1
  65. data/man/man8/puppet-module.8 +1 -1
  66. data/man/man8/puppet-node.8 +1 -1
  67. data/man/man8/puppet-parser.8 +1 -1
  68. data/man/man8/puppet-plugin.8 +1 -1
  69. data/man/man8/puppet-report.8 +1 -1
  70. data/man/man8/puppet-resource.8 +1 -1
  71. data/man/man8/puppet-script.8 +1 -1
  72. data/man/man8/puppet-ssl.8 +1 -1
  73. data/man/man8/puppet-status.8 +1 -1
  74. data/man/man8/puppet.8 +2 -2
  75. data/spec/fixtures/unit/forge/bacula.json +1 -1
  76. data/spec/integration/application/agent_spec.rb +108 -0
  77. data/spec/integration/application/lookup_spec.rb +81 -50
  78. data/spec/integration/application/resource_spec.rb +6 -2
  79. data/spec/integration/http/client_spec.rb +51 -4
  80. data/spec/lib/puppet_spec/https.rb +1 -1
  81. data/spec/lib/puppet_spec/puppetserver.rb +39 -2
  82. data/spec/shared_contexts/l10n.rb +5 -0
  83. data/spec/unit/agent_spec.rb +28 -2
  84. data/spec/unit/application/agent_spec.rb +26 -16
  85. data/spec/unit/application/lookup_spec.rb +131 -10
  86. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  87. data/spec/unit/configurer_spec.rb +124 -61
  88. data/spec/unit/daemon_spec.rb +2 -11
  89. data/spec/unit/face/generate_spec.rb +64 -0
  90. data/spec/unit/file_system_spec.rb +34 -4
  91. data/spec/unit/forge/module_release_spec.rb +3 -3
  92. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  93. data/spec/unit/http/client_spec.rb +18 -0
  94. data/spec/unit/node_spec.rb +6 -0
  95. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  96. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  97. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  98. data/spec/unit/provider/package/puppetserver_gem_spec.rb +2 -2
  99. data/spec/unit/provider/package/windows/exe_package_spec.rb +17 -0
  100. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  101. data/spec/unit/provider/service/init_spec.rb +15 -9
  102. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  103. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  104. data/spec/unit/ssl/ssl_provider_spec.rb +75 -1
  105. data/spec/unit/ssl/state_machine_spec.rb +1 -0
  106. data/spec/unit/transaction/persistence_spec.rb +51 -0
  107. data/spec/unit/type/user_spec.rb +0 -45
  108. data/spec/unit/util/json_spec.rb +126 -0
  109. data/spec/unit/util/windows_spec.rb +23 -0
  110. data/spec/unit/util/yaml_spec.rb +54 -29
  111. data/tasks/generate_cert_fixtures.rake +5 -4
  112. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a724a353bb29f1314e51c03a2cf0b635f6f517487e123270d409515a785eb3e
4
- data.tar.gz: 789282cad7e0859aada719aa40f7869eac73c2ef018fcd5193863a2dd6b2aa6c
3
+ metadata.gz: 4a5961fa6df54cdc74777c8fbab36fad2ae62bbd11ab0bbb80cccbb2ba062a37
4
+ data.tar.gz: 3747fb6b31a88749e0ab737d599be3b0df1e89b421d9601e3ce13a803725c140
5
5
  SHA512:
6
- metadata.gz: 73aef7b4f28354fb4e450cca3fd72a403294e59bd370c34e3b7fc28cd05436cd2934979081d3bd4855c98a4a7a3224082bfea9ee125b14263b6f10b531076ee0
7
- data.tar.gz: c67974115ff032d5f877028ca2d461f736c0c6c12538ec35482aa6ed19f9ffead3ae3c22228a432b69276afbfa4e62d720942c02a45c4fba432a93af4d8b4fbb
6
+ metadata.gz: 465ace5e96735204aba54d8135aca487329238e36b2250cd0c0fd022306f7104a3c9f89c79370886d9c9182862f0d96d3e2621cb1b5fa1af965f47945994c671
7
+ data.tar.gz: 8e83132e776e4f6e0291c2e28d8ea01c57cbb35093234ee3d3b109e6d22af16eb33b32e3deccf888d006837542c61726c633d185c8f16717f787d2a73373fe87
data/CODEOWNERS CHANGED
@@ -1,5 +1,5 @@
1
1
  # defaults
2
- * @puppetlabs/platform-core @puppetlabs/puppetserver-maintainers @puppetlabs/night-s-watch
2
+ * @puppetlabs/phoenix @puppetlabs/puppetserver-maintainers
3
3
 
4
4
  # PAL
5
5
  /lib/puppet/pal @puppetlabs/bolt
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source ENV['GEM_SOURCE'] || "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  def location_for(place, fake_version = nil)
6
- if place.is_a?(String) && place =~ /^(git[:@][^#]*)#(.*)/
6
+ if place.is_a?(String) && place =~ /^((?:git[:@]|https:)[^#]*)#(.*)/
7
7
  [fake_version, { git: $1, branch: $2, require: false }].compact
8
8
  elsif place.is_a?(String) && place =~ /^file:\/\/(.*)/
9
9
  ['>= 0', { path: File.expand_path($1), require: false }]
@@ -29,7 +29,7 @@ group(:features) do
29
29
  #gem 'ruby-shadow', '~> 2.5', require: false, platforms: [:ruby]
30
30
  gem 'minitar', '~> 0.9', require: false
31
31
  gem 'msgpack', '~> 1.2', require: false
32
- gem 'rdoc', '~> 6.0', require: false, platforms: [:ruby]
32
+ gem 'rdoc', ['~> 6.0', '< 6.4.0'], require: false, platforms: [:ruby]
33
33
  # requires native augeas headers/libs
34
34
  # gem 'ruby-augeas', require: false, platforms: [:ruby]
35
35
  # requires native ldap headers/libs
data/Gemfile.lock CHANGED
@@ -1,18 +1,21 @@
1
1
  GIT
2
- remote: git://github.com/puppetlabs/packaging
3
- revision: 4c5359786cad0d12877e10e98948065bfeb3e304
2
+ remote: https://github.com/puppetlabs/packaging
3
+ revision: 6edc2f8e4ebe3cbea96c3af9c294bcd6e2953648
4
4
  branch: 1.0.x
5
5
  specs:
6
- packaging (0.103.0)
7
- artifactory (~> 2)
6
+ packaging (0.107.0.9.g6edc2f8)
7
+ apt_stage_artifacts
8
+ artifactory (~> 3)
8
9
  csv (= 3.1.5)
10
+ google-cloud-storage
11
+ googleauth
9
12
  rake (>= 12.3)
10
13
  release-metrics
11
14
 
12
15
  PATH
13
16
  remote: .
14
17
  specs:
15
- puppet (6.25.1)
18
+ puppet (6.28.0)
16
19
  CFPropertyList (~> 2.2)
17
20
  concurrent-ruby (~> 1.0)
18
21
  deep_merge (~> 1.0)
@@ -30,21 +33,30 @@ GEM
30
33
  CFPropertyList (2.3.6)
31
34
  addressable (2.8.0)
32
35
  public_suffix (>= 2.0.2, < 5.0)
33
- artifactory (2.8.2)
36
+ apt_stage_artifacts (0.11.0)
37
+ docopt
38
+ artifactory (3.0.15)
34
39
  ast (2.4.2)
35
40
  coderay (1.1.3)
36
- concurrent-ruby (1.1.9)
41
+ concurrent-ruby (1.1.10)
37
42
  crack (0.4.5)
38
43
  rexml
39
44
  csv (3.1.5)
40
- deep_merge (1.2.1)
41
- diff-lcs (1.4.4)
45
+ declarative (0.0.20)
46
+ deep_merge (1.2.2)
47
+ diff-lcs (1.5.0)
48
+ digest-crc (0.6.4)
49
+ rake (>= 12.0.0, < 14.0.0)
42
50
  docopt (0.6.1)
43
- facter (4.2.5)
51
+ facter (4.2.10)
44
52
  hocon (~> 1.3)
45
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)
46
58
  fast_gettext (1.1.2)
47
- ffi (1.15.4)
59
+ ffi (1.15.5)
48
60
  gettext (3.2.9)
49
61
  locale (>= 2.0.5)
50
62
  text (>= 1.3.0)
@@ -52,9 +64,43 @@ GEM
52
64
  fast_gettext (~> 1.1.0)
53
65
  gettext (>= 3.0.2, < 3.3.0)
54
66
  locale
67
+ google-apis-core (0.7.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.13.0)
77
+ google-apis-core (>= 0.7, < 2.a)
78
+ google-apis-storage_v1 (0.18.0)
79
+ google-apis-core (>= 0.7, < 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.37.0)
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.2.0)
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)
55
101
  hashdiff (1.0.1)
56
- hiera (3.7.0)
57
- hiera-eyaml (3.2.2)
102
+ hiera (3.9.0)
103
+ hiera-eyaml (3.3.0)
58
104
  highline
59
105
  optimist
60
106
  highline (2.0.3)
@@ -63,56 +109,65 @@ GEM
63
109
  httpclient (2.8.3)
64
110
  json-schema (2.8.1)
65
111
  addressable (>= 2.4)
112
+ jwt (2.4.1)
66
113
  locale (2.1.3)
114
+ memoist (0.16.2)
67
115
  memory_profiler (1.0.0)
68
116
  method_source (1.0.0)
117
+ mini_mime (1.1.2)
69
118
  minitar (0.9)
70
- msgpack (1.4.2)
119
+ msgpack (1.5.3)
71
120
  multi_json (1.15.0)
72
121
  mustache (1.1.1)
73
122
  optimist (3.0.1)
74
- parallel (1.21.0)
123
+ os (1.1.4)
124
+ parallel (1.22.1)
75
125
  parser (2.7.2.0)
76
126
  ast (~> 2.4.1)
77
127
  powerpack (0.1.3)
78
128
  pry (0.14.1)
79
129
  coderay (~> 1.1)
80
130
  method_source (~> 1.0)
81
- public_suffix (4.0.6)
131
+ public_suffix (4.0.7)
82
132
  puppet-resource_api (1.8.14)
83
133
  hocon (>= 1.0)
84
- puppetserver-ca (1.11.6)
134
+ puppetserver-ca (1.11.7)
85
135
  facter (>= 2.0.1, < 5)
86
136
  racc (1.5.2)
87
137
  rainbow (2.2.2)
88
138
  rake
89
139
  rake (12.3.3)
90
140
  rdiscount (2.2.0.2)
91
- rdoc (6.3.2)
141
+ rdoc (6.3.3)
92
142
  release-metrics (1.1.0)
93
143
  csv
94
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)
95
150
  rexml (3.2.5)
96
151
  ronn (0.7.3)
97
152
  hpricot (>= 0.8.2)
98
153
  mustache (>= 0.7.0)
99
154
  rdiscount (>= 1.5.8)
100
- rspec (3.10.0)
101
- rspec-core (~> 3.10.0)
102
- rspec-expectations (~> 3.10.0)
103
- rspec-mocks (~> 3.10.0)
104
- rspec-core (3.10.1)
105
- rspec-support (~> 3.10.0)
106
- rspec-expectations (3.10.1)
155
+ rspec (3.11.0)
156
+ rspec-core (~> 3.11.0)
157
+ rspec-expectations (~> 3.11.0)
158
+ rspec-mocks (~> 3.11.0)
159
+ rspec-core (3.11.0)
160
+ rspec-support (~> 3.11.0)
161
+ rspec-expectations (3.11.0)
107
162
  diff-lcs (>= 1.2.0, < 2.0)
108
- rspec-support (~> 3.10.0)
163
+ rspec-support (~> 3.11.0)
109
164
  rspec-its (1.3.0)
110
165
  rspec-core (>= 3.0.0)
111
166
  rspec-expectations (>= 3.0.0)
112
- rspec-mocks (3.10.2)
167
+ rspec-mocks (3.11.1)
113
168
  diff-lcs (>= 1.2.0, < 2.0)
114
- rspec-support (~> 3.10.0)
115
- rspec-support (3.10.2)
169
+ rspec-support (~> 3.11.0)
170
+ rspec-support (3.11.0)
116
171
  rubocop (0.49.1)
117
172
  parallel (~> 1.10)
118
173
  parser (>= 2.3.3.1, < 3.0)
@@ -124,19 +179,30 @@ GEM
124
179
  rubocop (~> 0.49.0)
125
180
  ruby-prof (1.4.3)
126
181
  ruby-progressbar (1.11.0)
182
+ ruby2_keywords (0.0.5)
183
+ scanf (1.0.0)
127
184
  semantic_puppet (1.0.4)
185
+ signet (0.17.0)
186
+ addressable (~> 2.8)
187
+ faraday (>= 0.17.5, < 3.a)
188
+ jwt (>= 1.5, < 3.0)
189
+ multi_json (~> 1.10)
128
190
  text (1.3.1)
129
- thor (1.1.0)
191
+ thor (1.2.1)
192
+ trailblazer-option (0.1.2)
193
+ uber (0.1.0)
130
194
  unicode-display_width (1.8.0)
131
195
  vcr (5.1.0)
132
196
  webmock (3.14.0)
133
197
  addressable (>= 2.8.0)
134
198
  crack (>= 0.3.2)
135
199
  hashdiff (>= 0.4.0, < 2.0.0)
136
- yard (0.9.26)
200
+ webrick (1.7.0)
201
+ yard (0.9.28)
202
+ webrick (~> 1.7.0)
137
203
 
138
204
  PLATFORMS
139
- ruby
205
+ x86_64-linux
140
206
 
141
207
  DEPENDENCIES
142
208
  diff-lcs (~> 1.3)
@@ -155,7 +221,7 @@ DEPENDENCIES
155
221
  puppetserver-ca (~> 1.1)
156
222
  racc (= 1.5.2)
157
223
  rake (~> 12.2)
158
- rdoc (~> 6.0)
224
+ rdoc (~> 6.0, < 6.4.0)
159
225
  ronn (~> 0.7.3)
160
226
  rspec (~> 3.1)
161
227
  rspec-expectations (~> 3.9, != 3.9.3)
@@ -163,10 +229,11 @@ DEPENDENCIES
163
229
  rubocop (~> 0.49)
164
230
  rubocop-i18n (~> 1.2.0)
165
231
  ruby-prof (>= 0.16.0)
232
+ scanf
166
233
  semantic_puppet (~> 1.0)
167
234
  vcr (~> 5.0)
168
235
  webmock (~> 3.0)
169
236
  yard
170
237
 
171
238
  BUNDLED WITH
172
- 1.17.3
239
+ 2.3.10
data/lib/puppet/agent.rb CHANGED
@@ -38,26 +38,51 @@ class Puppet::Agent
38
38
  # Perform a run with our client.
39
39
  def run(client_options = {})
40
40
  if disabled?
41
- Puppet.notice _("Skipping run of %{client_class}; administratively disabled (Reason: '%{disable_message}');\nUse 'puppet agent --enable' to re-enable.") % { client_class: client_class, disable_message: disable_message }
41
+ log_disabled_message
42
42
  return
43
43
  end
44
44
 
45
45
  result = nil
46
46
  wait_for_lock_deadline = nil
47
47
  block_run = Puppet::Application.controlled_run do
48
- splay client_options.fetch :splay, Puppet[:splay]
48
+ # splay may sleep for awhile when running onetime! If not onetime, then
49
+ # the job scheduler splays (only once) so that agents assign themselves a
50
+ # slot within the splay interval.
51
+ do_splay = client_options.fetch(:splay, Puppet[:splay])
52
+ if do_splay
53
+ splay(do_splay)
54
+
55
+ if disabled?
56
+ log_disabled_message
57
+ break
58
+ end
59
+ end
60
+
61
+ # waiting for certs may sleep for awhile depending on onetime, waitforcert and maxwaitforcert!
62
+ # this needs to happen before forking so that if we fail to obtain certs and try to exit, then
63
+ # we exit the main process and not the forked child.
64
+ ssl_context = wait_for_certificates(client_options)
65
+
49
66
  result = run_in_fork(should_fork) do
50
67
  with_client(client_options[:transaction_uuid], client_options[:job_id]) do |client|
51
68
  client_args = client_options.merge(:pluginsync => Puppet::Configurer.should_pluginsync?)
52
69
  begin
70
+ # lock may sleep for awhile depending on waitforlock and maxwaitforlock!
53
71
  lock do
54
- # NOTE: Timeout is pretty heinous as the location in which it
55
- # throws an error is entirely unpredictable, which means that
56
- # it can interrupt code blocks that perform cleanup or enforce
57
- # sanity. The only thing a Puppet agent should do after this
58
- # error is thrown is die with as much dignity as possible.
59
- Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do
60
- client.run(client_args)
72
+ if disabled?
73
+ log_disabled_message
74
+ nil
75
+ else
76
+ # NOTE: Timeout is pretty heinous as the location in which it
77
+ # throws an error is entirely unpredictable, which means that
78
+ # it can interrupt code blocks that perform cleanup or enforce
79
+ # sanity. The only thing a Puppet agent should do after this
80
+ # error is thrown is die with as much dignity as possible.
81
+ Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do
82
+ Puppet.override(ssl_context: ssl_context) do
83
+ client.run(client_args)
84
+ end
85
+ end
61
86
  end
62
87
  end
63
88
  rescue Puppet::LockError
@@ -78,12 +103,13 @@ class Puppet::Agent
78
103
  end
79
104
  rescue RunTimeoutError => detail
80
105
  Puppet.log_exception(detail, _("Execution of %{client_class} did not complete within %{runtimeout} seconds and was terminated.") %
81
- {client_class: client_class,
82
- runtimeout: Puppet[:runtimeout]})
106
+ {client_class: client_class, runtimeout: Puppet[:runtimeout]})
83
107
  nil
84
108
  rescue StandardError => detail
85
109
  Puppet.log_exception(detail, _("Could not run %{client_class}: %{detail}") % { client_class: client_class, detail: detail })
86
110
  nil
111
+ ensure
112
+ Puppet.runtime[:http].close
87
113
  end
88
114
  end
89
115
  end
@@ -137,4 +163,14 @@ class Puppet::Agent
137
163
  ensure
138
164
  @client = nil
139
165
  end
166
+
167
+ def wait_for_certificates(options)
168
+ waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
169
+ sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert, onetime: Puppet[:onetime])
170
+ sm.ensure_client_certificate
171
+ end
172
+
173
+ def log_disabled_message
174
+ Puppet.notice _("Skipping run of %{client_class}; administratively disabled (Reason: '%{disable_message}');\nUse 'puppet agent --enable' to re-enable.") % { client_class: client_class, disable_message: disable_message }
175
+ end
140
176
  end
@@ -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(ssl_context: ssl_context,
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
@@ -7,6 +7,7 @@ class Puppet::Application::Lookup < Puppet::Application
7
7
 
8
8
  RUN_HELP = _("Run 'puppet lookup --help' for more details").freeze
9
9
  DEEP_MERGE_OPTIONS = '--knock-out-prefix, --sort-merged-arrays, and --merge-hash-arrays'.freeze
10
+ TRUSTED_INFORMATION_FACTS = ["hostname", "domain", "fqdn", "clientcert"].freeze
10
11
 
11
12
  run_mode :server
12
13
 
@@ -54,11 +55,7 @@ class Puppet::Application::Lookup < Puppet::Application
54
55
  end
55
56
 
56
57
  option('--facts FACT_FILE') do |arg|
57
- if %w{.yaml .yml .json}.include?(arg.match(/\.[^.]*$/)[0])
58
- options[:fact_file] = arg
59
- else
60
- raise _("The --fact file only accepts yaml and json files.\n%{run_help}") % { run_help: RUN_HELP }
61
- end
58
+ options[:fact_file] = arg
62
59
  end
63
60
 
64
61
  def app_defaults
@@ -137,7 +134,9 @@ DESCRIPTION
137
134
  The lookup command is a CLI for Puppet's 'lookup()' function. It searches your
138
135
  Hiera data and returns a value for the requested lookup key, so you can test and
139
136
  explore your data. It is a modern replacement for the 'hiera' command.
140
-
137
+ Lookup uses the setting for global hiera.yaml from puppet's config,
138
+ and the environment to find the environment level hiera.yaml as well as the
139
+ resulting modulepath for the environment (for hiera.yaml files in modules).
141
140
  Hiera usually relies on a node's facts to locate the relevant data sources. By
142
141
  default, 'puppet lookup' uses facts from the node you run the command on, but
143
142
  you can get data for any other node with the '--node <NAME>' option. If
@@ -186,7 +185,8 @@ OPTIONS
186
185
  * --environment <ENV>
187
186
  Like with most Puppet commands, you can specify an environment on the command
188
187
  line. This is important for lookup because different environments can have
189
- different Hiera data.
188
+ different Hiera data. This environment will be always be the one used regardless
189
+ of any other factors.
190
190
 
191
191
  * --merge first|unique|hash|deep:
192
192
  Specify the merge behavior, overriding any merge behavior from the data's
@@ -237,6 +237,13 @@ EXAMPLE
237
237
  To look up 'key_name' using the Puppet Server node's facts:
238
238
  $ puppet lookup key_name
239
239
 
240
+ To look up 'key_name' using the Puppet Server node's arbitrary variables from a manifest, and
241
+ classify the node if applicable:
242
+ $ puppet lookup key_name --compile
243
+
244
+ To look up 'key_name' using the Puppet Server node's facts, overridden by facts given in a file:
245
+ $ puppet lookup key_name --facts fact_file.yaml
246
+
240
247
  To look up 'key_name' with agent.local's facts:
241
248
  $ puppet lookup --node agent.local key_name
242
249
 
@@ -341,31 +348,62 @@ Copyright (c) 2015 Puppet Inc., LLC Licensed under the Apache 2.0 License
341
348
  Puppet.settings[:facts_terminus] = 'facter'
342
349
  end
343
350
 
344
- unless node.is_a?(Puppet::Node) # to allow unit tests to pass a node instance
345
- ni = Puppet::Node.indirection
346
- tc = ni.terminus_class
347
- if tc == :plain || options[:compile]
348
- node = ni.find(node)
349
- else
350
- ni.terminus_class = :plain
351
- node = ni.find(node)
352
- ni.terminus_class = tc
353
- end
354
- end
355
-
356
351
  fact_file = options[:fact_file]
357
352
 
358
353
  if fact_file
359
- if fact_file.end_with?("json")
360
- given_facts = Puppet::Util::Json.load(Puppet::FileSystem.read(fact_file, :encoding => 'utf-8'))
361
- else
354
+ if fact_file.end_with?('.json')
355
+ given_facts = Puppet::Util::Json.load_file(fact_file)
356
+ elsif fact_file.end_with?('.yml', '.yaml')
362
357
  given_facts = Puppet::Util::Yaml.safe_load_file(fact_file)
358
+ else
359
+ given_facts = Puppet::Util::Json.load_file_if_valid(fact_file)
360
+ given_facts = Puppet::Util::Yaml.safe_load_file_if_valid(fact_file) unless given_facts
363
361
  end
364
362
 
365
363
  unless given_facts.instance_of?(Hash)
366
- raise _("Incorrect formatted data in %{fact_file} given via the --facts flag") % { fact_file: fact_file }
364
+ raise _("Incorrectly formatted data in %{fact_file} given via the --facts flag (only accepts yaml and json files)") % { fact_file: fact_file }
365
+ end
366
+
367
+ if TRUSTED_INFORMATION_FACTS.any? { |key| given_facts.key? key }
368
+ unless TRUSTED_INFORMATION_FACTS.all? { |key| given_facts.key? key }
369
+ raise _("When overriding any of the %{trusted_facts_list} facts with %{fact_file} "\
370
+ "given via the --facts flag, they must all be overridden.") % { fact_file: fact_file ,trusted_facts_list: TRUSTED_INFORMATION_FACTS.join(',')}
371
+ end
367
372
  end
368
- node.add_extra_facts(given_facts)
373
+ end
374
+
375
+ unless node.is_a?(Puppet::Node) # to allow unit tests to pass a node instance
376
+ facts = retrieve_node_facts(node, given_facts)
377
+ ni = Puppet::Node.indirection
378
+ tc = ni.terminus_class
379
+ if options[:compile] && !Puppet.settings.set_by_cli?('environment')
380
+ if tc == :plain
381
+ node = ni.find(node, facts: facts)
382
+ else
383
+ begin
384
+ service = Puppet.runtime[:http]
385
+ session = service.create_session
386
+ cert = session.route_to(:ca)
387
+
388
+ _, x509 = cert.get_certificate(node)
389
+ cert = OpenSSL::X509::Certificate.new(x509)
390
+ Puppet::SSL::Oids.register_puppet_oids
391
+ trusted = Puppet::Context::TrustedInformation.remote(true, facts.values['certname'] || node, Puppet::SSL::Certificate.from_instance(cert))
392
+ Puppet.override(trusted_information: trusted) do
393
+ node = ni.find(node, facts: facts)
394
+ end
395
+ rescue
396
+ Puppet.warning _("CA is not available, the operation will continue without using trusted facts.")
397
+ node = ni.find(node, facts: facts)
398
+ end
399
+ end
400
+ else
401
+ ni.terminus_class = :plain
402
+ node = ni.find(node, facts: facts, environment: Puppet[:environment])
403
+ ni.terminus_class = tc
404
+ end
405
+ else
406
+ node.add_extra_facts(given_facts) if given_facts
369
407
  end
370
408
 
371
409
  Puppet[:code] = 'undef' unless options[:compile]
@@ -378,4 +416,16 @@ Copyright (c) 2015 Puppet Inc., LLC Licensed under the Apache 2.0 License
378
416
  compiler.compile { |catalog| yield(compiler.topscope); catalog }
379
417
  end
380
418
  end
419
+
420
+ def retrieve_node_facts(node, given_facts)
421
+ facts = Puppet::Node::Facts.indirection.find(node, :environment => Puppet.lookup(:current_environment))
422
+
423
+ facts = Puppet::Node::Facts.new(node, {}) if facts.nil?
424
+ facts.add_extra_values(given_facts) if given_facts
425
+
426
+ if facts.values.empty?
427
+ raise _("No facts available for target node: %{node}") % { node: node}
428
+ end
429
+ facts
430
+ end
381
431
  end
@@ -5,10 +5,12 @@ module Puppet
5
5
  def singleton
6
6
  key = (name + ".singleton").intern
7
7
  thread = Thread.current
8
- unless thread.thread_variable?(key)
9
- thread.thread_variable_set(key, new)
8
+ value = thread.thread_variable_get(key)
9
+ if value.nil?
10
+ value = new
11
+ thread.thread_variable_set(key, value)
10
12
  end
11
- thread.thread_variable_get(key)
13
+ value
12
14
  end
13
15
  end
14
16
  end
@@ -304,7 +304,7 @@ class Puppet::Configurer
304
304
  Puppet.debug(_("Environment not passed via CLI and no catalog was given, attempting to find out the last server-specified environment"))
305
305
  initial_environment, loaded_last_environment = last_server_specified_environment
306
306
 
307
- unless loaded_last_environment
307
+ unless Puppet[:use_last_environment] && loaded_last_environment
308
308
  Puppet.debug(_("Requesting environment from the server"))
309
309
  initial_environment = current_server_specified_environment(@environment, configured_environment, options)
310
310
  end
@@ -330,7 +330,7 @@ class Puppet::Configurer
330
330
  temp_value = options[:pluginsync]
331
331
 
332
332
  # only validate server environment if pluginsync is requested
333
- options[:pluginsync] = valid_server_environment? if options[:pluginsync] == true
333
+ options[:pluginsync] = valid_server_environment? if options[:pluginsync]
334
334
 
335
335
  query_options, facts = get_facts(options) unless query_options
336
336
  options[:pluginsync] = temp_value
@@ -443,7 +443,11 @@ class Puppet::Configurer
443
443
  true
444
444
  rescue Puppet::HTTP::ResponseError => detail
445
445
  if detail.response.code == 404
446
- Puppet.notice(_("Environment '%{environment}' not found on server, skipping initial pluginsync.") % { environment: @environment })
446
+ if Puppet[:strict_environment_mode]
447
+ raise Puppet::Error.new(_("Environment '%{environment}' not found on server, aborting run.") % { environment: @environment })
448
+ else
449
+ Puppet.notice(_("Environment '%{environment}' not found on server, skipping initial pluginsync.") % { environment: @environment })
450
+ end
447
451
  else
448
452
  Puppet.log_exception(detail, detail.message)
449
453
  end
@@ -513,17 +517,7 @@ class Puppet::Configurer
513
517
  :transaction_uuid => @transaction_uuid,
514
518
  :fail_on_404 => true)
515
519
 
516
- # The :rest node terminus returns a node with an environment_name, but not an
517
- # environment instance. Attempting to get the environment instance will load
518
- # it from disk, which will likely fail. So create a remote environment.
519
- #
520
- # The :plain node terminus returns a node with an environment, but not an
521
- # environment_name.
522
- if !node.has_environment_instance? && node.environment_name
523
- node.environment = Puppet::Node::Environment.remote(node.environment_name)
524
- end
525
-
526
- @server_specified_environment = node.environment.to_s
520
+ @server_specified_environment = node.environment_name.to_s
527
521
 
528
522
  if @server_specified_environment != @environment
529
523
  Puppet.notice _("Local environment: '%{local_env}' doesn't match server specified node environment '%{node_env}', switching agent to '%{node_env}'.") % { local_env: @environment, node_env: @server_specified_environment }
@@ -442,6 +442,17 @@ module Puppet
442
442
  <https://puppet.com/docs/puppet/latest/environments_about.html>",
443
443
  :type => :path,
444
444
  },
445
+ :use_last_environment => {
446
+ :type => :boolean,
447
+ :default => true,
448
+ :desc => <<-'EOT'
449
+ Puppet saves both the initial and converged environment in the last_run_summary file.
450
+ If they differ, and this setting is set to true, we will use the last converged
451
+ environment and skip the node request.
452
+
453
+ When set to false, we will do the node request and ignore the environment data from the last_run_summary file.
454
+ EOT
455
+ },
445
456
  :always_retry_plugins => {
446
457
  :type => :boolean,
447
458
  :default => true,
@@ -2056,7 +2067,8 @@ EOT
2056
2067
  :call_hook => :on_initialize_and_write, # Call our hook with the default value, so we always get the value added to facter.
2057
2068
  :hook => proc do |value|
2058
2069
  paths = value.split(File::PATH_SEPARATOR)
2059
- Puppet.runtime[:facter].search(*paths)
2070
+ facter = Puppet.runtime[:facter]
2071
+ facter.search(*paths)
2060
2072
  end
2061
2073
  }
2062
2074
  )
@@ -2197,8 +2209,6 @@ EOT
2197
2209
  # Call our hook with the default value, so we always get the libdir set.
2198
2210
  :call_hook => :on_initialize_and_write,
2199
2211
  :hook => proc do |value|
2200
- require 'puppet/node'
2201
- require 'puppet/node/facts'
2202
2212
  if value
2203
2213
  Puppet::Resource::Catalog.indirection.set_global_setting(:cache_class, :store_configs)
2204
2214
  settings.override_default(:catalog_cache_terminus, :store_configs)
@@ -58,6 +58,8 @@ Puppet::Face.define(:generate, '0.1.0') do
58
58
  Puppet::FileSystem::mkpath(outputdir)
59
59
 
60
60
  generator.generate(inputs, outputdir, options[:force])
61
+
62
+ exit(1) if generator.bad_input?
61
63
  nil
62
64
  end
63
65
  end