chef 17.3.48 → 17.6.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/chef.gemspec +2 -0
  4. data/lib/chef/application/base.rb +11 -1
  5. data/lib/chef/application.rb +3 -1
  6. data/lib/chef/client.rb +1 -2
  7. data/lib/chef/compliance/default_attributes.rb +5 -3
  8. data/lib/chef/compliance/input.rb +115 -0
  9. data/lib/chef/compliance/input_collection.rb +139 -0
  10. data/lib/chef/compliance/profile.rb +122 -0
  11. data/lib/chef/compliance/profile_collection.rb +109 -0
  12. data/lib/chef/compliance/reporter/automate.rb +1 -1
  13. data/lib/chef/compliance/runner.rb +62 -6
  14. data/lib/chef/compliance/waiver.rb +115 -0
  15. data/lib/chef/compliance/waiver_collection.rb +143 -0
  16. data/lib/chef/dsl/compliance.rb +38 -0
  17. data/lib/chef/dsl/reader_helpers.rb +51 -0
  18. data/lib/chef/dsl/recipe.rb +4 -2
  19. data/lib/chef/dsl/secret.rb +5 -7
  20. data/lib/chef/dsl/universal.rb +2 -0
  21. data/lib/chef/event_dispatch/base.rb +44 -2
  22. data/lib/chef/exceptions.rb +0 -2
  23. data/lib/chef/formatters/doc.rb +60 -13
  24. data/lib/chef/formatters/error_mapper.rb +2 -2
  25. data/lib/chef/formatters/minimal.rb +6 -5
  26. data/lib/chef/http/basic_client.rb +15 -7
  27. data/lib/chef/http.rb +12 -8
  28. data/lib/chef/provider/execute.rb +1 -1
  29. data/lib/chef/provider/file.rb +2 -0
  30. data/lib/chef/provider/group/dscl.rb +1 -1
  31. data/lib/chef/provider/launchd.rb +6 -6
  32. data/lib/chef/provider/link.rb +2 -2
  33. data/lib/chef/provider/registry_key.rb +3 -2
  34. data/lib/chef/provider/remote_file/http.rb +1 -1
  35. data/lib/chef/provider/subversion.rb +4 -4
  36. data/lib/chef/provider/support/yum_repo.erb +1 -1
  37. data/lib/chef/provider/systemd_unit.rb +17 -16
  38. data/lib/chef/provider/template.rb +1 -1
  39. data/lib/chef/provider/user/mac.rb +3 -3
  40. data/lib/chef/provider/yum_repository.rb +27 -43
  41. data/lib/chef/provider/zypper_repository.rb +3 -3
  42. data/lib/chef/provider.rb +26 -1
  43. data/lib/chef/provider_resolver.rb +8 -2
  44. data/lib/chef/resource/archive_file.rb +17 -14
  45. data/lib/chef/resource/chef_client_scheduled_task.rb +45 -2
  46. data/lib/chef/resource/chocolatey_config.rb +13 -13
  47. data/lib/chef/resource/execute.rb +2 -2
  48. data/lib/chef/resource/file/verification/json.rb +50 -0
  49. data/lib/chef/resource/file/verification/yaml.rb +52 -0
  50. data/lib/chef/resource/homebrew_cask.rb +1 -1
  51. data/lib/chef/resource/inspec_input.rb +127 -0
  52. data/lib/chef/resource/inspec_waiver.rb +184 -0
  53. data/lib/chef/resource/inspec_waiver_file_entry.rb +2 -2
  54. data/lib/chef/resource/launchd.rb +3 -3
  55. data/lib/chef/resource/mount.rb +1 -1
  56. data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
  57. data/lib/chef/resource/powershell_package_source.rb +234 -70
  58. data/lib/chef/resource/registry_key.rb +36 -48
  59. data/lib/chef/resource/remote_file.rb +99 -3
  60. data/lib/chef/resource/rhsm_subscription.rb +5 -5
  61. data/lib/chef/resource/ruby_block.rb +100 -0
  62. data/lib/chef/resource/scm/subversion.rb +1 -1
  63. data/lib/chef/resource/sysctl.rb +2 -2
  64. data/lib/chef/resource/systemd_unit.rb +3 -3
  65. data/lib/chef/resource/timezone.rb +2 -2
  66. data/lib/chef/resource/user_ulimit.rb +1 -0
  67. data/lib/chef/resource/windows_printer.rb +1 -1
  68. data/lib/chef/resource/windows_uac.rb +3 -1
  69. data/lib/chef/resource/windows_user_privilege.rb +1 -1
  70. data/lib/chef/resource/yum_package.rb +1 -5
  71. data/lib/chef/resource.rb +13 -17
  72. data/lib/chef/resource_inspector.rb +6 -2
  73. data/lib/chef/resources.rb +2 -0
  74. data/lib/chef/run_context/cookbook_compiler.rb +112 -28
  75. data/lib/chef/run_context.rb +31 -1
  76. data/lib/chef/secret_fetcher/akeyless_vault.rb +57 -0
  77. data/lib/chef/secret_fetcher/aws_secrets_manager.rb +17 -5
  78. data/lib/chef/secret_fetcher/azure_key_vault.rb +32 -10
  79. data/lib/chef/secret_fetcher/base.rb +6 -2
  80. data/lib/chef/secret_fetcher/hashi_vault.rb +100 -0
  81. data/lib/chef/secret_fetcher.rb +13 -6
  82. data/lib/chef/version.rb +1 -1
  83. data/lib/chef/win32/version.rb +2 -1
  84. data/spec/data/archive_file/test_archive.tar.gz +0 -0
  85. data/spec/functional/resource/archive_file_spec.rb +87 -0
  86. data/spec/functional/resource/group_spec.rb +5 -1
  87. data/spec/functional/resource/link_spec.rb +8 -0
  88. data/spec/functional/resource/powershell_package_source_spec.rb +5 -6
  89. data/spec/integration/compliance/compliance_spec.rb +61 -0
  90. data/spec/integration/recipes/resource_action_spec.rb +2 -2
  91. data/spec/spec_helper.rb +3 -0
  92. data/spec/support/platform_helpers.rb +4 -0
  93. data/spec/support/ruby_installer.rb +51 -0
  94. data/spec/unit/compliance/input_spec.rb +104 -0
  95. data/spec/unit/compliance/profile_spec.rb +120 -0
  96. data/spec/unit/compliance/runner_spec.rb +46 -2
  97. data/spec/unit/compliance/waiver_spec.rb +104 -0
  98. data/spec/unit/dsl/secret_spec.rb +8 -2
  99. data/spec/unit/formatters/doc_spec.rb +1 -1
  100. data/spec/unit/http/basic_client_spec.rb +30 -0
  101. data/spec/unit/http_spec.rb +8 -2
  102. data/spec/unit/provider/link_spec.rb +13 -7
  103. data/spec/unit/provider/remote_file/http_spec.rb +10 -0
  104. data/spec/unit/provider/template_spec.rb +2 -2
  105. data/spec/unit/provider_spec.rb +23 -0
  106. data/spec/unit/resource/archive_file_spec.rb +414 -3
  107. data/spec/unit/resource/chef_client_scheduled_task_spec.rb +69 -0
  108. data/spec/unit/resource/file/verification/json_spec.rb +72 -0
  109. data/spec/unit/resource/file/verification/yaml_spec.rb +67 -0
  110. data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
  111. data/spec/unit/resource/inspec_input_spec.rb +300 -0
  112. data/spec/unit/resource/inspec_waiver_spec.rb +312 -0
  113. data/spec/unit/resource/mount_spec.rb +10 -0
  114. data/spec/unit/resource/powershell_package_source_spec.rb +63 -62
  115. data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
  116. data/spec/unit/resource/systemd_unit_spec.rb +1 -1
  117. data/spec/unit/resource/user_ulimit_spec.rb +14 -1
  118. data/spec/unit/resource_spec.rb +19 -8
  119. data/spec/unit/secret_fetcher/akeyless_vault_spec.rb +37 -0
  120. data/spec/unit/secret_fetcher/aws_secrets_manager_spec.rb +70 -0
  121. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +23 -16
  122. data/spec/unit/secret_fetcher/hashi_vault_spec.rb +80 -0
  123. data/spec/unit/secret_fetcher_spec.rb +9 -9
  124. data/tasks/rspec.rb +2 -1
  125. metadata +61 -6
@@ -28,7 +28,7 @@ class Chef
28
28
  class Provider
29
29
  class User
30
30
  # A macOS user provider that is compatible with default TCC restrictions
31
- # in macOS 10.14. See resource/user/mac_user.rb for complete description
31
+ # in macOS 10.14+. See resource/user/mac_user.rb for complete description
32
32
  # of the mac_user resource
33
33
  class MacUser < Chef::Provider::User
34
34
  include Chef::Mixin::Which
@@ -49,11 +49,11 @@ class Chef
49
49
  current_resource.uid(user_plist[:uid][0])
50
50
  current_resource.gid(user_plist[:gid][0])
51
51
  current_resource.home(user_plist[:home][0])
52
- current_resource.shell(user_plist[:shell][0])
52
+ current_resource.shell(user_plist[:shell]&.first) # use &.first since shell can be nil
53
53
  current_resource.comment(user_plist[:comment][0])
54
54
 
55
55
  if user_plist[:is_hidden]
56
- current_resource.hidden(user_plist[:is_hidden][0] == "1" ? true : false)
56
+ current_resource.hidden(user_plist[:is_hidden]&.first == "1" ? true : false) # when not hidden the value seems to be nil so &.first to handle that
57
57
  end
58
58
 
59
59
  shadow_hash = user_plist[:shadow_hash]
@@ -17,7 +17,6 @@
17
17
  #
18
18
 
19
19
  require_relative "../resource"
20
- require_relative "../dsl/declare_resource"
21
20
  require_relative "../mixin/which"
22
21
  require_relative "noop"
23
22
 
@@ -32,8 +31,8 @@ class Chef
32
31
 
33
32
  def load_current_resource; end
34
33
 
35
- action :create do
36
- declare_resource(:template, ::File.join(new_resource.reposdir, "#{new_resource.repositoryid}.repo")) do
34
+ action :create, description: "Create a repository based on the properties." do
35
+ template ::File.join(new_resource.reposdir, "#{new_resource.repositoryid}.repo") do
37
36
  if template_available?(new_resource.source)
38
37
  source new_resource.source
39
38
  else
@@ -46,72 +45,57 @@ class Chef
46
45
  if new_resource.make_cache
47
46
  notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers
48
47
  notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately
49
- notifies :create, "ruby_block[package-cache-reload-#{new_resource.repositoryid}]", :immediately
48
+ notifies :flush_cache, "package[package-cache-reload-#{new_resource.repositoryid}]", :immediately
50
49
  end
51
50
  end
52
51
 
53
- declare_resource(:execute, "yum clean metadata #{new_resource.repositoryid}") do
54
- command "yum clean metadata --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
55
- action :nothing
56
- end
52
+ # avoid extra logging if make_cache property isn't set
53
+ if new_resource.make_cache
54
+ execute "yum clean metadata #{new_resource.repositoryid}" do
55
+ command "yum clean metadata --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
56
+ action :nothing
57
+ end
57
58
 
58
- # get the metadata for this repo only
59
- declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do
60
- command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
61
- action :nothing
62
- only_if { new_resource.enabled }
63
- end
59
+ # get the metadata for this repo only
60
+ execute "yum-makecache-#{new_resource.repositoryid}" do
61
+ command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
62
+ action :nothing
63
+ only_if { new_resource.enabled }
64
+ end
64
65
 
65
- # reload internal Chef yum/dnf cache
66
- declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do
67
- if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) ||
68
- ( platform_family?("rhel") && node["platform_version"].to_i >= 8 )
69
- block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart }
70
- else
71
- block { Chef::Provider::Package::Yum::YumCache.instance.reload }
66
+ package "package-cache-reload-#{new_resource.repositoryid}" do
67
+ action :nothing
72
68
  end
73
- action :nothing
74
69
  end
75
70
  end
76
71
 
77
- action :delete do
72
+ action :delete, description: "Remove a repository." do
78
73
  # clean the repo cache first
79
- declare_resource(:execute, "yum clean all #{new_resource.repositoryid}") do
74
+ execute "yum clean all #{new_resource.repositoryid}" do
80
75
  command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
81
76
  only_if "yum repolist all | grep -P '^#{new_resource.repositoryid}([ \t]|$)'"
82
77
  end
83
78
 
84
- declare_resource(:file, ::File.join(new_resource.reposdir, "#{new_resource.repositoryid}.repo")) do
79
+ file ::File.join(new_resource.reposdir, "#{new_resource.repositoryid}.repo") do
85
80
  action :delete
86
- notifies :create, "ruby_block[package-cache-reload-#{new_resource.repositoryid}]", :immediately
81
+ notifies :flush_cache, "package[package-cache-reload-#{new_resource.repositoryid}]", :immediately
87
82
  end
88
83
 
89
- declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do
90
- if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) ||
91
- ( platform_family?("rhel") && node["platform_version"].to_i >= 8 )
92
- block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart }
93
- else
94
- block { Chef::Provider::Package::Yum::YumCache.instance.reload }
95
- end
84
+ package "package-cache-reload-#{new_resource.repositoryid}" do
96
85
  action :nothing
97
86
  end
98
87
  end
99
88
 
100
- action :makecache do
101
- declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do
89
+ action :makecache, description: "Force the creation of the repository cache. This is also done automatically when a repository is updated." do
90
+ execute "yum-makecache-#{new_resource.repositoryid}" do
102
91
  command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
103
92
  action :run
104
93
  only_if { new_resource.enabled }
94
+ notifies :flush_cache, "package[package-cache-reload-#{new_resource.repositoryid}]", :immediately
105
95
  end
106
96
 
107
- declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do
108
- if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) ||
109
- ( platform_family?("rhel") && node["platform_version"].to_i >= 8 )
110
- block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart }
111
- else
112
- block { Chef::Provider::Package::Yum::YumCache.instance.reload }
113
- end
114
- action :run
97
+ package "package-cache-reload-#{new_resource.repositoryid}" do
98
+ action :nothing
115
99
  end
116
100
  end
117
101
 
@@ -29,7 +29,7 @@ class Chef
29
29
 
30
30
  def load_current_resource; end
31
31
 
32
- action :create do
32
+ action :create, description: "Add a new Zypper repository." do
33
33
  if new_resource.gpgautoimportkeys
34
34
  install_gpg_keys(new_resource.gpgkey)
35
35
  else
@@ -50,13 +50,13 @@ class Chef
50
50
  end
51
51
  end
52
52
 
53
- action :delete do
53
+ action :delete, description: "Remove a Zypper repository." do
54
54
  execute "zypper --quiet --non-interactive removerepo #{escaped_repo_name}" do
55
55
  only_if "zypper --quiet lr #{escaped_repo_name}"
56
56
  end
57
57
  end
58
58
 
59
- action :refresh do
59
+ action :refresh, description: "Refresh Zypper repository." do
60
60
  execute "zypper --quiet --non-interactive refresh --force #{escaped_repo_name}" do
61
61
  only_if "zypper --quiet lr #{escaped_repo_name}"
62
62
  end
data/lib/chef/provider.rb CHANGED
@@ -57,10 +57,12 @@ class Chef
57
57
  #
58
58
  # @since 13.0
59
59
  # @param name [String, Symbol] Name of the action to define.
60
+ # @param description [String] description of the action
60
61
  # @param block [Proc] Body of the action.
61
62
  #
62
63
  # @return [void]
63
- def self.action(name, &block)
64
+ def self.action(name, description: nil, &block)
65
+ action_descriptions[name.to_sym] = description unless description.nil?
64
66
  # We need the block directly in a method so that `return` works.
65
67
  define_method("compile_action_#{name}", &block)
66
68
  class_eval <<-EOM
@@ -70,6 +72,29 @@ class Chef
70
72
  EOM
71
73
  end
72
74
 
75
+ # Return the hash of action descriptions defined for
76
+ # the provider class.
77
+ #
78
+ # @return [Hash] hash of [Symbol] => [String] containing
79
+ # any provided action descriptions.
80
+ def self.action_descriptions
81
+ @action_descriptions ||= {}
82
+ end
83
+
84
+ # Retrieve the description for a provider's action, if
85
+ # any description has been included in the definition.
86
+ #
87
+ # @param action [Symbol,String] the action name
88
+ # @return [String] the description of the action provided, or nil if no description
89
+ # was defined
90
+ def self.action_description(action)
91
+ description = action_descriptions[action.to_sym]
92
+ if description.nil? && superclass.respond_to?(:action_description)
93
+ description = superclass.action_description(action)
94
+ end
95
+ description
96
+ end
97
+
73
98
  # Deprecation stub for the old use_inline_resources mode.
74
99
  #
75
100
  # @return [void]
@@ -57,10 +57,16 @@ class Chef
57
57
  end
58
58
 
59
59
  def resolve
60
- maybe_explicit_provider(resource) ||
60
+ resolved = maybe_explicit_provider(resource) ||
61
61
  maybe_custom_resource(resource) ||
62
- maybe_dynamic_provider_resolution(resource, action) ||
62
+ maybe_dynamic_provider_resolution(resource, action)
63
+
64
+ if resolved.nil?
65
+ raise(Chef::Exceptions::ProviderNotFound, "Cannot find a provider for #{resource}") if node.nil?
66
+
63
67
  raise(Chef::Exceptions::ProviderNotFound, "Cannot find a provider for #{resource} on #{node["platform"]} version #{node["platform_version"]}")
68
+ end
69
+ resolved
64
70
  end
65
71
 
66
72
  # Does NOT call provides? on the resource (it is assumed this is being
@@ -81,6 +81,11 @@ class Chef
81
81
  description: "Should the resource overwrite the destination file contents if they already exist? If set to `:auto` the date stamp of files within the archive will be compared to those on disk and disk contents will be overwritten if they differ. This may cause unintended consequences if disk date stamps are changed between runs, which will result in the files being overwritten during each client run. Make sure to properly test any change to this property.",
82
82
  default: false
83
83
 
84
+ property :strip_components, Integer,
85
+ description: "Remove the specified number of leading path elements. Pathnames with fewer elements will be silently skipped. This behaves similarly to tar's --strip-components command line argument.",
86
+ introduced: "17.5",
87
+ default: 0
88
+
84
89
  # backwards compatibility for the legacy cookbook names
85
90
  alias_method :extract_options, :options
86
91
  alias_method :extract_to, :destination
@@ -117,7 +122,7 @@ class Chef
117
122
 
118
123
  if new_resource.owner || new_resource.group
119
124
  converge_by("set owner of files extracted in #{new_resource.destination} to #{new_resource.owner}:#{new_resource.group}") do
120
- archive = Archive::Reader.open_filename(new_resource.path)
125
+ archive = Archive::Reader.open_filename(new_resource.path, nil, strip_components: new_resource.strip_components)
121
126
  archive.each_entry do |e|
122
127
  FileUtils.chown(new_resource.owner, new_resource.group, "#{new_resource.destination}/#{e.pathname}")
123
128
  end
@@ -160,18 +165,16 @@ class Chef
160
165
  # @return [Boolean]
161
166
  def archive_differs_from_disk?(src, dest)
162
167
  modified = false
163
- Dir.chdir(dest) do
164
- archive = Archive::Reader.open_filename(src)
165
- Chef::Log.trace("Beginning the comparison of file mtime between contents of #{src} and #{dest}")
166
- archive.each_entry do |e|
167
- pathname = ::File.expand_path(e.pathname)
168
- if ::File.exist?(pathname)
169
- Chef::Log.trace("#{pathname} mtime is #{::File.mtime(pathname)} and archive is #{e.mtime}")
170
- modified = true unless ::File.mtime(pathname) == e.mtime
171
- else
172
- Chef::Log.trace("#{pathname} doesn't exist on disk, but exists in the archive")
173
- modified = true
174
- end
168
+ archive = Archive::Reader.open_filename(src, nil, strip_components: new_resource.strip_components)
169
+ Chef::Log.trace("Beginning the comparison of file mtime between contents of #{src} and #{dest}")
170
+ archive.each_entry do |e|
171
+ pathname = ::File.expand_path(e.pathname, dest)
172
+ if ::File.exist?(pathname)
173
+ Chef::Log.trace("#{pathname} mtime is #{::File.mtime(pathname)} and archive is #{e.mtime}")
174
+ modified = true unless ::File.mtime(pathname) == e.mtime
175
+ else
176
+ Chef::Log.trace("#{pathname} doesn't exist on disk, but exists in the archive")
177
+ modified = true
175
178
  end
176
179
  end
177
180
  modified
@@ -189,7 +192,7 @@ class Chef
189
192
  flags = [options].flatten.map { |option| extract_option_map[option] }.compact.reduce(:|)
190
193
 
191
194
  Dir.chdir(dest) do
192
- archive = Archive::Reader.open_filename(src)
195
+ archive = Archive::Reader.open_filename(src, nil, strip_components: new_resource.strip_components)
193
196
 
194
197
  archive.each_entry do |e|
195
198
  archive.extract(e, flags.to_i)
@@ -58,6 +58,14 @@ class Chef
58
58
  daemon_options ['-n audit_only']
59
59
  end
60
60
  ```
61
+
62
+ **Run #{ChefUtils::Dist::Infra::PRODUCT} with a persistent delay on every run calculated once, similar to how chef_client_cron resource works**:
63
+
64
+ ```ruby
65
+ chef_client_scheduled_task 'Run chef-client with persistent splay' do
66
+ use_consistent_splay true
67
+ end
68
+ ```
61
69
  DOC
62
70
 
63
71
  resource_name :chef_client_scheduled_task
@@ -104,6 +112,11 @@ class Chef
104
112
  description: "A random number of seconds between 0 and X to add to interval so that all #{ChefUtils::Dist::Infra::CLIENT} commands don't execute at the same time.",
105
113
  default: 300
106
114
 
115
+ property :use_consistent_splay, [true, false],
116
+ description: "Always use the same random splay amount for each node to ensure consistent frequencies between #{ChefUtils::Dist::Infra::CLIENT} execution.",
117
+ introduced: "17.5",
118
+ default: false
119
+
107
120
  property :run_on_battery, [true, false],
108
121
  description: "Run the #{ChefUtils::Dist::Infra::PRODUCT} task when the system is on batteries.",
109
122
  default: true
@@ -129,6 +142,11 @@ class Chef
129
142
  description: "An array of options to pass to the #{ChefUtils::Dist::Infra::CLIENT} command.",
130
143
  default: []
131
144
 
145
+ property :priority, Integer,
146
+ description: "Use to set Priority Levels range from 0 to 10.",
147
+ introduced: "17.5",
148
+ default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
149
+
132
150
  action :add, description: "Add a Windows Scheduled Task that runs #{ChefUtils::Dist::Infra::PRODUCT}." do
133
151
  # TODO: Replace this with a :create_if_missing action on directory when that exists
134
152
  unless Dir.exist?(new_resource.log_directory)
@@ -151,8 +169,9 @@ class Chef
151
169
  frequency_modifier new_resource.frequency_modifier if frequency_supports_frequency_modifier?
152
170
  start_time new_resource.start_time
153
171
  start_day new_resource.start_date unless new_resource.start_date.nil?
154
- random_delay new_resource.splay if frequency_supports_random_delay?
172
+ random_delay new_resource.splay if frequency_supports_random_delay? && !new_resource.use_consistent_splay
155
173
  disallow_start_if_on_batteries new_resource.splay unless new_resource.run_on_battery
174
+ priority new_resource.priority
156
175
  action %i{create enable}
157
176
  end
158
177
  end
@@ -173,7 +192,31 @@ class Chef
173
192
  # Fetch path of cmd.exe through environment variable comspec
174
193
  cmd_path = ENV["COMSPEC"]
175
194
 
176
- "#{cmd_path} /c \"#{client_cmd}\""
195
+ "#{cmd_path} /c \"#{consistent_splay_command}#{client_cmd}\""
196
+ end
197
+
198
+ #
199
+ # Generate a uniformly distributed unique number to sleep from 0 to the splay time
200
+ #
201
+ # @param [Integer] splay The number of seconds to splay
202
+ #
203
+ # @return [Integer]
204
+ #
205
+ def splay_sleep_time(splay)
206
+ seed = node["shard_seed"] || Digest::MD5.hexdigest(node.name).to_s.hex
207
+ random = Random.new(seed.to_i)
208
+ random.rand(splay)
209
+ end
210
+
211
+ #
212
+ # The consistent splay sleep time when use_consistent_splay is true.
213
+ #
214
+ # @return [NilClass,String] The prepended sleep command to run prior to executing the full command.
215
+ #
216
+ def consistent_splay_command
217
+ return unless new_resource.use_consistent_splay
218
+
219
+ "C:/windows/system32/windowspowershell/v1.0/powershell.exe Start-Sleep -s #{splay_sleep_time(new_resource.splay)} && "
177
220
  end
178
221
 
179
222
  #
@@ -24,22 +24,22 @@ class Chef
24
24
  description "Use the **chocolatey_config** resource to add or remove Chocolatey configuration keys."
25
25
  introduced "14.3"
26
26
  examples <<~DOC
27
- **Set the Chocolatey cacheLocation config**:
27
+ **Set the Chocolatey cacheLocation config**:
28
28
 
29
- ```ruby
30
- chocolatey_config 'Set cacheLocation config' do
31
- config_key 'cacheLocation'
32
- value 'C:\temp\choco'
33
- end
34
- ```
29
+ ```ruby
30
+ chocolatey_config 'Set cacheLocation config' do
31
+ config_key 'cacheLocation'
32
+ value 'C:\\temp\\choco'
33
+ end
34
+ ```
35
35
 
36
- **Unset a Chocolatey config**:
36
+ **Unset a Chocolatey config**:
37
37
 
38
- ```ruby
39
- chocolatey_config 'BogusConfig' do
40
- action :unset
41
- end
42
- ```
38
+ ```ruby
39
+ chocolatey_config 'BogusConfig' do
40
+ action :unset
41
+ end
42
+ ```
43
43
  DOC
44
44
 
45
45
  property :config_key, String, name_property: true,
@@ -549,11 +549,11 @@ class Chef
549
549
  desired_state: false
550
550
 
551
551
  property :user, [ String, Integer ],
552
- description: "The user name of the user identity with which to launch the new process. The user name may optionally be specified with a domain, i.e. `domainuser` or `user@my.dns.domain.com` via Universal Principal Name (UPN)format. It can also be specified without a domain simply as user if the domain is instead specified using the domain property. On Windows only, if this property is specified, the password property must be specified."
552
+ description: "The user name of the user identity with which to launch the new process. The user name may optionally be specified with a domain, i.e. `domain\\user` or `user@my.dns.domain.com` via Universal Principal Name (UPN)format. It can also be specified without a domain simply as user if the domain is instead specified using the domain property. On Windows only, if this property is specified, the password property must be specified."
553
553
 
554
554
  property :domain, String,
555
555
  introduced: "12.21",
556
- description: "Windows only: The domain of the user user specified by the user property. If not specified, the username and password specified by the `user` and `password` properties will be used to resolve that user against the domain in which the system running #{ChefUtils::Dist::Infra::PRODUCT} is joined, or if that system is not joined to a domain it will resolve the user as a local account on that system. An alternative way to specify the domain is to leave this property unspecified and specify the domain as part of the user property."
556
+ description: "Windows only: The domain of the user specified by the user property. If not specified, the username and password specified by the `user` and `password` properties will be used to resolve that user against the domain in which the system running #{ChefUtils::Dist::Infra::PRODUCT} is joined, or if that system is not joined to a domain it will resolve the user as a local account on that system. An alternative way to specify the domain is to leave this property unspecified and specify the domain as part of the user property."
557
557
 
558
558
  property :password, String, sensitive: true,
559
559
  introduced: "12.21",
@@ -0,0 +1,50 @@
1
+ #
2
+ # Author:: Antony Thomas (<antonydeepak@gmail.com>)
3
+ # Copyright:: Copyright (c) Facebook, Inc. and its affiliates.
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
+
19
+ class Chef
20
+ class Resource
21
+ class File
22
+ class Verification
23
+
24
+ #
25
+ # Extends File verification to provide Json verification
26
+ #
27
+ # Example:
28
+ # file 'foo.json' do
29
+ # content '{"foo": "bar"}'
30
+ # verify :json
31
+ # end
32
+ #
33
+ #
34
+
35
+ class Json < Chef::Resource::File::Verification
36
+
37
+ provides :json
38
+
39
+ def verify(path, opts = {})
40
+ Chef::JSONCompat.parse(IO.read(path))
41
+ true
42
+ rescue Chef::Exceptions::JSON::ParseError => e
43
+ Chef::Log.error("Json syntax verify failed with : #{e.message}")
44
+ false
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,52 @@
1
+ #
2
+ # Author:: Antony Thomas (<antonydeepak@gmail.com>)
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
+
19
+ require "psych" unless defined?(Psych)
20
+
21
+ class Chef
22
+ class Resource
23
+ class File
24
+ class Verification
25
+
26
+ #
27
+ # Extends File verification to provide a Yaml verification
28
+ #
29
+ # Example:
30
+ # file 'foo.yaml' do
31
+ # content "--- foo: 'foo-"
32
+ # verify :yaml
33
+ # end
34
+ #
35
+ #
36
+
37
+ class Yaml < Chef::Resource::File::Verification
38
+
39
+ provides :yaml
40
+
41
+ def verify(path, opts = {})
42
+ Psych.parse_file(path)
43
+ true
44
+ rescue Psych::SyntaxError => e
45
+ Chef::Log.error("Yaml syntax verify failed with : #{e.message}")
46
+ false
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -34,7 +34,7 @@ class Chef
34
34
 
35
35
  property :cask_name, String,
36
36
  description: "An optional property to set the cask name if it differs from the resource block's name.",
37
- regex: %r{^[\w/-]+$},
37
+ regex: %r{^[\w/\-@]+$},
38
38
  validation_message: "The provided Homebrew cask name is not valid. Cask names can contain alphanumeric characters, _, -, or / only!",
39
39
  name_property: true
40
40
 
@@ -0,0 +1,127 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require_relative "../resource"
18
+
19
+ class Chef
20
+ class Resource
21
+ class InspecInput < Chef::Resource
22
+ provides :inspec_input
23
+ unified_mode true
24
+
25
+ description "Use the **inspec_input** resource to add an input to the Compliance Phase."
26
+ introduced "17.5"
27
+ examples <<~DOC
28
+
29
+ **Activate the default input in the openssh cookbook's compliance segment**:
30
+
31
+ ```ruby
32
+ inspec_input 'openssh' do
33
+ action :add
34
+ end
35
+ ```
36
+
37
+ **Activate all inputs in the openssh cookbook's compliance segment**:
38
+
39
+ ```ruby
40
+ inspec_input 'openssh::.*' do
41
+ action :add
42
+ end
43
+ ```
44
+
45
+ **Add an InSpec input to the Compliance Phase from a hash**:
46
+
47
+ ```ruby
48
+ inspec_input { ssh_custom_path: '/whatever2' }
49
+ ```
50
+
51
+ **Add an InSpec input to the Compliance Phase using the 'name' property to identify the input**:
52
+
53
+ ```ruby
54
+ inspec_input "setting my input" do
55
+ source( { ssh_custom_path: '/whatever2' })
56
+ end
57
+ ```
58
+
59
+ **Add an InSpec input to the Compliance Phase using a TOML, JSON, or YAML file**:
60
+
61
+ ```ruby
62
+ inspec_input "/path/to/my/input.yml"
63
+ ```
64
+
65
+ **Add an InSpec input to the Compliance Phase using a TOML, JSON, or YAML file, using the 'name' property**:
66
+
67
+ ```ruby
68
+ inspec_input "setting my input" do
69
+ source "/path/to/my/input.yml"
70
+ end
71
+ ```
72
+
73
+ Note that the **inspec_input** resource does not update and will not fire notifications (similar to the log resource). This is done to preserve the ability to use
74
+ the resource while not causing the updated resource count to be larger than zero. Since the resource does not update the state of the managed node, this behavior
75
+ is still consistent with the configuration management model. Instead, you should use events to observe configuration changes for the compliance phase. It is
76
+ possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use, and you should use pure ruby
77
+ conditionals instead. Compliance configuration should be independent of other resources and should only be conditional based on state/attributes, not other resources.
78
+ DOC
79
+
80
+ property :name, [ Hash, String ]
81
+
82
+ property :input, [ Hash, String ],
83
+ name_property: true
84
+
85
+ property :source, [ Hash, String ],
86
+ name_property: true
87
+
88
+ action :add, description: "Add an input to the compliance phase" do
89
+ if run_context.input_collection.valid?(new_resource.input)
90
+ include_input(new_resource.input)
91
+ else
92
+ include_input(input_hash)
93
+ end
94
+ end
95
+
96
+ action_class do
97
+ # If the source is nil and the input / name_property contains a file separator and is a string of a
98
+ # file that exists, then use that as the file (similar to the package provider automatic source property). Otherwise
99
+ # just return the source.
100
+ #
101
+ # @api private
102
+ def source
103
+ @source ||= build_source
104
+ end
105
+
106
+ def build_source
107
+ return new_resource.source unless new_resource.source.nil?
108
+ return nil unless new_resource.input.count(::File::SEPARATOR) > 0 || (::File::ALT_SEPARATOR && new_resource.input.count(::File::ALT_SEPARATOR) > 0 )
109
+ return nil unless ::File.exist?(new_resource.input)
110
+
111
+ new_resource.input
112
+ end
113
+
114
+ def input_hash
115
+ case source
116
+ when Hash
117
+ source
118
+ when String
119
+ parse_file(source)
120
+ when nil
121
+ raise Chef::Exceptions::ValidationFailed, "Could not find the input #{new_resource.input} in any cookbook segment."
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end