Define, enforce, and handle violations of validation rules for Chef node attributes. The rule definitions are themselves node attributes. This gem provides the validation engine, and can be used outside of a convergence run; a cookbook (attribute-validator) is planned to perform validation during a chef run, at compile or converge time.
Define rules by creating attributes that specify checks to make on node attributes that match a given path. By default the library looks for rules under node['attribute-validator']['rules'], but you can override that.
See Defining Validation Rules.
To scan for violations of all rules, do:
require 'chef-attribute-validator'
violations = Chef::Attribute::Validator.new(node).validate_all
You can also apply one rule, or rules that match a regex:
violations = Chef::Attribute::Validator.new(node).validate_rule('rulename')
violations = Chef::Attribute::Validator.new(node).validate_matching(/matchme/)
The return value from each is an array, possibly empty. Each array element is a simple object, with accessors:
rule_name (string)
path (in slash format, see REFERENCING ATTRIBUTES)
message
A single rule may have many violations.
To define validation rules, create attributes under
default['attribute-validator']['rules'][<rulename>]...
Each rule gets a unique name. Each entry is hash structure with the following keys:
path - Required. Slash formatted path of the attributes to check.
enabled - Optional boolean, default true. Set to false to knock out rule.
The remaining entries describe criteria to enforce on the value of the attribute(s) referenced by 'path'. You may list zero or more.
Note that nil is permitted as a value by most checks, except the following:
'required' check (which performs nilness checks) 'proc' check (which implements arbitrary user behavior) 'min_children', 'max_children' (which are restricted to operating on Hashes and Arrays) 'child_keys' (which is restricted to operating on Hashes)
Checks the immediate keys of the given path (which must be a Hash). Check argument may be an Array of Strings, in which case each key that is present must be in the list of valid keys, or else a Regexp, which will be matched against each key.
Checks type of value. One of 'string', 'number', 'boolean', 'hash', 'array'.
Integer. Fails for all but Hash and Array. For Hash and Array, minimum number of elements to be considered valid.
Integer. Fails for all but Hash and Array. For Hash and Array, maximum number of elements to be considered valid.
Boolean. If true, fails if the path matches zero attributes. If false, fails if the path matches nonzero attributes. This is most useful for enforcing deprecated attributes. Does not consider nilness, only existence of attribute key(s). See also required.
Regexp. Applies given regex to the value. Ignored for Hash and Array. See looks_like for a selection of canned regexen.
Boolean. If true, fails if the path matches zero attributes, or the value is nil, or the value is the empty string, or if the value is an empty array or empty hash. No-op if false (use present => false to enforce absence).
String, one of 'email', 'guid', 'hostname', 'ip', 'url'. Applies canned regexes (or more sophisticated matchers, like constructing objects from the stdlib). Details:
Uses a naive regex to do a simple sanity check. It may be too tight or too loose for you, in which case you can use a Proc and spend as much of your energy as you please solving that problem.
Uses a regex to match GUID/UUIDs, like 'ec73f2a8-510d-4e6a-be5d-7b234da03c92'
Uses a regex to guess if it looks hostnamish. Does not require a dot. Accepts IPv4, and checks ranges.
Uses the stdlib 'ipaddr' library to try to construct an IPAddr object from the value. If it worked, it's an IP. IPv6 is supported; ranges are checked; CIDR notation is supported; and no you can't pass a hostname to this.
Uses the stdlib 'url' library to try to construct an URI object from the value. If it worked, it's an URL. This is probably too loose; it will accept bare hostnames, for example.
Array, a set of possible values.
A Proc, which will be evaluated to determine the validity. The proc should take two args - a string rule name, and a Chef::Attribute::Validator::AttributeSet. You can treat the attribute set as a hash - its each() methods will yield path, value pairs.
The proc should return a possibly empty array of Chef::Attribute::Validator::Violations.
Attribute locations are described using a syntax similar to shell globs.
Given:
/foo - Matches node['foo']
/foo/bar - Matches node['foo']['bar']
Open a github issue at https://github.com/clintoncwolfe/chef-attribute-validator, ideally with a failing test case, a pull request that fixes the bug, and a unicorn.
Possibly eventually support for [], or {}.
Perhaps a hostname:port looks_like?
No real exception class, just raising a bare string exception, which could certainly be improved upon; hard to catch.
BrutalRegex is terrible.
Clinton Wolfe
- Fork it (https://github.com/clintoncwolfe/chef-attribute-validator)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request at (https://github.com/clintoncwolfe/chef-attribute-validator)