puppet 7.1.0 → 7.3.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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +15 -13
  3. data/lib/puppet/application.rb +10 -6
  4. data/lib/puppet/application/agent.rb +1 -0
  5. data/lib/puppet/application/apply.rb +3 -2
  6. data/lib/puppet/application/device.rb +1 -0
  7. data/lib/puppet/application/script.rb +1 -0
  8. data/lib/puppet/configurer.rb +16 -3
  9. data/lib/puppet/defaults.rb +5 -14
  10. data/lib/puppet/face/facts.rb +15 -1
  11. data/lib/puppet/file_serving/configuration/parser.rb +5 -2
  12. data/lib/puppet/module_tool/applications/installer.rb +48 -2
  13. data/lib/puppet/module_tool/errors/shared.rb +17 -2
  14. data/lib/puppet/network/formats.rb +67 -0
  15. data/lib/puppet/parser/ast/leaf.rb +3 -2
  16. data/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  17. data/lib/puppet/pops/model/ast_transformer.rb +1 -1
  18. data/lib/puppet/provider/package/apt.rb +4 -0
  19. data/lib/puppet/reference/configuration.rb +6 -5
  20. data/lib/puppet/settings.rb +33 -28
  21. data/lib/puppet/settings/alias_setting.rb +37 -0
  22. data/lib/puppet/util/autoload.rb +1 -8
  23. data/lib/puppet/util/posix.rb +1 -1
  24. data/lib/puppet/version.rb +1 -1
  25. data/locales/puppet.pot +157 -141
  26. data/man/man5/puppet.conf.5 +6 -6
  27. data/man/man8/puppet-agent.8 +2 -2
  28. data/man/man8/puppet-apply.8 +2 -2
  29. data/man/man8/puppet-catalog.8 +1 -1
  30. data/man/man8/puppet-config.8 +1 -1
  31. data/man/man8/puppet-describe.8 +1 -1
  32. data/man/man8/puppet-device.8 +2 -2
  33. data/man/man8/puppet-doc.8 +1 -1
  34. data/man/man8/puppet-epp.8 +1 -1
  35. data/man/man8/puppet-facts.8 +5 -2
  36. data/man/man8/puppet-filebucket.8 +1 -1
  37. data/man/man8/puppet-generate.8 +1 -1
  38. data/man/man8/puppet-help.8 +1 -1
  39. data/man/man8/puppet-lookup.8 +1 -1
  40. data/man/man8/puppet-module.8 +1 -1
  41. data/man/man8/puppet-node.8 +1 -1
  42. data/man/man8/puppet-parser.8 +1 -1
  43. data/man/man8/puppet-plugin.8 +1 -1
  44. data/man/man8/puppet-report.8 +1 -1
  45. data/man/man8/puppet-resource.8 +1 -1
  46. data/man/man8/puppet-script.8 +2 -2
  47. data/man/man8/puppet-ssl.8 +1 -1
  48. data/man/man8/puppet.8 +2 -2
  49. data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +91 -0
  50. data/spec/integration/application/agent_spec.rb +127 -3
  51. data/spec/integration/application/apply_spec.rb +19 -0
  52. data/spec/integration/defaults_spec.rb +0 -7
  53. data/spec/integration/indirector/file_content/file_server_spec.rb +0 -2
  54. data/spec/integration/indirector/file_metadata/file_server_spec.rb +0 -2
  55. data/spec/integration/resource/type_collection_spec.rb +2 -6
  56. data/spec/integration/transaction_spec.rb +4 -9
  57. data/spec/integration/util/windows/adsi_spec.rb +3 -1
  58. data/spec/integration/util/windows/registry_spec.rb +0 -10
  59. data/spec/spec_helper.rb +1 -4
  60. data/spec/unit/agent_spec.rb +8 -6
  61. data/spec/unit/application/agent_spec.rb +0 -1
  62. data/spec/unit/application/filebucket_spec.rb +0 -2
  63. data/spec/unit/application_spec.rb +17 -9
  64. data/spec/unit/confine/feature_spec.rb +1 -1
  65. data/spec/unit/confine_spec.rb +8 -2
  66. data/spec/unit/face/node_spec.rb +0 -11
  67. data/spec/unit/file_serving/configuration/parser_spec.rb +8 -1
  68. data/spec/unit/file_serving/metadata_spec.rb +3 -3
  69. data/spec/unit/file_serving/terminus_helper_spec.rb +11 -4
  70. data/spec/unit/forge/module_release_spec.rb +2 -7
  71. data/spec/unit/indirector/face_spec.rb +0 -1
  72. data/spec/unit/indirector/facts/facter_spec.rb +11 -5
  73. data/spec/unit/indirector/file_bucket_file/selector_spec.rb +26 -8
  74. data/spec/unit/indirector/indirection_spec.rb +8 -12
  75. data/spec/unit/indirector_spec.rb +2 -2
  76. data/spec/unit/module_tool/applications/installer_spec.rb +66 -0
  77. data/spec/unit/network/formats_spec.rb +41 -0
  78. data/spec/unit/network/http/api/indirected_routes_spec.rb +0 -4
  79. data/spec/unit/parser/compiler_spec.rb +3 -19
  80. data/spec/unit/parser/resource_spec.rb +14 -8
  81. data/spec/unit/pops/evaluator/deferred_resolver_spec.rb +20 -0
  82. data/spec/unit/property_spec.rb +1 -0
  83. data/spec/unit/provider/nameservice_spec.rb +66 -65
  84. data/spec/unit/provider/package/apt_spec.rb +4 -8
  85. data/spec/unit/provider/package/base_spec.rb +6 -5
  86. data/spec/unit/provider/package/pacman_spec.rb +18 -12
  87. data/spec/unit/provider/package/pip_spec.rb +6 -11
  88. data/spec/unit/provider/package/pkgdmg_spec.rb +0 -4
  89. data/spec/unit/provider/user/hpux_spec.rb +1 -1
  90. data/spec/unit/provider_spec.rb +6 -8
  91. data/spec/unit/resource/type_spec.rb +1 -1
  92. data/spec/unit/resource_spec.rb +11 -10
  93. data/spec/unit/settings_spec.rb +13 -6
  94. data/spec/unit/ssl/base_spec.rb +0 -1
  95. data/spec/unit/ssl/ssl_provider_spec.rb +5 -2
  96. data/spec/unit/transaction/additional_resource_generator_spec.rb +3 -7
  97. data/spec/unit/transaction/event_manager_spec.rb +14 -11
  98. data/spec/unit/transaction_spec.rb +13 -4
  99. data/spec/unit/type/file/content_spec.rb +0 -1
  100. data/spec/unit/type/file/selinux_spec.rb +0 -2
  101. data/spec/unit/type/file_spec.rb +0 -6
  102. data/spec/unit/type/group_spec.rb +13 -6
  103. data/spec/unit/type/resources_spec.rb +7 -7
  104. data/spec/unit/type/service_spec.rb +1 -1
  105. data/spec/unit/type/tidy_spec.rb +0 -1
  106. data/spec/unit/type_spec.rb +2 -2
  107. data/spec/unit/util/at_fork_spec.rb +2 -2
  108. data/spec/unit/util/autoload_spec.rb +5 -1
  109. data/spec/unit/util/backups_spec.rb +1 -2
  110. data/spec/unit/util/execution_spec.rb +15 -11
  111. data/spec/unit/util/inifile_spec.rb +6 -14
  112. data/spec/unit/util/log_spec.rb +8 -7
  113. data/spec/unit/util/logging_spec.rb +3 -3
  114. data/spec/unit/util/posix_spec.rb +16 -10
  115. data/spec/unit/util/selinux_spec.rb +76 -52
  116. data/spec/unit/util/suidmanager_spec.rb +44 -41
  117. data/spec/unit/util_spec.rb +13 -6
  118. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a266286fc66516f823076b6e02e50940b8c31a5d2a15e671b4e3d0109d1037a8
4
- data.tar.gz: fb8bfad528606af04781e2119331ff44b871e18174b655f47a2d0ec31b7dea85
3
+ metadata.gz: 6583e2420f7a36ea7119f415387e8f4dfa741e9537b7d17da02ad79a436c39f7
4
+ data.tar.gz: 9804c7626d3fc6a771b837a03afe2efe04daf56a6ce94dd1263275c9d7cd3c5e
5
5
  SHA512:
6
- metadata.gz: 32b3341aec92b3a0147bbc5ac67fd043d5121670add0955c1c38765d998c6cb327660031152df284bd75e7fd4579c2536da581979fb6f08b3c1080e730a38a78
7
- data.tar.gz: a8ed38a33320b7889eef178539be960b1ceb171f4d4c94760c036ea10bda609f4ac47c0438503a260af2a03def16faa283f9be41048bfbcfafbd677931010509
6
+ metadata.gz: 14c7a341a6f9e4a4565738112d736ba5a9b5eca3f6c64441565dee5eddfcc7fc1eff8794e8983ebf64ac1cff489d00666c4f3998ca5970d096eba117d829def8
7
+ data.tar.gz: '098227b0850062512d24aae0eeb6e5d31540029aa5d8418953a68597b46f8b278aad469263feee3ef059fcb5f1d6f1fc9dcb3a0b3810bf40c45a8680afd49f56'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- puppet (7.1.0)
4
+ puppet (7.3.0)
5
5
  CFPropertyList (~> 2.2)
6
6
  concurrent-ruby (~> 1.0)
7
7
  deep_merge (~> 1.0)
@@ -23,16 +23,17 @@ GEM
23
23
  ast (2.4.1)
24
24
  coderay (1.1.3)
25
25
  concurrent-ruby (1.1.7)
26
- crack (0.4.4)
26
+ crack (0.4.5)
27
+ rexml
27
28
  csv (3.1.5)
28
29
  deep_merge (1.2.1)
29
30
  diff-lcs (1.4.4)
30
31
  docopt (0.6.1)
31
- facter (4.0.46)
32
+ facter (4.0.49)
32
33
  hocon (~> 1.3)
33
34
  thor (>= 1.0.1, < 2.0)
34
35
  fast_gettext (1.1.2)
35
- ffi (1.13.1)
36
+ ffi (1.14.2)
36
37
  gettext (3.2.9)
37
38
  locale (>= 2.0.5)
38
39
  text (>= 1.3.0)
@@ -80,10 +81,11 @@ GEM
80
81
  rake
81
82
  rake (12.3.3)
82
83
  rdiscount (2.2.0.2)
83
- rdoc (6.2.1)
84
+ rdoc (6.3.0)
84
85
  release-metrics (1.1.0)
85
86
  csv
86
87
  docopt
88
+ rexml (3.2.4)
87
89
  ronn (0.7.3)
88
90
  hpricot (>= 0.8.2)
89
91
  mustache (>= 0.7.0)
@@ -92,18 +94,18 @@ GEM
92
94
  rspec-core (~> 3.10.0)
93
95
  rspec-expectations (~> 3.10.0)
94
96
  rspec-mocks (~> 3.10.0)
95
- rspec-core (3.10.0)
97
+ rspec-core (3.10.1)
96
98
  rspec-support (~> 3.10.0)
97
- rspec-expectations (3.10.0)
99
+ rspec-expectations (3.10.1)
98
100
  diff-lcs (>= 1.2.0, < 2.0)
99
101
  rspec-support (~> 3.10.0)
100
102
  rspec-its (1.3.0)
101
103
  rspec-core (>= 3.0.0)
102
104
  rspec-expectations (>= 3.0.0)
103
- rspec-mocks (3.10.0)
105
+ rspec-mocks (3.10.1)
104
106
  diff-lcs (>= 1.2.0, < 2.0)
105
107
  rspec-support (~> 3.10.0)
106
- rspec-support (3.10.0)
108
+ rspec-support (3.10.1)
107
109
  rubocop (0.49.1)
108
110
  parallel (~> 1.10)
109
111
  parser (>= 2.3.3.1, < 3.0)
@@ -114,18 +116,18 @@ GEM
114
116
  rubocop-i18n (1.2.0)
115
117
  rubocop (~> 0.49.0)
116
118
  ruby-prof (1.4.2)
117
- ruby-progressbar (1.10.1)
119
+ ruby-progressbar (1.11.0)
118
120
  scanf (1.0.0)
119
- semantic_puppet (1.0.2)
121
+ semantic_puppet (1.0.3)
120
122
  text (1.3.1)
121
123
  thor (1.0.1)
122
124
  unicode-display_width (1.7.0)
123
125
  vcr (5.1.0)
124
- webmock (3.10.0)
126
+ webmock (3.11.1)
125
127
  addressable (>= 2.3.6)
126
128
  crack (>= 0.3.2)
127
129
  hashdiff (>= 0.4.0, < 2.0.0)
128
- yard (0.9.25)
130
+ yard (0.9.26)
129
131
 
130
132
  PLATFORMS
131
133
  ruby
@@ -475,12 +475,16 @@ class Application
475
475
  def handle_logdest_arg(arg)
476
476
  return if arg.nil?
477
477
 
478
- begin
479
- Puppet[:logdest] = arg
480
- Puppet::Util::Log.newdestination(arg)
481
- options[:setdest] = true
482
- rescue => detail
483
- Puppet.log_and_raise(detail, _("Could not set logdest to %{dest}.") % { dest: arg })
478
+ logdest = arg.split(',').map!(&:strip)
479
+ Puppet[:logdest] = arg
480
+
481
+ logdest.each do |dest|
482
+ begin
483
+ Puppet::Util::Log.newdestination(dest)
484
+ options[:setdest] = true
485
+ rescue => detail
486
+ Puppet.log_and_raise(detail, _("Could not set logdest to %{dest}.") % { dest: arg })
487
+ end
484
488
  end
485
489
  end
486
490
 
@@ -267,6 +267,7 @@ generated by running puppet agent with '--genconfig'.
267
267
  service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
268
268
  file. If debugging or verbosity is enabled, this defaults to 'console'.
269
269
  Otherwise, it defaults to 'syslog' on POSIX systems and 'eventlog' on Windows.
270
+ Multiple destinations can be set using a comma separated list (eg: `/path/file1,console,/path/file2`)"
270
271
 
271
272
  A path ending with '.json' will receive structured output in JSON format. The
272
273
  log file will not have an ending ']' automatically written to it due to the
@@ -113,6 +113,7 @@ configuration options by running puppet with
113
113
  Where to send log messages. Choose between 'syslog' (the POSIX syslog
114
114
  service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
115
115
  file. Defaults to 'console'.
116
+ Multiple destinations can be set using a comma separated list (eg: `/path/file1,console,/path/file2`)"
116
117
 
117
118
  A path ending with '.json' will receive structured output in JSON format. The
118
119
  log file will not have an ending ']' automatically written to it due to the
@@ -236,7 +237,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
236
237
  end
237
238
 
238
239
  # Resolve all deferred values and replace them / mutate the catalog
239
- Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog)
240
+ Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, apply_environment)
240
241
 
241
242
  # Translate it to a RAL catalog
242
243
  catalog = catalog.to_ral
@@ -330,7 +331,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
330
331
  raise Puppet::Error, _("Could not deserialize catalog from %{format}: %{detail}") % { format: format, detail: detail }, detail.backtrace
331
332
  end
332
333
  # Resolve all deferred values and replace them / mutate the catalog
333
- Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog)
334
+ Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog, configured_environment)
334
335
 
335
336
  catalog.to_ral
336
337
  end
@@ -155,6 +155,7 @@ you can specify '--server <servername>' as an argument.
155
155
  Where to send log messages. Choose between 'syslog' (the POSIX syslog
156
156
  service), 'console', or the path to a log file. If debugging or verbosity is
157
157
  enabled, this defaults to 'console'. Otherwise, it defaults to 'syslog'.
158
+ Multiple destinations can be set using a comma separated list (eg: `/path/file1,console,/path/file2`)"
158
159
 
159
160
  A path ending with '.json' will receive structured output in JSON format. The
160
161
  log file will not have an ending ']' automatically written to it due to the
@@ -71,6 +71,7 @@ configuration options can also be generated by running puppet with
71
71
  Where to send log messages. Choose between 'syslog' (the POSIX syslog
72
72
  service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
73
73
  file. Defaults to 'console'.
74
+ Multiple destinations can be set using a comma separated list (eg: `/path/file1,console,/path/file2`)"
74
75
 
75
76
  A path ending with '.json' will receive structured output in JSON format. The
76
77
  log file will not have an ending ']' automatically written to it due to the
@@ -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)
115
+ Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(facts, result, Puppet.lookup(:current_environment))
116
116
  end
117
117
 
118
118
  catalog = result.to_ral
@@ -395,16 +395,29 @@ class Puppet::Configurer
395
395
  if !cached_catalog && options[:catalog]
396
396
  ral_catalog = options[:catalog]
397
397
  else
398
+ # Ordering here matters. We have to resolve deferred resources in the
399
+ # resource catalog, convert the resource catalog to a RAL catalog (which
400
+ # triggers type/provider validation), and only if that is successful,
401
+ # should we cache the *original* resource catalog. However, deferred
402
+ # evaluation mutates the resource catalog, so we need to make a copy of
403
+ # it here. If PUP-9323 is ever implemented so that we resolve deferred
404
+ # resources in the RAL catalog as they are needed, then we could eliminate
405
+ # this step.
406
+ catalog_to_cache = Puppet.override(:rich_data => Puppet[:rich_data]) do
407
+ Puppet::Resource::Catalog.from_data_hash(catalog.to_data_hash)
408
+ end
409
+
398
410
  # REMIND @duration is the time spent loading the last catalog, and doesn't
399
411
  # account for things like we failed to download and fell back to the cache
400
412
  ral_catalog = convert_catalog(catalog, @duration, facts, options)
401
413
 
402
- # If not noop, commit the cached resource catalog (not ral catalog). Ideally
414
+ # Validation succeeded, so commit the `catalog_to_cache` for non-noop runs. Don't
415
+ # commit `catalog` since it contains the result of deferred evaluation. Ideally
403
416
  # we'd just copy the downloaded response body, instead of serializing the
404
417
  # in-memory catalog, but that's hard due to the indirector.
405
418
  indirection = Puppet::Resource::Catalog.indirection
406
419
  if !Puppet[:noop] && indirection.cache?
407
- request = indirection.request(:save, nil, catalog, environment: Puppet::Node::Environment.remote(catalog.environment))
420
+ request = indirection.request(:save, nil, catalog_to_cache, environment: Puppet::Node::Environment.remote(catalog_to_cache.environment))
408
421
  Puppet.info("Caching catalog for #{request.key}")
409
422
  indirection.cache.save(request)
410
423
  end
@@ -1076,7 +1076,7 @@ EOT
1076
1076
  :type => :string,
1077
1077
  :desc => "Where to send log messages. Choose between 'syslog' (the POSIX syslog
1078
1078
  service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
1079
- file."
1079
+ file. Multiple destinations can be set using a comma separated list (eg: `/path/file1,console,/path/file2`)"
1080
1080
  # Sure would be nice to set the Puppet::Util::Log destination here in an :on_initialize_and_write hook,
1081
1081
  # unfortunately we have a large number of tests that rely on the logging not resetting itself when the
1082
1082
  # settings are initialized as they test what gets logged during settings initialization.
@@ -1319,25 +1319,16 @@ EOT
1319
1319
  by `puppet`, and should only be set if you're writing your own Puppet
1320
1320
  executable.",
1321
1321
  },
1322
- :serverport => {
1322
+ :masterport => {
1323
1323
  :default => 8140,
1324
1324
  :type => :port,
1325
1325
  :desc => "The default port puppet subcommands use to communicate
1326
1326
  with Puppet Server. (eg `puppet facts upload`, `puppet agent`). May be
1327
1327
  overridden by more specific settings (see `ca_port`, `report_port`).",
1328
- :hook => proc do |value|
1329
- Puppet[:masterport] = value unless Puppet.settings.set_by_config?(:masterport)
1330
- end
1331
1328
  },
1332
- :masterport => {
1333
- :default => "$serverport",
1334
- :type => :port,
1335
- :desc => "The default port puppet subcommands use to communicate
1336
- with Puppet Server. (eg `puppet facts upload`, `puppet agent`). May be
1337
- overridden by more specific settings (see `ca_port`, `report_port`).",
1338
- :hook => proc do |value|
1339
- Puppet[:serverport] = value unless Puppet.settings.set_by_config?(:serverport)
1340
- end
1329
+ :serverport => {
1330
+ :type => :alias,
1331
+ :alias_for => :masterport
1341
1332
  },
1342
1333
  :bucketdir => {
1343
1334
  :default => "$vardir/bucket",
@@ -127,6 +127,10 @@ Puppet::Indirector::Face.define(:facts, '0.0.1') do
127
127
  option("--show-legacy") do
128
128
  summary _("Show legacy facts when querying all facts.")
129
129
  end
130
+
131
+ option("--value-only") do
132
+ summary _("Show only the value when the action is called with a single query")
133
+ end
130
134
 
131
135
  when_invoked do |*args|
132
136
  options = args.pop
@@ -134,12 +138,22 @@ Puppet::Indirector::Face.define(:facts, '0.0.1') do
134
138
  Puppet.settings.preferred_run_mode = :agent
135
139
  Puppet::Node::Facts.indirection.terminus_class = :facter
136
140
 
141
+ if options[:value_only] && !args.count.eql?(1)
142
+ options[:value_only] = nil
143
+ Puppet.warning("Incorrect use of --value-only argument; it can only be used when querying for a single fact!")
144
+ end
137
145
 
138
146
  options[:user_query] = args
139
147
  options[:resolve_options] = true
140
148
  result = Puppet::Node::Facts.indirection.find(Puppet.settings[:certname], options)
141
149
 
142
- result.values
150
+ facts = result.values
151
+
152
+ if options[:value_only]
153
+ facts.values.first
154
+ else
155
+ facts
156
+ end
143
157
  end
144
158
 
145
159
  when_rendering :console do |result|
@@ -33,8 +33,11 @@ class Puppet::FileServing::Configuration::Parser
33
33
  when "path"
34
34
  path(mount, value)
35
35
  when "allow", "deny"
36
- error_location_str = Puppet::Util::Errors.error_location(@file.filename, @count)
37
- Puppet.err("Entry '#{line.chomp}' is unsupported and will be ignored at #{error_location_str}")
36
+ # ignore `allow *`, otherwise report error
37
+ if var != 'allow' || value != '*'
38
+ error_location_str = Puppet::Util::Errors.error_location(@file.filename, @count)
39
+ Puppet.err("Entry '#{line.chomp}' is unsupported and will be ignored at #{error_location_str}")
40
+ end
38
41
  else
39
42
  error_location_str = Puppet::Util::Errors.error_location(@file.filename, @count)
40
43
  raise ArgumentError.new(_("Invalid argument '%{var}' at %{error_location}") %
@@ -131,8 +131,54 @@ module Puppet::ModuleTool
131
131
  begin
132
132
  Puppet.info _("Resolving dependencies ...")
133
133
  releases = SemanticPuppet::Dependency.resolve(graph)
134
- rescue SemanticPuppet::Dependency::UnsatisfiableGraph
135
- raise NoVersionsSatisfyError, results.merge(:requested_name => name)
134
+ rescue SemanticPuppet::Dependency::UnsatisfiableGraph => e
135
+ unsatisfied = nil
136
+
137
+ if e.respond_to?(:unsatisfied)
138
+ constraints = {}
139
+ # If the module we're installing satisfies all its
140
+ # dependencies, but would break an already installed
141
+ # module that depends on it, show what would break.
142
+ if name == e.unsatisfied
143
+ graph.constraints[name].each do |mod, range, _|
144
+ next unless mod.split.include?('constraint')
145
+
146
+ # If the user requested a specific version or range,
147
+ # only show the modules with non-intersecting ranges
148
+ if options[:version]
149
+ requested_range = SemanticPuppet::VersionRange.parse(options[:version])
150
+ constraint_range = SemanticPuppet::VersionRange.parse(range)
151
+
152
+ if requested_range.intersection(constraint_range) == SemanticPuppet::VersionRange::EMPTY_RANGE
153
+ constraints[mod.split.first] = range
154
+ end
155
+ else
156
+ constraints[mod.split.first] = range
157
+ end
158
+ end
159
+
160
+ # If the module fails to satisfy one of its
161
+ # dependencies, show the unsatisfiable module
162
+ else
163
+ unsatisfied_range = graph.dependencies[name].max.constraints[e.unsatisfied].first[1]
164
+ constraints[e.unsatisfied] = unsatisfied_range
165
+ end
166
+
167
+ installed_module = @environment.module_by_forge_name(e.unsatisfied.tr('-', '/'))
168
+ current_version = installed_module.version if installed_module
169
+
170
+ unsatisfied = {
171
+ :name => e.unsatisfied,
172
+ :constraints => constraints,
173
+ :current_version => current_version
174
+ }
175
+ end
176
+
177
+ raise NoVersionsSatisfyError, results.merge(
178
+ :requested_name => name,
179
+ :requested_version => options[:version] || graph.dependencies[name].max.version.to_s,
180
+ :unsatisfied => unsatisfied
181
+ )
136
182
  end
137
183
 
138
184
  unless forced?
@@ -7,6 +7,7 @@ module Puppet::ModuleTool::Errors
7
7
  @installed_version = options[:installed_version]
8
8
  @conditions = options[:conditions]
9
9
  @action = options[:action]
10
+ @unsatisfied = options[:unsatisfied]
10
11
 
11
12
  super _("Could not %{action} '%{module_name}' (%{version}); no version satisfies all dependencies") % { action: @action, module_name: @requested_name, version: vstring }
12
13
  end
@@ -14,9 +15,23 @@ module Puppet::ModuleTool::Errors
14
15
  def multiline
15
16
  message = []
16
17
  message << _("Could not %{action} module '%{module_name}' (%{version})") % { action: @action, module_name: @requested_name, version: vstring }
17
- message << _(" No version of '%{module_name}' can satisfy all dependencies") % { module_name: @requested_name }
18
+
19
+ if @unsatisfied
20
+ message << _(" The requested version cannot satisfy one or more of the following installed modules:")
21
+ if @unsatisfied[:current_version]
22
+ message << _(" %{name}, installed: %{current_version}, expected: %{constraints}") % { name: @unsatisfied[:name], current_version: @unsatisfied[:current_version], constraints: @unsatisfied[:constraints][@unsatisfied[:name]] }
23
+ else
24
+ @unsatisfied[:constraints].each do |mod, range|
25
+ message << _(" %{mod}, expects '%{name}': %{range}") % { mod: mod, name: @requested_name, range: range }
26
+ end
27
+ end
28
+ message << _("")
29
+ else
30
+ message << _(" The requested version cannot satisfy all dependencies")
31
+ end
32
+
18
33
  #TRANSLATORS `puppet module %{action} --ignore-dependencies` is a command line and should not be translated
19
- message << _(" Use `puppet module %{action} --ignore-dependencies` to %{action} only this module") % { action: @action }
34
+ message << _(" Use `puppet module %{action} '%{module_name}' --ignore-dependencies` to %{action} only this module") % { action: @action, module_name: @requested_name }
20
35
  message.join("\n")
21
36
  end
22
37
  end
@@ -183,6 +183,73 @@ Puppet::Network::FormatHandler.create(:console,
183
183
  end
184
184
  end
185
185
 
186
+ Puppet::Network::FormatHandler.create(:flat,
187
+ :mime => 'text/x-flat-text',
188
+ :weight => 0) do
189
+
190
+ def flatten_hash(hash)
191
+ hash.each_with_object({}) do |(k, v), h|
192
+ if v.is_a? Hash
193
+ flatten_hash(v).map do |h_k, h_v|
194
+ h["#{k}.#{h_k}"] = h_v
195
+ end
196
+ elsif v.is_a? Array
197
+ v.each_with_index do |el, i|
198
+ if el.is_a? Hash
199
+ flatten_hash(el).map do |el_k, el_v|
200
+ h["#{k}.#{i}.#{el_k}"] = el_v
201
+ end
202
+ else
203
+ h["#{k}.#{i}"] = el
204
+ end
205
+ end
206
+ else
207
+ h[k] = v
208
+ end
209
+ end
210
+ end
211
+
212
+ def flatten_array(array)
213
+ a={}
214
+ array.each_with_index do |el, i|
215
+ if el.is_a? Hash
216
+ flatten_hash(el).map do |el_k, el_v|
217
+ a["#{i}.#{el_k}"] = el_v
218
+ end
219
+ else
220
+ a["#{i}"] = el
221
+ end
222
+ end
223
+ a
224
+ end
225
+
226
+ def construct_output(data)
227
+ output = ''
228
+ data.each do |key, value|
229
+ output << "#{key}=#{value}"
230
+ output << "\n"
231
+ end
232
+ output
233
+ end
234
+
235
+ def render(datum)
236
+ return datum if datum.is_a?(String) || datum.is_a?(Numeric)
237
+ # Simple hash
238
+ if datum.is_a?(Hash)
239
+ data = flatten_hash(datum)
240
+ return construct_output(data)
241
+ elsif datum.is_a?(Array)
242
+ data = flatten_array(datum)
243
+ return construct_output(data)
244
+ end
245
+ Puppet::Util::Json.dump(datum, :pretty => true, :quirks_mode => true)
246
+ end
247
+ def render_multiple(data)
248
+ data.collect(&:render).join("\n")
249
+ end
250
+ end
251
+
252
+
186
253
  Puppet::Network::FormatHandler.create(:rich_data_json, mime: 'application/vnd.puppet.rich+json', charset: Encoding::UTF_8, weight: 30) do
187
254
  def intern(klass, text)
188
255
  Puppet.override({:rich_data => true}) do