Inputs are the "knobs" you can use to customize the behavior of Chef InSpec profiles. If a profile supports Inputs, you can set the inputs in a variety of ways, allowing flexibility. Profiles that include other profiles can set inputs in the included profile, enabling a multi-layered approach to configuring profiles.
The best way for a profile to indicate it supports inputs is to list them in the metadata file, `inspec.yml`. Any profile that has an `inputs` (or the deprecated `attributes`) section in its `inspec.yml` metadata file is [configuring](#configuring-inputs-in-profile-metadata) inputs.
That said, any profile that uses the DSL keyword `input()` (or the deprecated `attribute()`) in the control source code supports inputs. These profiles are *reading* (and possibly setting) Input values and using them to make decisions.
Whenever an input provider sets a value on an input, a *priority value* is assigned to the operation. Over the life of the input, multiple assignments, with varying priority values, may occur. When the input is evaluated, the current value is determined by finding the setting event with the highest priority.
Note that this approach does not rely on execution order, nor does it rely on multiple named precedence levels. Each setting operation is preserved; this allows
Some input providers allow you to set a priority when you set the value. For example, to set a priority of 50 in a metadata file, use:
```yaml
inputs:
- name: very_important_input
value: 12
priority: 50
```
To set a priority in DSL, use:
```ruby
input('also_important', value: 42, priority: 45)
```
As packaged, Chef InSpec uses the following priority values:
| Input Provider | Priority | May change priority |
When originally introduced, the Input facility was named *Attributes*. This name was problematic, as the Chef Infra Client tool uses the same word to describe its parameterization system.
* Chef attributes have a completely different and much more complex precedence system
* Confusion about passing Chef Attributes into InSpec when using Audit Cookbook and kitchen-inspec
Based on these concerns, InSpec Attributes have been renamed to InSpec Inputs in Chef InSpec v4.
Support for using the DSL keyword `attribute()`, the metadata field `attributes:`, and the corresponding kitchen-inspec and audit cookbook values are anticipated to continue through Chef InSpec v5.
When you write `input('some_name', value: 'some_value')`, you are *setting* an input value in the DSL. Because the `value:` option is present, a new value will be set. You may also pass any other option listed in the [input option reference](#input-options-reference).
When you call `input('some_name')`, with or without additional options, the value of the input will be resolved and returned. Note that this may involve sourcing the value from another provider, or overriding the value provided in the same call.
```ruby
# You can use the value in a Ruby variable
some_var = input('some_input_name')
# Or more directly in a resource parameter
describe file(input('important_path')) do
it { should exist }
end
# Or as the resource itself (this could be a string, here)
Each profile has a metadata file at the top level, `inspec.yml`. In that file, you may add a section for Inputs. You may define inputs there, clearly setting options including values, type checking, and whether the input is required.
```yaml
name: my_profile
inputs:
- name: webserver_user # Name is the only required field
- name: favorite_fruit
value: banana # You can set a value; priority is 30 for metadata
There are two major advantages to defining inputs in profile metadata:
1. The inputs and their configuration are listed explicitly in simple YAML in one place - a consumer of your profile does not need to read through the control code to find the inputs.
2. You can set inputs in other profiles that you depend on using profile inheritance.
When your profile relies on another profile using the `depends` key in the metadata file, you can set (that is, override) the value of the input in the dependent profile by including the `profile` option and naming the dependent profile.
In Chef InSpec 4+, every Input is namespaced: so you could have an input named `wrapper/broccoli` and one named `child/broccoli`. Within the `wrapper` profile metadata file, if no explicit profile option is set, `wrapper` is assumed to be the profile.
2. Because the CLI is outside the scope of any one profile and the inputs don't take options, the Inputs are clumsily copied into every profile, effectively making the CLI mechanism global.
Allowed in: All. When used in DSL and Metadata, the name is unique with the current profile; when used in CLI input files, audit cookbook, and kitchen-inspec, the input is copied across all profiles using the same name.
Optional, any Ruby or YAML type. This is the value that will be available when you read the input. See [Reading Inputs](#reading-inputs-in-control-dsl).
Optional, `String`, one of `String`, `Numeric`, `Regexp`, `Array`, `Hash`, `Boolean`, or `Any`. If provided, the value with be checked to see if it is of the corresponding type. Note that `Regexp` indicates that the value itself should be a regular expression, not that it should match any particular one.
Optional, `true` or `false`. If `true`, a control using the input will be failed if it [reads](#reading-inputs-in-control-dsl) the value when none has been set.
If you are having difficulty determining why a particular value is being used, you can use the Event Log to determine what is going on.
First, use the `input_object()` DSL method. It's like `input()` in that it looks up an Input, but instead of evaluating the current value, it returns the underlying `Inspec::Input` object.
`diagnostic_string` assembles the Event Log into a printable log message for convenience.
The Event Log contains entries for every time that the value changed, as well as one for when the input was first created. When possible, stack probing is used to determine file and line numbers. Most importantly, you will see priority numbers; remember that highest priority wins; order only matters to break a tie.