1
0
Fork 0

feat: load definitions from rules (fixes #2)

BREAKING CHANGE: adds a required `name` property (string) at the
top level of each `--rules` file, used as the schema name
This commit is contained in:
ssube 2019-06-22 12:26:11 -05:00
parent e02cd67164
commit 9eb41fc38e
7 changed files with 87 additions and 38 deletions

View File

@ -123,7 +123,7 @@ run-rules: ## validate the rules directory
--config-name config-stderr.yml \
--rules $(ROOT_PATH)/rules/salty-dog.yml \
--source $${file} \
--tag important > /dev/null; \
--tag important > /dev/null || exit 1; \
done
run-stream: ## validate stdin and write it to stdout, errors to stderr

View File

@ -1,3 +1,4 @@
name: salty-dog-ansible
rules:
- name: ansible-playbook
desc: ensure plays have important properties

View File

@ -1,3 +1,4 @@
name: salty-dog-gitlab-ci
rules:
- name: gitlab-stages
desc: should specify stages

View File

@ -1,3 +1,4 @@
name: salty-dog-kubernetes
rules:
- name: kubernetes-resources
desc: containers must have complete resources specified

View File

@ -1,3 +1,45 @@
name: salty-dog-meta
definitions:
rule:
type: object
additionalProperties: false
required:
# metadata
- name
- desc
- level
- tags
# data
- select
- check
properties:
name:
type: string
pattern: "[-a-z0-9]+"
desc:
type: string
minLength: 8
maxLength: 255
level:
type: string
enum:
- debug
- info
- warn
- error
tags:
type: array
items:
type: string
pattern: "[-:a-z0-9]+"
select:
type: string
minLength: 1
filter:
type: object
check:
type: object
rules:
- name: salty-dog-rule
desc: rules must be complete
@ -7,42 +49,32 @@ rules:
- salty-dog
select: '$.rules[*]'
check:
$ref: "salty-dog-meta#/definitions/rule"
- name: salty-dog-source
desc: source files must have rules
level: info
tags:
- important
- salty-dog
select: '$'
check:
type: object
additionalProperties: false
required:
# metadata
- name
- desc
- level
- tags
# data
- select
- check
required: [name, rules]
properties:
definitions:
type: object
additionalProperties: false
patternProperties:
"[-a-z]+":
type: object
name:
type: string
pattern: "[-a-z0-9]+"
desc:
type: string
minLength: 8
maxLength: 255
level:
type: string
enum:
- debug
- info
- warn
- error
tags:
rules:
type: array
minItems: 1
items:
type: string
pattern: "[-:a-z0-9]+"
select:
type: string
minLength: 1
filter:
type: object
check:
type: object
$ref: "salty-dog-meta#/definitions/rule"

View File

@ -103,10 +103,6 @@ export async function main(argv: Array<string>): Promise<number> {
return STATUS_ERROR;
}
const rules = await loadRules(args.rules);
const source = await loadSource(args.source);
const activeRules = await resolveRules(rules, args as any);
const ctx = new VisitorContext({
coerce: args.coerce,
defaults: args.mode === 'fix',
@ -114,8 +110,12 @@ export async function main(argv: Array<string>): Promise<number> {
});
const parser = new YamlParser();
const source = await loadSource(args.source);
let data = parser.parse(source);
const rules = await loadRules(args.rules, ctx.ajv);
const activeRules = await resolveRules(rules, args as any);
for (const rule of activeRules) {
const workingCopy = cloneDeep(data);
const ruleErrors = await rule.visit(ctx, workingCopy);

View File

@ -28,7 +28,13 @@ export interface RuleSelector {
includeTag: Array<string>;
}
export async function loadRules(paths: Array<string>): Promise<Array<Rule>> {
export interface RuleSource {
definitions?: Array<any>;
name: string;
rules: Array<RuleData>;
}
export async function loadRules(paths: Array<string>, ajv: any): Promise<Array<Rule>> {
const parser = new YamlParser();
const rules = [];
@ -37,7 +43,15 @@ export async function loadRules(paths: Array<string>): Promise<Array<Rule>> {
encoding: 'utf-8',
});
const data = parser.parse(contents);
const data = parser.parse(contents) as RuleSource;
if (!isNil(data.definitions)) {
ajv.addSchema({
'$id': data.name,
definitions: data.definitions,
});
}
rules.push(...data.rules.map((data: any) => new Rule(data)));
}