diff --git a/config/_default/menu.toml b/config/_default/menu.toml
index 17b5c9bc43..390716253b 100644
--- a/config/_default/menu.toml
+++ b/config/_default/menu.toml
@@ -490,6 +490,14 @@ identifier = "chef_infra"
parent = "chef_infra/features"
weight = 20
+ [[infra]]
+ title = "Target Mode"
+ identifier = "chef_infra/features/Target Mode"
+ parent = "chef_infra/features"
+ url = "/target_mode/"
+ weight = 80
+
+
[[infra]]
title = "Integrations"
identifier = "chef_infra/integrations"
diff --git a/content/chef_deprecations_client.md b/content/chef_deprecations_client.md
index a643c88c5a..2f26564894 100644
--- a/content/chef_deprecations_client.md
+++ b/content/chef_deprecations_client.md
@@ -270,7 +270,7 @@ of Chef comes out.
CHEF-33 |
-Enabling unified mode in custom resources |
+Enabling Unified Mode in custom resources |
17.0 |
diff --git a/content/custom_resource_glossary.md b/content/custom_resource_glossary.md
index 60ce79bbc8..d3cd349f0e 100644
--- a/content/custom_resource_glossary.md
+++ b/content/custom_resource_glossary.md
@@ -1,5 +1,5 @@
+++
-title = "Custom Resources Glossary"
+title = "Custom resources glossary"
gh_repo = "chef-web-docs"
aliases = ["/custom_resource_glossary.html"]
@@ -13,9 +13,7 @@ product = ["client", "workstation"]
weight = 200
+++
-## Chef Infra Client Custom Resources Glossary
-
-The following __Domain Specific Language (DSL)__ methods are available when writing Custom Resources.
+The following domain-specific language (DSL) methods are available when writing custom resources.
For further information about how to write custom resources please see [about custom resources]({{< relref "custom_resources.md" >}})
@@ -23,9 +21,8 @@ For further information about how to write custom resources please see [about cu
`action_class` makes methods available to all actions within a single custom resource.
-### Example
-
-You have a template that requires `'yes'` or `'no'` written as a `String`, but you would like the user to use `true` or `false` for convenience. To allow both the `:add` and `:remove` actions to have access to this method, place the method in the `action_class` block.
+For example, a template requires `'yes'` or `'no'` written as a string, but you would like the user to use `true` or `false` for convenience.
+To allow both the `:add` and `:remove` actions to have access to this method, place the method in the `action_class` block.
```ruby
property :example, [true, false], default: true
@@ -57,18 +54,39 @@ action_class do
end
```
+## coerce
+
+`coerce` is used to transform user input into a canonical form. The
+value is passed in, and the transformed value returned as output. Lazy
+values will __not__ be passed to this method until after they're
+evaluated.
+
+`coerce` is run in the context of the instance, which gives it access to
+other properties.
+
+Here we transform,`true`/`false` in to `yes`, `no` for a template later on.
+
+```ruby
+property :browseable,
+ [true, false, String],
+ default: true,
+ coerce: proc { |p| p ? 'yes' : 'no' },
+```
+
+If you are modifying the properties type, you will also need to accept that Ruby type as an input.
+
## converge_if_changed
Use the `converge_if_changed` method inside an `action` block in a
custom resource to compare the desired property values against the
current property values (as loaded by the `load_current_value` method).
Use the `converge_if_changed` method to ensure that updates only occur
-when property values on the system are not the desired property values
+when property values on the system aren't the desired property values
and to otherwise prevent a resource from being converged.
To use the `converge_if_changed` method, wrap it around the part of a
recipe or custom resource that should only be converged when the current
-state is not the desired state:
+state isn't the desired state:
```ruby
action :some_action do
@@ -112,9 +130,30 @@ end
```
Chef Infra Client will only update the property values that require
-updates and will not make changes when the property values are already
+updates and won't make changes when the property values are already
in the desired state.
+
+
+## current_value_does_not_exist!
+
+
+
+When using the `load_current_value` block, use `current_value_does_not_exist!` to indicate that the value doesn't exist and that `current_resource` should therefore be `nil`.
+
+```ruby
+load_current_value do |new_resource|
+ port_data = powershell_exec(%Q{Get-WmiObject -Class Win32_TCPIPPrinterPort -Filter "Name='#{new_resource.port_name}'"}).result
+
+ if port_data.empty?
+ current_value_does_not_exist!
+ else
+ ipv4_address port_data["HostAddress"]
+ end
+ endo
+end
+```
+
## default_action
The default action in a custom resource is, by default, the first action
@@ -153,6 +192,80 @@ action :bbbbb do
end
```
+## deprecated
+
+### Deprecating a resource
+
+Deprecate resources that you no longer wish to maintain.
+This allows you make breaking changes to enterprise or community cookbooks with friendly notifications to downstream cookbook consumers directly in the Chef Infra Client run.
+
+Use the `deprecated` method to deprecate a resource in a cookbook. For example:
+
+```ruby
+deprecated 'The foo_bar resource has been deprecated and will be removed in the next major release of this cookbook scheduled for 25/01/2021!'
+
+property :thing, String, name_property: true
+
+action :create do
+ # Chef resource code
+end
+```
+
+### Deprecating a property
+
+Deprecate the `badly_named` property in a resource:
+
+```ruby
+property :badly_named, String, deprecated: 'The badly_named property has been deprecated and will be removed in the next major release of this cookbook scheduled for 12/25/2021!'
+```
+
+## deprecated_property_alias
+
+To rename a property with a deprecation warning for users of the old property name, use `deprecated_property_alias`:
+
+```ruby
+deprecated_property_alias 'badly_named', 'really_well_named', 'The badly_named property was renamed really_well_named in the 2.0 release of this cookbook. Please update your cookbooks to use the new property name.'
+```
+
+## desired_state
+
+Add `desired_state:` to set the desired state property for a resource.
+
+| Allowed values | Default |
+| -------------- | ------- |
+| `true` `false` | `true` |
+
+- When `true`, the state of the property is determined by the state of
+ the system
+- When `false`, the value of the property impacts how the resource
+ executes, but it's not determined by the state of the system.
+
+For example, if you were to write a resource to create volumes on a
+cloud provider you would need define properties such as `volume_name`,
+`volume_size`, and `volume_region`. The state of these properties would
+determine if your resource needed to converge or not. For the resource
+to function you would also need to define properties such as
+`cloud_login` and `cloud_password`. These are necessary properties for
+interacting with the cloud provider, but their state has no impact on
+decision to converge the resource or not, so you would set
+`desired_state` to `false` for these properties.
+
+```ruby
+property :volume_name, String
+property :volume_size, Integer
+property :volume_region, String
+property :cloud_login, String, desired_state: false
+property :cloud_password, String, desired_state: false
+```
+
+## lazy
+
+When setting a node attribute as the default value for a custom resource property, wrap the node attribute in `lazy {}` so that its value is available when the resource executes.
+
+```ruby
+property :thing, String, default: lazy { node['thingy'] }
+```
+
## load_current_value
Use the `load_current_value` method to load the specified property
@@ -189,27 +302,10 @@ load_current_value do
end
```
-This ensures the values for `homepage` and `page_not_found` are not
+This ensures the values for `homepage` and `page_not_found` aren't
changed to the default values when Chef Infra Client configures the
node.
-## `current_value_does_not_exist!`
-
-When using the `load_current_value` block, use `current_value_does_not_exist!` to indicate that the value does not exist and that `current_resource` should therefore be `nil`.
-
-```ruby
-load_current_value do |new_resource|
- port_data = powershell_exec(%Q{Get-WmiObject -Class Win32_TCPIPPrinterPort -Filter "Name='#{new_resource.port_name}'"}).result
-
- if port_data.empty?
- current_value_does_not_exist!
- else
- ipv4_address port_data["HostAddress"]
- end
- endo
-end
-```
-
## new_resource.property
Custom resources are designed to use resources that are built into Chef Infra and external custom resources.
@@ -248,7 +344,7 @@ action :run do
end
```
-The following properties are identical to the properties in the execute resource, which we are embedding in the custom resource.
+The following properties are identical to the properties in the execute resource, which we're embedding in the custom resource.
- `property :cwd`
- `property :environment`
@@ -308,6 +404,47 @@ where:
Correctly use the properties of the __execute__ resource and not the identically-named override properties of the custom resource.
+## partial
+
+To DRY (don't repeat yourself) up code, custom resources can include partials from common files.
+
+For example, if all of your resources need the `version` property, you can add this to a `partial/_common.rb` file and include that Ruby code in your resource using the `use` directive.
+
+In `resources/partial/_common.rb`, define the `version` property:
+
+```ruby
+# resources/partial/_common.rb
+property :version, String,
+ name_property: true,
+ description: 'Java version to install'
+```
+
+And then in your custom resources, include that code with the `use` directive:
+
+```ruby
+# resources/install_type_a.rb
+provides :adoptopenjdk_install
+unified_mode true
+use 'partial/_common'
+
+property :variant,
+ String,
+ description: 'Install flavour', default: 'openj9'
+```
+
+```ruby
+# resources/openjdk_install.rb
+provides :openjdk_install
+unified_mode true
+use 'partial/_common'
+
+property :install_type,
+ String,
+ default: lazy { default_openjdk_install_method(version) },
+ equal_to: %w( package source ),
+ description: 'Installation type'
+```
+
## property
Use the `property` method to define properties for the custom resource.
@@ -334,147 +471,6 @@ property :username, String
property :password, String
```
-## ruby_type
-
-The property ruby_type is a positional parameter.
-
-Use to ensure a property value is of a particular ruby class, such as:
-
-- `true`
-- `false`
-- `nil`
-- `String`
-- `Array`
-- `Hash`
-- `Integer`
-- `Symbol`
-
-Use an array of Ruby classes to allow a value to be of more than one type. For example:
-
-```ruby
-property :aaaa, String
-property :bbbb, Integer
-property :cccc, Hash
-property :dddd, [true, false]
-property :eeee, [String, nil]
-property :ffff, [Class, String, Symbol]
-property :gggg, [Array, Hash]
-```
-
-## sensitive
-
-A property can be marked sensitive by specifying `sensitive: true` on
-the property. This prevents the contents of the property from being
-exported to data collection and sent to an Automate server or shown in the
-logs of the Chef Infra Client run.
-
-## validators
-
-A validation parameter is used to add zero (or more) validation parameters to a property.
-
-
-
-
-
-
-
-
-
-
-
-
-:callbacks
|
-Use to define a collection of unique keys and values (a ruby hash) for which the key is the error message and the value is a lambda to validate the parameter. For example:
-callbacks: {
- 'should be a valid non-system port' => lambda {
- |p| p > 1024 && p < 65535
- }
- }
|
-
-
-:default
|
-Use to specify the default value for a property. For example:
-default: 'a_string_value'
-
-
-
- |
-
-
-:equal_to
|
-Use to match a value with == . Use an array of values to match any of those values with == . For example:
-
-equal_to: ['php', 'perl']
|
-
-
-:regex
|
-Use to match a value to a regular expression. For example:
-regex: [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ]
|
-
-
-:required
|
-Indicates that a property is required. For example:
- |
-
-
-:respond_to
|
-Use to ensure that a value has a given method. This can be a single method name or an array of method names. For example:
-respond_to: valid_encoding?
|
-
-
-
-
-
-Some examples of combining validation parameters:
-
-```ruby
-property :spool_name, String, regex: /$\w+/
-```
-
-```ruby
-property :enabled, equal_to: [true, false, 'true', 'false'], default: true
-```
-
-## desired_state
-
-Add `desired_state:` to set the desired state property for a resource.
-
-| Allowed values | Default |
-| -------------- | ------- |
-| `true` `false` | `true` |
-
-- When `true`, the state of the property is determined by the state of
- the system
-- When `false`, the value of the property impacts how the resource
- executes, but it is not determined by the state of the system.
-
-For example, if you were to write a resource to create volumes on a
-cloud provider you would need define properties such as `volume_name`,
-`volume_size`, and `volume_region`. The state of these properties would
-determine if your resource needed to converge or not. For the resource
-to function you would also need to define properties such as
-`cloud_login` and `cloud_password`. These are necessary properties for
-interacting with the cloud provider, but their state has no impact on
-decision to converge the resource or not, so you would set
-`desired_state` to `false` for these properties.
-
-```ruby
-property :volume_name, String
-property :volume_size, Integer
-property :volume_region, String
-property :cloud_login, String, desired_state: false
-property :cloud_password, String, desired_state: false
-```
-
-## run_context
-
-Chef loads and tracks the current run in the run context object.
-
-root_context
-
## property_is_set?
Use the `property_is_set?` method to check if the value for a property has been passed into the resource.
@@ -490,7 +486,7 @@ The `property_is_set?` method will return `true` if the property is set.
For example, the following custom resource creates and/or updates user
properties, but not their password. The `property_is_set?` method checks
if the user has specified a password and then tells Chef Infra Client
-what to do if the password is not identical:
+what to do if the password isn't identical:
```ruby
action :create do
@@ -510,28 +506,26 @@ end
## provides
-### Introduced
-
-Use the `provides` method to associate multiple custom resource files with the same resources name
+Use the `provides` method to associate multiple custom resource files with the same resources name.
For example:
```ruby
-# Provide my_custom_resource to Redhat 7 and above
-provides :my_custom_resource, platform: 'redhat' do |node|
+# Provide custom_resource_name to Red Hat 7 and above
+provides :custom_resource_name, platform: 'redhat' do |node|
node['platform_version'].to_i >= 7
end
-# Provide my_custom_resource to all Redhat platforms
-provides :my_custom_resource, platform: 'redhat'
+# Provide custom_resource_name to all Red Hat platforms
+provides :custom_resource_name, platform: 'redhat'
-# Provide my_custom_resource to the RedHat platform family
-provides :my_custom_resource, platform_family: 'rhel'
+# Provide custom_resource_name to the Red Hat platform family
+provides :custom_resource_name, platform_family: 'rhel'
-# Provide my_custom_resource to all linux machines
-provides :my_custom_resource, os: 'linux'
+# Provide custom_resource_name to all linux machines
+provides :custom_resource_name, os: 'linux'
-# Provide my_custom_resource, useful if your resource file is not named the same as the resource you want to provide
-provides :my_custom_resource
+# Provide custom_resource_name, useful if your resource file is not named the same as the resource you want to provide
+provides :custom_resource_name
```
This allows you to use multiple custom resources files that provide the
@@ -539,18 +533,18 @@ same resource to the user, but for different operating systems or
operation system versions. With this you can eliminate the need for
platform or platform version logic within your resources.
-### Precedent
+### Precedence
-Use the `provides` method to associate a custom resource with the Recipe
+Use the `provides` method to associate a custom resource with the recipe
DSL on different operating systems. When multiple custom resources use
the same DSL, specificity rules are applied to determine the priority,
from highest to lowest:
-1. provides :my_custom_resource, platform_version: '0.1.2'
-2. provides :my_custom_resource, platform: 'platform_name'
-3. provides :my_custom_resource, platform_family: 'platform_family'
-4. provides :my_custom_resource, os: 'operating_system'
-5. provides :my_custom_resource
+1. `provides :custom_resource_name, platform_version: '0.1.2'`
+2. `provides :custom_resource_name, platform: 'platform_name'`
+3. `provides :custom_resource_name, platform_family: 'platform_family'`
+4. `provides :custom_resource_name, os: 'operating_system'`
+5. `provides :custom_resource_name`
## reset_property
@@ -562,125 +556,163 @@ clear the value for a property named `password`:
reset_property(:password)
```
-## coerce
+## resource_name
-`coerce` is used to transform user input into a canonical form. The
-value is passed in, and the transformed value returned as output. Lazy
-values will __not__ be passed to this method until after they are
-evaluated.
+{{< note >}}
-`coerce` is run in the context of the instance, which gives it access to
-other properties.
+`resource_name` was deprecated in Chef Infra Client 15 and became EOL in 16.2.44.
+Use the [`provides`](#provides) method instead of `resource_name`.
-Here we transform,`true`/`false` in to `yes`, `no` for a template later on.
+For resources running on Chef Infra Client from 12.5 through 15, use `resource_name`:
```ruby
-property :browseable,
- [true, false, String],
- default: true,
- coerce: proc { |p| p ? 'yes' : 'no' },
+resource_name :foo
```
-If you are modifying the properties type, you will also need to accept that Ruby type as an input.
-
-## resource_name
-
-{{< note >}}
+For resources running on Chef Infra Client 15.13.8 to 16.1.16, use both methods to maintain backwards compatibility:
-The `resource_name` setting is necessary for backwards compatibility with Chef Infra Client 12 through 15. It's use is no longer recommended, please use the [`provides`]({{< relref "#provides" >}}) method instead.
+```ruby
+resource_name :foo
+provides :foo
+```
{{< /note >}}
-Introduced: 12.5
-Updated: 16.0
-
-Use the `resource_name` method at the top of a custom resource to
-declare a custom name for that resource. For example:
+Use the `resource_name` method at the top of a custom resource to declare a custom name for that resource. For example:
```ruby
resource_name :my_resource_name
```
-The `resource_name` is only used as a fallback name for display purposes.
-
-The `provides` statement is the preferred method of specifying the resources name.
+## ruby_type
-In Chef Infra Client 16 and later, the first `provides` in a resource declaration also sets the fallback `resource_name`, so we do not recommend that users set the `resource_name` at all.
+The property ruby_type is a positional parameter.
-## Deprecating entire resources
+Use to ensure a property value is of a particular ruby class, such as:
-Deprecate resources that you no longer wish to maintain.
-This allows you make breaking changes to enterprise or community cookbooks with friendly notifications to downstream cookbook consumers directly in the Chef Infra Client run.
+- `true`
+- `false`
+- `nil`
+- `String`
+- `Array`
+- `Hash`
+- `Integer`
+- `Symbol`
-Deprecate the `foo_bar` resource in a cookbook
+Use an array of Ruby classes to allow a value to be of more than one type. For example:
```ruby
-deprecated 'The foo_bar resource has been deprecated and will be removed in the next major release of this cookbook scheduled for 25/01/2021!'
+property :aaaa, String
+property :bbbb, Integer
+property :cccc, Hash
+property :dddd, [true, false]
+property :eeee, [String, nil]
+property :ffff, [Class, String, Symbol]
+property :gggg, [Array, Hash]
+```
-property :thing, String, name_property: true
+## run_context
-action :create do
- # Chef resource code
-end
-```
+Chef loads and tracks the current run in the run context object.
-## Deprecating a property
+root_context
-Deprecate the `badly_named` property in a resource:
+## sensitive
-```ruby
-property :badly_named, String, deprecated: 'The badly_named property has been deprecated and will be removed in the next major release of this cookbook scheduled for 12/25/2021!'
-```
+A property can be marked sensitive by specifying `sensitive: true` on
+the property. This prevents the contents of the property from being
+exported to data collection and sent to an Automate server or shown in the
+logs of the Chef Infra Client run.
-## Deprecate and alias
+## target_mode
-Rename a property with a deprecation warning for users of the old property name:
+{{< readfile file="content/reusable/md/target_mode_summary.md" >}}
-```ruby
-deprecated_property_alias 'badly_named', 'really_well_named', 'The badly_named property was renamed really_well_named in the 2.0 release of this cookbook. Please update your cookbooks to use the new property name.'
-```
+{{< readfile file="/reusable/md/target_mode_custom_resource.md" >}}
-## Lazy
+For more information on Target Mode, see the [Target Mode documentation]({{< relref "/target_mode.md" >}}).
-When setting a node attribute as the default value for a custom resource property, wrap the node attribute in `lazy {}` so that its value is available when the resource executes.
+## unified_mode
+
+{{< readfile file="content/reusable/md/unified_mode_overview.md" >}}
+
+To enable Unified Mode in a resource, declare it at the top of the resource. For example:
```ruby
-property :thing, String, default: lazy { node['thingy'] }
-```
+unified_mode true
-## Partials
+provides :resource_name
-To DRY (Do not Repeat Yourself) up code, custom resources can include partials from common files.
+```
-For example, if all of your resources need the version property you can add this to a `partial/_common.rb` file and include that Ruby code in your resource using the `use` directive.
+For information, see the [Unified Mode documentation]({{< relref "unified_mode" >}}).
-```ruby
-# resources/partial/_common.rb
-property :version, String,
- name_property: true,
- description: 'Java version to install'
+## Validation parameters
-# resources/install_type_a.rb
-provides :adoptopenjdk_install
-unified_mode true
-use 'partial/_common'
+Use a validation parameter to add zero (or more) validation parameters to a property.
-property :variant,
- String,
- description: 'Install flavour', default: 'openj9'
+
+
+
+
+
+
+
+
+
+
+
+:callbacks
|
+Use to define a collection of unique keys and values (a ruby hash) for which the key is the error message and the value is a lambda to validate the parameter. For example:
+callbacks: {
+ 'should be a valid non-system port' => lambda {
+ |p| p > 1024 && p < 65535
+ }
+ }
|
+
+
+:default
|
+Use to specify the default value for a property. For example:
+default: 'a_string_value'
+
+
+
+ |
+
+
+:equal_to
|
+Use to match a value with == . Use an array of values to match any of those values with == . For example:
+
+equal_to: ['php', 'perl']
|
+
+
+:regex
|
+Use to match a value to a regular expression. For example:
+regex: [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ]
|
+
+
+:required
|
+Indicates that a property is required. For example:
+ |
+
+
+:respond_to
|
+Use to ensure that a value has a given method. This can be a single method name or an array of method names. For example:
+respond_to: valid_encoding?
|
+
+
+
+
-# resources/openjdk_install.rb
-provides :openjdk_install
-unified_mode true
-use 'partial/_common'
+Some examples of combining validation parameters:
-property :install_type,
- String,
- default: lazy { default_openjdk_install_method(version) },
- equal_to: %w( package source ),
- description: 'Installation type'
+```ruby
+property :spool_name, String, regex: /$\w+/
```
-## Unified Mode
-
-See the [unified mode documentation]({{< relref "unified_mode" >}}) for information about unified mode.
+```ruby
+property :enabled, equal_to: [true, false, 'true', 'false'], default: true
+```
diff --git a/content/custom_resources.md b/content/custom_resources.md
index 99053f10fa..9d3bbcf470 100644
--- a/content/custom_resources.md
+++ b/content/custom_resources.md
@@ -1,5 +1,5 @@
+++
-title = "Custom Resource Guide"
+title = "Custom resource guide"
gh_repo = "chef-web-docs"
aliases = ["/custom_resources.html"]
@@ -7,86 +7,105 @@ product = ["client", "workstation"]
[menu]
[menu.infra]
- title = "Custom Resource Guide"
- identifier = "chef_infra/resources/custom_resources/custom_resources.md Custom Resources"
+ title = "Custom resource guide"
+ identifier = "chef_infra/resources/custom_resources/custom_resources.md custom resources"
parent = "chef_infra/resources/custom_resources"
weight = 10
+++
-Chef Infra Client ships with over 150 built-in resources for managing system configuration such as `directory`, `remote_file`, and `windows_firewall`. With Custom Resources you can extend the built-in capabilities of Chef Infra Client to create reusable resources for use anywhere in your infrastructure.
+Chef Infra Client ships with over 150 [built-in resources](/resources/) for managing system configuration such as `directory`, `remote_file`, and `windows_firewall`.
+With custom resources you can extend the built-in capabilities of Chef Infra Client to create reusable resources for use anywhere in your infrastructure.
-- Ship directly in cookbooks
-- Leverage Chef Infra Client built-in resources and any additional custom Ruby code (if needed)
-- Behave the same as existing built-in resources in your recipes
+Custom resources:
-## Syntax
+- Ship directly in cookbooks.
+- Leverage Chef Infra Client built-in resources and any additional custom Ruby code (if needed).
+- Behave the same as existing built-in resources in your recipes.
-The layout for a custom resource is:
+## Write a custom resource
-```ruby
-provides :resource_name
+Custom resources are written in Ruby and defined in a cookbook's `/resources` directory.
-property :property_name, RubyType, default: 'value'
+The custom resource code:
-action :action_a do
- # a mix of built-in Chef Infra resources and Ruby
-end
+- Declares the properties of the custom resource.
+- Loads the current state of properties for existing resources.
+- Defines each action that the custom resource may take.
-action :action_b do
- # a mix of built-in Chef Infra resources and Ruby
-end
-```
+Follow these steps to create a new custom resource:
-The first action listed is the default action.
+1. Generate a new custom resource.
-## Write a Custom Resource
+ The `resources` directory doesn't exist by default in a cookbook.
+ Generate the `resources` directory and a resource file from the `chef-repo/cookbooks` directory with the command:
-You'll write the code for a custom resource in a Ruby file and located in a cookbook's `/resources` directory (you need to generate the resource first). This code:
+ ```bash
+ chef generate resource
+ ```
-- Declares the properties of the custom resource
-- Loads current state of properties for existing resources
-- Defines each action the custom resource may take
+ For example, this command generates a `site` custom resource in the `custom_web` cookbook:
-### Generate a Custom Resource
+ ```bash
+ chef generate resource cookbooks/custom_web site
+ ```
-The `resources` directory does not exist by default in a cookbook.
-Generate the `resources` directory and a resource file from the `chef-repo/cookbooks` directory with the command:
+ The `custom_web` cookbook directory with a custom resource has the following structure:
-```bash
-chef generate resource PATH_TO_COOKBOOK RESOURCE_NAME
-```
+ ```text
+ . cookbooks
+ └── custom_web
+ ├── CHANGELOG.md
+ ├── LICENSE
+ ├── Policyfile.rb
+ ├── README.md
+ ├── chefignore
+ ├── kitchen.yml
+ ├── metadata.rb
+ ├── recipes
+ │ └── default.rb
+ ├── resources
+ │ └── site.rb
+ └── test
+ └── integration
+ └── default
+ └── default_test.rb
+ ```
-For example, this command generates a `site` resource in the `custom_web` cookbook:
+1. Define the custom resources.
-```bash
-chef generate resource cookbooks/custom_web site
-```
+ The layout for a custom resource is:
-The `custom_web` cookbook directory with a custom resource has the structure:
-
-```text
-. cookbooks
-└── custom_web
- ├── CHANGELOG.md
- ├── LICENSE
- ├── Policyfile.rb
- ├── README.md
- ├── chefignore
- ├── kitchen.yml
- ├── metadata.rb
- ├── recipes
- │ └── default.rb
- ├── resources
- │ └── site.rb
- └── test
- └── integration
- └── default
- └── default_test.rb
-```
+ ```ruby
+ provides :resource_name
+
+ property :property_name, RubyType, default: 'value'
+
+ action :an_action_name do
+ # a mix of built-in Chef Infra resources and Ruby
+ end
+
+ action :another_action_name do
+ # a mix of built-in Chef Infra resources and Ruby
+ end
+ ```
+
+ The first action listed is the default action.
+
+ For more details on the contents of a custom resource, see the [custom resource glossary]({{< relref "custom_resource_glossary" >}}).
+
+1. Add the custom resource to a recipe.
-### Example Resource
+ Call a resource in a recipe by its resource name. For example:
-This example `site` uses Chef Infra's built-in `file`, `service` and `package` resources, and includes `:create` and `:delete` actions. It also assumes the existence of a [custom httpd template]({{< relref "templates.md" >}}). The code in this custom resource is similar to a typical recipe because it uses built-in Chef Infra Client resources, with the addition of the property and actions definitions for this custom resource.
+ ```ruby
+ resource_name 'foo'
+ ```
+
+## Example custom resource
+
+This example creates a custom resource called `site`, which uses Chef Infra's built-in `file`, `service` and `package` resources, and includes `:create` and `:delete` actions.
+It also assumes the existence of a [custom httpd template]({{< relref "templates.md" >}}).
+The code in this custom resource is similar to a typical recipe because it uses built-in Chef Infra Client resources, with the addition of the property and actions definitions for this custom resource.
```ruby
provides :site
@@ -116,25 +135,48 @@ action :delete do
end
```
-where
+where:
- `site` is the name of the custom resource. The `provides` statement makes the custom resource available for use recipes.
- `homepage` sets the default HTML for the `index.html` file with a default value of `'Hello world!
'`
- the `action` block uses the built-in collection of resources to tell Chef Infra Client how to install Apache, start the service, and then create the contents of the file located at `/var/www/html/index.html`
-- `action :create` is the default resource (because it is listed first); `action :delete` must be called specifically (because it is not the default action)
+- `action :create` is the default resource (because it's listed first); `action :delete` must be called specifically (because it's not the default action)
-Once written, you can use a custom resource may be used in a recipe with the same syntax as Chef Infra Client built-in resources.
+Once written, you can use a custom resource in a recipe with the same syntax as Chef Infra Client built-in resources.
### Syntax
-Call a resource in a recipe by its `resource_name`. For example:
+To add a custom resource to a recipe, call it by its resource name. For example, this adds a the `site` resource:
```ruby
site 'foo'
```
-## Learn More
+## Target Mode
+
+{{< readfile file="content/reusable/md/target_mode_summary.md" >}} For more information on Target Mode, see the [Target Mode documentation]({{< relref "/target_mode.md" >}}).
+
+{{< readfile file="/reusable/md/target_mode_custom_resource.md" >}}
+
+### Example
+
+{{< readfile file="/reusable/md/target_mode_custom_resource_example.md" >}}
+
+## Unified Mode
+
+{{< readfile file="content/reusable/md/unified_mode_overview.md" >}}
+
+For more information on Unified Mode, see the [Unified Mode documentation]({{< relref "/unified_mode.md" >}}).
+
+### Enable Unified Mode
+
+{{< readfile file="content/reusable/md/unified_mode_enable.md" >}}
+
+## Learn more
-Learn Chef interactive tutorial: [Extending Chef Infra: Custom Resources](https://learn.chef.io/courses/course-v1:chef+Infra201+Perpetual/about)
+See these resources to learn more about custom resources:
-See the [Custom Resources Glossary]({{< relref "custom_resource_glossary" >}}) for a description of available methods.
+- See the LearnChef interactive tutorial: [Extending Chef Infra: Custom Resources](https://www.chef.io/training/tutorials).
+- For a description of available methods, see the [custom resources glossary]({{< relref "custom_resource_glossary" >}}).
+- For running resources in Target Mode, see the [Target Mode documentation]({{< relref "target_mode" >}}).
+- For running resources in Unified Mode, see the [Unified Mode documentation]({{< relref "unified_mode" >}}).
diff --git a/content/resource_common.md b/content/resource_common.md
index a546dd02db..cce421e10f 100644
--- a/content/resource_common.md
+++ b/content/resource_common.md
@@ -11,7 +11,7 @@ aliases = ["/resource_common.html"]
title = "Common Resource Functionality"
identifier = "chef_infra/resources/resource_common.md Common Resource Functionality"
parent = "chef_infra/resources"
- weight = 30
+ weight = 40
+++
diff --git a/content/reusable/md/target_mode_custom_resource.md b/content/reusable/md/target_mode_custom_resource.md
new file mode 100644
index 0000000000..5100016b10
--- /dev/null
+++ b/content/reusable/md/target_mode_custom_resource.md
@@ -0,0 +1,6 @@
+To enable a custom resource to run in Target Mode, add `target_mode: true` to the resource definition. For example:
+
+```ruby
+provides :resource_name, target_mode: true
+...
+```
diff --git a/content/reusable/md/target_mode_custom_resource_example.md b/content/reusable/md/target_mode_custom_resource_example.md
new file mode 100644
index 0000000000..12cc5ec32a
--- /dev/null
+++ b/content/reusable/md/target_mode_custom_resource_example.md
@@ -0,0 +1,31 @@
+
+The following custom resource example checks for and creates a new directory and runs in Target Mode:
+
+```ruby
+provides :example_directory, target_mode: true
+unified_mode true
+
+property: directory, String
+
+load_current_value do |new_resource|
+ dir = new_resource.directory
+ parsed = dir.match(%r{([^/]+$)})
+ path = ''
+ if parsed
+ path = dir[0..(dir.length - parsed[1].length - 1)]
+ dir = parsed[1]
+ end
+
+ tmp = __transport_connection.run_command( sprintf('ls -l %s | grep %s || echo -n', path, dir) )
+
+ if tmp.match(Regexp.new(dir))
+ directory new_resource.directory
+ end
+end
+
+action :create do
+ converge_if_changed do
+ __transport_connection.run_command( sprintf('mkdir %s', new_resource.directory) )
+ end
+end
+```
diff --git a/content/reusable/md/target_mode_summary.md b/content/reusable/md/target_mode_summary.md
new file mode 100644
index 0000000000..2561d9409f
--- /dev/null
+++ b/content/reusable/md/target_mode_summary.md
@@ -0,0 +1 @@
+Target Mode executes Chef Infra Client runs on nodes that don't have Chef Infra Client installed on them.
diff --git a/content/reusable/md/unified_mode_actions_later_resources.md b/content/reusable/md/unified_mode_actions_later_resources.md
index ba1f2ceee2..80ea220ccc 100644
--- a/content/reusable/md/unified_mode_actions_later_resources.md
+++ b/content/reusable/md/unified_mode_actions_later_resources.md
@@ -1,16 +1,16 @@
## Actions on Later Resources
-Since unified mode executes your resource as it is compiled, `:immediate` notifications that execute later resources are handled differently than in the past.
+Since Unified Mode executes your resource as it's compiled, `:immediate` notifications that execute later resources are handled differently than in the past.
### `:immediate` Notifications to Later Resources
Unified mode delays immediate notifications to later resources.
In unified mode, the Chef Infra Client saves immediate notifications and executes them when the later resource is parsed. Immediate notifications to prior resources and delayed notifications behave the same as they did before unified mode.
-The end result of sequentially chaining immediate notifications is the same as before unified mode. Instead of immediately notifying results, the notifications fire _in order_ as they are parsed, which has the same outcome. If the parse order and the intended execution order are different, then the results may be different and are a reflection of the parse order.
+The result of sequentially chaining immediate notifications is the same as before unified mode. Instead of immediately notifying results, the notifications fire _in order_ as they're parsed, which has the same outcome. If the parse order and the intended execution order are different, then the results may be different and are a reflection of the parse order.
-The changes to sending immediate notification could result in subtle changes to behaviors in some resources, but it is not a breaking change to common patterns of writing resources.
+The changes to sending immediate notification could result in subtle changes to behaviors in some resources, but it's not a breaking change to common patterns of writing resources.
Chaining immediate notifications to later resources:
@@ -65,6 +65,6 @@ end
### Out of Order Execution
-Unified mode breaks custom resources that rely on the out-of-order execution of compile-time statements. Move any affected compile-time statements to the location in the code where they are intended to execute.
+Unified mode breaks custom resources that rely on the out-of-order execution of compile-time statements. Move any affected compile-time statements to the location in the code where they're intended to execute.
-Out-of-order execution is rare. Internally at Chef, none of our custom resources broke during our migration to unified mode. Instead, we discovered a few cases in which custom resource code was intended to run in order, but Chef Infra Client executed it out of order. In these cases, unified mode fixed errors instead of introducing bugs.
+Out-of-order execution is rare. Internally at Chef, none of our custom resources broke during our migration to unified mode. Instead, we discovered a few cases in which custom resource code was intended to run in order, but Chef Infra Client executed it out of order. In these cases, Unified Mode fixed errors instead of introducing bugs.
diff --git a/content/reusable/md/unified_mode_client_releases.md b/content/reusable/md/unified_mode_client_releases.md
index 6ff2c01fca..3e1e79e8df 100644
--- a/content/reusable/md/unified_mode_client_releases.md
+++ b/content/reusable/md/unified_mode_client_releases.md
@@ -1,7 +1,6 @@
+Unified Mode (`unified_mode true`) is the default behavior starting in Chef Infra Client 18 (April 2022).
-In Chef Infra Client 17 (April 2021) and some earlier versions, unified mode is not enabled by default. Enable unified mode on a custom resource with `unified_mode true`. Chef Infra Client displays a deprecation message with `unified_mode false`.
-
-In Chef Infra Client 18 (April 2022), `unified_mode true` will become the default behavior.
+See the following table for Chef Infra Client versions where Unified Mode can be enabled in custom resources:
| Chef Infra Client | Unified Mode |
|-------------------|-------------------------------|
diff --git a/content/reusable/md/unified_mode_enable.md b/content/reusable/md/unified_mode_enable.md
index 80748f544e..1f7d06fac0 100644
--- a/content/reusable/md/unified_mode_enable.md
+++ b/content/reusable/md/unified_mode_enable.md
@@ -1,7 +1,6 @@
+Unified Mode is enabled by default starting in Chef Infra Client 18.
-## Enable Unified Mode
-
-Enable unified mode by adding the `unified_mode true` in a custom resource. You can upgrade most custom resources to use unified mode without additional work other than testing and validation.
+In Chef Infra Client 17 (April 2021) and some earlier versions, you can enable Unified Mode in custom resources by adding `unified_mode true`. You can upgrade most custom resources to use Unified Mode without additional work other than testing and validation. See the following example:
```ruby
# enable unified mode
diff --git a/content/reusable/md/unified_mode_troubleshooting.md b/content/reusable/md/unified_mode_troubleshooting.md
index b66f66239c..f1c030a785 100644
--- a/content/reusable/md/unified_mode_troubleshooting.md
+++ b/content/reusable/md/unified_mode_troubleshooting.md
@@ -12,11 +12,11 @@ When designing a custom resource for unified mode:
- Declare a resource first and then declare actions on it
- Write resources in run-time order
-### Resources with Changes to Internal Sub-resources
+### Resources with changes to internal sub-resources
-Some custom resources are designed to create and edit other sub-resources as part of the resource declaration. In unified mode, Chef Infra Client parses a resource code block that creates or edits a sub-resource and immediately tries to apply that change, even though the sub-resource does not yet exist. This results in the execution of an incomplete resource.
+Some custom resources are designed to create and edit other sub-resources as part of the resource declaration. In unified mode, Chef Infra Client parses a resource code block that creates or edits a sub-resource and immediately tries to apply that change, even though the sub-resource doesn't yet exist. This results in the execution of an incomplete resource.
-For example, with unified mode enabled, this code from the dhcp cookbook is designed to create and edit a shared `dhcp_subnet` resource, but it will not work as expected:
+For example, with Unified Mode enabled, this code from the dhcp cookbook is designed to create and edit a shared `dhcp_subnet` resource, but it won't work as expected:
```ruby
# 'edit_resource' results in an incomplete subresource
@@ -40,9 +40,9 @@ To correct custom resources that change sub-resources during their declaration,
- Apply properties in the code block (preferred)
- Run the resource explicitly (not preferred)
-#### Apply Properties in the Code Block
+#### Apply properties in the code block
-This pattern declares the sub-resource in one code block and then changes it in the next code block. This is the preferred pattern in unified mode because all resources execute in order at compile time.
+This pattern declares the sub-resource in one code block and then changes it in the next code block. This is the preferred pattern in Unified Mode because all resources execute in order at compile time.
```ruby
dhcp_subnet "#{new_resource.name}_sharedsubnet_#{subnet}" do
@@ -60,11 +60,11 @@ dhcp_subnet "#{new_resource.name}_sharedsubnet_#{subnet}" do
end
```
-#### Run the Resource Explicitly
+#### Run the resource explicitly
Another solution is to continue saving the resource as a variable, declare `action :nothing` within the codeblock, and then explicitly run the action in another code block.
-The pattern of saving a resource as a variable and then forcing it to run at compile time with an explicit `run_action` works as it has in the past, but it is not a preferred pattern. Unified mode forces resource execution to compile time by default, which makes this pattern redundant.
+The pattern of saving a resource as a variable and then forcing it to run at compile time with an explicit `run_action` works as it has in the past, but it's not a preferred pattern. Unified mode forces resource execution to compile time by default, which makes this pattern redundant.
```ruby
sr = edit_resource(:dhcp_subnet, "#{new_resource.name}_sharedsubnet_#{subnet}") do
diff --git a/content/target_mode.md b/content/target_mode.md
index 87c374767a..be9cab1b15 100644
--- a/content/target_mode.md
+++ b/content/target_mode.md
@@ -3,15 +3,16 @@ title = "Target Mode"
draft = false
gh_repo = "chef-web-docs"
+product = ["client"]
+
[menu]
[menu.infra]
- title = "Target Mode"
- identifier = "chef_infra/features/Target Mode"
- parent = "chef_infra/features"
- weight = 80
+ identifier = "chef_infra/resources/Target Mode"
+ parent = "chef_infra/resources"
+ weight = 30
+++
-Target Mode executes Chef Infra Client runs on nodes that don't have Chef Infra Client installed on them.
+{{< readfile file="content/reusable/md/target_mode_summary.md" >}}
The target node can be any remote system, edge device, or cloud resource that the host can reach. This includes edge devices, Wi-Fi routers, switches, relays, cloud resources, IP phones, router hubs, and network management peripherals.
@@ -32,16 +33,17 @@ Target Mode has the following requirements:
## Credentials file
-The credentials file defines the connection settings for each node in TOML format.
+The credentials file defines the SSH connection settings for each node in TOML format.
-The credentials file is located in `~/.chef/credentials` on Linux and Mac systems, or `c:\Users\\.chef\credentials` on Windows.
+Create a credentials file on the computer running Chef Workstation in the following location:
-### Examples
+- on Linux and macOS: `~/.chef/credentials`
+- on Windows: `c:\Users\\.chef\credentials`
-Define the list of nodes in the credentials file using the TOML format.
-The connection settings for each node are defined using a [TOML Inline Table](https://toml.io/en/v1.0.0#inline-table).
+### Define node connections
-For example, this adds credentials for three nodes using SSH:
+Define connection settings for each node with an [inline table](https://toml.io/en/v1.0.0#inline-table).
+For example, this adds credentials for three nodes:
```toml
['HOST-1']
@@ -86,38 +88,6 @@ host = ''
# key_files = ''
# password = ''
-# ssh_config_file: Whether to use settings from a local SSH config file. Default is 'true'.
-# ssh_config_file = true
-
-# ==== Keepalive settings ====
-# keepalive: Whether to keep the session alive. Default is true.
-# keepalive_interval: The keepalive interval. Default is 60 seconds.
-# ====
-
-# keepalive = true
-# keepalive_interval = '60'
-
-# ==== Connection attempt/delay settings ====
-# connection_timeout: The timeout (in seconds) used when connecting to the SSH target. Default is 15 seconds.
-# connection_retries: The number of connection retries. Default is 5.
-# connection_retry_sleep: The connection retry delay in seconds. Default is 1.
-# max_wait_until_ready: The maximum wait time for the SSH service to connect. Default is 600.
-# ====
-
-# connection_timeout = '15'
-# connection_retries = '5'
-# connection_retry_sleep = '1'
-# max_wait_until_ready = '600'
-
-# compression: Whether to use compression. Default is false.
-# compression = false
-
-# pty: Wether to use PTY to connect. Default is false.
-# pty = false
-
-# proxy_command: A proxy command to use to connect to the server. Default is 'nil'.
-# proxy_command = 'nil'
-
# ==== Bastion host settings ====
# bastion_host: A bastion host to connect to the target through. Default is 'nil'.
# bastion_user: The bastion host user. Default is 'root'.
@@ -128,9 +98,6 @@ host = ''
# bastion_user = 'root'
# bastion_port = '22'
-# non_interactive: Whether to use a non-interactive session. Default is false.
-# non_interactive = false
-
# verify_host_key: Whether to verify the host key. Default is false
# verify_host_key = false
@@ -141,11 +108,13 @@ host = ''
transport_protocol = 'ssh'
```
-### SSH properties
+### Node connection parameters
-Target Mode supports the following SSH connection properties in a credentials file:
+Target Mode supports the following SSH connection parameters in a credentials file.
+
+Common parameters:
`host`
: (Required) The IP address or FQDN of a node.
@@ -169,91 +138,32 @@ Target Mode supports the following SSH connection properties in a credentials fi
`transport_protocol`
: (Required) The protocol to use to connect to a node. Define this once for all nodes in the credentials file. Set to `ssh`.
-`ssh_config_file`
-: Whether to use an SSH config file. For example:
-
- - `~/.ssh/config`
- - `/etc/ssh_config`
- - `/etc/ssh/ssh_config`
-
- Settings defined in the credentials file override settings in the SSH config file.
-
- Default value: `true`
-
-`keepalive`
-: Whether to keep the session alive.
-
- Default value: `true`
-
-`keepalive_interval`
-: The keepalive interval.
-
- Default value: `60`
-
-`connection_timeout`
-: The timeout (in seconds) used when connecting to the SSH target.
-
- Default value: `15`
-
-`connection_retries`
-: The number of connection retries.
-
- Default value: `5`
-
-`connection_retry_sleep`
-: The connection retry delay in seconds.
-
- Default value: `1`
-
-`max_wait_until_ready`
-: The maximum wait time for the SSH service to connect.
-
- Default value: `600`
-
-`compression`
-: Whether to use compression.
-
- Default value: `false`
-
-`pty`
-: Wether to use PTY to connect.
-
- Default value: `false`
-
-`proxy_command`
-: A proxy command to use to connect to the server.
-
- Default value: `nil`
+Additional parameters:
`bastion_host`
: A bastion host to connect to the target through.
Default value: `nil`
-`bastion_user`
-: A bastion host user.
-
- Default value: `"root"`
-
`bastion_port`
: A bastion host port.
Default value: `22`
-`non_interactive`
-: Whether to use a non-interactive session.
+`bastion_user`
+: A bastion host user.
- Default value: `false`
+ Default value: `"root"`
-`verify_host_key`
-: Whether to verify the host key.
+`forward_agent`
+: Whether the connection to the authentication agent (if any) is forwarded to the remote machine.
Default value: `false`
-`forward_agent`
-: Whether the connection to the authentication agent (if any) will be forwarded to the remote machine.
+`verify_host_key`
+: Whether to verify the host key.
- Default value: `false`
+ Allowed values: `true`, `false`. Default value: `false`
@@ -273,47 +183,13 @@ The following Chef Infra Client resources are supported in Target Mode starting
### Custom resources
-To enable a custom resource to run in Target Mode, add `target_mode: true` to the resource definition. For example:
-
-```ruby
-provides :, target_mode: true
-...
-```
+{{< readfile file="/reusable/md/target_mode_custom_resource.md" >}}
See the [Custom Resources documentation]({{< relref "custom_resources" >}}) for more detailed documentation about creating custom resources.
#### Example
-The following custom resource example checks for and creates a new directory and runs in Target Mode:
-
-```ruby
-provides :example_directory, target_mode: true
-unified_mode true
-
-property: directory, String
-
-load_current_value do |new_resource|
- dir = new_resource.directory
- parsed = dir.match(%r{([^/]+$)})
- path = ''
- if parsed
- path = dir[0..(dir.length - parsed[1].length - 1)]
- dir = parsed[1]
- end
-
- tmp = __transport_connection.run_command( sprintf('ls -l %s | grep %s || echo -n', path, dir) )
-
- if tmp.match(Regexp.new(dir))
- directory new_resource.directory
- end
-end
-
-action :create do
- converge_if_changed do
- __transport_connection.run_command( sprintf('mkdir %s', new_resource.directory) )
- end
-end
-```
+{{< readfile file="/reusable/md/target_mode_custom_resource_example.md" >}}
## Run Target Mode
@@ -323,7 +199,8 @@ Run the `chef-client` executable using `-t` or `--target` to target a specific n
chef-client -t
```
-Replace `` with the name of the host as defined in the credentials file. For example, `HOST-1` in the [credential file example](#examples).
+Replace `` with the name of the host as defined in the credentials file.
+For example, `HOST-1` in the [credential file example](#define-node-connections).
To execute a specific Cookbook in Target Mode, run:
@@ -347,7 +224,8 @@ Use `-z` and `-t` to run Target Mode in Local Mode:
chef-client -z -t
```
-Replace `` with the name of the host as defined in the credentials file. For example, `HOST-1` in the [credential file example](#examples).
+Replace `` with the name of the host as defined in the credentials file.
+For example, `HOST-1` in the [credential file example](#define-node-connections).
## Run Target Mode with Chef Automate or Chef Infra Server
diff --git a/content/unified_mode.md b/content/unified_mode.md
index 7d90a3a5f5..a5b15cf648 100644
--- a/content/unified_mode.md
+++ b/content/unified_mode.md
@@ -7,6 +7,7 @@ product = ["client"]
[menu]
[menu.infra]
+ title = "Unified Mode"
identifier = "chef_infra/resources/unified_mode.md Use Unified Mode"
parent = "chef_infra/resources"
weight = 20
@@ -14,29 +15,37 @@ product = ["client"]
{{< readfile file="content/reusable/md/unified_mode_overview.md" >}}
+## Availability
+
{{< readfile file="content/reusable/md/unified_mode_client_releases.md" >}}
+## Enable Unified Mode
+
{{< readfile file="content/reusable/md/unified_mode_enable.md" >}}
-## Unified Mode Isolation
+## Unified Mode isolation
-If a unified mode resource calls a non-unified mode resource, the called resource is not executed in unified mode. Each resource maintains its own state whether it is in unified mode or not. You do not need to modify a custom resource that calls a unified mode resource since the calling context will not affect the resource's execution. Resources using unified mode may call resources not using unified mode and vice versa.
+If a Unified Mode resource calls a non-Unified Mode resource, the called resource isn't executed in Unified Mode.
+Each resource maintains its own state whether it's in Unified Mode or not.
+You don't need to modify a custom resource that calls a Unified Mode resource since the calling context won't affect the resource's execution.
+Resources using Unified Mode may call resources not using Unified Mode and vice versa.
## Benefits of Unified Mode
-### Single Pass Execution
+### Single-pass execution
-In unified mode, the Chef Infra Language executes from top to bottom, eliminating the compile and converge phases.
+In Unified Mode, the Chef Infra Language executes from top to bottom, eliminating the compile and converge phases.
-With the deferred execution of resources to converge time, the user has to understand many different details of the Ruby parser to understand what constructs relate to Chef Infra resources and what constructs are parts of the core Ruby language to determine when those expression are executed. All that complexity is removed in unified mode.
+With the deferred execution of resources to converge time, the user has to understand many different details of the Ruby parser to understand what constructs relate to Chef Infra resources and what constructs are parts of the core Ruby language to determine when those expression are executed. All that complexity is removed in Unified Mode.
-### Elimination of Lazy Blocks
+### Elimination of lazy blocks
-Several aspects of the Chef Infra Language still work but are no longer necessary in unified mode. Unified mode eliminates the need for lazy blocks and the need to lazy Ruby code through a Ruby block.
+Several aspects of the Chef Infra Language still work but are no longer necessary in Unified Mode.
+Unified Mode eliminates the need for lazy blocks and the need to lazy Ruby code through a Ruby block.
-### Rescue Blocks And Other Ruby Constructs Work Correctly
+### Rescue blocks and other Ruby constructs work correctly
-In unified mode, it is now easy to write a rescue wrapper around a Chef Infra resource:
+In Unified Mode, it's now easy to write a rescue wrapper around a Chef Infra resource:
```ruby
begin
@@ -50,11 +59,11 @@ end
## Examples
-### Basic Example
+### Basic example
A simple motivating example is to have a resource that downloads a JSON message using the [remote_file]({{< relref "/resources/remote_file" >}}) resource, parse the JSON using the [ruby_block]({{< relref "/resources/ruby_block" >}}), and then render a value into a [file]({{< relref "/resources/file" >}}) or [template]({{< relref "/resources/template" >}}) resource.
-Without unified mode, correctly writing this simple resource is complicated:
+Without Unified Mode, correctly writing this simple resource is complicated:
```ruby
provides :downloader
@@ -78,9 +87,9 @@ action :doit do
end
```
-Since the remote_file and file resources execute at converge time, the Ruby code to parse the JSON needs to be wrapped in a ruby_block resource, the local variable then needs to be declared outside of that scope (requiring a deep knowledge of Ruby variable scoping rules), and then the content rendered into the file resource must be wrapped with `lazy` since the Ruby parses all arguments of properties at compile time instead of converge time.
+Since the remote_file and file resources execute at converge time, the Ruby code to parse the JSON needs to be wrapped in a `ruby_block` resource, the local variable then needs to be declared outside of that scope (requiring a deep knowledge of Ruby variable scoping rules), and then the content rendered into the file resource must be wrapped with `lazy` since the Ruby parses all arguments of properties at compile time instead of converge time.
-Unified mode simplifies this resource:
+Unified Mode simplifies this resource:
```ruby
unified_mode true
@@ -100,9 +109,9 @@ action :doit do
end
```
-Unified mode eliminates the need for the ruby_block resource, the `lazy` evaluation, and the variable declaration, simplifying how the cookbook is authored.
+Unified Mode eliminates the need for the `ruby_block` resource, the `lazy` evaluation, and the variable declaration, simplifying how the cookbook is authored.
-### Recovery and Exception Handling
+### Recovery and exception handling
Another advantage is in error recovery and the use of rescue.
@@ -116,7 +125,7 @@ action :install do
# the downloading of this file acts as a guard for all the later
# resources -- but if the download is successful while the later
- # resources fail for some transient issue, will will not redownload on
+ # resources fail for some transient issue, will won't redownload on
# the next run -- we lose our edge trigger.
#
remote_file "/tmp/redis-#{version}.tar.gz" do
@@ -146,13 +155,13 @@ action :install do
end
```
-This simplified example shows how to trap exceptions from resources using normal Ruby syntax and to clean up the resource. Without unified mode, this syntax is impossible. Normally when the [execute]({{< relref "resources/execute" >}}) resources are parsed, they only create the objects in the `resource_collection` to later be evaluated so that no exception is thrown while Ruby is parsing the `action` block. Every action is delayed to the later converge phase. In unified mode, the resource runs when Ruby is done parsing its block, so exceptions happen in-line with Ruby parsing and the rescue clause now works as expected.
+This simplified example shows how to trap exceptions from resources using normal Ruby syntax and to clean up the resource. Without Unified Mode, this syntax is impossible. Normally when the [execute]({{< relref "resources/execute" >}}) resources are parsed, they only create the objects in the `resource_collection` to later be evaluated so that no exception is thrown while Ruby is parsing the `action` block. Every action is delayed to the later converge phase. In Unified Mode, the resource runs when Ruby is done parsing its block, so exceptions happen in-line with Ruby parsing and the rescue clause now works as expected.
-This is useful because the TAR extraction throws an exception (for example, the node could be out of disk space), which deletes the TAR file. The next time Chef Infra Client runs, the TAR file will be redownload. If the resource did not have file cleanup after an exception, the TAR file would remain on the client node even though the resource is not complete and the extraction did not happen, leaving the resource in a broken, indeterminate state.
+This is useful because the TAR extraction throws an exception (for example, the node could be out of disk space), which deletes the TAR file. The next time Chef Infra Client runs, the TAR file will be redownload. If the resource didn't have file cleanup after an exception, the TAR file would remain on the client node even though the resource isn't complete and the extraction didn't happen, leaving the resource in a broken, indeterminate state.
{{< readfile file="content/reusable/md/unified_mode_actions_later_resources.md" >}}
-### Notifications and Accumulators
+### Notifications and accumulators
The accumulator pattern works unchanged. Notifications to the `:root` run context still behave identically. Since the compile and converge phases of custom resources both fire in the converge time (typically) of the enclosing `run_context`, the effect of eliminating the separate compile and converge phases of the custom resource has no visible effect from the outer context.