Skip to content

Commit

Permalink
feat: support multiple documents per source (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Jun 25, 2019
1 parent 146bcc7 commit 2bd60c8
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 34 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -29,7 +29,7 @@ To download, validate, and apply a Kubernetes resource:

...
{"name":"salty-dog","hostname":"cerberus","pid":7860,"level":30,"msg":"all rules passed","time":"2019-06-16T02:04:37.797Z","v":0}
ingress.extensions/gitlab created (dry run
ingress.extensions/gitlab created (dry run)
```

### Docker
Expand Down
1 change: 1 addition & 0 deletions config/rollup.js
Expand Up @@ -51,6 +51,7 @@ export default {
'SAFE_SCHEMA',
'safeDump',
'safeLoad',
'safeLoadAll',
'Schema',
'Type',
],
Expand Down
41 changes: 41 additions & 0 deletions examples/kubernetes-resources-some.yml
@@ -0,0 +1,41 @@
metadata:
name: example
spec:
template:
spec:
containers:
- name: test

---

metadata:
name: example
spec:
template:
spec:
containers:
- name: test
resources:
limits:
memory: 5Mi
requests:
cpu: 1m
memory: 2Mi

---

metadata:
name: example
spec:
template:
spec:
containers:
- name: test
resources:
limits:
cpu: 4000m
memory: 5Gi
requests:
cpu: 4000m
memory: 5Gi

5 changes: 3 additions & 2 deletions src/config/index.ts
Expand Up @@ -40,13 +40,14 @@ export function completePaths(name: string, extras: Array<string>): Array<string
}

export async function loadConfig(name: string, ...extras: Array<string>): Promise<any> {
const parser = new YamlParser();
const paths = completePaths(name, extras);

for (const p of paths) {
const data = await readConfig(p);
if (!isNil(data)) {
return parser.parse(data);
const parser = new YamlParser();
const [head] = parser.parse(data);
return head;
}
}

Expand Down
36 changes: 19 additions & 17 deletions src/index.ts
Expand Up @@ -111,29 +111,31 @@ export async function main(argv: Array<string>): Promise<number> {

const parser = new YamlParser();
const source = await loadSource(args.source);
let data = parser.parse(source);
let docs = 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 items = await rule.pick(ctx, data);
for (const item of items) {
const itemCopy = cloneDeep(item);
const itemResult = await rule.visit(ctx, itemCopy);
for (const data of docs) {
for (const rule of activeRules) {
const items = await rule.pick(ctx, data);
for (const item of items) {
const itemCopy = cloneDeep(item);
const itemResult = await rule.visit(ctx, itemCopy);

if (itemResult.errors.length > 0) {
logger.warn({ count: itemResult.errors.length, rule }, 'rule failed');
if (itemResult.errors.length > 0) {
logger.warn({ count: itemResult.errors.length, rule }, 'rule failed');

ctx.mergeResult(itemResult);
} else {
const itemDiff = diff(item, itemCopy);
if (Array.isArray(itemDiff) && itemDiff.length > 0) {
logger.info({ diff: itemDiff, item, rule }, 'rule passed with modifications');

applyDiff(item, itemCopy);
ctx.mergeResult(itemResult);
} else {
logger.info({ rule }, 'rule passed');
const itemDiff = diff(item, itemCopy);
if (Array.isArray(itemDiff) && itemDiff.length > 0) {
logger.info({ diff: itemDiff, item, rule }, 'rule passed with modifications');

applyDiff(item, itemCopy);
} else {
logger.info({ rule }, 'rule passed');
}
}
}
}
Expand All @@ -148,7 +150,7 @@ export async function main(argv: Array<string>): Promise<number> {
}
} else {
logger.info('all rules passed');
const output = parser.dump(data);
const output = parser.dump(...docs);
await writeSource(args.dest, output);
return STATUS_SUCCESS;
}
Expand Down
10 changes: 6 additions & 4 deletions src/parser/YamlParser.ts
@@ -1,18 +1,20 @@
import { safeDump, safeLoad } from 'js-yaml';
import { safeDump, safeLoadAll } from 'js-yaml';

import { CONFIG_SCHEMA } from 'src/config/schema';
import { Parser } from 'src/parser';

export class YamlParser implements Parser {
dump(data: any): string {
dump(...data: Array<any>): string {
return safeDump(data, {
schema: CONFIG_SCHEMA,
});
}

parse(body: string): any {
return safeLoad(body, {
parse(body: string): Array<any> {
const docs: Array<any> = [];
safeLoadAll(body, (doc: any) => docs.push(doc), {
schema: CONFIG_SCHEMA,
});
return docs;
}
}
4 changes: 2 additions & 2 deletions src/parser/index.ts
@@ -1,4 +1,4 @@
export interface Parser {
dump(data: any): string;
parse(body: string): any;
dump(...data: Array<any>): string;
parse(body: string): Array<any>;
}
18 changes: 10 additions & 8 deletions src/rule.ts
Expand Up @@ -44,16 +44,18 @@ export async function loadRules(paths: Array<string>, ajv: any): Promise<Array<R
encoding: 'utf-8',
});

const data = parser.parse(contents) as RuleSource;
const docs = parser.parse(contents) as Array<RuleSource>;

for (const data of docs) {
if (!isNil(data.definitions)) {
ajv.addSchema({
'$id': data.name,
definitions: data.definitions,
});
}

if (!isNil(data.definitions)) {
ajv.addSchema({
'$id': data.name,
definitions: data.definitions,
});
rules.push(...data.rules.map((data: any) => new Rule(data)));
}

rules.push(...data.rules.map((data: any) => new Rule(data)));
}

return rules;
Expand Down

0 comments on commit 2bd60c8

Please sign in to comment.