docs/lint.md in sfn-3.0.12 vs docs/lint.md in sfn-3.0.14
- old
+ new
@@ -1,27 +1,115 @@
---
title: "Lint"
-weight: 5
+weight: 8
+anchors:
+ - title: "Lint Framework"
+ url: "#lint-framework"
+ - title: "Composition"
+ url: "#composition"
+ - title: "Usage"
+ url: "#usage"
---
## Lint
-The lint framework built within the sfn tool utilizes the JMESPath query language
+The lint framework built within the sfn tool utilizes the [JMESPath][jmespath] query language
for identifying patterns and apply validation rules.
-### Lint RuleSets
+### Lint Framework
-#### Local
+A rule set is a named collection of rules to be applied to a template. Each rule
+is composed of one or more definitions. A rule passes only if _all_ definitions
+can be successfully applied. Linting related classes:
-Create rule sets using the generator. Each file must contain a single
-lint rule set. Below is a simple rule set used to flag non-AWS type
-resources:
+* `Sfn::Lint::RuleSet`
+* `Sfn::Lint::Rule`
+* `Sfn::Lint::Definition`
+### Composition
+
+#### Long Form
+
+##### `Sfn::Lint::Definition`
+
+Definitions define a search expression to be applied to a given template. The search
+expression is a [JMESPath compatible query expression][jmespath-expr]. The matches
+of the search expression are then processed. If the results are valid, a `true` result
+is expected. If the results are invalid, a `false` value is expected, or an `Array<String>`
+value is expected which provides the list of invalid items.
+
~~~ruby
-# tests/lint/resource_type_check.rb
+Sfn::Lint::Definition.new('Resources.[*][0][*].Type') do |matches, template|
+ unless(search.nil?)
+ result = search.find_all{|i| !i.start_with?('AWS')}
+ result.empty? ? true : result
+ else
+ true
+ end
+end
+~~~
-RuleSet.build(:test) do
+The processing block is provided two arguments. The first is the match result of the
+search expression. The second is the full template `Hash` that is being processed.
+
+##### `Sfn::Lint::Rule`
+
+Rules are composed of definitions. When a rule is applied to a template it will only
+pass if _all_ definitions are successfully applied. A rule also includes a failure
+message to provide user context of the failure.
+
+~~~ruby
+definition = Sfn::Lint::Definition.new('Resources.[*][0][*].Type') do |matches, template|
+ unless(search.nil?)
+ result = search.find_all{|i| !i.start_with?('AWS')}
+ result.empty? ? true : result
+ else
+ true
+ end
+end
+
+Sfn::Lint::Rule.new(
+ :aws_resources_only,
+ [definition],
+ 'All types must be within AWS root namespace'
+)
+~~~
+
+##### `Sfn::Lint::RuleSet`
+
+A rule set is a named collection of rules. It allows logically grouping related
+rules together. Rule sets are the entry point of linting actions on templates. Once
+a rule set has been created, it must then be registered to be made available.
+
+~~~ruby
+definition = Sfn::Lint::Definition.new('Resources.[*][0][*].Type') do |matches, template|
+ unless(search.nil?)
+ result = search.find_all{|i| !i.start_with?('AWS')}
+ result.empty? ? true : result
+ else
+ true
+ end
+end
+
+rule = Sfn::Lint::Rule.new(
+ :aws_resources_only,
+ [definition],
+ 'All types must be within AWS root namespace'
+)
+
+rule_set = Sfn::Lint::RuleSet.new(:aws_rules, [rule])
+Sfn::Lint::RuleSet.register(rule_set)
+~~~
+
+#### Short Form
+
+Rule sets can also be created using a generator which reduces the amount of effort required
+for composition. The same rule set defined above can be created using the `RuleSet.build`
+generator:
+
+~~~ruby
+rule_set = Sfn::Lint::RuleSet.build(:aws_rules) do
rule :aws_resources_only do
definition 'Resources.[*][0][*].Type' do |search|
unless(search.nil?)
result = search.find_all{|i| !i.start_with?('AWS')}
result.empty? ? true : result
@@ -31,19 +119,45 @@
end
fail_message 'All types must be within AWS root namespace'
end
end
+
+Sfn::Lint::RuleSet.register(rule_set)
~~~
-#### Library
+### Usage
-When a rule set is defined within a library, it must use the full constant namespace and
-must register to allow access to the rule set:
+Linting functionality is available via the `lint` command. The only requirement of the `lint`
+command is a template provided by the `--file` flag:
+~~~
+$ sfn lint --file my-template
+~~~
+
+By default all registered rule sets applicable to the template will be applied. Rule sets can
+be disabled by name to prevent them from being applied:
+
+~~~
+$ sfn lint --file my-template --disable-rule-set aws_rules
+~~~
+
+or you can explicitly specify what rule sets should be applied:
+
+~~~
+$ sfn lint --file my-template --enable-rule-set aws_rules
+~~~
+
+#### Local rule sets
+
+Rule sets can be created for a local project. These rule sets are kept within a directory, and
+should be defined as a single rule set per file. For example, having a directory `tests/lint`
+the rule set can be created:
+
~~~ruby
-my_ruleset = Sfn::Lint::RuleSet.build(:test) do
+# tests/lint/resource_type_check.rb
+RuleSet.build(:aws_rules) do
rule :aws_resources_only do
definition 'Resources.[*][0][*].Type' do |search|
unless(search.nil?)
result = search.find_all{|i| !i.start_with?('AWS')}
result.empty? ? true : result
@@ -53,20 +167,22 @@
end
fail_message 'All types must be within AWS root namespace'
end
end
-Sfn::Lint::RuleSet.register(my_ruleset)
~~~
-### Usage
+To include the local rule sets the target directory must be provided:
-By default `sfn` will apply any registered rule sets that are defined for the target provider.
+~~~
+$ sfn lint --file my-template --lint-directory tests/lint
+~~~
-#### Local
+and if _only_ local rule sets should be applied, it is possible to disable all registered
+rule sets:
-Provide a template and lint directory to the `lint` command. For example,
-if lint rule sets are defined within `tests/lint`:
-
~~~
-$ sfn lint --file my-template --lint-directory tests/lint
+$ sfn lint --file my-template --lint-directory tests/lint --local-rule-sets-only
~~~
+
+[jmespath]: http://jmespath.org/
+[jmespath-expr]: http://jmespath.org/specification.html
\ No newline at end of file