summaryrefslogtreecommitdiff
path: root/lib/chef/resource
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/resource')
-rw-r--r--lib/chef/resource/apt_package.rb2
-rw-r--r--lib/chef/resource/cron_access.rb14
-rw-r--r--lib/chef/resource/execute.rb544
-rw-r--r--lib/chef/resource/file.rb2
-rw-r--r--lib/chef/resource/homebrew_package.rb31
-rw-r--r--lib/chef/resource/homebrew_update.rb106
-rw-r--r--lib/chef/resource/hostname.rb25
-rw-r--r--lib/chef/resource/kernel_module.rb15
-rw-r--r--lib/chef/resource/plist.rb27
-rw-r--r--lib/chef/resource/remote_file.rb36
-rw-r--r--lib/chef/resource/template.rb2
-rw-r--r--lib/chef/resource/windows_shortcut.rb1
-rw-r--r--lib/chef/resource/windows_task.rb4
-rw-r--r--lib/chef/resource/windows_user_privilege.rb10
-rw-r--r--lib/chef/resource/yum_repository.rb18
15 files changed, 775 insertions, 62 deletions
diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb
index 369330be9f..0a31f89af3 100644
--- a/lib/chef/resource/apt_package.rb
+++ b/lib/chef/resource/apt_package.rb
@@ -46,7 +46,7 @@ class Chef
apt_package %(package1 package2 package3)
```
- **Install without using recommend packages as a dependency**
+ **Install without using recommend packages as a dependency**:
```ruby
package 'apache2' do
diff --git a/lib/chef/resource/cron_access.rb b/lib/chef/resource/cron_access.rb
index f0e5ed64bf..59b510a65f 100644
--- a/lib/chef/resource/cron_access.rb
+++ b/lib/chef/resource/cron_access.rb
@@ -28,7 +28,7 @@ class Chef
provides(:cron_manage) # legacy name @todo in Chef 15 we should { true } this so it wins over the cookbook
introduced "14.4"
- description "Use the **cron_access** resource to manage the /etc/cron.allow and /etc/cron.deny files. Note: This resource previously shipped in the `cron` cookbook as `cron_manage`, which it can still be used as for backwards compatibility with existing Chef Infra Client releases."
+ description "Use the **cron_access** resource to manage cron's cron.allow and cron.deny files. Note: This resource previously shipped in the `cron` cookbook as `cron_manage`, which it can still be used as for backwards compatibility with existing Chef Infra Client releases."
examples <<~DOC
**Add the mike user to cron.allow**
@@ -58,11 +58,18 @@ class Chef
description: "An optional property to set the user name if it differs from the resource block's name.",
name_property: true
+ CRON_PATHS = {
+ "aix" => "/var/adm/cron",
+ "solaris" => "/etc/cron.d",
+ "default" => "/etc",
+ }.freeze
+
action :allow do
description "Add the user to the cron.allow file."
+ allow_path = ::File.join(value_for_platform_family(CRON_PATHS), "cron.allow")
with_run_context :root do
- edit_resource(:template, "/etc/cron.allow") do |new_resource|
+ edit_resource(:template, allow_path) do |new_resource|
source ::File.expand_path("../support/cron_access.erb", __FILE__)
local true
mode "0600"
@@ -76,9 +83,10 @@ class Chef
action :deny do
description "Add the user to the cron.deny file."
+ deny_path = ::File.join(value_for_platform_family(CRON_PATHS), "cron.deny")
with_run_context :root do
- edit_resource(:template, "/etc/cron.deny") do |new_resource|
+ edit_resource(:template, deny_path) do |new_resource|
source ::File.expand_path("../support/cron_access.erb", __FILE__)
local true
mode "0600"
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index 5a6b7ee960..1fc8922e71 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -27,10 +27,542 @@ class Chef
provides :execute, target_mode: true
- description "Use the **execute** resource to execute a single command. Commands that"\
- " are executed with this resource are (by their nature) not idempotent,"\
- " as they are typically unique to the environment in which they are run."\
- " Use not_if and only_if to guard this resource for idempotence."
+ description <<~DESC
+ Use the **execute** resource to execute a single command. Commands that
+ are executed with this resource are (by their nature) not idempotent,
+ as they are typically unique to the environment in which they are run.
+ Use not_if and only_if to guard this resource for idempotence.
+
+ Note: Use the **script** resource to execute a script using a specific
+ interpreter (Ruby, Python, Perl, csh, or Bash).'
+ DESC
+
+ examples <<~EXAMPLES
+ **Run a command upon notification**:
+
+ ```ruby
+ execute 'slapadd' do
+ command 'slapadd < /tmp/something.ldif'
+ creates '/var/lib/slapd/uid.bdb'
+
+ action :nothing
+ end
+
+ template '/tmp/something.ldif' do
+ source 'something.ldif'
+
+ notifies :run, 'execute[slapadd]', :immediately
+ end
+ ```
+
+ **Run a touch file only once while running a command**:
+
+ ```ruby
+ execute 'upgrade script' do
+ command 'php upgrade-application.php && touch /var/application/.upgraded'
+
+ creates '/var/application/.upgraded'
+ action :run
+ end
+ ```
+
+ **Run a command which requires an environment variable**:
+
+ ```ruby
+ execute 'slapadd' do
+ command 'slapadd < /tmp/something.ldif'
+ creates '/var/lib/slapd/uid.bdb'
+
+ action :run
+ environment ({'HOME' => '/home/myhome'})
+ end
+ ```
+
+ **Delete a repository using yum to scrub the cache**:
+
+ ```ruby
+ # the following code sample thanks to gaffneyc @ https://gist.github.com/918711
+ execute 'clean-yum-cache' do
+ command 'yum clean all'
+ action :nothing
+ end
+
+ file '/etc/yum.repos.d/bad.repo' do
+ action :delete
+ notifies :run, 'execute[clean-yum-cache]', :immediately
+
+ notifies :create, 'ruby_block[reload-internal-yum-cache]', :immediately
+ end
+ ```
+
+ **Install repositories from a file, trigger a command, and force the internal cache to reload**:
+
+ The following example shows how to install new Yum repositories from a file,
+ where the installation of the repository triggers a creation of the Yum cache
+ that forces the internal cache for Chef Infra Client to reload.
+
+ ```ruby
+ execute 'create-yum-cache' do
+ command 'yum -q makecache'
+ action :nothing
+ end
+
+ ruby_block 'reload-internal-yum-cache' do
+ block do
+ Chef::Provider::Package::Yum::YumCache.instance.reload
+ end
+ action :nothing
+ end
+
+ cookbook_file '/etc/yum.repos.d/custom.repo' do
+ source 'custom'
+ mode '0755'
+ notifies :run, 'execute[create-yum-cache]', :immediately
+ notifies :create, 'ruby_block[reload-internal-yum-cache]', :immediately
+ end
+ ```
+
+ **Prevent restart and reconfigure if configuration is broken**:
+
+ Use the `:nothing` action (common to all resources) to prevent the test from
+ starting automatically, and then use the `subscribes` notification to run a
+ configuration test when a change to the template is detected.
+
+ ```ruby
+ execute 'test-nagios-config' do
+ command 'nagios3 --verify-config'
+ action :nothing
+ subscribes :run, 'template[/etc/nagios3/configures-nagios.conf]', :immediately
+ end
+ ```
+
+ **Notify in a specific order**:
+
+ To notify multiple resources, and then have these resources run in a certain
+ order, do something like the following.
+
+ ```ruby
+ execute 'foo' do
+ command '...'
+ notifies :create, 'template[baz]', :immediately
+ notifies :install, 'package[bar]', :immediately
+ notifies :run, 'execute[final]', :immediately
+ end
+
+ template 'baz' do
+ #...
+ notifies :run, 'execute[restart_baz]', :immediately
+ end
+
+ package 'bar'
+ execute 'restart_baz'
+ execute 'final' do
+ command '...'
+ end
+ ```
+
+ where the sequencing will be in the same order as the resources are listed in
+ the recipe: `execute 'foo'`, `template 'baz'`, `execute [restart_baz]`,
+ `package 'bar'`, and `execute 'final'`.
+
+ **Execute a command using a template**:
+
+ The following example shows how to set up IPv4 packet forwarding using the
+ **execute** resource to run a command named `forward_ipv4` that uses a template
+ defined by the **template** resource.
+
+ ```ruby
+ execute 'forward_ipv4' do
+ command 'echo > /proc/.../ipv4/ip_forward'
+ action :nothing
+ end
+
+ template '/etc/file_name.conf' do
+ source 'routing/file_name.conf.erb'
+
+ notifies :run, 'execute[forward_ipv4]', :delayed
+ end
+ ```
+
+ where the `command` property for the **execute** resource contains the command
+ that is to be run and the `source` property for the **template** resource
+ specifies which template to use. The `notifies` property for the **template**
+ specifies that the `execute[forward_ipv4]` (which is defined by the **execute**
+ resource) should be queued up and run at the end of a Chef Infra Client run.
+
+ **Add a rule to an IP table**:
+
+ The following example shows how to add a rule named `test_rule` to an IP table
+ using the **execute** resource to run a command using a template that is defined
+ by the **template** resource:
+
+ ```ruby
+ execute 'test_rule' do
+ command 'command_to_run
+ --option value
+ --option value
+ --source \#{node[:name_of_node][:ipsec][:local][:subnet]}
+ -j test_rule'
+
+ action :nothing
+ end
+
+ template '/etc/file_name.local' do
+ source 'routing/file_name.local.erb'
+ notifies :run, 'execute[test_rule]', :delayed
+ end
+ ```
+
+ where the `command` property for the **execute** resource contains the command
+ that is to be run and the `source` property for the **template** resource
+ specifies which template to use. The `notifies` property for the **template**
+ specifies that the `execute[test_rule]` (which is defined by the **execute**
+ resource) should be queued up and run at the end of a Chef Infra Client run.
+
+ **Stop a service, do stuff, and then restart it**:
+
+ The following example shows how to use the **execute**, **service**, and
+ **mount** resources together to ensure that a node running on Amazon EC2 is
+ running MySQL. This example does the following:
+
+ - Checks to see if the Amazon EC2 node has MySQL
+ - If the node has MySQL, stops MySQL
+ - Installs MySQL
+ - Mounts the node
+ - Restarts MySQL
+
+ ```ruby
+ # the following code sample comes from the ``server_ec2``
+ # recipe in the following cookbook:
+ # https://github.com/chef-cookbooks/mysql
+
+ if (node.attribute?('ec2') && !FileTest.directory?(node['mysql']['ec2_path']))
+ service 'mysql' do
+ action :stop
+ end
+
+ execute 'install-mysql' do
+ command "mv \#{node['mysql']['data_dir']} \#{node['mysql']['ec2_path']}"
+ not_if do
+ FileTest.directory?(node['mysql']['ec2_path'])
+ end
+ end
+
+ [node['mysql']['ec2_path'], node['mysql']['data_dir']].each do |dir|
+ directory dir do
+ owner 'mysql'
+ group 'mysql'
+ end
+ end
+
+ mount node['mysql']['data_dir'] do
+ device node['mysql']['ec2_path']
+ fstype 'none'
+ options 'bind,rw'
+ action [:mount, :enable]
+ end
+
+ service 'mysql' do
+ action :start
+ end
+ end
+ ```
+
+ where
+
+ - the two **service** resources are used to stop, and then restart the MySQL service
+ - the **execute** resource is used to install MySQL
+ - the **mount** resource is used to mount the node and enable MySQL
+
+ **Use the platform_family? method**:
+
+ The following is an example of using the `platform_family?` method in the Recipe
+ DSL to create a variable that can be used with other resources in the same
+ recipe. In this example, `platform_family?` is being used to ensure that a
+ specific binary is used for a specific platform before using the **remote_file**
+ resource to download a file from a remote location, and then using the
+ **execute** resource to install that file by running a command.
+
+ ```ruby
+ if platform_family?('rhel')
+ pip_binary = '/usr/bin/pip'
+ else
+ pip_binary = '/usr/local/bin/pip'
+ end
+
+ remote_file "\#{Chef::Config[:file_cache_path]}/distribute_setup.py" do
+ source 'http://python-distribute.org/distribute_setup.py'
+ mode '0755'
+
+ not_if { File.exist?(pip_binary) }
+ end
+
+ execute 'install-pip' do
+ cwd Chef::Config[:file_cache_path]
+ command <<~EOF
+ # command for installing Python goes here
+ EOF
+ not_if { File.exist?(pip_binary) }
+ end
+ ```
+
+ where a command for installing Python might look something like:
+
+ ```ruby
+ \#{node['python']['binary']} distribute_setup.py \#{::File.dirname(pip_binary)}/easy_install pip
+ ```
+
+ **Control a service using the execute resource**:
+
+ <div class="admonition-warning">
+ <p class="admonition-warning-title">Warning</p>
+ <div class="admonition-warning-text">
+ This is an example of something that should NOT be done. Use the **service**
+ resource to control a service, not the **execute** resource.
+ </div>
+ </div>
+
+ Do something like this:
+
+ ```ruby
+ service 'tomcat' do
+ action :start
+ end
+ ```
+
+ and NOT something like this:
+
+ ```ruby
+ execute 'start-tomcat' do
+ command '/etc/init.d/tomcat6 start'
+ action :run
+ end
+ ```
+
+ There is no reason to use the **execute** resource to control a service because
+ the **service** resource exposes the `start_command` property directly, which
+ gives a recipe full control over the command issued in a much cleaner, more
+ direct manner.
+
+ **Use the search recipe DSL method to find users**:
+
+ The following example shows how to use the `search` method in the Recipe DSL to
+ search for users:
+
+ ```ruby
+ # the following code sample comes from the openvpn cookbook: https://github.com/chef-cookbooks/openvpn
+
+ search("users", "*:*") do |u|
+ execute "generate-openvpn-\#{u['id']}" do
+ command "./pkitool \#{u['id']}"
+ cwd '/etc/openvpn/easy-rsa'
+
+ environment(
+ 'EASY_RSA' => '/etc/openvpn/easy-rsa',
+ 'KEY_CONFIG' => '/etc/openvpn/easy-rsa/openssl.cnf',
+ 'KEY_DIR' => node['openvpn']['key_dir'],
+ 'CA_EXPIRE' => node['openvpn']['key']['ca_expire'].to_s,
+ 'KEY_EXPIRE' => node['openvpn']['key']['expire'].to_s,
+ 'KEY_SIZE' => node['openvpn']['key']['size'].to_s,
+ 'KEY_COUNTRY' => node['openvpn']['key']['country'],
+ 'KEY_PROVINCE' => node['openvpn']['key']['province'],
+ 'KEY_CITY' => node['openvpn']['key']['city'],
+ 'KEY_ORG' => node['openvpn']['key']['org'],
+ 'KEY_EMAIL' => node['openvpn']['key']['email']
+ )
+ not_if { File.exist?("\#{node['openvpn']['key_dir']}/\#{u['id']}.crt") }
+ end
+
+ %w{ conf ovpn }.each do |ext|
+ template "\#{node['openvpn']['key_dir']}/\#{u['id']}.\#{ext}" do
+ source 'client.conf.erb'
+ variables :username => u['id']
+ end
+ end
+
+ execute "create-openvpn-tar-\#{u['id']}" do
+ cwd node['openvpn']['key_dir']
+ command <<~EOH
+ tar zcf \#{u['id']}.tar.gz ca.crt \#{u['id']}.crt \#{u['id']}.key \#{u['id']}.conf \#{u['id']}.ovpn
+ EOH
+ not_if { File.exist?("\#{node['openvpn']['key_dir']}/\#{u['id']}.tar.gz") }
+ end
+ end
+ ```
+
+ where
+
+ - the search will use both of the **execute** resources, unless the condition
+ specified by the `not_if` commands are met
+ - the `environments` property in the first **execute** resource is being used to
+ define values that appear as variables in the OpenVPN configuration
+ - the **template** resource tells Chef Infra Client which template to use
+
+ **Enable remote login for macOS**:
+
+ ```ruby
+ execute 'enable ssh' do
+ command '/usr/sbin/systemsetup -setremotelogin on'
+ not_if '/usr/sbin/systemsetup -getremotelogin | /usr/bin/grep On'
+ action :run
+ end
+ ```
+
+ **Execute code immediately, based on the template resource**:
+
+ By default, notifications are `:delayed`, that is they are queued up as they are
+ triggered, and then executed at the very end of a Chef Infra Client run. To run
+ kan action immediately, use `:immediately`:
+
+ ```ruby
+ template '/etc/nagios3/configures-nagios.conf' do
+ # other parameters
+ notifies :run, 'execute[test-nagios-config]', :immediately
+ end
+ ```
+
+ and then Chef Infra Client would immediately run the following:
+
+ ```ruby
+ execute 'test-nagios-config' do
+ command 'nagios3 --verify-config'
+ action :nothing
+ end
+ ```
+
+ **Sourcing a file**:
+
+ The **execute** resource cannot be used to source a file (e.g. `command 'source
+ filename'`). The following example will fail because `source` is not an
+ executable:
+
+ ```ruby
+ execute 'foo' do
+ command 'source /tmp/foo.sh'
+ end
+ ```
+
+
+ Instead, use the **script** resource or one of the **script**-based resources
+ (**bash**, **csh**, **perl**, **python**, or **ruby**). For example:
+
+ ```ruby
+ bash 'foo' do
+ code 'source /tmp/foo.sh'
+ end
+ ```
+
+ **Run a Knife command**:
+
+ ```ruby
+ execute 'create_user' do
+ command <<~EOM
+ knife user create \#{user}
+ --admin
+ --password password
+ --disable-editing
+ --file /home/vagrant/.chef/user.pem
+ --config /tmp/knife-admin.rb
+ EOM
+ end
+ ```
+
+ **Run install command into virtual environment**:
+
+ The following example shows how to install a lightweight JavaScript framework
+ into Vagrant:
+
+ ```ruby
+ execute "install q and zombiejs" do
+ cwd "/home/vagrant"
+ user "vagrant"
+ environment ({'HOME' => '/home/vagrant', 'USER' => 'vagrant'})
+ command "npm install -g q zombie should mocha coffee-script"
+ action :run
+ end
+ ```
+
+ **Run a command as a named user**:
+
+ The following example shows how to run `bundle install` from a Chef Infra Client
+ run as a specific user. This will put the gem into the path of the user
+ (`vagrant`) instead of the root user (under which the Chef Infra Client runs):
+
+ ```ruby
+ execute '/opt/chefdk/embedded/bin/bundle install' do
+ cwd node['chef_workstation']['bundler_path']
+ user node['chef_workstation']['user']
+
+ environment ({
+ 'HOME' => "/home/\#{node['chef_workstation']['user']}",
+ 'USER' => node['chef_workstation']['user']
+ })
+ not_if 'bundle check'
+ end
+ ```
+
+ **Run a command as an alternate user**:
+
+ *Note*: When Chef is running as a service, this feature requires that the user
+ that Chef runs as has 'SeAssignPrimaryTokenPrivilege' (aka
+ 'SE_ASSIGNPRIMARYTOKEN_NAME') user right. By default only LocalSystem and
+ NetworkService have this right when running as a service. This is necessary
+ even if the user is an Administrator.
+
+ This right can be added and checked in a recipe using this example:
+
+ ```ruby
+ # Add 'SeAssignPrimaryTokenPrivilege' for the user
+ Chef::ReservedNames::Win32::Security.add_account_right('<user>', 'SeAssignPrimaryTokenPrivilege')
+
+ # Check if the user has 'SeAssignPrimaryTokenPrivilege' rights
+ Chef::ReservedNames::Win32::Security.get_account_right('<user>').include?('SeAssignPrimaryTokenPrivilege')
+ ```
+
+ The following example shows how to run `mkdir test_dir` from a Chef Infra Client
+ run as an alternate user.
+
+ ```ruby
+ # Passing only username and password
+ execute 'mkdir test_dir' do
+ cwd Chef::Config[:file_cache_path]
+
+ user "username"
+ password "password"
+ end
+
+ # Passing username and domain
+ execute 'mkdir test_dir' do
+ cwd Chef::Config[:file_cache_path]
+
+ domain "domain-name"
+ user "user"
+ password "password"
+ end
+
+ # Passing username = 'domain-name\\username'. No domain is passed
+ execute 'mkdir test_dir' do
+ cwd Chef::Config[:file_cache_path]
+
+ user "domain-name\\username"
+ password "password"
+ end
+
+ # Passing username = 'username@domain-name'. No domain is passed
+ execute 'mkdir test_dir' do
+ cwd Chef::Config[:file_cache_path]
+
+ user "username@domain-name"
+ password "password"
+ end
+ ```
+
+ **Run a command with an external input file**:
+
+ execute 'md5sum' do
+ input File.read(__FILE__)
+ end
+ EXAMPLES
# The ResourceGuardInterpreter wraps a resource's guards in another resource. That inner resource
# needs to behave differently during (for example) why_run mode, so we flag it here. For why_run mode
@@ -103,6 +635,10 @@ class Chef
description: "Determines whether the script will run with elevated permissions to circumvent User Access Control (UAC) interactively blocking the process.\nThis will cause the process to be run under a batch login instead of an interactive login. The user running #{Chef::Dist::CLIENT} needs the 'Replace a process level token' and 'Adjust Memory Quotas for a process' permissions. The user that is running the command needs the 'Log on as a batch job' permission.\nBecause this requires a login, the user and password properties are required.",
introduced: "13.3"
+ property :input, [String],
+ introduced: "16.2",
+ description: "An optional property to set the input sent to the command as STDIN."
+
alias :env :environment
def self.set_guard_inherited_attributes(*inherited_attributes)
diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb
index 59e917fbc4..eacddd02af 100644
--- a/lib/chef/resource/file.rb
+++ b/lib/chef/resource/file.rb
@@ -76,7 +76,7 @@ class Chef
property :diff, [ String, nil ], desired_state: false, skip_docs: true
property :force_unlink, [ TrueClass, FalseClass ], desired_state: false, default: false,
- description: "How #{Chef::Dist::PRODUCT} handles certain situations when the target file turns out not to be a file. For example, when a target file is actually a symlink. Set to true for #{Chef::Dist::PRODUCT} to delete the non-file target and replace it with the specified file. Set to false for #{Chef::Dist::PRODUCT} to raise an error."
+ description: "How #{Chef::Dist::PRODUCT} handles certain situations when the target file turns out not to be a file. For example, when a target file is actually a symlink. Set to `true` for #{Chef::Dist::PRODUCT} to delete the non-file target and replace it with the specified file. Set to `false` for #{Chef::Dist::PRODUCT} to raise an error."
property :manage_symlink_source, [ TrueClass, FalseClass ], desired_state: false,
description: "Change the behavior of the file resource if it is pointed at a symlink. When this value is set to true, #{Chef::Dist::PRODUCT} will manage the symlink's permissions or will replace the symlink with a normal file if the resource has content. When this value is set to false, #{Chef::Dist::PRODUCT} will follow the symlink and will manage the permissions and content of symlink's target file. The default behavior is true but emits a warning that the default value will be changed to false in a future version; setting this explicitly to true or false suppresses this warning."
diff --git a/lib/chef/resource/homebrew_package.rb b/lib/chef/resource/homebrew_package.rb
index 71a9ffde38..c3b34395f6 100644
--- a/lib/chef/resource/homebrew_package.rb
+++ b/lib/chef/resource/homebrew_package.rb
@@ -29,8 +29,37 @@ class Chef
provides :homebrew_package
provides :package, os: "darwin"
- description "Use the **homebrew_package** resource to manage packages for the macOS platform."
+ description "Use the **homebrew_package** resource to manage packages for the macOS platform. Note: Starting with #{Chef::Dist::PRODUCT} 16 the homebrew resource now accepts an array of packages for isntalling multiple packages at once."
introduced "12.0"
+ examples <<~DOC
+ **Install a package**:
+
+ ```ruby
+ homebrew_package 'git'
+ ```
+
+ **Install multiple packages at once**:
+
+ ```ruby
+ homebrew_package %w(git fish ruby)
+ ```
+
+ **Specify the Homebrew user with a UUID**
+
+ ```ruby
+ homebrew_package 'git' do
+ homebrew_user 1001
+ end
+ ```
+
+ **Specify the Homebrew user with a string**:
+
+ ```ruby
+ homebrew_package 'vim' do
+ homebrew_user 'user1'
+ end
+ ```
+ DOC
property :homebrew_user, [ String, Integer ],
description: "The name or uid of the Homebrew owner to be used by #{Chef::Dist::PRODUCT} when executing a command."
diff --git a/lib/chef/resource/homebrew_update.rb b/lib/chef/resource/homebrew_update.rb
new file mode 100644
index 0000000000..36dcda810d
--- /dev/null
+++ b/lib/chef/resource/homebrew_update.rb
@@ -0,0 +1,106 @@
+#
+# Author:: Joshua Timberman (<jtimberman@chef.io>)
+# Author:: Dan Webb (<dan@webb-agile-solutions.ltd>)
+#
+# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright (c) Webb Agile Solutions Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require_relative "../resource"
+
+class Chef
+ class Resource
+ class HomebrewUpdate < Chef::Resource
+ unified_mode true
+
+ provides(:homebrew_update) { true }
+
+ description "Use the **homebrew_update** resource to manage Homebrew repository updates on MacOS."
+ introduced "16.2"
+ examples <<~DOC
+ **Update the homebrew repository data at a specified interval**:
+ ```ruby
+ homebrew_update 'all platforms' do
+ frequency 86400
+ action :periodic
+ end
+ ```
+ **Update the Homebrew repository at the start of a Chef Infra Client run**:
+ ```ruby
+ homebrew_update 'update'
+ ```
+ DOC
+
+ # allow bare homebrew_update with no name
+ property :name, String, default: ""
+
+ property :frequency, Integer,
+ description: "Determines how frequently (in seconds) Homebrew updates are made. Use this property when the `:periodic` action is specified.",
+ default: 86_400
+
+ default_action :periodic
+ allowed_actions :update, :periodic
+
+ action_class do
+ BREW_STAMP_DIR = "/var/lib/homebrew/periodic".freeze
+ BREW_STAMP = "#{BREW_STAMP_DIR}/update-success-stamp".freeze
+
+ # Determines whether we need to run `homebrew update`
+ #
+ # @return [Boolean]
+ def brew_up_to_date?
+ ::File.exist?("#{BREW_STAMP}") &&
+ ::File.mtime("#{BREW_STAMP}") > Time.now - new_resource.frequency
+ end
+
+ def do_update
+ directory BREW_STAMP_DIR do
+ recursive true
+ end
+
+ file "#{BREW_STAMP}" do
+ content "BREW::Update::Post-Invoke-Success\n"
+ action :create_if_missing
+ end
+
+ execute "brew update" do
+ command %w{brew update}
+ default_env true
+ user Homebrew.owner
+ notifies :touch, "file[#{BREW_STAMP}]", :immediately
+ end
+ end
+ end
+
+ action :periodic do
+ return unless mac_os_x?
+
+ unless brew_up_to_date?
+ converge_by "update new lists of packages" do
+ do_update
+ end
+ end
+ end
+
+ action :update do
+ return unless mac_os_x?
+
+ converge_by "force update new lists of packages" do
+ do_update
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/hostname.rb b/lib/chef/resource/hostname.rb
index 41dc80d1bf..f096b0e881 100644
--- a/lib/chef/resource/hostname.rb
+++ b/lib/chef/resource/hostname.rb
@@ -1,4 +1,7 @@
#
+# Copyright:: Copyright (c) Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -13,6 +16,7 @@
#
require_relative "../resource"
+require_relative "../dist"
class Chef
class Resource
@@ -199,24 +203,7 @@ class Chef
group node["root_group"]
mode "0644"
end
- when ::File.exist?("/etc/nodename")
- # Solaris <= 5.10 systems prior to svccfg taking over this functionality (must come before svccfg handling)
- declare_resource(:file, "/etc/nodename") do
- content "#{new_resource.hostname}\n"
- owner "root"
- group node["root_group"]
- mode "0644"
- end
- # Solaris also has /etc/inet/hosts (copypasta alert)
- unless new_resource.ipaddress.nil?
- newline = "#{new_resource.ipaddress} #{new_resource.hostname}"
- newline << " #{new_resource.aliases.join(" ")}" if new_resource.aliases && !new_resource.aliases.empty?
- newline << " #{new_resource.hostname[/[^\.]*/]}"
- r = append_replacing_matching_lines("/etc/inet/hosts", /^#{new_resource.ipaddress}\s+|\s+#{new_resource.hostname}\s+/, newline)
- r.notifies :reload, "ohai[reload hostname]"
- end
- when ::File.exist?("/usr/sbin/svccfg")
- # Solaris >= 5.11 systems using svccfg (must come after /etc/nodename handling)
+ when ::File.exist?("/usr/sbin/svccfg") # solaris 5.11
declare_resource(:execute, "svccfg -s system/identity:node setprop config/nodename=\'#{new_resource.hostname}\'") do
notifies :run, "execute[svcadm refresh]", :immediately
notifies :run, "execute[svcadm restart]", :immediately
@@ -262,7 +249,7 @@ class Chef
# reboot because $windows
declare_resource(:reboot, "setting hostname") do
- reason "chef setting hostname"
+ reason "#{Chef::Dist::PRODUCT} updated system hostname"
action :nothing
only_if { new_resource.windows_reboot }
end
diff --git a/lib/chef/resource/kernel_module.rb b/lib/chef/resource/kernel_module.rb
index c3b3dba9d5..87a1d79d24 100644
--- a/lib/chef/resource/kernel_module.rb
+++ b/lib/chef/resource/kernel_module.rb
@@ -19,11 +19,14 @@ class Chef
introduced "14.3"
examples <<~DOC
Install and load a kernel module, and ensure it loads on reboot.
+
```ruby
kernel_module 'loop'
```
+
Install and load a kernel with a specific set of options, and ensure it loads on reboot. Consult kernel module
documentation for specific options that are supported.
+
```ruby
kernel_module 'loop' do
options [
@@ -32,31 +35,41 @@ class Chef
]
end
```
+
Load a kernel module.
+
```ruby
kernel_module 'loop' do
action :load
end
```
- Unload a kernel module and remove module config, so it doesn’t load on reboot.
+
+ Unload a kernel module and remove module config, so it doesn't load on reboot.
+
```ruby
kernel_module 'loop' do
action :uninstall
end
```
+
Unload kernel module.
+
```ruby
kernel_module 'loop' do
action :unload
end
```
+
Blacklist a module from loading.
+
```ruby
kernel_module 'loop' do
action :blacklist
end
```
+
Disable a kernel module.
+
```ruby
kernel_module 'loop' do
action :disable
diff --git a/lib/chef/resource/plist.rb b/lib/chef/resource/plist.rb
index 944eea18e9..06811ea8b6 100644
--- a/lib/chef/resource/plist.rb
+++ b/lib/chef/resource/plist.rb
@@ -28,14 +28,33 @@ class Chef
description "Use the **plist** resource to set config values in plist files on macOS systems."
introduced "16.0"
+ examples <<~DOC
+ **Show hidden files in finder**:
+
+ ```ruby
+ plist 'show hidden files' do
+ path '/Users/vagrant/Library/Preferences/com.apple.finder.plist'
+ entry 'AppleShowAllFiles'
+ value true
+ end
+ ```
+ DOC
+
+ property :path, String, name_property: true,
+ description: "The path on disk to the plist file."
- property :path, String, name_property: true
property :entry, String
property :value, [TrueClass, FalseClass, String, Integer, Float, Hash]
property :encoding, String, default: "binary"
- property :owner, String, default: "root"
- property :group, String, default: "wheel"
- property :mode, [String, Integer]
+
+ property :owner, String, default: "root",
+ description: "The owner of the plist file."
+
+ property :group, String, default: "wheel",
+ description: "The group of the plist file."
+
+ property :mode, [String, Integer],
+ description: "The file mode of the plist file. Ex: '644'"
PLISTBUDDY_EXECUTABLE = "/usr/libexec/PlistBuddy".freeze
DEFAULTS_EXECUTABLE = "/usr/bin/defaults".freeze
diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb
index 8056cac922..1641855ebb 100644
--- a/lib/chef/resource/remote_file.rb
+++ b/lib/chef/resource/remote_file.rb
@@ -22,6 +22,7 @@ require_relative "file"
require_relative "../provider/remote_file"
require_relative "../mixin/securable"
require_relative "../mixin/uris"
+require_relative "../dist"
class Chef
class Resource
@@ -31,7 +32,7 @@ class Chef
provides :remote_file
- description "Use the **remote_file** resource to transfer a file from a remote location using file specificity. This resource is similar to the file resource."
+ description "Use the **remote_file** resource to transfer a file from a remote location using file specificity. This resource is similar to the **file** resource. Note: Fetching files from the `files/` directory in a cookbook should be done with the **cookbook_file** resource."
def initialize(name, run_context = nil)
super
@@ -72,7 +73,8 @@ class Chef
end
end
- property :checksum, String
+ property :checksum, String,
+ description: "Optional, see `use_conditional_get`. The SHA-256 checksum of the file. Use to prevent a file from being re-downloaded. When the local file matches the checksum, #{Chef::Dist::PRODUCT} does not download it."
# Disable or enable ETag and Last Modified conditional GET. Equivalent to
# use_etag(true_or_false)
@@ -82,25 +84,39 @@ class Chef
use_last_modified(true_or_false)
end
- property :use_etag, [ TrueClass, FalseClass ], default: true
+ property :use_etag, [ TrueClass, FalseClass ], default: true,
+ description: "Enable ETag headers. Set to false to disable ETag headers. To use this setting, `use_conditional_get` must also be set to true."
alias :use_etags :use_etag
- property :use_last_modified, [ TrueClass, FalseClass ], default: true
+ property :use_last_modified, [ TrueClass, FalseClass ], default: true,
+ description: "Enable `If-Modified-Since` headers. Set to `false` to disable `If-Modified-Since` headers. To use this setting, `use_conditional_get` must also be set to `true`."
- property :ftp_active_mode, [ TrueClass, FalseClass ], default: false
+ property :ftp_active_mode, [ TrueClass, FalseClass ], default: false,
+ description: "Whether #{Chef::Dist::PRODUCT} uses active or passive FTP. Set to `true` to use active FTP."
- property :headers, Hash, default: lazy { {} }
+ property :headers, Hash, default: lazy { {} },
+ description: "A Hash of custom HTTP headers."
property :show_progress, [ TrueClass, FalseClass ], default: false
- property :remote_user, String
+ property :ssl_verify_mode, Symbol, equal_to: %i{verify_none verify_peer},
+ introduced: "16.2",
+ description: "Optional property to override SSL policy. If not specified, uses the SSL polify from `config.rb`."
- property :remote_domain, String
+ property :remote_user, String,
+ introduced: "13.4",
+ description: '**Windows only** The name of a user with access to the remote file specified by the source property. The user name may optionally be specified with a domain, such as: `domain\user` or `user@my.dns.domain.com` via Universal Principal Name (UPN) format. The domain may also be set using the `remote_domain` property. Note that this property is ignored if source is not a UNC path. If this property is specified, the `remote_password` property is required.'
- property :remote_password, String, sensitive: true
+ property :remote_domain, String,
+ introduced: "13.4",
+ description: "**Windows only** The domain of the user specified by the `remote_user` property. By default the resource will authenticate against the domain of the remote system, or as a local account if the remote system is not joined to a domain. If the remote system is not part of a domain, it is necessary to authenticate as a local user on the remote system by setting the domain to `.`, for example: remote_domain '.'. The domain may also be specified as part of the `remote_user` property."
- property :authentication, equal_to: %i{remote local}, default: :remote
+ property :remote_password, String, sensitive: true,
+ introduced: "13.4",
+ description: "**Windows only** The password of the user specified by the `remote_user` property. This property is required if `remote_user` is specified and may only be specified if `remote_user` is specified. The `sensitive` property for this resource will automatically be set to `true` if `remote_password` is specified."
+
+ property :authentication, Symbol, equal_to: %i{remote local}, default: :remote
def after_created
validate_identity_platform(remote_user, remote_password, remote_domain)
diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb
index 1ac99b3d13..0ffa2194d8 100644
--- a/lib/chef/resource/template.rb
+++ b/lib/chef/resource/template.rb
@@ -69,7 +69,7 @@ class Chef
property :local, [ TrueClass, FalseClass ],
default: false, desired_state: false,
- description: "Load a template from a local path. By default, the #{Chef::Dist::CLIENT} loads templates from a cookbook’s /templates directory. When this property is set to true, use the source property to specify the path to a template on the local node."
+ description: "Load a template from a local path. By default, the #{Chef::Dist::CLIENT} loads templates from a cookbook's /templates directory. When this property is set to true, use the source property to specify the path to a template on the local node."
# Declares a helper method to be defined in the template context when
# rendering.
diff --git a/lib/chef/resource/windows_shortcut.rb b/lib/chef/resource/windows_shortcut.rb
index e272e89e16..b5b532cb86 100644
--- a/lib/chef/resource/windows_shortcut.rb
+++ b/lib/chef/resource/windows_shortcut.rb
@@ -34,7 +34,6 @@ class Chef
description 'Make a shortcut to C:\\original_dir'
end
```
-
DOC
property :shortcut_name, String,
diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb
index d73030311e..2dfa22b8ca 100644
--- a/lib/chef/resource/windows_task.rb
+++ b/lib/chef/resource/windows_task.rb
@@ -189,11 +189,11 @@ class Chef
description: "The frequency with which to run the task."
property :start_day, String,
- description: "Specifies the first date on which the task runs in MM/DD/YYYY format.",
+ description: "Specifies the first date on which the task runs in **MM/DD/YYYY** format.",
default_description: "The current date."
property :start_time, String,
- description: "Specifies the start time to run the task, in HH:mm format."
+ description: "Specifies the start time to run the task, in **HH:mm** format."
property :day, [String, Integer],
description: "The day(s) on which the task runs."
diff --git a/lib/chef/resource/windows_user_privilege.rb b/lib/chef/resource/windows_user_privilege.rb
index 862a348e68..aeff7ad468 100644
--- a/lib/chef/resource/windows_user_privilege.rb
+++ b/lib/chef/resource/windows_user_privilege.rb
@@ -68,7 +68,7 @@ class Chef
}
provides :windows_user_privilege
- description "The windows_user_privilege resource allows to add and set principal (User/Group) to the specified privilege. \n Ref: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment"
+ description "The windows_user_privilege resource allows to add and set principal (User/Group) to the specified privilege.\n Ref: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment"
introduced "16.0"
@@ -78,7 +78,7 @@ class Chef
```ruby
windows_user_privilege 'Network Logon Rights' do
privilege 'SeNetworkLogonRight'
- users ['BUILTIN\Administrators', 'NT AUTHORITY\Authenticated Users']
+ users ['BUILTIN\\Administrators', 'NT AUTHORITY\\Authenticated Users']
action :set
end
```
@@ -88,7 +88,7 @@ class Chef
```ruby
windows_user_privilege 'Remote interactive logon' do
privilege 'SeDenyRemoteInteractiveLogonRight'
- users ['Builtin\Guests', 'NT AUTHORITY\Local Account']
+ users ['Builtin\\Guests', 'NT AUTHORITY\\Local Account']
action :add
end
```
@@ -98,7 +98,7 @@ class Chef
```ruby
windows_user_privilege 'Create Pagefile' do
privilege 'SeCreatePagefilePrivilege'
- users ['BUILTIN\Guests', 'BUILTIN\Administrators']
+ users ['BUILTIN\\Guests', 'BUILTIN\\Administrators']
action :set
end
```
@@ -108,7 +108,7 @@ class Chef
```ruby
windows_user_privilege 'Create Pagefile' do
privilege 'SeCreatePagefilePrivilege'
- users ['BUILTIN\Guests']
+ users ['BUILTIN\\Guests']
action :remove
end
```
diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb
index 4e23244dfe..3070075959 100644
--- a/lib/chef/resource/yum_repository.rb
+++ b/lib/chef/resource/yum_repository.rb
@@ -95,7 +95,7 @@ class Chef
description: "URL pointing to the ASCII-armored GPG key file for the repository. This is used if Yum needs a public key to verify a package and the required key hasn't been imported into the RPM database. If this option is set, Yum will automatically import the key from the specified URL. Multiple URLs may be specified in the same manner as the baseurl option. If a GPG key is required to install a package from a repository, all keys specified for that repository will be installed.\nMultiple URLs may be specified in the same manner as the baseurl option. If a GPG key is required to install a package from a repository, all keys specified for that repository will be installed."
property :http_caching, String, equal_to: %w{packages all none},
- description: "Determines how upstream HTTP caches are instructed to handle any HTTP downloads that Yum does. This option can take the following values: all (all HTTP downloads should be cached), packages (only RPM package downloads should be cached, but not repository metadata downloads), or none (no HTTP downloads should be cached)"
+ description: "Determines how upstream HTTP caches are instructed to handle any HTTP downloads that Yum does. This option can take the following values:\n - `all` means all HTTP downloads should be cached\n - `packages` means only RPM package downloads should be cached, but not repository metadata downloads\n - `none` means no HTTP downloads should be cached.\n\nThe default value of `all` is recommended unless you are experiencing caching related issues."
property :include_config, String,
description: "An external configuration file using the format `url://to/some/location`."
@@ -114,25 +114,25 @@ class Chef
description: "Number of times any attempt to retrieve a file should retry before returning an error. Setting this to `0` makes Yum try forever."
property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/],
- description: "Time (in seconds) after which the metadata will expire. If the current metadata downloaded is less than the value specified, then Yum will not update the metadata against the repository. If you find that Yum is not downloading information on updates as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively. The default is six hours to compliment yum-updates running once per hour. It is also possible to use the word `never`, meaning that the metadata will never expire. Note: When using a metalink file, the metalink must always be newer than the metadata for the repository due to the validation, so this timeout also applies to the metalink file.",
- validation_message: "The metadata_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with 'd', 'h', or 'm'!"
+ description: "Time (in seconds) after which the metadata will expire. If the current metadata downloaded is less than the value specified, then Yum will not update the metadata against the repository. If you find that Yum is not downloading information on updates as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a `d`, `h` or `m` respectively. The default is six hours to compliment yum-updates running once per hour. It is also possible to use the word `never`, meaning that the metadata will never expire. Note: When using a metalink file, the metalink must always be newer than the metadata for the repository due to the validation, so this timeout also applies to the metalink file.",
+ validation_message: "The metadata_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with `d`, `h`, or `m`!"
property :metalink, String,
description: "Specifies a URL to a metalink file for the repomd.xml, a list of mirrors for the entire repository are generated by converting the mirrors for the repomd.xml file to a baseurl."
property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/],
- description: "Time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than this many seconds old then Yum will not download another copy of the mirrorlist, it has the same extra format as metadata_expire. If you find that Yum is not downloading the mirrorlists as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively.",
- validation_message: "The mirror_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with 'd', 'h', or 'm'!"
+ description: "Time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than this many seconds old then Yum will not download another copy of the mirrorlist, it has the same extra format as metadata_expire. If you find that Yum is not downloading the mirrorlists as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a `d`, `h` or `m` respectively.",
+ validation_message: "The mirror_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with `d`, `h`, or `m`!"
property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/],
- description: "Specifies the time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than the value specified, then Yum will not download another copy of the mirrorlist. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively.",
- validation_message: "The mirrorlist_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with 'd', 'h', or 'm'!"
+ description: "Specifies the time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than the value specified, then Yum will not download another copy of the mirrorlist. You can also change from the default of using seconds to using days, hours or minutes by appending a `d`, `h` or `m` respectively.",
+ validation_message: "The mirrorlist_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with `d`, `h`, or `m`!"
property :mirrorlist, String,
description: "URL to a file containing a list of baseurls. This can be used instead of or with the baseurl option. Substitution variables, described below, can be used with this option."
property :mode, [String, Integer],
- description: "Permissions mode of .repo file on disk. This is useful for scenarios where secrets are in the repo file. If this value is set to '600', normal users will not be able to use Yum search, Yum info, etc.",
+ description: "Permissions mode of .repo file on disk. This is useful for scenarios where secrets are in the repo file. If this value is set to `600`, normal users will not be able to use Yum search, Yum info, etc.",
default: "0644"
property :options, Hash,
@@ -142,7 +142,7 @@ class Chef
description: "Password to use with the username for basic authentication."
property :priority, String, regex: /^(\d?[1-9]|[0-9][0-9])$/,
- description: "Assigns a priority to a repository where the priority value is between '1' and '99' inclusive. Priorities are used to enforce ordered protection of repositories. Packages from repositories with a lower priority (higher numerical value) will never be used to upgrade packages that were installed from a repository with a higher priority (lower numerical value). The repositories with the lowest numerical priority number have the highest priority.",
+ description: "Assigns a priority to a repository where the priority value is between `1` and `99` inclusive. Priorities are used to enforce ordered protection of repositories. Packages from repositories with a lower priority (higher numerical value) will never be used to upgrade packages that were installed from a repository with a higher priority (lower numerical value). The repositories with the lowest numerical priority number have the highest priority.",
validation_message: "The priority property must be a numeric value from 1-99!"
property :proxy_password, String,