puppet 7.12.1 → 7.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +36 -31
  5. data/ext/project_data.yaml +1 -1
  6. data/lib/puppet/application/lookup.rb +74 -24
  7. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  8. data/lib/puppet/configurer.rb +8 -14
  9. data/lib/puppet/defaults.rb +13 -1
  10. data/lib/puppet/face/generate.rb +2 -0
  11. data/lib/puppet/file_serving/metadata.rb +3 -0
  12. data/lib/puppet/file_system/file_impl.rb +7 -7
  13. data/lib/puppet/file_system/jruby.rb +1 -1
  14. data/lib/puppet/file_system/path_pattern.rb +10 -15
  15. data/lib/puppet/file_system/uniquefile.rb +1 -1
  16. data/lib/puppet/file_system/windows.rb +4 -4
  17. data/lib/puppet/file_system.rb +1 -1
  18. data/lib/puppet/functions/next.rb +18 -1
  19. data/lib/puppet/functions/tree_each.rb +0 -1
  20. data/lib/puppet/functions/versioncmp.rb +6 -2
  21. data/lib/puppet/generate/type.rb +9 -0
  22. data/lib/puppet/graph/simple_graph.rb +2 -1
  23. data/lib/puppet/http/client.rb +1 -1
  24. data/lib/puppet/node.rb +1 -1
  25. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  26. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  27. data/lib/puppet/pops/parser/eparser.rb +574 -558
  28. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  29. data/lib/puppet/pops/validation/checker4_0.rb +7 -2
  30. data/lib/puppet/provider/service/init.rb +5 -4
  31. data/lib/puppet/resource/type_collection.rb +21 -17
  32. data/lib/puppet/ssl/verifier.rb +3 -1
  33. data/lib/puppet/transaction/persistence.rb +22 -12
  34. data/lib/puppet/type/exec.rb +1 -1
  35. data/lib/puppet/type/file/data_sync.rb +1 -1
  36. data/lib/puppet/type/file/group.rb +8 -1
  37. data/lib/puppet/type/file/owner.rb +8 -1
  38. data/lib/puppet/type/user.rb +41 -39
  39. data/lib/puppet/util/json.rb +17 -0
  40. data/lib/puppet/util/log.rb +7 -2
  41. data/lib/puppet/util/monkey_patches.rb +26 -4
  42. data/lib/puppet/util/package.rb +25 -16
  43. data/lib/puppet/util/yaml.rb +16 -1
  44. data/lib/puppet/util.rb +1 -0
  45. data/lib/puppet/version.rb +1 -1
  46. data/lib/puppet.rb +1 -0
  47. data/locales/puppet.pot +5 -9741
  48. data/man/man5/puppet.conf.5 +21 -2
  49. data/man/man8/puppet-agent.8 +1 -1
  50. data/man/man8/puppet-apply.8 +1 -1
  51. data/man/man8/puppet-catalog.8 +1 -1
  52. data/man/man8/puppet-config.8 +1 -1
  53. data/man/man8/puppet-describe.8 +1 -1
  54. data/man/man8/puppet-device.8 +1 -1
  55. data/man/man8/puppet-doc.8 +1 -1
  56. data/man/man8/puppet-epp.8 +1 -1
  57. data/man/man8/puppet-facts.8 +1 -1
  58. data/man/man8/puppet-filebucket.8 +1 -1
  59. data/man/man8/puppet-generate.8 +1 -1
  60. data/man/man8/puppet-help.8 +1 -1
  61. data/man/man8/puppet-lookup.8 +9 -6
  62. data/man/man8/puppet-module.8 +1 -1
  63. data/man/man8/puppet-node.8 +1 -1
  64. data/man/man8/puppet-parser.8 +1 -1
  65. data/man/man8/puppet-plugin.8 +1 -1
  66. data/man/man8/puppet-report.8 +1 -1
  67. data/man/man8/puppet-resource.8 +1 -1
  68. data/man/man8/puppet-script.8 +1 -1
  69. data/man/man8/puppet-ssl.8 +1 -1
  70. data/man/man8/puppet.8 +2 -2
  71. data/spec/fixtures/unit/forge/bacula.json +1 -1
  72. data/spec/integration/application/lookup_spec.rb +81 -50
  73. data/spec/integration/application/resource_spec.rb +6 -2
  74. data/spec/integration/parser/pcore_resource_spec.rb +10 -0
  75. data/spec/shared_contexts/l10n.rb +5 -0
  76. data/spec/unit/application/lookup_spec.rb +131 -10
  77. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  78. data/spec/unit/configurer_spec.rb +124 -61
  79. data/spec/unit/confiner_spec.rb +6 -6
  80. data/spec/unit/face/generate_spec.rb +64 -0
  81. data/spec/unit/file_system/uniquefile_spec.rb +7 -1
  82. data/spec/unit/file_system_spec.rb +34 -4
  83. data/spec/unit/forge/module_release_spec.rb +3 -3
  84. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  85. data/spec/unit/node_spec.rb +6 -0
  86. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  87. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  88. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  89. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  90. data/spec/unit/provider/service/init_spec.rb +15 -9
  91. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  92. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  93. data/spec/unit/transaction/persistence_spec.rb +51 -0
  94. data/spec/unit/type/file/group_spec.rb +7 -0
  95. data/spec/unit/type/file/owner_spec.rb +7 -0
  96. data/spec/unit/type/user_spec.rb +67 -45
  97. data/spec/unit/util/json_spec.rb +126 -0
  98. data/spec/unit/util/windows_spec.rb +23 -0
  99. data/spec/unit/util/yaml_spec.rb +37 -13
  100. metadata +17 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c9a5ad10d1fe29d4c28a410c34cc28236cc3a678444e72cdbcbd824ead10f99
4
- data.tar.gz: 104352f3f069d1f9043dc386f035f0c18da3bbc09f1715092b682a6508b97842
3
+ metadata.gz: 236ffe679e7475017af27237b3584914e21fdc4c40640f1068b4f25a683b2b3c
4
+ data.tar.gz: e0ab738928ad2ff627eb22060064b02016fce0aa742eb0bd995d3cfbffd7ed2a
5
5
  SHA512:
6
- metadata.gz: 45dcb3ec19cc2b62b3a642a3adbe3697a08eee3f6f79158b30e4b32dfecc4eb908f4d0c7a22958606b2cf3ba4cfefc93f17108b1ec159e49bdb4ed18540538aa
7
- data.tar.gz: d5efd563f4a3bd518883d6ed8b8721cff49b81b9f0ccc0a382bb3e96ac4262ebbfe6535a12451f6d6a4ff61399cc5e79aeb64e13832443998dba2fa0fb2702ba
6
+ metadata.gz: a011343c68d88f25ec0ea67c2a47c74c826a67b1c354365c8d51d39ab3a08c622cc0f9ed631670b13fea35485467757be5aee34e1e94fcc4f579e862ec3040f1
7
+ data.tar.gz: 8b300a0eb554107049cf1d5fb2bc73c76e6bb4ebc24500c138da1b8dd4b0b945906231e8e3a3f97ee4f9dd8ce4913b5b944eae14dcd87296aafd05e126a950f1
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 }]
@@ -26,7 +26,7 @@ group(:features) do
26
26
  #gem 'ruby-shadow', '~> 2.5', require: false, platforms: [:ruby]
27
27
  gem 'minitar', '~> 0.9', require: false
28
28
  gem 'msgpack', '~> 1.2', require: false
29
- gem 'rdoc', '~> 6.0', require: false, platforms: [:ruby]
29
+ gem 'rdoc', ['~> 6.0', '< 6.4.0'], require: false, platforms: [:ruby]
30
30
  # requires native augeas headers/libs
31
31
  # gem 'ruby-augeas', require: false, platforms: [:ruby]
32
32
  # requires native ldap headers/libs
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  GIT
2
- remote: git://github.com/puppetlabs/packaging
3
- revision: 4c5359786cad0d12877e10e98948065bfeb3e304
2
+ remote: https://github.com/puppetlabs/packaging
3
+ revision: 478623dd22de2de32bbb7b7c340a8d80c269c9f4
4
4
  branch: 1.0.x
5
5
  specs:
6
- packaging (0.103.0)
7
- artifactory (~> 2)
6
+ packaging (0.106.0.20.g478623d)
7
+ apt_stage_artifacts
8
+ artifactory (~> 3)
8
9
  csv (= 3.1.5)
9
10
  rake (>= 12.3)
10
11
  release-metrics
@@ -12,12 +13,12 @@ GIT
12
13
  PATH
13
14
  remote: .
14
15
  specs:
15
- puppet (7.12.1)
16
+ puppet (7.15.0)
16
17
  CFPropertyList (~> 2.2)
17
18
  concurrent-ruby (~> 1.0)
18
19
  deep_merge (~> 1.0)
19
20
  facter (>= 2.4.0, < 5)
20
- fast_gettext (~> 1.1)
21
+ fast_gettext (>= 1.1, < 3)
21
22
  hiera (>= 3.2.1, < 4)
22
23
  locale (~> 2.1)
23
24
  multi_json (~> 1.13)
@@ -30,21 +31,23 @@ GEM
30
31
  CFPropertyList (2.3.6)
31
32
  addressable (2.8.0)
32
33
  public_suffix (>= 2.0.2, < 5.0)
33
- artifactory (2.8.2)
34
+ apt_stage_artifacts (0.10.1)
35
+ docopt
36
+ artifactory (3.0.15)
34
37
  ast (2.4.2)
35
38
  coderay (1.1.3)
36
39
  concurrent-ruby (1.1.9)
37
40
  crack (0.4.5)
38
41
  rexml
39
42
  csv (3.1.5)
40
- deep_merge (1.2.1)
41
- diff-lcs (1.4.4)
43
+ deep_merge (1.2.2)
44
+ diff-lcs (1.5.0)
42
45
  docopt (0.6.1)
43
- facter (4.2.5)
46
+ facter (4.2.7)
44
47
  hocon (~> 1.3)
45
48
  thor (>= 1.0.1, < 2.0)
46
49
  fast_gettext (1.1.2)
47
- ffi (1.15.4)
50
+ ffi (1.15.5)
48
51
  gettext (3.2.9)
49
52
  locale (>= 2.0.5)
50
53
  text (>= 1.3.0)
@@ -53,7 +56,7 @@ GEM
53
56
  gettext (>= 3.0.2, < 3.3.0)
54
57
  locale
55
58
  hashdiff (1.0.1)
56
- hiera (3.7.0)
59
+ hiera (3.8.0)
57
60
  hiera-eyaml (3.2.2)
58
61
  highline
59
62
  optimist
@@ -66,7 +69,7 @@ GEM
66
69
  memory_profiler (1.0.0)
67
70
  method_source (1.0.0)
68
71
  minitar (0.9)
69
- msgpack (1.4.2)
72
+ msgpack (1.4.5)
70
73
  multi_json (1.15.0)
71
74
  mustache (1.1.1)
72
75
  optimist (3.0.1)
@@ -80,14 +83,14 @@ GEM
80
83
  public_suffix (4.0.6)
81
84
  puppet-resource_api (1.8.14)
82
85
  hocon (>= 1.0)
83
- puppetserver-ca (2.3.5)
86
+ puppetserver-ca (2.3.6)
84
87
  facter (>= 2.0.1, < 5)
85
88
  racc (1.5.2)
86
89
  rainbow (2.2.2)
87
90
  rake
88
91
  rake (13.0.6)
89
92
  rdiscount (2.2.0.2)
90
- rdoc (6.3.2)
93
+ rdoc (6.3.3)
91
94
  release-metrics (1.1.0)
92
95
  csv
93
96
  docopt
@@ -96,22 +99,22 @@ GEM
96
99
  hpricot (>= 0.8.2)
97
100
  mustache (>= 0.7.0)
98
101
  rdiscount (>= 1.5.8)
99
- rspec (3.10.0)
100
- rspec-core (~> 3.10.0)
101
- rspec-expectations (~> 3.10.0)
102
- rspec-mocks (~> 3.10.0)
103
- rspec-core (3.10.1)
104
- rspec-support (~> 3.10.0)
105
- rspec-expectations (3.10.1)
102
+ rspec (3.11.0)
103
+ rspec-core (~> 3.11.0)
104
+ rspec-expectations (~> 3.11.0)
105
+ rspec-mocks (~> 3.11.0)
106
+ rspec-core (3.11.0)
107
+ rspec-support (~> 3.11.0)
108
+ rspec-expectations (3.11.0)
106
109
  diff-lcs (>= 1.2.0, < 2.0)
107
- rspec-support (~> 3.10.0)
110
+ rspec-support (~> 3.11.0)
108
111
  rspec-its (1.3.0)
109
112
  rspec-core (>= 3.0.0)
110
113
  rspec-expectations (>= 3.0.0)
111
- rspec-mocks (3.10.2)
114
+ rspec-mocks (3.11.0)
112
115
  diff-lcs (>= 1.2.0, < 2.0)
113
- rspec-support (~> 3.10.0)
114
- rspec-support (3.10.2)
116
+ rspec-support (~> 3.11.0)
117
+ rspec-support (3.11.0)
115
118
  rubocop (0.49.1)
116
119
  parallel (~> 1.10)
117
120
  parser (>= 2.3.3.1, < 3.0)
@@ -126,17 +129,19 @@ GEM
126
129
  scanf (1.0.0)
127
130
  semantic_puppet (1.0.4)
128
131
  text (1.3.1)
129
- thor (1.1.0)
132
+ thor (1.2.1)
130
133
  unicode-display_width (1.8.0)
131
134
  vcr (5.1.0)
132
135
  webmock (3.14.0)
133
136
  addressable (>= 2.8.0)
134
137
  crack (>= 0.3.2)
135
138
  hashdiff (>= 0.4.0, < 2.0.0)
136
- yard (0.9.26)
139
+ webrick (1.7.0)
140
+ yard (0.9.27)
141
+ webrick (~> 1.7.0)
137
142
 
138
143
  PLATFORMS
139
- ruby
144
+ x86_64-linux
140
145
 
141
146
  DEPENDENCIES
142
147
  diff-lcs (~> 1.3)
@@ -155,7 +160,7 @@ DEPENDENCIES
155
160
  puppetserver-ca (~> 2.0)
156
161
  racc (= 1.5.2)
157
162
  rake (~> 13.0)
158
- rdoc (~> 6.0)
163
+ rdoc (~> 6.0, < 6.4.0)
159
164
  ronn (~> 0.7.3)
160
165
  rspec (~> 3.1)
161
166
  rspec-expectations (~> 3.9, != 3.9.3)
@@ -169,4 +174,4 @@ DEPENDENCIES
169
174
  yard
170
175
 
171
176
  BUNDLED WITH
172
- 1.17.3
177
+ 2.3.8
@@ -21,7 +21,7 @@ gem_runtime_dependencies:
21
21
  facter: ['> 2.0.1', '< 5']
22
22
  hiera: ['>= 3.2.1', '< 4']
23
23
  semantic_puppet: '~> 1.0'
24
- fast_gettext: '~> 1.1'
24
+ fast_gettext: ['>= 1.1', '< 3']
25
25
  locale: '~> 2.1'
26
26
  multi_json: '~> 1.10'
27
27
  puppet-resource_api: '~>1.5'
@@ -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
@@ -392,7 +392,7 @@ class Puppet::Configurer
392
392
  Puppet.debug(_("Environment not passed via CLI and no catalog was given, attempting to find out the last server-specified environment"))
393
393
  initial_environment, loaded_last_environment = last_server_specified_environment
394
394
 
395
- unless loaded_last_environment
395
+ unless Puppet[:use_last_environment] && loaded_last_environment
396
396
  Puppet.debug(_("Requesting environment from the server"))
397
397
  initial_environment = current_server_specified_environment(@environment, configured_environment, options)
398
398
  end
@@ -418,7 +418,7 @@ class Puppet::Configurer
418
418
  temp_value = options[:pluginsync]
419
419
 
420
420
  # only validate server environment if pluginsync is requested
421
- options[:pluginsync] = valid_server_environment? if options[:pluginsync] == true
421
+ options[:pluginsync] = valid_server_environment? if options[:pluginsync]
422
422
 
423
423
  query_options, facts = get_facts(options) unless query_options
424
424
  options[:pluginsync] = temp_value
@@ -531,7 +531,11 @@ class Puppet::Configurer
531
531
  true
532
532
  rescue Puppet::HTTP::ResponseError => detail
533
533
  if detail.response.code == 404
534
- Puppet.notice(_("Environment '%{environment}' not found on server, skipping initial pluginsync.") % { environment: @environment })
534
+ if Puppet[:strict_environment_mode]
535
+ raise Puppet::Error.new(_("Environment '%{environment}' not found on server, aborting run.") % { environment: @environment })
536
+ else
537
+ Puppet.notice(_("Environment '%{environment}' not found on server, skipping initial pluginsync.") % { environment: @environment })
538
+ end
535
539
  else
536
540
  Puppet.log_exception(detail, detail.message)
537
541
  end
@@ -601,17 +605,7 @@ class Puppet::Configurer
601
605
  :transaction_uuid => @transaction_uuid,
602
606
  :fail_on_404 => true)
603
607
 
604
- # The :rest node terminus returns a node with an environment_name, but not an
605
- # environment instance. Attempting to get the environment instance will load
606
- # it from disk, which will likely fail. So create a remote environment.
607
- #
608
- # The :plain node terminus returns a node with an environment, but not an
609
- # environment_name.
610
- if !node.has_environment_instance? && node.environment_name
611
- node.environment = Puppet::Node::Environment.remote(node.environment_name)
612
- end
613
-
614
- @server_specified_environment = node.environment.to_s
608
+ @server_specified_environment = node.environment_name.to_s
615
609
 
616
610
  if @server_specified_environment != @environment
617
611
  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 }
@@ -421,6 +421,17 @@ module Puppet
421
421
  <https://puppet.com/docs/puppet/latest/environments_about.html>",
422
422
  :type => :path,
423
423
  },
424
+ :use_last_environment => {
425
+ :type => :boolean,
426
+ :default => true,
427
+ :desc => <<-'EOT'
428
+ Puppet saves both the initial and converged environment in the last_run_summary file.
429
+ If they differ, and this setting is set to true, we will use the last converged
430
+ environment and skip the node request.
431
+
432
+ When set to false, we will do the node request and ignore the environment data from the last_run_summary file.
433
+ EOT
434
+ },
424
435
  :always_retry_plugins => {
425
436
  :type => :boolean,
426
437
  :default => true,
@@ -1983,7 +1994,8 @@ EOT
1983
1994
  :call_hook => :on_initialize_and_write, # Call our hook with the default value, so we always get the value added to facter.
1984
1995
  :hook => proc do |value|
1985
1996
  paths = value.split(File::PATH_SEPARATOR)
1986
- Puppet.runtime[:facter].search(*paths)
1997
+ facter = Puppet.runtime[:facter]
1998
+ facter.search(*paths)
1987
1999
  end
1988
2000
  }
1989
2001
  )
@@ -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
@@ -118,6 +118,9 @@ class Puppet::FileServing::Metadata < Puppet::FileServing::Base
118
118
  when "link"
119
119
  @destination = Puppet::FileSystem.readlink(real_path)
120
120
  @checksum = ("{#{@checksum_type}}") + send("#{@checksum_type}_file", real_path).to_s rescue nil
121
+ when "fifo", "socket"
122
+ @checksum_type = "none"
123
+ @checksum = ("{#{@checksum_type}}") + send("#{@checksum_type}_file", real_path).to_s
121
124
  else
122
125
  raise ArgumentError, _("Cannot manage files of type %{file_type}") % { file_type: stat.ftype }
123
126
  end
@@ -130,23 +130,23 @@ class Puppet::FileSystem::FileImpl
130
130
  end
131
131
 
132
132
  def symlink?(path)
133
- File.symlink?(path)
133
+ ::File.symlink?(path)
134
134
  end
135
135
 
136
136
  def readlink(path)
137
- File.readlink(path)
137
+ ::File.readlink(path)
138
138
  end
139
139
 
140
140
  def unlink(*paths)
141
- File.unlink(*paths)
141
+ ::File.unlink(*paths)
142
142
  end
143
143
 
144
144
  def stat(path)
145
- File.stat(path)
145
+ ::File.stat(path)
146
146
  end
147
147
 
148
148
  def lstat(path)
149
- File.lstat(path)
149
+ ::File.lstat(path)
150
150
  end
151
151
 
152
152
  def compare_stream(path, stream)
@@ -159,7 +159,7 @@ class Puppet::FileSystem::FileImpl
159
159
 
160
160
  def replace_file(path, mode = nil)
161
161
  begin
162
- stat = Puppet::FileSystem.lstat(path)
162
+ stat = lstat(path)
163
163
  gid = stat.gid
164
164
  uid = stat.uid
165
165
  mode ||= stat.mode & 07777
@@ -180,7 +180,7 @@ class Puppet::FileSystem::FileImpl
180
180
  tempfile_path = tempfile.path
181
181
  FileUtils.chown(uid, gid, tempfile_path) if uid && gid
182
182
  chmod(mode, tempfile_path)
183
- File.rename(tempfile_path, Puppet::FileSystem.path_string(path))
183
+ ::File.rename(tempfile_path, path_string(path))
184
184
  ensure
185
185
  tempfile.close!
186
186
  end
@@ -14,7 +14,7 @@ class Puppet::FileSystem::JRuby < Puppet::FileSystem::Posix
14
14
  def replace_file(path, mode = nil, &block)
15
15
  # MRI Ruby rename checks if destination is a directory and raises, while
16
16
  # JRuby removes the directory and replaces the file.
17
- if Puppet::FileSystem.directory?(path)
17
+ if directory?(path)
18
18
  raise Errno::EISDIR, _("Is a directory: %{directory}") % { directory: path }
19
19
  end
20
20
 
@@ -5,10 +5,9 @@ module Puppet::FileSystem
5
5
  class PathPattern
6
6
  class InvalidPattern < Puppet::Error; end
7
7
 
8
- TRAVERSAL = /^\.\.$/
8
+ DOTDOT = '..'.freeze
9
9
  ABSOLUTE_UNIX = /^\//
10
10
  ABSOLUTE_WINDOWS = /^[a-z]:/i
11
- #ABSOLUT_VODKA #notappearinginthisclass
12
11
  CURRENT_DRIVE_RELATIVE_WINDOWS = /^\\/
13
12
 
14
13
  def self.relative(pattern)
@@ -32,11 +31,11 @@ module Puppet::FileSystem
32
31
  end
33
32
 
34
33
  def glob
35
- Dir.glob(pathname.to_s)
34
+ Dir.glob(@pathstr)
36
35
  end
37
36
 
38
37
  def to_s
39
- pathname.to_s
38
+ @pathstr
40
39
  end
41
40
 
42
41
  protected
@@ -46,13 +45,9 @@ module Puppet::FileSystem
46
45
  private
47
46
 
48
47
  def validate
49
- @pathname.each_filename do |e|
50
- if e =~ TRAVERSAL
51
- raise(InvalidPattern, _("PathPatterns cannot be created with directory traversals."))
52
- end
53
- end
54
- case @pathname.to_s
55
- when CURRENT_DRIVE_RELATIVE_WINDOWS
48
+ if @pathstr.split(Pathname::SEPARATOR_PAT).any? { |f| f == DOTDOT }
49
+ raise(InvalidPattern, _("PathPatterns cannot be created with directory traversals."))
50
+ elsif @pathstr.match?(CURRENT_DRIVE_RELATIVE_WINDOWS)
56
51
  raise(InvalidPattern, _("A PathPattern cannot be a Windows current drive relative path."))
57
52
  end
58
53
  end
@@ -60,6 +55,7 @@ module Puppet::FileSystem
60
55
  def initialize(pattern)
61
56
  begin
62
57
  @pathname = Pathname.new(pattern.strip)
58
+ @pathstr = @pathname.to_s
63
59
  rescue ArgumentError => error
64
60
  raise InvalidPattern.new(_("PathPatterns cannot be created with a zero byte."), error)
65
61
  end
@@ -74,10 +70,9 @@ module Puppet::FileSystem
74
70
 
75
71
  def validate
76
72
  super
77
- case @pathname.to_s
78
- when ABSOLUTE_WINDOWS
73
+ if @pathstr.match?(ABSOLUTE_WINDOWS)
79
74
  raise(InvalidPattern, _("A relative PathPattern cannot be prefixed with a drive."))
80
- when ABSOLUTE_UNIX
75
+ elsif @pathstr.match?(ABSOLUTE_UNIX)
81
76
  raise(InvalidPattern, _("A relative PathPattern cannot be an absolute path."))
82
77
  end
83
78
  end
@@ -90,7 +85,7 @@ module Puppet::FileSystem
90
85
 
91
86
  def validate
92
87
  super
93
- if @pathname.to_s !~ ABSOLUTE_UNIX and @pathname.to_s !~ ABSOLUTE_WINDOWS
88
+ if !@pathstr.match?(ABSOLUTE_UNIX) && !@pathstr.match?(ABSOLUTE_WINDOWS)
94
89
  raise(InvalidPattern, _("An absolute PathPattern cannot be a relative path."))
95
90
  end
96
91
  end
@@ -127,7 +127,7 @@ class Puppet::FileSystem::Uniquefile < DelegateClass(File)
127
127
  tmpdir ||= tmpdir()
128
128
  n = nil
129
129
  begin
130
- path = File.expand_path(make_tmpname(basename, n), tmpdir)
130
+ path = File.join(tmpdir, make_tmpname(basename, n))
131
131
  yield(path, n, *opts)
132
132
  rescue Errno::EEXIST
133
133
  n ||= 0
@@ -123,7 +123,7 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
123
123
  LOCK_VIOLATION = 33
124
124
 
125
125
  def replace_file(path, mode = nil)
126
- if Puppet::FileSystem.directory?(path)
126
+ if directory?(path)
127
127
  raise Errno::EISDIR, _("Is a directory: %{directory}") % { directory: path }
128
128
  end
129
129
 
@@ -159,14 +159,14 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
159
159
  end
160
160
 
161
161
  set_dacl(tempfile.path, dacl) if dacl
162
- File.rename(tempfile.path, Puppet::FileSystem.path_string(path))
162
+ ::File.rename(tempfile.path, path_string(path))
163
163
  ensure
164
164
  tempfile.close!
165
165
  end
166
166
  rescue Puppet::Util::Windows::Error => e
167
167
  case e.code
168
168
  when ACCESS_DENIED, SHARING_VIOLATION, LOCK_VIOLATION
169
- raise Errno::EACCES.new(Puppet::FileSystem.path_string(path), e)
169
+ raise Errno::EACCES.new(path_string(path), e)
170
170
  else
171
171
  raise SystemCallError.new(e.message)
172
172
  end
@@ -193,7 +193,7 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
193
193
  end
194
194
 
195
195
  def get_dacl_from_file(path)
196
- sd = Puppet::Util::Windows::Security.get_security_descriptor(Puppet::FileSystem.path_string(path))
196
+ sd = Puppet::Util::Windows::Security.get_security_descriptor(path_string(path))
197
197
  sd.dacl
198
198
  rescue Puppet::Util::Windows::Error => e
199
199
  raise e unless e.code == FILE_NOT_FOUND
@@ -397,7 +397,7 @@ module Puppet::FileSystem
397
397
  # @api public
398
398
  #
399
399
  def self.chmod(mode, path)
400
- @impl.chmod(mode, path)
400
+ @impl.chmod(mode, assert_path(path))
401
401
  end
402
402
 
403
403
  # Replace the contents of a file atomically, creating the file if necessary.