chef 17.2.29-universal-mingw32 → 17.3.48-universal-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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -3
  3. data/chef.gemspec +1 -0
  4. data/lib/chef/client.rb +1 -1
  5. data/lib/chef/data_bag.rb +1 -2
  6. data/lib/chef/data_bag_item.rb +1 -2
  7. data/lib/chef/deprecated.rb +10 -4
  8. data/lib/chef/dsl.rb +1 -0
  9. data/lib/chef/dsl/render_helpers.rb +44 -0
  10. data/lib/chef/dsl/secret.rb +64 -0
  11. data/lib/chef/dsl/toml.rb +116 -0
  12. data/lib/chef/dsl/universal.rb +5 -0
  13. data/lib/chef/exceptions.rb +22 -0
  14. data/lib/chef/handler/slow_report.rb +1 -1
  15. data/lib/chef/json_compat.rb +1 -1
  16. data/lib/chef/policy_builder/policyfile.rb +88 -45
  17. data/lib/chef/provider/file.rb +2 -2
  18. data/lib/chef/provider/lwrp_base.rb +1 -1
  19. data/lib/chef/provider/package/habitat.rb +168 -0
  20. data/lib/chef/provider/package/powershell.rb +5 -0
  21. data/lib/chef/providers.rb +1 -0
  22. data/lib/chef/resource/chef_client_config.rb +7 -2
  23. data/lib/chef/resource/chef_client_cron.rb +1 -1
  24. data/lib/chef/resource/chef_client_launchd.rb +1 -1
  25. data/lib/chef/resource/chef_client_scheduled_task.rb +1 -1
  26. data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
  27. data/lib/chef/resource/chef_client_trusted_certificate.rb +2 -2
  28. data/lib/chef/resource/chef_vault_secret.rb +2 -2
  29. data/lib/chef/resource/dsc_resource.rb +1 -1
  30. data/lib/chef/resource/execute.rb +3 -3
  31. data/lib/chef/resource/gem_package.rb +2 -1
  32. data/lib/chef/resource/habitat/_habitat_shared.rb +28 -0
  33. data/lib/chef/resource/habitat/habitat_package.rb +129 -0
  34. data/lib/chef/resource/habitat/habitat_sup.rb +329 -0
  35. data/lib/chef/resource/habitat/habitat_sup_systemd.rb +67 -0
  36. data/lib/chef/resource/habitat/habitat_sup_windows.rb +90 -0
  37. data/lib/chef/resource/habitat_config.rb +107 -0
  38. data/lib/chef/resource/habitat_install.rb +247 -0
  39. data/lib/chef/resource/habitat_service.rb +451 -0
  40. data/lib/chef/resource/habitat_user_toml.rb +92 -0
  41. data/lib/chef/resource/lwrp_base.rb +1 -1
  42. data/lib/chef/resource/support/HabService.dll.config.erb +19 -0
  43. data/lib/chef/resource/support/client.erb +8 -1
  44. data/lib/chef/resource/support/sup.toml.erb +179 -0
  45. data/lib/chef/resource/windows_defender.rb +163 -0
  46. data/lib/chef/resource/windows_defender_exclusion.rb +125 -0
  47. data/lib/chef/resource/windows_printer.rb +78 -44
  48. data/lib/chef/resource/windows_printer_port.rb +1 -1
  49. data/lib/chef/resource/windows_update_settings.rb +259 -0
  50. data/lib/chef/resources.rb +12 -1
  51. data/lib/chef/secret_fetcher.rb +54 -0
  52. data/lib/chef/secret_fetcher/aws_secrets_manager.rb +53 -0
  53. data/lib/chef/secret_fetcher/azure_key_vault.rb +56 -0
  54. data/lib/chef/secret_fetcher/base.rb +72 -0
  55. data/lib/chef/secret_fetcher/example.rb +46 -0
  56. data/lib/chef/version.rb +1 -1
  57. data/spec/functional/mixin/from_file_spec.rb +1 -1
  58. data/spec/integration/recipes/recipe_dsl_spec.rb +1 -1
  59. data/spec/integration/recipes/resource_action_spec.rb +4 -4
  60. data/spec/support/shared/unit/provider/file.rb +2 -8
  61. data/spec/unit/data_bag_item_spec.rb +2 -2
  62. data/spec/unit/data_bag_spec.rb +1 -1
  63. data/spec/unit/dsl/render_helpers_spec.rb +102 -0
  64. data/spec/unit/dsl/secret_spec.rb +65 -0
  65. data/spec/unit/policy_builder/dynamic_spec.rb +0 -5
  66. data/spec/unit/policy_builder/policyfile_spec.rb +144 -56
  67. data/spec/unit/provider/apt_update_spec.rb +3 -1
  68. data/spec/unit/provider/mount/aix_spec.rb +1 -1
  69. data/spec/unit/provider/package/powershell_spec.rb +74 -12
  70. data/spec/unit/resource/windows_defender_exclusion_spec.rb +62 -0
  71. data/spec/unit/resource/windows_defender_spec.rb +71 -0
  72. data/spec/unit/resource/windows_update_settings_spec.rb +64 -0
  73. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +63 -0
  74. data/spec/unit/secret_fetcher_spec.rb +82 -0
  75. metadata +51 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16349cc7cd44c42fa9e302a78df1ae63238d8826fad9f03e3ab7d64ed17398dc
4
- data.tar.gz: 5bda57a2da605d02ce0cb2d7c8f808c7f76943e54f5565694eba0d223c5e1ecd
3
+ metadata.gz: 203a5aa495fb3cbce86bd90e53bde981b7fe825dc5a02fb508342bfe24168736
4
+ data.tar.gz: d5aee72a800a84a704acf217184ae04830405fe12fa66f69b2bf768885cfcfa0
5
5
  SHA512:
6
- metadata.gz: 67a2d97e1dc18947e71a55deac5c8c35f5c51d2fdb78beda851dcf8f1f0219afce48f2e6f8fe49d3bed7abb32409ea1de60377b343bc6fab9e427d201abce143
7
- data.tar.gz: d8542bc72a0dd26d3b765968b77a45aeb5929618850c1a24af551bf74400c8f12dd7b1207c6638bd909254ace385d722e8a932a0b7a0ee9a8224b8e170407f42
6
+ metadata.gz: 9f0e89f09f3fa298a205b9094d042eb202d9992294b02cb332703e9a314bbe07414701713797eb1b3cd698e36b4e2de8f32b3ffbba913f42da33c86b98eacdbf
7
+ data.tar.gz: 4fbe89ccc95d59001243fc39267f314e77ebd7eeece444267715f9e6fd8123af6409db3956bd60c76e1e4ce57dcf60428f4d865d998fe6ac98cf5bc5498c5e29
data/Gemfile CHANGED
@@ -22,13 +22,14 @@ group(:omnibus_package) do
22
22
  gem "rb-readline"
23
23
  gem "inspec-core-bin", "~> 4.24" # need to provide the binaries for inspec
24
24
  gem "chef-vault"
25
- gem "ed25519", "~> 1.2" # to make it possible to install knife into chef. Remove this in Chef 18
26
25
  end
27
26
 
28
27
  group(:omnibus_package, :pry) do
29
- gem "pry"
28
+ # Locked because pry-byebug is broken with 13+.
29
+ # some work is ongoing? https://github.com/deivid-rodriguez/pry-byebug/issues/343
30
+ gem "pry", "= 0.13.0"
30
31
  # byebug does not install on freebsd on ruby 3.0
31
- # gem "pry-byebug"
32
+ gem "pry-byebug" unless RUBY_PLATFORM =~ /freebsd/i
32
33
  gem "pry-stack_explorer"
33
34
  end
34
35
 
data/chef.gemspec CHANGED
@@ -55,6 +55,7 @@ Gem::Specification.new do |s|
55
55
 
56
56
  s.add_dependency "proxifier", "~> 1.0"
57
57
 
58
+ s.add_dependency "aws-sdk-secretsmanager", "~> 1.46"
58
59
  s.bindir = "bin"
59
60
  s.executables = %w{ }
60
61
 
data/lib/chef/client.rb CHANGED
@@ -751,7 +751,7 @@ class Chef
751
751
  end
752
752
 
753
753
  # Notification registration
754
- class<<self
754
+ class << self
755
755
  #
756
756
  # Add a listener for the 'client run started' event.
757
757
  #
data/lib/chef/data_bag.rb CHANGED
@@ -32,8 +32,7 @@ class Chef
32
32
  include Chef::Mixin::FromFile
33
33
  include Chef::Mixin::ParamsValidate
34
34
 
35
- # Regex reference: https://rubular.com/r/oIMySIO4USPm5x
36
- VALID_NAME = /^[\-[:alnum:]_]+$/.freeze
35
+ VALID_NAME = /^[\.\-[:alnum:]_]+$/.freeze
37
36
  RESERVED_NAMES = /^(node|role|environment|client)$/.freeze
38
37
 
39
38
  def self.validate_name!(name)
@@ -36,8 +36,7 @@ class Chef
36
36
  include Chef::Mixin::FromFile
37
37
  include Chef::Mixin::ParamsValidate
38
38
 
39
- # Regex reference: https://rubular.com/r/oIMySIO4USPm5x
40
- VALID_ID = /^[\-[:alnum:]_]+$/.freeze
39
+ VALID_ID = /^[\.\-[:alnum:]_]+$/.freeze
41
40
 
42
41
  def self.validate_id!(id_str)
43
42
  if id_str.nil? || ( id_str !~ VALID_ID )
@@ -79,10 +79,12 @@ class Chef
79
79
  return true if location =~ /^(.*?):(\d+):in/ && begin
80
80
  # Don't buffer the whole file in memory, so read it one line at a time.
81
81
  line_no = $2.to_i
82
- location_file = ::File.open($1)
83
- (line_no - 1).times { location_file.readline } # Read all the lines we don't care about.
84
- relevant_line = location_file.readline
85
- relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/)
82
+ if File.exist?($1) # some stacktraces come from `eval` and not a file
83
+ location_file = ::File.open($1)
84
+ (line_no - 1).times { location_file.readline } # Read all the lines we don't care about.
85
+ relevant_line = location_file.readline
86
+ relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/)
87
+ end
86
88
  end
87
89
 
88
90
  false
@@ -257,6 +259,10 @@ class Chef
257
259
  target 34
258
260
  end
259
261
 
262
+ class PolicyfileCompatMode < Base
263
+ target 35
264
+ end
265
+
260
266
  class Generic < Base
261
267
  def url
262
268
  "https://docs.chef.io/chef_deprecations_client/"
data/lib/chef/dsl.rb CHANGED
@@ -4,3 +4,4 @@ require_relative "dsl/data_query"
4
4
  require_relative "dsl/include_recipe"
5
5
  require_relative "dsl/include_attribute"
6
6
  require_relative "dsl/registry_helper"
7
+ require_relative "dsl/secret"
@@ -0,0 +1,44 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ require_relative "toml"
17
+ require_relative "../json_compat"
18
+ autoload :YAML, "yaml"
19
+
20
+ class Chef
21
+ module DSL
22
+ module RenderHelpers
23
+
24
+ # pretty-print a hash as a JSON string
25
+ def render_json(hash)
26
+ JSON.pretty_generate(hash) + "\n"
27
+ end
28
+
29
+ # pretty-print a hash as a TOML string
30
+ def render_toml(hash)
31
+ Chef::DSL::Toml::Dumper.new(hash).toml_str
32
+ end
33
+
34
+ # pretty-print a hash as a YAML string
35
+ def render_yaml(hash)
36
+ yaml_content = hash.transform_keys(&:to_s).to_yaml
37
+ # above replaces first-level keys with strings, below the rest
38
+ yaml_content.gsub!(" :", " ")
39
+ end
40
+
41
+ extend self
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ #
2
+ # Author:: Marc Paradise (<marc@chef.io>)
3
+ # Copyright:: Copyright (c) Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ require_relative "../secret_fetcher"
19
+
20
+ class Chef
21
+ module DSL
22
+ module Secret
23
+
24
+ # Helper method which looks up a secret using the given service and configuration,
25
+ # and returns the retrieved secret value.
26
+ # This DSL providers a wrapper around [Chef::SecretFetcher]
27
+ #
28
+ # Use of the secret helper in the context of a resource block will automatically mark
29
+ # that resource as 'sensitive', preventing resource data from being logged. See [Chef::Resource#sensitive].
30
+ #
31
+ # @option name [Object] The identifier or name for this secret
32
+ # @option version [Object] The secret version. If a service supports versions
33
+ # and no version is provided, the latest version will be fetched.
34
+ # @option service [Symbol] The service identifier for the service that will
35
+ # perform the secret lookup. See
36
+ # [Chef::SecretFetcher::SECRET_FETCHERS]
37
+ # @option config [Hash] The configuration that the named service expects
38
+ #
39
+ # @return result [Object] The response object type is determined by the fetcher but will usually be a string or a hash.
40
+ # See individual fetcher documentation to know what to expect for a given service.
41
+ #
42
+ # @example
43
+ #
44
+ # This example uses the built-in :example secret manager service, which
45
+ # accepts a hash of secrets.
46
+ #
47
+ # value = secret(name: "test1", service: :example, config: { "test1" => "value1" })
48
+ # log "My secret is #{value}"
49
+ #
50
+ # value = secret(name: "test1", service: :aws_secrets_manager, version: "v1", config: { region: "us-west-1" })
51
+ # log "My secret is #{value}"
52
+ def secret(name: nil, version: nil, service: nil, config: nil)
53
+ Chef::Log.warn <<~EOM.gsub("\n", "")
54
+ The secrets Chef Infra language helper is currently in beta.
55
+ This helper will most likely change over time in potentially breaking ways.
56
+ If you have feedback or you'd like to be part of the future design of this
57
+ helper e-mail us at secrets_management_beta@progress.com"
58
+ EOM
59
+ sensitive(true) if is_a?(Chef::Resource)
60
+ Chef::SecretFetcher.for_service(service, config).fetch(name, version)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,116 @@
1
+ require "date"
2
+
3
+ # imported from https://github.com/chef-cookbooks/habitat
4
+ class Chef
5
+ module DSL
6
+ module Toml
7
+ class Dumper
8
+ attr_reader :toml_str
9
+
10
+ def initialize(hash)
11
+ @toml_str = ""
12
+
13
+ visit(hash, [])
14
+ end
15
+
16
+ private
17
+
18
+ def visit(hash, prefix, extra_brackets = false)
19
+ simple_pairs, nested_pairs, table_array_pairs = sort_pairs hash
20
+
21
+ if prefix.any? && (simple_pairs.any? || hash.empty?)
22
+ print_prefix prefix, extra_brackets
23
+ end
24
+
25
+ dump_pairs simple_pairs, nested_pairs, table_array_pairs, prefix
26
+ end
27
+
28
+ def sort_pairs(hash)
29
+ nested_pairs = []
30
+ simple_pairs = []
31
+ table_array_pairs = []
32
+
33
+ hash.keys.sort.each do |key|
34
+ val = hash[key]
35
+ element = [key, val]
36
+
37
+ if val.is_a? Hash
38
+ nested_pairs << element
39
+ elsif val.is_a?(Array) && val.first.is_a?(Hash)
40
+ table_array_pairs << element
41
+ else
42
+ simple_pairs << element
43
+ end
44
+ end
45
+
46
+ [simple_pairs, nested_pairs, table_array_pairs]
47
+ end
48
+
49
+ def dump_pairs(simple, nested, table_array, prefix = [])
50
+ # First add simple pairs, under the prefix
51
+ dump_simple_pairs simple
52
+ dump_nested_pairs nested, prefix
53
+ dump_table_array_pairs table_array, prefix
54
+ end
55
+
56
+ def dump_simple_pairs(simple_pairs)
57
+ simple_pairs.each do |key, val|
58
+ key = quote_key(key) unless bare_key? key
59
+ @toml_str << "#{key} = #{to_toml(val)}\n"
60
+ end
61
+ end
62
+
63
+ def dump_nested_pairs(nested_pairs, prefix)
64
+ nested_pairs.each do |key, val|
65
+ key = quote_key(key) unless bare_key? key
66
+
67
+ visit val, prefix + [key], false
68
+ end
69
+ end
70
+
71
+ def dump_table_array_pairs(table_array_pairs, prefix)
72
+ table_array_pairs.each do |key, val|
73
+ key = quote_key(key) unless bare_key? key
74
+ aux_prefix = prefix + [key]
75
+
76
+ val.each do |child|
77
+ print_prefix aux_prefix, true
78
+ args = sort_pairs(child) << aux_prefix
79
+
80
+ dump_pairs(*args)
81
+ end
82
+ end
83
+ end
84
+
85
+ def print_prefix(prefix, array = false)
86
+ new_prefix = prefix.join(".")
87
+ new_prefix = "[#{new_prefix}]" if array
88
+
89
+ @toml_str += "[#{new_prefix}]\n"
90
+ end
91
+
92
+ def to_toml(obj)
93
+ if obj.is_a?(Time) || obj.is_a?(DateTime)
94
+ obj.strftime("%Y-%m-%dT%H:%M:%SZ")
95
+ elsif obj.is_a?(Date)
96
+ obj.strftime("%Y-%m-%d")
97
+ elsif obj.is_a? Regexp
98
+ obj.inspect.inspect
99
+ elsif obj.is_a? String
100
+ obj.inspect.gsub(/\\(#[$@{])/, '\1')
101
+ else
102
+ obj.inspect
103
+ end
104
+ end
105
+
106
+ def bare_key?(key)
107
+ !!key.to_s.match(/^[a-zA-Z0-9_-]*$/)
108
+ end
109
+
110
+ def quote_key(key)
111
+ '"' + key.gsub('"', '\\"') + '"'
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -22,6 +22,9 @@ require_relative "data_query"
22
22
  require_relative "chef_vault"
23
23
  require_relative "registry_helper"
24
24
  require_relative "powershell"
25
+ require_relative "secret"
26
+ require_relative "render_helpers"
27
+ require_relative "toml"
25
28
  require_relative "../mixin/powershell_exec"
26
29
  require_relative "../mixin/powershell_out"
27
30
  require_relative "../mixin/shell_out"
@@ -47,6 +50,8 @@ class Chef
47
50
  include Chef::DSL::ChefVault
48
51
  include Chef::DSL::RegistryHelper
49
52
  include Chef::DSL::Powershell
53
+ include Chef::DSL::RenderHelpers
54
+ include Chef::DSL::Secret
50
55
  include Chef::Mixin::PowershellExec
51
56
  include Chef::Mixin::PowershellOut
52
57
  include Chef::Mixin::ShellOut
@@ -290,6 +290,28 @@ class Chef
290
290
 
291
291
  end
292
292
 
293
+ class Secret
294
+ class RetrievalError < RuntimeError; end
295
+ class ConfigurationInvalid < RuntimeError; end
296
+ class FetchFailed < RuntimeError; end
297
+ class MissingSecretName < RuntimeError; end
298
+ class InvalidSecretName < RuntimeError; end
299
+
300
+ class InvalidFetcherService < RuntimeError
301
+ def initialize(given, fetcher_service_names)
302
+ super("#{given} is not a supported secrets service. Supported services are: :#{fetcher_service_names.join(" :")}")
303
+ end
304
+ end
305
+
306
+ class MissingFetcher < RuntimeError
307
+ def initialize(fetcher_service_names)
308
+ super("No secret service provided. Supported services are: :#{fetcher_service_names.join(" :")}")
309
+ end
310
+ end
311
+
312
+ class MissingVaultName < RuntimeError; end
313
+ end
314
+
293
315
  # Exception class for collecting multiple failures. Used when running
294
316
  # delayed notifications so that chef can process each delayed
295
317
  # notification even if chef client or other notifications fail.
@@ -59,7 +59,7 @@ class Chef
59
59
 
60
60
  def stripped_source_line(resource)
61
61
  # strip the leading path off of the source line
62
- resource.source_line.gsub(%r{.*/cookbooks/}, "").gsub(%r{.*/chef-[0-9\.]+/}, "")
62
+ resource.source_line&.gsub(%r{.*/cookbooks/}, "")&.gsub(%r{.*/chef-[0-9\.]+/}, "")
63
63
  end
64
64
  end
65
65
  end
@@ -25,7 +25,7 @@ require "json" unless defined?(JSON)
25
25
  class Chef
26
26
  class JSONCompat
27
27
 
28
- class <<self
28
+ class << self
29
29
 
30
30
  def parse(source, opts = {})
31
31
  FFI_Yajl::Parser.parse(source, opts)
@@ -32,14 +32,8 @@ class Chef
32
32
  # Policyfile is a policy builder implementation that gets run
33
33
  # list and cookbook version information from a single document.
34
34
  #
35
- # == Unsupported Options:
36
- # * override_runlist:: This could potentially be integrated into the
37
- # policyfile, or replaced with a similar feature that has different
38
- # semantics.
39
- # * specific_recipes:: put more design thought into this use case.
40
- # * run_list in json_attribs:: would be ignored anyway, so it raises an error.
41
- # * chef-solo:: not currently supported. Need more design thought around
42
- # how this should work.
35
+ # Does not support legacy chef-solo or roles/environments.
36
+ #
43
37
  class Policyfile
44
38
 
45
39
  class UnsupportedFeature < StandardError; end
@@ -81,10 +75,12 @@ class Chef
81
75
  attr_reader :ohai_data
82
76
  attr_reader :json_attribs
83
77
  attr_reader :run_context
78
+ attr_reader :override_runlist
84
79
 
85
80
  def initialize(node_name, ohai_data, json_attribs, override_runlist, events)
86
81
  @node_name = node_name
87
82
  @ohai_data = ohai_data
83
+ @override_runlist = override_runlist
88
84
  @json_attribs = json_attribs
89
85
  @events = events
90
86
 
@@ -94,32 +90,11 @@ class Chef
94
90
  raise UnsupportedFeature, "Policyfile does not support chef-solo. Use #{ChefUtils::Dist::Infra::CLIENT} local mode instead."
95
91
  end
96
92
 
97
- if override_runlist
98
- raise UnsupportedFeature, "Policyfile does not support override run lists. Use named run_lists instead."
99
- end
100
-
101
- if json_attribs && json_attribs.key?("run_list")
102
- raise UnsupportedFeature, "Policyfile does not support setting the run_list in json data."
103
- end
104
-
105
93
  if Chef::Config[:environment] && !Chef::Config[:environment].chomp.empty?
106
94
  raise UnsupportedFeature, "Policyfile does not work with an Environment configured."
107
95
  end
108
96
  end
109
97
 
110
- ## API Compat ##
111
- # Methods related to unsupported features
112
-
113
- # Override run_list is not supported.
114
- def original_runlist
115
- nil
116
- end
117
-
118
- # Override run_list is not supported.
119
- def override_runlist
120
- nil
121
- end
122
-
123
98
  # Policyfile gives you the run_list already expanded, but users of this
124
99
  # class may expect to get a run_list expansion compatible object by
125
100
  # calling this method.
@@ -148,17 +123,27 @@ class Chef
148
123
  # consume_external_attrs may add items to the run_list. Save the
149
124
  # expanded run_list, which we will pass to the server later to
150
125
  # determine which versions of cookbooks to use.
126
+
127
+ unless Chef::Config[:policy_document_native_api]
128
+ Chef.deprecated(:policyfile_compat_mode, "The chef-server 11 policyfile compat mode is deprecated, please set policy_document_native_api to true in your config")
129
+ end
130
+
151
131
  node.reset_defaults_and_overrides
152
132
 
153
133
  node.consume_external_attrs(ohai_data, json_attribs)
154
134
 
135
+ setup_run_list_override
136
+
155
137
  expand_run_list
156
138
  apply_policyfile_attributes
157
139
 
140
+ if persistent_run_list_set?
141
+ Chef::Log.warn("The node.run_list setting is overriding the Policyfile run_list")
142
+ end
158
143
  Chef::Log.info("Run List is [#{run_list}]")
159
- Chef::Log.info("Run List expands to [#{run_list_with_versions_for_display.join(", ")}]")
144
+ Chef::Log.info("Run List expands to [#{run_list_with_versions_for_display(run_list).join(", ")}]")
160
145
 
161
- events.node_load_completed(node, run_list_with_versions_for_display, Chef::Config)
146
+ events.node_load_completed(node, run_list_with_versions_for_display(run_list), Chef::Config)
162
147
  events.run_list_expanded(run_list_expansion_ish)
163
148
 
164
149
  # we must do this after `node.consume_external_attrs`
@@ -194,6 +179,11 @@ class Chef
194
179
  events.cookbook_compilation_start(run_context)
195
180
 
196
181
  run_context.load(run_list_expansion_ish)
182
+ if specific_recipes
183
+ specific_recipes.each do |recipe_file|
184
+ run_context.load_recipe_file(recipe_file)
185
+ end
186
+ end
197
187
 
198
188
  events.cookbook_compilation_complete(run_context)
199
189
 
@@ -206,7 +196,7 @@ class Chef
206
196
  #
207
197
  # @return [RunListExpansionIsh] A RunListExpansion duck-type.
208
198
  def expand_run_list
209
- CookbookCacheCleaner.instance.skip_removal = true if named_run_list_requested?
199
+ validate_run_list!(run_list)
210
200
 
211
201
  node.run_list(run_list)
212
202
  node.automatic_attrs[:policy_revision] = revision_id
@@ -231,21 +221,25 @@ class Chef
231
221
  cookbooks_to_sync
232
222
  end
233
223
 
234
- # Whether or not this is a temporary policy. Since PolicyBuilder doesn't
235
- # support override_runlist, this is always false.
224
+ ## Internal Public API ##
225
+
226
+ # @api private
236
227
  #
237
- # @return [false]
238
- def temporary_policy?
239
- false
228
+ # Validate run_list against policyfile cookbooks
229
+ #
230
+ def validate_run_list!(run_list)
231
+ run_list.map do |recipe_spec|
232
+ cookbook, recipe = parse_recipe_spec(recipe_spec)
233
+ lock_data = cookbook_lock_for(cookbook)
234
+ raise PolicyfileError, "invalid run_list item '#{recipe_spec}' not in cookbook set of PolicyFile #{policyfile_location}" unless lock_data
235
+ end
240
236
  end
241
237
 
242
- ## Internal Public API ##
243
-
244
238
  # @api private
245
239
  #
246
240
  # Generates an array of strings with recipe names including version and
247
241
  # identifier info.
248
- def run_list_with_versions_for_display
242
+ def run_list_with_versions_for_display(run_list)
249
243
  run_list.map do |recipe_spec|
250
244
  cookbook, recipe = parse_recipe_spec(recipe_spec)
251
245
  lock_data = cookbook_lock_for(cookbook)
@@ -287,9 +281,14 @@ class Chef
287
281
 
288
282
  # @api private
289
283
  def parse_recipe_spec(recipe_spec)
290
- rmatch = recipe_spec.match(/recipe\[([^:]+)::([^:]+)\]/)
284
+ rmatch = recipe_spec.to_s.match(/recipe\[([^:]+)::([^:]+)\]/)
291
285
  if rmatch.nil?
292
- raise PolicyfileError, "invalid recipe specification #{recipe_spec} in Policyfile from #{policyfile_location}"
286
+ rmatch = recipe_spec.to_s.match(/recipe\[([^:]+)\]/)
287
+ if rmatch.nil?
288
+ raise PolicyfileError, "invalid recipe specification #{recipe_spec} in Policyfile from #{policyfile_location}"
289
+ else
290
+ [rmatch[1], "default"]
291
+ end
293
292
  else
294
293
  [rmatch[1], rmatch[2]]
295
294
  end
@@ -301,8 +300,15 @@ class Chef
301
300
  end
302
301
 
303
302
  # @api private
303
+ # @return [Array<String>]
304
304
  def run_list
305
- if named_run_list_requested?
305
+ return override_runlist.map(&:to_s) if override_runlist
306
+
307
+ if json_attribs["run_list"]
308
+ json_attribs["run_list"]
309
+ elsif persistent_run_list_set?
310
+ node.run_list
311
+ elsif named_run_list_requested?
306
312
  named_run_list || raise(ConfigurationError,
307
313
  "Policy '#{retrieved_policy_name}' revision '#{revision_id}' does not have named_run_list '#{named_run_list_name}'" +
308
314
  "(available named_run_lists: [#{available_named_run_lists.join(", ")}])")
@@ -458,7 +464,7 @@ class Chef
458
464
  # should be reduced to a single call.
459
465
  def cookbooks_to_sync
460
466
  @cookbook_to_sync ||= begin
461
- events.cookbook_resolution_start(run_list_with_versions_for_display)
467
+ events.cookbook_resolution_start(run_list_with_versions_for_display(run_list))
462
468
 
463
469
  cookbook_versions_by_name = cookbook_locks.inject({}) do |cb_map, (name, lock_data)|
464
470
  cb_map[name] = manifest_for(name, lock_data)
@@ -470,7 +476,7 @@ class Chef
470
476
  end
471
477
  rescue Exception => e
472
478
  # TODO: wrap/munge exception to provide helpful error output
473
- events.cookbook_resolution_failed(run_list_with_versions_for_display, e)
479
+ events.cookbook_resolution_failed(run_list_with_versions_for_display(run_list), e)
474
480
  raise
475
481
  end
476
482
 
@@ -509,6 +515,13 @@ class Chef
509
515
  Chef::Config
510
516
  end
511
517
 
518
+ # Indicates whether the policy is temporary, which means an
519
+ # override_runlist was provided. Chef::Client uses this to decide whether
520
+ # to do the final node save at the end of the run or not.
521
+ def temporary_policy?
522
+ node.override_runlist_set?
523
+ end
524
+
512
525
  private
513
526
 
514
527
  # This method injects the run_context and into the Chef class.
@@ -533,6 +546,10 @@ class Chef
533
546
  (policy["named_run_lists"] || {}).keys
534
547
  end
535
548
 
549
+ def persistent_run_list_set?
550
+ Chef::Config[:policy_persist_run_list] && node.run_list && !node.run_list.empty?
551
+ end
552
+
536
553
  def named_run_list_requested?
537
554
  !!Chef::Config[:named_run_list]
538
555
  end
@@ -567,6 +584,32 @@ class Chef
567
584
  Chef::CookbookVersion.from_cb_artifact_data(raw_manifest)
568
585
  end
569
586
 
587
+ def setup_run_list_override
588
+ unless override_runlist.nil?
589
+ runlist_override_sanity_check!
590
+ node.override_runlist = override_runlist
591
+ Chef::Log.warn "Run List override has been provided."
592
+ Chef::Log.warn "Original Run List: [#{node.primary_runlist}]"
593
+ Chef::Log.warn "Overridden Run List: [#{node.run_list}]"
594
+ end
595
+ end
596
+
597
+ # Ensures runlist override contains RunListItem instances
598
+ def runlist_override_sanity_check!
599
+ # Convert to array and remove whitespace
600
+ if override_runlist.is_a?(String)
601
+ @override_runlist = override_runlist.split(",").map(&:strip)
602
+ end
603
+ @override_runlist = [override_runlist].flatten.compact
604
+ override_runlist.map! do |item|
605
+ if item.is_a?(Chef::RunList::RunListItem)
606
+ item
607
+ else
608
+ Chef::RunList::RunListItem.new(item)
609
+ end
610
+ end
611
+ end
612
+
570
613
  end
571
614
  end
572
615
  end