chef 17.2.29 → 17.3.48
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -3
- data/chef.gemspec +1 -0
- data/lib/chef/client.rb +1 -1
- data/lib/chef/data_bag.rb +1 -2
- data/lib/chef/data_bag_item.rb +1 -2
- data/lib/chef/deprecated.rb +10 -4
- data/lib/chef/dsl.rb +1 -0
- data/lib/chef/dsl/render_helpers.rb +44 -0
- data/lib/chef/dsl/secret.rb +64 -0
- data/lib/chef/dsl/toml.rb +116 -0
- data/lib/chef/dsl/universal.rb +5 -0
- data/lib/chef/exceptions.rb +22 -0
- data/lib/chef/handler/slow_report.rb +1 -1
- data/lib/chef/json_compat.rb +1 -1
- data/lib/chef/policy_builder/policyfile.rb +88 -45
- data/lib/chef/provider/file.rb +2 -2
- data/lib/chef/provider/lwrp_base.rb +1 -1
- data/lib/chef/provider/package/habitat.rb +168 -0
- data/lib/chef/provider/package/powershell.rb +5 -0
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/resource/chef_client_config.rb +7 -2
- data/lib/chef/resource/chef_client_cron.rb +1 -1
- data/lib/chef/resource/chef_client_launchd.rb +1 -1
- data/lib/chef/resource/chef_client_scheduled_task.rb +1 -1
- data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
- data/lib/chef/resource/chef_client_trusted_certificate.rb +2 -2
- data/lib/chef/resource/chef_vault_secret.rb +2 -2
- data/lib/chef/resource/dsc_resource.rb +1 -1
- data/lib/chef/resource/execute.rb +3 -3
- data/lib/chef/resource/gem_package.rb +2 -1
- data/lib/chef/resource/habitat/_habitat_shared.rb +28 -0
- data/lib/chef/resource/habitat/habitat_package.rb +129 -0
- data/lib/chef/resource/habitat/habitat_sup.rb +329 -0
- data/lib/chef/resource/habitat/habitat_sup_systemd.rb +67 -0
- data/lib/chef/resource/habitat/habitat_sup_windows.rb +90 -0
- data/lib/chef/resource/habitat_config.rb +107 -0
- data/lib/chef/resource/habitat_install.rb +247 -0
- data/lib/chef/resource/habitat_service.rb +451 -0
- data/lib/chef/resource/habitat_user_toml.rb +92 -0
- data/lib/chef/resource/lwrp_base.rb +1 -1
- data/lib/chef/resource/support/HabService.dll.config.erb +19 -0
- data/lib/chef/resource/support/client.erb +8 -1
- data/lib/chef/resource/support/sup.toml.erb +179 -0
- data/lib/chef/resource/windows_defender.rb +163 -0
- data/lib/chef/resource/windows_defender_exclusion.rb +125 -0
- data/lib/chef/resource/windows_printer.rb +78 -44
- data/lib/chef/resource/windows_printer_port.rb +1 -1
- data/lib/chef/resource/windows_update_settings.rb +259 -0
- data/lib/chef/resources.rb +12 -1
- data/lib/chef/secret_fetcher.rb +54 -0
- data/lib/chef/secret_fetcher/aws_secrets_manager.rb +53 -0
- data/lib/chef/secret_fetcher/azure_key_vault.rb +56 -0
- data/lib/chef/secret_fetcher/base.rb +72 -0
- data/lib/chef/secret_fetcher/example.rb +46 -0
- data/lib/chef/version.rb +1 -1
- data/spec/functional/mixin/from_file_spec.rb +1 -1
- data/spec/integration/recipes/recipe_dsl_spec.rb +1 -1
- data/spec/integration/recipes/resource_action_spec.rb +4 -4
- data/spec/support/shared/unit/provider/file.rb +2 -8
- data/spec/unit/data_bag_item_spec.rb +2 -2
- data/spec/unit/data_bag_spec.rb +1 -1
- data/spec/unit/dsl/render_helpers_spec.rb +102 -0
- data/spec/unit/dsl/secret_spec.rb +65 -0
- data/spec/unit/policy_builder/dynamic_spec.rb +0 -5
- data/spec/unit/policy_builder/policyfile_spec.rb +144 -56
- data/spec/unit/provider/apt_update_spec.rb +3 -1
- data/spec/unit/provider/mount/aix_spec.rb +1 -1
- data/spec/unit/provider/package/powershell_spec.rb +74 -12
- data/spec/unit/resource/windows_defender_exclusion_spec.rb +62 -0
- data/spec/unit/resource/windows_defender_spec.rb +71 -0
- data/spec/unit/resource/windows_update_settings_spec.rb +64 -0
- data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +63 -0
- data/spec/unit/secret_fetcher_spec.rb +82 -0
- metadata +51 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45a45627ed2995c171f44e97e524e17cdcc2b8a3c4566c6cba3e7e57a5810f71
|
4
|
+
data.tar.gz: 5bbe7e7fecc35ddfddc730addb9a944a798ff252a239e433f6894228c9af6359
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ef336ebe43aa213491af9e263758101f040ee306537d8d3d0db4a6484fa33daf78c0a524525ee648688cfe9fa2c77d5163ce310d6977b85c0ccf761fcc763ba
|
7
|
+
data.tar.gz: 554e9acfa53f9bc83a3b04cd9efb913b984bf9f69cb58b924a3ad9744fd2af8ff8bf42b6b495ba243ad71364d59ba433f6c440b9768c59aa3a7d9239948e2c7e
|
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
|
-
|
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
|
-
|
32
|
+
gem "pry-byebug" unless RUBY_PLATFORM =~ /freebsd/i
|
32
33
|
gem "pry-stack_explorer"
|
33
34
|
end
|
34
35
|
|
data/chef.gemspec
CHANGED
data/lib/chef/client.rb
CHANGED
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
|
-
|
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)
|
data/lib/chef/data_bag_item.rb
CHANGED
@@ -36,8 +36,7 @@ class Chef
|
|
36
36
|
include Chef::Mixin::FromFile
|
37
37
|
include Chef::Mixin::ParamsValidate
|
38
38
|
|
39
|
-
|
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 )
|
data/lib/chef/deprecated.rb
CHANGED
@@ -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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
@@ -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
|
data/lib/chef/dsl/universal.rb
CHANGED
@@ -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
|
data/lib/chef/exceptions.rb
CHANGED
@@ -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
|
62
|
+
resource.source_line&.gsub(%r{.*/cookbooks/}, "")&.gsub(%r{.*/chef-[0-9\.]+/}, "")
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
data/lib/chef/json_compat.rb
CHANGED
@@ -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
|
-
#
|
36
|
-
#
|
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
|
-
|
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
|
-
|
235
|
-
|
224
|
+
## Internal Public API ##
|
225
|
+
|
226
|
+
# @api private
|
236
227
|
#
|
237
|
-
#
|
238
|
-
|
239
|
-
|
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
|
-
|
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
|
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
|