The lint framework built within the sfn tool utilizes the JMESPath query language for identifying patterns and apply validation rules.
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:
Sfn::Lint::RuleSet
Sfn::Lint::Rule
Sfn::Lint::Definition
Sfn::Lint::Definition
Definitions define a search expression to be applied to a given template. The search
expression is a JMESPath compatible query expression. 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.
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
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.
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.
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)
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:
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
else
true
end
end
fail_message 'All types must be within AWS root namespace'
end
end
Sfn::Lint::RuleSet.register(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
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:
# 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
else
true
end
end
fail_message 'All types must be within AWS root namespace'
end
end
To include the local rule sets the target directory must be provided:
$ sfn lint --file my-template --lint-directory tests/lint
and if only local rule sets should be applied, it is possible to disable all registered rule sets:
$ sfn lint --file my-template --lint-directory tests/lint --local-rule-sets-only