Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,6 @@

0.14.17 2019-02-01
* Add 'meta.redact' to replicated-supportbundle schema

0.15.0 2019-03-07
* Allow passing multidoc yaml to linter, though only the first document will be linted
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "replicated-lint",
"author": "Replicated, Inc.",
"version": "0.14.17",
"version": "0.15.0",
"engines": {
"node": ">=4.3.2"
},
Expand Down Expand Up @@ -46,7 +46,7 @@
"bin": "bin/replicated-lint",
"devDependencies": {
"@types/chai": "^3.4.34",
"@types/js-yaml": "^3.5.31",
"@types/js-yaml": "^3.12.0",
"@types/lodash": "^4.14.52",
"@types/node": "^7.0.0",
"chai": "^3.5.0",
Expand All @@ -70,7 +70,7 @@
"@types/json-schema": "^6.0.1",
"@types/tv4": "^1.2.28",
"chalk": "^1.1.3",
"js-yaml": "^3.8.4",
"js-yaml": "^3.12.2",
"junit-report-builder": "^1.3.1",
"line-column": "^1.0.2",
"lodash": "^4.17.5",
Expand Down
2 changes: 2 additions & 0 deletions src/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
GTE,
InvalidURL,
IsEmpty,
IsNative,
IsNotBytesCount,
IsNotKubernetesQuantity,
IsNotUint,
Expand Down Expand Up @@ -70,6 +71,7 @@ const defaultPredicates: PredicateRegistry = {
Falsey,
FalseyIfPresent,
IsEmpty,
IsNative,
IsNotBytesCount,
IsNotKubernetesQuantity,
IsNotUint,
Expand Down
64 changes: 35 additions & 29 deletions src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface Test {
IsEmpty?: {
path: string;
};
IsNative?: {};
IsNotBytesCount?: {
path: string;
};
Expand Down Expand Up @@ -230,34 +231,18 @@ const DOC_SEPARATOR_LENGTH = DOC_SEPARATOR.length;
*/
export function hackLintMultidoc(inYaml: string, maybeOpts?: MultidocLintOpts): RuleTrigger[] {
const targetIndex = maybeOpts ? maybeOpts.multidocIndex : 0;
// It's just one doc, do the normal thing, but keep signature same
if (inYaml.indexOf(DOC_SEPARATOR) === -1) {
return lint(inYaml, maybeOpts);
}

// It's many docs, split it on --- and lint each one,
// tracking offset for accurate global line/column computation
const opts = maybeOpts || {};
const docs = inYaml.split(DOC_SEPARATOR).slice(1);
let offset = inYaml.indexOf(DOC_SEPARATOR) + DOC_SEPARATOR_LENGTH;
const lineColumnFinder = lineColumn(inYaml);

let index = 0;
for (const doc of docs) {
if (index === targetIndex) {
return new Linter(doc, {
rules: opts.rules,
registry: opts.registry,
lineColumnFinder,
offset,
}).lint();
}
offset += doc.length + DOC_SEPARATOR_LENGTH;
index += 1;
}
return [Linter.noDocError()];

return new Linter(inYaml, {
rules: opts.rules,
schema: opts.schema,
registry: opts.registry,
multidocIndex: targetIndex,
}).lint();
}

export let docCount: number;

export class Linter {

public static withDefaults(inYaml: string): Linter {
Expand All @@ -278,8 +263,8 @@ export class Linter {
private readonly schema?: any;

private readonly registry: Registry;
private readonly lineColumnFinder: any;
private readonly offset: number;
private lineColumnFinder: any;
private offset: number;

private readonly multidocIndex: number;

Expand All @@ -299,9 +284,30 @@ export class Linter {
if (!this.inYaml) {
return [Linter.noDocError()];
}
let root;

let docs = this.inYaml.split(DOC_SEPARATOR);
if (docs.length > 1) {
docs = docs.slice(1);
this.offset += this.inYaml.indexOf(DOC_SEPARATOR) + DOC_SEPARATOR_LENGTH;
}

docCount = docs.length;
if (docs.length < this.multidocIndex) {
return [Linter.noDocError()];
}

let index = 0;
for (const doc of docs) {
if (index === this.multidocIndex) {
break;
}
this.offset += doc.length + DOC_SEPARATOR_LENGTH;
index += 1;
}

let root: any;
try {
root = yaml.safeLoad(this.inYaml);
root = yaml.safeLoad(docs[this.multidocIndex]);
} catch (err) {
return [this.loadYamlError(err)];
}
Expand Down
20 changes: 19 additions & 1 deletion src/predicates.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as _ from "lodash";
import * as semver from "semver";
import * as urlParse from "url-parse";
import { Predicate, RuleMatchedAt } from "./lint";
import { Predicate, RuleMatchedAt, docCount } from "./lint";
import { FoundValue, TraverseSearcher, ValueSearcher, ValueTraverser } from "./traverse";
import { Component, ConfigChildItem, ConfigOption, ConfigSection, Container } from "./replicated";
import { Registry } from "./engine";
Expand Down Expand Up @@ -1336,3 +1336,21 @@ export class Not<T_El> implements Predicate<T_El> {
}
}
}

export class IsNative implements Predicate<any> {
public static fromJson(): IsNative {
return new IsNative();
}

public test(root: any): RuleMatchedAt {
if (!root) {
return {matched: false};
}

if (docCount === 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this using a global variable?

return {matched: true, paths: []};
} else {
return {matched: false};
}
}
}
33 changes: 24 additions & 9 deletions src/rules/monitors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { YAMLRule } from "../lint";
export const cpuMonitorContainerExists: YAMLRule = {
name: "prop-monitors-cpuacct-container-exists",
type: "error",
message: "Entries in `monitors.cpuacct` must have matching component+container or the scheduler must be swarm",
message: "Entries in `monitors.cpuacct` must have matching component+container if the scheduler is Native",
test: {
And: {
preds: [
{ MonitorContainerMissing: { monitorPath: "monitors.cpuacct"} },
{ Not: { pred: { Exists: { path: "swarm"} } } },
{ IsNative: { } },
],
},
},
Expand Down Expand Up @@ -61,14 +61,19 @@ monitors:
`,
},
{
description: "All `cpuacct` monitors are valid if the scheduler is swarm",
description: "All `cpuacct` monitors are valid if the scheduler is not native",
yaml: `
---
monitors:
cpuacct:
- swarmstash
swarm:
minimum_node_count: "1"
---
# kind: scheduler-swarm

version: '3.3'
services:
mysql:
image: mysql
`,
},
{
Expand All @@ -86,12 +91,12 @@ monitors:
export const memMonitorContainerExists: YAMLRule = {
name: "prop-monitors-memory-container-exists",
type: "error",
message: "Entries in `monitors.memory` must have matching component+container or the scheduler must be swarm",
message: "Entries in `monitors.memory` must have matching component+container if the scheduler is Native",
test: {
And: {
preds: [
{ MonitorContainerMissing: { monitorPath: "monitors.memory"} },
{ Not: { pred: { Exists: { path: "swarm"} } } },
{ IsNative: { } },
],
},
},
Expand Down Expand Up @@ -151,8 +156,18 @@ monitors:
monitors:
memory:
- swarmstash
swarm:
minimum_node_count: "1"
---
# kind: scheduler-swarm

version: '3.3'
services:
mysql:
image: mysql
---
# kind: scheduler-swarm

#this is not valid yaml
{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But before anything else, I need to see if there's a way to fix this sort of thing
(by ignoring mesg-yaml-valid from the 2nd document on, for example)

`,
},
],
Expand Down
18 changes: 13 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.34.tgz#d5335792823bb09cddd5e38c3d211b709183854d"
integrity sha1-1TNXkoI7sJzd1eOMPSEbcJGDhU0=

"@types/js-yaml@^3.5.31":
version "3.5.31"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.5.31.tgz#54aeb8bcaaf94a7b1a64311bc318dbfe601a593a"
integrity sha512-tDsBKuC7nlShdRbR+rCe6qrs9Fqodi7WUxyeysCwKG0kWFWsisyZ8FhmYhCF6+lt3XhIwSExaD1MxidYtRW15w==
"@types/js-yaml@^3.12.0":
version "3.12.0"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.0.tgz#3494ce97358e2675e24e97a747ec23478eeaf8b6"
integrity sha512-UGEe/6RsNAxgWdknhzFZbCxuYc5I7b/YEKlfKbo+76SM8CJzGs7XKCj7zyugXViRbKYpXhSXhCYVQZL5tmDbpQ==

"@types/json-schema@^6.0.1":
version "6.0.1"
Expand Down Expand Up @@ -1562,7 +1562,7 @@ [email protected]:
argparse "^1.0.7"
esprima "^2.6.0"

[email protected], js-yaml@^3.8.4:
[email protected]:
version "3.8.4"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
integrity sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=
Expand All @@ -1578,6 +1578,14 @@ js-yaml@^3.12.0:
argparse "^1.0.7"
esprima "^4.0.0"

js-yaml@^3.12.2:
version "3.12.2"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc"
integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"

jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
Expand Down