The centralized deprecation facility is used to deprecate (retire, withdraw, etc) features both within InSpec core code, InSpec core resources, plugins, and custom resources.
The most important goal of the deprecation facility was to collect decisions about what actions should be taken for a deprecation in a central place, so that it is easier to handle major version changes.
In many applications, `feature flags` are used to deploy new feature code, without actually revealing it to the user. When certain conditions are met, the deployment team enables the flags, and the feature goes live.
Inverting this idea, we could use flags to withdraw features. For example, if we wish to retire the `lusers` property on the `shadow` resource, we might add:
```
# In lib/resources/shadow.rb
def lusers
Inspec.deprecate :old_shadow_fields, 'Please use the `users` property instead.'
end
```
Then, in `etc/deprecations.json` in version 3.5, we might add:
```
"groups": {
"old_shadow_features": { "action": "ignore" }
}
```
This makes the deprecation silent - it is there and ready to be triggered, but has no effect yet. We can add more deprecation declarations, using the `old_shadow_features` group. Then, when we decide that we'll start warning about it in v4.0 and withdraw it in v5.0, we can simply change the config file - we don't have to change every deprecation:
For v4:
```
"groups": {
"old_shadow_features": { "action": "warn", "suffix": "Certain properties of shadow will be withdrawn in InSpec v5.0" }
For v5, you have some choices as to how to harden the deprecation. `fail_control` will fail any control the deprecation is used in; while `exit` will exit the inspec run entirely.
For v5:
```
"groups": {
"old_shadow_features": { "action": "exit", "suffix": "Certain properties of shadow were deprecated in v4 and have now been removed in v5." }
}
```
Again, no need to update the deprecation calls; though in v6 it might make sense to remove the old code entirely.
### Groups
When you make a deprecation message, you add it to a group. InSpec will read the file `$INSPEC_INSTALL_ROOT/etc/deprecation.json` to determine the known groups - you may add to that file at any time.
If you make a deprecation using a group that is unknown, InSpec will by default treat it as a warning. You can change that behavior by setting the "unknown_group_action" top-level property to any of the valid actions.
There are no restrictions on the number or the naming of groups; you can have as many or as few as needed.
### Message Assembly
For all actions except `ignore`, a message is assembled, consisting of:
* The string 'DEPRECATION'
* The value of the `prefix` field of the group, if any
* The specific message provided by the deprecation declaration
* The value of the `suffix` field of the group, if any
* If possible, the string '(used at ' followed by a `path/file.rb:lineno` to help the user locate the deprecation in *their code*.
Issues an ERROR via `Inspec::Log.error` with the assembled message, then immediately exits the process via Inspec::UI. The reporters are not executed. By default, the exit code will be 3; but you can set a different code using the `exit_status` property of the group in the config file.
Checks to see if the code is being called within a control block; if so, raises a FailedResource exception with the assembled message, which causes the control to fail in the reporter.
If the code is outside a control, the `warn` action is triggered instead.
#### ignore
Does nothing; this is very useful for staging deprecations - you can have the deprecations in place, then enable them later.